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