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