f4e2300f527d80d377feef29d332bd131f6d525b
[platform/upstream/gstreamer.git] / ext / libav / gstavdemux.c
1 /* GStreamer
2  * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>,
3  *               <2006> Edward Hervey <bilboed@bilboed.com>
4  *               <2006> Wim Taymans <wim@fluendo.com>
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Library General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Library General Public License for more details.
15  *
16  * You should have received a copy of the GNU Library General Public
17  * License along with this library; if not, write to the
18  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
19  * Boston, MA 02110-1301, USA.
20  */
21
22 #ifdef HAVE_CONFIG_H
23 #include "config.h"
24 #endif
25
26 #include <string.h>
27
28 #include <libavformat/avformat.h>
29 /* #include <ffmpeg/avi.h> */
30 #include <gst/gst.h>
31
32 #include "gstav.h"
33 #include "gstavcodecmap.h"
34 #include "gstavutils.h"
35 #include "gstavprotocol.h"
36
37 #define MAX_STREAMS 20
38
39 typedef struct _GstFFMpegDemux GstFFMpegDemux;
40 typedef struct _GstFFStream GstFFStream;
41
42 struct _GstFFStream
43 {
44   GstPad *pad;
45
46   AVStream *avstream;
47
48   gboolean unknown;
49   GstClockTime last_ts;
50   gboolean discont;
51   gboolean eos;
52   GstFlowReturn last_flow;
53
54   GstTagList *tags;             /* stream tags */
55 };
56
57 struct _GstFFMpegDemux
58 {
59   GstElement element;
60
61   /* We need to keep track of our pads, so we do so here. */
62   GstPad *sinkpad;
63
64   gboolean have_group_id;
65   guint group_id;
66
67   AVFormatContext *context;
68   gboolean opened;
69
70   GstFFStream *streams[MAX_STREAMS];
71
72   gint videopads, audiopads;
73
74   GstClockTime start_time;
75   GstClockTime duration;
76
77   /* TRUE if working in pull-mode */
78   gboolean seekable;
79
80   /* TRUE if the avformat demuxer can reliably handle streaming mode */
81   gboolean can_push;
82
83   gboolean flushing;
84
85   /* segment stuff */
86   GstSegment segment;
87
88   /* cached seek in READY */
89   GstEvent *seek_event;
90
91   /* cached upstream events */
92   GList *cached_events;
93
94   /* push mode data */
95   GstFFMpegPipe ffpipe;
96   GstTask *task;
97   GRecMutex task_lock;
98 };
99
100 typedef struct _GstFFMpegDemuxClass GstFFMpegDemuxClass;
101
102 struct _GstFFMpegDemuxClass
103 {
104   GstElementClass parent_class;
105
106   AVInputFormat *in_plugin;
107   GstPadTemplate *sinktempl;
108   GstPadTemplate *videosrctempl;
109   GstPadTemplate *audiosrctempl;
110 };
111
112 /* A number of function prototypes are given so we can refer to them later. */
113 static void gst_ffmpegdemux_class_init (GstFFMpegDemuxClass * klass);
114 static void gst_ffmpegdemux_base_init (GstFFMpegDemuxClass * klass);
115 static void gst_ffmpegdemux_init (GstFFMpegDemux * demux);
116 static void gst_ffmpegdemux_finalize (GObject * object);
117
118 static gboolean gst_ffmpegdemux_sink_event (GstPad * sinkpad,
119     GstObject * parent, GstEvent * event);
120 static GstFlowReturn gst_ffmpegdemux_chain (GstPad * sinkpad,
121     GstObject * parent, GstBuffer * buf);
122
123 static void gst_ffmpegdemux_loop (GstFFMpegDemux * demux);
124 static gboolean gst_ffmpegdemux_sink_activate (GstPad * sinkpad,
125     GstObject * parent);
126 static gboolean gst_ffmpegdemux_sink_activate_mode (GstPad * sinkpad,
127     GstObject * parent, GstPadMode mode, gboolean active);
128
129 #if 0
130 static gboolean
131 gst_ffmpegdemux_src_convert (GstPad * pad,
132     GstFormat src_fmt,
133     gint64 src_value, GstFormat * dest_fmt, gint64 * dest_value);
134 #endif
135 static gboolean
136 gst_ffmpegdemux_send_event (GstElement * element, GstEvent * event);
137 static GstStateChangeReturn
138 gst_ffmpegdemux_change_state (GstElement * element, GstStateChange transition);
139
140 #define GST_FFDEMUX_PARAMS_QDATA g_quark_from_static_string("avdemux-params")
141
142 static GstElementClass *parent_class = NULL;
143
144 static const gchar *
145 gst_ffmpegdemux_averror (gint av_errno)
146 {
147   const gchar *message = NULL;
148
149   switch (av_errno) {
150     case AVERROR (EINVAL):
151       message = "Unknown error";
152       break;
153     case AVERROR (EIO):
154       message = "Input/output error";
155       break;
156     case AVERROR (EDOM):
157       message = "Number syntax expected in filename";
158       break;
159     case AVERROR (ENOMEM):
160       message = "Not enough memory";
161       break;
162     case AVERROR (EILSEQ):
163       message = "Unknown format";
164       break;
165     case AVERROR (ENOSYS):
166       message = "Operation not supported";
167       break;
168     default:
169       message = "Unhandled error code received";
170       break;
171   }
172
173   return message;
174 }
175
176 static void
177 gst_ffmpegdemux_base_init (GstFFMpegDemuxClass * klass)
178 {
179   GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
180   AVInputFormat *in_plugin;
181   gchar *p, *name;
182   GstCaps *sinkcaps;
183   GstPadTemplate *sinktempl, *audiosrctempl, *videosrctempl;
184   gchar *longname, *description;
185
186   in_plugin = (AVInputFormat *)
187       g_type_get_qdata (G_OBJECT_CLASS_TYPE (klass), GST_FFDEMUX_PARAMS_QDATA);
188   g_assert (in_plugin != NULL);
189
190   p = name = g_strdup (in_plugin->name);
191   while (*p) {
192     if (*p == '.' || *p == ',')
193       *p = '_';
194     p++;
195   }
196
197   /* construct the element details struct */
198   longname = g_strdup_printf ("libav %s demuxer", in_plugin->long_name);
199   description = g_strdup_printf ("libav %s demuxer", in_plugin->long_name);
200   gst_element_class_set_metadata (element_class, longname,
201       "Codec/Demuxer", description,
202       "Wim Taymans <wim@fluendo.com>, "
203       "Ronald Bultje <rbultje@ronald.bitfreak.net>, "
204       "Edward Hervey <bilboed@bilboed.com>");
205   g_free (longname);
206   g_free (description);
207
208   /* pad templates */
209   sinkcaps = gst_ffmpeg_formatid_to_caps (name);
210   sinktempl = gst_pad_template_new ("sink",
211       GST_PAD_SINK, GST_PAD_ALWAYS, sinkcaps);
212   videosrctempl = gst_pad_template_new ("video_%u",
213       GST_PAD_SRC, GST_PAD_SOMETIMES, GST_CAPS_ANY);
214   audiosrctempl = gst_pad_template_new ("audio_%u",
215       GST_PAD_SRC, GST_PAD_SOMETIMES, GST_CAPS_ANY);
216
217   gst_element_class_add_pad_template (element_class, videosrctempl);
218   gst_element_class_add_pad_template (element_class, audiosrctempl);
219   gst_element_class_add_pad_template (element_class, sinktempl);
220
221   klass->in_plugin = in_plugin;
222   klass->videosrctempl = videosrctempl;
223   klass->audiosrctempl = audiosrctempl;
224   klass->sinktempl = sinktempl;
225 }
226
227 static void
228 gst_ffmpegdemux_class_init (GstFFMpegDemuxClass * klass)
229 {
230   GObjectClass *gobject_class;
231   GstElementClass *gstelement_class;
232
233   gobject_class = (GObjectClass *) klass;
234   gstelement_class = (GstElementClass *) klass;
235
236   parent_class = g_type_class_peek_parent (klass);
237
238   gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_ffmpegdemux_finalize);
239
240   gstelement_class->change_state = gst_ffmpegdemux_change_state;
241   gstelement_class->send_event = gst_ffmpegdemux_send_event;
242 }
243
244 static void
245 gst_ffmpegdemux_init (GstFFMpegDemux * demux)
246 {
247   GstFFMpegDemuxClass *oclass =
248       (GstFFMpegDemuxClass *) (G_OBJECT_GET_CLASS (demux));
249   gint n;
250
251   demux->sinkpad = gst_pad_new_from_template (oclass->sinktempl, "sink");
252   gst_pad_set_activate_function (demux->sinkpad,
253       GST_DEBUG_FUNCPTR (gst_ffmpegdemux_sink_activate));
254   gst_pad_set_activatemode_function (demux->sinkpad,
255       GST_DEBUG_FUNCPTR (gst_ffmpegdemux_sink_activate_mode));
256   gst_element_add_pad (GST_ELEMENT (demux), demux->sinkpad);
257
258   /* push based setup */
259   /* the following are not used in pull-based mode, so safe to set anyway */
260   gst_pad_set_event_function (demux->sinkpad,
261       GST_DEBUG_FUNCPTR (gst_ffmpegdemux_sink_event));
262   gst_pad_set_chain_function (demux->sinkpad,
263       GST_DEBUG_FUNCPTR (gst_ffmpegdemux_chain));
264   /* task for driving ffmpeg in loop function */
265   demux->task =
266       gst_task_new ((GstTaskFunction) gst_ffmpegdemux_loop, demux, NULL);
267   g_rec_mutex_init (&demux->task_lock);
268   gst_task_set_lock (demux->task, &demux->task_lock);
269
270   demux->have_group_id = FALSE;
271   demux->group_id = G_MAXUINT;
272
273   demux->opened = FALSE;
274   demux->context = NULL;
275
276   for (n = 0; n < MAX_STREAMS; n++) {
277     demux->streams[n] = NULL;
278   }
279   demux->videopads = 0;
280   demux->audiopads = 0;
281
282   demux->seek_event = NULL;
283   gst_segment_init (&demux->segment, GST_FORMAT_TIME);
284
285   /* push based data */
286   g_mutex_init (&demux->ffpipe.tlock);
287   g_cond_init (&demux->ffpipe.cond);
288   demux->ffpipe.adapter = gst_adapter_new ();
289
290   /* blacklist unreliable push-based demuxers */
291   if (strcmp (oclass->in_plugin->name, "ape"))
292     demux->can_push = TRUE;
293   else
294     demux->can_push = FALSE;
295 }
296
297 static void
298 gst_ffmpegdemux_finalize (GObject * object)
299 {
300   GstFFMpegDemux *demux;
301
302   demux = (GstFFMpegDemux *) object;
303
304   g_mutex_clear (&demux->ffpipe.tlock);
305   g_cond_clear (&demux->ffpipe.cond);
306   gst_object_unref (demux->ffpipe.adapter);
307
308   gst_object_unref (demux->task);
309   g_rec_mutex_clear (&demux->task_lock);
310
311   G_OBJECT_CLASS (parent_class)->finalize (object);
312 }
313
314 static void
315 gst_ffmpegdemux_close (GstFFMpegDemux * demux)
316 {
317   gint n;
318   GstEvent **event_p;
319
320   if (!demux->opened)
321     return;
322
323   /* remove pads from ourselves */
324   for (n = 0; n < MAX_STREAMS; n++) {
325     GstFFStream *stream;
326
327     stream = demux->streams[n];
328     if (stream) {
329       if (stream->pad)
330         gst_element_remove_pad (GST_ELEMENT (demux), stream->pad);
331       if (stream->tags)
332         gst_tag_list_unref (stream->tags);
333       g_free (stream);
334     }
335     demux->streams[n] = NULL;
336   }
337   demux->videopads = 0;
338   demux->audiopads = 0;
339
340   /* close demuxer context from ffmpeg */
341   if (demux->seekable)
342     gst_ffmpegdata_close (demux->context->pb);
343   else
344     gst_ffmpeg_pipe_close (demux->context->pb);
345   demux->context->pb = NULL;
346   avformat_close_input (&demux->context);
347   if (demux->context)
348     avformat_free_context (demux->context);
349   demux->context = NULL;
350
351   GST_OBJECT_LOCK (demux);
352   demux->opened = FALSE;
353   event_p = &demux->seek_event;
354   gst_event_replace (event_p, NULL);
355   GST_OBJECT_UNLOCK (demux);
356
357   gst_segment_init (&demux->segment, GST_FORMAT_TIME);
358 }
359
360 /* send an event to all the source pads .
361  * Takes ownership of the event.
362  *
363  * Returns FALSE if none of the source pads handled the event.
364  */
365 static gboolean
366 gst_ffmpegdemux_push_event (GstFFMpegDemux * demux, GstEvent * event)
367 {
368   gboolean res;
369   gint n;
370
371   res = TRUE;
372
373   for (n = 0; n < MAX_STREAMS; n++) {
374     GstFFStream *s = demux->streams[n];
375
376     if (s && s->pad) {
377       gst_event_ref (event);
378       res &= gst_pad_push_event (s->pad, event);
379     }
380   }
381   gst_event_unref (event);
382
383   return res;
384 }
385
386 /* set flags on all streams */
387 static void
388 gst_ffmpegdemux_set_flags (GstFFMpegDemux * demux, gboolean discont,
389     gboolean eos)
390 {
391   GstFFStream *s;
392   gint n;
393
394   for (n = 0; n < MAX_STREAMS; n++) {
395     if ((s = demux->streams[n])) {
396       s->discont = discont;
397       s->eos = eos;
398     }
399   }
400 }
401
402 /* check if all streams are eos */
403 static gboolean
404 gst_ffmpegdemux_is_eos (GstFFMpegDemux * demux)
405 {
406   GstFFStream *s;
407   gint n;
408
409   for (n = 0; n < MAX_STREAMS; n++) {
410     if ((s = demux->streams[n])) {
411       GST_DEBUG ("stream %d %p eos:%d", n, s, s->eos);
412       if (!s->eos)
413         return FALSE;
414     }
415   }
416   return TRUE;
417 }
418
419 /* Returns True if we at least outputted one buffer */
420 static gboolean
421 gst_ffmpegdemux_has_outputted (GstFFMpegDemux * demux)
422 {
423   GstFFStream *s;
424   gint n;
425
426   for (n = 0; n < MAX_STREAMS; n++) {
427     if ((s = demux->streams[n])) {
428       if (GST_CLOCK_TIME_IS_VALID (s->last_ts))
429         return TRUE;
430     }
431   }
432   return FALSE;
433 }
434
435 static gboolean
436 gst_ffmpegdemux_do_seek (GstFFMpegDemux * demux, GstSegment * segment)
437 {
438   gboolean ret;
439   gint seekret;
440   gint64 target;
441   gint64 fftarget;
442   AVStream *stream;
443   gint index;
444
445   /* find default index and fail if none is present */
446   index = av_find_default_stream_index (demux->context);
447   GST_LOG_OBJECT (demux, "default stream index %d", index);
448   if (index < 0)
449     return FALSE;
450
451   ret = TRUE;
452
453   /* get the stream for seeking */
454   stream = demux->context->streams[index];
455   /* initial seek position */
456   target = segment->position;
457   /* convert target to ffmpeg time */
458   fftarget = gst_ffmpeg_time_gst_to_ff (target, stream->time_base);
459
460   GST_LOG_OBJECT (demux, "do seek to time %" GST_TIME_FORMAT,
461       GST_TIME_ARGS (target));
462
463   /* if we need to land on a keyframe, try to do so, we don't try to do a 
464    * keyframe seek if we are not absolutely sure we have an index.*/
465   if (segment->flags & GST_SEEK_FLAG_KEY_UNIT) {
466     gint keyframeidx;
467
468     GST_LOG_OBJECT (demux, "looking for keyframe in ffmpeg for time %"
469         GST_TIME_FORMAT, GST_TIME_ARGS (target));
470
471     /* search in the index for the previous keyframe */
472     keyframeidx =
473         av_index_search_timestamp (stream, fftarget, AVSEEK_FLAG_BACKWARD);
474
475     GST_LOG_OBJECT (demux, "keyframeidx: %d", keyframeidx);
476
477     if (keyframeidx >= 0) {
478       fftarget = stream->index_entries[keyframeidx].timestamp;
479       target = gst_ffmpeg_time_ff_to_gst (fftarget, stream->time_base);
480
481       GST_LOG_OBJECT (demux,
482           "Found a keyframe at ffmpeg idx: %d timestamp :%" GST_TIME_FORMAT,
483           keyframeidx, GST_TIME_ARGS (target));
484     }
485   }
486
487   GST_DEBUG_OBJECT (demux,
488       "About to call av_seek_frame (context, %d, %" G_GINT64_FORMAT
489       ", 0) for time %" GST_TIME_FORMAT, index, fftarget,
490       GST_TIME_ARGS (target));
491
492   if ((seekret =
493           av_seek_frame (demux->context, index, fftarget,
494               AVSEEK_FLAG_BACKWARD)) < 0)
495     goto seek_failed;
496
497   GST_DEBUG_OBJECT (demux, "seek success, returned %d", seekret);
498
499   segment->position = target;
500   segment->time = target;
501   segment->start = target;
502
503   return ret;
504
505   /* ERRORS */
506 seek_failed:
507   {
508     GST_WARNING_OBJECT (demux, "Call to av_seek_frame failed : %d", seekret);
509     return FALSE;
510   }
511 }
512
513 static gboolean
514 gst_ffmpegdemux_perform_seek (GstFFMpegDemux * demux, GstEvent * event)
515 {
516   gboolean res;
517   gdouble rate;
518   GstFormat format;
519   GstSeekFlags flags;
520   GstSeekType cur_type, stop_type;
521   gint64 cur, stop;
522   gboolean flush;
523   gboolean update;
524   GstSegment seeksegment;
525
526   if (!demux->seekable) {
527     GST_DEBUG_OBJECT (demux, "in push mode; ignoring seek");
528     return FALSE;
529   }
530
531   GST_DEBUG_OBJECT (demux, "starting seek");
532
533   if (event) {
534     gst_event_parse_seek (event, &rate, &format, &flags,
535         &cur_type, &cur, &stop_type, &stop);
536
537     /* we have to have a format as the segment format. Try to convert
538      * if not. */
539     if (demux->segment.format != format) {
540       GstFormat fmt;
541
542       fmt = demux->segment.format;
543       res = TRUE;
544       /* FIXME, use source pad */
545       if (cur_type != GST_SEEK_TYPE_NONE && cur != -1)
546         res = gst_pad_query_convert (demux->sinkpad, format, cur, fmt, &cur);
547       if (res && stop_type != GST_SEEK_TYPE_NONE && stop != -1)
548         res = gst_pad_query_convert (demux->sinkpad, format, stop, fmt, &stop);
549       if (!res)
550         goto no_format;
551
552       format = fmt;
553     }
554   } else {
555     flags = 0;
556   }
557
558   flush = flags & GST_SEEK_FLAG_FLUSH;
559
560   /* send flush start */
561   if (flush) {
562     /* mark flushing so that the streaming thread can react on it */
563     GST_OBJECT_LOCK (demux);
564     demux->flushing = TRUE;
565     GST_OBJECT_UNLOCK (demux);
566     gst_pad_push_event (demux->sinkpad, gst_event_new_flush_start ());
567     gst_ffmpegdemux_push_event (demux, gst_event_new_flush_start ());
568   } else {
569     gst_pad_pause_task (demux->sinkpad);
570   }
571
572   /* grab streaming lock, this should eventually be possible, either
573    * because the task is paused or our streaming thread stopped
574    * because our peer is flushing. */
575   GST_PAD_STREAM_LOCK (demux->sinkpad);
576
577   /* make copy into temp structure, we can only update the main one
578    * when we actually could do the seek. */
579   memcpy (&seeksegment, &demux->segment, sizeof (GstSegment));
580
581   /* now configure the seek segment */
582   if (event) {
583     gst_segment_do_seek (&seeksegment, rate, format, flags,
584         cur_type, cur, stop_type, stop, &update);
585   }
586
587   GST_DEBUG_OBJECT (demux, "segment configured from %" G_GINT64_FORMAT
588       " to %" G_GINT64_FORMAT ", position %" G_GINT64_FORMAT,
589       seeksegment.start, seeksegment.stop, seeksegment.position);
590
591   /* make the sinkpad available for data passing since we might need
592    * it when doing the seek */
593   if (flush) {
594     GST_OBJECT_LOCK (demux);
595     demux->flushing = FALSE;
596     GST_OBJECT_UNLOCK (demux);
597     gst_pad_push_event (demux->sinkpad, gst_event_new_flush_stop (TRUE));
598   }
599
600   /* do the seek, segment.position contains new position. */
601   res = gst_ffmpegdemux_do_seek (demux, &seeksegment);
602
603   /* and prepare to continue streaming */
604   if (flush) {
605     gint n;
606
607     /* send flush stop, peer will accept data and events again. We
608      * are not yet providing data as we still have the STREAM_LOCK. */
609     gst_ffmpegdemux_push_event (demux, gst_event_new_flush_stop (TRUE));
610     for (n = 0; n < MAX_STREAMS; ++n) {
611       if (demux->streams[n])
612         demux->streams[n]->last_flow = GST_FLOW_OK;
613     }
614   }
615   /* if successfull seek, we update our real segment and push
616    * out the new segment. */
617   if (res) {
618     memcpy (&demux->segment, &seeksegment, sizeof (GstSegment));
619
620     if (demux->segment.flags & GST_SEEK_FLAG_SEGMENT) {
621       gst_element_post_message (GST_ELEMENT (demux),
622           gst_message_new_segment_start (GST_OBJECT (demux),
623               demux->segment.format, demux->segment.position));
624     }
625
626     /* now send the newsegment, FIXME, do this from the streaming thread */
627     GST_DEBUG_OBJECT (demux, "Sending newsegment %" GST_SEGMENT_FORMAT,
628         &demux->segment);
629
630     gst_ffmpegdemux_push_event (demux, gst_event_new_segment (&demux->segment));
631   }
632
633   /* Mark discont on all srcpads and remove eos */
634   gst_ffmpegdemux_set_flags (demux, TRUE, FALSE);
635
636   /* and restart the task in case it got paused explicitely or by
637    * the FLUSH_START event we pushed out. */
638   gst_pad_start_task (demux->sinkpad, (GstTaskFunction) gst_ffmpegdemux_loop,
639       demux->sinkpad, NULL);
640
641   /* and release the lock again so we can continue streaming */
642   GST_PAD_STREAM_UNLOCK (demux->sinkpad);
643
644   return res;
645
646   /* ERROR */
647 no_format:
648   {
649     GST_DEBUG_OBJECT (demux, "undefined format given, seek aborted.");
650     return FALSE;
651   }
652 }
653
654 static gboolean
655 gst_ffmpegdemux_src_event (GstPad * pad, GstObject * parent, GstEvent * event)
656 {
657   GstFFMpegDemux *demux;
658   gboolean res = TRUE;
659
660   demux = (GstFFMpegDemux *) parent;
661
662   switch (GST_EVENT_TYPE (event)) {
663     case GST_EVENT_SEEK:
664       res = gst_ffmpegdemux_perform_seek (demux, event);
665       gst_event_unref (event);
666       break;
667     case GST_EVENT_LATENCY:
668       res = gst_pad_push_event (demux->sinkpad, event);
669       break;
670     case GST_EVENT_NAVIGATION:
671     case GST_EVENT_QOS:
672     default:
673       res = FALSE;
674       gst_event_unref (event);
675       break;
676   }
677
678   return res;
679 }
680
681 static gboolean
682 gst_ffmpegdemux_send_event (GstElement * element, GstEvent * event)
683 {
684   GstFFMpegDemux *demux = (GstFFMpegDemux *) (element);
685   gboolean res;
686
687   switch (GST_EVENT_TYPE (event)) {
688     case GST_EVENT_SEEK:
689       GST_OBJECT_LOCK (demux);
690       if (!demux->opened) {
691         GstEvent **event_p;
692
693         GST_DEBUG_OBJECT (demux, "caching seek event");
694         event_p = &demux->seek_event;
695         gst_event_replace (event_p, event);
696         GST_OBJECT_UNLOCK (demux);
697
698         res = TRUE;
699       } else {
700         GST_OBJECT_UNLOCK (demux);
701         res = gst_ffmpegdemux_perform_seek (demux, event);
702         gst_event_unref (event);
703       }
704       break;
705     default:
706       res = FALSE;
707       break;
708   }
709
710   return res;
711 }
712
713 static gboolean
714 gst_ffmpegdemux_src_query (GstPad * pad, GstObject * parent, GstQuery * query)
715 {
716   GstFFMpegDemux *demux;
717   GstFFStream *stream;
718   AVStream *avstream;
719   gboolean res = FALSE;
720
721   if (!(stream = gst_pad_get_element_private (pad)))
722     return FALSE;
723
724   avstream = stream->avstream;
725
726   demux = (GstFFMpegDemux *) parent;
727
728   switch (GST_QUERY_TYPE (query)) {
729     case GST_QUERY_POSITION:
730     {
731       GstFormat format;
732       gint64 timeposition;
733
734       gst_query_parse_position (query, &format, NULL);
735
736       timeposition = stream->last_ts;
737       if (!(GST_CLOCK_TIME_IS_VALID (timeposition)))
738         break;
739
740       switch (format) {
741         case GST_FORMAT_TIME:
742           gst_query_set_position (query, GST_FORMAT_TIME, timeposition);
743           res = TRUE;
744           break;
745         case GST_FORMAT_DEFAULT:
746           gst_query_set_position (query, GST_FORMAT_DEFAULT,
747               gst_util_uint64_scale (timeposition, avstream->avg_frame_rate.num,
748                   GST_SECOND * avstream->avg_frame_rate.den));
749           res = TRUE;
750           break;
751         case GST_FORMAT_BYTES:
752           if (demux->videopads + demux->audiopads == 1 &&
753               GST_PAD_PEER (demux->sinkpad) != NULL)
754             res = gst_pad_query_default (pad, parent, query);
755           break;
756         default:
757           break;
758       }
759     }
760       break;
761     case GST_QUERY_DURATION:
762     {
763       GstFormat format;
764       gint64 timeduration;
765
766       gst_query_parse_duration (query, &format, NULL);
767
768       timeduration =
769           gst_ffmpeg_time_ff_to_gst (avstream->duration, avstream->time_base);
770       if (!(GST_CLOCK_TIME_IS_VALID (timeduration))) {
771         /* use duration of complete file if the stream duration is not known */
772         timeduration = demux->duration;
773         if (!(GST_CLOCK_TIME_IS_VALID (timeduration)))
774           break;
775       }
776
777       switch (format) {
778         case GST_FORMAT_TIME:
779           gst_query_set_duration (query, GST_FORMAT_TIME, timeduration);
780           res = TRUE;
781           break;
782         case GST_FORMAT_DEFAULT:
783           gst_query_set_duration (query, GST_FORMAT_DEFAULT,
784               gst_util_uint64_scale (timeduration, avstream->avg_frame_rate.num,
785                   GST_SECOND * avstream->avg_frame_rate.den));
786           res = TRUE;
787           break;
788         case GST_FORMAT_BYTES:
789           if (demux->videopads + demux->audiopads == 1 &&
790               GST_PAD_PEER (demux->sinkpad) != NULL)
791             res = gst_pad_query_default (pad, parent, query);
792           break;
793         default:
794           break;
795       }
796     }
797       break;
798     case GST_QUERY_SEEKING:{
799       GstFormat format;
800       gboolean seekable;
801       gint64 dur = -1;
802
803       gst_query_parse_seeking (query, &format, NULL, NULL, NULL);
804       seekable = demux->seekable;
805       if (!gst_pad_query_duration (pad, format, &dur)) {
806         /* unlikely that we don't know duration but can seek */
807         seekable = FALSE;
808         dur = -1;
809       }
810       gst_query_set_seeking (query, format, seekable, 0, dur);
811       res = TRUE;
812       break;
813     }
814     case GST_QUERY_SEGMENT:{
815       GstFormat format;
816       gint64 start, stop;
817
818       format = demux->segment.format;
819
820       start =
821           gst_segment_to_stream_time (&demux->segment, format,
822           demux->segment.start);
823       if ((stop = demux->segment.stop) == -1)
824         stop = demux->segment.duration;
825       else
826         stop = gst_segment_to_stream_time (&demux->segment, format, stop);
827
828       gst_query_set_segment (query, demux->segment.rate, format, start, stop);
829       res = TRUE;
830       break;
831     }
832     default:
833       /* FIXME : ADD GST_QUERY_CONVERT */
834       res = gst_pad_query_default (pad, parent, query);
835       break;
836   }
837
838   return res;
839 }
840
841 #if 0
842 /* FIXME, reenable me */
843 static gboolean
844 gst_ffmpegdemux_src_convert (GstPad * pad,
845     GstFormat src_fmt,
846     gint64 src_value, GstFormat * dest_fmt, gint64 * dest_value)
847 {
848   GstFFStream *stream;
849   gboolean res = TRUE;
850   AVStream *avstream;
851
852   if (!(stream = gst_pad_get_element_private (pad)))
853     return FALSE;
854
855   avstream = stream->avstream;
856   if (avstream->codec->codec_type != AVMEDIA_TYPE_VIDEO)
857     return FALSE;
858
859   switch (src_fmt) {
860     case GST_FORMAT_TIME:
861       switch (*dest_fmt) {
862         case GST_FORMAT_DEFAULT:
863           *dest_value = gst_util_uint64_scale (src_value,
864               avstream->avg_frame_rate.num,
865               GST_SECOND * avstream->avg_frame_rate.den);
866           break;
867         default:
868           res = FALSE;
869           break;
870       }
871       break;
872     case GST_FORMAT_DEFAULT:
873       switch (*dest_fmt) {
874         case GST_FORMAT_TIME:
875           *dest_value = gst_util_uint64_scale (src_value,
876               GST_SECOND * avstream->avg_frame_rate.num,
877               avstream->avg_frame_rate.den);
878           break;
879         default:
880           res = FALSE;
881           break;
882       }
883       break;
884     default:
885       res = FALSE;
886       break;
887   }
888
889   return res;
890 }
891 #endif
892
893 static GstFlowReturn
894 gst_ffmpegdemux_aggregated_flow (GstFFMpegDemux * demux)
895 {
896   gint n;
897   GstFlowReturn res = GST_FLOW_OK;
898   gboolean have_ok = FALSE;
899
900   for (n = 0; n < MAX_STREAMS; n++) {
901     GstFFStream *s = demux->streams[n];
902
903     if (s) {
904       res = MIN (res, s->last_flow);
905
906       if (s->last_flow == GST_FLOW_OK)
907         have_ok = TRUE;
908     }
909   }
910
911   /* NOT_LINKED is OK, if at least one pad is linked */
912   if (res == GST_FLOW_NOT_LINKED && have_ok)
913     res = GST_FLOW_OK;
914
915   GST_DEBUG_OBJECT (demux, "Returning aggregated value of %s",
916       gst_flow_get_name (res));
917
918   return res;
919 }
920
921 static gchar *
922 gst_ffmpegdemux_create_padname (const gchar * templ, gint n)
923 {
924   GString *string;
925
926   /* FIXME, we just want to printf the number according to the template but
927    * then the format string is not a literal and we can't check arguments and
928    * this generates a compiler error */
929   string = g_string_new (templ);
930   g_string_truncate (string, string->len - 2);
931   g_string_append_printf (string, "%u", n);
932
933   return g_string_free (string, FALSE);
934 }
935
936 static GstFFStream *
937 gst_ffmpegdemux_get_stream (GstFFMpegDemux * demux, AVStream * avstream)
938 {
939   GstFFMpegDemuxClass *oclass;
940   GstPadTemplate *templ = NULL;
941   GstPad *pad;
942   GstCaps *caps;
943   gint num;
944   gchar *padname;
945   const gchar *codec;
946   AVCodecContext *ctx;
947   GstFFStream *stream;
948   GstEvent *event;
949   gchar *stream_id;
950
951   ctx = avstream->codec;
952
953   oclass = (GstFFMpegDemuxClass *) G_OBJECT_GET_CLASS (demux);
954
955   if (demux->streams[avstream->index] != NULL)
956     goto exists;
957
958   /* create new stream */
959   stream = g_new0 (GstFFStream, 1);
960   demux->streams[avstream->index] = stream;
961
962   /* mark stream as unknown */
963   stream->unknown = TRUE;
964   stream->discont = TRUE;
965   stream->avstream = avstream;
966   stream->last_ts = GST_CLOCK_TIME_NONE;
967   stream->last_flow = GST_FLOW_OK;
968   stream->tags = NULL;
969
970   switch (ctx->codec_type) {
971     case AVMEDIA_TYPE_VIDEO:
972       templ = oclass->videosrctempl;
973       num = demux->videopads++;
974       break;
975     case AVMEDIA_TYPE_AUDIO:
976       templ = oclass->audiosrctempl;
977       num = demux->audiopads++;
978       break;
979     default:
980       goto unknown_type;
981   }
982
983   /* get caps that belongs to this stream */
984   caps = gst_ffmpeg_codecid_to_caps (ctx->codec_id, ctx, TRUE);
985   if (caps == NULL)
986     goto unknown_caps;
987
988   /* stream is known now */
989   stream->unknown = FALSE;
990
991   /* create new pad for this stream */
992   padname =
993       gst_ffmpegdemux_create_padname (GST_PAD_TEMPLATE_NAME_TEMPLATE (templ),
994       num);
995   pad = gst_pad_new_from_template (templ, padname);
996   g_free (padname);
997
998   gst_pad_use_fixed_caps (pad);
999   gst_pad_set_active (pad, TRUE);
1000
1001   gst_pad_set_query_function (pad, gst_ffmpegdemux_src_query);
1002   gst_pad_set_event_function (pad, gst_ffmpegdemux_src_event);
1003
1004   /* store pad internally */
1005   stream->pad = pad;
1006   gst_pad_set_element_private (pad, stream);
1007
1008   /* transform some useful info to GstClockTime and remember */
1009   {
1010     GstClockTime tmp;
1011
1012     /* FIXME, actually use the start_time in some way */
1013     tmp = gst_ffmpeg_time_ff_to_gst (avstream->start_time, avstream->time_base);
1014     GST_DEBUG_OBJECT (demux, "stream %d: start time: %" GST_TIME_FORMAT,
1015         avstream->index, GST_TIME_ARGS (tmp));
1016
1017     tmp = gst_ffmpeg_time_ff_to_gst (avstream->duration, avstream->time_base);
1018     GST_DEBUG_OBJECT (demux, "stream %d: duration: %" GST_TIME_FORMAT,
1019         avstream->index, GST_TIME_ARGS (tmp));
1020   }
1021
1022   demux->streams[avstream->index] = stream;
1023
1024
1025   stream_id =
1026       gst_pad_create_stream_id_printf (pad, GST_ELEMENT_CAST (demux), "%03u",
1027       avstream->index);
1028
1029   event = gst_pad_get_sticky_event (demux->sinkpad, GST_EVENT_STREAM_START, 0);
1030   if (event) {
1031     if (gst_event_parse_group_id (event, &demux->group_id))
1032       demux->have_group_id = TRUE;
1033     else
1034       demux->have_group_id = FALSE;
1035     gst_event_unref (event);
1036   } else if (!demux->have_group_id) {
1037     demux->have_group_id = TRUE;
1038     demux->group_id = gst_util_group_id_next ();
1039   }
1040   event = gst_event_new_stream_start (stream_id);
1041   if (demux->have_group_id)
1042     gst_event_set_group_id (event, demux->group_id);
1043
1044   gst_pad_push_event (pad, event);
1045   g_free (stream_id);
1046
1047   GST_INFO_OBJECT (pad, "adding pad with caps %" GST_PTR_FORMAT, caps);
1048   gst_pad_set_caps (pad, caps);
1049   gst_caps_unref (caps);
1050
1051   /* activate and add */
1052   gst_element_add_pad (GST_ELEMENT (demux), pad);
1053
1054   /* metadata */
1055   if ((codec = gst_ffmpeg_get_codecid_longname (ctx->codec_id))) {
1056     stream->tags = gst_tag_list_new_empty ();
1057
1058     gst_tag_list_add (stream->tags, GST_TAG_MERGE_REPLACE,
1059         (ctx->codec_type == AVMEDIA_TYPE_VIDEO) ?
1060         GST_TAG_VIDEO_CODEC : GST_TAG_AUDIO_CODEC, codec, NULL);
1061   }
1062
1063   return stream;
1064
1065   /* ERRORS */
1066 exists:
1067   {
1068     GST_DEBUG_OBJECT (demux, "Pad existed (stream %d)", avstream->index);
1069     return demux->streams[avstream->index];
1070   }
1071 unknown_type:
1072   {
1073     GST_WARNING_OBJECT (demux, "Unknown pad type %d", ctx->codec_type);
1074     return stream;
1075   }
1076 unknown_caps:
1077   {
1078     GST_WARNING_OBJECT (demux, "Unknown caps for codec %d", ctx->codec_id);
1079     return stream;
1080   }
1081 }
1082
1083 #if 0
1084     /* Re-enable once converted to new AVMetaData API
1085      * See #566605
1086      */
1087 static gchar *
1088 my_safe_copy (gchar * input)
1089 {
1090   gchar *output;
1091
1092   if (!(g_utf8_validate (input, -1, NULL))) {
1093     output = g_convert (input, strlen (input),
1094         "UTF-8", "ISO-8859-1", NULL, NULL, NULL);
1095   } else {
1096     output = g_strdup (input);
1097   }
1098
1099   return output;
1100 }
1101
1102 static GstTagList *
1103 gst_ffmpegdemux_read_tags (GstFFMpegDemux * demux)
1104 {
1105   GstTagList *tlist;
1106   gboolean hastag = FALSE;
1107
1108   tlist = gst_tag_list_new ();
1109
1110   if (*demux->context->title) {
1111     gst_tag_list_add (tlist, GST_TAG_MERGE_REPLACE,
1112         GST_TAG_TITLE, my_safe_copy (demux->context->title), NULL);
1113     hastag = TRUE;
1114   }
1115   if (*demux->context->author) {
1116     gst_tag_list_add (tlist, GST_TAG_MERGE_REPLACE,
1117         GST_TAG_ARTIST, my_safe_copy (demux->context->author), NULL);
1118     hastag = TRUE;
1119   }
1120   if (*demux->context->copyright) {
1121     gst_tag_list_add (tlist, GST_TAG_MERGE_REPLACE,
1122         GST_TAG_COPYRIGHT, my_safe_copy (demux->context->copyright), NULL);
1123     hastag = TRUE;
1124   }
1125   if (*demux->context->comment) {
1126     gst_tag_list_add (tlist, GST_TAG_MERGE_REPLACE,
1127         GST_TAG_COMMENT, my_safe_copy (demux->context->comment), NULL);
1128     hastag = TRUE;
1129   }
1130   if (*demux->context->album) {
1131     gst_tag_list_add (tlist, GST_TAG_MERGE_REPLACE,
1132         GST_TAG_ALBUM, my_safe_copy (demux->context->album), NULL);
1133     hastag = TRUE;
1134   }
1135   if (demux->context->track) {
1136     gst_tag_list_add (tlist, GST_TAG_MERGE_REPLACE,
1137         GST_TAG_TRACK_NUMBER, demux->context->track, NULL);
1138     hastag = TRUE;
1139   }
1140   if (*demux->context->genre) {
1141     gst_tag_list_add (tlist, GST_TAG_MERGE_REPLACE,
1142         GST_TAG_GENRE, my_safe_copy (demux->context->genre), NULL);
1143     hastag = TRUE;
1144   }
1145   if (demux->context->year) {
1146     gst_tag_list_add (tlist, GST_TAG_MERGE_REPLACE,
1147         GST_TAG_DATE, g_date_new_dmy (1, 1, demux->context->year), NULL);
1148     hastag = TRUE;
1149   }
1150
1151   if (!hastag) {
1152     gst_tag_list_unref (tlist);
1153     tlist = NULL;
1154   }
1155   return tlist;
1156 }
1157 #endif
1158
1159 static gboolean
1160 gst_ffmpegdemux_open (GstFFMpegDemux * demux)
1161 {
1162   AVIOContext *iocontext = NULL;
1163   GstFFMpegDemuxClass *oclass =
1164       (GstFFMpegDemuxClass *) G_OBJECT_GET_CLASS (demux);
1165   gint res, n_streams, i;
1166 #if 0
1167   /* Re-enable once converted to new AVMetaData API
1168    * See #566605
1169    */
1170   GstTagList *tags;
1171 #endif
1172   GstEvent *event;
1173   GList *cached_events;
1174
1175   /* to be sure... */
1176   gst_ffmpegdemux_close (demux);
1177
1178   /* open via our input protocol hack */
1179   if (demux->seekable)
1180     res = gst_ffmpegdata_open (demux->sinkpad, AVIO_FLAG_READ, &iocontext);
1181   else
1182     res = gst_ffmpeg_pipe_open (&demux->ffpipe, AVIO_FLAG_READ, &iocontext);
1183
1184   demux->context = avformat_alloc_context ();
1185   demux->context->pb = iocontext;
1186   res = avformat_open_input (&demux->context, NULL, oclass->in_plugin, NULL);
1187
1188   GST_DEBUG_OBJECT (demux, "av_open_input returned %d", res);
1189   if (res < 0)
1190     goto open_failed;
1191
1192   res = gst_ffmpeg_av_find_stream_info (demux->context);
1193   GST_DEBUG_OBJECT (demux, "av_find_stream_info returned %d", res);
1194   if (res < 0)
1195     goto no_info;
1196
1197   n_streams = demux->context->nb_streams;
1198   GST_DEBUG_OBJECT (demux, "we have %d streams", n_streams);
1199
1200   /* open_input_file() automatically reads the header. We can now map each
1201    * created AVStream to a GstPad to make GStreamer handle it. */
1202   for (i = 0; i < n_streams; i++) {
1203     gst_ffmpegdemux_get_stream (demux, demux->context->streams[i]);
1204   }
1205
1206   gst_element_no_more_pads (GST_ELEMENT (demux));
1207
1208   /* transform some useful info to GstClockTime and remember */
1209   demux->start_time = gst_util_uint64_scale_int (demux->context->start_time,
1210       GST_SECOND, AV_TIME_BASE);
1211   GST_DEBUG_OBJECT (demux, "start time: %" GST_TIME_FORMAT,
1212       GST_TIME_ARGS (demux->start_time));
1213   if (demux->context->duration > 0)
1214     demux->duration = gst_util_uint64_scale_int (demux->context->duration,
1215         GST_SECOND, AV_TIME_BASE);
1216   else
1217     demux->duration = GST_CLOCK_TIME_NONE;
1218
1219   GST_DEBUG_OBJECT (demux, "duration: %" GST_TIME_FORMAT,
1220       GST_TIME_ARGS (demux->duration));
1221
1222   /* store duration in the segment as well */
1223   demux->segment.duration = demux->duration;
1224
1225   GST_OBJECT_LOCK (demux);
1226   demux->opened = TRUE;
1227   event = demux->seek_event;
1228   demux->seek_event = NULL;
1229   cached_events = demux->cached_events;
1230   demux->cached_events = NULL;
1231   GST_OBJECT_UNLOCK (demux);
1232
1233   if (event) {
1234     gst_ffmpegdemux_perform_seek (demux, event);
1235     gst_event_unref (event);
1236   } else {
1237     GST_DEBUG_OBJECT (demux, "Sending segment %" GST_SEGMENT_FORMAT,
1238         &demux->segment);
1239     gst_ffmpegdemux_push_event (demux, gst_event_new_segment (&demux->segment));
1240   }
1241
1242   while (cached_events) {
1243     event = cached_events->data;
1244     GST_INFO_OBJECT (demux, "pushing cached event: %" GST_PTR_FORMAT, event);
1245     gst_ffmpegdemux_push_event (demux, event);
1246     cached_events = g_list_delete_link (cached_events, cached_events);
1247   }
1248
1249 #if 0
1250   /* Re-enable once converted to new AVMetaData API
1251    * See #566605
1252    */
1253   /* grab the global tags */
1254   tags = gst_ffmpegdemux_read_tags (demux);
1255   if (tags) {
1256     GST_INFO_OBJECT (demux, "global tags: %" GST_PTR_FORMAT, tags);
1257     gst_element_found_tags (GST_ELEMENT (demux), tags);
1258   }
1259 #endif
1260
1261   /* now handle the stream tags */
1262   for (i = 0; i < n_streams; i++) {
1263     GstFFStream *stream;
1264
1265     stream = gst_ffmpegdemux_get_stream (demux, demux->context->streams[i]);
1266     if (stream->tags != NULL && stream->pad != NULL) {
1267       GST_INFO_OBJECT (stream->pad, "stream tags: %" GST_PTR_FORMAT,
1268           stream->tags);
1269       gst_pad_push_event (stream->pad,
1270           gst_event_new_tag (gst_tag_list_ref (stream->tags)));
1271     }
1272   }
1273
1274   return TRUE;
1275
1276   /* ERRORS */
1277 open_failed:
1278   {
1279     GST_ELEMENT_ERROR (demux, LIBRARY, FAILED, (NULL),
1280         ("%s", gst_ffmpegdemux_averror (res)));
1281     return FALSE;
1282   }
1283 no_info:
1284   {
1285     GST_ELEMENT_ERROR (demux, LIBRARY, FAILED, (NULL),
1286         ("%s", gst_ffmpegdemux_averror (res)));
1287     return FALSE;
1288   }
1289 }
1290
1291 #define GST_FFMPEG_TYPE_FIND_SIZE 4096
1292 #define GST_FFMPEG_TYPE_FIND_MIN_SIZE 256
1293
1294 static void
1295 gst_ffmpegdemux_type_find (GstTypeFind * tf, gpointer priv)
1296 {
1297   const guint8 *data;
1298   AVInputFormat *in_plugin = (AVInputFormat *) priv;
1299   gint res = 0;
1300   guint64 length;
1301   GstCaps *sinkcaps;
1302
1303   /* We want GST_FFMPEG_TYPE_FIND_SIZE bytes, but if the file is shorter than
1304    * that we'll give it a try... */
1305   length = gst_type_find_get_length (tf);
1306   if (length == 0 || length > GST_FFMPEG_TYPE_FIND_SIZE)
1307     length = GST_FFMPEG_TYPE_FIND_SIZE;
1308
1309   /* The ffmpeg typefinders assume there's a certain minimum amount of data
1310    * and will happily do invalid memory access if there isn't, so let's just
1311    * skip the ffmpeg typefinders if the data available is too short
1312    * (in which case it's unlikely to be a media file anyway) */
1313   if (length < GST_FFMPEG_TYPE_FIND_MIN_SIZE) {
1314     GST_LOG ("not typefinding %" G_GUINT64_FORMAT " bytes, too short", length);
1315     return;
1316   }
1317
1318   GST_LOG ("typefinding %" G_GUINT64_FORMAT " bytes", length);
1319   if (in_plugin->read_probe &&
1320       (data = gst_type_find_peek (tf, 0, length)) != NULL) {
1321     AVProbeData probe_data;
1322
1323     probe_data.filename = "";
1324     probe_data.buf = (guint8 *) data;
1325     probe_data.buf_size = length;
1326
1327     res = in_plugin->read_probe (&probe_data);
1328     if (res > 0) {
1329       res = MAX (1, res * GST_TYPE_FIND_MAXIMUM / AVPROBE_SCORE_MAX);
1330       /* Restrict the probability for MPEG-TS streams, because there is
1331        * probably a better version in plugins-base, if the user has a recent
1332        * plugins-base (in fact we shouldn't even get here for ffmpeg mpegts or
1333        * mpegtsraw typefinders, since we blacklist them) */
1334       if (g_str_has_prefix (in_plugin->name, "mpegts"))
1335         res = MIN (res, GST_TYPE_FIND_POSSIBLE);
1336
1337       sinkcaps = gst_ffmpeg_formatid_to_caps (in_plugin->name);
1338
1339       GST_LOG ("libav typefinder '%s' suggests %" GST_PTR_FORMAT ", p=%u%%",
1340           in_plugin->name, sinkcaps, res);
1341
1342       gst_type_find_suggest (tf, res, sinkcaps);
1343       gst_caps_unref (sinkcaps);
1344     }
1345   }
1346 }
1347
1348 /* Task */
1349 static void
1350 gst_ffmpegdemux_loop (GstFFMpegDemux * demux)
1351 {
1352   GstFlowReturn ret;
1353   gint res;
1354   AVPacket pkt;
1355   GstPad *srcpad;
1356   GstFFStream *stream;
1357   AVStream *avstream;
1358   GstBuffer *outbuf = NULL;
1359   GstClockTime timestamp, duration;
1360   gint outsize;
1361   gboolean rawvideo;
1362
1363   /* open file if we didn't so already */
1364   if (!demux->opened)
1365     if (!gst_ffmpegdemux_open (demux))
1366       goto open_failed;
1367
1368   GST_DEBUG_OBJECT (demux, "about to read a frame");
1369
1370   /* read a frame */
1371   res = av_read_frame (demux->context, &pkt);
1372   if (res < 0)
1373     goto read_failed;
1374
1375   /* get the stream */
1376   stream =
1377       gst_ffmpegdemux_get_stream (demux,
1378       demux->context->streams[pkt.stream_index]);
1379
1380   /* check if we know the stream */
1381   if (stream->unknown)
1382     goto done;
1383
1384   /* get more stuff belonging to this stream */
1385   avstream = stream->avstream;
1386
1387   /* do timestamps, we do this first so that we can know when we
1388    * stepped over the segment stop position. */
1389   timestamp = gst_ffmpeg_time_ff_to_gst (pkt.pts, avstream->time_base);
1390   if (GST_CLOCK_TIME_IS_VALID (timestamp)) {
1391     stream->last_ts = timestamp;
1392   }
1393   duration = gst_ffmpeg_time_ff_to_gst (pkt.duration, avstream->time_base);
1394   if (G_UNLIKELY (!duration)) {
1395     GST_WARNING_OBJECT (demux, "invalid buffer duration, setting to NONE");
1396     duration = GST_CLOCK_TIME_NONE;
1397   }
1398
1399
1400   GST_DEBUG_OBJECT (demux,
1401       "pkt pts:%" GST_TIME_FORMAT
1402       " / size:%d / stream_index:%d / flags:%d / duration:%" GST_TIME_FORMAT
1403       " / pos:%" G_GINT64_FORMAT, GST_TIME_ARGS (timestamp), pkt.size,
1404       pkt.stream_index, pkt.flags, GST_TIME_ARGS (duration), (gint64) pkt.pos);
1405
1406   /* check start_time */
1407 #if 0
1408   if (demux->start_time != -1 && demux->start_time > timestamp)
1409     goto drop;
1410 #endif
1411
1412   if (GST_CLOCK_TIME_IS_VALID (timestamp))
1413     timestamp -= demux->start_time;
1414
1415   /* check if we ran outside of the segment */
1416   if (demux->segment.stop != -1 && timestamp > demux->segment.stop)
1417     goto drop;
1418
1419   /* prepare to push packet to peer */
1420   srcpad = stream->pad;
1421
1422   rawvideo = (avstream->codec->codec_type == AVMEDIA_TYPE_VIDEO &&
1423       avstream->codec->codec_id == AV_CODEC_ID_RAWVIDEO);
1424
1425   if (rawvideo)
1426     outsize = gst_ffmpeg_avpicture_get_size (avstream->codec->pix_fmt,
1427         avstream->codec->width, avstream->codec->height);
1428   else
1429     outsize = pkt.size;
1430
1431   outbuf = gst_buffer_new_and_alloc (outsize);
1432
1433   /* copy the data from packet into the target buffer
1434    * and do conversions for raw video packets */
1435   if (rawvideo) {
1436     AVPicture src, dst;
1437     const gchar *plugin_name =
1438         ((GstFFMpegDemuxClass *) (G_OBJECT_GET_CLASS (demux)))->in_plugin->name;
1439     GstMapInfo map;
1440
1441     if (strcmp (plugin_name, "gif") == 0) {
1442       src.data[0] = pkt.data;
1443       src.data[1] = NULL;
1444       src.data[2] = NULL;
1445       src.linesize[0] = avstream->codec->width * 3;;
1446     } else {
1447       GST_WARNING ("Unknown demuxer %s, no idea what to do", plugin_name);
1448       gst_ffmpeg_avpicture_fill (&src, pkt.data,
1449           avstream->codec->pix_fmt, avstream->codec->width,
1450           avstream->codec->height);
1451     }
1452
1453     gst_buffer_map (outbuf, &map, GST_MAP_WRITE);
1454     gst_ffmpeg_avpicture_fill (&dst, map.data,
1455         avstream->codec->pix_fmt, avstream->codec->width,
1456         avstream->codec->height);
1457
1458     av_picture_copy (&dst, &src, avstream->codec->pix_fmt,
1459         avstream->codec->width, avstream->codec->height);
1460     gst_buffer_unmap (outbuf, &map);
1461   } else {
1462     gst_buffer_fill (outbuf, 0, pkt.data, outsize);
1463   }
1464
1465   GST_BUFFER_TIMESTAMP (outbuf) = timestamp;
1466   GST_BUFFER_DURATION (outbuf) = duration;
1467
1468   /* mark keyframes */
1469   if (!(pkt.flags & AV_PKT_FLAG_KEY)) {
1470     GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_DELTA_UNIT);
1471   }
1472
1473   /* Mark discont */
1474   if (stream->discont) {
1475     GST_DEBUG_OBJECT (demux, "marking DISCONT");
1476     GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_DISCONT);
1477     stream->discont = FALSE;
1478   }
1479
1480   GST_DEBUG_OBJECT (demux,
1481       "Sending out buffer time:%" GST_TIME_FORMAT " size:%" G_GSIZE_FORMAT,
1482       GST_TIME_ARGS (timestamp), gst_buffer_get_size (outbuf));
1483
1484   ret = stream->last_flow = gst_pad_push (srcpad, outbuf);
1485
1486   /* if a pad is in e.g. WRONG_STATE, we want to pause to unlock the STREAM_LOCK */
1487   if ((ret != GST_FLOW_OK)
1488       && ((ret = gst_ffmpegdemux_aggregated_flow (demux)) != GST_FLOW_OK)) {
1489     GST_WARNING_OBJECT (demux, "stream_movi flow: %s / %s",
1490         gst_flow_get_name (stream->last_flow), gst_flow_get_name (ret));
1491     goto pause;
1492   }
1493
1494 done:
1495   /* can destroy the packet now */
1496   av_free_packet (&pkt);
1497
1498   return;
1499
1500   /* ERRORS */
1501 pause:
1502   {
1503     GST_LOG_OBJECT (demux, "pausing task, reason %d (%s)", ret,
1504         gst_flow_get_name (ret));
1505     if (demux->seekable)
1506       gst_pad_pause_task (demux->sinkpad);
1507     else {
1508       GstFFMpegPipe *ffpipe = &demux->ffpipe;
1509
1510       GST_FFMPEG_PIPE_MUTEX_LOCK (ffpipe);
1511       /* pause task and make sure loop stops */
1512       gst_task_pause (demux->task);
1513       g_rec_mutex_lock (&demux->task_lock);
1514       g_rec_mutex_unlock (&demux->task_lock);
1515       demux->ffpipe.srcresult = ret;
1516       GST_FFMPEG_PIPE_MUTEX_UNLOCK (ffpipe);
1517     }
1518
1519     if (ret == GST_FLOW_EOS) {
1520       if (demux->segment.flags & GST_SEEK_FLAG_SEGMENT) {
1521         gint64 stop;
1522
1523         if ((stop = demux->segment.stop) == -1)
1524           stop = demux->segment.duration;
1525
1526         GST_LOG_OBJECT (demux, "posting segment done");
1527         gst_element_post_message (GST_ELEMENT (demux),
1528             gst_message_new_segment_done (GST_OBJECT (demux),
1529                 demux->segment.format, stop));
1530         gst_ffmpegdemux_push_event (demux,
1531             gst_event_new_segment_done (demux->segment.format, stop));
1532       } else {
1533         GST_LOG_OBJECT (demux, "pushing eos");
1534         gst_ffmpegdemux_push_event (demux, gst_event_new_eos ());
1535       }
1536     } else if (ret == GST_FLOW_NOT_LINKED || ret < GST_FLOW_EOS) {
1537       GST_ELEMENT_ERROR (demux, STREAM, FAILED,
1538           ("Internal data stream error."),
1539           ("streaming stopped, reason %s", gst_flow_get_name (ret)));
1540       gst_ffmpegdemux_push_event (demux, gst_event_new_eos ());
1541     }
1542     return;
1543   }
1544 open_failed:
1545   {
1546     ret = GST_FLOW_ERROR;
1547     goto pause;
1548   }
1549 read_failed:
1550   {
1551     /* something went wrong... */
1552     GST_WARNING_OBJECT (demux, "av_read_frame returned %d", res);
1553
1554     GST_OBJECT_LOCK (demux);
1555     /* pause appropriatly based on if we are flushing or not */
1556     if (demux->flushing)
1557       ret = GST_FLOW_FLUSHING;
1558     else if (gst_ffmpegdemux_has_outputted (demux)
1559         || gst_ffmpegdemux_is_eos (demux)) {
1560       GST_DEBUG_OBJECT (demux, "We are EOS");
1561       ret = GST_FLOW_EOS;
1562     } else
1563       ret = GST_FLOW_ERROR;
1564     GST_OBJECT_UNLOCK (demux);
1565
1566     goto pause;
1567   }
1568 drop:
1569   {
1570     GST_DEBUG_OBJECT (demux, "dropping buffer out of segment, stream eos");
1571     stream->eos = TRUE;
1572     if (gst_ffmpegdemux_is_eos (demux)) {
1573       av_free_packet (&pkt);
1574       GST_DEBUG_OBJECT (demux, "we are eos");
1575       ret = GST_FLOW_EOS;
1576       goto pause;
1577     } else {
1578       GST_DEBUG_OBJECT (demux, "some streams are not yet eos");
1579       goto done;
1580     }
1581   }
1582 }
1583
1584
1585 static gboolean
1586 gst_ffmpegdemux_sink_event (GstPad * sinkpad, GstObject * parent,
1587     GstEvent * event)
1588 {
1589   GstFFMpegDemux *demux;
1590   GstFFMpegPipe *ffpipe;
1591   gboolean result = TRUE;
1592
1593   demux = (GstFFMpegDemux *) parent;
1594   ffpipe = &(demux->ffpipe);
1595
1596   GST_LOG_OBJECT (demux, "event: %" GST_PTR_FORMAT, event);
1597
1598   switch (GST_EVENT_TYPE (event)) {
1599     case GST_EVENT_FLUSH_START:
1600       /* forward event */
1601       gst_pad_event_default (sinkpad, parent, event);
1602
1603       /* now unblock the chain function */
1604       GST_FFMPEG_PIPE_MUTEX_LOCK (ffpipe);
1605       ffpipe->srcresult = GST_FLOW_FLUSHING;
1606       GST_FFMPEG_PIPE_SIGNAL (ffpipe);
1607       GST_FFMPEG_PIPE_MUTEX_UNLOCK (ffpipe);
1608
1609       /* loop might run into WRONG_STATE and end itself,
1610        * but may also be waiting in a ffmpeg read
1611        * trying to break that would make ffmpeg believe eos,
1612        * so no harm to have the loop 'pausing' there ... */
1613       goto done;
1614     case GST_EVENT_FLUSH_STOP:
1615       /* forward event */
1616       gst_pad_event_default (sinkpad, parent, event);
1617
1618       GST_OBJECT_LOCK (demux);
1619       g_list_foreach (demux->cached_events, (GFunc) gst_mini_object_unref,
1620           NULL);
1621       g_list_free (demux->cached_events);
1622       GST_OBJECT_UNLOCK (demux);
1623       GST_FFMPEG_PIPE_MUTEX_LOCK (ffpipe);
1624       gst_adapter_clear (ffpipe->adapter);
1625       ffpipe->srcresult = GST_FLOW_OK;
1626       /* loop may have decided to end itself as a result of flush WRONG_STATE */
1627       gst_task_start (demux->task);
1628       demux->flushing = FALSE;
1629       GST_LOG_OBJECT (demux, "loop started");
1630       GST_FFMPEG_PIPE_MUTEX_UNLOCK (ffpipe);
1631       goto done;
1632     case GST_EVENT_EOS:
1633       /* inform the src task that it can stop now */
1634       GST_FFMPEG_PIPE_MUTEX_LOCK (ffpipe);
1635       ffpipe->eos = TRUE;
1636       GST_FFMPEG_PIPE_SIGNAL (ffpipe);
1637       GST_FFMPEG_PIPE_MUTEX_UNLOCK (ffpipe);
1638
1639       /* eat this event for now, task will send eos when finished */
1640       gst_event_unref (event);
1641       goto done;
1642     case GST_EVENT_STREAM_START:
1643     case GST_EVENT_CAPS:
1644       GST_LOG_OBJECT (demux, "dropping %s event", GST_EVENT_TYPE_NAME (event));
1645       gst_event_unref (event);
1646       goto done;
1647     default:
1648       /* for a serialized event, wait until an earlier data is gone,
1649        * though this is no guarantee as to when task is done with it.
1650        *
1651        * If the demuxer isn't opened, push straight away, since we'll
1652        * be waiting against a cond that will never be signalled. */
1653       if (GST_EVENT_IS_SERIALIZED (event)) {
1654         if (demux->opened) {
1655           GST_FFMPEG_PIPE_MUTEX_LOCK (ffpipe);
1656           while (!ffpipe->needed)
1657             GST_FFMPEG_PIPE_WAIT (ffpipe);
1658           GST_FFMPEG_PIPE_MUTEX_UNLOCK (ffpipe);
1659         } else {
1660           /* queue events and send them later (esp. tag events) */
1661           GST_OBJECT_LOCK (demux);
1662           demux->cached_events = g_list_append (demux->cached_events, event);
1663           GST_OBJECT_UNLOCK (demux);
1664           goto done;
1665         }
1666       }
1667       break;
1668   }
1669
1670   result = gst_pad_event_default (sinkpad, parent, event);
1671
1672 done:
1673
1674   return result;
1675 }
1676
1677 static GstFlowReturn
1678 gst_ffmpegdemux_chain (GstPad * sinkpad, GstObject * parent, GstBuffer * buffer)
1679 {
1680   GstFFMpegDemux *demux;
1681   GstFFMpegPipe *ffpipe;
1682
1683   demux = (GstFFMpegDemux *) parent;
1684   ffpipe = &demux->ffpipe;
1685
1686   GST_FFMPEG_PIPE_MUTEX_LOCK (ffpipe);
1687
1688   if (G_UNLIKELY (ffpipe->eos))
1689     goto eos;
1690
1691   if (G_UNLIKELY (ffpipe->srcresult != GST_FLOW_OK))
1692     goto ignore;
1693
1694   GST_DEBUG ("Giving a buffer of %" G_GSIZE_FORMAT " bytes",
1695       gst_buffer_get_size (buffer));
1696   gst_adapter_push (ffpipe->adapter, buffer);
1697   buffer = NULL;
1698   while (gst_adapter_available (ffpipe->adapter) >= ffpipe->needed) {
1699     GST_DEBUG ("Adapter has more that requested (ffpipe->needed:%d)",
1700         ffpipe->needed);
1701     GST_FFMPEG_PIPE_SIGNAL (ffpipe);
1702     GST_FFMPEG_PIPE_WAIT (ffpipe);
1703     /* may have become flushing */
1704     if (G_UNLIKELY (ffpipe->srcresult != GST_FLOW_OK))
1705       goto ignore;
1706   }
1707
1708   GST_FFMPEG_PIPE_MUTEX_UNLOCK (ffpipe);
1709
1710   return GST_FLOW_OK;
1711
1712 /* special cases */
1713 eos:
1714   {
1715     GST_DEBUG_OBJECT (demux, "ignoring buffer at end-of-stream");
1716     GST_FFMPEG_PIPE_MUTEX_UNLOCK (ffpipe);
1717
1718     gst_buffer_unref (buffer);
1719     return GST_FLOW_EOS;
1720   }
1721 ignore:
1722   {
1723     GST_DEBUG_OBJECT (demux, "ignoring buffer because src task encountered %s",
1724         gst_flow_get_name (ffpipe->srcresult));
1725     GST_FFMPEG_PIPE_MUTEX_UNLOCK (ffpipe);
1726
1727     if (buffer)
1728       gst_buffer_unref (buffer);
1729     return GST_FLOW_FLUSHING;
1730   }
1731 }
1732
1733 static gboolean
1734 gst_ffmpegdemux_sink_activate (GstPad * sinkpad, GstObject * parent)
1735 {
1736   GstQuery *query;
1737   gboolean pull_mode;
1738   GstSchedulingFlags flags;
1739
1740   query = gst_query_new_scheduling ();
1741
1742   if (!gst_pad_peer_query (sinkpad, query)) {
1743     gst_query_unref (query);
1744     goto activate_push;
1745   }
1746
1747   pull_mode = gst_query_has_scheduling_mode_with_flags (query,
1748       GST_PAD_MODE_PULL, GST_SCHEDULING_FLAG_SEEKABLE);
1749
1750   gst_query_parse_scheduling (query, &flags, NULL, NULL, NULL);
1751   if (flags & GST_SCHEDULING_FLAG_SEQUENTIAL)
1752     pull_mode = FALSE;
1753
1754   gst_query_unref (query);
1755
1756   if (!pull_mode)
1757     goto activate_push;
1758
1759   GST_DEBUG_OBJECT (sinkpad, "activating pull");
1760   return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PULL, TRUE);
1761
1762 activate_push:
1763   {
1764     GST_DEBUG_OBJECT (sinkpad, "activating push");
1765     return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PUSH, TRUE);
1766   }
1767 }
1768
1769 /* push mode:
1770  * - not seekable
1771  * - use gstpipe protocol, like ffmpeg's pipe protocol
1772  * - (independently managed) task driving ffmpeg
1773  */
1774 static gboolean
1775 gst_ffmpegdemux_sink_activate_push (GstPad * sinkpad, GstObject * parent,
1776     gboolean active)
1777 {
1778   GstFFMpegDemux *demux;
1779   gboolean res = FALSE;
1780
1781   demux = (GstFFMpegDemux *) (parent);
1782
1783   if (active) {
1784     if (demux->can_push == FALSE) {
1785       GST_WARNING_OBJECT (demux, "Demuxer can't reliably operate in push-mode");
1786       goto beach;
1787     }
1788     demux->ffpipe.eos = FALSE;
1789     demux->ffpipe.srcresult = GST_FLOW_OK;
1790     demux->ffpipe.needed = 0;
1791     demux->seekable = FALSE;
1792     res = gst_task_start (demux->task);
1793   } else {
1794     GstFFMpegPipe *ffpipe = &demux->ffpipe;
1795
1796     /* release chain and loop */
1797     GST_FFMPEG_PIPE_MUTEX_LOCK (ffpipe);
1798     demux->ffpipe.srcresult = GST_FLOW_FLUSHING;
1799     /* end streaming by making ffmpeg believe eos */
1800     demux->ffpipe.eos = TRUE;
1801     GST_FFMPEG_PIPE_SIGNAL (ffpipe);
1802     GST_FFMPEG_PIPE_MUTEX_UNLOCK (ffpipe);
1803
1804     /* make sure streaming ends */
1805     gst_task_stop (demux->task);
1806     g_rec_mutex_lock (&demux->task_lock);
1807     g_rec_mutex_unlock (&demux->task_lock);
1808     res = gst_task_join (demux->task);
1809     demux->seekable = FALSE;
1810   }
1811
1812 beach:
1813   return res;
1814 }
1815
1816 /* pull mode:
1817  * - seekable
1818  * - use gstreamer protocol, like ffmpeg's file protocol
1819  * - task driving ffmpeg based on sink pad
1820  */
1821 static gboolean
1822 gst_ffmpegdemux_sink_activate_pull (GstPad * sinkpad, GstObject * parent,
1823     gboolean active)
1824 {
1825   GstFFMpegDemux *demux;
1826   gboolean res;
1827
1828   demux = (GstFFMpegDemux *) parent;
1829
1830   if (active) {
1831     demux->seekable = TRUE;
1832     res = gst_pad_start_task (sinkpad, (GstTaskFunction) gst_ffmpegdemux_loop,
1833         demux, NULL);
1834   } else {
1835     res = gst_pad_stop_task (sinkpad);
1836     demux->seekable = FALSE;
1837   }
1838
1839   return res;
1840 }
1841
1842 static gboolean
1843 gst_ffmpegdemux_sink_activate_mode (GstPad * sinkpad, GstObject * parent,
1844     GstPadMode mode, gboolean active)
1845 {
1846   gboolean res;
1847
1848   switch (mode) {
1849     case GST_PAD_MODE_PUSH:
1850       res = gst_ffmpegdemux_sink_activate_push (sinkpad, parent, active);
1851       break;
1852     case GST_PAD_MODE_PULL:
1853       res = gst_ffmpegdemux_sink_activate_pull (sinkpad, parent, active);
1854       break;
1855     default:
1856       res = FALSE;
1857       break;
1858   }
1859   return res;
1860 }
1861
1862 static GstStateChangeReturn
1863 gst_ffmpegdemux_change_state (GstElement * element, GstStateChange transition)
1864 {
1865   GstFFMpegDemux *demux = (GstFFMpegDemux *) (element);
1866   GstStateChangeReturn ret;
1867
1868   switch (transition) {
1869     case GST_STATE_CHANGE_READY_TO_PAUSED:
1870 #if 0
1871       /* test seek in READY here */
1872       gst_element_send_event (element, gst_event_new_seek (1.0,
1873               GST_FORMAT_TIME, GST_SEEK_FLAG_NONE,
1874               GST_SEEK_TYPE_SET, 10 * GST_SECOND,
1875               GST_SEEK_TYPE_SET, 13 * GST_SECOND));
1876 #endif
1877       break;
1878     default:
1879       break;
1880   }
1881
1882   ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
1883
1884   switch (transition) {
1885     case GST_STATE_CHANGE_PAUSED_TO_READY:
1886       gst_ffmpegdemux_close (demux);
1887       gst_adapter_clear (demux->ffpipe.adapter);
1888       g_list_foreach (demux->cached_events, (GFunc) gst_mini_object_unref,
1889           NULL);
1890       g_list_free (demux->cached_events);
1891       demux->cached_events = NULL;
1892       demux->have_group_id = FALSE;
1893       demux->group_id = G_MAXUINT;
1894       break;
1895     default:
1896       break;
1897   }
1898
1899   return ret;
1900 }
1901
1902 gboolean
1903 gst_ffmpegdemux_register (GstPlugin * plugin)
1904 {
1905   GType type;
1906   AVInputFormat *in_plugin;
1907   gchar *extensions;
1908   GTypeInfo typeinfo = {
1909     sizeof (GstFFMpegDemuxClass),
1910     (GBaseInitFunc) gst_ffmpegdemux_base_init,
1911     NULL,
1912     (GClassInitFunc) gst_ffmpegdemux_class_init,
1913     NULL,
1914     NULL,
1915     sizeof (GstFFMpegDemux),
1916     0,
1917     (GInstanceInitFunc) gst_ffmpegdemux_init,
1918   };
1919
1920   in_plugin = av_iformat_next (NULL);
1921
1922   GST_LOG ("Registering demuxers");
1923
1924   while (in_plugin) {
1925     gchar *type_name, *typefind_name;
1926     gchar *p, *name = NULL;
1927     gint rank;
1928     gboolean register_typefind_func = TRUE;
1929
1930     GST_LOG ("Attempting to handle libav demuxer plugin %s [%s]",
1931         in_plugin->name, in_plugin->long_name);
1932
1933     /* no emulators */
1934     if (!strncmp (in_plugin->long_name, "raw ", 4) ||
1935         !strncmp (in_plugin->long_name, "pcm ", 4) ||
1936         !strcmp (in_plugin->name, "audio_device") ||
1937         !strncmp (in_plugin->name, "image", 5) ||
1938         !strcmp (in_plugin->name, "mpegvideo") ||
1939         !strcmp (in_plugin->name, "mjpeg") ||
1940         !strcmp (in_plugin->name, "redir") ||
1941         !strncmp (in_plugin->name, "u8", 2) ||
1942         !strncmp (in_plugin->name, "u16", 3) ||
1943         !strncmp (in_plugin->name, "u24", 3) ||
1944         !strncmp (in_plugin->name, "u32", 3) ||
1945         !strncmp (in_plugin->name, "s8", 2) ||
1946         !strncmp (in_plugin->name, "s16", 3) ||
1947         !strncmp (in_plugin->name, "s24", 3) ||
1948         !strncmp (in_plugin->name, "s32", 3) ||
1949         !strncmp (in_plugin->name, "f32", 3) ||
1950         !strncmp (in_plugin->name, "f64", 3) ||
1951         !strcmp (in_plugin->name, "mulaw") || !strcmp (in_plugin->name, "alaw")
1952         )
1953       goto next;
1954
1955     /* no network demuxers */
1956     if (!strcmp (in_plugin->name, "sdp") ||
1957         !strcmp (in_plugin->name, "rtsp") ||
1958         !strcmp (in_plugin->name, "applehttp")
1959         )
1960       goto next;
1961
1962     /* these don't do what one would expect or
1963      * are only partially functional/useful */
1964     if (!strcmp (in_plugin->name, "aac") ||
1965         !strcmp (in_plugin->name, "wv") ||
1966         !strcmp (in_plugin->name, "ass") ||
1967         !strcmp (in_plugin->name, "ffmetadata"))
1968       goto next;
1969
1970     /* Don't use the typefind functions of formats for which we already have
1971      * better typefind functions */
1972     if (!strcmp (in_plugin->name, "mov,mp4,m4a,3gp,3g2,mj2") ||
1973         !strcmp (in_plugin->name, "ass") ||
1974         !strcmp (in_plugin->name, "avi") ||
1975         !strcmp (in_plugin->name, "asf") ||
1976         !strcmp (in_plugin->name, "mpegvideo") ||
1977         !strcmp (in_plugin->name, "mp3") ||
1978         !strcmp (in_plugin->name, "matroska") ||
1979         !strcmp (in_plugin->name, "matroska_webm") ||
1980         !strcmp (in_plugin->name, "matroska,webm") ||
1981         !strcmp (in_plugin->name, "mpeg") ||
1982         !strcmp (in_plugin->name, "wav") ||
1983         !strcmp (in_plugin->name, "au") ||
1984         !strcmp (in_plugin->name, "tta") ||
1985         !strcmp (in_plugin->name, "rm") ||
1986         !strcmp (in_plugin->name, "amr") ||
1987         !strcmp (in_plugin->name, "ogg") ||
1988         !strcmp (in_plugin->name, "aiff") ||
1989         !strcmp (in_plugin->name, "ape") ||
1990         !strcmp (in_plugin->name, "dv") ||
1991         !strcmp (in_plugin->name, "flv") ||
1992         !strcmp (in_plugin->name, "mpc") ||
1993         !strcmp (in_plugin->name, "mpc8") ||
1994         !strcmp (in_plugin->name, "mpegts") ||
1995         !strcmp (in_plugin->name, "mpegtsraw") ||
1996         !strcmp (in_plugin->name, "mxf") ||
1997         !strcmp (in_plugin->name, "nuv") ||
1998         !strcmp (in_plugin->name, "swf") ||
1999         !strcmp (in_plugin->name, "voc") ||
2000         !strcmp (in_plugin->name, "pva") ||
2001         !strcmp (in_plugin->name, "gif") || !strcmp (in_plugin->name, "vc1test")
2002         )
2003       register_typefind_func = FALSE;
2004
2005     /* Set the rank of demuxers known to work to MARGINAL.
2006      * Set demuxers for which we already have another implementation to NONE
2007      * Set All others to NONE*/
2008     if (!strcmp (in_plugin->name, "wsvqa") ||
2009         !strcmp (in_plugin->name, "wsaud") ||
2010         !strcmp (in_plugin->name, "wc3movie") ||
2011         !strcmp (in_plugin->name, "voc") ||
2012         !strcmp (in_plugin->name, "tta") ||
2013         !strcmp (in_plugin->name, "sol") ||
2014         !strcmp (in_plugin->name, "smk") ||
2015         !strcmp (in_plugin->name, "vmd") ||
2016         !strcmp (in_plugin->name, "film_cpk") ||
2017         !strcmp (in_plugin->name, "ingenient") ||
2018         !strcmp (in_plugin->name, "psxstr") ||
2019         !strcmp (in_plugin->name, "nuv") ||
2020         !strcmp (in_plugin->name, "nut") ||
2021         !strcmp (in_plugin->name, "nsv") ||
2022         !strcmp (in_plugin->name, "mxf") ||
2023         !strcmp (in_plugin->name, "mmf") ||
2024         !strcmp (in_plugin->name, "mm") ||
2025         !strcmp (in_plugin->name, "ipmovie") ||
2026         !strcmp (in_plugin->name, "ape") ||
2027         !strcmp (in_plugin->name, "RoQ") ||
2028         !strcmp (in_plugin->name, "idcin") ||
2029         !strcmp (in_plugin->name, "gxf") ||
2030         !strcmp (in_plugin->name, "ffm") ||
2031         !strcmp (in_plugin->name, "ea") ||
2032         !strcmp (in_plugin->name, "daud") ||
2033         !strcmp (in_plugin->name, "avs") ||
2034         !strcmp (in_plugin->name, "aiff") ||
2035         !strcmp (in_plugin->name, "4xm") ||
2036         !strcmp (in_plugin->name, "yuv4mpegpipe") ||
2037         !strcmp (in_plugin->name, "pva") ||
2038         !strcmp (in_plugin->name, "mpc") || !strcmp (in_plugin->name, "gif"))
2039       rank = GST_RANK_MARGINAL;
2040     else {
2041       GST_DEBUG ("ignoring %s", in_plugin->name);
2042       rank = GST_RANK_NONE;
2043       goto next;
2044     }
2045
2046     p = name = g_strdup (in_plugin->name);
2047     while (*p) {
2048       if (*p == '.' || *p == ',')
2049         *p = '_';
2050       p++;
2051     }
2052
2053     /* construct the type */
2054     type_name = g_strdup_printf ("avdemux_%s", name);
2055
2056     /* if it's already registered, drop it */
2057     if (g_type_from_name (type_name)) {
2058       g_free (type_name);
2059       goto next;
2060     }
2061
2062     typefind_name = g_strdup_printf ("avtype_%s", name);
2063
2064     /* create the type now */
2065     type = g_type_register_static (GST_TYPE_ELEMENT, type_name, &typeinfo, 0);
2066     g_type_set_qdata (type, GST_FFDEMUX_PARAMS_QDATA, (gpointer) in_plugin);
2067
2068     if (in_plugin->extensions)
2069       extensions = g_strdelimit (g_strdup (in_plugin->extensions), " ", ',');
2070     else
2071       extensions = NULL;
2072
2073     if (!gst_element_register (plugin, type_name, rank, type) ||
2074         (register_typefind_func == TRUE &&
2075             !gst_type_find_register (plugin, typefind_name, rank,
2076                 gst_ffmpegdemux_type_find, extensions, NULL, in_plugin,
2077                 NULL))) {
2078       g_warning ("Register of type avdemux_%s failed", name);
2079       g_free (type_name);
2080       g_free (typefind_name);
2081       return FALSE;
2082     }
2083
2084     g_free (type_name);
2085     g_free (typefind_name);
2086     g_free (extensions);
2087
2088   next:
2089     g_free (name);
2090     in_plugin = av_iformat_next (in_plugin);
2091   }
2092
2093   GST_LOG ("Finished registering demuxers");
2094
2095   return TRUE;
2096 }