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