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