1 /* RealVideo wrapper plugin
3 * Copyright (C) 2005 Lutz Mueller <lutz@topfrose.de>
4 * Copyright (C) 2006 Edward Hervey <bilboed@bilboed.com>
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Library General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Library General Public License for more details.
16 * You should have received a copy of the GNU Library General Public
17 * License along with this library; if not, write to the
18 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 * Boston, MA 02111-1307, USA.
27 #include "gstrealvideodec.h"
31 GST_DEBUG_CATEGORY_STATIC (realvideode_debug);
32 #define GST_CAT_DEFAULT realvideode_debug
34 static GstStaticPadTemplate snk_t =
35 GST_STATIC_PAD_TEMPLATE ("sink", GST_PAD_SINK, GST_PAD_ALWAYS,
36 GST_STATIC_CAPS ("video/x-pn-realvideo, " "rmversion = (int) [ 2, 4 ]"));
37 static GstStaticPadTemplate src_t =
38 GST_STATIC_PAD_TEMPLATE ("src", GST_PAD_SRC, GST_PAD_ALWAYS,
39 GST_STATIC_CAPS ("video/x-raw-yuv, "
40 "format = (fourcc) I420, "
41 "framerate = (fraction) [0/1, MAX], "
42 "width = (int) [ 16, 4096 ], " "height = (int) [ 16, 4096 ] "));
44 #define DEFAULT_RV20_NAMES "drv2.so:drv2.so.6.0"
45 #define DEFAULT_RV30_NAMES "drvc.so:drv3.so.6.0"
46 #define DEFAULT_RV40_NAMES "drvc.so:drv4.so.6.0"
47 #define DEFAULT_MAX_ERRORS 25
52 PROP_REAL_CODECS_PATH,
59 GST_BOILERPLATE (GstRealVideoDec, gst_real_video_dec, GstElement,
62 static gboolean open_library (GstRealVideoDec * dec,
63 GstRealVideoDecVersion version, GstRVDecLibrary * lib);
64 static void close_library (GstRealVideoDec * dec, GstRVDecLibrary * lib);
86 gst_real_video_dec_chain (GstPad * pad, GstBuffer * in)
94 GstClockTime timestamp, duration;
97 guint frag_count, frag_size;
99 dec = GST_REAL_VIDEO_DEC (GST_PAD_PARENT (pad));
101 if (G_UNLIKELY (dec->lib.Transform == NULL || dec->lib.module == NULL))
104 data = GST_BUFFER_DATA (in);
105 size = GST_BUFFER_SIZE (in);
106 timestamp = GST_BUFFER_TIMESTAMP (in);
107 duration = GST_BUFFER_DURATION (in);
109 GST_DEBUG_OBJECT (dec, "got buffer of size %u, timestamp %" GST_TIME_FORMAT,
110 size, GST_TIME_ARGS (timestamp));
112 /* alloc output buffer */
113 ret = gst_pad_alloc_buffer (dec->src, GST_BUFFER_OFFSET_NONE,
114 dec->width * dec->height * 3 / 2, GST_PAD_CAPS (dec->src), &out);
115 if (ret != GST_FLOW_OK)
118 GST_BUFFER_TIMESTAMP (out) = timestamp;
119 GST_BUFFER_DURATION (out) = duration;
121 frag_count = *data++;
122 frag_size = (frag_count + 1) * 8;
123 size -= (frag_size + 1);
125 GST_DEBUG_OBJECT (dec, "frag_count %u, frag_size %u, data size %u",
126 frag_count, frag_size, size);
130 * The Buffers contain
133 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
134 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
135 * | nfragments | fragment1 ... |
136 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
138 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
139 * | ... | fragment2 ... |
140 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
142 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
143 * | ... | fragment data |
144 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
146 * nfragments: number of fragments
147 * fragmentN: 8 bytes of fragment data (nfragements + 1) of them
148 * fragment data: the data of the fragments.
152 tin.nfragments = frag_count;
153 tin.fragments = data;
155 tin.timestamp = timestamp;
157 /* jump over the frag table to the fragments */
160 result = dec->lib.Transform (
162 (gchar *) GST_BUFFER_DATA (out), &tin, &tout, dec->lib.context);
164 goto could_not_transform;
166 /* When we decoded a frame, reset the error counter. We only fail after N
167 * consecutive decoding errors. */
168 dec->error_count = 0;
170 gst_buffer_unref (in);
172 /* Check for new dimensions */
173 if (tout.frames && ((dec->width != tout.width)
174 || (dec->height != tout.height))) {
175 GstCaps *caps = gst_caps_copy (GST_PAD_CAPS (dec->src));
176 GstStructure *s = gst_caps_get_structure (caps, 0);
178 GST_DEBUG_OBJECT (dec, "New dimensions: %"
179 G_GUINT32_FORMAT " x %" G_GUINT32_FORMAT, tout.width, tout.height);
181 gst_structure_set (s, "width", G_TYPE_INT, (gint) tout.width,
182 "height", G_TYPE_INT, (gint) tout.height, NULL);
184 gst_pad_set_caps (dec->src, caps);
185 gst_buffer_set_caps (out, caps);
186 gst_caps_unref (caps);
188 dec->width = tout.width;
189 dec->height = tout.height;
190 GST_BUFFER_SIZE (out) = dec->width * dec->height * 3 / 2;
193 GST_DEBUG_OBJECT (dec,
194 "Pushing out buffer with timestamp %" GST_TIME_FORMAT,
195 GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (out)));
197 if ((ret = gst_pad_push (dec->src, out)) != GST_FLOW_OK)
205 GST_WARNING_OBJECT (dec, "decoder not open, probably no input caps set "
206 "yet, caps on input buffer: %" GST_PTR_FORMAT, GST_BUFFER_CAPS (in));
207 gst_buffer_unref (in);
208 return GST_FLOW_NOT_NEGOTIATED;
212 GST_DEBUG_OBJECT (dec, "buffer alloc failed: %s", gst_flow_get_name (ret));
213 gst_buffer_unref (in);
218 gst_buffer_unref (out);
219 gst_buffer_unref (in);
223 if (dec->max_errors && dec->error_count >= dec->max_errors) {
224 GST_ELEMENT_ERROR (dec, STREAM, DECODE,
225 ("Could not decode buffer: %" G_GUINT32_FORMAT, result), (NULL));
226 return GST_FLOW_ERROR;
228 GST_ELEMENT_WARNING (dec, STREAM, DECODE,
229 ("Could not decode buffer: %" G_GUINT32_FORMAT, result), (NULL));
235 GST_DEBUG_OBJECT (dec, "Could not push buffer: %s",
236 gst_flow_get_name (ret));
242 gst_real_video_dec_getcaps (GstPad * pad)
244 GstRealVideoDec *dec = GST_REAL_VIDEO_DEC (GST_PAD_PARENT (pad));
247 if (dec->checked_modules) {
248 GValue versions = { 0 };
249 GValue version = { 0 };
251 GST_LOG_OBJECT (dec, "constructing caps");
253 g_value_init (&versions, GST_TYPE_LIST);
254 g_value_init (&version, G_TYPE_INT);
256 if (dec->valid_rv20) {
257 g_value_set_int (&version, GST_REAL_VIDEO_DEC_VERSION_2);
258 gst_value_list_append_value (&versions, &version);
260 if (dec->valid_rv30) {
261 g_value_set_int (&version, GST_REAL_VIDEO_DEC_VERSION_3);
262 gst_value_list_append_value (&versions, &version);
264 if (dec->valid_rv40) {
265 g_value_set_int (&version, GST_REAL_VIDEO_DEC_VERSION_4);
266 gst_value_list_append_value (&versions, &version);
269 if (gst_value_list_get_size (&versions) > 0) {
270 res = gst_caps_new_simple ("video/x-pn-realvideo", NULL);
271 gst_structure_set_value (gst_caps_get_structure (res, 0),
272 "rmversion", &versions);
274 res = gst_caps_new_empty ();
276 g_value_unset (&versions);
277 g_value_unset (&version);
279 GST_LOG_OBJECT (dec, "returning padtemplate caps");
280 res = gst_caps_copy (gst_pad_get_pad_template_caps (pad));
282 GST_LOG_OBJECT (dec, "returning caps %" GST_PTR_FORMAT, res);
288 gst_real_video_dec_setcaps (GstPad * pad, GstCaps * caps)
290 GstRealVideoDec *dec = GST_REAL_VIDEO_DEC (GST_PAD_PARENT (pad));
291 GstStructure *s = gst_caps_get_structure (caps, 0);
292 gint version, res, width, height, format, subformat;
293 gint framerate_num, framerate_denom;
298 if (!gst_structure_get_int (s, "rmversion", &version) ||
299 !gst_structure_get_int (s, "width", (gint *) & width) ||
300 !gst_structure_get_int (s, "height", (gint *) & height) ||
301 !gst_structure_get_int (s, "format", &format) ||
302 !gst_structure_get_int (s, "subformat", &subformat) ||
303 !gst_structure_get_fraction (s, "framerate", &framerate_num,
307 GST_LOG_OBJECT (dec, "Setting version to %d", version);
309 close_library (dec, &dec->lib);
311 if (!open_library (dec, version, &dec->lib))
314 /* Initialize REAL driver. */
315 GST_WRITE_UINT16_LE (data + 0, 11);
316 GST_WRITE_UINT16_LE (data + 2, width);
317 GST_WRITE_UINT16_LE (data + 4, height);
318 GST_WRITE_UINT16_LE (data + 6, 0);
319 GST_WRITE_UINT32_LE (data + 8, 0);
320 GST_WRITE_UINT32_LE (data + 12, subformat);
321 GST_WRITE_UINT32_LE (data + 16, 1);
322 GST_WRITE_UINT32_LE (data + 20, format);
324 if ((res = dec->lib.Init (&data, &dec->lib.context)))
325 goto could_not_initialize;
327 if ((v = gst_structure_get_value (s, "codec_data"))) {
341 buf = g_value_peek_pointer (v);
343 bufdata = GST_BUFFER_DATA (buf);
344 bufsize = GST_BUFFER_SIZE (buf);
346 /* skip format and subformat */
350 GST_LOG_OBJECT (dec, "Creating custom message of length %d", bufsize);
352 msgdata = g_new0 (guint32, bufsize + 2);
354 goto could_not_allocate;
357 msg.msg = 1 + ((subformat >> 16) & 7);
359 for (i = 0; i < 6; i++)
363 for (i = 0; i < bufsize; i++)
364 msgdata[i + 2] = 4 * (guint32) bufdata[i];
366 res = dec->lib.Message (&msg, dec->lib.context);
370 goto could_not_send_message;
373 caps = gst_caps_new_simple ("video/x-raw-yuv",
374 "format", GST_TYPE_FOURCC, GST_MAKE_FOURCC ('I', '4', '2', '0'),
375 "framerate", GST_TYPE_FRACTION, framerate_num, framerate_denom,
376 "width", G_TYPE_INT, width, "height", G_TYPE_INT, height, NULL);
378 /* set PAR if one was specified in the sink caps */
379 if ((v = gst_structure_get_value (s, "pixel-aspect-ratio"))) {
380 gst_structure_set_value (gst_caps_get_structure (caps, 0),
381 "pixel-aspect-ratio", v);
384 bres = gst_pad_set_caps (GST_PAD (dec->src), caps);
385 gst_caps_unref (caps);
387 goto could_not_set_caps;
389 dec->version = version;
391 dec->height = height;
392 dec->format = format;
393 dec->subformat = subformat;
394 dec->framerate_num = framerate_num;
395 dec->framerate_denom = framerate_denom;
401 GST_ERROR_OBJECT (dec, "Could not find all necessary keys in structure.");
406 GST_ERROR_OBJECT (dec, "failed to open library");
409 could_not_initialize:
411 GST_ERROR_OBJECT (dec, "Initialization of REAL driver failed (%i).", res);
412 close_library (dec, &dec->lib);
417 GST_ERROR_OBJECT (dec, "Could not allocate memory.");
418 close_library (dec, &dec->lib);
421 could_not_send_message:
423 GST_ERROR_OBJECT (dec, "Failed to send custom message needed for "
424 "initialization (%i).", res);
425 close_library (dec, &dec->lib);
430 GST_ERROR_OBJECT (dec, "Could not convince peer to accept dimensions "
431 "%i x %i.", dec->width, dec->height);
432 close_library (dec, &dec->lib);
437 /* Attempts to open the correct library for the configured version */
440 open_library (GstRealVideoDec * dec, GstRealVideoDecVersion version,
441 GstRVDecLibrary * lib)
443 gpointer rv_custom_msg, rv_free, rv_init, rv_transform;
444 GModule *module = NULL;
445 const gchar *path, *names;
446 gchar **split_names, **split_path;
449 GST_DEBUG_OBJECT (dec,
450 "Attempting to open shared library for real video version %d", version);
452 path = dec->real_codecs_path ? dec->real_codecs_path :
453 DEFAULT_REAL_CODECS_PATH;
456 case GST_REAL_VIDEO_DEC_VERSION_2:
457 names = dec->rv20_names ? dec->rv20_names : DEFAULT_RV20_NAMES;
459 case GST_REAL_VIDEO_DEC_VERSION_3:
460 names = dec->rv30_names ? dec->rv30_names : DEFAULT_RV30_NAMES;
462 case GST_REAL_VIDEO_DEC_VERSION_4:
463 names = dec->rv40_names ? dec->rv40_names : DEFAULT_RV40_NAMES;
466 goto unknown_version;
469 split_path = g_strsplit (path, ":", 0);
470 split_names = g_strsplit (names, ":", 0);
472 for (i = 0; split_path[i]; i++) {
473 for (j = 0; split_names[j]; j++) {
474 gchar *codec = g_strconcat (split_path[i], "/", split_names[j], NULL);
476 GST_DEBUG_OBJECT (dec, "trying %s", codec);
477 /* This is racy, but it doesn't matter here; would be nice if GModule
478 * gave us a GError instead of an error string, but it doesn't, so.. */
479 if (g_file_test (codec, G_FILE_TEST_EXISTS)) {
480 module = g_module_open (codec, G_MODULE_BIND_LAZY);
481 if (module == NULL) {
482 GST_ERROR_OBJECT (dec, "Could not open codec library '%s': %s",
483 codec, g_module_error ());
486 GST_LOG_OBJECT (dec, "%s does not exist", codec);
490 goto codec_search_done;
495 g_strfreev (split_path);
496 g_strfreev (split_names);
501 GST_DEBUG_OBJECT (dec, "module opened, finding symbols");
503 /* First try opening legacy symbols, if that fails try loading new symbols */
504 if (g_module_symbol (module, "RV20toYUV420Init", &rv_init) &&
505 g_module_symbol (module, "RV20toYUV420Free", &rv_free) &&
506 g_module_symbol (module, "RV20toYUV420Transform", &rv_transform) &&
507 g_module_symbol (module, "RV20toYUV420CustomMessage", &rv_custom_msg)) {
508 GST_LOG_OBJECT (dec, "Loaded legacy symbols");
509 } else if (g_module_symbol (module, "RV40toYUV420Init", &rv_init) &&
510 g_module_symbol (module, "RV40toYUV420Free", &rv_free) &&
511 g_module_symbol (module, "RV40toYUV420Transform", &rv_transform) &&
512 g_module_symbol (module, "RV40toYUV420CustomMessage", &rv_custom_msg)) {
513 GST_LOG_OBJECT (dec, "Loaded new symbols");
518 lib->Init = (guint32 (*)(gpointer, gpointer)) rv_init;
519 lib->Free = (guint32 (*)(gpointer)) rv_free;
520 lib->Transform = (guint32 (*)(gchar *, gchar *, gpointer, gpointer, gpointer))
522 lib->Message = (guint32 (*)(gpointer, gpointer)) rv_custom_msg;
523 lib->module = module;
525 dec->error_count = 0;
531 GST_ERROR_OBJECT (dec, "Cannot handle version %i.", version);
536 close_library (dec, lib);
537 GST_ERROR_OBJECT (dec, "Could not load all symbols: %s", g_module_error ());
543 close_library (GstRealVideoDec * dec, GstRVDecLibrary * lib)
546 GST_LOG_OBJECT (dec, "closing library");
548 lib->Free (lib->context);
551 GST_LOG_OBJECT (dec, "closing library module");
552 g_module_close (lib->module);
555 memset (lib, 0, sizeof (*lib));
559 gst_real_video_dec_probe_modules (GstRealVideoDec * dec)
561 GstRVDecLibrary dummy = { NULL };
563 if ((dec->valid_rv20 =
564 open_library (dec, GST_REAL_VIDEO_DEC_VERSION_2, &dummy)))
565 close_library (dec, &dummy);
566 if ((dec->valid_rv30 =
567 open_library (dec, GST_REAL_VIDEO_DEC_VERSION_3, &dummy)))
568 close_library (dec, &dummy);
569 if ((dec->valid_rv40 =
570 open_library (dec, GST_REAL_VIDEO_DEC_VERSION_4, &dummy)))
571 close_library (dec, &dummy);
574 static GstStateChangeReturn
575 gst_real_video_dec_change_state (GstElement * element,
576 GstStateChange transition)
578 GstStateChangeReturn ret;
579 GstRealVideoDec *dec = GST_REAL_VIDEO_DEC (element);
581 switch (transition) {
582 case GST_STATE_CHANGE_NULL_TO_READY:
583 gst_real_video_dec_probe_modules (dec);
584 dec->checked_modules = TRUE;
590 ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
592 switch (transition) {
593 case GST_STATE_CHANGE_PAUSED_TO_READY:
594 close_library (dec, &dec->lib);
596 case GST_STATE_CHANGE_READY_TO_NULL:
597 dec->checked_modules = FALSE;
606 gst_real_video_dec_init (GstRealVideoDec * dec, GstRealVideoDecClass * klass)
608 dec->snk = gst_pad_new_from_static_template (&snk_t, "sink");
609 gst_pad_set_getcaps_function (dec->snk,
610 GST_DEBUG_FUNCPTR (gst_real_video_dec_getcaps));
611 gst_pad_set_setcaps_function (dec->snk,
612 GST_DEBUG_FUNCPTR (gst_real_video_dec_setcaps));
613 gst_pad_set_chain_function (dec->snk,
614 GST_DEBUG_FUNCPTR (gst_real_video_dec_chain));
615 gst_element_add_pad (GST_ELEMENT (dec), dec->snk);
617 dec->src = gst_pad_new_from_static_template (&src_t, "src");
618 gst_pad_use_fixed_caps (dec->src);
619 gst_element_add_pad (GST_ELEMENT (dec), dec->src);
621 dec->max_errors = DEFAULT_MAX_ERRORS;
622 dec->error_count = 0;
626 gst_real_video_dec_base_init (gpointer g_class)
628 GstElementClass *ec = GST_ELEMENT_CLASS (g_class);
630 gst_element_class_add_static_pad_template (ec, &snk_t);
631 gst_element_class_add_static_pad_template (ec, &src_t);
632 gst_element_class_set_details_simple (ec, "RealVideo decoder",
633 "Codec/Decoder/Video", "Decoder for RealVideo streams",
634 "Lutz Mueller <lutz@topfrose.de>");
638 gst_real_video_dec_finalize (GObject * object)
640 GstRealVideoDec *dec = GST_REAL_VIDEO_DEC (object);
642 close_library (dec, &dec->lib);
644 if (dec->real_codecs_path) {
645 g_free (dec->real_codecs_path);
646 dec->real_codecs_path = NULL;
648 if (dec->rv20_names) {
649 g_free (dec->rv20_names);
650 dec->rv20_names = NULL;
652 if (dec->rv30_names) {
653 g_free (dec->rv30_names);
654 dec->rv30_names = NULL;
656 if (dec->rv40_names) {
657 g_free (dec->rv40_names);
658 dec->rv40_names = NULL;
661 G_OBJECT_CLASS (parent_class)->finalize (object);
665 gst_real_video_dec_set_property (GObject * object, guint prop_id,
666 const GValue * value, GParamSpec * pspec)
668 GstRealVideoDec *dec = GST_REAL_VIDEO_DEC (object);
670 /* Changing the location of the .so supposes it's not being done
671 * in a state greater than READY !
675 case PROP_REAL_CODECS_PATH:
676 if (dec->real_codecs_path)
677 g_free (dec->real_codecs_path);
678 dec->real_codecs_path = g_value_dup_string (value);
680 case PROP_RV20_NAMES:
682 g_free (dec->rv20_names);
683 dec->rv20_names = g_value_dup_string (value);
685 case PROP_RV30_NAMES:
687 g_free (dec->rv30_names);
688 dec->rv30_names = g_value_dup_string (value);
690 case PROP_RV40_NAMES:
692 g_free (dec->rv40_names);
693 dec->rv40_names = g_value_dup_string (value);
695 case PROP_MAX_ERRORS:
696 dec->max_errors = g_value_get_int (value);
699 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
705 gst_real_video_dec_get_property (GObject * object, guint prop_id,
706 GValue * value, GParamSpec * pspec)
708 GstRealVideoDec *dec = GST_REAL_VIDEO_DEC (object);
711 case PROP_REAL_CODECS_PATH:
712 g_value_set_string (value, dec->real_codecs_path ? dec->real_codecs_path
713 : DEFAULT_REAL_CODECS_PATH);
715 case PROP_RV20_NAMES:
716 g_value_set_string (value, dec->rv20_names ? dec->rv20_names :
719 case PROP_RV30_NAMES:
720 g_value_set_string (value, dec->rv30_names ? dec->rv30_names :
723 case PROP_RV40_NAMES:
724 g_value_set_string (value, dec->rv40_names ? dec->rv40_names :
727 case PROP_MAX_ERRORS:
728 g_value_set_int (value, dec->max_errors);
731 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
737 gst_real_video_dec_class_init (GstRealVideoDecClass * klass)
739 GObjectClass *object_class = G_OBJECT_CLASS (klass);
740 GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
742 object_class->set_property = gst_real_video_dec_set_property;
743 object_class->get_property = gst_real_video_dec_get_property;
744 object_class->finalize = gst_real_video_dec_finalize;
746 element_class->change_state = gst_real_video_dec_change_state;
748 g_object_class_install_property (object_class, PROP_REAL_CODECS_PATH,
749 g_param_spec_string ("real-codecs-path",
750 "Path where to search for RealPlayer codecs",
751 "Path where to search for RealPlayer codecs",
752 DEFAULT_REAL_CODECS_PATH,
753 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
754 g_object_class_install_property (object_class, PROP_RV20_NAMES,
755 g_param_spec_string ("rv20-names", "Names of rv20 driver",
756 "Names of rv20 driver", DEFAULT_RV20_NAMES,
757 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
758 g_object_class_install_property (object_class, PROP_RV30_NAMES,
759 g_param_spec_string ("rv30-names", "Names of rv30 driver",
760 "Names of rv30 driver", DEFAULT_RV30_NAMES,
761 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
762 g_object_class_install_property (object_class, PROP_RV40_NAMES,
763 g_param_spec_string ("rv40-names", "Names of rv40 driver",
764 "Names of rv40 driver", DEFAULT_RV40_NAMES,
765 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
766 g_object_class_install_property (object_class, PROP_MAX_ERRORS,
767 g_param_spec_int ("max-errors", "Max errors",
768 "Maximum number of consecutive errors (0 = unlimited)",
769 0, G_MAXINT, DEFAULT_MAX_ERRORS,
770 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
772 GST_DEBUG_CATEGORY_INIT (realvideode_debug, "realvideodec", 0,
773 "RealVideo decoder");