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