ffmpegdec: Setting AC3/EAC3/DTS decoders to rank NONE for release
[gstreamer-omap:gst-ffmpeg.git] / ext / ffmpeg / gstffmpegdec.c
1 /* GStreamer
2  * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19
20 #ifdef HAVE_CONFIG_H
21 #include "config.h"
22 #endif
23
24 #include <assert.h>
25 #include <string.h>
26
27 #ifdef HAVE_FFMPEG_UNINSTALLED
28 #include <avcodec.h>
29 #else
30 #include <libavcodec/avcodec.h>
31 #endif
32
33 #include <gst/gst.h>
34 #include <gst/video/video.h>
35
36 #include "gstffmpeg.h"
37 #include "gstffmpegcodecmap.h"
38 #include "gstffmpegutils.h"
39
40 /* define to enable alternative buffer refcounting algorithm */
41 #undef EXTRA_REF
42
43 typedef struct _GstFFMpegDec GstFFMpegDec;
44
45 #define MAX_TS_MASK 0xff
46
47 /* for each incomming buffer we keep all timing info in a structure like this.
48  * We keep a circular array of these structures around to store the timing info.
49  * The index in the array is what we pass as opaque data (to pictures) and
50  * pts (to parsers) so that ffmpeg can remember them for us. */
51 typedef struct
52 {
53   gint idx;
54   GstClockTime timestamp;
55   GstClockTime duration;
56   gint64 offset;
57 } GstTSInfo;
58
59 struct _GstFFMpegDec
60 {
61   GstElement element;
62
63   /* We need to keep track of our pads, so we do so here. */
64   GstPad *srcpad;
65   GstPad *sinkpad;
66
67   /* decoding */
68   AVCodecContext *context;
69   AVFrame *picture;
70   gboolean opened;
71   union
72   {
73     struct
74     {
75       gint width, height;
76       gint clip_width, clip_height;
77       gint par_n, par_d;
78       gint fps_n, fps_d;
79       gint old_fps_n, old_fps_d;
80       gboolean interlaced;
81
82       enum PixelFormat pix_fmt;
83     } video;
84     struct
85     {
86       gint channels;
87       gint samplerate;
88       gint depth;
89     } audio;
90   } format;
91   gboolean waiting_for_key;
92   gboolean discont;
93   gboolean clear_ts;
94
95   /* for tracking DTS/PTS */
96   gboolean has_b_frames;
97   gboolean reordered_in;
98   GstClockTime last_in;
99   GstClockTime last_diff;
100   guint last_frames;
101   gboolean reordered_out;
102   GstClockTime last_out;
103   GstClockTime next_out;
104
105   /* parsing */
106   gboolean turnoff_parser;      /* used for turning off aac raw parsing
107                                  * See bug #566250 */
108   AVCodecParserContext *pctx;
109   GstBuffer *pcache;
110   guint8 *padded;
111   guint padded_size;
112
113   GValue *par;                  /* pixel aspect ratio of incoming data */
114   gboolean current_dr;          /* if direct rendering is enabled */
115   gboolean extra_ref;           /* keep extra ref around in get/release */
116
117   /* some properties */
118   enum AVDiscard skip_frame;
119   gint lowres;
120   gboolean direct_rendering;
121   gboolean do_padding;
122   gboolean debug_mv;
123   gboolean crop;
124   int max_threads;
125
126   /* QoS stuff *//* with LOCK */
127   gdouble proportion;
128   GstClockTime earliest_time;
129
130   /* clipping segment */
131   GstSegment segment;
132
133   gboolean is_realvideo;
134
135   GstTSInfo ts_info[MAX_TS_MASK + 1];
136   gint ts_idx;
137
138   /* reverse playback queue */
139   GList *queued;
140
141   /* Can downstream allocate 16bytes aligned data. */
142   gboolean can_allocate_aligned;
143 };
144
145 typedef struct _GstFFMpegDecClass GstFFMpegDecClass;
146
147 struct _GstFFMpegDecClass
148 {
149   GstElementClass parent_class;
150
151   AVCodec *in_plugin;
152   GstPadTemplate *srctempl, *sinktempl;
153 };
154
155 #define GST_TS_INFO_NONE &ts_info_none
156 static const GstTSInfo ts_info_none = { -1, -1, -1, -1 };
157
158 static const GstTSInfo *
159 gst_ts_info_store (GstFFMpegDec * dec, GstClockTime timestamp,
160     GstClockTime duration, gint64 offset)
161 {
162   gint idx = dec->ts_idx;
163   dec->ts_info[idx].idx = idx;
164   dec->ts_info[idx].timestamp = timestamp;
165   dec->ts_info[idx].duration = duration;
166   dec->ts_info[idx].offset = offset;
167   dec->ts_idx = (idx + 1) & MAX_TS_MASK;
168
169   return &dec->ts_info[idx];
170 }
171
172 static const GstTSInfo *
173 gst_ts_info_get (GstFFMpegDec * dec, gint idx)
174 {
175   if (G_UNLIKELY (idx < 0 || idx > MAX_TS_MASK))
176     return GST_TS_INFO_NONE;
177
178   return &dec->ts_info[idx];
179 }
180
181 #define GST_TYPE_FFMPEGDEC \
182   (gst_ffmpegdec_get_type())
183 #define GST_FFMPEGDEC(obj) \
184   (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_FFMPEGDEC,GstFFMpegDec))
185 #define GST_FFMPEGDEC_CLASS(klass) \
186   (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_FFMPEGDEC,GstFFMpegDecClass))
187 #define GST_IS_FFMPEGDEC(obj) \
188   (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_FFMPEGDEC))
189 #define GST_IS_FFMPEGDEC_CLASS(klass) \
190   (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_FFMPEGDEC))
191
192 #define DEFAULT_LOWRES                  0
193 #define DEFAULT_SKIPFRAME               0
194 #define DEFAULT_DIRECT_RENDERING        TRUE
195 #define DEFAULT_DO_PADDING              TRUE
196 #define DEFAULT_DEBUG_MV                FALSE
197 #define DEFAULT_CROP                    TRUE
198 #define DEFAULT_MAX_THREADS             0
199
200 enum
201 {
202   PROP_0,
203   PROP_LOWRES,
204   PROP_SKIPFRAME,
205   PROP_DIRECT_RENDERING,
206   PROP_DO_PADDING,
207   PROP_DEBUG_MV,
208   PROP_CROP,
209   PROP_MAX_THREADS,
210   PROP_LAST
211 };
212
213 /* A number of function prototypes are given so we can refer to them later. */
214 static void gst_ffmpegdec_base_init (GstFFMpegDecClass * klass);
215 static void gst_ffmpegdec_class_init (GstFFMpegDecClass * klass);
216 static void gst_ffmpegdec_init (GstFFMpegDec * ffmpegdec);
217 static void gst_ffmpegdec_finalize (GObject * object);
218
219 static gboolean gst_ffmpegdec_query (GstPad * pad, GstQuery * query);
220 static gboolean gst_ffmpegdec_src_event (GstPad * pad, GstEvent * event);
221
222 static gboolean gst_ffmpegdec_setcaps (GstPad * pad, GstCaps * caps);
223 static gboolean gst_ffmpegdec_sink_event (GstPad * pad, GstEvent * event);
224 static GstFlowReturn gst_ffmpegdec_chain (GstPad * pad, GstBuffer * buf);
225
226 static GstStateChangeReturn gst_ffmpegdec_change_state (GstElement * element,
227     GstStateChange transition);
228
229 static void gst_ffmpegdec_set_property (GObject * object,
230     guint prop_id, const GValue * value, GParamSpec * pspec);
231 static void gst_ffmpegdec_get_property (GObject * object,
232     guint prop_id, GValue * value, GParamSpec * pspec);
233
234 static gboolean gst_ffmpegdec_negotiate (GstFFMpegDec * ffmpegdec,
235     gboolean force);
236
237 /* some sort of bufferpool handling, but different */
238 static int gst_ffmpegdec_get_buffer (AVCodecContext * context,
239     AVFrame * picture);
240 static void gst_ffmpegdec_release_buffer (AVCodecContext * context,
241     AVFrame * picture);
242
243 static void gst_ffmpegdec_drain (GstFFMpegDec * ffmpegdec);
244
245 #define GST_FFDEC_PARAMS_QDATA g_quark_from_static_string("ffdec-params")
246
247 static GstElementClass *parent_class = NULL;
248
249 #define GST_FFMPEGDEC_TYPE_LOWRES (gst_ffmpegdec_lowres_get_type())
250 static GType
251 gst_ffmpegdec_lowres_get_type (void)
252 {
253   static GType ffmpegdec_lowres_type = 0;
254
255   if (!ffmpegdec_lowres_type) {
256     static const GEnumValue ffmpegdec_lowres[] = {
257       {0, "0", "full"},
258       {1, "1", "1/2-size"},
259       {2, "2", "1/4-size"},
260       {0, NULL, NULL},
261     };
262
263     ffmpegdec_lowres_type =
264         g_enum_register_static ("GstFFMpegDecLowres", ffmpegdec_lowres);
265   }
266
267   return ffmpegdec_lowres_type;
268 }
269
270 #define GST_FFMPEGDEC_TYPE_SKIPFRAME (gst_ffmpegdec_skipframe_get_type())
271 static GType
272 gst_ffmpegdec_skipframe_get_type (void)
273 {
274   static GType ffmpegdec_skipframe_type = 0;
275
276   if (!ffmpegdec_skipframe_type) {
277     static const GEnumValue ffmpegdec_skipframe[] = {
278       {0, "0", "Skip nothing"},
279       {1, "1", "Skip B-frames"},
280       {2, "2", "Skip IDCT/Dequantization"},
281       {5, "5", "Skip everything"},
282       {0, NULL, NULL},
283     };
284
285     ffmpegdec_skipframe_type =
286         g_enum_register_static ("GstFFMpegDecSkipFrame", ffmpegdec_skipframe);
287   }
288
289   return ffmpegdec_skipframe_type;
290 }
291
292 static void
293 gst_ffmpegdec_base_init (GstFFMpegDecClass * klass)
294 {
295   GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
296   GstPadTemplate *sinktempl, *srctempl;
297   GstCaps *sinkcaps, *srccaps;
298   AVCodec *in_plugin;
299   gchar *longname, *classification, *description;
300
301   in_plugin =
302       (AVCodec *) g_type_get_qdata (G_OBJECT_CLASS_TYPE (klass),
303       GST_FFDEC_PARAMS_QDATA);
304   g_assert (in_plugin != NULL);
305
306   /* construct the element details struct */
307   longname = g_strdup_printf ("FFmpeg %s decoder", in_plugin->long_name);
308   classification = g_strdup_printf ("Codec/Decoder/%s",
309       (in_plugin->type == AVMEDIA_TYPE_VIDEO) ? "Video" : "Audio");
310   description = g_strdup_printf ("FFmpeg %s decoder", in_plugin->name);
311   gst_element_class_set_details_simple (element_class, longname, classification,
312       description,
313       "Wim Taymans <wim.taymans@gmail.com>, "
314       "Ronald Bultje <rbultje@ronald.bitfreak.net>, "
315       "Edward Hervey <bilboed@bilboed.com>");
316   g_free (longname);
317   g_free (classification);
318   g_free (description);
319
320   /* get the caps */
321   sinkcaps = gst_ffmpeg_codecid_to_caps (in_plugin->id, NULL, FALSE);
322   if (!sinkcaps) {
323     GST_DEBUG ("Couldn't get sink caps for decoder '%s'", in_plugin->name);
324     sinkcaps = gst_caps_from_string ("unknown/unknown");
325   }
326   if (in_plugin->type == AVMEDIA_TYPE_VIDEO) {
327     srccaps = gst_caps_from_string ("video/x-raw-rgb; video/x-raw-yuv");
328   } else {
329     srccaps = gst_ffmpeg_codectype_to_audio_caps (NULL,
330         in_plugin->id, FALSE, in_plugin);
331   }
332   if (!srccaps) {
333     GST_DEBUG ("Couldn't get source caps for decoder '%s'", in_plugin->name);
334     srccaps = gst_caps_from_string ("unknown/unknown");
335   }
336
337   /* pad templates */
338   sinktempl = gst_pad_template_new ("sink", GST_PAD_SINK,
339       GST_PAD_ALWAYS, sinkcaps);
340   srctempl = gst_pad_template_new ("src", GST_PAD_SRC, GST_PAD_ALWAYS, srccaps);
341
342   gst_element_class_add_pad_template (element_class, srctempl);
343   gst_element_class_add_pad_template (element_class, sinktempl);
344
345   klass->in_plugin = in_plugin;
346   klass->srctempl = srctempl;
347   klass->sinktempl = sinktempl;
348 }
349
350 static void
351 gst_ffmpegdec_class_init (GstFFMpegDecClass * klass)
352 {
353   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
354   GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass);
355
356   parent_class = g_type_class_peek_parent (klass);
357
358   gobject_class->finalize = gst_ffmpegdec_finalize;
359
360   gobject_class->set_property = gst_ffmpegdec_set_property;
361   gobject_class->get_property = gst_ffmpegdec_get_property;
362
363   if (klass->in_plugin->type == AVMEDIA_TYPE_VIDEO) {
364     int caps;
365
366     g_object_class_install_property (gobject_class, PROP_SKIPFRAME,
367         g_param_spec_enum ("skip-frame", "Skip frames",
368             "Which types of frames to skip during decoding",
369             GST_FFMPEGDEC_TYPE_SKIPFRAME, 0,
370             G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
371     g_object_class_install_property (gobject_class, PROP_LOWRES,
372         g_param_spec_enum ("lowres", "Low resolution",
373             "At which resolution to decode images", GST_FFMPEGDEC_TYPE_LOWRES,
374             0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
375     g_object_class_install_property (gobject_class, PROP_DIRECT_RENDERING,
376         g_param_spec_boolean ("direct-rendering", "Direct Rendering",
377             "Enable direct rendering", DEFAULT_DIRECT_RENDERING,
378             G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
379     g_object_class_install_property (gobject_class, PROP_DO_PADDING,
380         g_param_spec_boolean ("do-padding", "Do Padding",
381             "Add 0 padding before decoding data", DEFAULT_DO_PADDING,
382             G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
383     g_object_class_install_property (gobject_class, PROP_DEBUG_MV,
384         g_param_spec_boolean ("debug-mv", "Debug motion vectors",
385             "Whether ffmpeg should print motion vectors on top of the image",
386             DEFAULT_DEBUG_MV, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
387 #if 0
388     g_object_class_install_property (gobject_class, PROP_CROP,
389         g_param_spec_boolean ("crop", "Crop",
390             "Crop images to the display region",
391             DEFAULT_CROP, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
392 #endif
393
394     caps = klass->in_plugin->capabilities;
395     if (caps & (CODEC_CAP_FRAME_THREADS | CODEC_CAP_SLICE_THREADS)) {
396       g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_MAX_THREADS,
397           g_param_spec_int ("max-threads", "Maximum decode threads",
398               "Maximum number of worker threads to spawn. (0 = auto)",
399               0, G_MAXINT, DEFAULT_MAX_THREADS,
400               G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
401     }
402   }
403
404   gstelement_class->change_state = gst_ffmpegdec_change_state;
405 }
406
407 static void
408 gst_ffmpegdec_init (GstFFMpegDec * ffmpegdec)
409 {
410   GstFFMpegDecClass *oclass;
411
412   oclass = (GstFFMpegDecClass *) (G_OBJECT_GET_CLASS (ffmpegdec));
413
414   /* setup pads */
415   ffmpegdec->sinkpad = gst_pad_new_from_template (oclass->sinktempl, "sink");
416   gst_pad_set_setcaps_function (ffmpegdec->sinkpad,
417       GST_DEBUG_FUNCPTR (gst_ffmpegdec_setcaps));
418   gst_pad_set_event_function (ffmpegdec->sinkpad,
419       GST_DEBUG_FUNCPTR (gst_ffmpegdec_sink_event));
420   gst_pad_set_chain_function (ffmpegdec->sinkpad,
421       GST_DEBUG_FUNCPTR (gst_ffmpegdec_chain));
422   gst_element_add_pad (GST_ELEMENT (ffmpegdec), ffmpegdec->sinkpad);
423
424   ffmpegdec->srcpad = gst_pad_new_from_template (oclass->srctempl, "src");
425   gst_pad_use_fixed_caps (ffmpegdec->srcpad);
426   gst_pad_set_event_function (ffmpegdec->srcpad,
427       GST_DEBUG_FUNCPTR (gst_ffmpegdec_src_event));
428   gst_pad_set_query_function (ffmpegdec->srcpad,
429       GST_DEBUG_FUNCPTR (gst_ffmpegdec_query));
430   gst_element_add_pad (GST_ELEMENT (ffmpegdec), ffmpegdec->srcpad);
431
432   /* some ffmpeg data */
433   ffmpegdec->context = avcodec_alloc_context ();
434   ffmpegdec->picture = avcodec_alloc_frame ();
435   ffmpegdec->pctx = NULL;
436   ffmpegdec->pcache = NULL;
437   ffmpegdec->par = NULL;
438   ffmpegdec->opened = FALSE;
439   ffmpegdec->waiting_for_key = TRUE;
440   ffmpegdec->skip_frame = ffmpegdec->lowres = 0;
441   ffmpegdec->direct_rendering = DEFAULT_DIRECT_RENDERING;
442   ffmpegdec->do_padding = DEFAULT_DO_PADDING;
443   ffmpegdec->debug_mv = DEFAULT_DEBUG_MV;
444   ffmpegdec->crop = DEFAULT_CROP;
445   ffmpegdec->max_threads = DEFAULT_MAX_THREADS;
446
447   ffmpegdec->format.video.par_n = -1;
448   ffmpegdec->format.video.fps_n = -1;
449   ffmpegdec->format.video.old_fps_n = -1;
450   gst_segment_init (&ffmpegdec->segment, GST_FORMAT_TIME);
451
452   /* We initially assume downstream can allocate 16 bytes aligned buffers */
453   ffmpegdec->can_allocate_aligned = TRUE;
454 }
455
456 static void
457 gst_ffmpegdec_finalize (GObject * object)
458 {
459   GstFFMpegDec *ffmpegdec = (GstFFMpegDec *) object;
460
461   if (ffmpegdec->context != NULL) {
462     av_free (ffmpegdec->context);
463     ffmpegdec->context = NULL;
464   }
465
466   if (ffmpegdec->picture != NULL) {
467     av_free (ffmpegdec->picture);
468     ffmpegdec->picture = NULL;
469   }
470
471   G_OBJECT_CLASS (parent_class)->finalize (object);
472 }
473
474 static gboolean
475 gst_ffmpegdec_query (GstPad * pad, GstQuery * query)
476 {
477   GstFFMpegDec *ffmpegdec;
478   GstPad *peer;
479   gboolean res;
480
481   ffmpegdec = (GstFFMpegDec *) gst_pad_get_parent (pad);
482
483   res = FALSE;
484
485   if ((peer = gst_pad_get_peer (ffmpegdec->sinkpad))) {
486     /* just forward to peer */
487     res = gst_pad_query (peer, query);
488     gst_object_unref (peer);
489   }
490 #if 0
491   {
492     GstFormat bfmt;
493
494     bfmt = GST_FORMAT_BYTES;
495
496     /* ok, do bitrate calc... */
497     if ((type != GST_QUERY_POSITION && type != GST_QUERY_TOTAL) ||
498         *fmt != GST_FORMAT_TIME || ffmpegdec->context->bit_rate == 0 ||
499         !gst_pad_query (peer, type, &bfmt, value))
500       return FALSE;
501
502     if (ffmpegdec->pcache && type == GST_QUERY_POSITION)
503       *value -= GST_BUFFER_SIZE (ffmpegdec->pcache);
504     *value *= GST_SECOND / ffmpegdec->context->bit_rate;
505   }
506 #endif
507
508   gst_object_unref (ffmpegdec);
509
510   return res;
511 }
512
513 static void
514 gst_ffmpegdec_reset_ts (GstFFMpegDec * ffmpegdec)
515 {
516   ffmpegdec->last_in = GST_CLOCK_TIME_NONE;
517   ffmpegdec->last_diff = GST_CLOCK_TIME_NONE;
518   ffmpegdec->last_frames = 0;
519   ffmpegdec->last_out = GST_CLOCK_TIME_NONE;
520   ffmpegdec->next_out = GST_CLOCK_TIME_NONE;
521   ffmpegdec->reordered_in = FALSE;
522   ffmpegdec->reordered_out = FALSE;
523 }
524
525 static void
526 gst_ffmpegdec_update_qos (GstFFMpegDec * ffmpegdec, gdouble proportion,
527     GstClockTime timestamp)
528 {
529   GST_LOG_OBJECT (ffmpegdec, "update QOS: %f, %" GST_TIME_FORMAT,
530       proportion, GST_TIME_ARGS (timestamp));
531
532   GST_OBJECT_LOCK (ffmpegdec);
533   ffmpegdec->proportion = proportion;
534   ffmpegdec->earliest_time = timestamp;
535   GST_OBJECT_UNLOCK (ffmpegdec);
536 }
537
538 static void
539 gst_ffmpegdec_reset_qos (GstFFMpegDec * ffmpegdec)
540 {
541   gst_ffmpegdec_update_qos (ffmpegdec, 0.5, GST_CLOCK_TIME_NONE);
542 }
543
544 static void
545 gst_ffmpegdec_read_qos (GstFFMpegDec * ffmpegdec, gdouble * proportion,
546     GstClockTime * timestamp)
547 {
548   GST_OBJECT_LOCK (ffmpegdec);
549   *proportion = ffmpegdec->proportion;
550   *timestamp = ffmpegdec->earliest_time;
551   GST_OBJECT_UNLOCK (ffmpegdec);
552 }
553
554 static gboolean
555 gst_ffmpegdec_src_event (GstPad * pad, GstEvent * event)
556 {
557   GstFFMpegDec *ffmpegdec;
558   gboolean res;
559
560   ffmpegdec = (GstFFMpegDec *) gst_pad_get_parent (pad);
561
562   switch (GST_EVENT_TYPE (event)) {
563     case GST_EVENT_QOS:
564     {
565       gdouble proportion;
566       GstClockTimeDiff diff;
567       GstClockTime timestamp;
568
569       gst_event_parse_qos (event, &proportion, &diff, &timestamp);
570
571       /* update our QoS values */
572       gst_ffmpegdec_update_qos (ffmpegdec, proportion, timestamp + diff);
573
574       /* forward upstream */
575       res = gst_pad_push_event (ffmpegdec->sinkpad, event);
576       break;
577     }
578     default:
579       /* forward upstream */
580       res = gst_pad_push_event (ffmpegdec->sinkpad, event);
581       break;
582   }
583
584   gst_object_unref (ffmpegdec);
585
586   return res;
587 }
588
589 /* with LOCK */
590 static void
591 gst_ffmpegdec_close (GstFFMpegDec * ffmpegdec)
592 {
593   if (!ffmpegdec->opened)
594     return;
595
596   GST_LOG_OBJECT (ffmpegdec, "closing ffmpeg codec");
597
598   if (ffmpegdec->par) {
599     g_free (ffmpegdec->par);
600     ffmpegdec->par = NULL;
601   }
602
603   if (ffmpegdec->context->priv_data)
604     gst_ffmpeg_avcodec_close (ffmpegdec->context);
605   ffmpegdec->opened = FALSE;
606
607   if (ffmpegdec->context->palctrl) {
608     av_free (ffmpegdec->context->palctrl);
609     ffmpegdec->context->palctrl = NULL;
610   }
611
612   if (ffmpegdec->context->extradata) {
613     av_free (ffmpegdec->context->extradata);
614     ffmpegdec->context->extradata = NULL;
615   }
616
617   if (ffmpegdec->pctx) {
618     if (ffmpegdec->pcache) {
619       gst_buffer_unref (ffmpegdec->pcache);
620       ffmpegdec->pcache = NULL;
621     }
622     av_parser_close (ffmpegdec->pctx);
623     ffmpegdec->pctx = NULL;
624   }
625
626   ffmpegdec->format.video.par_n = -1;
627   ffmpegdec->format.video.fps_n = -1;
628   ffmpegdec->format.video.old_fps_n = -1;
629   ffmpegdec->format.video.interlaced = FALSE;
630 }
631
632 /* with LOCK */
633 static gboolean
634 gst_ffmpegdec_open (GstFFMpegDec * ffmpegdec)
635 {
636   GstFFMpegDecClass *oclass;
637
638   oclass = (GstFFMpegDecClass *) (G_OBJECT_GET_CLASS (ffmpegdec));
639
640   if (gst_ffmpeg_avcodec_open (ffmpegdec->context, oclass->in_plugin) < 0)
641     goto could_not_open;
642
643   ffmpegdec->opened = TRUE;
644   ffmpegdec->is_realvideo = FALSE;
645
646   GST_LOG_OBJECT (ffmpegdec, "Opened ffmpeg codec %s, id %d",
647       oclass->in_plugin->name, oclass->in_plugin->id);
648
649   /* open a parser if we can */
650   switch (oclass->in_plugin->id) {
651     case CODEC_ID_MPEG4:
652     case CODEC_ID_MJPEG:
653     case CODEC_ID_VC1:
654       GST_LOG_OBJECT (ffmpegdec, "not using parser, blacklisted codec");
655       ffmpegdec->pctx = NULL;
656       break;
657     case CODEC_ID_H264:
658       /* For H264, only use a parser if there is no context data, if there is, 
659        * we're talking AVC */
660       if (ffmpegdec->context->extradata_size == 0) {
661         GST_LOG_OBJECT (ffmpegdec, "H264 with no extradata, creating parser");
662         ffmpegdec->pctx = av_parser_init (oclass->in_plugin->id);
663       } else {
664         GST_LOG_OBJECT (ffmpegdec,
665             "H264 with extradata implies framed data - not using parser");
666         ffmpegdec->pctx = NULL;
667       }
668       break;
669     case CODEC_ID_RV10:
670     case CODEC_ID_RV30:
671     case CODEC_ID_RV20:
672     case CODEC_ID_RV40:
673       ffmpegdec->is_realvideo = TRUE;
674       break;
675     default:
676       if (!ffmpegdec->turnoff_parser) {
677         ffmpegdec->pctx = av_parser_init (oclass->in_plugin->id);
678         if (ffmpegdec->pctx)
679           GST_LOG_OBJECT (ffmpegdec, "Using parser %p", ffmpegdec->pctx);
680         else
681           GST_LOG_OBJECT (ffmpegdec, "No parser for codec");
682       } else {
683         GST_LOG_OBJECT (ffmpegdec, "Parser deactivated for format");
684       }
685       break;
686   }
687
688   switch (oclass->in_plugin->type) {
689     case AVMEDIA_TYPE_VIDEO:
690       ffmpegdec->format.video.width = 0;
691       ffmpegdec->format.video.height = 0;
692       ffmpegdec->format.video.clip_width = -1;
693       ffmpegdec->format.video.clip_height = -1;
694       ffmpegdec->format.video.pix_fmt = PIX_FMT_NB;
695       ffmpegdec->format.video.interlaced = FALSE;
696       break;
697     case AVMEDIA_TYPE_AUDIO:
698       ffmpegdec->format.audio.samplerate = 0;
699       ffmpegdec->format.audio.channels = 0;
700       ffmpegdec->format.audio.depth = 0;
701       break;
702     default:
703       break;
704   }
705
706   gst_ffmpegdec_reset_ts (ffmpegdec);
707   /* FIXME, reset_qos holds the LOCK */
708   ffmpegdec->proportion = 0.0;
709   ffmpegdec->earliest_time = -1;
710
711   return TRUE;
712
713   /* ERRORS */
714 could_not_open:
715   {
716     gst_ffmpegdec_close (ffmpegdec);
717     GST_DEBUG_OBJECT (ffmpegdec, "ffdec_%s: Failed to open FFMPEG codec",
718         oclass->in_plugin->name);
719     return FALSE;
720   }
721 }
722
723 static gboolean
724 gst_ffmpegdec_setcaps (GstPad * pad, GstCaps * caps)
725 {
726   GstFFMpegDec *ffmpegdec;
727   GstFFMpegDecClass *oclass;
728   GstStructure *structure;
729   const GValue *par;
730   const GValue *fps;
731   gboolean ret = TRUE;
732
733   ffmpegdec = (GstFFMpegDec *) (gst_pad_get_parent (pad));
734   oclass = (GstFFMpegDecClass *) (G_OBJECT_GET_CLASS (ffmpegdec));
735
736   GST_DEBUG_OBJECT (pad, "setcaps called");
737
738   GST_OBJECT_LOCK (ffmpegdec);
739
740   /* stupid check for VC1 */
741   if ((oclass->in_plugin->id == CODEC_ID_WMV3) ||
742       (oclass->in_plugin->id == CODEC_ID_VC1))
743     oclass->in_plugin->id = gst_ffmpeg_caps_to_codecid (caps, NULL);
744
745   /* close old session */
746   if (ffmpegdec->opened) {
747     GST_OBJECT_UNLOCK (ffmpegdec);
748     gst_ffmpegdec_drain (ffmpegdec);
749     GST_OBJECT_LOCK (ffmpegdec);
750     gst_ffmpegdec_close (ffmpegdec);
751
752     /* and reset the defaults that were set when a context is created */
753     avcodec_get_context_defaults (ffmpegdec->context);
754   }
755
756   /* set buffer functions */
757   ffmpegdec->context->get_buffer = gst_ffmpegdec_get_buffer;
758   ffmpegdec->context->release_buffer = gst_ffmpegdec_release_buffer;
759   ffmpegdec->context->draw_horiz_band = NULL;
760
761   /* default is to let format decide if it needs a parser */
762   ffmpegdec->turnoff_parser = FALSE;
763
764   ffmpegdec->has_b_frames = FALSE;
765
766   GST_LOG_OBJECT (ffmpegdec, "size %dx%d", ffmpegdec->context->width,
767       ffmpegdec->context->height);
768
769   /* get size and so */
770   gst_ffmpeg_caps_with_codecid (oclass->in_plugin->id,
771       oclass->in_plugin->type, caps, ffmpegdec->context);
772
773   GST_LOG_OBJECT (ffmpegdec, "size after %dx%d", ffmpegdec->context->width,
774       ffmpegdec->context->height);
775
776   if (!ffmpegdec->context->time_base.den || !ffmpegdec->context->time_base.num) {
777     GST_DEBUG_OBJECT (ffmpegdec, "forcing 25/1 framerate");
778     ffmpegdec->context->time_base.num = 1;
779     ffmpegdec->context->time_base.den = 25;
780   }
781
782   /* get pixel aspect ratio if it's set */
783   structure = gst_caps_get_structure (caps, 0);
784
785   par = gst_structure_get_value (structure, "pixel-aspect-ratio");
786   if (par) {
787     GST_DEBUG_OBJECT (ffmpegdec, "sink caps have pixel-aspect-ratio of %d:%d",
788         gst_value_get_fraction_numerator (par),
789         gst_value_get_fraction_denominator (par));
790     /* should be NULL */
791     if (ffmpegdec->par)
792       g_free (ffmpegdec->par);
793     ffmpegdec->par = g_new0 (GValue, 1);
794     gst_value_init_and_copy (ffmpegdec->par, par);
795   }
796
797   /* get the framerate from incoming caps. fps_n is set to -1 when
798    * there is no valid framerate */
799   fps = gst_structure_get_value (structure, "framerate");
800   if (fps != NULL && GST_VALUE_HOLDS_FRACTION (fps)) {
801     ffmpegdec->format.video.fps_n = gst_value_get_fraction_numerator (fps);
802     ffmpegdec->format.video.fps_d = gst_value_get_fraction_denominator (fps);
803     GST_DEBUG_OBJECT (ffmpegdec, "Using framerate %d/%d from incoming caps",
804         ffmpegdec->format.video.fps_n, ffmpegdec->format.video.fps_d);
805   } else {
806     ffmpegdec->format.video.fps_n = -1;
807     GST_DEBUG_OBJECT (ffmpegdec, "Using framerate from codec");
808   }
809
810   /* figure out if we can use direct rendering */
811   ffmpegdec->current_dr = FALSE;
812   ffmpegdec->extra_ref = FALSE;
813   if (ffmpegdec->direct_rendering) {
814     GST_DEBUG_OBJECT (ffmpegdec, "trying to enable direct rendering");
815     if (oclass->in_plugin->capabilities & CODEC_CAP_DR1) {
816       if (oclass->in_plugin->id == CODEC_ID_H264) {
817         GST_DEBUG_OBJECT (ffmpegdec, "disable direct rendering setup for H264");
818         /* does not work, many stuff reads outside of the planes */
819         ffmpegdec->current_dr = FALSE;
820         ffmpegdec->extra_ref = TRUE;
821       } else if ((oclass->in_plugin->id == CODEC_ID_SVQ1) ||
822           (oclass->in_plugin->id == CODEC_ID_VP5) ||
823           (oclass->in_plugin->id == CODEC_ID_VP6) ||
824           (oclass->in_plugin->id == CODEC_ID_VP6F) ||
825           (oclass->in_plugin->id == CODEC_ID_VP6A)) {
826         GST_DEBUG_OBJECT (ffmpegdec,
827             "disable direct rendering setup for broken stride support");
828         /* does not work, uses a incompatible stride. See #610613 */
829         ffmpegdec->current_dr = FALSE;
830         ffmpegdec->extra_ref = TRUE;
831       } else {
832         GST_DEBUG_OBJECT (ffmpegdec, "enabled direct rendering");
833         ffmpegdec->current_dr = TRUE;
834       }
835     } else {
836       GST_DEBUG_OBJECT (ffmpegdec, "direct rendering not supported");
837     }
838   }
839   if (ffmpegdec->current_dr) {
840     /* do *not* draw edges when in direct rendering, for some reason it draws
841      * outside of the memory. */
842     ffmpegdec->context->flags |= CODEC_FLAG_EMU_EDGE;
843   }
844
845   /* for AAC we only use av_parse if not on stream-format==raw or ==loas */
846   if (oclass->in_plugin->id == CODEC_ID_AAC
847       || oclass->in_plugin->id == CODEC_ID_AAC_LATM) {
848     const gchar *format = gst_structure_get_string (structure, "stream-format");
849
850     if (format == NULL || strcmp (format, "raw") == 0) {
851       ffmpegdec->turnoff_parser = TRUE;
852     }
853   }
854
855   /* workaround encoder bugs */
856   ffmpegdec->context->workaround_bugs |= FF_BUG_AUTODETECT;
857   ffmpegdec->context->error_recognition = 1;
858
859   /* for slow cpus */
860   ffmpegdec->context->lowres = ffmpegdec->lowres;
861   ffmpegdec->context->skip_frame = ffmpegdec->skip_frame;
862
863   /* ffmpeg can draw motion vectors on top of the image (not every decoder
864    * supports it) */
865   ffmpegdec->context->debug_mv = ffmpegdec->debug_mv;
866
867   if (ffmpegdec->max_threads == 0)
868     ffmpegdec->context->thread_count = gst_ffmpeg_auto_max_threads ();
869   else
870     ffmpegdec->context->thread_count = ffmpegdec->max_threads;
871
872   /* open codec - we don't select an output pix_fmt yet,
873    * simply because we don't know! We only get it
874    * during playback... */
875   if (!gst_ffmpegdec_open (ffmpegdec))
876     goto open_failed;
877
878   /* clipping region */
879   gst_structure_get_int (structure, "width",
880       &ffmpegdec->format.video.clip_width);
881   gst_structure_get_int (structure, "height",
882       &ffmpegdec->format.video.clip_height);
883
884   GST_DEBUG_OBJECT (pad, "clipping to %dx%d",
885       ffmpegdec->format.video.clip_width, ffmpegdec->format.video.clip_height);
886
887   /* take into account the lowres property */
888   if (ffmpegdec->format.video.clip_width != -1)
889     ffmpegdec->format.video.clip_width >>= ffmpegdec->lowres;
890   if (ffmpegdec->format.video.clip_height != -1)
891     ffmpegdec->format.video.clip_height >>= ffmpegdec->lowres;
892
893   GST_DEBUG_OBJECT (pad, "final clipping to %dx%d",
894       ffmpegdec->format.video.clip_width, ffmpegdec->format.video.clip_height);
895
896 done:
897   GST_OBJECT_UNLOCK (ffmpegdec);
898
899   gst_object_unref (ffmpegdec);
900
901   return ret;
902
903   /* ERRORS */
904 open_failed:
905   {
906     GST_DEBUG_OBJECT (ffmpegdec, "Failed to open");
907     if (ffmpegdec->par) {
908       g_free (ffmpegdec->par);
909       ffmpegdec->par = NULL;
910     }
911     ret = FALSE;
912     goto done;
913   }
914 }
915
916 static GstFlowReturn
917 alloc_output_buffer (GstFFMpegDec * ffmpegdec, GstBuffer ** outbuf,
918     gint width, gint height)
919 {
920   GstFlowReturn ret;
921   gint fsize;
922
923   ret = GST_FLOW_ERROR;
924   *outbuf = NULL;
925
926   GST_LOG_OBJECT (ffmpegdec, "alloc output buffer");
927
928   /* see if we need renegotiation */
929   if (G_UNLIKELY (!gst_ffmpegdec_negotiate (ffmpegdec, FALSE)))
930     goto negotiate_failed;
931
932   /* get the size of the gstreamer output buffer given a
933    * width/height/format */
934   fsize = gst_ffmpeg_avpicture_get_size (ffmpegdec->context->pix_fmt,
935       width, height);
936
937   if (!ffmpegdec->context->palctrl && ffmpegdec->can_allocate_aligned) {
938     GST_LOG_OBJECT (ffmpegdec, "calling pad_alloc");
939     /* no pallete, we can use the buffer size to alloc */
940     ret = gst_pad_alloc_buffer_and_set_caps (ffmpegdec->srcpad,
941         GST_BUFFER_OFFSET_NONE, fsize,
942         GST_PAD_CAPS (ffmpegdec->srcpad), outbuf);
943     if (G_UNLIKELY (ret != GST_FLOW_OK))
944       goto alloc_failed;
945
946     /* If buffer isn't 128-bit aligned, create a memaligned one ourselves */
947     if (((uintptr_t) GST_BUFFER_DATA (*outbuf)) % 16) {
948       GST_DEBUG_OBJECT (ffmpegdec,
949           "Downstream can't allocate aligned buffers.");
950       ffmpegdec->can_allocate_aligned = FALSE;
951       gst_buffer_unref (*outbuf);
952       *outbuf = new_aligned_buffer (fsize, GST_PAD_CAPS (ffmpegdec->srcpad));
953     }
954   } else {
955     GST_LOG_OBJECT (ffmpegdec,
956         "not calling pad_alloc, we have a pallete or downstream can't give 16 byte aligned buffers.");
957     /* for paletted data we can't use pad_alloc_buffer(), because
958      * fsize contains the size of the palette, so the overall size
959      * is bigger than ffmpegcolorspace's unit size, which will
960      * prompt GstBaseTransform to complain endlessly ... */
961     *outbuf = new_aligned_buffer (fsize, GST_PAD_CAPS (ffmpegdec->srcpad));
962     ret = GST_FLOW_OK;
963   }
964   /* set caps, we do this here because the buffer is still writable here and we
965    * are sure to be negotiated */
966   gst_buffer_set_caps (*outbuf, GST_PAD_CAPS (ffmpegdec->srcpad));
967
968   return ret;
969
970   /* special cases */
971 negotiate_failed:
972   {
973     GST_DEBUG_OBJECT (ffmpegdec, "negotiate failed");
974     return GST_FLOW_NOT_NEGOTIATED;
975   }
976 alloc_failed:
977   {
978     GST_DEBUG_OBJECT (ffmpegdec, "pad_alloc failed %d (%s)", ret,
979         gst_flow_get_name (ret));
980     return ret;
981   }
982 }
983
984 static int
985 gst_ffmpegdec_get_buffer (AVCodecContext * context, AVFrame * picture)
986 {
987   GstBuffer *buf = NULL;
988   GstFFMpegDec *ffmpegdec;
989   gint width, height;
990   gint coded_width, coded_height;
991   gint res;
992
993   ffmpegdec = (GstFFMpegDec *) context->opaque;
994
995   GST_DEBUG_OBJECT (ffmpegdec, "getting buffer");
996
997   /* apply the last info we have seen to this picture, when we get the
998    * picture back from ffmpeg we can use this to correctly timestamp the output
999    * buffer */
1000   picture->reordered_opaque = context->reordered_opaque;
1001   /* make sure we don't free the buffer when it's not ours */
1002   picture->opaque = NULL;
1003
1004   /* take width and height before clipping */
1005   width = context->width;
1006   height = context->height;
1007   coded_width = context->coded_width;
1008   coded_height = context->coded_height;
1009
1010   GST_LOG_OBJECT (ffmpegdec, "dimension %dx%d, coded %dx%d", width, height,
1011       coded_width, coded_height);
1012   if (!ffmpegdec->current_dr) {
1013     GST_LOG_OBJECT (ffmpegdec, "direct rendering disabled, fallback alloc");
1014     res = avcodec_default_get_buffer (context, picture);
1015
1016     GST_LOG_OBJECT (ffmpegdec, "linsize %d %d %d", picture->linesize[0],
1017         picture->linesize[1], picture->linesize[2]);
1018     GST_LOG_OBJECT (ffmpegdec, "data %u %u %u", 0,
1019         (guint) (picture->data[1] - picture->data[0]),
1020         (guint) (picture->data[2] - picture->data[0]));
1021     return res;
1022   }
1023
1024   switch (context->codec_type) {
1025     case AVMEDIA_TYPE_VIDEO:
1026       /* some ffmpeg video plugins don't see the point in setting codec_type ... */
1027     case AVMEDIA_TYPE_UNKNOWN:
1028     {
1029       GstFlowReturn ret;
1030       gint clip_width, clip_height;
1031
1032       /* take final clipped output size */
1033       if ((clip_width = ffmpegdec->format.video.clip_width) == -1)
1034         clip_width = width;
1035       if ((clip_height = ffmpegdec->format.video.clip_height) == -1)
1036         clip_height = height;
1037
1038       GST_LOG_OBJECT (ffmpegdec, "raw outsize %d/%d", width, height);
1039
1040       /* this is the size ffmpeg needs for the buffer */
1041       avcodec_align_dimensions (context, &width, &height);
1042
1043       GST_LOG_OBJECT (ffmpegdec, "aligned outsize %d/%d, clip %d/%d",
1044           width, height, clip_width, clip_height);
1045
1046       if (width != clip_width || height != clip_height) {
1047         /* We can't alloc if we need to clip the output buffer later */
1048         GST_LOG_OBJECT (ffmpegdec, "we need clipping, fallback alloc");
1049         return avcodec_default_get_buffer (context, picture);
1050       }
1051
1052       /* alloc with aligned dimensions for ffmpeg */
1053       ret = alloc_output_buffer (ffmpegdec, &buf, width, height);
1054       if (G_UNLIKELY (ret != GST_FLOW_OK)) {
1055         /* alloc default buffer when we can't get one from downstream */
1056         GST_LOG_OBJECT (ffmpegdec, "alloc failed, fallback alloc");
1057         return avcodec_default_get_buffer (context, picture);
1058       }
1059
1060       /* copy the right pointers and strides in the picture object */
1061       gst_ffmpeg_avpicture_fill ((AVPicture *) picture,
1062           GST_BUFFER_DATA (buf), context->pix_fmt, width, height);
1063       break;
1064     }
1065     case AVMEDIA_TYPE_AUDIO:
1066     default:
1067       GST_ERROR_OBJECT (ffmpegdec,
1068           "_get_buffer() should never get called for non-video buffers !");
1069       g_assert_not_reached ();
1070       break;
1071   }
1072
1073   /* tell ffmpeg we own this buffer, tranfer the ref we have on the buffer to
1074    * the opaque data. */
1075   picture->type = FF_BUFFER_TYPE_USER;
1076   picture->age = 256 * 256 * 256 * 64;
1077   picture->opaque = buf;
1078
1079 #ifdef EXTRA_REF
1080   if (picture->reference != 0 || ffmpegdec->extra_ref) {
1081     GST_DEBUG_OBJECT (ffmpegdec, "adding extra ref");
1082     gst_buffer_ref (buf);
1083   }
1084 #endif
1085
1086   GST_LOG_OBJECT (ffmpegdec, "returned buffer %p", buf);
1087
1088   return 0;
1089 }
1090
1091 static void
1092 gst_ffmpegdec_release_buffer (AVCodecContext * context, AVFrame * picture)
1093 {
1094   gint i;
1095   GstBuffer *buf;
1096   GstFFMpegDec *ffmpegdec;
1097
1098   ffmpegdec = (GstFFMpegDec *) context->opaque;
1099
1100   /* check if it was our buffer */
1101   if (picture->opaque == NULL) {
1102     GST_DEBUG_OBJECT (ffmpegdec, "default release buffer");
1103     avcodec_default_release_buffer (context, picture);
1104     return;
1105   }
1106
1107   /* we remove the opaque data now */
1108   buf = GST_BUFFER_CAST (picture->opaque);
1109   GST_DEBUG_OBJECT (ffmpegdec, "release buffer %p", buf);
1110   picture->opaque = NULL;
1111
1112 #ifdef EXTRA_REF
1113   if (picture->reference != 0 || ffmpegdec->extra_ref) {
1114     GST_DEBUG_OBJECT (ffmpegdec, "remove extra ref");
1115     gst_buffer_unref (buf);
1116   }
1117 #else
1118   gst_buffer_unref (buf);
1119 #endif
1120
1121   /* zero out the reference in ffmpeg */
1122   for (i = 0; i < 4; i++) {
1123     picture->data[i] = NULL;
1124     picture->linesize[i] = 0;
1125   }
1126 }
1127
1128 static void
1129 gst_ffmpegdec_add_pixel_aspect_ratio (GstFFMpegDec * ffmpegdec,
1130     GstStructure * s)
1131 {
1132   gboolean demuxer_par_set = FALSE;
1133   gboolean decoder_par_set = FALSE;
1134   gint demuxer_num = 1, demuxer_denom = 1;
1135   gint decoder_num = 1, decoder_denom = 1;
1136
1137   GST_OBJECT_LOCK (ffmpegdec);
1138
1139   if (ffmpegdec->par) {
1140     demuxer_num = gst_value_get_fraction_numerator (ffmpegdec->par);
1141     demuxer_denom = gst_value_get_fraction_denominator (ffmpegdec->par);
1142     demuxer_par_set = TRUE;
1143     GST_DEBUG_OBJECT (ffmpegdec, "Demuxer PAR: %d:%d", demuxer_num,
1144         demuxer_denom);
1145   }
1146
1147   if (ffmpegdec->context->sample_aspect_ratio.num &&
1148       ffmpegdec->context->sample_aspect_ratio.den) {
1149     decoder_num = ffmpegdec->context->sample_aspect_ratio.num;
1150     decoder_denom = ffmpegdec->context->sample_aspect_ratio.den;
1151     decoder_par_set = TRUE;
1152     GST_DEBUG_OBJECT (ffmpegdec, "Decoder PAR: %d:%d", decoder_num,
1153         decoder_denom);
1154   }
1155
1156   GST_OBJECT_UNLOCK (ffmpegdec);
1157
1158   if (!demuxer_par_set && !decoder_par_set)
1159     goto no_par;
1160
1161   if (demuxer_par_set && !decoder_par_set)
1162     goto use_demuxer_par;
1163
1164   if (decoder_par_set && !demuxer_par_set)
1165     goto use_decoder_par;
1166
1167   /* Both the demuxer and the decoder provide a PAR. If one of
1168    * the two PARs is 1:1 and the other one is not, use the one
1169    * that is not 1:1. */
1170   if (demuxer_num == demuxer_denom && decoder_num != decoder_denom)
1171     goto use_decoder_par;
1172
1173   if (decoder_num == decoder_denom && demuxer_num != demuxer_denom)
1174     goto use_demuxer_par;
1175
1176   /* Both PARs are non-1:1, so use the PAR provided by the demuxer */
1177   goto use_demuxer_par;
1178
1179 use_decoder_par:
1180   {
1181     GST_DEBUG_OBJECT (ffmpegdec,
1182         "Setting decoder provided pixel-aspect-ratio of %u:%u", decoder_num,
1183         decoder_denom);
1184     gst_structure_set (s, "pixel-aspect-ratio", GST_TYPE_FRACTION, decoder_num,
1185         decoder_denom, NULL);
1186     return;
1187   }
1188
1189 use_demuxer_par:
1190   {
1191     GST_DEBUG_OBJECT (ffmpegdec,
1192         "Setting demuxer provided pixel-aspect-ratio of %u:%u", demuxer_num,
1193         demuxer_denom);
1194     gst_structure_set (s, "pixel-aspect-ratio", GST_TYPE_FRACTION, demuxer_num,
1195         demuxer_denom, NULL);
1196     return;
1197   }
1198 no_par:
1199   {
1200     GST_DEBUG_OBJECT (ffmpegdec,
1201         "Neither demuxer nor codec provide a pixel-aspect-ratio");
1202     return;
1203   }
1204 }
1205
1206 static gboolean
1207 gst_ffmpegdec_negotiate (GstFFMpegDec * ffmpegdec, gboolean force)
1208 {
1209   GstFFMpegDecClass *oclass;
1210   GstCaps *caps;
1211
1212   oclass = (GstFFMpegDecClass *) (G_OBJECT_GET_CLASS (ffmpegdec));
1213
1214   switch (oclass->in_plugin->type) {
1215     case AVMEDIA_TYPE_VIDEO:
1216       if (!force && ffmpegdec->format.video.width == ffmpegdec->context->width
1217           && ffmpegdec->format.video.height == ffmpegdec->context->height
1218           && ffmpegdec->format.video.fps_n == ffmpegdec->format.video.old_fps_n
1219           && ffmpegdec->format.video.fps_d == ffmpegdec->format.video.old_fps_d
1220           && ffmpegdec->format.video.pix_fmt == ffmpegdec->context->pix_fmt
1221           && ffmpegdec->format.video.par_n ==
1222           ffmpegdec->context->sample_aspect_ratio.num
1223           && ffmpegdec->format.video.par_d ==
1224           ffmpegdec->context->sample_aspect_ratio.den)
1225         return TRUE;
1226       GST_DEBUG_OBJECT (ffmpegdec,
1227           "Renegotiating video from %dx%d@ %d:%d PAR %d/%d fps to %dx%d@ %d:%d PAR %d/%d fps",
1228           ffmpegdec->format.video.width, ffmpegdec->format.video.height,
1229           ffmpegdec->format.video.par_n, ffmpegdec->format.video.par_d,
1230           ffmpegdec->format.video.old_fps_n, ffmpegdec->format.video.old_fps_n,
1231           ffmpegdec->context->width, ffmpegdec->context->height,
1232           ffmpegdec->context->sample_aspect_ratio.num,
1233           ffmpegdec->context->sample_aspect_ratio.den,
1234           ffmpegdec->format.video.fps_n, ffmpegdec->format.video.fps_d);
1235       ffmpegdec->format.video.width = ffmpegdec->context->width;
1236       ffmpegdec->format.video.height = ffmpegdec->context->height;
1237       ffmpegdec->format.video.old_fps_n = ffmpegdec->format.video.fps_n;
1238       ffmpegdec->format.video.old_fps_d = ffmpegdec->format.video.fps_d;
1239       ffmpegdec->format.video.pix_fmt = ffmpegdec->context->pix_fmt;
1240       ffmpegdec->format.video.par_n =
1241           ffmpegdec->context->sample_aspect_ratio.num;
1242       ffmpegdec->format.video.par_d =
1243           ffmpegdec->context->sample_aspect_ratio.den;
1244       break;
1245     case AVMEDIA_TYPE_AUDIO:
1246     {
1247       gint depth = av_smp_format_depth (ffmpegdec->context->sample_fmt);
1248       if (!force && ffmpegdec->format.audio.samplerate ==
1249           ffmpegdec->context->sample_rate &&
1250           ffmpegdec->format.audio.channels == ffmpegdec->context->channels &&
1251           ffmpegdec->format.audio.depth == depth)
1252         return TRUE;
1253       GST_DEBUG_OBJECT (ffmpegdec,
1254           "Renegotiating audio from %dHz@%dchannels (%d) to %dHz@%dchannels (%d)",
1255           ffmpegdec->format.audio.samplerate, ffmpegdec->format.audio.channels,
1256           ffmpegdec->format.audio.depth,
1257           ffmpegdec->context->sample_rate, ffmpegdec->context->channels, depth);
1258       ffmpegdec->format.audio.samplerate = ffmpegdec->context->sample_rate;
1259       ffmpegdec->format.audio.channels = ffmpegdec->context->channels;
1260       ffmpegdec->format.audio.depth = depth;
1261     }
1262       break;
1263     default:
1264       break;
1265   }
1266
1267   caps = gst_ffmpeg_codectype_to_caps (oclass->in_plugin->type,
1268       ffmpegdec->context, oclass->in_plugin->id, FALSE);
1269
1270   if (caps == NULL)
1271     goto no_caps;
1272
1273   switch (oclass->in_plugin->type) {
1274     case AVMEDIA_TYPE_VIDEO:
1275     {
1276       gint width, height;
1277       gboolean interlaced;
1278
1279       width = ffmpegdec->format.video.clip_width;
1280       height = ffmpegdec->format.video.clip_height;
1281       interlaced = ffmpegdec->format.video.interlaced;
1282
1283       if (width != -1 && height != -1) {
1284         /* overwrite the output size with the dimension of the
1285          * clipping region but only if they are smaller. */
1286         if (width < ffmpegdec->context->width)
1287           gst_caps_set_simple (caps, "width", G_TYPE_INT, width, NULL);
1288         if (height < ffmpegdec->context->height)
1289           gst_caps_set_simple (caps, "height", G_TYPE_INT, height, NULL);
1290       }
1291       gst_caps_set_simple (caps, "interlaced", G_TYPE_BOOLEAN, interlaced,
1292           NULL);
1293
1294       /* If a demuxer provided a framerate then use it (#313970) */
1295       if (ffmpegdec->format.video.fps_n != -1) {
1296         gst_caps_set_simple (caps, "framerate",
1297             GST_TYPE_FRACTION, ffmpegdec->format.video.fps_n,
1298             ffmpegdec->format.video.fps_d, NULL);
1299       }
1300       gst_ffmpegdec_add_pixel_aspect_ratio (ffmpegdec,
1301           gst_caps_get_structure (caps, 0));
1302       break;
1303     }
1304     case AVMEDIA_TYPE_AUDIO:
1305     {
1306       break;
1307     }
1308     default:
1309       break;
1310   }
1311
1312   if (!gst_pad_set_caps (ffmpegdec->srcpad, caps))
1313     goto caps_failed;
1314
1315   gst_caps_unref (caps);
1316
1317   return TRUE;
1318
1319   /* ERRORS */
1320 no_caps:
1321   {
1322 #ifdef HAVE_FFMPEG_UNINSTALLED
1323     /* using internal ffmpeg snapshot */
1324     GST_ELEMENT_ERROR (ffmpegdec, CORE, NEGOTIATION,
1325         ("Could not find GStreamer caps mapping for FFmpeg codec '%s'.",
1326             oclass->in_plugin->name), (NULL));
1327 #else
1328     /* using external ffmpeg */
1329     GST_ELEMENT_ERROR (ffmpegdec, CORE, NEGOTIATION,
1330         ("Could not find GStreamer caps mapping for FFmpeg codec '%s', and "
1331             "you are using an external libavcodec. This is most likely due to "
1332             "a packaging problem and/or libavcodec having been upgraded to a "
1333             "version that is not compatible with this version of "
1334             "gstreamer-ffmpeg. Make sure your gstreamer-ffmpeg and libavcodec "
1335             "packages come from the same source/repository.",
1336             oclass->in_plugin->name), (NULL));
1337 #endif
1338     return FALSE;
1339   }
1340 caps_failed:
1341   {
1342     GST_ELEMENT_ERROR (ffmpegdec, CORE, NEGOTIATION, (NULL),
1343         ("Could not set caps for ffmpeg decoder (%s), not fixed?",
1344             oclass->in_plugin->name));
1345     gst_caps_unref (caps);
1346
1347     return FALSE;
1348   }
1349 }
1350
1351 /* perform qos calculations before decoding the next frame.
1352  *
1353  * Sets the skip_frame flag and if things are really bad, skips to the next
1354  * keyframe.
1355  * 
1356  * Returns TRUE if the frame should be decoded, FALSE if the frame can be dropped
1357  * entirely.
1358  */
1359 static gboolean
1360 gst_ffmpegdec_do_qos (GstFFMpegDec * ffmpegdec, GstClockTime timestamp,
1361     gboolean * mode_switch)
1362 {
1363   GstClockTimeDiff diff;
1364   gdouble proportion;
1365   GstClockTime qostime, earliest_time;
1366
1367   *mode_switch = FALSE;
1368
1369   /* no timestamp, can't do QoS */
1370   if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (timestamp)))
1371     goto no_qos;
1372
1373   /* get latest QoS observation values */
1374   gst_ffmpegdec_read_qos (ffmpegdec, &proportion, &earliest_time);
1375
1376   /* skip qos if we have no observation (yet) */
1377   if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (earliest_time))) {
1378     /* no skip_frame initialy */
1379     ffmpegdec->context->skip_frame = AVDISCARD_DEFAULT;
1380     goto no_qos;
1381   }
1382
1383   /* qos is done on running time of the timestamp */
1384   qostime = gst_segment_to_running_time (&ffmpegdec->segment, GST_FORMAT_TIME,
1385       timestamp);
1386
1387   /* timestamp can be out of segment, then we don't do QoS */
1388   if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (qostime)))
1389     goto no_qos;
1390
1391   /* see how our next timestamp relates to the latest qos timestamp. negative
1392    * values mean we are early, positive values mean we are too late. */
1393   diff = GST_CLOCK_DIFF (qostime, earliest_time);
1394
1395   GST_DEBUG_OBJECT (ffmpegdec, "QOS: qostime %" GST_TIME_FORMAT
1396       ", earliest %" GST_TIME_FORMAT, GST_TIME_ARGS (qostime),
1397       GST_TIME_ARGS (earliest_time));
1398
1399   /* if we using less than 40% of the available time, we can try to
1400    * speed up again when we were slow. */
1401   if (proportion < 0.4 && diff < 0) {
1402     goto normal_mode;
1403   } else {
1404     if (diff >= 0) {
1405       /* we're too slow, try to speed up */
1406       if (ffmpegdec->waiting_for_key) {
1407         /* we were waiting for a keyframe, that's ok */
1408         goto skipping;
1409       }
1410       /* switch to skip_frame mode */
1411       goto skip_frame;
1412     }
1413   }
1414
1415 no_qos:
1416   return TRUE;
1417
1418 skipping:
1419   {
1420     return FALSE;
1421   }
1422 normal_mode:
1423   {
1424     if (ffmpegdec->context->skip_frame != AVDISCARD_DEFAULT) {
1425       ffmpegdec->context->skip_frame = AVDISCARD_DEFAULT;
1426       *mode_switch = TRUE;
1427       GST_DEBUG_OBJECT (ffmpegdec, "QOS: normal mode %g < 0.4", proportion);
1428     }
1429     return TRUE;
1430   }
1431 skip_frame:
1432   {
1433     if (ffmpegdec->context->skip_frame != AVDISCARD_NONREF) {
1434       ffmpegdec->context->skip_frame = AVDISCARD_NONREF;
1435       *mode_switch = TRUE;
1436       GST_DEBUG_OBJECT (ffmpegdec,
1437           "QOS: hurry up, diff %" G_GINT64_FORMAT " >= 0", diff);
1438     }
1439     return TRUE;
1440   }
1441 }
1442
1443 /* returns TRUE if buffer is within segment, else FALSE.
1444  * if Buffer is on segment border, it's timestamp and duration will be clipped */
1445 static gboolean
1446 clip_video_buffer (GstFFMpegDec * dec, GstBuffer * buf, GstClockTime in_ts,
1447     GstClockTime in_dur)
1448 {
1449   gboolean res = TRUE;
1450   gint64 cstart, cstop;
1451   GstClockTime stop;
1452
1453   GST_LOG_OBJECT (dec,
1454       "timestamp:%" GST_TIME_FORMAT " , duration:%" GST_TIME_FORMAT,
1455       GST_TIME_ARGS (in_ts), GST_TIME_ARGS (in_dur));
1456
1457   /* can't clip without TIME segment */
1458   if (G_UNLIKELY (dec->segment.format != GST_FORMAT_TIME))
1459     goto beach;
1460
1461   /* we need a start time */
1462   if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (in_ts)))
1463     goto beach;
1464
1465   /* generate valid stop, if duration unknown, we have unknown stop */
1466   stop =
1467       GST_CLOCK_TIME_IS_VALID (in_dur) ? (in_ts + in_dur) : GST_CLOCK_TIME_NONE;
1468
1469   /* now clip */
1470   res =
1471       gst_segment_clip (&dec->segment, GST_FORMAT_TIME, in_ts, stop, &cstart,
1472       &cstop);
1473   if (G_UNLIKELY (!res))
1474     goto beach;
1475
1476   /* we're pretty sure the duration of this buffer is not till the end of this
1477    * segment (which _clip will assume when the stop is -1) */
1478   if (stop == GST_CLOCK_TIME_NONE)
1479     cstop = GST_CLOCK_TIME_NONE;
1480
1481   /* update timestamp and possibly duration if the clipped stop time is
1482    * valid */
1483   GST_BUFFER_TIMESTAMP (buf) = cstart;
1484   if (GST_CLOCK_TIME_IS_VALID (cstop))
1485     GST_BUFFER_DURATION (buf) = cstop - cstart;
1486
1487   GST_LOG_OBJECT (dec,
1488       "clipped timestamp:%" GST_TIME_FORMAT " , duration:%" GST_TIME_FORMAT,
1489       GST_TIME_ARGS (cstart), GST_TIME_ARGS (GST_BUFFER_DURATION (buf)));
1490
1491 beach:
1492   GST_LOG_OBJECT (dec, "%sdropping", (res ? "not " : ""));
1493   return res;
1494 }
1495
1496
1497 /* figure out if the current picture is a keyframe, return TRUE if that is
1498  * the case. */
1499 static gboolean
1500 check_keyframe (GstFFMpegDec * ffmpegdec)
1501 {
1502   GstFFMpegDecClass *oclass;
1503   gboolean is_itype = FALSE;
1504   gboolean is_reference = FALSE;
1505   gboolean iskeyframe;
1506
1507   /* figure out if we are dealing with a keyframe */
1508   oclass = (GstFFMpegDecClass *) (G_OBJECT_GET_CLASS (ffmpegdec));
1509
1510   /* remember that we have B frames, we need this for the DTS -> PTS conversion
1511    * code */
1512   if (!ffmpegdec->has_b_frames && ffmpegdec->picture->pict_type == FF_B_TYPE) {
1513     GST_DEBUG_OBJECT (ffmpegdec, "we have B frames");
1514     ffmpegdec->has_b_frames = TRUE;
1515   }
1516
1517   is_itype = (ffmpegdec->picture->pict_type == FF_I_TYPE);
1518   is_reference = (ffmpegdec->picture->reference == 1);
1519
1520   iskeyframe = (is_itype || is_reference || ffmpegdec->picture->key_frame)
1521       || (oclass->in_plugin->id == CODEC_ID_INDEO3)
1522       || (oclass->in_plugin->id == CODEC_ID_MSZH)
1523       || (oclass->in_plugin->id == CODEC_ID_ZLIB)
1524       || (oclass->in_plugin->id == CODEC_ID_VP3)
1525       || (oclass->in_plugin->id == CODEC_ID_HUFFYUV);
1526
1527   GST_LOG_OBJECT (ffmpegdec,
1528       "current picture: type: %d, is_keyframe:%d, is_itype:%d, is_reference:%d",
1529       ffmpegdec->picture->pict_type, iskeyframe, is_itype, is_reference);
1530
1531   return iskeyframe;
1532 }
1533
1534 /* get an outbuf buffer with the current picture */
1535 static GstFlowReturn
1536 get_output_buffer (GstFFMpegDec * ffmpegdec, GstBuffer ** outbuf)
1537 {
1538   GstFlowReturn ret;
1539
1540   ret = GST_FLOW_OK;
1541   *outbuf = NULL;
1542
1543   if (ffmpegdec->picture->opaque != NULL) {
1544     /* we allocated a picture already for ffmpeg to decode into, let's pick it
1545      * up and use it now. */
1546     *outbuf = (GstBuffer *) ffmpegdec->picture->opaque;
1547     GST_LOG_OBJECT (ffmpegdec, "using opaque buffer %p", *outbuf);
1548 #ifndef EXTRA_REF
1549     gst_buffer_ref (*outbuf);
1550 #endif
1551   } else {
1552     AVPicture pic, *outpic;
1553     gint width, height;
1554
1555     GST_LOG_OBJECT (ffmpegdec, "get output buffer");
1556
1557     /* figure out size of output buffer, this is the clipped output size because
1558      * we will copy the picture into it but only when the clipping region is
1559      * smaller than the actual picture size. */
1560     if ((width = ffmpegdec->format.video.clip_width) == -1)
1561       width = ffmpegdec->context->width;
1562     else if (width > ffmpegdec->context->width)
1563       width = ffmpegdec->context->width;
1564
1565     if ((height = ffmpegdec->format.video.clip_height) == -1)
1566       height = ffmpegdec->context->height;
1567     else if (height > ffmpegdec->context->height)
1568       height = ffmpegdec->context->height;
1569
1570     GST_LOG_OBJECT (ffmpegdec, "clip width %d/height %d", width, height);
1571
1572     ret = alloc_output_buffer (ffmpegdec, outbuf, width, height);
1573     if (G_UNLIKELY (ret != GST_FLOW_OK))
1574       goto alloc_failed;
1575
1576     /* original ffmpeg code does not handle odd sizes correctly.
1577      * This patched up version does */
1578     gst_ffmpeg_avpicture_fill (&pic, GST_BUFFER_DATA (*outbuf),
1579         ffmpegdec->context->pix_fmt, width, height);
1580
1581     outpic = (AVPicture *) ffmpegdec->picture;
1582
1583     GST_LOG_OBJECT (ffmpegdec, "linsize %d %d %d", outpic->linesize[0],
1584         outpic->linesize[1], outpic->linesize[2]);
1585     GST_LOG_OBJECT (ffmpegdec, "data %u %u %u", 0,
1586         (guint) (outpic->data[1] - outpic->data[0]),
1587         (guint) (outpic->data[2] - outpic->data[0]));
1588
1589     av_picture_copy (&pic, outpic, ffmpegdec->context->pix_fmt, width, height);
1590   }
1591   ffmpegdec->picture->reordered_opaque = -1;
1592
1593   return ret;
1594
1595   /* special cases */
1596 alloc_failed:
1597   {
1598     GST_DEBUG_OBJECT (ffmpegdec, "pad_alloc failed");
1599     return ret;
1600   }
1601 }
1602
1603 static void
1604 clear_queued (GstFFMpegDec * ffmpegdec)
1605 {
1606   g_list_foreach (ffmpegdec->queued, (GFunc) gst_mini_object_unref, NULL);
1607   g_list_free (ffmpegdec->queued);
1608   ffmpegdec->queued = NULL;
1609 }
1610
1611 static GstFlowReturn
1612 flush_queued (GstFFMpegDec * ffmpegdec)
1613 {
1614   GstFlowReturn res = GST_FLOW_OK;
1615
1616   while (ffmpegdec->queued) {
1617     GstBuffer *buf = GST_BUFFER_CAST (ffmpegdec->queued->data);
1618
1619     GST_LOG_OBJECT (ffmpegdec, "pushing buffer %p, offset %"
1620         G_GUINT64_FORMAT ", timestamp %"
1621         GST_TIME_FORMAT ", duration %" GST_TIME_FORMAT, buf,
1622         GST_BUFFER_OFFSET (buf),
1623         GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)),
1624         GST_TIME_ARGS (GST_BUFFER_DURATION (buf)));
1625
1626     /* iterate ouput queue an push downstream */
1627     res = gst_pad_push (ffmpegdec->srcpad, buf);
1628
1629     ffmpegdec->queued =
1630         g_list_delete_link (ffmpegdec->queued, ffmpegdec->queued);
1631   }
1632   return res;
1633 }
1634
1635 static void
1636 gst_avpacket_init (AVPacket * packet, guint8 * data, guint size)
1637 {
1638   memset (packet, 0, sizeof (AVPacket));
1639   packet->data = data;
1640   packet->size = size;
1641 }
1642
1643 /* gst_ffmpegdec_[video|audio]_frame:
1644  * ffmpegdec:
1645  * data: pointer to the data to decode
1646  * size: size of data in bytes
1647  * in_timestamp: incoming timestamp.
1648  * in_duration: incoming duration.
1649  * in_offset: incoming offset (frame number).
1650  * outbuf: outgoing buffer. Different from NULL ONLY if it contains decoded data.
1651  * ret: Return flow.
1652  *
1653  * Returns: number of bytes used in decoding. The check for successful decode is
1654  *   outbuf being non-NULL.
1655  */
1656 static gint
1657 gst_ffmpegdec_video_frame (GstFFMpegDec * ffmpegdec,
1658     guint8 * data, guint size,
1659     const GstTSInfo * dec_info, GstBuffer ** outbuf, GstFlowReturn * ret)
1660 {
1661   gint len = -1;
1662   gint have_data;
1663   gboolean iskeyframe;
1664   gboolean mode_switch;
1665   gboolean decode;
1666   gint skip_frame = AVDISCARD_DEFAULT;
1667   GstClockTime out_timestamp, out_duration, out_pts;
1668   gint64 out_offset;
1669   const GstTSInfo *out_info;
1670   AVPacket packet;
1671
1672   *ret = GST_FLOW_OK;
1673   *outbuf = NULL;
1674
1675   ffmpegdec->context->opaque = ffmpegdec;
1676
1677   /* in case we skip frames */
1678   ffmpegdec->picture->pict_type = -1;
1679
1680   /* run QoS code, we don't stop decoding the frame when we are late because
1681    * else we might skip a reference frame */
1682   decode = gst_ffmpegdec_do_qos (ffmpegdec, dec_info->timestamp, &mode_switch);
1683
1684   if (ffmpegdec->is_realvideo && data != NULL) {
1685     gint slice_count;
1686     gint i;
1687
1688     /* setup the slice table for realvideo */
1689     if (ffmpegdec->context->slice_offset == NULL)
1690       ffmpegdec->context->slice_offset = g_malloc (sizeof (guint32) * 1000);
1691
1692     slice_count = (*data++) + 1;
1693     ffmpegdec->context->slice_count = slice_count;
1694
1695     for (i = 0; i < slice_count; i++) {
1696       data += 4;
1697       ffmpegdec->context->slice_offset[i] = GST_READ_UINT32_LE (data);
1698       data += 4;
1699     }
1700   }
1701
1702   if (!decode) {
1703     /* no decoding needed, save previous skip_frame value and brutely skip
1704      * decoding everything */
1705     skip_frame = ffmpegdec->context->skip_frame;
1706     ffmpegdec->context->skip_frame = AVDISCARD_NONREF;
1707   }
1708
1709   /* save reference to the timing info */
1710   ffmpegdec->context->reordered_opaque = (gint64) dec_info->idx;
1711   ffmpegdec->picture->reordered_opaque = (gint64) dec_info->idx;
1712
1713   GST_DEBUG_OBJECT (ffmpegdec, "stored opaque values idx %d", dec_info->idx);
1714
1715   /* now decode the frame */
1716   gst_avpacket_init (&packet, data, size);
1717   len = avcodec_decode_video2 (ffmpegdec->context,
1718       ffmpegdec->picture, &have_data, &packet);
1719
1720   /* restore previous state */
1721   if (!decode)
1722     ffmpegdec->context->skip_frame = skip_frame;
1723
1724   GST_DEBUG_OBJECT (ffmpegdec, "after decode: len %d, have_data %d",
1725       len, have_data);
1726
1727   /* when we are in skip_frame mode, don't complain when ffmpeg returned
1728    * no data because we told it to skip stuff. */
1729   if (len < 0 && (mode_switch || ffmpegdec->context->skip_frame))
1730     len = 0;
1731
1732   if (len > 0 && have_data <= 0 && (mode_switch
1733           || ffmpegdec->context->skip_frame)) {
1734     /* we consumed some bytes but nothing decoded and we are skipping frames,
1735      * disable the interpollation of DTS timestamps */
1736     ffmpegdec->last_out = -1;
1737   }
1738
1739   /* no data, we're done */
1740   if (len < 0 || have_data <= 0)
1741     goto beach;
1742
1743   /* get the output picture timing info again */
1744   out_info = gst_ts_info_get (ffmpegdec, ffmpegdec->picture->reordered_opaque);
1745   out_pts = out_info->timestamp;
1746   out_duration = out_info->duration;
1747   out_offset = out_info->offset;
1748
1749   GST_DEBUG_OBJECT (ffmpegdec,
1750       "pts %" G_GUINT64_FORMAT " duration %" G_GUINT64_FORMAT " offset %"
1751       G_GINT64_FORMAT, out_pts, out_duration, out_offset);
1752   GST_DEBUG_OBJECT (ffmpegdec, "picture: pts %" G_GUINT64_FORMAT,
1753       (guint64) ffmpegdec->picture->pts);
1754   GST_DEBUG_OBJECT (ffmpegdec, "picture: num %d",
1755       ffmpegdec->picture->coded_picture_number);
1756   GST_DEBUG_OBJECT (ffmpegdec, "picture: ref %d",
1757       ffmpegdec->picture->reference);
1758   GST_DEBUG_OBJECT (ffmpegdec, "picture: display %d",
1759       ffmpegdec->picture->display_picture_number);
1760   GST_DEBUG_OBJECT (ffmpegdec, "picture: opaque %p",
1761       ffmpegdec->picture->opaque);
1762   GST_DEBUG_OBJECT (ffmpegdec, "picture: reordered opaque %" G_GUINT64_FORMAT,
1763       (guint64) ffmpegdec->picture->reordered_opaque);
1764   GST_DEBUG_OBJECT (ffmpegdec, "repeat_pict:%d",
1765       ffmpegdec->picture->repeat_pict);
1766   GST_DEBUG_OBJECT (ffmpegdec, "interlaced_frame:%d",
1767       ffmpegdec->picture->interlaced_frame);
1768
1769   if (G_UNLIKELY (ffmpegdec->picture->interlaced_frame !=
1770           ffmpegdec->format.video.interlaced)) {
1771     GST_WARNING ("Change in interlacing ! picture:%d, recorded:%d",
1772         ffmpegdec->picture->interlaced_frame,
1773         ffmpegdec->format.video.interlaced);
1774     ffmpegdec->format.video.interlaced = ffmpegdec->picture->interlaced_frame;
1775     gst_ffmpegdec_negotiate (ffmpegdec, TRUE);
1776   }
1777
1778   /* check if we are dealing with a keyframe here, this will also check if we
1779    * are dealing with B frames. */
1780   iskeyframe = check_keyframe (ffmpegdec);
1781
1782   /* check that the timestamps go upwards */
1783   if (ffmpegdec->last_out != -1 && ffmpegdec->last_out > out_pts) {
1784     /* timestamps go backwards, this means frames were reordered and we must
1785      * be dealing with DTS as the buffer timestamps */
1786     if (!ffmpegdec->reordered_out) {
1787       GST_DEBUG_OBJECT (ffmpegdec, "detected reordered out timestamps");
1788       ffmpegdec->reordered_out = TRUE;
1789     }
1790     if (ffmpegdec->reordered_in) {
1791       /* we reset the input reordering here because we want to recover from an
1792        * occasionally wrong reordered input timestamp */
1793       GST_DEBUG_OBJECT (ffmpegdec, "assuming DTS input timestamps");
1794       ffmpegdec->reordered_in = FALSE;
1795     }
1796   }
1797
1798   if (out_pts == 0 && out_pts == ffmpegdec->last_out) {
1799     GST_LOG_OBJECT (ffmpegdec, "ffmpeg returns 0 timestamps, ignoring");
1800     /* some codecs only output 0 timestamps, when that happens, make us select an
1801      * output timestamp based on the input timestamp. We do this by making the
1802      * ffmpeg timestamp and the interpollated next timestamp invalid. */
1803     out_pts = -1;
1804     ffmpegdec->next_out = -1;
1805   } else
1806     ffmpegdec->last_out = out_pts;
1807
1808   /* we assume DTS as input timestamps unless we see reordered input
1809    * timestamps */
1810   if (!ffmpegdec->reordered_in && ffmpegdec->reordered_out) {
1811     /* PTS and DTS are the same for keyframes */
1812     if (!iskeyframe && ffmpegdec->next_out != -1) {
1813       /* interpolate all timestamps except for keyframes, FIXME, this is
1814        * wrong when QoS is active. */
1815       GST_DEBUG_OBJECT (ffmpegdec, "interpolate timestamps");
1816       out_pts = -1;
1817       out_offset = -1;
1818     }
1819   }
1820
1821   /* when we're waiting for a keyframe, see if we have one or drop the current
1822    * non-keyframe */
1823   if (G_UNLIKELY (ffmpegdec->waiting_for_key)) {
1824     if (G_LIKELY (!iskeyframe))
1825       goto drop_non_keyframe;
1826
1827     /* we have a keyframe, we can stop waiting for one */
1828     ffmpegdec->waiting_for_key = FALSE;
1829   }
1830
1831   /* get a handle to the output buffer */
1832   *ret = get_output_buffer (ffmpegdec, outbuf);
1833   if (G_UNLIKELY (*ret != GST_FLOW_OK))
1834     goto no_output;
1835
1836   /*
1837    * Timestamps:
1838    *
1839    *  1) Copy picture timestamp if valid
1840    *  2) else interpolate from previous output timestamp
1841    *  3) else copy input timestamp
1842    */
1843   out_timestamp = -1;
1844   if (out_pts != -1) {
1845     /* Get (interpolated) timestamp from FFMPEG */
1846     out_timestamp = (GstClockTime) out_pts;
1847     GST_LOG_OBJECT (ffmpegdec, "using timestamp %" GST_TIME_FORMAT
1848         " returned by ffmpeg", GST_TIME_ARGS (out_timestamp));
1849   }
1850   if (!GST_CLOCK_TIME_IS_VALID (out_timestamp) && ffmpegdec->next_out != -1) {
1851     out_timestamp = ffmpegdec->next_out;
1852     GST_LOG_OBJECT (ffmpegdec, "using next timestamp %" GST_TIME_FORMAT,
1853         GST_TIME_ARGS (out_timestamp));
1854   }
1855   if (!GST_CLOCK_TIME_IS_VALID (out_timestamp)) {
1856     out_timestamp = dec_info->timestamp;
1857     GST_LOG_OBJECT (ffmpegdec, "using in timestamp %" GST_TIME_FORMAT,
1858         GST_TIME_ARGS (out_timestamp));
1859   }
1860   GST_BUFFER_TIMESTAMP (*outbuf) = out_timestamp;
1861
1862   /*
1863    * Offset:
1864    *  0) Use stored input offset (from opaque)
1865    *  1) Use value converted from timestamp if valid
1866    *  2) Use input offset if valid
1867    */
1868   if (out_offset != GST_BUFFER_OFFSET_NONE) {
1869     /* out_offset already contains the offset from ts_info */
1870     GST_LOG_OBJECT (ffmpegdec, "Using offset returned by ffmpeg");
1871   } else if (out_timestamp != GST_CLOCK_TIME_NONE) {
1872     GstFormat out_fmt = GST_FORMAT_DEFAULT;
1873     GST_LOG_OBJECT (ffmpegdec, "Using offset converted from timestamp");
1874     /* FIXME, we should really remove this as it's not nice at all to do
1875      * upstream queries for each frame to get the frame offset. We also can't
1876      * really remove this because it is the only way of setting frame offsets
1877      * on outgoing buffers. We should have metadata so that the upstream peer
1878      * can set a frame number on the encoded data. */
1879     gst_pad_query_peer_convert (ffmpegdec->sinkpad,
1880         GST_FORMAT_TIME, out_timestamp, &out_fmt, &out_offset);
1881   } else if (dec_info->offset != GST_BUFFER_OFFSET_NONE) {
1882     /* FIXME, the input offset is input media specific and might not
1883      * be the same for the output media. (byte offset as input, frame number
1884      * as output, for example) */
1885     GST_LOG_OBJECT (ffmpegdec, "using in_offset %" G_GINT64_FORMAT,
1886         dec_info->offset);
1887     out_offset = dec_info->offset;
1888   } else {
1889     GST_LOG_OBJECT (ffmpegdec, "no valid offset found");
1890     out_offset = GST_BUFFER_OFFSET_NONE;
1891   }
1892   GST_BUFFER_OFFSET (*outbuf) = out_offset;
1893
1894   /*
1895    * Duration:
1896    *
1897    *  1) Use reordered input duration if valid
1898    *  2) Else use input duration
1899    *  3) else use input framerate
1900    *  4) else use ffmpeg framerate
1901    */
1902   if (GST_CLOCK_TIME_IS_VALID (out_duration)) {
1903     /* We have a valid (reordered) duration */
1904     GST_LOG_OBJECT (ffmpegdec, "Using duration returned by ffmpeg");
1905   } else if (GST_CLOCK_TIME_IS_VALID (dec_info->duration)) {
1906     GST_LOG_OBJECT (ffmpegdec, "using in_duration");
1907     out_duration = dec_info->duration;
1908   } else if (GST_CLOCK_TIME_IS_VALID (ffmpegdec->last_diff)) {
1909     GST_LOG_OBJECT (ffmpegdec, "using last-diff");
1910     out_duration = ffmpegdec->last_diff;
1911   } else {
1912     /* if we have an input framerate, use that */
1913     if (ffmpegdec->format.video.fps_n != -1 &&
1914         (ffmpegdec->format.video.fps_n != 1000 &&
1915             ffmpegdec->format.video.fps_d != 1)) {
1916       GST_LOG_OBJECT (ffmpegdec, "using input framerate for duration");
1917       out_duration = gst_util_uint64_scale_int (GST_SECOND,
1918           ffmpegdec->format.video.fps_d, ffmpegdec->format.video.fps_n);
1919     } else {
1920       /* don't try to use the decoder's framerate when it seems a bit abnormal,
1921        * which we assume when den >= 1000... */
1922       if (ffmpegdec->context->time_base.num != 0 &&
1923           (ffmpegdec->context->time_base.den > 0 &&
1924               ffmpegdec->context->time_base.den < 1000)) {
1925         GST_LOG_OBJECT (ffmpegdec, "using decoder's framerate for duration");
1926         out_duration = gst_util_uint64_scale_int (GST_SECOND,
1927             ffmpegdec->context->time_base.num *
1928             ffmpegdec->context->ticks_per_frame,
1929             ffmpegdec->context->time_base.den);
1930       } else {
1931         GST_LOG_OBJECT (ffmpegdec, "no valid duration found");
1932       }
1933     }
1934   }
1935
1936   /* Take repeat_pict into account */
1937   if (GST_CLOCK_TIME_IS_VALID (out_duration)) {
1938     out_duration += out_duration * ffmpegdec->picture->repeat_pict / 2;
1939   }
1940   GST_BUFFER_DURATION (*outbuf) = out_duration;
1941
1942   if (out_timestamp != -1 && out_duration != -1 && out_duration != 0)
1943     ffmpegdec->next_out = out_timestamp + out_duration;
1944   else
1945     ffmpegdec->next_out = -1;
1946
1947   /* palette is not part of raw video frame in gst and the size
1948    * of the outgoing buffer needs to be adjusted accordingly */
1949   if (ffmpegdec->context->palctrl != NULL)
1950     GST_BUFFER_SIZE (*outbuf) -= AVPALETTE_SIZE;
1951
1952   /* now see if we need to clip the buffer against the segment boundaries. */
1953   if (G_UNLIKELY (!clip_video_buffer (ffmpegdec, *outbuf, out_timestamp,
1954               out_duration)))
1955     goto clipped;
1956
1957   /* mark as keyframe or delta unit */
1958   if (!iskeyframe)
1959     GST_BUFFER_FLAG_SET (*outbuf, GST_BUFFER_FLAG_DELTA_UNIT);
1960
1961   if (ffmpegdec->picture->top_field_first)
1962     GST_BUFFER_FLAG_SET (*outbuf, GST_VIDEO_BUFFER_TFF);
1963
1964
1965 beach:
1966   GST_DEBUG_OBJECT (ffmpegdec, "return flow %d, out %p, len %d",
1967       *ret, *outbuf, len);
1968   return len;
1969
1970   /* special cases */
1971 drop_non_keyframe:
1972   {
1973     GST_WARNING_OBJECT (ffmpegdec, "Dropping non-keyframe (seek/init)");
1974     goto beach;
1975   }
1976 no_output:
1977   {
1978     GST_DEBUG_OBJECT (ffmpegdec, "no output buffer");
1979     len = -1;
1980     goto beach;
1981   }
1982 clipped:
1983   {
1984     GST_DEBUG_OBJECT (ffmpegdec, "buffer clipped");
1985     gst_buffer_unref (*outbuf);
1986     *outbuf = NULL;
1987     goto beach;
1988   }
1989 }
1990
1991 /* returns TRUE if buffer is within segment, else FALSE.
1992  * if Buffer is on segment border, it's timestamp and duration will be clipped */
1993 static gboolean
1994 clip_audio_buffer (GstFFMpegDec * dec, GstBuffer * buf, GstClockTime in_ts,
1995     GstClockTime in_dur)
1996 {
1997   GstClockTime stop;
1998   gint64 diff, ctime, cstop;
1999   gboolean res = TRUE;
2000
2001   GST_LOG_OBJECT (dec,
2002       "timestamp:%" GST_TIME_FORMAT ", duration:%" GST_TIME_FORMAT
2003       ", size %u", GST_TIME_ARGS (in_ts), GST_TIME_ARGS (in_dur),
2004       GST_BUFFER_SIZE (buf));
2005
2006   /* can't clip without TIME segment */
2007   if (G_UNLIKELY (dec->segment.format != GST_FORMAT_TIME))
2008     goto beach;
2009
2010   /* we need a start time */
2011   if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (in_ts)))
2012     goto beach;
2013
2014   /* trust duration */
2015   stop = in_ts + in_dur;
2016
2017   res = gst_segment_clip (&dec->segment, GST_FORMAT_TIME, in_ts, stop, &ctime,
2018       &cstop);
2019   if (G_UNLIKELY (!res))
2020     goto out_of_segment;
2021
2022   /* see if some clipping happened */
2023   if (G_UNLIKELY ((diff = ctime - in_ts) > 0)) {
2024     /* bring clipped time to bytes */
2025     diff =
2026         gst_util_uint64_scale_int (diff, dec->format.audio.samplerate,
2027         GST_SECOND) * (dec->format.audio.depth * dec->format.audio.channels);
2028
2029     GST_DEBUG_OBJECT (dec, "clipping start to %" GST_TIME_FORMAT " %"
2030         G_GINT64_FORMAT " bytes", GST_TIME_ARGS (ctime), diff);
2031
2032     GST_BUFFER_SIZE (buf) -= diff;
2033     GST_BUFFER_DATA (buf) += diff;
2034   }
2035   if (G_UNLIKELY ((diff = stop - cstop) > 0)) {
2036     /* bring clipped time to bytes */
2037     diff =
2038         gst_util_uint64_scale_int (diff, dec->format.audio.samplerate,
2039         GST_SECOND) * (dec->format.audio.depth * dec->format.audio.channels);
2040
2041     GST_DEBUG_OBJECT (dec, "clipping stop to %" GST_TIME_FORMAT " %"
2042         G_GINT64_FORMAT " bytes", GST_TIME_ARGS (cstop), diff);
2043
2044     GST_BUFFER_SIZE (buf) -= diff;
2045   }
2046   GST_BUFFER_TIMESTAMP (buf) = ctime;
2047   GST_BUFFER_DURATION (buf) = cstop - ctime;
2048
2049 beach:
2050   GST_LOG_OBJECT (dec, "%sdropping", (res ? "not " : ""));
2051   return res;
2052
2053   /* ERRORS */
2054 out_of_segment:
2055   {
2056     GST_LOG_OBJECT (dec, "out of segment");
2057     goto beach;
2058   }
2059 }
2060
2061 static gint
2062 gst_ffmpegdec_audio_frame (GstFFMpegDec * ffmpegdec,
2063     AVCodec * in_plugin, guint8 * data, guint size,
2064     const GstTSInfo * dec_info, GstBuffer ** outbuf, GstFlowReturn * ret)
2065 {
2066   gint len = -1;
2067   gint have_data = AVCODEC_MAX_AUDIO_FRAME_SIZE;
2068   GstClockTime out_timestamp, out_duration;
2069   gint64 out_offset;
2070   AVPacket packet;
2071
2072   GST_DEBUG_OBJECT (ffmpegdec,
2073       "size:%d, offset:%" G_GINT64_FORMAT ", ts:%" GST_TIME_FORMAT ", dur:%"
2074       GST_TIME_FORMAT ", ffmpegdec->next_out:%" GST_TIME_FORMAT, size,
2075       dec_info->offset, GST_TIME_ARGS (dec_info->timestamp),
2076       GST_TIME_ARGS (dec_info->duration), GST_TIME_ARGS (ffmpegdec->next_out));
2077
2078   *outbuf =
2079       new_aligned_buffer (AVCODEC_MAX_AUDIO_FRAME_SIZE,
2080       GST_PAD_CAPS (ffmpegdec->srcpad));
2081
2082   gst_avpacket_init (&packet, data, size);
2083   len = avcodec_decode_audio3 (ffmpegdec->context,
2084       (int16_t *) GST_BUFFER_DATA (*outbuf), &have_data, &packet);
2085   GST_DEBUG_OBJECT (ffmpegdec,
2086       "Decode audio: len=%d, have_data=%d", len, have_data);
2087
2088   if (len >= 0 && have_data > 0) {
2089     GST_DEBUG_OBJECT (ffmpegdec, "Creating output buffer");
2090     if (!gst_ffmpegdec_negotiate (ffmpegdec, FALSE)) {
2091       gst_buffer_unref (*outbuf);
2092       *outbuf = NULL;
2093       len = -1;
2094       goto beach;
2095     }
2096
2097     /* Buffer size */
2098     GST_BUFFER_SIZE (*outbuf) = have_data;
2099
2100     /*
2101      * Timestamps:
2102      *
2103      *  1) Copy input timestamp if valid
2104      *  2) else interpolate from previous input timestamp
2105      */
2106     /* always take timestamps from the input buffer if any */
2107     if (GST_CLOCK_TIME_IS_VALID (dec_info->timestamp)) {
2108       out_timestamp = dec_info->timestamp;
2109     } else {
2110       out_timestamp = ffmpegdec->next_out;
2111     }
2112
2113     /*
2114      * Duration:
2115      *
2116      *  1) calculate based on number of samples
2117      */
2118     out_duration = gst_util_uint64_scale (have_data, GST_SECOND,
2119         ffmpegdec->format.audio.depth * ffmpegdec->format.audio.channels *
2120         ffmpegdec->format.audio.samplerate);
2121
2122     /* offset:
2123      *
2124      * Just copy
2125      */
2126     out_offset = dec_info->offset;
2127
2128     GST_DEBUG_OBJECT (ffmpegdec,
2129         "Buffer created. Size:%d , timestamp:%" GST_TIME_FORMAT " , duration:%"
2130         GST_TIME_FORMAT, have_data,
2131         GST_TIME_ARGS (out_timestamp), GST_TIME_ARGS (out_duration));
2132
2133     GST_BUFFER_TIMESTAMP (*outbuf) = out_timestamp;
2134     GST_BUFFER_DURATION (*outbuf) = out_duration;
2135     GST_BUFFER_OFFSET (*outbuf) = out_offset;
2136     gst_buffer_set_caps (*outbuf, GST_PAD_CAPS (ffmpegdec->srcpad));
2137
2138     /* the next timestamp we'll use when interpolating */
2139     if (GST_CLOCK_TIME_IS_VALID (out_timestamp))
2140       ffmpegdec->next_out = out_timestamp + out_duration;
2141
2142     /* now see if we need to clip the buffer against the segment boundaries. */
2143     if (G_UNLIKELY (!clip_audio_buffer (ffmpegdec, *outbuf, out_timestamp,
2144                 out_duration)))
2145       goto clipped;
2146
2147   } else {
2148     gst_buffer_unref (*outbuf);
2149     *outbuf = NULL;
2150   }
2151
2152   /* If we don't error out after the first failed read with the AAC decoder,
2153    * we must *not* carry on pushing data, else we'll cause segfaults... */
2154   if (len == -1 && (in_plugin->id == CODEC_ID_AAC
2155           || in_plugin->id == CODEC_ID_AAC_LATM)) {
2156     GST_ELEMENT_ERROR (ffmpegdec, STREAM, DECODE, (NULL),
2157         ("Decoding of AAC stream by FFMPEG failed."));
2158     *ret = GST_FLOW_ERROR;
2159   }
2160
2161 beach:
2162   GST_DEBUG_OBJECT (ffmpegdec, "return flow %d, out %p, len %d",
2163       *ret, *outbuf, len);
2164   return len;
2165
2166   /* ERRORS */
2167 clipped:
2168   {
2169     GST_DEBUG_OBJECT (ffmpegdec, "buffer clipped");
2170     gst_buffer_unref (*outbuf);
2171     *outbuf = NULL;
2172     goto beach;
2173   }
2174 }
2175
2176 /* gst_ffmpegdec_frame:
2177  * ffmpegdec:
2178  * data: pointer to the data to decode
2179  * size: size of data in bytes
2180  * got_data: 0 if no data was decoded, != 0 otherwise.
2181  * in_time: timestamp of data
2182  * in_duration: duration of data
2183  * ret: GstFlowReturn to return in the chain function
2184  *
2185  * Decode the given frame and pushes it downstream.
2186  *
2187  * Returns: Number of bytes used in decoding, -1 on error/failure.
2188  */
2189
2190 static gint
2191 gst_ffmpegdec_frame (GstFFMpegDec * ffmpegdec,
2192     guint8 * data, guint size, gint * got_data, const GstTSInfo * dec_info,
2193     GstFlowReturn * ret)
2194 {
2195   GstFFMpegDecClass *oclass;
2196   GstBuffer *outbuf = NULL;
2197   gint have_data = 0, len = 0;
2198
2199   if (G_UNLIKELY (ffmpegdec->context->codec == NULL))
2200     goto no_codec;
2201
2202   GST_LOG_OBJECT (ffmpegdec, "data:%p, size:%d, id:%d", data, size,
2203       dec_info->idx);
2204
2205   *ret = GST_FLOW_OK;
2206   ffmpegdec->context->frame_number++;
2207
2208   oclass = (GstFFMpegDecClass *) (G_OBJECT_GET_CLASS (ffmpegdec));
2209
2210   switch (oclass->in_plugin->type) {
2211     case AVMEDIA_TYPE_VIDEO:
2212       len =
2213           gst_ffmpegdec_video_frame (ffmpegdec, data, size, dec_info, &outbuf,
2214           ret);
2215       break;
2216     case AVMEDIA_TYPE_AUDIO:
2217       len =
2218           gst_ffmpegdec_audio_frame (ffmpegdec, oclass->in_plugin, data, size,
2219           dec_info, &outbuf, ret);
2220
2221       /* if we did not get an output buffer and we have a pending discont, don't
2222        * clear the input timestamps, we will put them on the next buffer because
2223        * else we might create the first buffer with a very big timestamp gap. */
2224       if (outbuf == NULL && ffmpegdec->discont) {
2225         GST_DEBUG_OBJECT (ffmpegdec, "no buffer but keeping timestamp");
2226         ffmpegdec->clear_ts = FALSE;
2227       }
2228       break;
2229     default:
2230       GST_ERROR_OBJECT (ffmpegdec, "Asked to decode non-audio/video frame !");
2231       g_assert_not_reached ();
2232       break;
2233   }
2234
2235   if (outbuf)
2236     have_data = 1;
2237
2238   if (len < 0 || have_data < 0) {
2239     GST_WARNING_OBJECT (ffmpegdec,
2240         "ffdec_%s: decoding error (len: %d, have_data: %d)",
2241         oclass->in_plugin->name, len, have_data);
2242     *got_data = 0;
2243     goto beach;
2244   } else if (len == 0 && have_data == 0) {
2245     *got_data = 0;
2246     goto beach;
2247   } else {
2248     /* this is where I lost my last clue on ffmpeg... */
2249     *got_data = 1;
2250   }
2251
2252   if (outbuf) {
2253     GST_LOG_OBJECT (ffmpegdec,
2254         "Decoded data, now pushing buffer %p with offset %" G_GINT64_FORMAT
2255         ", timestamp %" GST_TIME_FORMAT " and duration %" GST_TIME_FORMAT,
2256         outbuf, GST_BUFFER_OFFSET (outbuf),
2257         GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (outbuf)),
2258         GST_TIME_ARGS (GST_BUFFER_DURATION (outbuf)));
2259
2260     /* mark pending discont */
2261     if (ffmpegdec->discont) {
2262       GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_DISCONT);
2263       ffmpegdec->discont = FALSE;
2264     }
2265
2266     if (ffmpegdec->segment.rate > 0.0) {
2267       /* and off we go */
2268       *ret = gst_pad_push (ffmpegdec->srcpad, outbuf);
2269     } else {
2270       /* reverse playback, queue frame till later when we get a discont. */
2271       GST_DEBUG_OBJECT (ffmpegdec, "queued frame");
2272       ffmpegdec->queued = g_list_prepend (ffmpegdec->queued, outbuf);
2273       *ret = GST_FLOW_OK;
2274     }
2275   } else {
2276     GST_DEBUG_OBJECT (ffmpegdec, "We didn't get a decoded buffer");
2277   }
2278
2279 beach:
2280   return len;
2281
2282   /* ERRORS */
2283 no_codec:
2284   {
2285     GST_ERROR_OBJECT (ffmpegdec, "no codec context");
2286     return -1;
2287   }
2288 }
2289
2290 static void
2291 gst_ffmpegdec_drain (GstFFMpegDec * ffmpegdec)
2292 {
2293   GstFFMpegDecClass *oclass;
2294
2295   oclass = (GstFFMpegDecClass *) (G_OBJECT_GET_CLASS (ffmpegdec));
2296
2297   if (oclass->in_plugin->capabilities & CODEC_CAP_DELAY) {
2298     gint have_data, len, try = 0;
2299
2300     GST_LOG_OBJECT (ffmpegdec,
2301         "codec has delay capabilities, calling until ffmpeg has drained everything");
2302
2303     do {
2304       GstFlowReturn ret;
2305
2306       len =
2307           gst_ffmpegdec_frame (ffmpegdec, NULL, 0, &have_data, &ts_info_none,
2308           &ret);
2309       if (len < 0 || have_data == 0)
2310         break;
2311     } while (try++ < 10);
2312   }
2313   if (ffmpegdec->segment.rate < 0.0) {
2314     /* if we have some queued frames for reverse playback, flush them now */
2315     flush_queued (ffmpegdec);
2316   }
2317 }
2318
2319 static void
2320 gst_ffmpegdec_flush_pcache (GstFFMpegDec * ffmpegdec)
2321 {
2322   if (ffmpegdec->pctx) {
2323     gint size, bsize;
2324     guint8 *data;
2325     guint8 bdata[FF_INPUT_BUFFER_PADDING_SIZE];
2326
2327     bsize = FF_INPUT_BUFFER_PADDING_SIZE;
2328     memset (bdata, 0, bsize);
2329
2330     /* parse some dummy data to work around some ffmpeg weirdness where it keeps
2331      * the previous pts around */
2332     av_parser_parse2 (ffmpegdec->pctx, ffmpegdec->context,
2333         &data, &size, bdata, bsize, -1, -1, -1);
2334     ffmpegdec->pctx->pts = -1;
2335     ffmpegdec->pctx->dts = -1;
2336   }
2337
2338   if (ffmpegdec->pcache) {
2339     gst_buffer_unref (ffmpegdec->pcache);
2340     ffmpegdec->pcache = NULL;
2341   }
2342 }
2343
2344 static gboolean
2345 gst_ffmpegdec_sink_event (GstPad * pad, GstEvent * event)
2346 {
2347   GstFFMpegDec *ffmpegdec;
2348   gboolean ret = FALSE;
2349
2350   ffmpegdec = (GstFFMpegDec *) gst_pad_get_parent (pad);
2351
2352   GST_DEBUG_OBJECT (ffmpegdec, "Handling %s event",
2353       GST_EVENT_TYPE_NAME (event));
2354
2355   switch (GST_EVENT_TYPE (event)) {
2356     case GST_EVENT_EOS:
2357     {
2358       gst_ffmpegdec_drain (ffmpegdec);
2359       break;
2360     }
2361     case GST_EVENT_FLUSH_STOP:
2362     {
2363       if (ffmpegdec->opened) {
2364         avcodec_flush_buffers (ffmpegdec->context);
2365       }
2366       gst_ffmpegdec_reset_ts (ffmpegdec);
2367       gst_ffmpegdec_reset_qos (ffmpegdec);
2368       gst_ffmpegdec_flush_pcache (ffmpegdec);
2369       ffmpegdec->waiting_for_key = TRUE;
2370       gst_segment_init (&ffmpegdec->segment, GST_FORMAT_TIME);
2371       clear_queued (ffmpegdec);
2372       break;
2373     }
2374     case GST_EVENT_NEWSEGMENT:
2375     {
2376       gboolean update;
2377       GstFormat fmt;
2378       gint64 start, stop, time;
2379       gdouble rate, arate;
2380
2381       gst_event_parse_new_segment_full (event, &update, &rate, &arate, &fmt,
2382           &start, &stop, &time);
2383
2384       switch (fmt) {
2385         case GST_FORMAT_TIME:
2386           /* fine, our native segment format */
2387           break;
2388         case GST_FORMAT_BYTES:
2389         {
2390           gint bit_rate;
2391
2392           bit_rate = ffmpegdec->context->bit_rate;
2393
2394           /* convert to time or fail */
2395           if (!bit_rate)
2396             goto no_bitrate;
2397
2398           GST_DEBUG_OBJECT (ffmpegdec, "bitrate: %d", bit_rate);
2399
2400           /* convert values to TIME */
2401           if (start != -1)
2402             start = gst_util_uint64_scale_int (start, GST_SECOND, bit_rate);
2403           if (stop != -1)
2404             stop = gst_util_uint64_scale_int (stop, GST_SECOND, bit_rate);
2405           if (time != -1)
2406             time = gst_util_uint64_scale_int (time, GST_SECOND, bit_rate);
2407
2408           /* unref old event */
2409           gst_event_unref (event);
2410
2411           /* create new converted time segment */
2412           fmt = GST_FORMAT_TIME;
2413           /* FIXME, bitrate is not good enough too find a good stop, let's
2414            * hope start and time were 0... meh. */
2415           stop = -1;
2416           event = gst_event_new_new_segment (update, rate, fmt,
2417               start, stop, time);
2418           break;
2419         }
2420         default:
2421           /* invalid format */
2422           goto invalid_format;
2423       }
2424
2425       /* drain pending frames before trying to use the new segment, queued
2426        * buffers belonged to the previous segment. */
2427       if (ffmpegdec->context->codec)
2428         gst_ffmpegdec_drain (ffmpegdec);
2429
2430       GST_DEBUG_OBJECT (ffmpegdec,
2431           "NEWSEGMENT in time start %" GST_TIME_FORMAT " -- stop %"
2432           GST_TIME_FORMAT, GST_TIME_ARGS (start), GST_TIME_ARGS (stop));
2433
2434       /* and store the values */
2435       gst_segment_set_newsegment_full (&ffmpegdec->segment, update,
2436           rate, arate, fmt, start, stop, time);
2437       break;
2438     }
2439     default:
2440       break;
2441   }
2442
2443   /* and push segment downstream */
2444   ret = gst_pad_push_event (ffmpegdec->srcpad, event);
2445
2446 done:
2447   gst_object_unref (ffmpegdec);
2448
2449   return ret;
2450
2451   /* ERRORS */
2452 no_bitrate:
2453   {
2454     GST_WARNING_OBJECT (ffmpegdec, "no bitrate to convert BYTES to TIME");
2455     gst_event_unref (event);
2456     goto done;
2457   }
2458 invalid_format:
2459   {
2460     GST_WARNING_OBJECT (ffmpegdec, "unknown format received in NEWSEGMENT");
2461     gst_event_unref (event);
2462     goto done;
2463   }
2464 }
2465
2466 static GstFlowReturn
2467 gst_ffmpegdec_chain (GstPad * pad, GstBuffer * inbuf)
2468 {
2469   GstFFMpegDec *ffmpegdec;
2470   GstFFMpegDecClass *oclass;
2471   guint8 *data, *bdata;
2472   gint size, bsize, len, have_data;
2473   GstFlowReturn ret = GST_FLOW_OK;
2474   GstClockTime in_timestamp;
2475   GstClockTime in_duration;
2476   gboolean discont;
2477   gint64 in_offset;
2478   const GstTSInfo *in_info;
2479   const GstTSInfo *dec_info;
2480
2481   ffmpegdec = (GstFFMpegDec *) (GST_PAD_PARENT (pad));
2482
2483   if (G_UNLIKELY (!ffmpegdec->opened))
2484     goto not_negotiated;
2485
2486   discont = GST_BUFFER_IS_DISCONT (inbuf);
2487
2488   /* The discont flags marks a buffer that is not continuous with the previous
2489    * buffer. This means we need to clear whatever data we currently have. We
2490    * currently also wait for a new keyframe, which might be suboptimal in the
2491    * case of a network error, better show the errors than to drop all data.. */
2492   if (G_UNLIKELY (discont)) {
2493     GST_DEBUG_OBJECT (ffmpegdec, "received DISCONT");
2494     /* drain what we have queued */
2495     gst_ffmpegdec_drain (ffmpegdec);
2496     gst_ffmpegdec_flush_pcache (ffmpegdec);
2497     avcodec_flush_buffers (ffmpegdec->context);
2498     ffmpegdec->discont = TRUE;
2499     gst_ffmpegdec_reset_ts (ffmpegdec);
2500   }
2501   /* by default we clear the input timestamp after decoding each frame so that
2502    * interpollation can work. */
2503   ffmpegdec->clear_ts = TRUE;
2504
2505   oclass = (GstFFMpegDecClass *) (G_OBJECT_GET_CLASS (ffmpegdec));
2506
2507   /* do early keyframe check pretty bad to rely on the keyframe flag in the
2508    * source for this as it might not even be parsed (UDP/file/..).  */
2509   if (G_UNLIKELY (ffmpegdec->waiting_for_key)) {
2510     GST_DEBUG_OBJECT (ffmpegdec, "waiting for keyframe");
2511     if (GST_BUFFER_FLAG_IS_SET (inbuf, GST_BUFFER_FLAG_DELTA_UNIT) &&
2512         oclass->in_plugin->type != AVMEDIA_TYPE_AUDIO)
2513       goto skip_keyframe;
2514
2515     GST_DEBUG_OBJECT (ffmpegdec, "got keyframe");
2516     ffmpegdec->waiting_for_key = FALSE;
2517   }
2518   /* parse cache joining. If there is cached data */
2519   if (ffmpegdec->pcache) {
2520     /* join with previous data */
2521     GST_LOG_OBJECT (ffmpegdec, "join parse cache");
2522     inbuf = gst_buffer_join (ffmpegdec->pcache, inbuf);
2523     /* no more cached data, we assume we can consume the complete cache */
2524     ffmpegdec->pcache = NULL;
2525   }
2526
2527   in_timestamp = GST_BUFFER_TIMESTAMP (inbuf);
2528   in_duration = GST_BUFFER_DURATION (inbuf);
2529   in_offset = GST_BUFFER_OFFSET (inbuf);
2530
2531   /* get handle to timestamp info, we can pass this around to ffmpeg */
2532   in_info = gst_ts_info_store (ffmpegdec, in_timestamp, in_duration, in_offset);
2533
2534   if (in_timestamp != -1) {
2535     /* check for increasing timestamps if they are jumping backwards, we
2536      * probably are dealing with PTS as timestamps */
2537     if (!ffmpegdec->reordered_in && ffmpegdec->last_in != -1) {
2538       if (in_timestamp < ffmpegdec->last_in) {
2539         GST_LOG_OBJECT (ffmpegdec, "detected reordered input timestamps");
2540         ffmpegdec->reordered_in = TRUE;
2541         ffmpegdec->last_diff = GST_CLOCK_TIME_NONE;
2542       } else if (in_timestamp > ffmpegdec->last_in) {
2543         GstClockTime diff;
2544         /* keep track of timestamp diff to estimate duration */
2545         diff = in_timestamp - ffmpegdec->last_in;
2546         /* need to scale with amount of frames in the interval */
2547         if (ffmpegdec->last_frames)
2548           diff /= ffmpegdec->last_frames;
2549
2550         GST_LOG_OBJECT (ffmpegdec, "estimated duration %" GST_TIME_FORMAT " %u",
2551             GST_TIME_ARGS (diff), ffmpegdec->last_frames);
2552
2553         ffmpegdec->last_diff = diff;
2554       }
2555     }
2556     ffmpegdec->last_in = in_timestamp;
2557     ffmpegdec->last_frames = 0;
2558   }
2559
2560   GST_LOG_OBJECT (ffmpegdec,
2561       "Received new data of size %u, offset:%" G_GUINT64_FORMAT ", ts:%"
2562       GST_TIME_FORMAT ", dur:%" GST_TIME_FORMAT ", info %d",
2563       GST_BUFFER_SIZE (inbuf), GST_BUFFER_OFFSET (inbuf),
2564       GST_TIME_ARGS (in_timestamp), GST_TIME_ARGS (in_duration), in_info->idx);
2565
2566   /* workarounds, functions write to buffers:
2567    *  libavcodec/svq1.c:svq1_decode_frame writes to the given buffer.
2568    *  libavcodec/svq3.c:svq3_decode_slice_header too.
2569    * ffmpeg devs know about it and will fix it (they said). */
2570   if (oclass->in_plugin->id == CODEC_ID_SVQ1 ||
2571       oclass->in_plugin->id == CODEC_ID_SVQ3) {
2572     inbuf = gst_buffer_make_writable (inbuf);
2573   }
2574
2575   bdata = GST_BUFFER_DATA (inbuf);
2576   bsize = GST_BUFFER_SIZE (inbuf);
2577
2578   if (ffmpegdec->do_padding) {
2579     /* add padding */
2580     if (ffmpegdec->padded_size < bsize + FF_INPUT_BUFFER_PADDING_SIZE) {
2581       ffmpegdec->padded_size = bsize + FF_INPUT_BUFFER_PADDING_SIZE;
2582       ffmpegdec->padded = g_realloc (ffmpegdec->padded, ffmpegdec->padded_size);
2583       GST_LOG_OBJECT (ffmpegdec, "resized padding buffer to %d",
2584           ffmpegdec->padded_size);
2585     }
2586     memcpy (ffmpegdec->padded, bdata, bsize);
2587     memset (ffmpegdec->padded + bsize, 0, FF_INPUT_BUFFER_PADDING_SIZE);
2588
2589     bdata = ffmpegdec->padded;
2590   }
2591
2592   do {
2593     guint8 tmp_padding[FF_INPUT_BUFFER_PADDING_SIZE];
2594
2595     /* parse, if at all possible */
2596     if (ffmpegdec->pctx) {
2597       gint res;
2598
2599       GST_LOG_OBJECT (ffmpegdec,
2600           "Calling av_parser_parse2 with offset %" G_GINT64_FORMAT ", ts:%"
2601           GST_TIME_FORMAT " size %d", in_offset, GST_TIME_ARGS (in_timestamp),
2602           bsize);
2603
2604       /* feed the parser. We pass the timestamp info so that we can recover all
2605        * info again later */
2606       res = av_parser_parse2 (ffmpegdec->pctx, ffmpegdec->context,
2607           &data, &size, bdata, bsize, in_info->idx, in_info->idx, in_offset);
2608
2609       GST_LOG_OBJECT (ffmpegdec,
2610           "parser returned res %d and size %d, id %" G_GINT64_FORMAT, res, size,
2611           ffmpegdec->pctx->pts);
2612
2613       /* store pts for decoding */
2614       if (ffmpegdec->pctx->pts != AV_NOPTS_VALUE && ffmpegdec->pctx->pts != -1)
2615         dec_info = gst_ts_info_get (ffmpegdec, ffmpegdec->pctx->pts);
2616       else {
2617         /* ffmpeg sometimes loses track after a flush, help it by feeding a
2618          * valid start time */
2619         ffmpegdec->pctx->pts = in_info->idx;
2620         ffmpegdec->pctx->dts = in_info->idx;
2621         dec_info = in_info;
2622       }
2623
2624       GST_LOG_OBJECT (ffmpegdec, "consuming %d bytes. id %d", size,
2625           dec_info->idx);
2626
2627       if (res) {
2628         /* there is output, set pointers for next round. */
2629         bsize -= res;
2630         bdata += res;
2631       } else {
2632         /* Parser did not consume any data, make sure we don't clear the
2633          * timestamp for the next round */
2634         ffmpegdec->clear_ts = FALSE;
2635       }
2636
2637       /* if there is no output, we must break and wait for more data. also the
2638        * timestamp in the context is not updated. */
2639       if (size == 0) {
2640         if (bsize > 0)
2641           continue;
2642         else
2643           break;
2644       }
2645     } else {
2646       data = bdata;
2647       size = bsize;
2648
2649       dec_info = in_info;
2650     }
2651
2652     if (ffmpegdec->do_padding) {
2653       /* add temporary padding */
2654       memcpy (tmp_padding, data + size, FF_INPUT_BUFFER_PADDING_SIZE);
2655       memset (data + size, 0, FF_INPUT_BUFFER_PADDING_SIZE);
2656     }
2657
2658     /* decode a frame of audio/video now */
2659     len =
2660         gst_ffmpegdec_frame (ffmpegdec, data, size, &have_data, dec_info, &ret);
2661
2662     if (ffmpegdec->do_padding) {
2663       memcpy (data + size, tmp_padding, FF_INPUT_BUFFER_PADDING_SIZE);
2664     }
2665
2666     if (ret != GST_FLOW_OK) {
2667       GST_LOG_OBJECT (ffmpegdec, "breaking because of flow ret %s",
2668           gst_flow_get_name (ret));
2669       /* bad flow retun, make sure we discard all data and exit */
2670       bsize = 0;
2671       break;
2672     }
2673     if (!ffmpegdec->pctx) {
2674       if (len == 0 && !have_data) {
2675         /* nothing was decoded, this could be because no data was available or
2676          * because we were skipping frames.
2677          * If we have no context we must exit and wait for more data, we keep the
2678          * data we tried. */
2679         GST_LOG_OBJECT (ffmpegdec, "Decoding didn't return any data, breaking");
2680         break;
2681       } else if (len < 0) {
2682         /* a decoding error happened, we must break and try again with next data. */
2683         GST_LOG_OBJECT (ffmpegdec, "Decoding error, breaking");
2684         bsize = 0;
2685         break;
2686       }
2687       /* prepare for the next round, for codecs with a context we did this
2688        * already when using the parser. */
2689       bsize -= len;
2690       bdata += len;
2691     } else {
2692       if (len == 0) {
2693         /* nothing was decoded, this could be because no data was available or
2694          * because we were skipping frames. Since we have a parser we can
2695          * continue with the next frame */
2696         GST_LOG_OBJECT (ffmpegdec,
2697             "Decoding didn't return any data, trying next");
2698       } else if (len < 0) {
2699         /* we have a context that will bring us to the next frame */
2700         GST_LOG_OBJECT (ffmpegdec, "Decoding error, trying next");
2701       }
2702     }
2703
2704     /* make sure we don't use the same old timestamp for the next frame and let
2705      * the interpollation take care of it. */
2706     if (ffmpegdec->clear_ts) {
2707       in_timestamp = GST_CLOCK_TIME_NONE;
2708       in_duration = GST_CLOCK_TIME_NONE;
2709       in_offset = GST_BUFFER_OFFSET_NONE;
2710       in_info = GST_TS_INFO_NONE;
2711     } else {
2712       ffmpegdec->clear_ts = TRUE;
2713     }
2714     ffmpegdec->last_frames++;
2715
2716     GST_LOG_OBJECT (ffmpegdec, "Before (while bsize>0).  bsize:%d , bdata:%p",
2717         bsize, bdata);
2718   } while (bsize > 0);
2719
2720   /* keep left-over */
2721   if (ffmpegdec->pctx && bsize > 0) {
2722     in_timestamp = GST_BUFFER_TIMESTAMP (inbuf);
2723     in_offset = GST_BUFFER_OFFSET (inbuf);
2724
2725     GST_LOG_OBJECT (ffmpegdec,
2726         "Keeping %d bytes of data with offset %" G_GINT64_FORMAT ", timestamp %"
2727         GST_TIME_FORMAT, bsize, in_offset, GST_TIME_ARGS (in_timestamp));
2728
2729     ffmpegdec->pcache = gst_buffer_create_sub (inbuf,
2730         GST_BUFFER_SIZE (inbuf) - bsize, bsize);
2731     /* we keep timestamp, even though all we really know is that the correct
2732      * timestamp is not below the one from inbuf */
2733     GST_BUFFER_TIMESTAMP (ffmpegdec->pcache) = in_timestamp;
2734     GST_BUFFER_OFFSET (ffmpegdec->pcache) = in_offset;
2735   } else if (bsize > 0) {
2736     GST_DEBUG_OBJECT (ffmpegdec, "Dropping %d bytes of data", bsize);
2737   }
2738   gst_buffer_unref (inbuf);
2739
2740   return ret;
2741
2742   /* ERRORS */
2743 not_negotiated:
2744   {
2745     oclass = (GstFFMpegDecClass *) (G_OBJECT_GET_CLASS (ffmpegdec));
2746     GST_ELEMENT_ERROR (ffmpegdec, CORE, NEGOTIATION, (NULL),
2747         ("ffdec_%s: input format was not set before data start",
2748             oclass->in_plugin->name));
2749     gst_buffer_unref (inbuf);
2750     return GST_FLOW_NOT_NEGOTIATED;
2751   }
2752 skip_keyframe:
2753   {
2754     GST_DEBUG_OBJECT (ffmpegdec, "skipping non keyframe");
2755     gst_buffer_unref (inbuf);
2756     return GST_FLOW_OK;
2757   }
2758 }
2759
2760 static GstStateChangeReturn
2761 gst_ffmpegdec_change_state (GstElement * element, GstStateChange transition)
2762 {
2763   GstFFMpegDec *ffmpegdec = (GstFFMpegDec *) element;
2764   GstStateChangeReturn ret;
2765
2766   ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
2767
2768   switch (transition) {
2769     case GST_STATE_CHANGE_PAUSED_TO_READY:
2770       GST_OBJECT_LOCK (ffmpegdec);
2771       gst_ffmpegdec_close (ffmpegdec);
2772       GST_OBJECT_UNLOCK (ffmpegdec);
2773       clear_queued (ffmpegdec);
2774       g_free (ffmpegdec->padded);
2775       ffmpegdec->padded = NULL;
2776       ffmpegdec->padded_size = 0;
2777       ffmpegdec->can_allocate_aligned = TRUE;
2778       break;
2779     default:
2780       break;
2781   }
2782
2783   return ret;
2784 }
2785
2786 static void
2787 gst_ffmpegdec_set_property (GObject * object,
2788     guint prop_id, const GValue * value, GParamSpec * pspec)
2789 {
2790   GstFFMpegDec *ffmpegdec = (GstFFMpegDec *) object;
2791
2792   switch (prop_id) {
2793     case PROP_LOWRES:
2794       ffmpegdec->lowres = ffmpegdec->context->lowres = g_value_get_enum (value);
2795       break;
2796     case PROP_SKIPFRAME:
2797       ffmpegdec->skip_frame = ffmpegdec->context->skip_frame =
2798           g_value_get_enum (value);
2799       break;
2800     case PROP_DIRECT_RENDERING:
2801       ffmpegdec->direct_rendering = g_value_get_boolean (value);
2802       break;
2803     case PROP_DO_PADDING:
2804       ffmpegdec->do_padding = g_value_get_boolean (value);
2805       break;
2806     case PROP_DEBUG_MV:
2807       ffmpegdec->debug_mv = ffmpegdec->context->debug_mv =
2808           g_value_get_boolean (value);
2809       break;
2810     case PROP_CROP:
2811       ffmpegdec->crop = g_value_get_boolean (value);
2812       break;
2813     case PROP_MAX_THREADS:
2814       ffmpegdec->max_threads = g_value_get_int (value);
2815       break;
2816     default:
2817       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
2818       break;
2819   }
2820 }
2821
2822 static void
2823 gst_ffmpegdec_get_property (GObject * object,
2824     guint prop_id, GValue * value, GParamSpec * pspec)
2825 {
2826   GstFFMpegDec *ffmpegdec = (GstFFMpegDec *) object;
2827
2828   switch (prop_id) {
2829     case PROP_LOWRES:
2830       g_value_set_enum (value, ffmpegdec->context->lowres);
2831       break;
2832     case PROP_SKIPFRAME:
2833       g_value_set_enum (value, ffmpegdec->context->skip_frame);
2834       break;
2835     case PROP_DIRECT_RENDERING:
2836