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