flvdemux: Handle seek flags properly
[platform/upstream/gst-plugins-good.git] / gst / flv / gstflvdemux.c
1 /* GStreamer
2  * Copyright (C) <2007> Julien Moutte <julien@moutte.net>
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., 51 Franklin St, Fifth Floor,
17  * Boston, MA 02110-1301, USA.
18  */
19
20 /**
21  * SECTION:element-flvdemux
22  *
23  * flvdemux demuxes an FLV file into the different contained streams.
24  *
25  * <refsect2>
26  * <title>Example launch line</title>
27  * |[
28  * gst-launch-1.0 -v filesrc location=/path/to/flv ! flvdemux ! audioconvert ! autoaudiosink
29  * ]| This pipeline demuxes an FLV file and outputs the contained raw audio streams.
30  * </refsect2>
31  */
32
33 #ifdef HAVE_CONFIG_H
34 #include "config.h"
35 #endif
36
37 #include "gstflvdemux.h"
38 #include "gstflvmux.h"
39
40 #include <string.h>
41 #include <gst/base/gstbytereader.h>
42 #include <gst/base/gstbytewriter.h>
43 #include <gst/pbutils/descriptions.h>
44 #include <gst/pbutils/pbutils.h>
45 #include <gst/audio/audio.h>
46 #include <gst/video/video.h>
47
48 /* FIXME: don't rely on own GstIndex */
49 #include "gstindex.c"
50 #include "gstmemindex.c"
51 #define GST_ASSOCIATION_FLAG_NONE GST_INDEX_ASSOCIATION_FLAG_NONE
52 #define GST_ASSOCIATION_FLAG_KEY_UNIT GST_INDEX_ASSOCIATION_FLAG_KEY_UNIT
53 #define GST_ASSOCIATION_FLAG_DELTA_UNIT GST_INDEX_ASSOCIATION_FLAG_DELTA_UNIT
54
55 static GstStaticPadTemplate flv_sink_template = GST_STATIC_PAD_TEMPLATE ("sink",
56     GST_PAD_SINK,
57     GST_PAD_ALWAYS,
58     GST_STATIC_CAPS ("video/x-flv")
59     );
60
61 static GstStaticPadTemplate audio_src_template =
62     GST_STATIC_PAD_TEMPLATE ("audio",
63     GST_PAD_SRC,
64     GST_PAD_SOMETIMES,
65     GST_STATIC_CAPS
66     ("audio/x-adpcm, layout = (string) swf, channels = (int) { 1, 2 }, rate = (int) { 5512, 11025, 22050, 44100 }; "
67         "audio/mpeg, mpegversion = (int) 1, layer = (int) 3, channels = (int) { 1, 2 }, rate = (int) { 5512, 8000, 11025, 22050, 44100 }, parsed = (boolean) TRUE; "
68         "audio/mpeg, mpegversion = (int) 4, stream-format = (string) raw, framed = (boolean) TRUE; "
69         "audio/x-nellymoser, channels = (int) { 1, 2 }, rate = (int) { 5512, 8000, 11025, 16000, 22050, 44100 }; "
70         "audio/x-raw, format = (string) { U8, S16LE }, layout = (string) interleaved, channels = (int) { 1, 2 }, rate = (int) { 5512, 11025, 22050, 44100 }; "
71         "audio/x-alaw, channels = (int) { 1, 2 }, rate = (int) { 5512, 11025, 22050, 44100 }; "
72         "audio/x-mulaw, channels = (int) { 1, 2 }, rate = (int) { 5512, 11025, 22050, 44100 }; "
73         "audio/x-speex, channels = (int) 1, rate = (int) 16000;")
74     );
75
76 static GstStaticPadTemplate video_src_template =
77     GST_STATIC_PAD_TEMPLATE ("video",
78     GST_PAD_SRC,
79     GST_PAD_SOMETIMES,
80     GST_STATIC_CAPS ("video/x-flash-video, flvversion=(int) 1; "
81         "video/x-flash-screen; "
82         "video/x-vp6-flash; " "video/x-vp6-alpha; "
83         "video/x-h264, stream-format=avc;")
84     );
85
86 GST_DEBUG_CATEGORY_STATIC (flvdemux_debug);
87 #define GST_CAT_DEFAULT flvdemux_debug
88
89 #define gst_flv_demux_parent_class parent_class
90 G_DEFINE_TYPE (GstFlvDemux, gst_flv_demux, GST_TYPE_ELEMENT);
91
92 /* 9 bytes of header + 4 bytes of first previous tag size */
93 #define FLV_HEADER_SIZE 13
94 /* 1 byte of tag type + 3 bytes of tag data size */
95 #define FLV_TAG_TYPE_SIZE 4
96
97 /* two seconds - consider dts are resynced to another base if this different */
98 #define RESYNC_THRESHOLD 2000
99
100 /* how much stream time to wait for audio tags to appear after we have video, or vice versa */
101 #define NO_MORE_PADS_THRESHOLD (6 * GST_SECOND)
102
103 static gboolean flv_demux_handle_seek_push (GstFlvDemux * demux,
104     GstEvent * event);
105 static gboolean gst_flv_demux_handle_seek_pull (GstFlvDemux * demux,
106     GstEvent * event, gboolean seeking);
107
108 static gboolean gst_flv_demux_query (GstPad * pad, GstObject * parent,
109     GstQuery * query);
110 static gboolean gst_flv_demux_src_event (GstPad * pad, GstObject * parent,
111     GstEvent * event);
112
113 static GstIndex *gst_flv_demux_get_index (GstElement * element);
114
115 static void
116 gst_flv_demux_parse_and_add_index_entry (GstFlvDemux * demux, GstClockTime ts,
117     guint64 pos, gboolean keyframe)
118 {
119   GstIndexAssociation associations[2];
120   GstIndex *index;
121   GstIndexEntry *entry;
122
123   GST_LOG_OBJECT (demux,
124       "adding key=%d association %" GST_TIME_FORMAT "-> %" G_GUINT64_FORMAT,
125       keyframe, GST_TIME_ARGS (ts), pos);
126
127   /* if upstream is not seekable there is no point in building an index */
128   if (!demux->upstream_seekable)
129     return;
130
131   index = gst_flv_demux_get_index (GST_ELEMENT (demux));
132
133   if (!index)
134     return;
135
136   /* entry may already have been added before, avoid adding indefinitely */
137   entry = gst_index_get_assoc_entry (index, demux->index_id,
138       GST_INDEX_LOOKUP_EXACT, GST_ASSOCIATION_FLAG_NONE, GST_FORMAT_BYTES, pos);
139
140   if (entry) {
141 #ifndef GST_DISABLE_GST_DEBUG
142     gint64 time = 0;
143     gboolean key;
144
145     gst_index_entry_assoc_map (entry, GST_FORMAT_TIME, &time);
146     key = ! !(GST_INDEX_ASSOC_FLAGS (entry) & GST_ASSOCIATION_FLAG_KEY_UNIT);
147     GST_LOG_OBJECT (demux, "position already mapped to time %" GST_TIME_FORMAT
148         ", keyframe %d", GST_TIME_ARGS (time), key);
149     /* there is not really a way to delete the existing one */
150     if (time != ts || key != ! !keyframe)
151       GST_DEBUG_OBJECT (demux, "metadata mismatch");
152 #endif
153     gst_object_unref (index);
154     return;
155   }
156
157   associations[0].format = GST_FORMAT_TIME;
158   associations[0].value = ts;
159   associations[1].format = GST_FORMAT_BYTES;
160   associations[1].value = pos;
161
162   gst_index_add_associationv (index, demux->index_id,
163       (keyframe) ? GST_ASSOCIATION_FLAG_KEY_UNIT :
164       GST_ASSOCIATION_FLAG_DELTA_UNIT, 2,
165       (const GstIndexAssociation *) &associations);
166
167   if (pos > demux->index_max_pos)
168     demux->index_max_pos = pos;
169   if (ts > demux->index_max_time)
170     demux->index_max_time = ts;
171
172   gst_object_unref (index);
173 }
174
175 static gchar *
176 FLV_GET_STRING (GstByteReader * reader)
177 {
178   guint16 string_size = 0;
179   gchar *string = NULL;
180   const guint8 *str = NULL;
181
182   g_return_val_if_fail (reader != NULL, NULL);
183
184   if (G_UNLIKELY (!gst_byte_reader_get_uint16_be (reader, &string_size)))
185     return NULL;
186
187   if (G_UNLIKELY (string_size > gst_byte_reader_get_remaining (reader)))
188     return NULL;
189
190   string = g_try_malloc0 (string_size + 1);
191   if (G_UNLIKELY (!string)) {
192     return NULL;
193   }
194
195   if (G_UNLIKELY (!gst_byte_reader_get_data (reader, string_size, &str))) {
196     g_free (string);
197     return NULL;
198   }
199
200   memcpy (string, str, string_size);
201   if (!g_utf8_validate (string, string_size, NULL)) {
202     g_free (string);
203     return NULL;
204   }
205
206   return string;
207 }
208
209 static void
210 gst_flv_demux_check_seekability (GstFlvDemux * demux)
211 {
212   GstQuery *query;
213   gint64 start = -1, stop = -1;
214
215   demux->upstream_seekable = FALSE;
216
217   query = gst_query_new_seeking (GST_FORMAT_BYTES);
218   if (!gst_pad_peer_query (demux->sinkpad, query)) {
219     GST_DEBUG_OBJECT (demux, "seeking query failed");
220     gst_query_unref (query);
221     return;
222   }
223
224   gst_query_parse_seeking (query, NULL, &demux->upstream_seekable,
225       &start, &stop);
226
227   gst_query_unref (query);
228
229   /* try harder to query upstream size if we didn't get it the first time */
230   if (demux->upstream_seekable && stop == -1) {
231     GST_DEBUG_OBJECT (demux, "doing duration query to fix up unset stop");
232     gst_pad_peer_query_duration (demux->sinkpad, GST_FORMAT_BYTES, &stop);
233   }
234
235   /* if upstream doesn't know the size, it's likely that it's not seekable in
236    * practice even if it technically may be seekable */
237   if (demux->upstream_seekable && (start != 0 || stop <= start)) {
238     GST_DEBUG_OBJECT (demux, "seekable but unknown start/stop -> disable");
239     demux->upstream_seekable = FALSE;
240   }
241
242   GST_DEBUG_OBJECT (demux, "upstream seekable: %d", demux->upstream_seekable);
243 }
244
245 static void
246 parse_flv_demux_parse_date_string (GDate * date, const gchar * s)
247 {
248   g_date_set_parse (date, s);
249   if (g_date_valid (date))
250     return;
251
252   /* "Fri Oct 15 15:13:16 2004" needs to be parsed */
253   {
254     static const gchar *months[] = {
255       "Jan", "Feb", "Mar", "Apr",
256       "May", "Jun", "Jul", "Aug",
257       "Sep", "Oct", "Nov", "Dec"
258     };
259     gchar **tokens = g_strsplit (s, " ", -1);
260     guint64 d;
261     gchar *endptr;
262     gint i;
263
264     if (g_strv_length (tokens) != 5)
265       goto out;
266
267     if (strlen (tokens[1]) != 3)
268       goto out;
269     for (i = 0; i < 12; i++) {
270       if (!strcmp (tokens[1], months[i])) {
271         break;
272       }
273     }
274     if (i == 12)
275       goto out;
276     g_date_set_month (date, i + 1);
277
278     d = g_ascii_strtoull (tokens[2], &endptr, 10);
279     if (d == 0 && *endptr != '\0')
280       goto out;
281
282     g_date_set_day (date, d);
283
284     d = g_ascii_strtoull (tokens[4], &endptr, 10);
285     if (d == 0 && *endptr != '\0')
286       goto out;
287
288     g_date_set_year (date, d);
289
290   out:
291     if (tokens)
292       g_strfreev (tokens);
293   }
294 }
295
296 static gboolean
297 gst_flv_demux_parse_metadata_item (GstFlvDemux * demux, GstByteReader * reader,
298     gboolean * end_marker)
299 {
300   gchar *tag_name = NULL;
301   guint8 tag_type = 0;
302
303   /* Initialize the end_marker flag to FALSE */
304   *end_marker = FALSE;
305
306   /* Name of the tag */
307   tag_name = FLV_GET_STRING (reader);
308   if (G_UNLIKELY (!tag_name)) {
309     GST_WARNING_OBJECT (demux, "failed reading tag name");
310     return FALSE;
311   }
312
313   /* What kind of object is that */
314   if (!gst_byte_reader_get_uint8 (reader, &tag_type))
315     goto error;
316
317   GST_DEBUG_OBJECT (demux, "tag name %s, tag type %d", tag_name, tag_type);
318
319   switch (tag_type) {
320     case 0:                    /* Double */
321     {                           /* Use a union to read the uint64 and then as a double */
322       gdouble d = 0;
323
324       if (!gst_byte_reader_get_float64_be (reader, &d))
325         goto error;
326
327       GST_DEBUG_OBJECT (demux, "%s => (double) %f", tag_name, d);
328
329       if (!strcmp (tag_name, "duration")) {
330         demux->duration = d * GST_SECOND;
331
332         gst_tag_list_add (demux->taglist, GST_TAG_MERGE_REPLACE,
333             GST_TAG_DURATION, demux->duration, NULL);
334       } else if (!strcmp (tag_name, "AspectRatioX")) {
335         demux->par_x = d;
336         demux->got_par = TRUE;
337       } else if (!strcmp (tag_name, "AspectRatioY")) {
338         demux->par_y = d;
339         demux->got_par = TRUE;
340       } else if (!strcmp (tag_name, "width")) {
341         demux->w = d;
342       } else if (!strcmp (tag_name, "height")) {
343         demux->h = d;
344       } else if (!strcmp (tag_name, "framerate")) {
345         demux->framerate = d;
346       } else {
347         GST_INFO_OBJECT (demux, "Tag \'%s\' not handled", tag_name);
348       }
349
350       break;
351     }
352     case 1:                    /* Boolean */
353     {
354       guint8 b = 0;
355
356       if (!gst_byte_reader_get_uint8 (reader, &b))
357         goto error;
358
359       GST_DEBUG_OBJECT (demux, "%s => (boolean) %d", tag_name, b);
360
361       GST_INFO_OBJECT (demux, "Tag \'%s\' not handled", tag_name);
362
363       break;
364     }
365     case 2:                    /* String */
366     {
367       gchar *s = NULL;
368
369       s = FLV_GET_STRING (reader);
370       if (s == NULL)
371         goto error;
372
373       GST_DEBUG_OBJECT (demux, "%s => (string) %s", tag_name, s);
374
375       if (!strcmp (tag_name, "creationdate")) {
376         GDate *date = g_date_new ();
377
378         parse_flv_demux_parse_date_string (date, s);
379         if (!g_date_valid (date)) {
380           GST_DEBUG_OBJECT (demux, "Failed to parse string as date");
381         } else {
382           gst_tag_list_add (demux->taglist, GST_TAG_MERGE_REPLACE,
383               GST_TAG_DATE, date, NULL);
384         }
385         g_date_free (date);
386       } else if (!strcmp (tag_name, "creator")) {
387         gst_tag_list_add (demux->taglist, GST_TAG_MERGE_REPLACE,
388             GST_TAG_ARTIST, s, NULL);
389       } else if (!strcmp (tag_name, "title")) {
390         gst_tag_list_add (demux->taglist, GST_TAG_MERGE_REPLACE,
391             GST_TAG_TITLE, s, NULL);
392       } else if (!strcmp (tag_name, "metadatacreator")) {
393         gst_tag_list_add (demux->taglist, GST_TAG_MERGE_REPLACE,
394             GST_TAG_ENCODER, s, NULL);
395       } else {
396         GST_INFO_OBJECT (demux, "Tag \'%s\' not handled", tag_name);
397       }
398
399       g_free (s);
400
401       break;
402     }
403     case 3:                    /* Object */
404     {
405       gboolean end_of_object_marker = FALSE;
406
407       while (!end_of_object_marker) {
408         gboolean ok = gst_flv_demux_parse_metadata_item (demux, reader,
409             &end_of_object_marker);
410
411         if (G_UNLIKELY (!ok)) {
412           GST_WARNING_OBJECT (demux, "failed reading a tag, skipping");
413           goto error;
414         }
415       }
416
417       break;
418     }
419     case 8:                    /* ECMA array */
420     {
421       guint32 nb_elems = 0;
422       gboolean end_of_object_marker = FALSE;
423
424       if (!gst_byte_reader_get_uint32_be (reader, &nb_elems))
425         goto error;
426
427       GST_DEBUG_OBJECT (demux, "there are approx. %d elements in the array",
428           nb_elems);
429
430       while (!end_of_object_marker) {
431         gboolean ok = gst_flv_demux_parse_metadata_item (demux, reader,
432             &end_of_object_marker);
433
434         if (G_UNLIKELY (!ok)) {
435           GST_WARNING_OBJECT (demux, "failed reading a tag, skipping");
436           goto error;
437         }
438       }
439
440       break;
441     }
442     case 9:                    /* End marker */
443     {
444       GST_DEBUG_OBJECT (demux, "end marker ?");
445       if (tag_name[0] == '\0') {
446
447         GST_DEBUG_OBJECT (demux, "end marker detected");
448
449         *end_marker = TRUE;
450       }
451
452       break;
453     }
454     case 10:                   /* Array */
455     {
456       guint32 nb_elems = 0;
457
458       if (!gst_byte_reader_get_uint32_be (reader, &nb_elems))
459         goto error;
460
461       GST_DEBUG_OBJECT (demux, "array has %d elements", nb_elems);
462
463       if (!strcmp (tag_name, "times")) {
464         if (demux->times) {
465           g_array_free (demux->times, TRUE);
466         }
467         demux->times = g_array_new (FALSE, TRUE, sizeof (gdouble));
468       } else if (!strcmp (tag_name, "filepositions")) {
469         if (demux->filepositions) {
470           g_array_free (demux->filepositions, TRUE);
471         }
472         demux->filepositions = g_array_new (FALSE, TRUE, sizeof (gdouble));
473       }
474
475       while (nb_elems--) {
476         guint8 elem_type = 0;
477
478         if (!gst_byte_reader_get_uint8 (reader, &elem_type))
479           goto error;
480
481         switch (elem_type) {
482           case 0:
483           {
484             gdouble d;
485
486             if (!gst_byte_reader_get_float64_be (reader, &d))
487               goto error;
488
489             GST_DEBUG_OBJECT (demux, "element is a double %f", d);
490
491             if (!strcmp (tag_name, "times") && demux->times) {
492               g_array_append_val (demux->times, d);
493             } else if (!strcmp (tag_name, "filepositions") &&
494                 demux->filepositions) {
495               g_array_append_val (demux->filepositions, d);
496             }
497             break;
498           }
499           default:
500             GST_WARNING_OBJECT (demux, "unsupported array element type %d",
501                 elem_type);
502         }
503       }
504
505       break;
506     }
507     case 11:                   /* Date */
508     {
509       gdouble d = 0;
510       gint16 i = 0;
511
512       if (!gst_byte_reader_get_float64_be (reader, &d))
513         goto error;
514
515       if (!gst_byte_reader_get_int16_be (reader, &i))
516         goto error;
517
518       GST_DEBUG_OBJECT (demux,
519           "%s => (date as a double) %f, timezone offset %d", tag_name, d, i);
520
521       GST_INFO_OBJECT (demux, "Tag \'%s\' not handled", tag_name);
522
523       break;
524     }
525     default:
526       GST_WARNING_OBJECT (demux, "unsupported tag type %d", tag_type);
527   }
528
529   g_free (tag_name);
530
531   return TRUE;
532
533 error:
534   g_free (tag_name);
535
536   return FALSE;
537 }
538
539 static GstFlowReturn
540 gst_flv_demux_parse_tag_script (GstFlvDemux * demux, GstBuffer * buffer)
541 {
542   GstFlowReturn ret = GST_FLOW_OK;
543   GstByteReader reader;
544   guint8 type = 0;
545   GstMapInfo map;
546
547   g_return_val_if_fail (gst_buffer_get_size (buffer) >= 7, GST_FLOW_ERROR);
548
549   gst_buffer_map (buffer, &map, GST_MAP_READ);
550   gst_byte_reader_init (&reader, map.data, map.size);
551
552   gst_byte_reader_skip_unchecked (&reader, 7);
553
554   GST_LOG_OBJECT (demux, "parsing a script tag");
555
556   if (!gst_byte_reader_get_uint8 (&reader, &type))
557     goto cleanup;
558
559   /* Must be string */
560   if (type == 2) {
561     gchar *function_name;
562     guint i;
563
564     function_name = FLV_GET_STRING (&reader);
565
566     GST_LOG_OBJECT (demux, "function name is %s", GST_STR_NULL (function_name));
567
568     if (function_name != NULL && strcmp (function_name, "onMetaData") == 0) {
569       gboolean end_marker = FALSE;
570       GST_DEBUG_OBJECT (demux, "we have a metadata script object");
571
572       if (!gst_byte_reader_get_uint8 (&reader, &type)) {
573         g_free (function_name);
574         goto cleanup;
575       }
576
577       switch (type) {
578         case 8:
579         {
580           guint32 nb_elems = 0;
581
582           /* ECMA array */
583           if (!gst_byte_reader_get_uint32_be (&reader, &nb_elems)) {
584             g_free (function_name);
585             goto cleanup;
586           }
587
588           /* The number of elements is just a hint, some files have
589              nb_elements == 0 and actually contain items. */
590           GST_DEBUG_OBJECT (demux, "there are approx. %d elements in the array",
591               nb_elems);
592         }
593           /* fallthrough to read data */
594         case 3:
595         {
596           /* Object */
597           while (!end_marker) {
598             gboolean ok =
599                 gst_flv_demux_parse_metadata_item (demux, &reader, &end_marker);
600
601             if (G_UNLIKELY (!ok)) {
602               GST_WARNING_OBJECT (demux, "failed reading a tag, skipping");
603               break;
604             }
605           }
606         }
607           break;
608         default:
609           GST_DEBUG_OBJECT (demux, "Unhandled script data type : %d", type);
610           g_free (function_name);
611           goto cleanup;
612       }
613
614       demux->push_tags = TRUE;
615     }
616
617     g_free (function_name);
618
619     if (demux->times && demux->filepositions) {
620       guint num;
621
622       /* If an index was found, insert associations */
623       num = MIN (demux->times->len, demux->filepositions->len);
624       for (i = 0; i < num; i++) {
625         guint64 time, fileposition;
626
627         time = g_array_index (demux->times, gdouble, i) * GST_SECOND;
628         fileposition = g_array_index (demux->filepositions, gdouble, i);
629         gst_flv_demux_parse_and_add_index_entry (demux, time, fileposition,
630             TRUE);
631       }
632       demux->indexed = TRUE;
633     }
634   }
635
636 cleanup:
637   gst_buffer_unmap (buffer, &map);
638
639   return ret;
640 }
641
642 static gboolean
643 have_group_id (GstFlvDemux * demux)
644 {
645   GstEvent *event;
646
647   event = gst_pad_get_sticky_event (demux->sinkpad, GST_EVENT_STREAM_START, 0);
648   if (event) {
649     if (gst_event_parse_group_id (event, &demux->group_id))
650       demux->have_group_id = TRUE;
651     else
652       demux->have_group_id = FALSE;
653     gst_event_unref (event);
654   } else if (!demux->have_group_id) {
655     demux->have_group_id = TRUE;
656     demux->group_id = gst_util_group_id_next ();
657   }
658
659   return demux->have_group_id;
660 }
661
662 static gboolean
663 gst_flv_demux_audio_negotiate (GstFlvDemux * demux, guint32 codec_tag,
664     guint32 rate, guint32 channels, guint32 width)
665 {
666   GstCaps *caps = NULL, *old_caps;
667   gchar *codec_name = NULL;
668   gboolean ret = FALSE;
669   guint adjusted_rate = rate;
670   GstEvent *event;
671   gchar *stream_id;
672
673   switch (codec_tag) {
674     case 1:
675       caps = gst_caps_new_simple ("audio/x-adpcm", "layout", G_TYPE_STRING,
676           "swf", NULL);
677       break;
678     case 2:
679     case 14:
680       caps = gst_caps_new_simple ("audio/mpeg",
681           "mpegversion", G_TYPE_INT, 1, "layer", G_TYPE_INT, 3,
682           "parsed", G_TYPE_BOOLEAN, TRUE, NULL);
683       break;
684     case 0:
685     case 3:
686     {
687       GstAudioFormat format;
688
689       /* Assuming little endian for 0 (aka endianness of the
690        * system on which the file was created) as most people
691        * are probably using little endian machines */
692       format = gst_audio_format_build_integer ((width == 8) ? FALSE : TRUE,
693           G_LITTLE_ENDIAN, width, width);
694
695       caps = gst_caps_new_simple ("audio/x-raw",
696           "format", G_TYPE_STRING, gst_audio_format_to_string (format),
697           "layout", G_TYPE_STRING, "interleaved", NULL);
698       break;
699     }
700     case 4:
701     case 5:
702     case 6:
703       caps = gst_caps_new_empty_simple ("audio/x-nellymoser");
704       break;
705     case 10:
706     {
707       GstMapInfo map;
708       if (!demux->audio_codec_data) {
709         GST_DEBUG_OBJECT (demux, "don't have AAC codec data yet");
710         ret = TRUE;
711         goto done;
712       }
713
714       gst_buffer_map (demux->audio_codec_data, &map, GST_MAP_READ);
715
716       /* use codec-data to extract and verify samplerate */
717       if (map.size >= 2) {
718         gint freq_index;
719
720         freq_index = GST_READ_UINT16_BE (map.data);
721         freq_index = (freq_index & 0x0780) >> 7;
722         adjusted_rate =
723             gst_codec_utils_aac_get_sample_rate_from_index (freq_index);
724
725         if (adjusted_rate && (rate != adjusted_rate)) {
726           GST_LOG_OBJECT (demux, "Ajusting AAC sample rate %d -> %d", rate,
727               adjusted_rate);
728         } else {
729           adjusted_rate = rate;
730         }
731       }
732       gst_buffer_unmap (demux->audio_codec_data, &map);
733
734       caps = gst_caps_new_simple ("audio/mpeg",
735           "mpegversion", G_TYPE_INT, 4, "framed", G_TYPE_BOOLEAN, TRUE,
736           "stream-format", G_TYPE_STRING, "raw", NULL);
737       break;
738     }
739     case 7:
740       caps = gst_caps_new_empty_simple ("audio/x-alaw");
741       break;
742     case 8:
743       caps = gst_caps_new_empty_simple ("audio/x-mulaw");
744       break;
745     case 11:
746     {
747       GValue streamheader = G_VALUE_INIT;
748       GValue value = G_VALUE_INIT;
749       GstByteWriter w;
750       GstStructure *structure;
751       GstBuffer *buf;
752
753       caps = gst_caps_new_empty_simple ("audio/x-speex");
754       structure = gst_caps_get_structure (caps, 0);
755
756       GST_DEBUG_OBJECT (demux, "generating speex header");
757
758       /* Speex decoder expects streamheader to be { [header], [comment] } */
759       g_value_init (&streamheader, GST_TYPE_ARRAY);
760
761       /* header part */
762       gst_byte_writer_init_with_size (&w, 80, TRUE);
763       gst_byte_writer_put_data (&w, (guint8 *) "Speex   ", 8);
764       gst_byte_writer_put_data (&w, (guint8 *) "1.1.12", 7);
765       gst_byte_writer_fill (&w, 0, 13);
766       gst_byte_writer_put_uint32_le (&w, 1);    /* version */
767       gst_byte_writer_put_uint32_le (&w, 80);   /* header_size */
768       gst_byte_writer_put_uint32_le (&w, 16000);        /* rate */
769       gst_byte_writer_put_uint32_le (&w, 1);    /* mode: Wideband */
770       gst_byte_writer_put_uint32_le (&w, 4);    /* mode_bitstream_version */
771       gst_byte_writer_put_uint32_le (&w, 1);    /* nb_channels: 1 */
772       gst_byte_writer_put_uint32_le (&w, -1);   /* bitrate */
773       gst_byte_writer_put_uint32_le (&w, 0x50); /* frame_size */
774       gst_byte_writer_put_uint32_le (&w, 0);    /* VBR */
775       gst_byte_writer_put_uint32_le (&w, 1);    /* frames_per_packet */
776       gst_byte_writer_put_uint32_le (&w, 0);    /* extra_headers */
777       gst_byte_writer_put_uint32_le (&w, 0);    /* reserved1 */
778       gst_byte_writer_put_uint32_le (&w, 0);    /* reserved2 */
779       g_assert (gst_byte_writer_get_size (&w) == 80);
780
781       g_value_init (&value, GST_TYPE_BUFFER);
782       g_value_take_boxed (&value, gst_byte_writer_reset_and_get_buffer (&w));
783       gst_value_array_append_value (&streamheader, &value);
784       g_value_unset (&value);
785
786       /* comment part */
787       g_value_init (&value, GST_TYPE_BUFFER);
788       buf = gst_buffer_new_wrapped (g_memdup ("No comments", 12), 12);
789       g_value_take_boxed (&value, buf);
790       gst_value_array_append_value (&streamheader, &value);
791       g_value_unset (&value);
792
793       gst_structure_take_value (structure, "streamheader", &streamheader);
794
795       channels = 1;
796       adjusted_rate = 16000;
797       break;
798     }
799     default:
800       GST_WARNING_OBJECT (demux, "unsupported audio codec tag %u", codec_tag);
801       break;
802   }
803
804   if (G_UNLIKELY (!caps)) {
805     GST_WARNING_OBJECT (demux, "failed creating caps for audio pad");
806     goto beach;
807   }
808
809   gst_caps_set_simple (caps, "rate", G_TYPE_INT, adjusted_rate,
810       "channels", G_TYPE_INT, channels, NULL);
811
812   if (demux->audio_codec_data) {
813     gst_caps_set_simple (caps, "codec_data", GST_TYPE_BUFFER,
814         demux->audio_codec_data, NULL);
815   }
816
817   old_caps = gst_pad_get_current_caps (demux->audio_pad);
818   if (!old_caps) {
819     stream_id =
820         gst_pad_create_stream_id (demux->audio_pad, GST_ELEMENT_CAST (demux),
821         "audio");
822
823     event = gst_event_new_stream_start (stream_id);
824     if (have_group_id (demux))
825       gst_event_set_group_id (event, demux->group_id);
826     gst_pad_push_event (demux->audio_pad, event);
827     g_free (stream_id);
828   }
829   if (!old_caps || !gst_caps_is_equal (old_caps, caps))
830     ret = gst_pad_set_caps (demux->audio_pad, caps);
831   else
832     ret = TRUE;
833
834   if (old_caps)
835     gst_caps_unref (old_caps);
836
837 done:
838   if (G_LIKELY (ret)) {
839     /* Store the caps we got from tags */
840     demux->audio_codec_tag = codec_tag;
841     demux->rate = rate;
842     demux->channels = channels;
843     demux->width = width;
844
845     if (caps) {
846       codec_name = gst_pb_utils_get_codec_description (caps);
847
848       if (codec_name) {
849         if (demux->taglist == NULL)
850           demux->taglist = gst_tag_list_new_empty ();
851         gst_tag_list_add (demux->taglist, GST_TAG_MERGE_REPLACE,
852             GST_TAG_AUDIO_CODEC, codec_name, NULL);
853         g_free (codec_name);
854       }
855
856       GST_DEBUG_OBJECT (demux->audio_pad, "successfully negotiated caps %"
857           GST_PTR_FORMAT, caps);
858     } else {
859       GST_DEBUG_OBJECT (demux->audio_pad, "delayed setting caps");
860     }
861   } else {
862     GST_WARNING_OBJECT (demux->audio_pad, "failed negotiating caps %"
863         GST_PTR_FORMAT, caps);
864   }
865
866   if (caps)
867     gst_caps_unref (caps);
868
869 beach:
870   return ret;
871 }
872
873 static gboolean
874 gst_flv_demux_push_src_event (GstFlvDemux * demux, GstEvent * event)
875 {
876   gboolean ret = TRUE;
877
878   if (demux->audio_pad)
879     ret |= gst_pad_push_event (demux->audio_pad, gst_event_ref (event));
880
881   if (demux->video_pad)
882     ret |= gst_pad_push_event (demux->video_pad, gst_event_ref (event));
883
884   gst_event_unref (event);
885
886   return ret;
887 }
888
889 static void
890 gst_flv_demux_push_tags (GstFlvDemux * demux)
891 {
892   if (demux->has_audio && !demux->audio_pad) {
893     GST_DEBUG_OBJECT (demux,
894         "Waiting for audio stream pad to come up before we can push tags");
895     return;
896   }
897   if (demux->has_video && !demux->video_pad) {
898     GST_DEBUG_OBJECT (demux,
899         "Waiting for video stream pad to come up before we can push tags");
900     return;
901   }
902   if (demux->taglist) {
903     GST_DEBUG_OBJECT (demux, "pushing tags out %" GST_PTR_FORMAT,
904         demux->taglist);
905     gst_tag_list_set_scope (demux->taglist, GST_TAG_SCOPE_GLOBAL);
906     gst_flv_demux_push_src_event (demux, gst_event_new_tag (demux->taglist));
907     demux->taglist = gst_tag_list_new_empty ();
908     demux->push_tags = FALSE;
909   }
910 }
911
912 static gboolean
913 gst_flv_demux_update_resync (GstFlvDemux * demux, guint32 dts, gboolean discont,
914     guint32 * last, GstClockTime * offset)
915 {
916   gboolean ret = FALSE;
917   gint32 ddts = dts - *last;
918   if (!discont && ddts <= -RESYNC_THRESHOLD) {
919     /* Theoretically, we should use substract the duration of the last buffer,
920        but this demuxer sends no durations on buffers, not sure if it cannot
921        know, or just does not care to calculate. */
922     *offset -= ddts * GST_MSECOND;
923     GST_WARNING_OBJECT (demux,
924         "Large dts gap (%" G_GINT32_FORMAT " ms), assuming resync, offset now %"
925         GST_TIME_FORMAT "", ddts, GST_TIME_ARGS (*offset));
926
927     ret = TRUE;
928   }
929   *last = dts;
930
931   return ret;
932 }
933
934 static GstFlowReturn
935 gst_flv_demux_parse_tag_audio (GstFlvDemux * demux, GstBuffer * buffer)
936 {
937   GstFlowReturn ret = GST_FLOW_OK;
938   guint32 pts = 0, codec_tag = 0, rate = 5512, width = 8, channels = 1;
939   guint32 codec_data = 0, pts_ext = 0;
940   guint8 flags = 0;
941   GstMapInfo map;
942   GstBuffer *outbuf;
943   guint8 *data;
944
945   GST_LOG_OBJECT (demux, "parsing an audio tag");
946
947   if (G_UNLIKELY (!demux->audio_pad && demux->no_more_pads)) {
948 #ifndef GST_DISABLE_DEBUG
949     if (G_UNLIKELY (!demux->no_audio_warned)) {
950       GST_WARNING_OBJECT (demux,
951           "Signaled no-more-pads already but had no audio pad -- ignoring");
952       demux->no_audio_warned = TRUE;
953     }
954 #endif
955     return GST_FLOW_OK;
956   }
957
958   g_return_val_if_fail (gst_buffer_get_size (buffer) == demux->tag_size,
959       GST_FLOW_ERROR);
960
961   /* Error out on tags with too small headers */
962   if (gst_buffer_get_size (buffer) < 11) {
963     GST_ERROR_OBJECT (demux, "Too small tag size (%" G_GSIZE_FORMAT ")",
964         gst_buffer_get_size (buffer));
965     return GST_FLOW_ERROR;
966   }
967
968   gst_buffer_map (buffer, &map, GST_MAP_READ);
969   data = map.data;
970
971   /* Grab information about audio tag */
972   pts = GST_READ_UINT24_BE (data);
973   /* read the pts extension to 32 bits integer */
974   pts_ext = GST_READ_UINT8 (data + 3);
975   /* Combine them */
976   pts |= pts_ext << 24;
977
978   GST_LOG_OBJECT (demux, "pts bytes %02X %02X %02X %02X (%d)", data[0], data[1],
979       data[2], data[3], pts);
980
981   /* Skip the stream id and go directly to the flags */
982   flags = GST_READ_UINT8 (data + 7);
983
984   /* Silently skip buffers with no data */
985   if (map.size == 11)
986     goto beach;
987
988   /* Channels */
989   if (flags & 0x01) {
990     channels = 2;
991   }
992   /* Width */
993   if (flags & 0x02) {
994     width = 16;
995   }
996   /* Sampling rate */
997   if ((flags & 0x0C) == 0x0C) {
998     rate = 44100;
999   } else if ((flags & 0x0C) == 0x08) {
1000     rate = 22050;
1001   } else if ((flags & 0x0C) == 0x04) {
1002     rate = 11025;
1003   }
1004   /* Codec tag */
1005   codec_tag = flags >> 4;
1006   if (codec_tag == 10) {        /* AAC has an extra byte for packet type */
1007     codec_data = 2;
1008   } else {
1009     codec_data = 1;
1010   }
1011
1012   /* codec tags with special rates */
1013   if (codec_tag == 5 || codec_tag == 14)
1014     rate = 8000;
1015   else if (codec_tag == 4)
1016     rate = 16000;
1017
1018   GST_LOG_OBJECT (demux, "audio tag with %d channels, %dHz sampling rate, "
1019       "%d bits width, codec tag %u (flags %02X)", channels, rate, width,
1020       codec_tag, flags);
1021
1022   /* If we don't have our audio pad created, then create it. */
1023   if (G_UNLIKELY (!demux->audio_pad)) {
1024
1025     demux->audio_pad =
1026         gst_pad_new_from_template (gst_element_class_get_pad_template
1027         (GST_ELEMENT_GET_CLASS (demux), "audio"), "audio");
1028     if (G_UNLIKELY (!demux->audio_pad)) {
1029       GST_WARNING_OBJECT (demux, "failed creating audio pad");
1030       ret = GST_FLOW_ERROR;
1031       goto beach;
1032     }
1033
1034     /* Set functions on the pad */
1035     gst_pad_set_query_function (demux->audio_pad,
1036         GST_DEBUG_FUNCPTR (gst_flv_demux_query));
1037     gst_pad_set_event_function (demux->audio_pad,
1038         GST_DEBUG_FUNCPTR (gst_flv_demux_src_event));
1039
1040     gst_pad_use_fixed_caps (demux->audio_pad);
1041
1042     /* Make it active */
1043     gst_pad_set_active (demux->audio_pad, TRUE);
1044
1045     /* Negotiate caps */
1046     if (!gst_flv_demux_audio_negotiate (demux, codec_tag, rate, channels,
1047             width)) {
1048       gst_object_unref (demux->audio_pad);
1049       demux->audio_pad = NULL;
1050       ret = GST_FLOW_ERROR;
1051       goto beach;
1052     }
1053 #ifndef GST_DISABLE_GST_DEBUG
1054     {
1055       GstCaps *caps;
1056
1057       caps = gst_pad_get_current_caps (demux->audio_pad);
1058       GST_DEBUG_OBJECT (demux, "created audio pad with caps %" GST_PTR_FORMAT,
1059           caps);
1060       if (caps)
1061         gst_caps_unref (caps);
1062     }
1063 #endif
1064
1065     /* We need to set caps before adding */
1066     gst_element_add_pad (GST_ELEMENT (demux),
1067         gst_object_ref (demux->audio_pad));
1068     gst_flow_combiner_add_pad (demux->flowcombiner, demux->audio_pad);
1069
1070     /* We only emit no more pads when we have audio and video. Indeed we can
1071      * not trust the FLV header to tell us if there will be only audio or
1072      * only video and we would just break discovery of some files */
1073     if (demux->audio_pad && demux->video_pad) {
1074       GST_DEBUG_OBJECT (demux, "emitting no more pads");
1075       gst_element_no_more_pads (GST_ELEMENT (demux));
1076       demux->no_more_pads = TRUE;
1077       demux->push_tags = TRUE;
1078     }
1079   }
1080
1081   /* Check if caps have changed */
1082   if (G_UNLIKELY (rate != demux->rate || channels != demux->channels ||
1083           codec_tag != demux->audio_codec_tag || width != demux->width)) {
1084     GST_DEBUG_OBJECT (demux, "audio settings have changed, changing caps");
1085
1086     gst_buffer_replace (&demux->audio_codec_data, NULL);
1087
1088     /* Negotiate caps */
1089     if (!gst_flv_demux_audio_negotiate (demux, codec_tag, rate, channels,
1090             width)) {
1091       ret = GST_FLOW_ERROR;
1092       goto beach;
1093     }
1094   }
1095
1096   /* Push taglist if present */
1097   if (G_UNLIKELY (demux->push_tags))
1098     gst_flv_demux_push_tags (demux);
1099
1100   /* Check if we have anything to push */
1101   if (demux->tag_data_size <= codec_data) {
1102     GST_LOG_OBJECT (demux, "Nothing left in this tag, returning");
1103     goto beach;
1104   }
1105
1106   /* Create buffer from pad */
1107   outbuf = gst_buffer_copy_region (buffer, GST_BUFFER_COPY_MEMORY,
1108       7 + codec_data, demux->tag_data_size - codec_data);
1109
1110   if (demux->audio_codec_tag == 10) {
1111     guint8 aac_packet_type = GST_READ_UINT8 (data + 8);
1112
1113     switch (aac_packet_type) {
1114       case 0:
1115       {
1116         /* AudioSpecificConfig data */
1117         GST_LOG_OBJECT (demux, "got an AAC codec data packet");
1118         if (demux->audio_codec_data) {
1119           gst_buffer_unref (demux->audio_codec_data);
1120         }
1121         demux->audio_codec_data = outbuf;
1122         /* Use that buffer data in the caps */
1123         gst_flv_demux_audio_negotiate (demux, codec_tag, rate, channels, width);
1124         goto beach;
1125       }
1126       case 1:
1127         if (!demux->audio_codec_data) {
1128           GST_ERROR_OBJECT (demux, "got AAC audio packet before codec data");
1129           ret = GST_FLOW_OK;
1130           gst_buffer_unref (outbuf);
1131           goto beach;
1132         }
1133         /* AAC raw packet */
1134         GST_LOG_OBJECT (demux, "got a raw AAC audio packet");
1135         break;
1136       default:
1137         GST_WARNING_OBJECT (demux, "invalid AAC packet type %u",
1138             aac_packet_type);
1139     }
1140   }
1141
1142   /* detect (and deem to be resyncs)  large pts gaps */
1143   if (gst_flv_demux_update_resync (demux, pts, demux->audio_need_discont,
1144           &demux->last_audio_pts, &demux->audio_time_offset)) {
1145     GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_RESYNC);
1146   }
1147
1148   /* Fill buffer with data */
1149   GST_BUFFER_PTS (outbuf) = pts * GST_MSECOND + demux->audio_time_offset;
1150   GST_BUFFER_DTS (outbuf) = GST_BUFFER_PTS (outbuf);
1151   GST_BUFFER_DURATION (outbuf) = GST_CLOCK_TIME_NONE;
1152   GST_BUFFER_OFFSET (outbuf) = demux->audio_offset++;
1153   GST_BUFFER_OFFSET_END (outbuf) = demux->audio_offset;
1154
1155   if (demux->duration == GST_CLOCK_TIME_NONE ||
1156       demux->duration < GST_BUFFER_TIMESTAMP (outbuf))
1157     demux->duration = GST_BUFFER_TIMESTAMP (outbuf);
1158
1159   /* Only add audio frames to the index if we have no video,
1160    * and if the index is not yet complete */
1161   if (!demux->has_video && !demux->indexed) {
1162     gst_flv_demux_parse_and_add_index_entry (demux,
1163         GST_BUFFER_TIMESTAMP (outbuf), demux->cur_tag_offset, TRUE);
1164   }
1165
1166   if (G_UNLIKELY (demux->audio_need_discont)) {
1167     GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_DISCONT);
1168     demux->audio_need_discont = FALSE;
1169   }
1170
1171   demux->segment.position = GST_BUFFER_TIMESTAMP (outbuf);
1172
1173   /* Do we need a newsegment event ? */
1174   if (G_UNLIKELY (demux->audio_need_segment)) {
1175     if (!demux->new_seg_event) {
1176       GST_DEBUG_OBJECT (demux, "pushing newsegment from %"
1177           GST_TIME_FORMAT " to %" GST_TIME_FORMAT,
1178           GST_TIME_ARGS (demux->segment.position),
1179           GST_TIME_ARGS (demux->segment.stop));
1180       demux->segment.start = demux->segment.time = demux->segment.position;
1181       demux->new_seg_event = gst_event_new_segment (&demux->segment);
1182     } else {
1183       GST_DEBUG_OBJECT (demux, "pushing pre-generated newsegment event");
1184     }
1185
1186     gst_pad_push_event (demux->audio_pad, gst_event_ref (demux->new_seg_event));
1187
1188     demux->audio_need_segment = FALSE;
1189   }
1190
1191   GST_LOG_OBJECT (demux,
1192       "pushing %" G_GSIZE_FORMAT " bytes buffer at pts %" GST_TIME_FORMAT
1193       " with duration %" GST_TIME_FORMAT ", offset %" G_GUINT64_FORMAT,
1194       gst_buffer_get_size (outbuf),
1195       GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (outbuf)),
1196       GST_TIME_ARGS (GST_BUFFER_DURATION (outbuf)), GST_BUFFER_OFFSET (outbuf));
1197
1198   if (!GST_CLOCK_TIME_IS_VALID (demux->audio_start)) {
1199     demux->audio_start = GST_BUFFER_TIMESTAMP (outbuf);
1200   }
1201   if (!GST_CLOCK_TIME_IS_VALID (demux->audio_first_ts)) {
1202     demux->audio_first_ts = GST_BUFFER_TIMESTAMP (outbuf);
1203   }
1204
1205   if (G_UNLIKELY (!demux->no_more_pads
1206           && (GST_CLOCK_DIFF (demux->audio_start,
1207                   GST_BUFFER_TIMESTAMP (outbuf)) > NO_MORE_PADS_THRESHOLD))) {
1208     GST_DEBUG_OBJECT (demux,
1209         "Signalling no-more-pads because no video stream was found"
1210         " after 6 seconds of audio");
1211     gst_element_no_more_pads (GST_ELEMENT_CAST (demux));
1212     demux->no_more_pads = TRUE;
1213     demux->push_tags = TRUE;
1214   }
1215
1216   /* Push downstream */
1217   ret = gst_pad_push (demux->audio_pad, outbuf);
1218
1219   if (G_UNLIKELY (ret != GST_FLOW_OK) &&
1220       demux->segment.rate < 0.0 && ret == GST_FLOW_EOS &&
1221       demux->segment.position > demux->segment.stop) {
1222     /* In reverse playback we can get a GST_FLOW_EOS when
1223      * we are at the end of the segment, so we just need to jump
1224      * back to the previous section. */
1225     GST_DEBUG_OBJECT (demux, "downstream has reached end of segment");
1226     demux->audio_done = TRUE;
1227     ret = GST_FLOW_OK;
1228     goto beach;
1229   }
1230
1231   ret = gst_flow_combiner_update_pad_flow (demux->flowcombiner,
1232       demux->audio_pad, ret);
1233
1234 beach:
1235   gst_buffer_unmap (buffer, &map);
1236
1237   return ret;
1238 }
1239
1240 static gboolean
1241 gst_flv_demux_video_negotiate (GstFlvDemux * demux, guint32 codec_tag)
1242 {
1243   gboolean ret = FALSE;
1244   GstCaps *caps = NULL, *old_caps;
1245   gchar *codec_name = NULL;
1246   GstEvent *event;
1247   gchar *stream_id;
1248
1249   /* Generate caps for that pad */
1250   switch (codec_tag) {
1251     case 2:
1252       caps =
1253           gst_caps_new_simple ("video/x-flash-video", "flvversion", G_TYPE_INT,
1254           1, NULL);
1255       break;
1256     case 3:
1257       caps = gst_caps_new_empty_simple ("video/x-flash-screen");
1258       break;
1259     case 4:
1260       caps = gst_caps_new_empty_simple ("video/x-vp6-flash");
1261       break;
1262     case 5:
1263       caps = gst_caps_new_empty_simple ("video/x-vp6-alpha");
1264       break;
1265     case 7:
1266       if (!demux->video_codec_data) {
1267         GST_DEBUG_OBJECT (demux, "don't have h264 codec data yet");
1268         ret = TRUE;
1269         goto done;
1270       }
1271       caps =
1272           gst_caps_new_simple ("video/x-h264", "stream-format", G_TYPE_STRING,
1273           "avc", NULL);
1274       break;
1275     default:
1276       GST_WARNING_OBJECT (demux, "unsupported video codec tag %u", codec_tag);
1277   }
1278
1279   if (G_UNLIKELY (!caps)) {
1280     GST_WARNING_OBJECT (demux, "failed creating caps for video pad");
1281     goto beach;
1282   }
1283
1284   gst_caps_set_simple (caps, "pixel-aspect-ratio", GST_TYPE_FRACTION,
1285       demux->par_x, demux->par_y, NULL);
1286
1287   if (G_LIKELY (demux->w)) {
1288     gst_caps_set_simple (caps, "width", G_TYPE_INT, demux->w, NULL);
1289   }
1290
1291   if (G_LIKELY (demux->h)) {
1292     gst_caps_set_simple (caps, "height", G_TYPE_INT, demux->h, NULL);
1293   }
1294
1295   if (G_LIKELY (demux->framerate)) {
1296     gint num = 0, den = 0;
1297
1298     gst_video_guess_framerate (GST_SECOND / demux->framerate, &num, &den);
1299     GST_DEBUG_OBJECT (demux->video_pad,
1300         "fps to be used on caps %f (as a fraction = %d/%d)", demux->framerate,
1301         num, den);
1302
1303     gst_caps_set_simple (caps, "framerate", GST_TYPE_FRACTION, num, den, NULL);
1304   }
1305
1306   if (demux->video_codec_data) {
1307     gst_caps_set_simple (caps, "codec_data", GST_TYPE_BUFFER,
1308         demux->video_codec_data, NULL);
1309   }
1310
1311   old_caps = gst_pad_get_current_caps (demux->video_pad);
1312   if (!old_caps) {
1313     stream_id =
1314         gst_pad_create_stream_id (demux->video_pad, GST_ELEMENT_CAST (demux),
1315         "video");
1316     event = gst_event_new_stream_start (stream_id);
1317     g_free (stream_id);
1318
1319     if (have_group_id (demux))
1320       gst_event_set_group_id (event, demux->group_id);
1321     gst_pad_push_event (demux->video_pad, event);
1322   }
1323
1324   if (!old_caps || !gst_caps_is_equal (old_caps, caps))
1325     ret = gst_pad_set_caps (demux->video_pad, caps);
1326   else
1327     ret = TRUE;
1328
1329   if (old_caps)
1330     gst_caps_unref (old_caps);
1331
1332 done:
1333   if (G_LIKELY (ret)) {
1334     /* Store the caps we have set */
1335     demux->video_codec_tag = codec_tag;
1336
1337     if (caps) {
1338       codec_name = gst_pb_utils_get_codec_description (caps);
1339
1340       if (codec_name) {
1341         if (demux->taglist == NULL)
1342           demux->taglist = gst_tag_list_new_empty ();
1343         gst_tag_list_add (demux->taglist, GST_TAG_MERGE_REPLACE,
1344             GST_TAG_VIDEO_CODEC, codec_name, NULL);
1345         g_free (codec_name);
1346       }
1347
1348       GST_DEBUG_OBJECT (demux->video_pad, "successfully negotiated caps %"
1349           GST_PTR_FORMAT, caps);
1350     } else {
1351       GST_DEBUG_OBJECT (demux->video_pad, "delayed setting caps");
1352     }
1353   } else {
1354     GST_WARNING_OBJECT (demux->video_pad, "failed negotiating caps %"
1355         GST_PTR_FORMAT, caps);
1356   }
1357
1358   if (caps)
1359     gst_caps_unref (caps);
1360
1361 beach:
1362   return ret;
1363 }
1364
1365 static GstFlowReturn
1366 gst_flv_demux_parse_tag_video (GstFlvDemux * demux, GstBuffer * buffer)
1367 {
1368   GstFlowReturn ret = GST_FLOW_OK;
1369   guint32 dts = 0, codec_data = 1, dts_ext = 0;
1370   gint32 cts = 0;
1371   gboolean keyframe = FALSE;
1372   guint8 flags = 0, codec_tag = 0;
1373   GstBuffer *outbuf;
1374   GstMapInfo map;
1375   guint8 *data;
1376
1377   g_return_val_if_fail (gst_buffer_get_size (buffer) == demux->tag_size,
1378       GST_FLOW_ERROR);
1379
1380   GST_LOG_OBJECT (demux, "parsing a video tag");
1381
1382   if G_UNLIKELY
1383     (!demux->video_pad && demux->no_more_pads) {
1384 #ifndef GST_DISABLE_DEBUG
1385     if G_UNLIKELY
1386       (!demux->no_video_warned) {
1387       GST_WARNING_OBJECT (demux,
1388           "Signaled no-more-pads already but had no video pad -- ignoring");
1389       demux->no_video_warned = TRUE;
1390       }
1391 #endif
1392     return GST_FLOW_OK;
1393     }
1394
1395   if (gst_buffer_get_size (buffer) < 12) {
1396     GST_ERROR_OBJECT (demux, "Too small tag size");
1397     return GST_FLOW_ERROR;
1398   }
1399
1400   gst_buffer_map (buffer, &map, GST_MAP_READ);
1401   data = map.data;
1402
1403   /* Grab information about video tag */
1404   dts = GST_READ_UINT24_BE (data);
1405   /* read the dts extension to 32 bits integer */
1406   dts_ext = GST_READ_UINT8 (data + 3);
1407   /* Combine them */
1408   dts |= dts_ext << 24;
1409
1410   GST_LOG_OBJECT (demux, "dts bytes %02X %02X %02X %02X (%d)", data[0], data[1],
1411       data[2], data[3], dts);
1412
1413   /* Skip the stream id and go directly to the flags */
1414   flags = GST_READ_UINT8 (data + 7);
1415
1416   /* Keyframe */
1417   if ((flags >> 4) == 1) {
1418     keyframe = TRUE;
1419   }
1420   /* Codec tag */
1421   codec_tag = flags & 0x0F;
1422   if (codec_tag == 4 || codec_tag == 5) {
1423     codec_data = 2;
1424   } else if (codec_tag == 7) {
1425     codec_data = 5;
1426
1427     cts = GST_READ_UINT24_BE (data + 9);
1428     cts = (cts + 0xff800000) ^ 0xff800000;
1429
1430     GST_LOG_OBJECT (demux, "got cts %d", cts);
1431   }
1432
1433   GST_LOG_OBJECT (demux, "video tag with codec tag %u, keyframe (%d) "
1434       "(flags %02X)", codec_tag, keyframe, flags);
1435
1436   /* If we don't have our video pad created, then create it. */
1437   if (G_UNLIKELY (!demux->video_pad)) {
1438     demux->video_pad =
1439         gst_pad_new_from_template (gst_element_class_get_pad_template
1440         (GST_ELEMENT_GET_CLASS (demux), "video"), "video");
1441     if (G_UNLIKELY (!demux->video_pad)) {
1442       GST_WARNING_OBJECT (demux, "failed creating video pad");
1443       ret = GST_FLOW_ERROR;
1444       goto beach;
1445     }
1446
1447     /* Set functions on the pad */
1448     gst_pad_set_query_function (demux->video_pad,
1449         GST_DEBUG_FUNCPTR (gst_flv_demux_query));
1450     gst_pad_set_event_function (demux->video_pad,
1451         GST_DEBUG_FUNCPTR (gst_flv_demux_src_event));
1452
1453     gst_pad_use_fixed_caps (demux->video_pad);
1454
1455     /* Make it active */
1456     gst_pad_set_active (demux->video_pad, TRUE);
1457
1458     /* Needs to be active before setting caps */
1459     if (!gst_flv_demux_video_negotiate (demux, codec_tag)) {
1460       gst_object_unref (demux->video_pad);
1461       demux->video_pad = NULL;
1462       ret = GST_FLOW_ERROR;
1463       goto beach;
1464     }
1465
1466     /* When we ve set pixel-aspect-ratio we use that boolean to detect a
1467      * metadata tag that would come later and trigger a caps change */
1468     demux->got_par = FALSE;
1469
1470 #ifndef GST_DISABLE_GST_DEBUG
1471     {
1472       GstCaps *caps;
1473
1474       caps = gst_pad_get_current_caps (demux->video_pad);
1475       GST_DEBUG_OBJECT (demux, "created video pad with caps %" GST_PTR_FORMAT,
1476           caps);
1477       if (caps)
1478         gst_caps_unref (caps);
1479     }
1480 #endif
1481
1482     /* We need to set caps before adding */
1483     gst_element_add_pad (GST_ELEMENT (demux),
1484         gst_object_ref (demux->video_pad));
1485     gst_flow_combiner_add_pad (demux->flowcombiner, demux->video_pad);
1486
1487     /* We only emit no more pads when we have audio and video. Indeed we can
1488      * not trust the FLV header to tell us if there will be only audio or
1489      * only video and we would just break discovery of some files */
1490     if (demux->audio_pad && demux->video_pad) {
1491       GST_DEBUG_OBJECT (demux, "emitting no more pads");
1492       gst_element_no_more_pads (GST_ELEMENT (demux));
1493       demux->no_more_pads = TRUE;
1494       demux->push_tags = TRUE;
1495     }
1496   }
1497
1498   /* Check if caps have changed */
1499   if (G_UNLIKELY (codec_tag != demux->video_codec_tag || demux->got_par)) {
1500     GST_DEBUG_OBJECT (demux, "video settings have changed, changing caps");
1501     gst_buffer_replace (&demux->video_codec_data, NULL);
1502
1503     if (!gst_flv_demux_video_negotiate (demux, codec_tag)) {
1504       ret = GST_FLOW_ERROR;
1505       goto beach;
1506     }
1507
1508     /* When we ve set pixel-aspect-ratio we use that boolean to detect a
1509      * metadata tag that would come later and trigger a caps change */
1510     demux->got_par = FALSE;
1511   }
1512
1513   /* Push taglist if present */
1514   if (G_UNLIKELY (demux->push_tags))
1515     gst_flv_demux_push_tags (demux);
1516
1517   /* Check if we have anything to push */
1518   if (demux->tag_data_size <= codec_data) {
1519     GST_LOG_OBJECT (demux, "Nothing left in this tag, returning");
1520     goto beach;
1521   }
1522
1523   /* Create buffer from pad */
1524   outbuf = gst_buffer_copy_region (buffer, GST_BUFFER_COPY_MEMORY,
1525       7 + codec_data, demux->tag_data_size - codec_data);
1526
1527   if (demux->video_codec_tag == 7) {
1528     guint8 avc_packet_type = GST_READ_UINT8 (data + 8);
1529
1530     switch (avc_packet_type) {
1531       case 0:
1532       {
1533         /* AVCDecoderConfigurationRecord data */
1534         GST_LOG_OBJECT (demux, "got an H.264 codec data packet");
1535         if (demux->video_codec_data) {
1536           gst_buffer_unref (demux->video_codec_data);
1537         }
1538         demux->video_codec_data = outbuf;
1539         /* Use that buffer data in the caps */
1540         gst_flv_demux_video_negotiate (demux, codec_tag);
1541         goto beach;
1542       }
1543       case 1:
1544         /* H.264 NALU packet */
1545         if (!demux->video_codec_data) {
1546           GST_ERROR_OBJECT (demux, "got H.264 video packet before codec data");
1547           ret = GST_FLOW_OK;
1548           gst_buffer_unref (outbuf);
1549           goto beach;
1550         }
1551         GST_LOG_OBJECT (demux, "got a H.264 NALU video packet");
1552         break;
1553       default:
1554         GST_WARNING_OBJECT (demux, "invalid video packet type %u",
1555             avc_packet_type);
1556     }
1557   }
1558
1559   /* detect (and deem to be resyncs)  large dts gaps */
1560   if (gst_flv_demux_update_resync (demux, dts, demux->video_need_discont,
1561           &demux->last_video_dts, &demux->video_time_offset)) {
1562     GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_RESYNC);
1563   }
1564
1565   /* Fill buffer with data */
1566   GST_LOG_OBJECT (demux, "dts %u pts %u cts %d", dts, dts + cts, cts);
1567
1568   GST_BUFFER_PTS (outbuf) =
1569       (dts + cts) * GST_MSECOND + demux->video_time_offset;
1570   GST_BUFFER_DTS (outbuf) = dts * GST_MSECOND + demux->video_time_offset;
1571   GST_BUFFER_DURATION (outbuf) = GST_CLOCK_TIME_NONE;
1572   GST_BUFFER_OFFSET (outbuf) = demux->video_offset++;
1573   GST_BUFFER_OFFSET_END (outbuf) = demux->video_offset;
1574
1575   if (demux->duration == GST_CLOCK_TIME_NONE ||
1576       demux->duration < GST_BUFFER_TIMESTAMP (outbuf))
1577     demux->duration = GST_BUFFER_TIMESTAMP (outbuf);
1578
1579   if (!keyframe)
1580     GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_DELTA_UNIT);
1581
1582   if (!demux->indexed) {
1583     gst_flv_demux_parse_and_add_index_entry (demux,
1584         GST_BUFFER_TIMESTAMP (outbuf), demux->cur_tag_offset, keyframe);
1585   }
1586
1587   if (G_UNLIKELY (demux->video_need_discont)) {
1588     GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_DISCONT);
1589     demux->video_need_discont = FALSE;
1590   }
1591
1592   demux->segment.position = GST_BUFFER_TIMESTAMP (outbuf);
1593
1594   /* Do we need a newsegment event ? */
1595   if (G_UNLIKELY (demux->video_need_segment)) {
1596     if (!demux->new_seg_event) {
1597       GST_DEBUG_OBJECT (demux, "pushing newsegment from %"
1598           GST_TIME_FORMAT " to %" GST_TIME_FORMAT,
1599           GST_TIME_ARGS (demux->segment.position),
1600           GST_TIME_ARGS (demux->segment.stop));
1601       demux->segment.start = demux->segment.time = demux->segment.position;
1602       demux->new_seg_event = gst_event_new_segment (&demux->segment);
1603     } else {
1604       GST_DEBUG_OBJECT (demux, "pushing pre-generated newsegment event");
1605     }
1606
1607     gst_pad_push_event (demux->video_pad, gst_event_ref (demux->new_seg_event));
1608
1609     demux->video_need_segment = FALSE;
1610   }
1611
1612   GST_LOG_OBJECT (demux,
1613       "pushing %" G_GSIZE_FORMAT " bytes buffer at dts %" GST_TIME_FORMAT
1614       " with duration %" GST_TIME_FORMAT ", offset %" G_GUINT64_FORMAT
1615       ", keyframe (%d)", gst_buffer_get_size (outbuf),
1616       GST_TIME_ARGS (GST_BUFFER_DTS (outbuf)),
1617       GST_TIME_ARGS (GST_BUFFER_DURATION (outbuf)), GST_BUFFER_OFFSET (outbuf),
1618       keyframe);
1619
1620   if (!GST_CLOCK_TIME_IS_VALID (demux->video_start)) {
1621     demux->video_start = GST_BUFFER_TIMESTAMP (outbuf);
1622   }
1623   if (!GST_CLOCK_TIME_IS_VALID (demux->audio_first_ts)) {
1624     demux->video_first_ts = GST_BUFFER_TIMESTAMP (outbuf);
1625   }
1626
1627   if (G_UNLIKELY (!demux->no_more_pads
1628           && (GST_CLOCK_DIFF (demux->video_start,
1629                   GST_BUFFER_TIMESTAMP (outbuf)) > NO_MORE_PADS_THRESHOLD))) {
1630     GST_DEBUG_OBJECT (demux,
1631         "Signalling no-more-pads because no audio stream was found"
1632         " after 6 seconds of video");
1633     gst_element_no_more_pads (GST_ELEMENT_CAST (demux));
1634     demux->no_more_pads = TRUE;
1635     demux->push_tags = TRUE;
1636   }
1637
1638   /* Push downstream */
1639   ret = gst_pad_push (demux->video_pad, outbuf);
1640
1641   if (G_UNLIKELY (ret != GST_FLOW_OK) &&
1642       demux->segment.rate < 0.0 && ret == GST_FLOW_EOS &&
1643       demux->segment.position > demux->segment.stop) {
1644     /* In reverse playback we can get a GST_FLOW_EOS when
1645      * we are at the end of the segment, so we just need to jump
1646      * back to the previous section. */
1647     GST_DEBUG_OBJECT (demux, "downstream has reached end of segment");
1648     demux->video_done = TRUE;
1649     ret = GST_FLOW_OK;
1650     goto beach;
1651   }
1652
1653   ret = gst_flow_combiner_update_pad_flow (demux->flowcombiner,
1654       demux->video_pad, ret);
1655
1656 beach:
1657   gst_buffer_unmap (buffer, &map);
1658   return ret;
1659 }
1660
1661 static GstClockTime
1662 gst_flv_demux_parse_tag_timestamp (GstFlvDemux * demux, gboolean index,
1663     GstBuffer * buffer, size_t * tag_size)
1664 {
1665   guint32 dts = 0, dts_ext = 0;
1666   guint32 tag_data_size;
1667   guint8 type;
1668   gboolean keyframe = TRUE;
1669   GstClockTime ret = GST_CLOCK_TIME_NONE;
1670   GstMapInfo map;
1671   guint8 *data;
1672   gsize size;
1673
1674   g_return_val_if_fail (gst_buffer_get_size (buffer) >= 12,
1675       GST_CLOCK_TIME_NONE);
1676
1677   gst_buffer_map (buffer, &map, GST_MAP_READ);
1678   data = map.data;
1679   size = map.size;
1680
1681   type = data[0];
1682
1683   if (type != 9 && type != 8 && type != 18) {
1684     GST_WARNING_OBJECT (demux, "Unsupported tag type %u", data[0]);
1685     goto exit;
1686   }
1687
1688   if (type == 9)
1689     demux->has_video = TRUE;
1690   else if (type == 8)
1691     demux->has_audio = TRUE;
1692
1693   tag_data_size = GST_READ_UINT24_BE (data + 1);
1694
1695   if (size >= tag_data_size + 11 + 4) {
1696     if (GST_READ_UINT32_BE (data + tag_data_size + 11) != tag_data_size + 11) {
1697       GST_WARNING_OBJECT (demux, "Invalid tag size");
1698       goto exit;
1699     }
1700   }
1701
1702   if (tag_size)
1703     *tag_size = tag_data_size + 11 + 4;
1704
1705   data += 4;
1706
1707   GST_LOG_OBJECT (demux, "dts bytes %02X %02X %02X %02X", data[0], data[1],
1708       data[2], data[3]);
1709
1710   /* Grab timestamp of tag tag */
1711   dts = GST_READ_UINT24_BE (data);
1712   /* read the dts extension to 32 bits integer */
1713   dts_ext = GST_READ_UINT8 (data + 3);
1714   /* Combine them */
1715   dts |= dts_ext << 24;
1716
1717   if (type == 9) {
1718     data += 7;
1719
1720     keyframe = ((data[0] >> 4) == 1);
1721   }
1722
1723   ret = dts * GST_MSECOND;
1724   GST_LOG_OBJECT (demux, "dts: %" GST_TIME_FORMAT, GST_TIME_ARGS (ret));
1725
1726   if (index && !demux->indexed && (type == 9 || (type == 8
1727               && !demux->has_video))) {
1728     gst_flv_demux_parse_and_add_index_entry (demux, ret, demux->offset,
1729         keyframe);
1730   }
1731
1732   if (demux->duration == GST_CLOCK_TIME_NONE || demux->duration < ret)
1733     demux->duration = ret;
1734
1735 exit:
1736   gst_buffer_unmap (buffer, &map);
1737   return ret;
1738 }
1739
1740 static GstFlowReturn
1741 gst_flv_demux_parse_tag_type (GstFlvDemux * demux, GstBuffer * buffer)
1742 {
1743   GstFlowReturn ret = GST_FLOW_OK;
1744   guint8 tag_type = 0;
1745   GstMapInfo map;
1746
1747   g_return_val_if_fail (gst_buffer_get_size (buffer) >= 4, GST_FLOW_ERROR);
1748
1749   gst_buffer_map (buffer, &map, GST_MAP_READ);
1750
1751   tag_type = map.data[0];
1752
1753   /* Tag size is 1 byte of type + 3 bytes of size + 7 bytes + tag data size +
1754    * 4 bytes of previous tag size */
1755   demux->tag_data_size = GST_READ_UINT24_BE (map.data + 1);
1756   demux->tag_size = demux->tag_data_size + 11;
1757
1758   GST_LOG_OBJECT (demux, "tag data size is %" G_GUINT64_FORMAT,
1759       demux->tag_data_size);
1760
1761   gst_buffer_unmap (buffer, &map);
1762
1763   switch (tag_type) {
1764     case 9:
1765       demux->state = FLV_STATE_TAG_VIDEO;
1766       demux->has_video = TRUE;
1767       break;
1768     case 8:
1769       demux->state = FLV_STATE_TAG_AUDIO;
1770       demux->has_audio = TRUE;
1771       break;
1772     case 18:
1773       demux->state = FLV_STATE_TAG_SCRIPT;
1774       break;
1775     default:
1776       GST_WARNING_OBJECT (demux, "unsupported tag type %u", tag_type);
1777       demux->state = FLV_STATE_SKIP;
1778   }
1779
1780   return ret;
1781 }
1782
1783 static GstFlowReturn
1784 gst_flv_demux_parse_header (GstFlvDemux * demux, GstBuffer * buffer)
1785 {
1786   GstFlowReturn ret = GST_FLOW_OK;
1787   GstMapInfo map;
1788
1789   g_return_val_if_fail (gst_buffer_get_size (buffer) >= 9, GST_FLOW_ERROR);
1790
1791   gst_buffer_map (buffer, &map, GST_MAP_READ);
1792
1793   /* Check for the FLV tag */
1794   if (map.data[0] == 'F' && map.data[1] == 'L' && map.data[2] == 'V') {
1795     GST_DEBUG_OBJECT (demux, "FLV header detected");
1796   } else {
1797     if (G_UNLIKELY (demux->strict)) {
1798       GST_WARNING_OBJECT (demux, "invalid header tag detected");
1799       ret = GST_FLOW_EOS;
1800       goto beach;
1801     }
1802   }
1803
1804   if (map.data[3] == '1') {
1805     GST_DEBUG_OBJECT (demux, "FLV version 1 detected");
1806   } else {
1807     if (G_UNLIKELY (demux->strict)) {
1808       GST_WARNING_OBJECT (demux, "invalid header version detected");
1809       ret = GST_FLOW_EOS;
1810       goto beach;
1811     }
1812
1813   }
1814
1815   /* Now look at audio/video flags */
1816   {
1817     guint8 flags = map.data[4];
1818
1819     demux->has_video = demux->has_audio = FALSE;
1820
1821     if (flags & 1) {
1822       GST_DEBUG_OBJECT (demux, "there is a video stream");
1823       demux->has_video = TRUE;
1824     }
1825     if (flags & 4) {
1826       GST_DEBUG_OBJECT (demux, "there is an audio stream");
1827       demux->has_audio = TRUE;
1828     }
1829   }
1830
1831   /* do a one-time seekability check */
1832   gst_flv_demux_check_seekability (demux);
1833
1834   /* We don't care about the rest */
1835   demux->need_header = FALSE;
1836
1837 beach:
1838   gst_buffer_unmap (buffer, &map);
1839   return ret;
1840 }
1841
1842
1843 static void
1844 gst_flv_demux_flush (GstFlvDemux * demux, gboolean discont)
1845 {
1846   GST_DEBUG_OBJECT (demux, "flushing queued data in the FLV demuxer");
1847
1848   gst_adapter_clear (demux->adapter);
1849
1850   demux->audio_need_discont = TRUE;
1851   demux->video_need_discont = TRUE;
1852
1853   demux->flushing = FALSE;
1854
1855   /* Only in push mode and if we're not during a seek */
1856   if (!demux->random_access && demux->state != FLV_STATE_SEEK) {
1857     /* After a flush we expect a tag_type */
1858     demux->state = FLV_STATE_TAG_TYPE;
1859     /* We reset the offset and will get one from first push */
1860     demux->offset = 0;
1861   }
1862 }
1863
1864 static void
1865 gst_flv_demux_cleanup (GstFlvDemux * demux)
1866 {
1867   GST_DEBUG_OBJECT (demux, "cleaning up FLV demuxer");
1868
1869   demux->state = FLV_STATE_HEADER;
1870
1871   demux->have_group_id = FALSE;
1872   demux->group_id = G_MAXUINT;
1873
1874   demux->flushing = FALSE;
1875   demux->need_header = TRUE;
1876   demux->audio_need_segment = TRUE;
1877   demux->video_need_segment = TRUE;
1878   demux->audio_need_discont = TRUE;
1879   demux->video_need_discont = TRUE;
1880
1881   demux->has_audio = FALSE;
1882   demux->has_video = FALSE;
1883   demux->push_tags = FALSE;
1884   demux->got_par = FALSE;
1885
1886   demux->indexed = FALSE;
1887   demux->upstream_seekable = FALSE;
1888   demux->file_size = 0;
1889
1890   demux->index_max_pos = 0;
1891   demux->index_max_time = 0;
1892
1893   demux->audio_start = demux->video_start = GST_CLOCK_TIME_NONE;
1894   demux->last_audio_pts = demux->last_video_dts = 0;
1895   demux->audio_time_offset = demux->video_time_offset = 0;
1896
1897   demux->no_more_pads = FALSE;
1898
1899 #ifndef GST_DISABLE_DEBUG
1900   demux->no_audio_warned = FALSE;
1901   demux->no_video_warned = FALSE;
1902 #endif
1903
1904   gst_segment_init (&demux->segment, GST_FORMAT_TIME);
1905
1906   demux->w = demux->h = 0;
1907   demux->framerate = 0.0;
1908   demux->par_x = demux->par_y = 1;
1909   demux->video_offset = 0;
1910   demux->audio_offset = 0;
1911   demux->offset = demux->cur_tag_offset = 0;
1912   demux->tag_size = demux->tag_data_size = 0;
1913   demux->duration = GST_CLOCK_TIME_NONE;
1914
1915   if (demux->new_seg_event) {
1916     gst_event_unref (demux->new_seg_event);
1917     demux->new_seg_event = NULL;
1918   }
1919
1920   gst_adapter_clear (demux->adapter);
1921
1922   if (demux->audio_codec_data) {
1923     gst_buffer_unref (demux->audio_codec_data);
1924     demux->audio_codec_data = NULL;
1925   }
1926
1927   if (demux->video_codec_data) {
1928     gst_buffer_unref (demux->video_codec_data);
1929     demux->video_codec_data = NULL;
1930   }
1931
1932   if (demux->audio_pad) {
1933     gst_flow_combiner_remove_pad (demux->flowcombiner, demux->audio_pad);
1934     gst_element_remove_pad (GST_ELEMENT (demux), demux->audio_pad);
1935     gst_object_unref (demux->audio_pad);
1936     demux->audio_pad = NULL;
1937   }
1938
1939   if (demux->video_pad) {
1940     gst_flow_combiner_remove_pad (demux->flowcombiner, demux->video_pad);
1941     gst_element_remove_pad (GST_ELEMENT (demux), demux->video_pad);
1942     gst_object_unref (demux->video_pad);
1943     demux->video_pad = NULL;
1944   }
1945
1946   if (demux->times) {
1947     g_array_free (demux->times, TRUE);
1948     demux->times = NULL;
1949   }
1950
1951   if (demux->filepositions) {
1952     g_array_free (demux->filepositions, TRUE);
1953     demux->filepositions = NULL;
1954   }
1955 }
1956
1957 /*
1958  * Create and push a flushing seek event upstream
1959  */
1960 static gboolean
1961 flv_demux_seek_to_offset (GstFlvDemux * demux, guint64 offset)
1962 {
1963   GstEvent *event;
1964   gboolean res = 0;
1965
1966   GST_DEBUG_OBJECT (demux, "Seeking to %" G_GUINT64_FORMAT, offset);
1967
1968   event =
1969       gst_event_new_seek (1.0, GST_FORMAT_BYTES,
1970       GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE, GST_SEEK_TYPE_SET, offset,
1971       GST_SEEK_TYPE_NONE, -1);
1972
1973   res = gst_pad_push_event (demux->sinkpad, event);
1974
1975   if (res)
1976     demux->offset = offset;
1977   return res;
1978 }
1979
1980 static GstFlowReturn
1981 gst_flv_demux_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer)
1982 {
1983   GstFlowReturn ret = GST_FLOW_OK;
1984   GstFlvDemux *demux = NULL;
1985
1986   demux = GST_FLV_DEMUX (parent);
1987
1988   GST_LOG_OBJECT (demux,
1989       "received buffer of %" G_GSIZE_FORMAT " bytes at offset %"
1990       G_GUINT64_FORMAT, gst_buffer_get_size (buffer),
1991       GST_BUFFER_OFFSET (buffer));
1992
1993   if (G_UNLIKELY (GST_BUFFER_OFFSET (buffer) == 0)) {
1994     GST_DEBUG_OBJECT (demux, "beginning of file, expect header");
1995     demux->state = FLV_STATE_HEADER;
1996     demux->offset = 0;
1997   }
1998
1999   if (G_UNLIKELY (demux->offset == 0 && GST_BUFFER_OFFSET (buffer) != 0)) {
2000     GST_DEBUG_OBJECT (demux, "offset was zero, synchronizing with buffer's");
2001     demux->offset = GST_BUFFER_OFFSET (buffer);
2002   }
2003
2004   if (GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_DISCONT)) {
2005     GST_DEBUG_OBJECT (demux, "Discontinuity");
2006     gst_adapter_clear (demux->adapter);
2007   }
2008
2009   gst_adapter_push (demux->adapter, buffer);
2010
2011   if (demux->seeking) {
2012     demux->state = FLV_STATE_SEEK;
2013     GST_OBJECT_LOCK (demux);
2014     demux->seeking = FALSE;
2015     GST_OBJECT_UNLOCK (demux);
2016   }
2017
2018 parse:
2019   if (G_UNLIKELY (ret != GST_FLOW_OK)) {
2020     GST_DEBUG_OBJECT (demux, "got flow return %s", gst_flow_get_name (ret));
2021     goto beach;
2022   }
2023
2024   if (G_UNLIKELY (demux->flushing)) {
2025     GST_DEBUG_OBJECT (demux, "we are now flushing, exiting parser loop");
2026     ret = GST_FLOW_FLUSHING;
2027     goto beach;
2028   }
2029
2030   switch (demux->state) {
2031     case FLV_STATE_HEADER:
2032     {
2033       if (gst_adapter_available (demux->adapter) >= FLV_HEADER_SIZE) {
2034         GstBuffer *buffer;
2035
2036         buffer = gst_adapter_take_buffer (demux->adapter, FLV_HEADER_SIZE);
2037
2038         ret = gst_flv_demux_parse_header (demux, buffer);
2039
2040         gst_buffer_unref (buffer);
2041         demux->offset += FLV_HEADER_SIZE;
2042
2043         demux->state = FLV_STATE_TAG_TYPE;
2044         goto parse;
2045       } else {
2046         goto beach;
2047       }
2048     }
2049     case FLV_STATE_TAG_TYPE:
2050     {
2051       if (gst_adapter_available (demux->adapter) >= FLV_TAG_TYPE_SIZE) {
2052         GstBuffer *buffer;
2053
2054         /* Remember the tag offset in bytes */
2055         demux->cur_tag_offset = demux->offset;
2056
2057         buffer = gst_adapter_take_buffer (demux->adapter, FLV_TAG_TYPE_SIZE);
2058
2059         ret = gst_flv_demux_parse_tag_type (demux, buffer);
2060
2061         gst_buffer_unref (buffer);
2062         demux->offset += FLV_TAG_TYPE_SIZE;
2063
2064         /* last tag is not an index => no index/don't know where the index is
2065          * seek back to the beginning */
2066         if (demux->seek_event && demux->state != FLV_STATE_TAG_SCRIPT)
2067           goto no_index;
2068
2069         goto parse;
2070       } else {
2071         goto beach;
2072       }
2073     }
2074     case FLV_STATE_TAG_VIDEO:
2075     {
2076       if (gst_adapter_available (demux->adapter) >= demux->tag_size) {
2077         GstBuffer *buffer;
2078
2079         buffer = gst_adapter_take_buffer (demux->adapter, demux->tag_size);
2080
2081         ret = gst_flv_demux_parse_tag_video (demux, buffer);
2082
2083         gst_buffer_unref (buffer);
2084         demux->offset += demux->tag_size;
2085
2086         demux->state = FLV_STATE_TAG_TYPE;
2087         goto parse;
2088       } else {
2089         goto beach;
2090       }
2091     }
2092     case FLV_STATE_TAG_AUDIO:
2093     {
2094       if (gst_adapter_available (demux->adapter) >= demux->tag_size) {
2095         GstBuffer *buffer;
2096
2097         buffer = gst_adapter_take_buffer (demux->adapter, demux->tag_size);
2098
2099         ret = gst_flv_demux_parse_tag_audio (demux, buffer);
2100
2101         gst_buffer_unref (buffer);
2102         demux->offset += demux->tag_size;
2103
2104         demux->state = FLV_STATE_TAG_TYPE;
2105         goto parse;
2106       } else {
2107         goto beach;
2108       }
2109     }
2110     case FLV_STATE_TAG_SCRIPT:
2111     {
2112       if (gst_adapter_available (demux->adapter) >= demux->tag_size) {
2113         GstBuffer *buffer;
2114
2115         buffer = gst_adapter_take_buffer (demux->adapter, demux->tag_size);
2116
2117         ret = gst_flv_demux_parse_tag_script (demux, buffer);
2118
2119         gst_buffer_unref (buffer);
2120         demux->offset += demux->tag_size;
2121
2122         demux->state = FLV_STATE_TAG_TYPE;
2123
2124         /* if there's a seek event we're here for the index so if we don't have it
2125          * we seek back to the beginning */
2126         if (demux->seek_event) {
2127           if (demux->indexed)
2128             demux->state = FLV_STATE_SEEK;
2129           else
2130             goto no_index;
2131         }
2132
2133         goto parse;
2134       } else {
2135         goto beach;
2136       }
2137     }
2138     case FLV_STATE_SEEK:
2139     {
2140       GstEvent *event;
2141
2142       ret = GST_FLOW_OK;
2143
2144       if (!demux->indexed) {
2145         if (demux->offset == demux->file_size - sizeof (guint32)) {
2146           guint64 seek_offset;
2147           guint8 *data;
2148
2149           data = gst_adapter_take (demux->adapter, 4);
2150           if (!data)
2151             goto no_index;
2152
2153           seek_offset = demux->file_size - sizeof (guint32) -
2154               GST_READ_UINT32_BE (data);
2155           g_free (data);
2156
2157           GST_INFO_OBJECT (demux,
2158               "Seeking to beginning of last tag at %" G_GUINT64_FORMAT,
2159               seek_offset);
2160           demux->state = FLV_STATE_TAG_TYPE;
2161           flv_demux_seek_to_offset (demux, seek_offset);
2162           goto beach;
2163         } else
2164           goto no_index;
2165       }
2166
2167       GST_OBJECT_LOCK (demux);
2168       event = demux->seek_event;
2169       demux->seek_event = NULL;
2170       GST_OBJECT_UNLOCK (demux);
2171
2172       /* calculate and perform seek */
2173       if (!flv_demux_handle_seek_push (demux, event))
2174         goto seek_failed;
2175
2176       gst_event_unref (event);
2177       demux->state = FLV_STATE_TAG_TYPE;
2178       goto beach;
2179     }
2180     case FLV_STATE_SKIP:
2181       /* Skip unknown tags (set in _parse_tag_type()) */
2182       if (gst_adapter_available (demux->adapter) >= demux->tag_size) {
2183         gst_adapter_flush (demux->adapter, demux->tag_size);
2184         demux->offset += demux->tag_size;
2185         demux->state = FLV_STATE_TAG_TYPE;
2186         goto parse;
2187       } else {
2188         goto beach;
2189       }
2190     default:
2191       GST_DEBUG_OBJECT (demux, "unexpected demuxer state");
2192   }
2193
2194 beach:
2195   return ret;
2196
2197 /* ERRORS */
2198 no_index:
2199   {
2200     GST_OBJECT_LOCK (demux);
2201     demux->seeking = FALSE;
2202     gst_event_unref (demux->seek_event);
2203     demux->seek_event = NULL;
2204     GST_OBJECT_UNLOCK (demux);
2205     GST_WARNING_OBJECT (demux,
2206         "failed to find an index, seeking back to beginning");
2207     flv_demux_seek_to_offset (demux, 0);
2208     return GST_FLOW_OK;
2209   }
2210 seek_failed:
2211   {
2212     GST_ELEMENT_ERROR (demux, STREAM, DEMUX, (NULL), ("seek failed"));
2213     return GST_FLOW_ERROR;
2214   }
2215
2216 }
2217
2218 static GstFlowReturn
2219 gst_flv_demux_pull_range (GstFlvDemux * demux, GstPad * pad, guint64 offset,
2220     guint size, GstBuffer ** buffer)
2221 {
2222   GstFlowReturn ret;
2223
2224   ret = gst_pad_pull_range (pad, offset, size, buffer);
2225   if (G_UNLIKELY (ret != GST_FLOW_OK)) {
2226     GST_WARNING_OBJECT (demux,
2227         "failed when pulling %d bytes from offset %" G_GUINT64_FORMAT ": %s",
2228         size, offset, gst_flow_get_name (ret));
2229     *buffer = NULL;
2230     return ret;
2231   }
2232
2233   if (G_UNLIKELY (*buffer && gst_buffer_get_size (*buffer) != size)) {
2234     GST_WARNING_OBJECT (demux,
2235         "partial pull got %" G_GSIZE_FORMAT " when expecting %d from offset %"
2236         G_GUINT64_FORMAT, gst_buffer_get_size (*buffer), size, offset);
2237     gst_buffer_unref (*buffer);
2238     ret = GST_FLOW_EOS;
2239     *buffer = NULL;
2240     return ret;
2241   }
2242
2243   return ret;
2244 }
2245
2246 static GstFlowReturn
2247 gst_flv_demux_pull_tag (GstPad * pad, GstFlvDemux * demux)
2248 {
2249   GstBuffer *buffer = NULL;
2250   GstFlowReturn ret = GST_FLOW_OK;
2251
2252   /* Store tag offset */
2253   demux->cur_tag_offset = demux->offset;
2254
2255   /* Get the first 4 bytes to identify tag type and size */
2256   if (G_UNLIKELY ((ret = gst_flv_demux_pull_range (demux, pad, demux->offset,
2257                   FLV_TAG_TYPE_SIZE, &buffer)) != GST_FLOW_OK))
2258     goto beach;
2259
2260   /* Identify tag type */
2261   ret = gst_flv_demux_parse_tag_type (demux, buffer);
2262
2263   gst_buffer_unref (buffer);
2264
2265   if (G_UNLIKELY (ret != GST_FLOW_OK))
2266     goto beach;
2267
2268   /* Jump over tag type + size */
2269   demux->offset += FLV_TAG_TYPE_SIZE;
2270
2271   /* Pull the whole tag */
2272   buffer = NULL;
2273   if (G_UNLIKELY ((ret = gst_flv_demux_pull_range (demux, pad, demux->offset,
2274                   demux->tag_size, &buffer)) != GST_FLOW_OK))
2275     goto beach;
2276
2277   switch (demux->state) {
2278     case FLV_STATE_TAG_VIDEO:
2279       ret = gst_flv_demux_parse_tag_video (demux, buffer);
2280       break;
2281     case FLV_STATE_TAG_AUDIO:
2282       ret = gst_flv_demux_parse_tag_audio (demux, buffer);
2283       break;
2284     case FLV_STATE_TAG_SCRIPT:
2285       ret = gst_flv_demux_parse_tag_script (demux, buffer);
2286       break;
2287     default:
2288       GST_WARNING_OBJECT (demux, "unexpected state %d", demux->state);
2289   }
2290
2291   gst_buffer_unref (buffer);
2292
2293   /* Jump over that part we've just parsed */
2294   demux->offset += demux->tag_size;
2295
2296   /* Make sure we reinitialize the tag size */
2297   demux->tag_size = 0;
2298
2299   /* Ready for the next tag */
2300   demux->state = FLV_STATE_TAG_TYPE;
2301
2302   if (G_UNLIKELY (ret == GST_FLOW_NOT_LINKED)) {
2303     GST_WARNING_OBJECT (demux, "parsing this tag returned not-linked and "
2304         "neither video nor audio are linked");
2305   }
2306
2307 beach:
2308   return ret;
2309 }
2310
2311 static GstFlowReturn
2312 gst_flv_demux_pull_header (GstPad * pad, GstFlvDemux * demux)
2313 {
2314   GstBuffer *buffer = NULL;
2315   GstFlowReturn ret = GST_FLOW_OK;
2316
2317   /* Get the first 9 bytes */
2318   if (G_UNLIKELY ((ret = gst_flv_demux_pull_range (demux, pad, demux->offset,
2319                   FLV_HEADER_SIZE, &buffer)) != GST_FLOW_OK))
2320     goto beach;
2321
2322   ret = gst_flv_demux_parse_header (demux, buffer);
2323
2324   gst_buffer_unref (buffer);
2325
2326   /* Jump over the header now */
2327   demux->offset += FLV_HEADER_SIZE;
2328   demux->state = FLV_STATE_TAG_TYPE;
2329
2330 beach:
2331   return ret;
2332 }
2333
2334 static void
2335 gst_flv_demux_move_to_offset (GstFlvDemux * demux, gint64 offset,
2336     gboolean reset)
2337 {
2338   demux->offset = offset;
2339
2340   /* Tell all the stream we moved to a different position (discont) */
2341   demux->audio_need_discont = TRUE;
2342   demux->video_need_discont = TRUE;
2343
2344   /* next section setup */
2345   demux->from_offset = -1;
2346   demux->audio_done = demux->video_done = FALSE;
2347   demux->audio_first_ts = demux->video_first_ts = GST_CLOCK_TIME_NONE;
2348
2349   if (reset) {
2350     demux->from_offset = -1;
2351     demux->to_offset = G_MAXINT64;
2352   }
2353
2354   /* If we seeked at the beginning of the file parse the header again */
2355   if (G_UNLIKELY (!demux->offset)) {
2356     demux->state = FLV_STATE_HEADER;
2357   } else {                      /* or parse a tag */
2358     demux->state = FLV_STATE_TAG_TYPE;
2359   }
2360 }
2361
2362 static GstFlowReturn
2363 gst_flv_demux_seek_to_prev_keyframe (GstFlvDemux * demux)
2364 {
2365   GstFlowReturn ret = GST_FLOW_EOS;
2366   GstIndex *index;
2367   GstIndexEntry *entry = NULL;
2368
2369   GST_DEBUG_OBJECT (demux,
2370       "terminated section started at offset %" G_GINT64_FORMAT,
2371       demux->from_offset);
2372
2373   /* we are done if we got all audio and video */
2374   if ((!GST_CLOCK_TIME_IS_VALID (demux->audio_first_ts) ||
2375           demux->audio_first_ts < demux->segment.start) &&
2376       (!GST_CLOCK_TIME_IS_VALID (demux->video_first_ts) ||
2377           demux->video_first_ts < demux->segment.start))
2378     goto done;
2379
2380   if (demux->from_offset <= 0)
2381     goto done;
2382
2383   GST_DEBUG_OBJECT (demux, "locating previous position");
2384
2385   index = gst_flv_demux_get_index (GST_ELEMENT (demux));
2386
2387   /* locate index entry before previous start position */
2388   if (index) {
2389     entry = gst_index_get_assoc_entry (index, demux->index_id,
2390         GST_INDEX_LOOKUP_BEFORE, GST_ASSOCIATION_FLAG_KEY_UNIT,
2391         GST_FORMAT_BYTES, demux->from_offset - 1);
2392
2393     if (entry) {
2394       gint64 bytes = 0, time = 0;
2395
2396       gst_index_entry_assoc_map (entry, GST_FORMAT_BYTES, &bytes);
2397       gst_index_entry_assoc_map (entry, GST_FORMAT_TIME, &time);
2398
2399       GST_DEBUG_OBJECT (demux, "found index entry for %" G_GINT64_FORMAT
2400           " at %" GST_TIME_FORMAT ", seeking to %" G_GINT64_FORMAT,
2401           demux->offset - 1, GST_TIME_ARGS (time), bytes);
2402
2403       /* setup for next section */
2404       demux->to_offset = demux->from_offset;
2405       gst_flv_demux_move_to_offset (demux, bytes, FALSE);
2406       ret = GST_FLOW_OK;
2407     }
2408
2409     gst_object_unref (index);
2410   }
2411
2412 done:
2413   return ret;
2414 }
2415
2416 static GstFlowReturn
2417 gst_flv_demux_create_index (GstFlvDemux * demux, gint64 pos, GstClockTime ts)
2418 {
2419   gint64 size;
2420   size_t tag_size;
2421   guint64 old_offset;
2422   GstBuffer *buffer;
2423   GstClockTime tag_time;
2424   GstFlowReturn ret = GST_FLOW_OK;
2425
2426   if (!gst_pad_peer_query_duration (demux->sinkpad, GST_FORMAT_BYTES, &size))
2427     return GST_FLOW_OK;
2428
2429   GST_DEBUG_OBJECT (demux, "building index at %" G_GINT64_FORMAT
2430       " looking for time %" GST_TIME_FORMAT, pos, GST_TIME_ARGS (ts));
2431
2432   old_offset = demux->offset;
2433   demux->offset = pos;
2434
2435   buffer = NULL;
2436   while ((ret = gst_flv_demux_pull_range (demux, demux->sinkpad, demux->offset,
2437               12, &buffer)) == GST_FLOW_OK) {
2438     tag_time =
2439         gst_flv_demux_parse_tag_timestamp (demux, TRUE, buffer, &tag_size);
2440
2441     gst_buffer_unref (buffer);
2442     buffer = NULL;
2443
2444     if (G_UNLIKELY (tag_time == GST_CLOCK_TIME_NONE || tag_time > ts))
2445       goto exit;
2446
2447     demux->offset += tag_size;
2448   }
2449
2450   if (ret == GST_FLOW_EOS) {
2451     /* file ran out, so mark we have complete index */
2452     demux->indexed = TRUE;
2453     ret = GST_FLOW_OK;
2454   }
2455
2456 exit:
2457   demux->offset = old_offset;
2458
2459   return ret;
2460 }
2461
2462 static gint64
2463 gst_flv_demux_get_metadata (GstFlvDemux * demux)
2464 {
2465   gint64 ret = 0, offset;
2466   size_t tag_size, size;
2467   GstBuffer *buffer = NULL;
2468   GstMapInfo map;
2469
2470   if (!gst_pad_peer_query_duration (demux->sinkpad, GST_FORMAT_BYTES, &offset))
2471     goto exit;
2472
2473   ret = offset;
2474   GST_DEBUG_OBJECT (demux, "upstream size: %" G_GINT64_FORMAT, offset);
2475   if (G_UNLIKELY (offset < 4))
2476     goto exit;
2477
2478   offset -= 4;
2479   if (GST_FLOW_OK != gst_flv_demux_pull_range (demux, demux->sinkpad, offset,
2480           4, &buffer))
2481     goto exit;
2482
2483   gst_buffer_map (buffer, &map, GST_MAP_READ);
2484   tag_size = GST_READ_UINT32_BE (map.data);
2485   gst_buffer_unmap (buffer, &map);
2486   GST_DEBUG_OBJECT (demux, "last tag size: %" G_GSIZE_FORMAT, tag_size);
2487   gst_buffer_unref (buffer);
2488   buffer = NULL;
2489
2490   offset -= tag_size;
2491   if (GST_FLOW_OK != gst_flv_demux_pull_range (demux, demux->sinkpad, offset,
2492           12, &buffer))
2493     goto exit;
2494
2495   /* a consistency check */
2496   gst_buffer_map (buffer, &map, GST_MAP_READ);
2497   size = GST_READ_UINT24_BE (map.data + 1);
2498   if (size != tag_size - 11) {
2499     gst_buffer_unmap (buffer, &map);
2500     GST_DEBUG_OBJECT (demux,
2501         "tag size %" G_GSIZE_FORMAT ", expected %" G_GSIZE_FORMAT
2502         ", corrupt or truncated file", size, tag_size - 11);
2503     goto exit;
2504   }
2505
2506   /* try to update duration with timestamp in any case */
2507   gst_flv_demux_parse_tag_timestamp (demux, FALSE, buffer, &size);
2508
2509   /* maybe get some more metadata */
2510   if (map.data[0] == 18) {
2511     gst_buffer_unmap (buffer, &map);
2512     gst_buffer_unref (buffer);
2513     buffer = NULL;
2514     GST_DEBUG_OBJECT (demux, "script tag, pulling it to parse");
2515     offset += 4;
2516     if (GST_FLOW_OK == gst_flv_demux_pull_range (demux, demux->sinkpad, offset,
2517             tag_size, &buffer))
2518       gst_flv_demux_parse_tag_script (demux, buffer);
2519   } else {
2520     gst_buffer_unmap (buffer, &map);
2521   }
2522
2523 exit:
2524   if (buffer)
2525     gst_buffer_unref (buffer);
2526
2527   return ret;
2528 }
2529
2530 static void
2531 gst_flv_demux_loop (GstPad * pad)
2532 {
2533   GstFlvDemux *demux = NULL;
2534   GstFlowReturn ret = GST_FLOW_OK;
2535
2536   demux = GST_FLV_DEMUX (gst_pad_get_parent (pad));
2537
2538   /* pull in data */
2539   switch (demux->state) {
2540     case FLV_STATE_TAG_TYPE:
2541       if (demux->from_offset == -1)
2542         demux->from_offset = demux->offset;
2543       ret = gst_flv_demux_pull_tag (pad, demux);
2544       /* if we have seen real data, we probably passed a possible metadata
2545        * header located at start.  So if we do not yet have an index,
2546        * try to pick up metadata (index, duration) at the end */
2547       if (G_UNLIKELY (!demux->file_size && !demux->indexed &&
2548               (demux->has_video || demux->has_audio)))
2549         demux->file_size = gst_flv_demux_get_metadata (demux);
2550       break;
2551     case FLV_STATE_DONE:
2552       ret = GST_FLOW_EOS;
2553       break;
2554     case FLV_STATE_SEEK:
2555       /* seek issued with insufficient index;
2556        * scan for index in task thread from current maximum offset to
2557        * desired time and then perform seek */
2558       /* TODO maybe some buffering message or so to indicate scan progress */
2559       ret = gst_flv_demux_create_index (demux, demux->index_max_pos,
2560           demux->seek_time);
2561       if (ret != GST_FLOW_OK)
2562         goto pause;
2563       /* position and state arranged by seek,
2564        * also unrefs event */
2565       gst_flv_demux_handle_seek_pull (demux, demux->seek_event, FALSE);
2566       demux->seek_event = NULL;
2567       break;
2568     default:
2569       ret = gst_flv_demux_pull_header (pad, demux);
2570       /* index scans start after header */
2571       demux->index_max_pos = demux->offset;
2572       break;
2573   }
2574
2575   if (demux->segment.rate < 0.0) {
2576     /* check end of section */
2577     if ((gint64) demux->offset >= demux->to_offset ||
2578         demux->segment.position >= demux->segment.stop + 2 * GST_SECOND ||
2579         (demux->audio_done && demux->video_done))
2580       ret = gst_flv_demux_seek_to_prev_keyframe (demux);
2581   } else {
2582     /* check EOS condition */
2583     if ((demux->segment.stop != -1) &&
2584         (demux->segment.position >= demux->segment.stop)) {
2585       ret = GST_FLOW_EOS;
2586     }
2587   }
2588
2589   /* pause if something went wrong or at end */
2590   if (G_UNLIKELY (ret != GST_FLOW_OK))
2591     goto pause;
2592
2593   gst_object_unref (demux);
2594
2595   return;
2596
2597 pause:
2598   {
2599     const gchar *reason = gst_flow_get_name (ret);
2600
2601     GST_LOG_OBJECT (demux, "pausing task, reason %s", reason);
2602     gst_pad_pause_task (pad);
2603
2604     if (ret == GST_FLOW_EOS) {
2605       /* handle end-of-stream/segment */
2606       /* so align our position with the end of it, if there is one
2607        * this ensures a subsequent will arrive at correct base/acc time */
2608       if (demux->segment.rate > 0.0 &&
2609           GST_CLOCK_TIME_IS_VALID (demux->segment.stop))
2610         demux->segment.position = demux->segment.stop;
2611       else if (demux->segment.rate < 0.0)
2612         demux->segment.position = demux->segment.start;
2613
2614       /* perform EOS logic */
2615       if (!demux->no_more_pads) {
2616         gst_element_no_more_pads (GST_ELEMENT_CAST (demux));
2617         demux->no_more_pads = TRUE;
2618       }
2619
2620       if (demux->segment.flags & GST_SEGMENT_FLAG_SEGMENT) {
2621         gint64 stop;
2622
2623         /* for segment playback we need to post when (in stream time)
2624          * we stopped, this is either stop (when set) or the duration. */
2625         if ((stop = demux->segment.stop) == -1)
2626           stop = demux->segment.duration;
2627
2628         if (demux->segment.rate >= 0) {
2629           GST_LOG_OBJECT (demux, "Sending segment done, at end of segment");
2630           gst_element_post_message (GST_ELEMENT_CAST (demux),
2631               gst_message_new_segment_done (GST_OBJECT_CAST (demux),
2632                   GST_FORMAT_TIME, stop));
2633           gst_flv_demux_push_src_event (demux,
2634               gst_event_new_segment_done (GST_FORMAT_TIME, stop));
2635         } else {                /* Reverse playback */
2636           GST_LOG_OBJECT (demux, "Sending segment done, at beginning of "
2637               "segment");
2638           gst_element_post_message (GST_ELEMENT_CAST (demux),
2639               gst_message_new_segment_done (GST_OBJECT_CAST (demux),
2640                   GST_FORMAT_TIME, demux->segment.start));
2641           gst_flv_demux_push_src_event (demux,
2642               gst_event_new_segment_done (GST_FORMAT_TIME,
2643                   demux->segment.start));
2644         }
2645       } else {
2646         /* normal playback, send EOS to all linked pads */
2647         if (!demux->no_more_pads) {
2648           gst_element_no_more_pads (GST_ELEMENT (demux));
2649           demux->no_more_pads = TRUE;
2650         }
2651
2652         GST_LOG_OBJECT (demux, "Sending EOS, at end of stream");
2653         if (!demux->audio_pad && !demux->video_pad)
2654           GST_ELEMENT_ERROR (demux, STREAM, FAILED,
2655               ("Internal data stream error."), ("Got EOS before any data"));
2656         else if (!gst_flv_demux_push_src_event (demux, gst_event_new_eos ()))
2657           GST_WARNING_OBJECT (demux, "failed pushing EOS on streams");
2658       }
2659     } else if (ret == GST_FLOW_NOT_LINKED || ret < GST_FLOW_EOS) {
2660       GST_ELEMENT_ERROR (demux, STREAM, FAILED,
2661           ("Internal data stream error."),
2662           ("stream stopped, reason %s", reason));
2663       gst_flv_demux_push_src_event (demux, gst_event_new_eos ());
2664     }
2665     gst_object_unref (demux);
2666     return;
2667   }
2668 }
2669
2670 static guint64
2671 gst_flv_demux_find_offset (GstFlvDemux * demux, GstSegment * segment,
2672     GstSeekFlags seek_flags)
2673 {
2674   gint64 bytes = 0;
2675   gint64 time = 0;
2676   GstIndex *index;
2677   GstIndexEntry *entry;
2678
2679   g_return_val_if_fail (segment != NULL, 0);
2680
2681   time = segment->position;
2682
2683   index = gst_flv_demux_get_index (GST_ELEMENT (demux));
2684
2685   if (index) {
2686     /* Let's check if we have an index entry for that seek time */
2687     entry = gst_index_get_assoc_entry (index, demux->index_id,
2688         seek_flags & GST_SEEK_FLAG_SNAP_AFTER ?
2689         GST_INDEX_LOOKUP_AFTER : GST_INDEX_LOOKUP_BEFORE,
2690         GST_ASSOCIATION_FLAG_KEY_UNIT, GST_FORMAT_TIME, time);
2691
2692     if (entry) {
2693       gst_index_entry_assoc_map (entry, GST_FORMAT_BYTES, &bytes);
2694       gst_index_entry_assoc_map (entry, GST_FORMAT_TIME, &time);
2695
2696       GST_DEBUG_OBJECT (demux, "found index entry for %" GST_TIME_FORMAT
2697           " at %" GST_TIME_FORMAT ", seeking to %" G_GINT64_FORMAT,
2698           GST_TIME_ARGS (segment->position), GST_TIME_ARGS (time), bytes);
2699
2700       /* Key frame seeking */
2701       if (seek_flags & GST_SEEK_FLAG_KEY_UNIT) {
2702         /* Adjust the segment so that the keyframe fits in */
2703         segment->start = segment->time = time;
2704         segment->position = time;
2705       }
2706     } else {
2707       GST_DEBUG_OBJECT (demux, "no index entry found for %" GST_TIME_FORMAT,
2708           GST_TIME_ARGS (segment->start));
2709     }
2710
2711     gst_object_unref (index);
2712   }
2713
2714   return bytes;
2715 }
2716
2717 static gboolean
2718 flv_demux_handle_seek_push (GstFlvDemux * demux, GstEvent * event)
2719 {
2720   GstFormat format;
2721   GstSeekFlags flags;
2722   GstSeekType start_type, stop_type;
2723   gint64 start, stop;
2724   gdouble rate;
2725   gboolean update, flush, ret;
2726   GstSegment seeksegment;
2727
2728   gst_event_parse_seek (event, &rate, &format, &flags,
2729       &start_type, &start, &stop_type, &stop);
2730
2731   if (format != GST_FORMAT_TIME)
2732     goto wrong_format;
2733
2734   flush = ! !(flags & GST_SEEK_FLAG_FLUSH);
2735
2736   /* Work on a copy until we are sure the seek succeeded. */
2737   memcpy (&seeksegment, &demux->segment, sizeof (GstSegment));
2738
2739   GST_DEBUG_OBJECT (demux, "segment before configure %" GST_SEGMENT_FORMAT,
2740       &demux->segment);
2741
2742   /* Apply the seek to our segment */
2743   gst_segment_do_seek (&seeksegment, rate, format, flags,
2744       start_type, start, stop_type, stop, &update);
2745
2746   GST_DEBUG_OBJECT (demux, "segment configured %" GST_SEGMENT_FORMAT,
2747       &seeksegment);
2748
2749   if (flush || seeksegment.position != demux->segment.position) {
2750     /* Do the actual seeking */
2751     guint64 offset = gst_flv_demux_find_offset (demux, &seeksegment, flags);
2752
2753     GST_DEBUG_OBJECT (demux, "generating an upstream seek at position %"
2754         G_GUINT64_FORMAT, offset);
2755     ret = gst_pad_push_event (demux->sinkpad,
2756         gst_event_new_seek (seeksegment.rate, GST_FORMAT_BYTES,
2757             flags | GST_SEEK_FLAG_ACCURATE, GST_SEEK_TYPE_SET,
2758             offset, GST_SEEK_TYPE_NONE, 0));
2759     if (G_UNLIKELY (!ret)) {
2760       GST_WARNING_OBJECT (demux, "upstream seek failed");
2761     }
2762
2763     gst_flow_combiner_reset (demux->flowcombiner);
2764     /* Tell all the stream we moved to a different position (discont) */
2765     demux->audio_need_discont = TRUE;
2766     demux->video_need_discont = TRUE;
2767   } else {
2768     ret = TRUE;
2769   }
2770
2771   if (ret) {
2772     /* Ok seek succeeded, take the newly configured segment */
2773     memcpy (&demux->segment, &seeksegment, sizeof (GstSegment));
2774
2775     /* Tell all the stream a new segment is needed */
2776     demux->audio_need_segment = TRUE;
2777     demux->video_need_segment = TRUE;
2778     /* Clean any potential newsegment event kept for the streams. The first
2779      * stream needing a new segment will create a new one. */
2780     if (G_UNLIKELY (demux->new_seg_event)) {
2781       gst_event_unref (demux->new_seg_event);
2782       demux->new_seg_event = NULL;
2783     }
2784     GST_DEBUG_OBJECT (demux, "preparing newsegment from %"
2785         GST_TIME_FORMAT " to %" GST_TIME_FORMAT,
2786         GST_TIME_ARGS (demux->segment.start),
2787         GST_TIME_ARGS (demux->segment.stop));
2788     demux->new_seg_event = gst_event_new_segment (&demux->segment);
2789     gst_event_unref (event);
2790   } else {
2791     ret = gst_pad_push_event (demux->sinkpad, event);
2792   }
2793
2794   return ret;
2795
2796 /* ERRORS */
2797 wrong_format:
2798   {
2799     GST_WARNING_OBJECT (demux, "we only support seeking in TIME format");
2800     gst_event_unref (event);
2801     return FALSE;
2802   }
2803 }
2804
2805 static gboolean
2806 gst_flv_demux_handle_seek_push (GstFlvDemux * demux, GstEvent * event)
2807 {
2808   GstFormat format;
2809
2810   gst_event_parse_seek (event, NULL, &format, NULL, NULL, NULL, NULL, NULL);
2811
2812   if (format != GST_FORMAT_TIME) {
2813     GST_WARNING_OBJECT (demux, "we only support seeking in TIME format");
2814     gst_event_unref (event);
2815     return FALSE;
2816   }
2817
2818   /* First try upstream */
2819   if (gst_pad_push_event (demux->sinkpad, gst_event_ref (event))) {
2820     GST_DEBUG_OBJECT (demux, "Upstream successfully seeked");
2821     gst_event_unref (event);
2822     return TRUE;
2823   }
2824
2825   if (!demux->indexed) {
2826     guint64 seek_offset = 0;
2827     gboolean building_index;
2828
2829     GST_OBJECT_LOCK (demux);
2830     /* handle the seek in the chain function */
2831     demux->seeking = TRUE;
2832     demux->state = FLV_STATE_SEEK;
2833
2834     /* copy the event */
2835     if (demux->seek_event)
2836       gst_event_unref (demux->seek_event);
2837     demux->seek_event = gst_event_ref (event);
2838
2839     /* set the building_index flag so that only one thread can setup the
2840      * structures for index seeking. */
2841     building_index = demux->building_index;
2842     if (!building_index) {
2843       demux->building_index = TRUE;
2844       if (!demux->file_size
2845           && !gst_pad_peer_query_duration (demux->sinkpad, GST_FORMAT_BYTES,
2846               &demux->file_size)) {
2847         GST_WARNING_OBJECT (demux, "Failed to query upstream file size");
2848         GST_OBJECT_UNLOCK (demux);
2849         return FALSE;
2850       }
2851
2852       /* we hope the last tag is a scriptdataobject containing an index
2853        * the size of the last tag is given in the last guint32 bits
2854        * then we seek to the beginning of the tag, parse it and hopefully obtain an index */
2855       seek_offset = demux->file_size - sizeof (guint32);
2856       GST_DEBUG_OBJECT (demux,
2857           "File size obtained, seeking to %" G_GUINT64_FORMAT, seek_offset);
2858     }
2859     GST_OBJECT_UNLOCK (demux);
2860
2861     if (!building_index) {
2862       GST_INFO_OBJECT (demux, "Seeking to last 4 bytes at %" G_GUINT64_FORMAT,
2863           seek_offset);
2864       return flv_demux_seek_to_offset (demux, seek_offset);
2865     }
2866
2867     /* FIXME: we have to always return true so that we don't block the seek
2868      * thread.
2869      * Note: maybe it is OK to return true if we're still building the index */
2870     return TRUE;
2871   }
2872
2873   return flv_demux_handle_seek_push (demux, event);
2874 }
2875
2876 static gboolean
2877 gst_flv_demux_handle_seek_pull (GstFlvDemux * demux, GstEvent * event,
2878     gboolean seeking)
2879 {
2880   GstFormat format;
2881   GstSeekFlags flags;
2882   GstSeekType start_type, stop_type;
2883   gint64 start, stop;
2884   gdouble rate;
2885   gboolean update, flush, ret = FALSE;
2886   GstSegment seeksegment;
2887
2888   gst_event_parse_seek (event, &rate, &format, &flags,
2889       &start_type, &start, &stop_type, &stop);
2890
2891   if (format != GST_FORMAT_TIME)
2892     goto wrong_format;
2893
2894   /* mark seeking thread entering flushing/pausing */
2895   GST_OBJECT_LOCK (demux);
2896   if (seeking)
2897     demux->seeking = seeking;
2898   GST_OBJECT_UNLOCK (demux);
2899
2900   flush = ! !(flags & GST_SEEK_FLAG_FLUSH);
2901
2902   if (flush) {
2903     /* Flush start up and downstream to make sure data flow and loops are
2904        idle */
2905     gst_flv_demux_push_src_event (demux, gst_event_new_flush_start ());
2906     gst_pad_push_event (demux->sinkpad, gst_event_new_flush_start ());
2907   } else {
2908     /* Pause the pulling task */
2909     gst_pad_pause_task (demux->sinkpad);
2910   }
2911
2912   /* Take the stream lock */
2913   GST_PAD_STREAM_LOCK (demux->sinkpad);
2914
2915   if (flush) {
2916     /* Stop flushing upstream we need to pull */
2917     gst_pad_push_event (demux->sinkpad, gst_event_new_flush_stop (TRUE));
2918   }
2919
2920   /* Work on a copy until we are sure the seek succeeded. */
2921   memcpy (&seeksegment, &demux->segment, sizeof (GstSegment));
2922
2923   GST_DEBUG_OBJECT (demux, "segment before configure %" GST_SEGMENT_FORMAT,
2924       &demux->segment);
2925
2926   /* Apply the seek to our segment */
2927   gst_segment_do_seek (&seeksegment, rate, format, flags,
2928       start_type, start, stop_type, stop, &update);
2929
2930   GST_DEBUG_OBJECT (demux, "segment configured %" GST_SEGMENT_FORMAT,
2931       &seeksegment);
2932
2933   if (flush || seeksegment.position != demux->segment.position) {
2934     /* Do the actual seeking */
2935     /* index is reliable if it is complete or we do not go to far ahead */
2936     if (seeking && !demux->indexed &&
2937         seeksegment.position > demux->index_max_time + 10 * GST_SECOND) {
2938       GST_DEBUG_OBJECT (demux, "delaying seek to post-scan; "
2939           " index only up to %" GST_TIME_FORMAT,
2940           GST_TIME_ARGS (demux->index_max_time));
2941       /* stop flushing for now */
2942       if (flush)
2943         gst_flv_demux_push_src_event (demux, gst_event_new_flush_stop (TRUE));
2944       /* delegate scanning and index building to task thread to avoid
2945        * occupying main (UI) loop */
2946       if (demux->seek_event)
2947         gst_event_unref (demux->seek_event);
2948       demux->seek_event = gst_event_ref (event);
2949       demux->seek_time = seeksegment.position;
2950       demux->state = FLV_STATE_SEEK;
2951       /* do not know about succes yet, but we did care and handled it */
2952       ret = TRUE;
2953       goto exit;
2954     }
2955
2956     /* now index should be as reliable as it can be for current purpose */
2957     gst_flv_demux_move_to_offset (demux,
2958         gst_flv_demux_find_offset (demux, &seeksegment, flags), TRUE);
2959     ret = TRUE;
2960   } else {
2961     ret = TRUE;
2962   }
2963
2964   if (flush) {
2965     /* Stop flushing, the sinks are at time 0 now */
2966     gst_flv_demux_push_src_event (demux, gst_event_new_flush_stop (TRUE));
2967   }
2968
2969   if (ret) {
2970     /* Ok seek succeeded, take the newly configured segment */
2971     memcpy (&demux->segment, &seeksegment, sizeof (GstSegment));
2972
2973     /* Notify about the start of a new segment */
2974     if (demux->segment.flags & GST_SEGMENT_FLAG_SEGMENT) {
2975       gst_element_post_message (GST_ELEMENT (demux),
2976           gst_message_new_segment_start (GST_OBJECT (demux),
2977               demux->segment.format, demux->segment.position));
2978     }
2979
2980     gst_flow_combiner_reset (demux->flowcombiner);
2981     /* Tell all the stream a new segment is needed */
2982     demux->audio_need_segment = TRUE;
2983     demux->video_need_segment = TRUE;
2984     /* Clean any potential newsegment event kept for the streams. The first
2985      * stream needing a new segment will create a new one. */
2986     if (G_UNLIKELY (demux->new_seg_event)) {
2987       gst_event_unref (demux->new_seg_event);
2988       demux->new_seg_event = NULL;
2989     }
2990     GST_DEBUG_OBJECT (demux, "preparing newsegment from %"
2991         GST_TIME_FORMAT " to %" GST_TIME_FORMAT,
2992         GST_TIME_ARGS (demux->segment.start),
2993         GST_TIME_ARGS (demux->segment.stop));
2994     demux->new_seg_event = gst_event_new_segment (&demux->segment);
2995   }
2996
2997 exit:
2998   GST_OBJECT_LOCK (demux);
2999   seeking = demux->seeking && !seeking;
3000   demux->seeking = FALSE;
3001   GST_OBJECT_UNLOCK (demux);
3002
3003   /* if we detect an external seek having started (and possibly already having
3004    * flushed), do not restart task to give it a chance.
3005    * Otherwise external one's flushing will take care to pause task */
3006   if (seeking) {
3007     gst_pad_pause_task (demux->sinkpad);
3008   } else {
3009     gst_pad_start_task (demux->sinkpad,
3010         (GstTaskFunction) gst_flv_demux_loop, demux->sinkpad, NULL);
3011   }
3012
3013   GST_PAD_STREAM_UNLOCK (demux->sinkpad);
3014
3015   gst_event_unref (event);
3016   return ret;
3017
3018   /* ERRORS */
3019 wrong_format:
3020   {
3021     GST_WARNING_OBJECT (demux, "we only support seeking in TIME format");
3022     gst_event_unref (event);
3023     return ret;
3024   }
3025 }
3026
3027 /* If we can pull that's prefered */
3028 static gboolean
3029 gst_flv_demux_sink_activate (GstPad * sinkpad, GstObject * parent)
3030 {
3031   GstQuery *query;
3032   gboolean pull_mode;
3033
3034   query = gst_query_new_scheduling ();
3035
3036   if (!gst_pad_peer_query (sinkpad, query)) {
3037     gst_query_unref (query);
3038     goto activate_push;
3039   }
3040
3041   pull_mode = gst_query_has_scheduling_mode_with_flags (query,
3042       GST_PAD_MODE_PULL, GST_SCHEDULING_FLAG_SEEKABLE);
3043   gst_query_unref (query);
3044
3045   if (!pull_mode)
3046     goto activate_push;
3047
3048   GST_DEBUG_OBJECT (sinkpad, "activating pull");
3049   return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PULL, TRUE);
3050
3051 activate_push:
3052   {
3053     GST_DEBUG_OBJECT (sinkpad, "activating push");
3054     return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PUSH, TRUE);
3055   }
3056 }
3057
3058 static gboolean
3059 gst_flv_demux_sink_activate_mode (GstPad * sinkpad, GstObject * parent,
3060     GstPadMode mode, gboolean active)
3061 {
3062   gboolean res;
3063   GstFlvDemux *demux;
3064
3065   demux = GST_FLV_DEMUX (parent);
3066
3067   switch (mode) {
3068     case GST_PAD_MODE_PUSH:
3069       demux->random_access = FALSE;
3070       res = TRUE;
3071       break;
3072     case GST_PAD_MODE_PULL:
3073       if (active) {
3074         demux->random_access = TRUE;
3075         res = gst_pad_start_task (sinkpad, (GstTaskFunction) gst_flv_demux_loop,
3076             sinkpad, NULL);
3077       } else {
3078         demux->random_access = FALSE;
3079         res = gst_pad_stop_task (sinkpad);
3080       }
3081       break;
3082     default:
3083       res = FALSE;
3084       break;
3085   }
3086   return res;
3087 }
3088
3089 static gboolean
3090 gst_flv_demux_sink_event (GstPad * pad, GstObject * parent, GstEvent * event)
3091 {
3092   GstFlvDemux *demux;
3093   gboolean ret = FALSE;
3094
3095   demux = GST_FLV_DEMUX (parent);
3096
3097   GST_DEBUG_OBJECT (demux, "handling event %s", GST_EVENT_TYPE_NAME (event));
3098
3099   switch (GST_EVENT_TYPE (event)) {
3100     case GST_EVENT_FLUSH_START:
3101       GST_DEBUG_OBJECT (demux, "trying to force chain function to exit");
3102       demux->flushing = TRUE;
3103       ret = gst_flv_demux_push_src_event (demux, event);
3104       break;
3105     case GST_EVENT_FLUSH_STOP:
3106       GST_DEBUG_OBJECT (demux, "flushing FLV demuxer");
3107       gst_flv_demux_flush (demux, TRUE);
3108       ret = gst_flv_demux_push_src_event (demux, event);
3109       break;
3110     case GST_EVENT_EOS:
3111     {
3112       GstIndex *index;
3113
3114       GST_DEBUG_OBJECT (demux, "received EOS");
3115
3116       index = gst_flv_demux_get_index (GST_ELEMENT (demux));
3117
3118       if (index) {
3119         GST_DEBUG_OBJECT (demux, "committing index");
3120         gst_index_commit (index, demux->index_id);
3121         gst_object_unref (index);
3122       }
3123
3124       if (!demux->audio_pad && !demux->video_pad)
3125         GST_ELEMENT_ERROR (demux, STREAM, FAILED,
3126             ("Internal data stream error."), ("Got EOS before any data"));
3127       else {
3128         if (!demux->no_more_pads) {
3129           gst_element_no_more_pads (GST_ELEMENT (demux));
3130           demux->no_more_pads = TRUE;
3131         }
3132
3133         if (!gst_flv_demux_push_src_event (demux, event))
3134           GST_WARNING_OBJECT (demux, "failed pushing EOS on streams");
3135       }
3136       ret = TRUE;
3137       break;
3138     }
3139     case GST_EVENT_SEGMENT:
3140     {
3141       GstSegment in_segment;
3142
3143       GST_DEBUG_OBJECT (demux, "received new segment");
3144
3145       gst_event_copy_segment (event, &in_segment);
3146
3147       if (in_segment.format == GST_FORMAT_TIME) {
3148         /* time segment, this is perfect, copy over the values. */
3149         memcpy (&demux->segment, &in_segment, sizeof (in_segment));
3150
3151         GST_DEBUG_OBJECT (demux, "NEWSEGMENT: %" GST_SEGMENT_FORMAT,
3152             &demux->segment);
3153
3154         /* and forward */
3155         ret = gst_flv_demux_push_src_event (demux, event);
3156       } else {
3157         /* non-time format */
3158         demux->audio_need_segment = TRUE;
3159         demux->video_need_segment = TRUE;
3160         ret = TRUE;
3161         gst_event_unref (event);
3162         if (demux->new_seg_event) {
3163           gst_event_unref (demux->new_seg_event);
3164           demux->new_seg_event = NULL;
3165         }
3166       }
3167       gst_flow_combiner_reset (demux->flowcombiner);
3168       break;
3169     }
3170     default:
3171       ret = gst_pad_event_default (pad, parent, event);
3172       break;
3173   }
3174
3175   return ret;
3176 }
3177
3178 static gboolean
3179 gst_flv_demux_src_event (GstPad * pad, GstObject * parent, GstEvent * event)
3180 {
3181   GstFlvDemux *demux;
3182   gboolean ret = FALSE;
3183
3184   demux = GST_FLV_DEMUX (parent);
3185
3186   GST_DEBUG_OBJECT (demux, "handling event %s", GST_EVENT_TYPE_NAME (event));
3187
3188   switch (GST_EVENT_TYPE (event)) {
3189     case GST_EVENT_SEEK:
3190       /* Try to push upstream first */
3191       gst_event_ref (event);
3192       ret = gst_pad_push_event (demux->sinkpad, event);
3193       if (ret) {
3194         gst_event_unref (event);
3195         break;
3196       }
3197       if (demux->random_access) {
3198         ret = gst_flv_demux_handle_seek_pull (demux, event, TRUE);
3199       } else {
3200         ret = gst_flv_demux_handle_seek_push (demux, event);
3201       }
3202       break;
3203     default:
3204       ret = gst_pad_push_event (demux->sinkpad, event);
3205       break;
3206   }
3207
3208   return ret;
3209 }
3210
3211 static gboolean
3212 gst_flv_demux_query (GstPad * pad, GstObject * parent, GstQuery * query)
3213 {
3214   gboolean res = TRUE;
3215   GstFlvDemux *demux;
3216
3217   demux = GST_FLV_DEMUX (parent);
3218
3219   switch (GST_QUERY_TYPE (query)) {
3220     case GST_QUERY_DURATION:
3221     {
3222       GstFormat format;
3223
3224       gst_query_parse_duration (query, &format, NULL);
3225
3226       /* duration is time only */
3227       if (format != GST_FORMAT_TIME) {
3228         GST_DEBUG_OBJECT (demux, "duration query only supported for time "
3229             "format");
3230         res = FALSE;
3231         goto beach;
3232       }
3233
3234       /* Try to push upstream first */
3235       res = gst_pad_peer_query (demux->sinkpad, query);
3236       if (res)
3237         goto beach;
3238
3239       GST_DEBUG_OBJECT (pad, "duration query, replying %" GST_TIME_FORMAT,
3240           GST_TIME_ARGS (demux->duration));
3241
3242       gst_query_set_duration (query, GST_FORMAT_TIME, demux->duration);
3243       res = TRUE;
3244       break;
3245     }
3246     case GST_QUERY_POSITION:
3247     {
3248       GstFormat format;
3249
3250       gst_query_parse_position (query, &format, NULL);
3251
3252       /* position is time only */
3253       if (format != GST_FORMAT_TIME) {
3254         GST_DEBUG_OBJECT (demux, "position query only supported for time "
3255             "format");
3256         res = FALSE;
3257         goto beach;
3258       }
3259
3260       GST_DEBUG_OBJECT (pad, "position query, replying %" GST_TIME_FORMAT,
3261           GST_TIME_ARGS (demux->segment.position));
3262
3263       gst_query_set_position (query, GST_FORMAT_TIME, demux->segment.position);
3264
3265       break;
3266     }
3267
3268     case GST_QUERY_SEEKING:{
3269       GstFormat fmt;
3270
3271       gst_query_parse_seeking (query, &fmt, NULL, NULL, NULL);
3272
3273       /* First ask upstream */
3274       if (fmt == GST_FORMAT_TIME && gst_pad_peer_query (demux->sinkpad, query)) {
3275         gboolean seekable;
3276
3277         gst_query_parse_seeking (query, NULL, &seekable, NULL, NULL);
3278         if (seekable) {
3279           res = TRUE;
3280           break;
3281         }
3282       }
3283       res = TRUE;
3284       /* FIXME, check index this way is not thread safe */
3285       if (fmt != GST_FORMAT_TIME || !demux->index) {
3286         gst_query_set_seeking (query, fmt, FALSE, -1, -1);
3287       } else if (demux->random_access) {
3288         gst_query_set_seeking (query, GST_FORMAT_TIME, TRUE, 0,
3289             demux->duration);
3290       } else {
3291         GstQuery *peerquery = gst_query_new_seeking (GST_FORMAT_BYTES);
3292         gboolean seekable = gst_pad_peer_query (demux->sinkpad, peerquery);
3293
3294         if (seekable)
3295           gst_query_parse_seeking (peerquery, NULL, &seekable, NULL, NULL);
3296         gst_query_unref (peerquery);
3297
3298         if (seekable)
3299           gst_query_set_seeking (query, GST_FORMAT_TIME, seekable, 0,
3300               demux->duration);
3301         else
3302           gst_query_set_seeking (query, GST_FORMAT_TIME, FALSE, -1, -1);
3303       }
3304       break;
3305     }
3306     case GST_QUERY_SEGMENT:
3307     {
3308       GstFormat format;
3309       gint64 start, stop;
3310
3311       format = demux->segment.format;
3312
3313       start =
3314           gst_segment_to_stream_time (&demux->segment, format,
3315           demux->segment.start);
3316       if ((stop = demux->segment.stop) == -1)
3317         stop = demux->segment.duration;
3318       else
3319         stop = gst_segment_to_stream_time (&demux->segment, format, stop);
3320
3321       gst_query_set_segment (query, demux->segment.rate, format, start, stop);
3322       res = TRUE;
3323       break;
3324     }
3325     case GST_QUERY_LATENCY:
3326     default:
3327       res = gst_pad_query_default (pad, parent, query);
3328       break;
3329   }
3330
3331 beach:
3332
3333   return res;
3334 }
3335
3336 static GstStateChangeReturn
3337 gst_flv_demux_change_state (GstElement * element, GstStateChange transition)
3338 {
3339   GstFlvDemux *demux;
3340   GstStateChangeReturn ret;
3341
3342   demux = GST_FLV_DEMUX (element);
3343
3344   switch (transition) {
3345     case GST_STATE_CHANGE_READY_TO_PAUSED:
3346       /* If this is our own index destroy it as the
3347        * old entries might be wrong for the new stream */
3348       if (demux->own_index) {
3349         gst_object_unref (demux->index);
3350         demux->index = NULL;
3351         demux->own_index = FALSE;
3352       }
3353
3354       /* If no index was created, generate one */
3355       if (G_UNLIKELY (!demux->index)) {
3356         GST_DEBUG_OBJECT (demux, "no index provided creating our own");
3357
3358         demux->index = g_object_new (gst_mem_index_get_type (), NULL);
3359
3360         gst_index_get_writer_id (demux->index, GST_OBJECT (demux),
3361             &demux->index_id);
3362         demux->own_index = TRUE;
3363       }
3364       gst_flv_demux_cleanup (demux);
3365       break;
3366     default:
3367       break;
3368   }
3369
3370   ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
3371   if (ret == GST_STATE_CHANGE_FAILURE)
3372     return ret;
3373
3374   switch (transition) {
3375     case GST_STATE_CHANGE_PAUSED_TO_READY:
3376       gst_flv_demux_cleanup (demux);
3377       break;
3378     default:
3379       break;
3380   }
3381
3382   return ret;
3383 }
3384
3385 #if 0
3386 static void
3387 gst_flv_demux_set_index (GstElement * element, GstIndex * index)
3388 {
3389   GstFlvDemux *demux = GST_FLV_DEMUX (element);
3390   GstIndex *old_index;
3391
3392   GST_OBJECT_LOCK (demux);
3393
3394   old_index = demux->index;
3395
3396   if (index) {
3397     demux->index = gst_object_ref (index);
3398     demux->own_index = FALSE;
3399   } else
3400     demux->index = NULL;
3401
3402   if (old_index)
3403     gst_object_unref (demux->index);
3404
3405   gst_object_ref (index);
3406
3407   GST_OBJECT_UNLOCK (demux);
3408
3409   /* object lock might be taken again */
3410   if (index)
3411     gst_index_get_writer_id (index, GST_OBJECT (element), &demux->index_id);
3412
3413   GST_DEBUG_OBJECT (demux, "Set index %" GST_PTR_FORMAT, demux->index);
3414
3415   gst_object_unref (index);
3416 }
3417 #endif
3418
3419 static GstIndex *
3420 gst_flv_demux_get_index (GstElement * element)
3421 {
3422   GstIndex *result = NULL;
3423
3424   GstFlvDemux *demux = GST_FLV_DEMUX (element);
3425
3426   GST_OBJECT_LOCK (demux);
3427   if (demux->index)
3428     result = gst_object_ref (demux->index);
3429   GST_OBJECT_UNLOCK (demux);
3430
3431   return result;
3432 }
3433
3434 static void
3435 gst_flv_demux_dispose (GObject * object)
3436 {
3437   GstFlvDemux *demux = GST_FLV_DEMUX (object);
3438
3439   GST_DEBUG_OBJECT (demux, "disposing FLV demuxer");
3440
3441   if (demux->adapter) {
3442     gst_adapter_clear (demux->adapter);
3443     g_object_unref (demux->adapter);
3444     demux->adapter = NULL;
3445   }
3446
3447   if (demux->taglist) {
3448     gst_tag_list_unref (demux->taglist);
3449     demux->taglist = NULL;
3450   }
3451
3452   if (demux->flowcombiner) {
3453     gst_flow_combiner_free (demux->flowcombiner);
3454     demux->flowcombiner = NULL;
3455   }
3456
3457   if (demux->new_seg_event) {
3458     gst_event_unref (demux->new_seg_event);
3459     demux->new_seg_event = NULL;
3460   }
3461
3462   if (demux->audio_codec_data) {
3463     gst_buffer_unref (demux->audio_codec_data);
3464     demux->audio_codec_data = NULL;
3465   }
3466
3467   if (demux->video_codec_data) {
3468     gst_buffer_unref (demux->video_codec_data);
3469     demux->video_codec_data = NULL;
3470   }
3471
3472   if (demux->audio_pad) {
3473     gst_object_unref (demux->audio_pad);
3474     demux->audio_pad = NULL;
3475   }
3476
3477   if (demux->video_pad) {
3478     gst_object_unref (demux->video_pad);
3479     demux->video_pad = NULL;
3480   }
3481
3482   if (demux->index) {
3483     gst_object_unref (demux->index);
3484     demux->index = NULL;
3485   }
3486
3487   if (demux->times) {
3488     g_array_free (demux->times, TRUE);
3489     demux->times = NULL;
3490   }
3491
3492   if (demux->filepositions) {
3493     g_array_free (demux->filepositions, TRUE);
3494     demux->filepositions = NULL;
3495   }
3496
3497   GST_CALL_PARENT (G_OBJECT_CLASS, dispose, (object));
3498 }
3499
3500 static void
3501 gst_flv_demux_class_init (GstFlvDemuxClass * klass)
3502 {
3503   GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass);
3504   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
3505
3506   gobject_class->dispose = gst_flv_demux_dispose;
3507
3508   gstelement_class->change_state =
3509       GST_DEBUG_FUNCPTR (gst_flv_demux_change_state);
3510
3511 #if 0
3512   gstelement_class->set_index = GST_DEBUG_FUNCPTR (gst_flv_demux_set_index);
3513   gstelement_class->get_index = GST_DEBUG_FUNCPTR (gst_flv_demux_get_index);
3514 #endif
3515
3516   gst_element_class_add_pad_template (gstelement_class,
3517       gst_static_pad_template_get (&flv_sink_template));
3518   gst_element_class_add_pad_template (gstelement_class,
3519       gst_static_pad_template_get (&audio_src_template));
3520   gst_element_class_add_pad_template (gstelement_class,
3521       gst_static_pad_template_get (&video_src_template));
3522   gst_element_class_set_static_metadata (gstelement_class, "FLV Demuxer",
3523       "Codec/Demuxer",
3524       "Demux FLV feeds into digital streams",
3525       "Julien Moutte <julien@moutte.net>");
3526 }
3527
3528 static void
3529 gst_flv_demux_init (GstFlvDemux * demux)
3530 {
3531   demux->sinkpad =
3532       gst_pad_new_from_static_template (&flv_sink_template, "sink");
3533
3534   gst_pad_set_event_function (demux->sinkpad,
3535       GST_DEBUG_FUNCPTR (gst_flv_demux_sink_event));
3536   gst_pad_set_chain_function (demux->sinkpad,
3537       GST_DEBUG_FUNCPTR (gst_flv_demux_chain));
3538   gst_pad_set_activate_function (demux->sinkpad,
3539       GST_DEBUG_FUNCPTR (gst_flv_demux_sink_activate));
3540   gst_pad_set_activatemode_function (demux->sinkpad,
3541       GST_DEBUG_FUNCPTR (gst_flv_demux_sink_activate_mode));
3542
3543   gst_element_add_pad (GST_ELEMENT (demux), demux->sinkpad);
3544
3545   demux->adapter = gst_adapter_new ();
3546   demux->taglist = gst_tag_list_new_empty ();
3547   demux->flowcombiner = gst_flow_combiner_new ();
3548   gst_segment_init (&demux->segment, GST_FORMAT_TIME);
3549
3550   demux->own_index = FALSE;
3551
3552   GST_OBJECT_FLAG_SET (demux, GST_ELEMENT_FLAG_INDEXABLE);
3553
3554   gst_flv_demux_cleanup (demux);
3555 }
3556
3557 static gboolean
3558 plugin_init (GstPlugin * plugin)
3559 {
3560   GST_DEBUG_CATEGORY_INIT (flvdemux_debug, "flvdemux", 0, "FLV demuxer");
3561
3562   if (!gst_element_register (plugin, "flvdemux", GST_RANK_PRIMARY,
3563           gst_flv_demux_get_type ()) ||
3564       !gst_element_register (plugin, "flvmux", GST_RANK_PRIMARY,
3565           gst_flv_mux_get_type ()))
3566     return FALSE;
3567
3568   return TRUE;
3569 }
3570
3571 GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, GST_VERSION_MINOR,
3572     flv, "FLV muxing and demuxing plugin",
3573     plugin_init, VERSION, "LGPL", GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN)