Merge branch 'master' of ssh://thomasvs@git.freedesktop.org/git/gstreamer/gst-plugins...
[platform/upstream/gst-plugins-good.git] / ext / dv / gstdvdec.c
1 /* GStreamer
2  * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
3  *               <2005> Wim Taymans <wim@fluendo.com>
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Library General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Library General Public License for more details.
14  *
15  * You should have received a copy of the GNU Library General Public
16  * License along with this library; if not, write to the
17  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18  * Boston, MA 02111-1307, USA.
19  */
20
21 /**
22  * SECTION:element-dvdec
23  *
24  * dvdec decodes DV video into raw video. The element expects a full DV frame
25  * as input, which is 120000 bytes for NTSC and 144000 for PAL video.
26  *
27  * This element can perform simple frame dropping with the #GstDVDec:drop-factor
28  * property. Setting this property to a value N > 1 will only decode every 
29  * Nth frame.
30  *
31  * <refsect2>
32  * <title>Example launch line</title>
33  * |[
34  * gst-launch filesrc location=test.dv ! dvdemux name=demux ! dvdec ! xvimagesink
35  * ]| This pipeline decodes and renders the raw DV stream to a videosink.
36  * </refsect2>
37  *
38  * Last reviewed on 2006-02-28 (0.10.3)
39  */
40
41 #ifdef HAVE_CONFIG_H
42 #include "config.h"
43 #endif
44 #include <string.h>
45 #include <math.h>
46 #include <gst/video/video.h>
47
48 #include "gstdvdec.h"
49
50
51 static const GstElementDetails dvdec_details =
52 GST_ELEMENT_DETAILS ("DV video decoder",
53     "Codec/Decoder/Video",
54     "Uses libdv to decode DV video (smpte314) (libdv.sourceforge.net)",
55     "Erik Walthinsen <omega@cse.ogi.edu>," "Wim Taymans <wim@fluendo.com>");
56
57 /* sizes of one input buffer */
58 #define NTSC_HEIGHT 480
59 #define NTSC_BUFFER 120000
60 #define NTSC_FRAMERATE_NUMERATOR 30000
61 #define NTSC_FRAMERATE_DENOMINATOR 1001
62
63 #define PAL_HEIGHT 576
64 #define PAL_BUFFER 144000
65 #define PAL_FRAMERATE_NUMERATOR 25
66 #define PAL_FRAMERATE_DENOMINATOR 1
67
68 #define PAL_NORMAL_PAR_X        59
69 #define PAL_NORMAL_PAR_Y        54
70 #define PAL_WIDE_PAR_X          118
71 #define PAL_WIDE_PAR_Y          81
72
73 #define NTSC_NORMAL_PAR_X       10
74 #define NTSC_NORMAL_PAR_Y       11
75 #define NTSC_WIDE_PAR_X         40
76 #define NTSC_WIDE_PAR_Y         33
77
78 #define DV_DEFAULT_QUALITY DV_QUALITY_BEST
79 #define DV_DEFAULT_DECODE_NTH 1
80
81 GST_DEBUG_CATEGORY_STATIC (dvdec_debug);
82 #define GST_CAT_DEFAULT dvdec_debug
83
84 enum
85 {
86   PROP_0,
87   PROP_CLAMP_LUMA,
88   PROP_CLAMP_CHROMA,
89   PROP_QUALITY,
90   PROP_DECODE_NTH
91 };
92
93 const gint qualities[] = {
94   DV_QUALITY_DC,
95   DV_QUALITY_AC_1,
96   DV_QUALITY_AC_2,
97   DV_QUALITY_DC | DV_QUALITY_COLOR,
98   DV_QUALITY_AC_1 | DV_QUALITY_COLOR,
99   DV_QUALITY_AC_2 | DV_QUALITY_COLOR
100 };
101
102 static GstStaticPadTemplate sink_temp = GST_STATIC_PAD_TEMPLATE ("sink",
103     GST_PAD_SINK,
104     GST_PAD_ALWAYS,
105     GST_STATIC_CAPS ("video/x-dv, systemstream = (boolean) false")
106     );
107
108 static GstStaticPadTemplate src_temp = GST_STATIC_PAD_TEMPLATE ("src",
109     GST_PAD_SRC,
110     GST_PAD_ALWAYS,
111     GST_STATIC_CAPS ("video/x-raw-yuv, "
112         "format = (fourcc) YUY2, "
113         "width = (int) 720, "
114         "framerate = (fraction) [ 1/1, 60/1 ];"
115         "video/x-raw-rgb, "
116         "bpp = (int) 32, "
117         "depth = (int) 24, "
118         "endianness = (int) " G_STRINGIFY (G_BIG_ENDIAN) ", "
119         "red_mask =   (int) 0x0000ff00, "
120         "green_mask = (int) 0x00ff0000, "
121         "blue_mask =  (int) 0xff000000, "
122         "width = (int) 720, "
123         "framerate = (fraction) [ 1/1, 60/1 ];"
124         "video/x-raw-rgb, "
125         "bpp = (int) 24, "
126         "depth = (int) 24, "
127         "endianness = (int) " G_STRINGIFY (G_BIG_ENDIAN) ", "
128         "red_mask =   (int) 0x00ff0000, "
129         "green_mask = (int) 0x0000ff00, "
130         "blue_mask =  (int) 0x000000ff, "
131         "width = (int) 720, " "framerate = (fraction) [ 1/1, 60/1 ]")
132     );
133
134 #define GST_TYPE_DVDEC_QUALITY (gst_dvdec_quality_get_type())
135 GType
136 gst_dvdec_quality_get_type (void)
137 {
138   static GType qtype = 0;
139
140   if (qtype == 0) {
141     static const GEnumValue values[] = {
142       {0, "Monochrome, DC (Fastest)", "fastest"},
143       {1, "Monochrome, first AC coefficient", "monochrome-ac"},
144       {2, "Monochrome, highest quality", "monochrome-best"},
145       {3, "Colour, DC, fastest", "colour-fastest"},
146       {4, "Colour, using only the first AC coefficient", "colour-ac"},
147       {5, "Highest quality colour decoding", "best"},
148       {0, NULL, NULL},
149     };
150
151     qtype = g_enum_register_static ("GstDVDecQualityEnum", values);
152   }
153   return qtype;
154 }
155
156 GST_BOILERPLATE (GstDVDec, gst_dvdec, GstElement, GST_TYPE_ELEMENT);
157
158 static void gst_dvdec_finalize (GObject * object);
159 static gboolean gst_dvdec_sink_setcaps (GstPad * pad, GstCaps * caps);
160 static GstFlowReturn gst_dvdec_chain (GstPad * pad, GstBuffer * buffer);
161 static gboolean gst_dvdec_sink_event (GstPad * pad, GstEvent * event);
162
163 static GstStateChangeReturn gst_dvdec_change_state (GstElement * element,
164     GstStateChange transition);
165
166 static void gst_dvdec_set_property (GObject * object, guint prop_id,
167     const GValue * value, GParamSpec * pspec);
168 static void gst_dvdec_get_property (GObject * object, guint prop_id,
169     GValue * value, GParamSpec * pspec);
170
171 static void
172 gst_dvdec_base_init (gpointer g_class)
173 {
174   GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
175
176   gst_element_class_add_pad_template (element_class,
177       gst_static_pad_template_get (&sink_temp));
178   gst_element_class_add_pad_template (element_class,
179       gst_static_pad_template_get (&src_temp));
180
181   gst_element_class_set_details (element_class, &dvdec_details);
182
183   GST_DEBUG_CATEGORY_INIT (dvdec_debug, "dvdec", 0, "DV decoding element");
184 }
185
186 static void
187 gst_dvdec_class_init (GstDVDecClass * klass)
188 {
189   GObjectClass *gobject_class;
190   GstElementClass *gstelement_class;
191
192   gobject_class = (GObjectClass *) klass;
193   gstelement_class = (GstElementClass *) klass;
194
195   gobject_class->finalize = gst_dvdec_finalize;
196   gobject_class->set_property = gst_dvdec_set_property;
197   gobject_class->get_property = gst_dvdec_get_property;
198
199   g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_CLAMP_LUMA,
200       g_param_spec_boolean ("clamp_luma", "Clamp luma", "Clamp luma",
201           FALSE, G_PARAM_READWRITE));
202   g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_CLAMP_CHROMA,
203       g_param_spec_boolean ("clamp_chroma", "Clamp chroma", "Clamp chroma",
204           FALSE, G_PARAM_READWRITE));
205   g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_QUALITY,
206       g_param_spec_enum ("quality", "Quality", "Decoding quality",
207           GST_TYPE_DVDEC_QUALITY, DV_DEFAULT_QUALITY, G_PARAM_READWRITE));
208   g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_DECODE_NTH,
209       g_param_spec_int ("drop-factor", "Drop Factor", "Only decode Nth frame",
210           1, G_MAXINT, DV_DEFAULT_DECODE_NTH, G_PARAM_READWRITE));
211
212   gstelement_class->change_state = gst_dvdec_change_state;
213 }
214
215 static void
216 gst_dvdec_init (GstDVDec * dvdec, GstDVDecClass * g_class)
217 {
218   dvdec->sinkpad = gst_pad_new_from_static_template (&sink_temp, "sink");
219   gst_pad_set_setcaps_function (dvdec->sinkpad,
220       GST_DEBUG_FUNCPTR (gst_dvdec_sink_setcaps));
221   gst_pad_set_chain_function (dvdec->sinkpad, gst_dvdec_chain);
222   gst_pad_set_event_function (dvdec->sinkpad, gst_dvdec_sink_event);
223   gst_element_add_pad (GST_ELEMENT (dvdec), dvdec->sinkpad);
224
225   dvdec->srcpad = gst_pad_new_from_static_template (&src_temp, "src");
226   gst_pad_use_fixed_caps (dvdec->srcpad);
227   gst_element_add_pad (GST_ELEMENT (dvdec), dvdec->srcpad);
228
229   dvdec->framerate_numerator = 0;
230   dvdec->framerate_denominator = 0;
231   dvdec->wide = FALSE;
232   dvdec->drop_factor = 1;
233
234   dvdec->clamp_luma = FALSE;
235   dvdec->clamp_chroma = FALSE;
236   dvdec->quality = DV_DEFAULT_QUALITY;
237   dvdec->segment = gst_segment_new ();
238 }
239
240 static void
241 gst_dvdec_finalize (GObject * object)
242 {
243   GstDVDec *dvdec = GST_DVDEC (object);
244
245   gst_segment_free (dvdec->segment);
246
247   G_OBJECT_CLASS (parent_class)->finalize (object);
248 }
249
250 static gboolean
251 gst_dvdec_sink_setcaps (GstPad * pad, GstCaps * caps)
252 {
253   GstDVDec *dvdec;
254   GstStructure *s;
255   const GValue *par = NULL, *rate = NULL;
256
257   dvdec = GST_DVDEC (gst_pad_get_parent (pad));
258
259   /* first parse the caps */
260   s = gst_caps_get_structure (caps, 0);
261
262   /* we allow framerate and PAR to be overwritten. framerate is mandatory. */
263   if (!(rate = gst_structure_get_value (s, "framerate")))
264     goto no_framerate;
265   par = gst_structure_get_value (s, "pixel-aspect-ratio");
266
267   if (par) {
268     dvdec->par_x = gst_value_get_fraction_numerator (par);
269     dvdec->par_y = gst_value_get_fraction_denominator (par);
270     dvdec->need_par = FALSE;
271   } else {
272     dvdec->par_x = 0;
273     dvdec->par_y = 0;
274     dvdec->need_par = TRUE;
275   }
276   dvdec->framerate_numerator = gst_value_get_fraction_numerator (rate);
277   dvdec->framerate_denominator = gst_value_get_fraction_denominator (rate);
278   dvdec->sink_negotiated = TRUE;
279   dvdec->src_negotiated = FALSE;
280
281   gst_object_unref (dvdec);
282
283   return TRUE;
284
285   /* ERRORS */
286 no_framerate:
287   {
288     GST_DEBUG_OBJECT (dvdec, "no framerate specified in caps");
289     gst_object_unref (dvdec);
290     return FALSE;
291   }
292 }
293
294 static gboolean
295 gst_dvdec_src_negotiate (GstDVDec * dvdec)
296 {
297   GstCaps *othercaps;
298
299   /* no PAR was specified in input, derive from encoded data */
300   if (dvdec->need_par) {
301     if (dvdec->PAL) {
302       if (dvdec->wide) {
303         dvdec->par_x = PAL_WIDE_PAR_X;
304         dvdec->par_y = PAL_WIDE_PAR_Y;
305       } else {
306         dvdec->par_x = PAL_NORMAL_PAR_X;
307         dvdec->par_y = PAL_NORMAL_PAR_Y;
308       }
309     } else {
310       if (dvdec->wide) {
311         dvdec->par_x = NTSC_WIDE_PAR_X;
312         dvdec->par_y = NTSC_WIDE_PAR_Y;
313       } else {
314         dvdec->par_x = NTSC_NORMAL_PAR_X;
315         dvdec->par_y = NTSC_NORMAL_PAR_Y;
316       }
317     }
318     GST_DEBUG_OBJECT (dvdec, "Inferred PAR %d/%d from video format",
319         dvdec->par_x, dvdec->par_y);
320   }
321
322   /* ignoring rgb, bgr0 for now */
323   dvdec->bpp = 2;
324
325   othercaps = gst_caps_new_simple ("video/x-raw-yuv",
326       "format", GST_TYPE_FOURCC, GST_STR_FOURCC ("YUY2"),
327       "width", G_TYPE_INT, 720,
328       "height", G_TYPE_INT, dvdec->height,
329       "framerate", GST_TYPE_FRACTION, dvdec->framerate_numerator,
330       dvdec->framerate_denominator,
331       "pixel-aspect-ratio", GST_TYPE_FRACTION, dvdec->par_x,
332       dvdec->par_y, "interlaced", G_TYPE_BOOLEAN, dvdec->interlaced, NULL);
333
334   gst_pad_set_caps (dvdec->srcpad, othercaps);
335   gst_caps_unref (othercaps);
336
337   dvdec->src_negotiated = TRUE;
338
339   return TRUE;
340 }
341
342 static gboolean
343 gst_dvdec_sink_event (GstPad * pad, GstEvent * event)
344 {
345   GstDVDec *dvdec;
346   gboolean res = TRUE;
347
348   dvdec = GST_DVDEC (gst_pad_get_parent (pad));
349
350   switch (GST_EVENT_TYPE (event)) {
351     case GST_EVENT_FLUSH_STOP:
352       gst_segment_init (dvdec->segment, GST_FORMAT_UNDEFINED);
353       break;
354     case GST_EVENT_NEWSEGMENT:{
355       gboolean update;
356       gdouble rate, applied_rate;
357       GstFormat format;
358       gint64 start, stop, position;
359
360       gst_event_parse_new_segment_full (event, &update, &rate, &applied_rate,
361           &format, &start, &stop, &position);
362
363       GST_DEBUG_OBJECT (dvdec, "Got NEWSEGMENT [%" GST_TIME_FORMAT
364           " - %" GST_TIME_FORMAT " / %" GST_TIME_FORMAT "]",
365           GST_TIME_ARGS (start), GST_TIME_ARGS (stop),
366           GST_TIME_ARGS (position));
367
368       gst_segment_set_newsegment_full (dvdec->segment, update, rate,
369           applied_rate, format, start, stop, position);
370       break;
371     }
372     default:
373       break;
374   }
375
376   res = gst_pad_push_event (dvdec->srcpad, event);
377
378   return res;
379 }
380
381 static GstFlowReturn
382 gst_dvdec_chain (GstPad * pad, GstBuffer * buf)
383 {
384   GstDVDec *dvdec;
385   guint8 *inframe;
386   guint8 *outframe;
387   guint8 *outframe_ptrs[3];
388   gint outframe_pitches[3];
389   GstBuffer *outbuf;
390   GstFlowReturn ret = GST_FLOW_OK;
391   guint length;
392   gint64 cstart, cstop;
393   gboolean PAL, wide;
394
395   dvdec = GST_DVDEC (gst_pad_get_parent (pad));
396   inframe = GST_BUFFER_DATA (buf);
397
398   /* buffer should be at least the size of one NTSC frame, this should
399    * be enough to decode the header. */
400   if (G_UNLIKELY (GST_BUFFER_SIZE (buf) < NTSC_BUFFER))
401     goto wrong_size;
402
403   /* preliminary dropping. unref and return if outside of configured segment */
404   if ((dvdec->segment->format == GST_FORMAT_TIME) &&
405       (!(gst_segment_clip (dvdec->segment, GST_FORMAT_TIME,
406                   GST_BUFFER_TIMESTAMP (buf),
407                   GST_BUFFER_TIMESTAMP (buf) + GST_BUFFER_DURATION (buf),
408                   &cstart, &cstop))))
409     goto dropping;
410
411   if (G_UNLIKELY (dv_parse_header (dvdec->decoder, inframe) < 0))
412     goto parse_header_error;
413
414   /* get size */
415   PAL = dv_system_50_fields (dvdec->decoder);
416   wide = dv_format_wide (dvdec->decoder);
417
418   /* check the buffer is of right size after we know if we are
419    * dealing with PAL or NTSC */
420   length = (PAL ? PAL_BUFFER : NTSC_BUFFER);
421   if (G_UNLIKELY (GST_BUFFER_SIZE (buf) < length))
422     goto wrong_size;
423
424   dv_parse_packs (dvdec->decoder, inframe);
425
426   if (dvdec->video_offset % dvdec->drop_factor != 0)
427     goto skip;
428
429   /* renegotiate on change */
430   if (PAL != dvdec->PAL || wide != dvdec->wide) {
431     dvdec->src_negotiated = FALSE;
432     dvdec->PAL = PAL;
433     dvdec->wide = wide;
434   }
435
436   dvdec->height = (dvdec->PAL ? PAL_HEIGHT : NTSC_HEIGHT);
437
438   dvdec->interlaced = !dv_is_progressive (dvdec->decoder);
439
440   /* negotiate if not done yet */
441   if (!dvdec->src_negotiated) {
442     if (!gst_dvdec_src_negotiate (dvdec))
443       goto not_negotiated;
444   }
445
446   ret =
447       gst_pad_alloc_buffer_and_set_caps (dvdec->srcpad, 0,
448       (720 * dvdec->height) * dvdec->bpp,
449       GST_PAD_CAPS (dvdec->srcpad), &outbuf);
450   if (G_UNLIKELY (ret != GST_FLOW_OK))
451     goto no_buffer;
452
453   outframe = GST_BUFFER_DATA (outbuf);
454
455   outframe_ptrs[0] = outframe;
456   outframe_pitches[0] = 720 * dvdec->bpp;
457
458   /* the rest only matters for YUY2 */
459   if (dvdec->bpp < 3) {
460     outframe_ptrs[1] = outframe_ptrs[0] + 720 * dvdec->height;
461     outframe_ptrs[2] = outframe_ptrs[1] + 360 * dvdec->height;
462
463     outframe_pitches[1] = dvdec->height / 2;
464     outframe_pitches[2] = outframe_pitches[1];
465   }
466
467   GST_DEBUG_OBJECT (dvdec, "decoding and pushing buffer");
468   dv_decode_full_frame (dvdec->decoder, inframe,
469       e_dv_color_yuv, outframe_ptrs, outframe_pitches);
470
471   if (dvdec->PAL) {
472     GST_BUFFER_FLAG_SET (outbuf, GST_VIDEO_BUFFER_TFF);
473   } else {
474     GST_BUFFER_FLAG_UNSET (outbuf, GST_VIDEO_BUFFER_TFF);
475   }
476
477   GST_BUFFER_OFFSET (outbuf) = GST_BUFFER_OFFSET (buf);
478   GST_BUFFER_OFFSET_END (outbuf) = GST_BUFFER_OFFSET_END (buf);
479   GST_BUFFER_TIMESTAMP (outbuf) = cstart;
480   GST_BUFFER_DURATION (outbuf) = cstop - cstart;
481
482   ret = gst_pad_push (dvdec->srcpad, outbuf);
483
484 skip:
485   dvdec->video_offset++;
486
487 done:
488   gst_buffer_unref (buf);
489   gst_object_unref (dvdec);
490
491   return ret;
492
493   /* ERRORS */
494 wrong_size:
495   {
496     GST_ELEMENT_ERROR (dvdec, STREAM, DECODE,
497         (NULL), ("Input buffer too small"));
498     ret = GST_FLOW_ERROR;
499     goto done;
500   }
501 parse_header_error:
502   {
503     GST_ELEMENT_ERROR (dvdec, STREAM, DECODE,
504         (NULL), ("Error parsing DV header"));
505     ret = GST_FLOW_ERROR;
506     goto done;
507   }
508 not_negotiated:
509   {
510     GST_DEBUG_OBJECT (dvdec, "could not negotiate output");
511     ret = GST_FLOW_NOT_NEGOTIATED;
512     goto done;
513   }
514 no_buffer:
515   {
516     GST_DEBUG_OBJECT (dvdec, "could not allocate buffer");
517     goto done;
518   }
519
520 dropping:
521   {
522     GST_DEBUG_OBJECT (dvdec,
523         "dropping buffer since it's out of the configured segment");
524     goto done;
525   }
526 }
527
528 static GstStateChangeReturn
529 gst_dvdec_change_state (GstElement * element, GstStateChange transition)
530 {
531   GstDVDec *dvdec = GST_DVDEC (element);
532   GstStateChangeReturn ret;
533
534
535   switch (transition) {
536     case GST_STATE_CHANGE_NULL_TO_READY:
537       break;
538     case GST_STATE_CHANGE_READY_TO_PAUSED:
539       dvdec->decoder =
540           dv_decoder_new (0, dvdec->clamp_luma, dvdec->clamp_chroma);
541       dvdec->decoder->quality = qualities[dvdec->quality];
542       dv_set_error_log (dvdec->decoder, NULL);
543       gst_segment_init (dvdec->segment, GST_FORMAT_UNDEFINED);
544       dvdec->src_negotiated = FALSE;
545       dvdec->sink_negotiated = FALSE;
546       /* 
547        * Enable this function call when libdv2 0.100 or higher is more
548        * common
549        */
550       /* dv_set_quality (dvdec->decoder, qualities [dvdec->quality]); */
551       break;
552     case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
553       break;
554     default:
555       break;
556   }
557
558   ret = parent_class->change_state (element, transition);
559
560   switch (transition) {
561     case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
562       break;
563     case GST_STATE_CHANGE_PAUSED_TO_READY:
564       dv_decoder_free (dvdec->decoder);
565       dvdec->decoder = NULL;
566       break;
567     case GST_STATE_CHANGE_READY_TO_NULL:
568       break;
569     default:
570       break;
571   }
572   return ret;
573 }
574
575 static void
576 gst_dvdec_set_property (GObject * object, guint prop_id, const GValue * value,
577     GParamSpec * pspec)
578 {
579   GstDVDec *dvdec = GST_DVDEC (object);
580
581   switch (prop_id) {
582     case PROP_CLAMP_LUMA:
583       dvdec->clamp_luma = g_value_get_boolean (value);
584       break;
585     case PROP_CLAMP_CHROMA:
586       dvdec->clamp_chroma = g_value_get_boolean (value);
587       break;
588     case PROP_QUALITY:
589       dvdec->quality = g_value_get_enum (value);
590       if ((dvdec->quality < 0) || (dvdec->quality > 5))
591         dvdec->quality = 0;
592       break;
593     case PROP_DECODE_NTH:
594       dvdec->drop_factor = g_value_get_int (value);
595       break;
596     default:
597       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
598       break;
599   }
600 }
601
602 static void
603 gst_dvdec_get_property (GObject * object, guint prop_id, GValue * value,
604     GParamSpec * pspec)
605 {
606   GstDVDec *dvdec = GST_DVDEC (object);
607
608   switch (prop_id) {
609     case PROP_CLAMP_LUMA:
610       g_value_set_boolean (value, dvdec->clamp_luma);
611       break;
612     case PROP_CLAMP_CHROMA:
613       g_value_set_boolean (value, dvdec->clamp_chroma);
614       break;
615     case PROP_QUALITY:
616       g_value_set_enum (value, dvdec->quality);
617       break;
618     case PROP_DECODE_NTH:
619       g_value_set_int (value, dvdec->drop_factor);
620       break;
621     default:
622       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
623       break;
624   }
625 }