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