2 * Copyright (C) <2007> Julien Moutte <julien@moutte.net>
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.
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.
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
17 * Boston, MA 02110-1301, USA.
21 * SECTION:element-flvdemux
23 * flvdemux demuxes an FLV file into the different contained streams.
26 * <title>Example launch line</title>
28 * gst-launch-1.0 -v filesrc location=/path/to/flv ! flvdemux ! audioconvert ! autoaudiosink
29 * ]| This pipeline demuxes an FLV file and outputs the contained raw audio streams.
37 #include "gstflvdemux.h"
38 #include "gstflvmux.h"
42 #include <gst/base/gstbytereader.h>
43 #include <gst/base/gstbytewriter.h>
44 #include <gst/pbutils/descriptions.h>
45 #include <gst/pbutils/pbutils.h>
46 #include <gst/audio/audio.h>
47 #include <gst/video/video.h>
48 #include <gst/tag/tag.h>
50 /* FIXME: don't rely on own GstIndex */
52 #include "gstmemindex.c"
53 #define GST_ASSOCIATION_FLAG_NONE GST_INDEX_ASSOCIATION_FLAG_NONE
54 #define GST_ASSOCIATION_FLAG_KEY_UNIT GST_INDEX_ASSOCIATION_FLAG_KEY_UNIT
55 #define GST_ASSOCIATION_FLAG_DELTA_UNIT GST_INDEX_ASSOCIATION_FLAG_DELTA_UNIT
57 static GstStaticPadTemplate flv_sink_template = GST_STATIC_PAD_TEMPLATE ("sink",
60 GST_STATIC_CAPS ("video/x-flv")
63 static GstStaticPadTemplate audio_src_template =
64 GST_STATIC_PAD_TEMPLATE ("audio",
68 ("audio/x-adpcm, layout = (string) swf, channels = (int) { 1, 2 }, rate = (int) { 5512, 11025, 22050, 44100 }; "
69 "audio/mpeg, mpegversion = (int) 1, layer = (int) 3, channels = (int) { 1, 2 }, rate = (int) { 5512, 8000, 11025, 22050, 44100 }, parsed = (boolean) TRUE; "
70 "audio/mpeg, mpegversion = (int) 4, stream-format = (string) raw, framed = (boolean) TRUE; "
71 "audio/x-nellymoser, channels = (int) { 1, 2 }, rate = (int) { 5512, 8000, 11025, 16000, 22050, 44100 }; "
72 "audio/x-raw, format = (string) { U8, S16LE }, layout = (string) interleaved, channels = (int) { 1, 2 }, rate = (int) { 5512, 11025, 22050, 44100 }; "
73 "audio/x-alaw, channels = (int) { 1, 2 }, rate = (int) 8000; "
74 "audio/x-mulaw, channels = (int) { 1, 2 }, rate = (int) 8000; "
75 "audio/x-speex, channels = (int) 1, rate = (int) 16000;")
78 static GstStaticPadTemplate video_src_template =
79 GST_STATIC_PAD_TEMPLATE ("video",
82 GST_STATIC_CAPS ("video/x-flash-video, flvversion=(int) 1; "
83 "video/x-flash-screen; "
84 "video/x-vp6-flash; " "video/x-vp6-alpha; "
85 "video/x-h264, stream-format=avc;")
88 GST_DEBUG_CATEGORY_STATIC (flvdemux_debug);
89 #define GST_CAT_DEFAULT flvdemux_debug
91 #define gst_flv_demux_parent_class parent_class
92 G_DEFINE_TYPE (GstFlvDemux, gst_flv_demux, GST_TYPE_ELEMENT);
94 /* 9 bytes of header + 4 bytes of first previous tag size */
95 #define FLV_HEADER_SIZE 13
96 /* 1 byte of tag type + 3 bytes of tag data size */
97 #define FLV_TAG_TYPE_SIZE 4
99 /* two seconds - consider dts are resynced to another base if this different */
100 #define RESYNC_THRESHOLD 2000
102 /* how much stream time to wait for audio tags to appear after we have video, or vice versa */
103 #define NO_MORE_PADS_THRESHOLD (6 * GST_SECOND)
105 static gboolean flv_demux_handle_seek_push (GstFlvDemux * demux,
107 static gboolean gst_flv_demux_handle_seek_pull (GstFlvDemux * demux,
108 GstEvent * event, gboolean seeking);
110 static gboolean gst_flv_demux_query (GstPad * pad, GstObject * parent,
112 static gboolean gst_flv_demux_src_event (GstPad * pad, GstObject * parent,
115 static GstIndex *gst_flv_demux_get_index (GstElement * element);
117 static void gst_flv_demux_push_tags (GstFlvDemux * demux);
120 gst_flv_demux_parse_and_add_index_entry (GstFlvDemux * demux, GstClockTime ts,
121 guint64 pos, gboolean keyframe)
123 GstIndexAssociation associations[2];
125 GstIndexEntry *entry;
127 GST_LOG_OBJECT (demux,
128 "adding key=%d association %" GST_TIME_FORMAT "-> %" G_GUINT64_FORMAT,
129 keyframe, GST_TIME_ARGS (ts), pos);
131 /* if upstream is not seekable there is no point in building an index */
132 if (!demux->upstream_seekable)
135 index = gst_flv_demux_get_index (GST_ELEMENT (demux));
140 /* entry may already have been added before, avoid adding indefinitely */
141 entry = gst_index_get_assoc_entry (index, demux->index_id,
142 GST_INDEX_LOOKUP_EXACT, GST_ASSOCIATION_FLAG_NONE, GST_FORMAT_BYTES, pos);
145 #ifndef GST_DISABLE_GST_DEBUG
149 gst_index_entry_assoc_map (entry, GST_FORMAT_TIME, &time);
150 key = ! !(GST_INDEX_ASSOC_FLAGS (entry) & GST_ASSOCIATION_FLAG_KEY_UNIT);
151 GST_LOG_OBJECT (demux, "position already mapped to time %" GST_TIME_FORMAT
152 ", keyframe %d", GST_TIME_ARGS (time), key);
153 /* there is not really a way to delete the existing one */
154 if (time != ts || key != ! !keyframe)
155 GST_DEBUG_OBJECT (demux, "metadata mismatch");
157 gst_object_unref (index);
161 associations[0].format = GST_FORMAT_TIME;
162 associations[0].value = ts;
163 associations[1].format = GST_FORMAT_BYTES;
164 associations[1].value = pos;
166 gst_index_add_associationv (index, demux->index_id,
167 (keyframe) ? GST_ASSOCIATION_FLAG_KEY_UNIT :
168 GST_ASSOCIATION_FLAG_DELTA_UNIT, 2,
169 (const GstIndexAssociation *) &associations);
171 if (pos > demux->index_max_pos)
172 demux->index_max_pos = pos;
173 if (ts > demux->index_max_time)
174 demux->index_max_time = ts;
176 gst_object_unref (index);
180 FLV_GET_STRING (GstByteReader * reader)
182 guint16 string_size = 0;
183 gchar *string = NULL;
184 const guint8 *str = NULL;
186 g_return_val_if_fail (reader != NULL, NULL);
188 if (G_UNLIKELY (!gst_byte_reader_get_uint16_be (reader, &string_size)))
191 if (G_UNLIKELY (string_size > gst_byte_reader_get_remaining (reader)))
194 string = g_try_malloc0 (string_size + 1);
195 if (G_UNLIKELY (!string)) {
199 if (G_UNLIKELY (!gst_byte_reader_get_data (reader, string_size, &str))) {
204 memcpy (string, str, string_size);
205 if (!g_utf8_validate (string, string_size, NULL)) {
214 gst_flv_demux_check_seekability (GstFlvDemux * demux)
217 gint64 start = -1, stop = -1;
219 demux->upstream_seekable = FALSE;
221 query = gst_query_new_seeking (GST_FORMAT_BYTES);
222 if (!gst_pad_peer_query (demux->sinkpad, query)) {
223 GST_DEBUG_OBJECT (demux, "seeking query failed");
224 gst_query_unref (query);
228 gst_query_parse_seeking (query, NULL, &demux->upstream_seekable,
231 gst_query_unref (query);
233 /* try harder to query upstream size if we didn't get it the first time */
234 if (demux->upstream_seekable && stop == -1) {
235 GST_DEBUG_OBJECT (demux, "doing duration query to fix up unset stop");
236 gst_pad_peer_query_duration (demux->sinkpad, GST_FORMAT_BYTES, &stop);
239 /* if upstream doesn't know the size, it's likely that it's not seekable in
240 * practice even if it technically may be seekable */
241 if (demux->upstream_seekable && (start != 0 || stop <= start)) {
242 GST_DEBUG_OBJECT (demux, "seekable but unknown start/stop -> disable");
243 demux->upstream_seekable = FALSE;
246 GST_DEBUG_OBJECT (demux, "upstream seekable: %d", demux->upstream_seekable);
250 parse_flv_demux_parse_date_string (const gchar * s)
252 static const gchar months[12][4] = {
253 "Jan", "Feb", "Mar", "Apr",
254 "May", "Jun", "Jul", "Aug",
255 "Sep", "Oct", "Nov", "Dec"
257 GstDateTime *dt = NULL;
260 gchar *endptr, *stripped;
262 gint year = -1, month = -1, day = -1;
263 gint hour = -1, minute = -1, seconds = -1;
265 stripped = g_strstrip (g_strdup (s));
267 /* "Fri Oct 15 15:13:16 2004" needs to be parsed */
268 tokens = g_strsplit (stripped, " ", -1);
272 if (g_strv_length (tokens) != 5)
276 d = g_ascii_strtoull (tokens[4], &endptr, 10);
277 if (d == 0 && *endptr != '\0')
283 if (strlen (tokens[1]) != 3)
285 for (i = 0; i < 12; i++) {
286 if (!strcmp (tokens[1], months[i])) {
296 d = g_ascii_strtoull (tokens[2], &endptr, 10);
297 if (d == 0 && *endptr != '\0')
304 if (sscanf (tokens[3], "%d:%d:%d", &hh, &mm, &ss) < 2)
306 if (hh >= 0 && hh < 24 && mm >= 0 && mm < 60 && ss >= 0 && ss < 60) {
318 dt = gst_date_time_new (0.0, year, month, day, hour, minute, seconds);
324 gst_flv_demux_parse_metadata_item (GstFlvDemux * demux, GstByteReader * reader,
325 gboolean * end_marker)
327 gchar *tag_name = NULL;
330 /* Initialize the end_marker flag to FALSE */
333 /* Name of the tag */
334 tag_name = FLV_GET_STRING (reader);
335 if (G_UNLIKELY (!tag_name)) {
336 GST_WARNING_OBJECT (demux, "failed reading tag name");
340 /* What kind of object is that */
341 if (!gst_byte_reader_get_uint8 (reader, &tag_type))
344 GST_DEBUG_OBJECT (demux, "tag name %s, tag type %d", tag_name, tag_type);
348 { /* Use a union to read the uint64 and then as a double */
351 if (!gst_byte_reader_get_float64_be (reader, &d))
354 GST_DEBUG_OBJECT (demux, "%s => (double) %f", tag_name, d);
356 if (!strcmp (tag_name, "duration")) {
357 demux->duration = d * GST_SECOND;
359 gst_tag_list_add (demux->taglist, GST_TAG_MERGE_REPLACE,
360 GST_TAG_DURATION, demux->duration, NULL);
361 } else if (!strcmp (tag_name, "AspectRatioX")) {
363 demux->got_par = TRUE;
364 } else if (!strcmp (tag_name, "AspectRatioY")) {
366 demux->got_par = TRUE;
367 } else if (!strcmp (tag_name, "width")) {
369 } else if (!strcmp (tag_name, "height")) {
371 } else if (!strcmp (tag_name, "framerate")) {
372 demux->framerate = d;
373 } else if (!strcmp (tag_name, "audiodatarate")) {
374 gst_tag_list_add (demux->audio_tags, GST_TAG_MERGE_REPLACE,
375 GST_TAG_NOMINAL_BITRATE, (guint) (d * 1024), NULL);
376 } else if (!strcmp (tag_name, "videodatarate")) {
377 gst_tag_list_add (demux->video_tags, GST_TAG_MERGE_REPLACE,
378 GST_TAG_NOMINAL_BITRATE, (guint) (d * 1024), NULL);
380 GST_INFO_OBJECT (demux, "Tag \'%s\' not handled", tag_name);
385 case 1: /* Boolean */
389 if (!gst_byte_reader_get_uint8 (reader, &b))
392 GST_DEBUG_OBJECT (demux, "%s => (boolean) %d", tag_name, b);
394 GST_INFO_OBJECT (demux, "Tag \'%s\' not handled", tag_name);
402 s = FLV_GET_STRING (reader);
406 GST_DEBUG_OBJECT (demux, "%s => (string) %s", tag_name, s);
408 if (!strcmp (tag_name, "creationdate")) {
411 dt = parse_flv_demux_parse_date_string (s);
413 GST_DEBUG_OBJECT (demux, "Failed to parse '%s' into datetime", s);
415 gst_tag_list_add (demux->taglist, GST_TAG_MERGE_REPLACE,
416 GST_TAG_DATE_TIME, dt, NULL);
417 gst_date_time_unref (dt);
419 } else if (!strcmp (tag_name, "creator")) {
420 gst_tag_list_add (demux->taglist, GST_TAG_MERGE_REPLACE,
421 GST_TAG_ARTIST, s, NULL);
422 } else if (!strcmp (tag_name, "title")) {
423 gst_tag_list_add (demux->taglist, GST_TAG_MERGE_REPLACE,
424 GST_TAG_TITLE, s, NULL);
425 } else if (!strcmp (tag_name, "metadatacreator")
426 || !strcmp (tag_name, "encoder")) {
427 gst_tag_list_add (demux->taglist, GST_TAG_MERGE_REPLACE,
428 GST_TAG_ENCODER, s, NULL);
430 GST_INFO_OBJECT (demux, "Tag \'%s\' not handled", tag_name);
439 gboolean end_of_object_marker = FALSE;
441 while (!end_of_object_marker) {
442 gboolean ok = gst_flv_demux_parse_metadata_item (demux, reader,
443 &end_of_object_marker);
445 if (G_UNLIKELY (!ok)) {
446 GST_WARNING_OBJECT (demux, "failed reading a tag, skipping");
453 case 8: /* ECMA array */
455 guint32 nb_elems = 0;
456 gboolean end_of_object_marker = FALSE;
458 if (!gst_byte_reader_get_uint32_be (reader, &nb_elems))
461 GST_DEBUG_OBJECT (demux, "there are approx. %d elements in the array",
464 while (!end_of_object_marker) {
465 gboolean ok = gst_flv_demux_parse_metadata_item (demux, reader,
466 &end_of_object_marker);
468 if (G_UNLIKELY (!ok)) {
469 GST_WARNING_OBJECT (demux, "failed reading a tag, skipping");
476 case 9: /* End marker */
478 GST_DEBUG_OBJECT (demux, "end marker ?");
479 if (tag_name[0] == '\0') {
481 GST_DEBUG_OBJECT (demux, "end marker detected");
490 guint32 nb_elems = 0;
492 if (!gst_byte_reader_get_uint32_be (reader, &nb_elems))
495 GST_DEBUG_OBJECT (demux, "array has %d elements", nb_elems);
497 if (!strcmp (tag_name, "times")) {
499 g_array_free (demux->times, TRUE);
501 demux->times = g_array_new (FALSE, TRUE, sizeof (gdouble));
502 } else if (!strcmp (tag_name, "filepositions")) {
503 if (demux->filepositions) {
504 g_array_free (demux->filepositions, TRUE);
506 demux->filepositions = g_array_new (FALSE, TRUE, sizeof (gdouble));
510 guint8 elem_type = 0;
512 if (!gst_byte_reader_get_uint8 (reader, &elem_type))
520 if (!gst_byte_reader_get_float64_be (reader, &d))
523 GST_DEBUG_OBJECT (demux, "element is a double %f", d);
525 if (!strcmp (tag_name, "times") && demux->times) {
526 g_array_append_val (demux->times, d);
527 } else if (!strcmp (tag_name, "filepositions") &&
528 demux->filepositions) {
529 g_array_append_val (demux->filepositions, d);
534 GST_WARNING_OBJECT (demux, "unsupported array element type %d",
546 if (!gst_byte_reader_get_float64_be (reader, &d))
549 if (!gst_byte_reader_get_int16_be (reader, &i))
552 GST_DEBUG_OBJECT (demux,
553 "%s => (date as a double) %f, timezone offset %d", tag_name, d, i);
555 GST_INFO_OBJECT (demux, "Tag \'%s\' not handled", tag_name);
560 GST_WARNING_OBJECT (demux, "unsupported tag type %d", tag_type);
574 gst_flv_demux_clear_tags (GstFlvDemux * demux)
576 GST_DEBUG_OBJECT (demux, "clearing taglist");
578 if (demux->taglist) {
579 gst_tag_list_unref (demux->taglist);
581 demux->taglist = gst_tag_list_new_empty ();
582 gst_tag_list_set_scope (demux->taglist, GST_TAG_SCOPE_GLOBAL);
584 if (demux->audio_tags) {
585 gst_tag_list_unref (demux->audio_tags);
587 demux->audio_tags = gst_tag_list_new_empty ();
589 if (demux->video_tags) {
590 gst_tag_list_unref (demux->video_tags);
592 demux->video_tags = gst_tag_list_new_empty ();
596 gst_flv_demux_parse_tag_script (GstFlvDemux * demux, GstBuffer * buffer)
598 GstFlowReturn ret = GST_FLOW_OK;
599 GstByteReader reader;
603 g_return_val_if_fail (gst_buffer_get_size (buffer) >= 7, GST_FLOW_ERROR);
605 gst_buffer_map (buffer, &map, GST_MAP_READ);
606 gst_byte_reader_init (&reader, map.data, map.size);
608 gst_byte_reader_skip_unchecked (&reader, 7);
610 GST_LOG_OBJECT (demux, "parsing a script tag");
612 if (!gst_byte_reader_get_uint8 (&reader, &type))
617 gchar *function_name;
620 function_name = FLV_GET_STRING (&reader);
622 GST_LOG_OBJECT (demux, "function name is %s", GST_STR_NULL (function_name));
624 if (function_name != NULL && strcmp (function_name, "onMetaData") == 0) {
625 gboolean end_marker = FALSE;
626 GST_DEBUG_OBJECT (demux, "we have a metadata script object");
628 gst_flv_demux_clear_tags (demux);
630 if (!gst_byte_reader_get_uint8 (&reader, &type)) {
631 g_free (function_name);
638 guint32 nb_elems = 0;
641 if (!gst_byte_reader_get_uint32_be (&reader, &nb_elems)) {
642 g_free (function_name);
646 /* The number of elements is just a hint, some files have
647 nb_elements == 0 and actually contain items. */
648 GST_DEBUG_OBJECT (demux, "there are approx. %d elements in the array",
651 /* fallthrough to read data */
655 while (!end_marker) {
657 gst_flv_demux_parse_metadata_item (demux, &reader, &end_marker);
659 if (G_UNLIKELY (!ok)) {
660 GST_WARNING_OBJECT (demux, "failed reading a tag, skipping");
667 GST_DEBUG_OBJECT (demux, "Unhandled script data type : %d", type);
668 g_free (function_name);
672 gst_flv_demux_push_tags (demux);
675 g_free (function_name);
677 if (demux->times && demux->filepositions) {
680 /* If an index was found, insert associations */
681 num = MIN (demux->times->len, demux->filepositions->len);
682 for (i = 0; i < num; i++) {
683 guint64 time, fileposition;
685 time = g_array_index (demux->times, gdouble, i) * GST_SECOND;
686 fileposition = g_array_index (demux->filepositions, gdouble, i);
687 gst_flv_demux_parse_and_add_index_entry (demux, time, fileposition,
690 demux->indexed = TRUE;
695 gst_buffer_unmap (buffer, &map);
701 have_group_id (GstFlvDemux * demux)
705 event = gst_pad_get_sticky_event (demux->sinkpad, GST_EVENT_STREAM_START, 0);
707 if (gst_event_parse_group_id (event, &demux->group_id))
708 demux->have_group_id = TRUE;
710 demux->have_group_id = FALSE;
711 gst_event_unref (event);
712 } else if (!demux->have_group_id) {
713 demux->have_group_id = TRUE;
714 demux->group_id = gst_util_group_id_next ();
717 return demux->have_group_id;
721 gst_flv_demux_audio_negotiate (GstFlvDemux * demux, guint32 codec_tag,
722 guint32 rate, guint32 channels, guint32 width)
724 GstCaps *caps = NULL, *old_caps;
725 gboolean ret = FALSE;
726 guint adjusted_rate = rate;
727 guint adjusted_channels = channels;
733 caps = gst_caps_new_simple ("audio/x-adpcm", "layout", G_TYPE_STRING,
738 caps = gst_caps_new_simple ("audio/mpeg",
739 "mpegversion", G_TYPE_INT, 1, "layer", G_TYPE_INT, 3,
740 "parsed", G_TYPE_BOOLEAN, TRUE, NULL);
745 GstAudioFormat format;
747 /* Assuming little endian for 0 (aka endianness of the
748 * system on which the file was created) as most people
749 * are probably using little endian machines */
750 format = gst_audio_format_build_integer ((width == 8) ? FALSE : TRUE,
751 G_LITTLE_ENDIAN, width, width);
753 caps = gst_caps_new_simple ("audio/x-raw",
754 "format", G_TYPE_STRING, gst_audio_format_to_string (format),
755 "layout", G_TYPE_STRING, "interleaved", NULL);
761 caps = gst_caps_new_empty_simple ("audio/x-nellymoser");
766 if (!demux->audio_codec_data) {
767 GST_DEBUG_OBJECT (demux, "don't have AAC codec data yet");
772 gst_buffer_map (demux->audio_codec_data, &map, GST_MAP_READ);
774 /* use codec-data to extract and verify samplerate */
778 freq_index = GST_READ_UINT16_BE (map.data);
779 freq_index = (freq_index & 0x0780) >> 7;
781 gst_codec_utils_aac_get_sample_rate_from_index (freq_index);
783 if (adjusted_rate && (rate != adjusted_rate)) {
784 GST_LOG_OBJECT (demux, "Ajusting AAC sample rate %d -> %d", rate,
787 adjusted_rate = rate;
791 gst_codec_utils_aac_get_channels (map.data, map.size);
793 if (adjusted_channels && (channels != adjusted_channels)) {
794 GST_LOG_OBJECT (demux, "Ajusting AAC channels %d -> %d", channels,
797 adjusted_channels = channels;
800 gst_buffer_unmap (demux->audio_codec_data, &map);
802 caps = gst_caps_new_simple ("audio/mpeg",
803 "mpegversion", G_TYPE_INT, 4, "framed", G_TYPE_BOOLEAN, TRUE,
804 "stream-format", G_TYPE_STRING, "raw", NULL);
808 caps = gst_caps_new_empty_simple ("audio/x-alaw");
811 caps = gst_caps_new_empty_simple ("audio/x-mulaw");
815 GValue streamheader = G_VALUE_INIT;
816 GValue value = G_VALUE_INIT;
818 GstStructure *structure;
822 caps = gst_caps_new_empty_simple ("audio/x-speex");
823 structure = gst_caps_get_structure (caps, 0);
825 GST_DEBUG_OBJECT (demux, "generating speex header");
827 /* Speex decoder expects streamheader to be { [header], [comment] } */
828 g_value_init (&streamheader, GST_TYPE_ARRAY);
831 gst_byte_writer_init_with_size (&w, 80, TRUE);
832 gst_byte_writer_put_data (&w, (guint8 *) "Speex ", 8);
833 gst_byte_writer_put_data (&w, (guint8 *) "1.1.12", 7);
834 gst_byte_writer_fill (&w, 0, 13);
835 gst_byte_writer_put_uint32_le (&w, 1); /* version */
836 gst_byte_writer_put_uint32_le (&w, 80); /* header_size */
837 gst_byte_writer_put_uint32_le (&w, 16000); /* rate */
838 gst_byte_writer_put_uint32_le (&w, 1); /* mode: Wideband */
839 gst_byte_writer_put_uint32_le (&w, 4); /* mode_bitstream_version */
840 gst_byte_writer_put_uint32_le (&w, 1); /* nb_channels: 1 */
841 gst_byte_writer_put_uint32_le (&w, -1); /* bitrate */
842 gst_byte_writer_put_uint32_le (&w, 0x50); /* frame_size */
843 gst_byte_writer_put_uint32_le (&w, 0); /* VBR */
844 gst_byte_writer_put_uint32_le (&w, 1); /* frames_per_packet */
845 gst_byte_writer_put_uint32_le (&w, 0); /* extra_headers */
846 gst_byte_writer_put_uint32_le (&w, 0); /* reserved1 */
847 gst_byte_writer_put_uint32_le (&w, 0); /* reserved2 */
848 g_assert (gst_byte_writer_get_size (&w) == 80);
850 g_value_init (&value, GST_TYPE_BUFFER);
851 g_value_take_boxed (&value, gst_byte_writer_reset_and_get_buffer (&w));
852 gst_value_array_append_value (&streamheader, &value);
853 g_value_unset (&value);
856 g_value_init (&value, GST_TYPE_BUFFER);
857 tags = gst_tag_list_new_empty ();
858 buf = gst_tag_list_to_vorbiscomment_buffer (tags, NULL, 0, "No comments");
859 gst_tag_list_unref (tags);
860 g_value_take_boxed (&value, buf);
861 gst_value_array_append_value (&streamheader, &value);
862 g_value_unset (&value);
864 gst_structure_take_value (structure, "streamheader", &streamheader);
867 adjusted_rate = 16000;
871 GST_WARNING_OBJECT (demux, "unsupported audio codec tag %u", codec_tag);
875 if (G_UNLIKELY (!caps)) {
876 GST_WARNING_OBJECT (demux, "failed creating caps for audio pad");
880 gst_caps_set_simple (caps, "rate", G_TYPE_INT, adjusted_rate,
881 "channels", G_TYPE_INT, adjusted_channels, NULL);
883 if (demux->audio_codec_data) {
884 gst_caps_set_simple (caps, "codec_data", GST_TYPE_BUFFER,
885 demux->audio_codec_data, NULL);
888 old_caps = gst_pad_get_current_caps (demux->audio_pad);
891 gst_pad_create_stream_id (demux->audio_pad, GST_ELEMENT_CAST (demux),
894 event = gst_event_new_stream_start (stream_id);
895 if (have_group_id (demux))
896 gst_event_set_group_id (event, demux->group_id);
897 gst_pad_push_event (demux->audio_pad, event);
900 if (!old_caps || !gst_caps_is_equal (old_caps, caps))
901 ret = gst_pad_set_caps (demux->audio_pad, caps);
906 gst_caps_unref (old_caps);
909 if (G_LIKELY (ret)) {
910 /* Store the caps we got from tags */
911 demux->audio_codec_tag = codec_tag;
913 demux->channels = channels;
914 demux->width = width;
917 GST_DEBUG_OBJECT (demux->audio_pad, "successfully negotiated caps %"
918 GST_PTR_FORMAT, caps);
920 gst_flv_demux_push_tags (demux);
922 GST_DEBUG_OBJECT (demux->audio_pad, "delayed setting caps");
925 GST_WARNING_OBJECT (demux->audio_pad, "failed negotiating caps %"
926 GST_PTR_FORMAT, caps);
930 gst_caps_unref (caps);
937 gst_flv_demux_push_src_event (GstFlvDemux * demux, GstEvent * event)
941 if (demux->audio_pad)
942 ret |= gst_pad_push_event (demux->audio_pad, gst_event_ref (event));
944 if (demux->video_pad)
945 ret |= gst_pad_push_event (demux->video_pad, gst_event_ref (event));
947 gst_event_unref (event);
953 gst_flv_demux_add_codec_tag (GstFlvDemux * demux, const gchar * tag,
957 GstCaps *caps = gst_pad_get_current_caps (pad);
960 gchar *codec_name = gst_pb_utils_get_codec_description (caps);
963 gst_tag_list_add (demux->taglist, GST_TAG_MERGE_REPLACE,
964 tag, codec_name, NULL);
968 gst_caps_unref (caps);
974 gst_flv_demux_push_tags (GstFlvDemux * demux)
976 gst_flv_demux_add_codec_tag (demux, GST_TAG_AUDIO_CODEC, demux->audio_pad);
977 gst_flv_demux_add_codec_tag (demux, GST_TAG_VIDEO_CODEC, demux->video_pad);
979 GST_DEBUG_OBJECT (demux, "pushing %" GST_PTR_FORMAT, demux->taglist);
981 gst_flv_demux_push_src_event (demux,
982 gst_event_new_tag (gst_tag_list_copy (demux->taglist)));
984 if (demux->audio_pad) {
985 GST_DEBUG_OBJECT (demux->audio_pad, "pushing audio %" GST_PTR_FORMAT,
987 gst_pad_push_event (demux->audio_pad,
988 gst_event_new_tag (gst_tag_list_copy (demux->audio_tags)));
991 if (demux->video_pad) {
992 GST_DEBUG_OBJECT (demux->video_pad, "pushing video %" GST_PTR_FORMAT,
994 gst_pad_push_event (demux->video_pad,
995 gst_event_new_tag (gst_tag_list_copy (demux->video_tags)));
1000 gst_flv_demux_update_resync (GstFlvDemux * demux, guint32 dts, gboolean discont,
1001 guint32 * last, GstClockTime * offset)
1003 gboolean ret = FALSE;
1004 gint32 ddts = dts - *last;
1005 if (!discont && ddts <= -RESYNC_THRESHOLD) {
1006 /* Theoretically, we should use substract the duration of the last buffer,
1007 but this demuxer sends no durations on buffers, not sure if it cannot
1008 know, or just does not care to calculate. */
1009 *offset -= ddts * GST_MSECOND;
1010 GST_WARNING_OBJECT (demux,
1011 "Large dts gap (%" G_GINT32_FORMAT " ms), assuming resync, offset now %"
1012 GST_TIME_FORMAT "", ddts, GST_TIME_ARGS (*offset));
1021 static GstFlowReturn
1022 gst_flv_demux_parse_tag_audio (GstFlvDemux * demux, GstBuffer * buffer)
1024 GstFlowReturn ret = GST_FLOW_OK;
1025 guint32 pts = 0, codec_tag = 0, rate = 5512, width = 8, channels = 1;
1026 guint32 codec_data = 0, pts_ext = 0;
1032 GST_LOG_OBJECT (demux, "parsing an audio tag");
1034 if (G_UNLIKELY (!demux->audio_pad && demux->no_more_pads)) {
1035 #ifndef GST_DISABLE_DEBUG
1036 if (G_UNLIKELY (!demux->no_audio_warned)) {
1037 GST_WARNING_OBJECT (demux,
1038 "Signaled no-more-pads already but had no audio pad -- ignoring");
1039 demux->no_audio_warned = TRUE;
1045 g_return_val_if_fail (gst_buffer_get_size (buffer) == demux->tag_size,
1048 /* Error out on tags with too small headers */
1049 if (gst_buffer_get_size (buffer) < 11) {
1050 GST_ERROR_OBJECT (demux, "Too small tag size (%" G_GSIZE_FORMAT ")",
1051 gst_buffer_get_size (buffer));
1052 return GST_FLOW_ERROR;
1055 gst_buffer_map (buffer, &map, GST_MAP_READ);
1058 /* Grab information about audio tag */
1059 pts = GST_READ_UINT24_BE (data);
1060 /* read the pts extension to 32 bits integer */
1061 pts_ext = GST_READ_UINT8 (data + 3);
1063 pts |= pts_ext << 24;
1065 GST_LOG_OBJECT (demux, "pts bytes %02X %02X %02X %02X (%d)", data[0], data[1],
1066 data[2], data[3], pts);
1068 /* Skip the stream id and go directly to the flags */
1069 flags = GST_READ_UINT8 (data + 7);
1071 /* Silently skip buffers with no data */
1084 if ((flags & 0x0C) == 0x0C) {
1086 } else if ((flags & 0x0C) == 0x08) {
1088 } else if ((flags & 0x0C) == 0x04) {
1092 codec_tag = flags >> 4;
1093 if (codec_tag == 10) { /* AAC has an extra byte for packet type */
1099 /* codec tags with special rates */
1100 if (codec_tag == 5 || codec_tag == 14 || codec_tag == 7 || codec_tag == 8)
1102 else if ((codec_tag == 4) || (codec_tag == 11))
1105 GST_LOG_OBJECT (demux, "audio tag with %d channels, %dHz sampling rate, "
1106 "%d bits width, codec tag %u (flags %02X)", channels, rate, width,
1109 if (codec_tag == 10) {
1110 guint8 aac_packet_type = GST_READ_UINT8 (data + 8);
1112 switch (aac_packet_type) {
1115 /* AudioSpecificConfig data */
1116 GST_LOG_OBJECT (demux, "got an AAC codec data packet");
1117 if (demux->audio_codec_data) {
1118 gst_buffer_unref (demux->audio_codec_data);
1120 demux->audio_codec_data =
1121 gst_buffer_copy_region (buffer, GST_BUFFER_COPY_MEMORY,
1122 7 + codec_data, demux->tag_data_size - codec_data);
1124 /* Use that buffer data in the caps */
1125 if (demux->audio_pad)
1126 gst_flv_demux_audio_negotiate (demux, codec_tag, rate, channels,
1131 if (!demux->audio_codec_data) {
1132 GST_ERROR_OBJECT (demux, "got AAC audio packet before codec data");
1136 /* AAC raw packet */
1137 GST_LOG_OBJECT (demux, "got a raw AAC audio packet");
1140 GST_WARNING_OBJECT (demux, "invalid AAC packet type %u",
1145 /* If we don't have our audio pad created, then create it. */
1146 if (G_UNLIKELY (!demux->audio_pad)) {
1148 gst_pad_new_from_template (gst_element_class_get_pad_template
1149 (GST_ELEMENT_GET_CLASS (demux), "audio"), "audio");
1150 if (G_UNLIKELY (!demux->audio_pad)) {
1151 GST_WARNING_OBJECT (demux, "failed creating audio pad");
1152 ret = GST_FLOW_ERROR;
1156 /* Set functions on the pad */
1157 gst_pad_set_query_function (demux->audio_pad,
1158 GST_DEBUG_FUNCPTR (gst_flv_demux_query));
1159 gst_pad_set_event_function (demux->audio_pad,
1160 GST_DEBUG_FUNCPTR (gst_flv_demux_src_event));
1162 gst_pad_use_fixed_caps (demux->audio_pad);
1164 /* Make it active */
1165 gst_pad_set_active (demux->audio_pad, TRUE);
1167 /* Negotiate caps */
1168 if (!gst_flv_demux_audio_negotiate (demux, codec_tag, rate, channels,
1170 gst_object_unref (demux->audio_pad);
1171 demux->audio_pad = NULL;
1172 ret = GST_FLOW_ERROR;
1175 #ifndef GST_DISABLE_GST_DEBUG
1179 caps = gst_pad_get_current_caps (demux->audio_pad);
1180 GST_DEBUG_OBJECT (demux, "created audio pad with caps %" GST_PTR_FORMAT,
1183 gst_caps_unref (caps);
1187 /* We need to set caps before adding */
1188 gst_element_add_pad (GST_ELEMENT (demux),
1189 gst_object_ref (demux->audio_pad));
1190 gst_flow_combiner_add_pad (demux->flowcombiner, demux->audio_pad);
1192 /* We only emit no more pads when we have audio and video. Indeed we can
1193 * not trust the FLV header to tell us if there will be only audio or
1194 * only video and we would just break discovery of some files */
1195 if (demux->audio_pad && demux->video_pad) {
1196 GST_DEBUG_OBJECT (demux, "emitting no more pads");
1197 gst_element_no_more_pads (GST_ELEMENT (demux));
1198 demux->no_more_pads = TRUE;
1202 /* Check if caps have changed */
1203 if (G_UNLIKELY (rate != demux->rate || channels != demux->channels ||
1204 codec_tag != demux->audio_codec_tag || width != demux->width)) {
1205 GST_DEBUG_OBJECT (demux, "audio settings have changed, changing caps");
1207 gst_buffer_replace (&demux->audio_codec_data, NULL);
1209 /* Negotiate caps */
1210 if (!gst_flv_demux_audio_negotiate (demux, codec_tag, rate, channels,
1212 ret = GST_FLOW_ERROR;
1217 /* Check if we have anything to push */
1218 if (demux->tag_data_size <= codec_data) {
1219 GST_LOG_OBJECT (demux, "Nothing left in this tag, returning");
1223 /* Create buffer from pad */
1224 outbuf = gst_buffer_copy_region (buffer, GST_BUFFER_COPY_MEMORY,
1225 7 + codec_data, demux->tag_data_size - codec_data);
1227 /* detect (and deem to be resyncs) large pts gaps */
1228 if (gst_flv_demux_update_resync (demux, pts, demux->audio_need_discont,
1229 &demux->last_audio_pts, &demux->audio_time_offset)) {
1230 GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_RESYNC);
1233 /* Fill buffer with data */
1234 GST_BUFFER_PTS (outbuf) = pts * GST_MSECOND + demux->audio_time_offset;
1235 GST_BUFFER_DTS (outbuf) = GST_BUFFER_PTS (outbuf);
1236 GST_BUFFER_DURATION (outbuf) = GST_CLOCK_TIME_NONE;
1237 GST_BUFFER_OFFSET (outbuf) = demux->audio_offset++;
1238 GST_BUFFER_OFFSET_END (outbuf) = demux->audio_offset;
1240 if (demux->duration == GST_CLOCK_TIME_NONE ||
1241 demux->duration < GST_BUFFER_TIMESTAMP (outbuf))
1242 demux->duration = GST_BUFFER_TIMESTAMP (outbuf);
1244 /* Only add audio frames to the index if we have no video,
1245 * and if the index is not yet complete */
1246 if (!demux->has_video && !demux->indexed) {
1247 gst_flv_demux_parse_and_add_index_entry (demux,
1248 GST_BUFFER_TIMESTAMP (outbuf), demux->cur_tag_offset, TRUE);
1251 if (G_UNLIKELY (demux->audio_need_discont)) {
1252 GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_DISCONT);
1253 demux->audio_need_discont = FALSE;
1256 demux->segment.position = GST_BUFFER_TIMESTAMP (outbuf);
1258 /* Do we need a newsegment event ? */
1259 if (G_UNLIKELY (demux->audio_need_segment)) {
1260 if (!demux->new_seg_event) {
1261 GST_DEBUG_OBJECT (demux, "pushing newsegment from %"
1262 GST_TIME_FORMAT " to %" GST_TIME_FORMAT,
1263 GST_TIME_ARGS (demux->segment.position),
1264 GST_TIME_ARGS (demux->segment.stop));
1265 demux->segment.start = demux->segment.time = demux->segment.position;
1266 demux->new_seg_event = gst_event_new_segment (&demux->segment);
1268 GST_DEBUG_OBJECT (demux, "pushing pre-generated newsegment event");
1271 gst_pad_push_event (demux->audio_pad, gst_event_ref (demux->new_seg_event));
1273 demux->audio_need_segment = FALSE;
1276 GST_LOG_OBJECT (demux,
1277 "pushing %" G_GSIZE_FORMAT " bytes buffer at pts %" GST_TIME_FORMAT
1278 " with duration %" GST_TIME_FORMAT ", offset %" G_GUINT64_FORMAT,
1279 gst_buffer_get_size (outbuf),
1280 GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (outbuf)),
1281 GST_TIME_ARGS (GST_BUFFER_DURATION (outbuf)), GST_BUFFER_OFFSET (outbuf));
1283 if (!GST_CLOCK_TIME_IS_VALID (demux->audio_start)) {
1284 demux->audio_start = GST_BUFFER_TIMESTAMP (outbuf);
1286 if (!GST_CLOCK_TIME_IS_VALID (demux->audio_first_ts)) {
1287 demux->audio_first_ts = GST_BUFFER_TIMESTAMP (outbuf);
1290 if (G_UNLIKELY (!demux->no_more_pads
1291 && (GST_CLOCK_DIFF (demux->audio_start,
1292 GST_BUFFER_TIMESTAMP (outbuf)) > NO_MORE_PADS_THRESHOLD))) {
1293 GST_DEBUG_OBJECT (demux,
1294 "Signalling no-more-pads because no video stream was found"
1295 " after 6 seconds of audio");
1296 gst_element_no_more_pads (GST_ELEMENT_CAST (demux));
1297 demux->no_more_pads = TRUE;
1300 /* Push downstream */
1301 ret = gst_pad_push (demux->audio_pad, outbuf);
1303 if (G_UNLIKELY (ret != GST_FLOW_OK) &&
1304 demux->segment.rate < 0.0 && ret == GST_FLOW_EOS &&
1305 demux->segment.position > demux->segment.stop) {
1306 /* In reverse playback we can get a GST_FLOW_EOS when
1307 * we are at the end of the segment, so we just need to jump
1308 * back to the previous section. */
1309 GST_DEBUG_OBJECT (demux, "downstream has reached end of segment");
1310 demux->audio_done = TRUE;
1315 ret = gst_flow_combiner_update_pad_flow (demux->flowcombiner,
1316 demux->audio_pad, ret);
1319 gst_buffer_unmap (buffer, &map);
1325 gst_flv_demux_video_negotiate (GstFlvDemux * demux, guint32 codec_tag)
1327 gboolean ret = FALSE;
1328 GstCaps *caps = NULL, *old_caps;
1332 /* Generate caps for that pad */
1333 switch (codec_tag) {
1336 gst_caps_new_simple ("video/x-flash-video", "flvversion", G_TYPE_INT,
1340 caps = gst_caps_new_empty_simple ("video/x-flash-screen");
1343 caps = gst_caps_new_empty_simple ("video/x-vp6-flash");
1346 caps = gst_caps_new_empty_simple ("video/x-vp6-alpha");
1349 if (!demux->video_codec_data) {
1350 GST_DEBUG_OBJECT (demux, "don't have h264 codec data yet");
1355 gst_caps_new_simple ("video/x-h264", "stream-format", G_TYPE_STRING,
1358 /* The following two are non-standard but apparently used, see in ffmpeg
1359 * https://git.videolan.org/?p=ffmpeg.git;a=blob;f=libavformat/flvdec.c;h=2bf1e059e1cbeeb79e4af9542da23f4560e1cf59;hb=b18d6c58000beed872d6bb1fe7d0fbe75ae26aef#l254
1360 * https://git.videolan.org/?p=ffmpeg.git;a=blob;f=libavformat/flvdec.c;h=2bf1e059e1cbeeb79e4af9542da23f4560e1cf59;hb=b18d6c58000beed872d6bb1fe7d0fbe75ae26aef#l282
1363 caps = gst_caps_new_empty_simple ("video/x-h263");
1367 gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 4,
1368 "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
1371 GST_WARNING_OBJECT (demux, "unsupported video codec tag %u", codec_tag);
1374 if (G_UNLIKELY (!caps)) {
1375 GST_WARNING_OBJECT (demux, "failed creating caps for video pad");
1379 if (demux->got_par) {
1380 gst_caps_set_simple (caps, "pixel-aspect-ratio", GST_TYPE_FRACTION,
1381 demux->par_x, demux->par_y, NULL);
1384 if (G_LIKELY (demux->w)) {
1385 gst_caps_set_simple (caps, "width", G_TYPE_INT, demux->w, NULL);
1388 if (G_LIKELY (demux->h)) {
1389 gst_caps_set_simple (caps, "height", G_TYPE_INT, demux->h, NULL);
1392 if (G_LIKELY (demux->framerate)) {
1393 gint num = 0, den = 0;
1395 gst_video_guess_framerate (GST_SECOND / demux->framerate, &num, &den);
1396 GST_DEBUG_OBJECT (demux->video_pad,
1397 "fps to be used on caps %f (as a fraction = %d/%d)", demux->framerate,
1400 gst_caps_set_simple (caps, "framerate", GST_TYPE_FRACTION, num, den, NULL);
1403 if (demux->video_codec_data) {
1404 gst_caps_set_simple (caps, "codec_data", GST_TYPE_BUFFER,
1405 demux->video_codec_data, NULL);
1408 old_caps = gst_pad_get_current_caps (demux->video_pad);
1411 gst_pad_create_stream_id (demux->video_pad, GST_ELEMENT_CAST (demux),
1413 event = gst_event_new_stream_start (stream_id);
1416 if (have_group_id (demux))
1417 gst_event_set_group_id (event, demux->group_id);
1418 gst_pad_push_event (demux->video_pad, event);
1421 if (!old_caps || !gst_caps_is_equal (old_caps, caps))
1422 ret = gst_pad_set_caps (demux->video_pad, caps);
1427 gst_caps_unref (old_caps);
1430 if (G_LIKELY (ret)) {
1431 /* Store the caps we have set */
1432 demux->video_codec_tag = codec_tag;
1435 GST_DEBUG_OBJECT (demux->video_pad, "successfully negotiated caps %"
1436 GST_PTR_FORMAT, caps);
1438 gst_flv_demux_push_tags (demux);
1440 GST_DEBUG_OBJECT (demux->video_pad, "delayed setting caps");
1443 GST_WARNING_OBJECT (demux->video_pad, "failed negotiating caps %"
1444 GST_PTR_FORMAT, caps);
1448 gst_caps_unref (caps);
1454 static GstFlowReturn
1455 gst_flv_demux_parse_tag_video (GstFlvDemux * demux, GstBuffer * buffer)
1457 GstFlowReturn ret = GST_FLOW_OK;
1458 guint32 dts = 0, codec_data = 1, dts_ext = 0;
1460 gboolean keyframe = FALSE;
1461 guint8 flags = 0, codec_tag = 0;
1466 g_return_val_if_fail (gst_buffer_get_size (buffer) == demux->tag_size,
1469 GST_LOG_OBJECT (demux, "parsing a video tag");
1472 (!demux->video_pad && demux->no_more_pads) {
1473 #ifndef GST_DISABLE_DEBUG
1475 (!demux->no_video_warned) {
1476 GST_WARNING_OBJECT (demux,
1477 "Signaled no-more-pads already but had no video pad -- ignoring");
1478 demux->no_video_warned = TRUE;
1484 if (gst_buffer_get_size (buffer) < 12) {
1485 GST_ERROR_OBJECT (demux, "Too small tag size");
1486 return GST_FLOW_ERROR;
1489 gst_buffer_map (buffer, &map, GST_MAP_READ);
1492 /* Grab information about video tag */
1493 dts = GST_READ_UINT24_BE (data);
1494 /* read the dts extension to 32 bits integer */
1495 dts_ext = GST_READ_UINT8 (data + 3);
1497 dts |= dts_ext << 24;
1499 GST_LOG_OBJECT (demux, "dts bytes %02X %02X %02X %02X (%d)", data[0], data[1],
1500 data[2], data[3], dts);
1502 /* Skip the stream id and go directly to the flags */
1503 flags = GST_READ_UINT8 (data + 7);
1506 if ((flags >> 4) == 1) {
1510 codec_tag = flags & 0x0F;
1511 if (codec_tag == 4 || codec_tag == 5) {
1513 } else if (codec_tag == 7) {
1516 cts = GST_READ_UINT24_BE (data + 9);
1517 cts = (cts + 0xff800000) ^ 0xff800000;
1519 if (cts < 0 && ABS (cts) > dts) {
1520 GST_ERROR_OBJECT (demux, "Detected a negative composition time offset "
1521 "'%d' that would lead to negative PTS, fixing", cts);
1522 cts += ABS (cts) - dts;
1525 GST_LOG_OBJECT (demux, "got cts %d", cts);
1528 GST_LOG_OBJECT (demux, "video tag with codec tag %u, keyframe (%d) "
1529 "(flags %02X)", codec_tag, keyframe, flags);
1531 if (codec_tag == 7) {
1532 guint8 avc_packet_type = GST_READ_UINT8 (data + 8);
1534 switch (avc_packet_type) {
1537 if (demux->tag_data_size < codec_data) {
1538 GST_ERROR_OBJECT (demux, "Got invalid H.264 codec, ignoring.");
1542 /* AVCDecoderConfigurationRecord data */
1543 GST_LOG_OBJECT (demux, "got an H.264 codec data packet");
1544 if (demux->video_codec_data) {
1545 gst_buffer_unref (demux->video_codec_data);
1547 demux->video_codec_data = gst_buffer_copy_region (buffer,
1548 GST_BUFFER_COPY_MEMORY, 7 + codec_data,
1549 demux->tag_data_size - codec_data);;
1550 /* Use that buffer data in the caps */
1551 if (demux->video_pad)
1552 gst_flv_demux_video_negotiate (demux, codec_tag);
1556 /* H.264 NALU packet */
1557 if (!demux->video_codec_data) {
1558 GST_ERROR_OBJECT (demux, "got H.264 video packet before codec data");
1562 GST_LOG_OBJECT (demux, "got a H.264 NALU video packet");
1565 GST_WARNING_OBJECT (demux, "invalid video packet type %u",
1570 /* If we don't have our video pad created, then create it. */
1571 if (G_UNLIKELY (!demux->video_pad)) {
1573 gst_pad_new_from_template (gst_element_class_get_pad_template
1574 (GST_ELEMENT_GET_CLASS (demux), "video"), "video");
1575 if (G_UNLIKELY (!demux->video_pad)) {
1576 GST_WARNING_OBJECT (demux, "failed creating video pad");
1577 ret = GST_FLOW_ERROR;
1581 /* Set functions on the pad */
1582 gst_pad_set_query_function (demux->video_pad,
1583 GST_DEBUG_FUNCPTR (gst_flv_demux_query));
1584 gst_pad_set_event_function (demux->video_pad,
1585 GST_DEBUG_FUNCPTR (gst_flv_demux_src_event));
1587 gst_pad_use_fixed_caps (demux->video_pad);
1589 /* Make it active */
1590 gst_pad_set_active (demux->video_pad, TRUE);
1592 /* Needs to be active before setting caps */
1593 if (!gst_flv_demux_video_negotiate (demux, codec_tag)) {
1594 gst_object_unref (demux->video_pad);
1595 demux->video_pad = NULL;
1596 ret = GST_FLOW_ERROR;
1600 /* When we ve set pixel-aspect-ratio we use that boolean to detect a
1601 * metadata tag that would come later and trigger a caps change */
1602 demux->got_par = FALSE;
1604 #ifndef GST_DISABLE_GST_DEBUG
1608 caps = gst_pad_get_current_caps (demux->video_pad);
1609 GST_DEBUG_OBJECT (demux, "created video pad with caps %" GST_PTR_FORMAT,
1612 gst_caps_unref (caps);
1616 /* We need to set caps before adding */
1617 gst_element_add_pad (GST_ELEMENT (demux),
1618 gst_object_ref (demux->video_pad));
1619 gst_flow_combiner_add_pad (demux->flowcombiner, demux->video_pad);
1621 /* We only emit no more pads when we have audio and video. Indeed we can
1622 * not trust the FLV header to tell us if there will be only audio or
1623 * only video and we would just break discovery of some files */
1624 if (demux->audio_pad && demux->video_pad) {
1625 GST_DEBUG_OBJECT (demux, "emitting no more pads");
1626 gst_element_no_more_pads (GST_ELEMENT (demux));
1627 demux->no_more_pads = TRUE;
1631 /* Check if caps have changed */
1632 if (G_UNLIKELY (codec_tag != demux->video_codec_tag || demux->got_par)) {
1633 GST_DEBUG_OBJECT (demux, "video settings have changed, changing caps");
1634 gst_buffer_replace (&demux->video_codec_data, NULL);
1636 if (!gst_flv_demux_video_negotiate (demux, codec_tag)) {
1637 ret = GST_FLOW_ERROR;
1641 /* When we ve set pixel-aspect-ratio we use that boolean to detect a
1642 * metadata tag that would come later and trigger a caps change */
1643 demux->got_par = FALSE;
1646 /* Check if we have anything to push */
1647 if (demux->tag_data_size <= codec_data) {
1648 GST_LOG_OBJECT (demux, "Nothing left in this tag, returning");
1652 /* Create buffer from pad */
1653 outbuf = gst_buffer_copy_region (buffer, GST_BUFFER_COPY_MEMORY,
1654 7 + codec_data, demux->tag_data_size - codec_data);
1656 /* detect (and deem to be resyncs) large dts gaps */
1657 if (gst_flv_demux_update_resync (demux, dts, demux->video_need_discont,
1658 &demux->last_video_dts, &demux->video_time_offset)) {
1659 GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_RESYNC);
1662 /* Fill buffer with data */
1663 GST_LOG_OBJECT (demux, "dts %u pts %u cts %d", dts, dts + cts, cts);
1665 GST_BUFFER_PTS (outbuf) =
1666 (dts + cts) * GST_MSECOND + demux->video_time_offset;
1667 GST_BUFFER_DTS (outbuf) = dts * GST_MSECOND + demux->video_time_offset;
1668 GST_BUFFER_DURATION (outbuf) = GST_CLOCK_TIME_NONE;
1669 GST_BUFFER_OFFSET (outbuf) = demux->video_offset++;
1670 GST_BUFFER_OFFSET_END (outbuf) = demux->video_offset;
1672 if (demux->duration == GST_CLOCK_TIME_NONE ||
1673 demux->duration < GST_BUFFER_TIMESTAMP (outbuf))
1674 demux->duration = GST_BUFFER_TIMESTAMP (outbuf);
1677 GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_DELTA_UNIT);
1679 if (!demux->indexed) {
1680 gst_flv_demux_parse_and_add_index_entry (demux,
1681 GST_BUFFER_TIMESTAMP (outbuf), demux->cur_tag_offset, keyframe);
1684 if (G_UNLIKELY (demux->video_need_discont)) {
1685 GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_DISCONT);
1686 demux->video_need_discont = FALSE;
1689 demux->segment.position = GST_BUFFER_TIMESTAMP (outbuf);
1691 /* Do we need a newsegment event ? */
1692 if (G_UNLIKELY (demux->video_need_segment)) {
1693 if (!demux->new_seg_event) {
1694 GST_DEBUG_OBJECT (demux, "pushing newsegment from %"
1695 GST_TIME_FORMAT " to %" GST_TIME_FORMAT,
1696 GST_TIME_ARGS (demux->segment.position),
1697 GST_TIME_ARGS (demux->segment.stop));
1698 demux->segment.start = demux->segment.time = demux->segment.position;
1699 demux->new_seg_event = gst_event_new_segment (&demux->segment);
1701 GST_DEBUG_OBJECT (demux, "pushing pre-generated newsegment event");
1704 gst_pad_push_event (demux->video_pad, gst_event_ref (demux->new_seg_event));
1706 demux->video_need_segment = FALSE;
1709 GST_LOG_OBJECT (demux,
1710 "pushing %" G_GSIZE_FORMAT " bytes buffer at dts %" GST_TIME_FORMAT
1711 " with duration %" GST_TIME_FORMAT ", offset %" G_GUINT64_FORMAT
1712 ", keyframe (%d)", gst_buffer_get_size (outbuf),
1713 GST_TIME_ARGS (GST_BUFFER_DTS (outbuf)),
1714 GST_TIME_ARGS (GST_BUFFER_DURATION (outbuf)), GST_BUFFER_OFFSET (outbuf),
1717 if (!GST_CLOCK_TIME_IS_VALID (demux->video_start)) {
1718 demux->video_start = GST_BUFFER_TIMESTAMP (outbuf);
1720 if (!GST_CLOCK_TIME_IS_VALID (demux->audio_first_ts)) {
1721 demux->video_first_ts = GST_BUFFER_TIMESTAMP (outbuf);
1724 if (G_UNLIKELY (!demux->no_more_pads
1725 && (GST_CLOCK_DIFF (demux->video_start,
1726 GST_BUFFER_TIMESTAMP (outbuf)) > NO_MORE_PADS_THRESHOLD))) {
1727 GST_DEBUG_OBJECT (demux,
1728 "Signalling no-more-pads because no audio stream was found"
1729 " after 6 seconds of video");
1730 gst_element_no_more_pads (GST_ELEMENT_CAST (demux));
1731 demux->no_more_pads = TRUE;
1734 /* Push downstream */
1735 ret = gst_pad_push (demux->video_pad, outbuf);
1737 if (G_UNLIKELY (ret != GST_FLOW_OK) &&
1738 demux->segment.rate < 0.0 && ret == GST_FLOW_EOS &&
1739 demux->segment.position > demux->segment.stop) {
1740 /* In reverse playback we can get a GST_FLOW_EOS when
1741 * we are at the end of the segment, so we just need to jump
1742 * back to the previous section. */
1743 GST_DEBUG_OBJECT (demux, "downstream has reached end of segment");
1744 demux->video_done = TRUE;
1749 ret = gst_flow_combiner_update_pad_flow (demux->flowcombiner,
1750 demux->video_pad, ret);
1753 gst_buffer_unmap (buffer, &map);
1758 gst_flv_demux_parse_tag_timestamp (GstFlvDemux * demux, gboolean index,
1759 GstBuffer * buffer, size_t * tag_size)
1761 guint32 dts = 0, dts_ext = 0;
1762 guint32 tag_data_size;
1764 gboolean keyframe = TRUE;
1765 GstClockTime ret = GST_CLOCK_TIME_NONE;
1770 g_return_val_if_fail (gst_buffer_get_size (buffer) >= 12,
1771 GST_CLOCK_TIME_NONE);
1773 gst_buffer_map (buffer, &map, GST_MAP_READ);
1779 if (type != 9 && type != 8 && type != 18) {
1780 GST_WARNING_OBJECT (demux, "Unsupported tag type %u", data[0]);
1785 demux->has_video = TRUE;
1787 demux->has_audio = TRUE;
1789 tag_data_size = GST_READ_UINT24_BE (data + 1);
1791 if (size >= tag_data_size + 11 + 4) {
1792 if (GST_READ_UINT32_BE (data + tag_data_size + 11) != tag_data_size + 11) {
1793 GST_WARNING_OBJECT (demux, "Invalid tag size");
1799 *tag_size = tag_data_size + 11 + 4;
1803 GST_LOG_OBJECT (demux, "dts bytes %02X %02X %02X %02X", data[0], data[1],
1806 /* Grab timestamp of tag tag */
1807 dts = GST_READ_UINT24_BE (data);
1808 /* read the dts extension to 32 bits integer */
1809 dts_ext = GST_READ_UINT8 (data + 3);
1811 dts |= dts_ext << 24;
1816 keyframe = ((data[0] >> 4) == 1);
1819 ret = dts * GST_MSECOND;
1820 GST_LOG_OBJECT (demux, "dts: %" GST_TIME_FORMAT, GST_TIME_ARGS (ret));
1822 if (index && !demux->indexed && (type == 9 || (type == 8
1823 && !demux->has_video))) {
1824 gst_flv_demux_parse_and_add_index_entry (demux, ret, demux->offset,
1828 if (demux->duration == GST_CLOCK_TIME_NONE || demux->duration < ret)
1829 demux->duration = ret;
1832 gst_buffer_unmap (buffer, &map);
1836 static GstFlowReturn
1837 gst_flv_demux_parse_tag_type (GstFlvDemux * demux, GstBuffer * buffer)
1839 GstFlowReturn ret = GST_FLOW_OK;
1840 guint8 tag_type = 0;
1843 g_return_val_if_fail (gst_buffer_get_size (buffer) >= 4, GST_FLOW_ERROR);
1845 gst_buffer_map (buffer, &map, GST_MAP_READ);
1847 tag_type = map.data[0];
1849 /* Tag size is 1 byte of type + 3 bytes of size + 7 bytes + tag data size +
1850 * 4 bytes of previous tag size */
1851 demux->tag_data_size = GST_READ_UINT24_BE (map.data + 1);
1852 demux->tag_size = demux->tag_data_size + 11;
1854 GST_LOG_OBJECT (demux, "tag data size is %" G_GUINT64_FORMAT,
1855 demux->tag_data_size);
1857 gst_buffer_unmap (buffer, &map);
1861 demux->state = FLV_STATE_TAG_VIDEO;
1862 demux->has_video = TRUE;
1865 demux->state = FLV_STATE_TAG_AUDIO;
1866 demux->has_audio = TRUE;
1869 demux->state = FLV_STATE_TAG_SCRIPT;
1872 GST_WARNING_OBJECT (demux, "unsupported tag type %u", tag_type);
1873 demux->state = FLV_STATE_SKIP;
1879 static GstFlowReturn
1880 gst_flv_demux_parse_header (GstFlvDemux * demux, GstBuffer * buffer)
1882 GstFlowReturn ret = GST_FLOW_OK;
1885 g_return_val_if_fail (gst_buffer_get_size (buffer) >= 9, GST_FLOW_ERROR);
1887 gst_buffer_map (buffer, &map, GST_MAP_READ);
1889 /* Check for the FLV tag */
1890 if (map.data[0] == 'F' && map.data[1] == 'L' && map.data[2] == 'V') {
1891 GST_DEBUG_OBJECT (demux, "FLV header detected");
1893 if (G_UNLIKELY (demux->strict)) {
1894 GST_WARNING_OBJECT (demux, "invalid header tag detected");
1900 if (map.data[3] == '1') {
1901 GST_DEBUG_OBJECT (demux, "FLV version 1 detected");
1903 if (G_UNLIKELY (demux->strict)) {
1904 GST_WARNING_OBJECT (demux, "invalid header version detected");
1911 /* Now look at audio/video flags */
1913 guint8 flags = map.data[4];
1915 demux->has_video = demux->has_audio = FALSE;
1918 GST_DEBUG_OBJECT (demux, "there is a video stream");
1919 demux->has_video = TRUE;
1922 GST_DEBUG_OBJECT (demux, "there is an audio stream");
1923 demux->has_audio = TRUE;
1927 /* do a one-time seekability check */
1928 gst_flv_demux_check_seekability (demux);
1930 /* We don't care about the rest */
1931 demux->need_header = FALSE;
1934 gst_buffer_unmap (buffer, &map);
1940 gst_flv_demux_flush (GstFlvDemux * demux, gboolean discont)
1942 GST_DEBUG_OBJECT (demux, "flushing queued data in the FLV demuxer");
1944 gst_adapter_clear (demux->adapter);
1946 demux->audio_need_discont = TRUE;
1947 demux->video_need_discont = TRUE;
1949 demux->flushing = FALSE;
1951 /* Only in push mode and if we're not during a seek */
1952 if (!demux->random_access && demux->state != FLV_STATE_SEEK) {
1953 /* After a flush we expect a tag_type */
1954 demux->state = FLV_STATE_TAG_TYPE;
1955 /* We reset the offset and will get one from first push */
1961 gst_flv_demux_cleanup (GstFlvDemux * demux)
1963 GST_DEBUG_OBJECT (demux, "cleaning up FLV demuxer");
1965 demux->state = FLV_STATE_HEADER;
1967 demux->have_group_id = FALSE;
1968 demux->group_id = G_MAXUINT;
1970 demux->flushing = FALSE;
1971 demux->need_header = TRUE;
1972 demux->audio_need_segment = TRUE;
1973 demux->video_need_segment = TRUE;
1974 demux->audio_need_discont = TRUE;
1975 demux->video_need_discont = TRUE;
1977 demux->has_audio = FALSE;
1978 demux->has_video = FALSE;
1979 demux->got_par = FALSE;
1981 demux->indexed = FALSE;
1982 demux->upstream_seekable = FALSE;
1983 demux->file_size = 0;
1985 demux->index_max_pos = 0;
1986 demux->index_max_time = 0;
1988 demux->audio_start = demux->video_start = GST_CLOCK_TIME_NONE;
1989 demux->last_audio_pts = demux->last_video_dts = 0;
1990 demux->audio_time_offset = demux->video_time_offset = 0;
1992 demux->no_more_pads = FALSE;
1994 #ifndef GST_DISABLE_DEBUG
1995 demux->no_audio_warned = FALSE;
1996 demux->no_video_warned = FALSE;
1999 gst_segment_init (&demux->segment, GST_FORMAT_TIME);
2001 demux->w = demux->h = 0;
2002 demux->framerate = 0.0;
2003 demux->par_x = demux->par_y = 1;
2004 demux->video_offset = 0;
2005 demux->audio_offset = 0;
2006 demux->offset = demux->cur_tag_offset = 0;
2007 demux->tag_size = demux->tag_data_size = 0;
2008 demux->duration = GST_CLOCK_TIME_NONE;
2010 if (demux->new_seg_event) {
2011 gst_event_unref (demux->new_seg_event);
2012 demux->new_seg_event = NULL;
2015 gst_adapter_clear (demux->adapter);
2017 if (demux->audio_codec_data) {
2018 gst_buffer_unref (demux->audio_codec_data);
2019 demux->audio_codec_data = NULL;
2022 if (demux->video_codec_data) {
2023 gst_buffer_unref (demux->video_codec_data);
2024 demux->video_codec_data = NULL;
2027 if (demux->audio_pad) {
2028 gst_flow_combiner_remove_pad (demux->flowcombiner, demux->audio_pad);
2029 gst_element_remove_pad (GST_ELEMENT (demux), demux->audio_pad);
2030 gst_object_unref (demux->audio_pad);
2031 demux->audio_pad = NULL;
2034 if (demux->video_pad) {
2035 gst_flow_combiner_remove_pad (demux->flowcombiner, demux->video_pad);
2036 gst_element_remove_pad (GST_ELEMENT (demux), demux->video_pad);
2037 gst_object_unref (demux->video_pad);
2038 demux->video_pad = NULL;
2042 g_array_free (demux->times, TRUE);
2043 demux->times = NULL;
2046 if (demux->filepositions) {
2047 g_array_free (demux->filepositions, TRUE);
2048 demux->filepositions = NULL;
2051 gst_flv_demux_clear_tags (demux);
2055 * Create and push a flushing seek event upstream
2058 flv_demux_seek_to_offset (GstFlvDemux * demux, guint64 offset)
2063 GST_DEBUG_OBJECT (demux, "Seeking to %" G_GUINT64_FORMAT, offset);
2066 gst_event_new_seek (1.0, GST_FORMAT_BYTES,
2067 GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE, GST_SEEK_TYPE_SET, offset,
2068 GST_SEEK_TYPE_NONE, -1);
2070 res = gst_pad_push_event (demux->sinkpad, event);
2073 demux->offset = offset;
2077 static GstFlowReturn
2078 gst_flv_demux_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer)
2080 GstFlowReturn ret = GST_FLOW_OK;
2081 GstFlvDemux *demux = NULL;
2083 demux = GST_FLV_DEMUX (parent);
2085 GST_LOG_OBJECT (demux,
2086 "received buffer of %" G_GSIZE_FORMAT " bytes at offset %"
2087 G_GUINT64_FORMAT, gst_buffer_get_size (buffer),
2088 GST_BUFFER_OFFSET (buffer));
2090 if (G_UNLIKELY (GST_BUFFER_OFFSET (buffer) == 0)) {
2091 GST_DEBUG_OBJECT (demux, "beginning of file, expect header");
2092 demux->state = FLV_STATE_HEADER;
2096 if (G_UNLIKELY (demux->offset == 0 && GST_BUFFER_OFFSET (buffer) != 0)) {
2097 GST_DEBUG_OBJECT (demux, "offset was zero, synchronizing with buffer's");
2098 demux->offset = GST_BUFFER_OFFSET (buffer);
2101 if (GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_DISCONT)) {
2102 GST_DEBUG_OBJECT (demux, "Discontinuity");
2103 gst_adapter_clear (demux->adapter);
2106 gst_adapter_push (demux->adapter, buffer);
2108 if (demux->seeking) {
2109 demux->state = FLV_STATE_SEEK;
2110 GST_OBJECT_LOCK (demux);
2111 demux->seeking = FALSE;
2112 GST_OBJECT_UNLOCK (demux);
2116 if (G_UNLIKELY (ret != GST_FLOW_OK)) {
2117 GST_DEBUG_OBJECT (demux, "got flow return %s", gst_flow_get_name (ret));
2121 if (G_UNLIKELY (demux->flushing)) {
2122 GST_DEBUG_OBJECT (demux, "we are now flushing, exiting parser loop");
2123 ret = GST_FLOW_FLUSHING;
2127 switch (demux->state) {
2128 case FLV_STATE_HEADER:
2130 if (gst_adapter_available (demux->adapter) >= FLV_HEADER_SIZE) {
2133 buffer = gst_adapter_take_buffer (demux->adapter, FLV_HEADER_SIZE);
2135 ret = gst_flv_demux_parse_header (demux, buffer);
2137 gst_buffer_unref (buffer);
2138 demux->offset += FLV_HEADER_SIZE;
2140 demux->state = FLV_STATE_TAG_TYPE;
2146 case FLV_STATE_TAG_TYPE:
2148 if (gst_adapter_available (demux->adapter) >= FLV_TAG_TYPE_SIZE) {
2151 /* Remember the tag offset in bytes */
2152 demux->cur_tag_offset = demux->offset;
2154 buffer = gst_adapter_take_buffer (demux->adapter, FLV_TAG_TYPE_SIZE);
2156 ret = gst_flv_demux_parse_tag_type (demux, buffer);
2158 gst_buffer_unref (buffer);
2159 demux->offset += FLV_TAG_TYPE_SIZE;
2161 /* last tag is not an index => no index/don't know where the index is
2162 * seek back to the beginning */
2163 if (demux->seek_event && demux->state != FLV_STATE_TAG_SCRIPT)
2171 case FLV_STATE_TAG_VIDEO:
2173 if (gst_adapter_available (demux->adapter) >= demux->tag_size) {
2176 buffer = gst_adapter_take_buffer (demux->adapter, demux->tag_size);
2178 ret = gst_flv_demux_parse_tag_video (demux, buffer);
2180 gst_buffer_unref (buffer);
2181 demux->offset += demux->tag_size;
2183 demux->state = FLV_STATE_TAG_TYPE;
2189 case FLV_STATE_TAG_AUDIO:
2191 if (gst_adapter_available (demux->adapter) >= demux->tag_size) {
2194 buffer = gst_adapter_take_buffer (demux->adapter, demux->tag_size);
2196 ret = gst_flv_demux_parse_tag_audio (demux, buffer);
2198 gst_buffer_unref (buffer);
2199 demux->offset += demux->tag_size;
2201 demux->state = FLV_STATE_TAG_TYPE;
2207 case FLV_STATE_TAG_SCRIPT:
2209 if (gst_adapter_available (demux->adapter) >= demux->tag_size) {
2212 buffer = gst_adapter_take_buffer (demux->adapter, demux->tag_size);
2214 ret = gst_flv_demux_parse_tag_script (demux, buffer);
2216 gst_buffer_unref (buffer);
2217 demux->offset += demux->tag_size;
2219 demux->state = FLV_STATE_TAG_TYPE;
2221 /* if there's a seek event we're here for the index so if we don't have it
2222 * we seek back to the beginning */
2223 if (demux->seek_event) {
2225 demux->state = FLV_STATE_SEEK;
2235 case FLV_STATE_SEEK:
2241 if (!demux->indexed) {
2242 if (demux->offset == demux->file_size - sizeof (guint32)) {
2243 guint64 seek_offset;
2246 data = gst_adapter_take (demux->adapter, 4);
2250 seek_offset = demux->file_size - sizeof (guint32) -
2251 GST_READ_UINT32_BE (data);
2254 GST_INFO_OBJECT (demux,
2255 "Seeking to beginning of last tag at %" G_GUINT64_FORMAT,
2257 demux->state = FLV_STATE_TAG_TYPE;
2258 flv_demux_seek_to_offset (demux, seek_offset);
2264 GST_OBJECT_LOCK (demux);
2265 event = demux->seek_event;
2266 demux->seek_event = NULL;
2267 GST_OBJECT_UNLOCK (demux);
2269 /* calculate and perform seek */
2270 if (!flv_demux_handle_seek_push (demux, event))
2273 gst_event_unref (event);
2274 demux->state = FLV_STATE_TAG_TYPE;
2277 case FLV_STATE_SKIP:
2278 /* Skip unknown tags (set in _parse_tag_type()) */
2279 if (gst_adapter_available (demux->adapter) >= demux->tag_size) {
2280 gst_adapter_flush (demux->adapter, demux->tag_size);
2281 demux->offset += demux->tag_size;
2282 demux->state = FLV_STATE_TAG_TYPE;
2288 GST_DEBUG_OBJECT (demux, "unexpected demuxer state");
2297 GST_OBJECT_LOCK (demux);
2298 demux->seeking = FALSE;
2299 gst_event_unref (demux->seek_event);
2300 demux->seek_event = NULL;
2301 GST_OBJECT_UNLOCK (demux);
2302 GST_WARNING_OBJECT (demux,
2303 "failed to find an index, seeking back to beginning");
2304 flv_demux_seek_to_offset (demux, 0);
2309 GST_ELEMENT_ERROR (demux, STREAM, DEMUX, (NULL), ("seek failed"));
2310 return GST_FLOW_ERROR;
2315 static GstFlowReturn
2316 gst_flv_demux_pull_range (GstFlvDemux * demux, GstPad * pad, guint64 offset,
2317 guint size, GstBuffer ** buffer)
2321 ret = gst_pad_pull_range (pad, offset, size, buffer);
2322 if (G_UNLIKELY (ret != GST_FLOW_OK)) {
2323 GST_WARNING_OBJECT (demux,
2324 "failed when pulling %d bytes from offset %" G_GUINT64_FORMAT ": %s",
2325 size, offset, gst_flow_get_name (ret));
2330 if (G_UNLIKELY (*buffer && gst_buffer_get_size (*buffer) != size)) {
2331 GST_WARNING_OBJECT (demux,
2332 "partial pull got %" G_GSIZE_FORMAT " when expecting %d from offset %"
2333 G_GUINT64_FORMAT, gst_buffer_get_size (*buffer), size, offset);
2334 gst_buffer_unref (*buffer);
2343 static GstFlowReturn
2344 gst_flv_demux_pull_tag (GstPad * pad, GstFlvDemux * demux)
2346 GstBuffer *buffer = NULL;
2347 GstFlowReturn ret = GST_FLOW_OK;
2349 /* Store tag offset */
2350 demux->cur_tag_offset = demux->offset;
2352 /* Get the first 4 bytes to identify tag type and size */
2353 if (G_UNLIKELY ((ret = gst_flv_demux_pull_range (demux, pad, demux->offset,
2354 FLV_TAG_TYPE_SIZE, &buffer)) != GST_FLOW_OK))
2357 /* Identify tag type */
2358 ret = gst_flv_demux_parse_tag_type (demux, buffer);
2360 gst_buffer_unref (buffer);
2362 if (G_UNLIKELY (ret != GST_FLOW_OK))
2365 /* Jump over tag type + size */
2366 demux->offset += FLV_TAG_TYPE_SIZE;
2368 /* Pull the whole tag */
2370 if (G_UNLIKELY ((ret = gst_flv_demux_pull_range (demux, pad, demux->offset,
2371 demux->tag_size, &buffer)) != GST_FLOW_OK))
2374 switch (demux->state) {
2375 case FLV_STATE_TAG_VIDEO:
2376 ret = gst_flv_demux_parse_tag_video (demux, buffer);
2378 case FLV_STATE_TAG_AUDIO:
2379 ret = gst_flv_demux_parse_tag_audio (demux, buffer);
2381 case FLV_STATE_TAG_SCRIPT:
2382 ret = gst_flv_demux_parse_tag_script (demux, buffer);
2385 GST_WARNING_OBJECT (demux, "unexpected state %d", demux->state);
2388 gst_buffer_unref (buffer);
2390 /* Jump over that part we've just parsed */
2391 demux->offset += demux->tag_size;
2393 /* Make sure we reinitialize the tag size */
2394 demux->tag_size = 0;
2396 /* Ready for the next tag */
2397 demux->state = FLV_STATE_TAG_TYPE;
2399 if (G_UNLIKELY (ret == GST_FLOW_NOT_LINKED)) {
2400 GST_WARNING_OBJECT (demux, "parsing this tag returned not-linked and "
2401 "neither video nor audio are linked");
2408 static GstFlowReturn
2409 gst_flv_demux_pull_header (GstPad * pad, GstFlvDemux * demux)
2411 GstBuffer *buffer = NULL;
2412 GstFlowReturn ret = GST_FLOW_OK;
2414 /* Get the first 9 bytes */
2415 if (G_UNLIKELY ((ret = gst_flv_demux_pull_range (demux, pad, demux->offset,
2416 FLV_HEADER_SIZE, &buffer)) != GST_FLOW_OK))
2419 ret = gst_flv_demux_parse_header (demux, buffer);
2421 gst_buffer_unref (buffer);
2423 /* Jump over the header now */
2424 demux->offset += FLV_HEADER_SIZE;
2425 demux->state = FLV_STATE_TAG_TYPE;
2432 gst_flv_demux_move_to_offset (GstFlvDemux * demux, gint64 offset,
2435 demux->offset = offset;
2437 /* Tell all the stream we moved to a different position (discont) */
2438 demux->audio_need_discont = TRUE;
2439 demux->video_need_discont = TRUE;
2441 /* next section setup */
2442 demux->from_offset = -1;
2443 demux->audio_done = demux->video_done = FALSE;
2444 demux->audio_first_ts = demux->video_first_ts = GST_CLOCK_TIME_NONE;
2447 demux->from_offset = -1;
2448 demux->to_offset = G_MAXINT64;
2451 /* If we seeked at the beginning of the file parse the header again */
2452 if (G_UNLIKELY (!demux->offset)) {
2453 demux->state = FLV_STATE_HEADER;
2454 } else { /* or parse a tag */
2455 demux->state = FLV_STATE_TAG_TYPE;
2459 static GstFlowReturn
2460 gst_flv_demux_seek_to_prev_keyframe (GstFlvDemux * demux)
2462 GstFlowReturn ret = GST_FLOW_EOS;
2464 GstIndexEntry *entry = NULL;
2466 GST_DEBUG_OBJECT (demux,
2467 "terminated section started at offset %" G_GINT64_FORMAT,
2468 demux->from_offset);
2470 /* we are done if we got all audio and video */
2471 if ((!GST_CLOCK_TIME_IS_VALID (demux->audio_first_ts) ||
2472 demux->audio_first_ts < demux->segment.start) &&
2473 (!GST_CLOCK_TIME_IS_VALID (demux->video_first_ts) ||
2474 demux->video_first_ts < demux->segment.start))
2477 if (demux->from_offset <= 0)
2480 GST_DEBUG_OBJECT (demux, "locating previous position");
2482 index = gst_flv_demux_get_index (GST_ELEMENT (demux));
2484 /* locate index entry before previous start position */
2486 entry = gst_index_get_assoc_entry (index, demux->index_id,
2487 GST_INDEX_LOOKUP_BEFORE, GST_ASSOCIATION_FLAG_KEY_UNIT,
2488 GST_FORMAT_BYTES, demux->from_offset - 1);
2491 gint64 bytes = 0, time = 0;
2493 gst_index_entry_assoc_map (entry, GST_FORMAT_BYTES, &bytes);
2494 gst_index_entry_assoc_map (entry, GST_FORMAT_TIME, &time);
2496 GST_DEBUG_OBJECT (demux, "found index entry for %" G_GINT64_FORMAT
2497 " at %" GST_TIME_FORMAT ", seeking to %" G_GINT64_FORMAT,
2498 demux->offset - 1, GST_TIME_ARGS (time), bytes);
2500 /* setup for next section */
2501 demux->to_offset = demux->from_offset;
2502 gst_flv_demux_move_to_offset (demux, bytes, FALSE);
2506 gst_object_unref (index);
2513 static GstFlowReturn
2514 gst_flv_demux_create_index (GstFlvDemux * demux, gint64 pos, GstClockTime ts)
2520 GstClockTime tag_time;
2521 GstFlowReturn ret = GST_FLOW_OK;
2523 if (!gst_pad_peer_query_duration (demux->sinkpad, GST_FORMAT_BYTES, &size))
2526 GST_DEBUG_OBJECT (demux, "building index at %" G_GINT64_FORMAT
2527 " looking for time %" GST_TIME_FORMAT, pos, GST_TIME_ARGS (ts));
2529 old_offset = demux->offset;
2530 demux->offset = pos;
2533 while ((ret = gst_flv_demux_pull_range (demux, demux->sinkpad, demux->offset,
2534 12, &buffer)) == GST_FLOW_OK) {
2536 gst_flv_demux_parse_tag_timestamp (demux, TRUE, buffer, &tag_size);
2538 gst_buffer_unref (buffer);
2541 if (G_UNLIKELY (tag_time == GST_CLOCK_TIME_NONE || tag_time > ts))
2544 demux->offset += tag_size;
2547 if (ret == GST_FLOW_EOS) {
2548 /* file ran out, so mark we have complete index */
2549 demux->indexed = TRUE;
2554 demux->offset = old_offset;
2560 gst_flv_demux_get_metadata (GstFlvDemux * demux)
2562 gint64 ret = 0, offset;
2563 size_t tag_size, size;
2564 GstBuffer *buffer = NULL;
2567 if (!gst_pad_peer_query_duration (demux->sinkpad, GST_FORMAT_BYTES, &offset))
2571 GST_DEBUG_OBJECT (demux, "upstream size: %" G_GINT64_FORMAT, offset);
2572 if (G_UNLIKELY (offset < 4))
2576 if (GST_FLOW_OK != gst_flv_demux_pull_range (demux, demux->sinkpad, offset,
2580 gst_buffer_map (buffer, &map, GST_MAP_READ);
2581 tag_size = GST_READ_UINT32_BE (map.data);
2582 gst_buffer_unmap (buffer, &map);
2583 GST_DEBUG_OBJECT (demux, "last tag size: %" G_GSIZE_FORMAT, tag_size);
2584 gst_buffer_unref (buffer);
2587 if (G_UNLIKELY (offset < tag_size))
2591 if (GST_FLOW_OK != gst_flv_demux_pull_range (demux, demux->sinkpad, offset,
2595 /* a consistency check */
2596 gst_buffer_map (buffer, &map, GST_MAP_READ);
2597 size = GST_READ_UINT24_BE (map.data + 1);
2598 if (size != tag_size - 11) {
2599 gst_buffer_unmap (buffer, &map);
2600 GST_DEBUG_OBJECT (demux,
2601 "tag size %" G_GSIZE_FORMAT ", expected %" G_GSIZE_FORMAT
2602 ", corrupt or truncated file", size, tag_size - 11);
2606 /* try to update duration with timestamp in any case */
2607 gst_flv_demux_parse_tag_timestamp (demux, FALSE, buffer, &size);
2609 /* maybe get some more metadata */
2610 if (map.data[0] == 18) {
2611 gst_buffer_unmap (buffer, &map);
2612 gst_buffer_unref (buffer);
2614 GST_DEBUG_OBJECT (demux, "script tag, pulling it to parse");
2616 if (GST_FLOW_OK == gst_flv_demux_pull_range (demux, demux->sinkpad, offset,
2618 gst_flv_demux_parse_tag_script (demux, buffer);
2620 gst_buffer_unmap (buffer, &map);
2625 gst_buffer_unref (buffer);
2631 gst_flv_demux_loop (GstPad * pad)
2633 GstFlvDemux *demux = NULL;
2634 GstFlowReturn ret = GST_FLOW_OK;
2636 demux = GST_FLV_DEMUX (gst_pad_get_parent (pad));
2639 switch (demux->state) {
2640 case FLV_STATE_TAG_TYPE:
2641 if (demux->from_offset == -1)
2642 demux->from_offset = demux->offset;
2643 ret = gst_flv_demux_pull_tag (pad, demux);
2644 /* if we have seen real data, we probably passed a possible metadata
2645 * header located at start. So if we do not yet have an index,
2646 * try to pick up metadata (index, duration) at the end */
2647 if (G_UNLIKELY (!demux->file_size && !demux->indexed &&
2648 (demux->has_video || demux->has_audio)))
2649 demux->file_size = gst_flv_demux_get_metadata (demux);
2651 case FLV_STATE_DONE:
2654 case FLV_STATE_SEEK:
2655 /* seek issued with insufficient index;
2656 * scan for index in task thread from current maximum offset to
2657 * desired time and then perform seek */
2658 /* TODO maybe some buffering message or so to indicate scan progress */
2659 ret = gst_flv_demux_create_index (demux, demux->index_max_pos,
2661 if (ret != GST_FLOW_OK)
2663 /* position and state arranged by seek,
2664 * also unrefs event */
2665 gst_flv_demux_handle_seek_pull (demux, demux->seek_event, FALSE);
2666 demux->seek_event = NULL;
2669 ret = gst_flv_demux_pull_header (pad, demux);
2670 /* index scans start after header */
2671 demux->index_max_pos = demux->offset;
2675 if (demux->segment.rate < 0.0) {
2676 /* check end of section */
2677 if ((gint64) demux->offset >= demux->to_offset ||
2678 demux->segment.position >= demux->segment.stop + 2 * GST_SECOND ||
2679 (demux->audio_done && demux->video_done))
2680 ret = gst_flv_demux_seek_to_prev_keyframe (demux);
2682 /* check EOS condition */
2683 if ((demux->segment.stop != -1) &&
2684 (demux->segment.position >= demux->segment.stop)) {
2689 /* pause if something went wrong or at end */
2690 if (G_UNLIKELY (ret != GST_FLOW_OK) && !(ret == GST_FLOW_NOT_LINKED
2691 && !demux->no_more_pads))
2694 gst_object_unref (demux);
2700 const gchar *reason = gst_flow_get_name (ret);
2702 GST_LOG_OBJECT (demux, "pausing task, reason %s", reason);
2703 gst_pad_pause_task (pad);
2705 if (ret == GST_FLOW_EOS) {
2706 /* handle end-of-stream/segment */
2707 /* so align our position with the end of it, if there is one
2708 * this ensures a subsequent will arrive at correct base/acc time */
2709 if (demux->segment.rate > 0.0 &&
2710 GST_CLOCK_TIME_IS_VALID (demux->segment.stop))
2711 demux->segment.position = demux->segment.stop;
2712 else if (demux->segment.rate < 0.0)
2713 demux->segment.position = demux->segment.start;
2715 /* perform EOS logic */
2716 if (!demux->no_more_pads) {
2717 gst_element_no_more_pads (GST_ELEMENT_CAST (demux));
2718 demux->no_more_pads = TRUE;
2721 if (demux->segment.flags & GST_SEGMENT_FLAG_SEGMENT) {
2724 /* for segment playback we need to post when (in stream time)
2725 * we stopped, this is either stop (when set) or the duration. */
2726 if ((stop = demux->segment.stop) == -1)
2727 stop = demux->segment.duration;
2729 if (demux->segment.rate >= 0) {
2730 GST_LOG_OBJECT (demux, "Sending segment done, at end of segment");
2731 gst_element_post_message (GST_ELEMENT_CAST (demux),
2732 gst_message_new_segment_done (GST_OBJECT_CAST (demux),
2733 GST_FORMAT_TIME, stop));
2734 gst_flv_demux_push_src_event (demux,
2735 gst_event_new_segment_done (GST_FORMAT_TIME, stop));
2736 } else { /* Reverse playback */
2737 GST_LOG_OBJECT (demux, "Sending segment done, at beginning of "
2739 gst_element_post_message (GST_ELEMENT_CAST (demux),
2740 gst_message_new_segment_done (GST_OBJECT_CAST (demux),
2741 GST_FORMAT_TIME, demux->segment.start));
2742 gst_flv_demux_push_src_event (demux,
2743 gst_event_new_segment_done (GST_FORMAT_TIME,
2744 demux->segment.start));
2747 /* normal playback, send EOS to all linked pads */
2748 if (!demux->no_more_pads) {
2749 gst_element_no_more_pads (GST_ELEMENT (demux));
2750 demux->no_more_pads = TRUE;
2753 GST_LOG_OBJECT (demux, "Sending EOS, at end of stream");
2754 if (!demux->audio_pad && !demux->video_pad)
2755 GST_ELEMENT_ERROR (demux, STREAM, FAILED,
2756 ("Internal data stream error."), ("Got EOS before any data"));
2757 else if (!gst_flv_demux_push_src_event (demux, gst_event_new_eos ()))
2758 GST_WARNING_OBJECT (demux, "failed pushing EOS on streams");
2760 } else if (ret == GST_FLOW_NOT_LINKED || ret < GST_FLOW_EOS) {
2761 GST_ELEMENT_FLOW_ERROR (demux, ret);
2762 gst_flv_demux_push_src_event (demux, gst_event_new_eos ());
2764 gst_object_unref (demux);
2770 gst_flv_demux_find_offset (GstFlvDemux * demux, GstSegment * segment,
2771 GstSeekFlags seek_flags)
2776 GstIndexEntry *entry;
2778 g_return_val_if_fail (segment != NULL, 0);
2780 time = segment->position;
2782 index = gst_flv_demux_get_index (GST_ELEMENT (demux));
2785 /* Let's check if we have an index entry for that seek time */
2786 entry = gst_index_get_assoc_entry (index, demux->index_id,
2787 seek_flags & GST_SEEK_FLAG_SNAP_AFTER ?
2788 GST_INDEX_LOOKUP_AFTER : GST_INDEX_LOOKUP_BEFORE,
2789 GST_ASSOCIATION_FLAG_KEY_UNIT, GST_FORMAT_TIME, time);
2792 gst_index_entry_assoc_map (entry, GST_FORMAT_BYTES, &bytes);
2793 gst_index_entry_assoc_map (entry, GST_FORMAT_TIME, &time);
2795 GST_DEBUG_OBJECT (demux, "found index entry for %" GST_TIME_FORMAT
2796 " at %" GST_TIME_FORMAT ", seeking to %" G_GINT64_FORMAT,
2797 GST_TIME_ARGS (segment->position), GST_TIME_ARGS (time), bytes);
2799 /* Key frame seeking */
2800 if (seek_flags & GST_SEEK_FLAG_KEY_UNIT) {
2801 /* Adjust the segment so that the keyframe fits in */
2802 segment->start = segment->time = time;
2803 segment->position = time;
2806 GST_DEBUG_OBJECT (demux, "no index entry found for %" GST_TIME_FORMAT,
2807 GST_TIME_ARGS (segment->start));
2810 gst_object_unref (index);
2817 flv_demux_handle_seek_push (GstFlvDemux * demux, GstEvent * event)
2821 GstSeekType start_type, stop_type;
2824 gboolean update, flush, ret;
2825 GstSegment seeksegment;
2827 gst_event_parse_seek (event, &rate, &format, &flags,
2828 &start_type, &start, &stop_type, &stop);
2830 if (format != GST_FORMAT_TIME)
2833 flush = ! !(flags & GST_SEEK_FLAG_FLUSH);
2835 /* Work on a copy until we are sure the seek succeeded. */
2836 memcpy (&seeksegment, &demux->segment, sizeof (GstSegment));
2838 GST_DEBUG_OBJECT (demux, "segment before configure %" GST_SEGMENT_FORMAT,
2841 /* Apply the seek to our segment */
2842 gst_segment_do_seek (&seeksegment, rate, format, flags,
2843 start_type, start, stop_type, stop, &update);
2845 GST_DEBUG_OBJECT (demux, "segment configured %" GST_SEGMENT_FORMAT,
2848 if (flush || seeksegment.position != demux->segment.position) {
2849 /* Do the actual seeking */
2850 guint64 offset = gst_flv_demux_find_offset (demux, &seeksegment, flags);
2852 GST_DEBUG_OBJECT (demux, "generating an upstream seek at position %"
2853 G_GUINT64_FORMAT, offset);
2854 ret = gst_pad_push_event (demux->sinkpad,
2855 gst_event_new_seek (seeksegment.rate, GST_FORMAT_BYTES,
2856 flags | GST_SEEK_FLAG_ACCURATE, GST_SEEK_TYPE_SET,
2857 offset, GST_SEEK_TYPE_NONE, 0));
2858 if (G_UNLIKELY (!ret)) {
2859 GST_WARNING_OBJECT (demux, "upstream seek failed");
2862 gst_flow_combiner_reset (demux->flowcombiner);
2863 /* Tell all the stream we moved to a different position (discont) */
2864 demux->audio_need_discont = TRUE;
2865 demux->video_need_discont = TRUE;
2871 /* Ok seek succeeded, take the newly configured segment */
2872 memcpy (&demux->segment, &seeksegment, sizeof (GstSegment));
2874 /* Tell all the stream a new segment is needed */
2875 demux->audio_need_segment = TRUE;
2876 demux->video_need_segment = TRUE;
2877 /* Clean any potential newsegment event kept for the streams. The first
2878 * stream needing a new segment will create a new one. */
2879 if (G_UNLIKELY (demux->new_seg_event)) {
2880 gst_event_unref (demux->new_seg_event);
2881 demux->new_seg_event = NULL;
2883 GST_DEBUG_OBJECT (demux, "preparing newsegment from %"
2884 GST_TIME_FORMAT " to %" GST_TIME_FORMAT,
2885 GST_TIME_ARGS (demux->segment.start),
2886 GST_TIME_ARGS (demux->segment.stop));
2887 demux->new_seg_event = gst_event_new_segment (&demux->segment);
2888 gst_event_unref (event);
2890 ret = gst_pad_push_event (demux->sinkpad, event);
2898 GST_WARNING_OBJECT (demux, "we only support seeking in TIME format");
2899 gst_event_unref (event);
2905 gst_flv_demux_handle_seek_push (GstFlvDemux * demux, GstEvent * event)
2909 gst_event_parse_seek (event, NULL, &format, NULL, NULL, NULL, NULL, NULL);
2911 if (format != GST_FORMAT_TIME) {
2912 GST_WARNING_OBJECT (demux, "we only support seeking in TIME format");
2913 gst_event_unref (event);
2917 /* First try upstream */
2918 if (gst_pad_push_event (demux->sinkpad, gst_event_ref (event))) {
2919 GST_DEBUG_OBJECT (demux, "Upstream successfully seeked");
2920 gst_event_unref (event);
2924 if (!demux->indexed) {
2925 guint64 seek_offset = 0;
2926 gboolean building_index;
2928 GST_OBJECT_LOCK (demux);
2929 /* handle the seek in the chain function */
2930 demux->seeking = TRUE;
2931 demux->state = FLV_STATE_SEEK;
2933 /* copy the event */
2934 if (demux->seek_event)
2935 gst_event_unref (demux->seek_event);
2936 demux->seek_event = gst_event_ref (event);
2938 /* set the building_index flag so that only one thread can setup the
2939 * structures for index seeking. */
2940 building_index = demux->building_index;
2941 if (!building_index) {
2942 demux->building_index = TRUE;
2943 if (!demux->file_size
2944 && !gst_pad_peer_query_duration (demux->sinkpad, GST_FORMAT_BYTES,
2945 &demux->file_size)) {
2946 GST_WARNING_OBJECT (demux, "Failed to query upstream file size");
2947 GST_OBJECT_UNLOCK (demux);
2951 /* we hope the last tag is a scriptdataobject containing an index
2952 * the size of the last tag is given in the last guint32 bits
2953 * then we seek to the beginning of the tag, parse it and hopefully obtain an index */
2954 seek_offset = demux->file_size - sizeof (guint32);
2955 GST_DEBUG_OBJECT (demux,
2956 "File size obtained, seeking to %" G_GUINT64_FORMAT, seek_offset);
2958 GST_OBJECT_UNLOCK (demux);
2960 if (!building_index) {
2961 GST_INFO_OBJECT (demux, "Seeking to last 4 bytes at %" G_GUINT64_FORMAT,
2963 return flv_demux_seek_to_offset (demux, seek_offset);
2966 /* FIXME: we have to always return true so that we don't block the seek
2968 * Note: maybe it is OK to return true if we're still building the index */
2972 return flv_demux_handle_seek_push (demux, event);
2976 gst_flv_demux_handle_seek_pull (GstFlvDemux * demux, GstEvent * event,
2981 GstSeekType start_type, stop_type;
2984 gboolean update, flush, ret = FALSE;
2985 GstSegment seeksegment;
2987 gst_event_parse_seek (event, &rate, &format, &flags,
2988 &start_type, &start, &stop_type, &stop);
2990 if (format != GST_FORMAT_TIME)
2993 /* mark seeking thread entering flushing/pausing */
2994 GST_OBJECT_LOCK (demux);
2996 demux->seeking = seeking;
2997 GST_OBJECT_UNLOCK (demux);
2999 flush = ! !(flags & GST_SEEK_FLAG_FLUSH);
3002 /* Flush start up and downstream to make sure data flow and loops are
3004 gst_flv_demux_push_src_event (demux, gst_event_new_flush_start ());
3005 gst_pad_push_event (demux->sinkpad, gst_event_new_flush_start ());
3007 /* Pause the pulling task */
3008 gst_pad_pause_task (demux->sinkpad);
3011 /* Take the stream lock */
3012 GST_PAD_STREAM_LOCK (demux->sinkpad);
3015 /* Stop flushing upstream we need to pull */
3016 gst_pad_push_event (demux->sinkpad, gst_event_new_flush_stop (TRUE));
3019 /* Work on a copy until we are sure the seek succeeded. */
3020 memcpy (&seeksegment, &demux->segment, sizeof (GstSegment));
3022 GST_DEBUG_OBJECT (demux, "segment before configure %" GST_SEGMENT_FORMAT,
3025 /* Apply the seek to our segment */
3026 gst_segment_do_seek (&seeksegment, rate, format, flags,
3027 start_type, start, stop_type, stop, &update);
3029 GST_DEBUG_OBJECT (demux, "segment configured %" GST_SEGMENT_FORMAT,
3032 if (flush || seeksegment.position != demux->segment.position) {
3033 /* Do the actual seeking */
3034 /* index is reliable if it is complete or we do not go to far ahead */
3035 if (seeking && !demux->indexed &&
3036 seeksegment.position > demux->index_max_time + 10 * GST_SECOND) {
3037 GST_DEBUG_OBJECT (demux, "delaying seek to post-scan; "
3038 " index only up to %" GST_TIME_FORMAT,
3039 GST_TIME_ARGS (demux->index_max_time));
3040 /* stop flushing for now */
3042 gst_flv_demux_push_src_event (demux, gst_event_new_flush_stop (TRUE));
3043 /* delegate scanning and index building to task thread to avoid
3044 * occupying main (UI) loop */
3045 if (demux->seek_event)
3046 gst_event_unref (demux->seek_event);
3047 demux->seek_event = gst_event_ref (event);
3048 demux->seek_time = seeksegment.position;
3049 demux->state = FLV_STATE_SEEK;
3050 /* do not know about succes yet, but we did care and handled it */
3055 /* now index should be as reliable as it can be for current purpose */
3056 gst_flv_demux_move_to_offset (demux,
3057 gst_flv_demux_find_offset (demux, &seeksegment, flags), TRUE);
3064 /* Stop flushing, the sinks are at time 0 now */
3065 gst_flv_demux_push_src_event (demux, gst_event_new_flush_stop (TRUE));
3069 /* Ok seek succeeded, take the newly configured segment */
3070 memcpy (&demux->segment, &seeksegment, sizeof (GstSegment));
3072 /* Notify about the start of a new segment */
3073 if (demux->segment.flags & GST_SEGMENT_FLAG_SEGMENT) {
3074 gst_element_post_message (GST_ELEMENT (demux),
3075 gst_message_new_segment_start (GST_OBJECT (demux),
3076 demux->segment.format, demux->segment.position));
3079 gst_flow_combiner_reset (demux->flowcombiner);
3080 /* Tell all the stream a new segment is needed */
3081 demux->audio_need_segment = TRUE;
3082 demux->video_need_segment = TRUE;
3083 /* Clean any potential newsegment event kept for the streams. The first
3084 * stream needing a new segment will create a new one. */
3085 if (G_UNLIKELY (demux->new_seg_event)) {
3086 gst_event_unref (demux->new_seg_event);
3087 demux->new_seg_event = NULL;
3089 GST_DEBUG_OBJECT (demux, "preparing newsegment from %"
3090 GST_TIME_FORMAT " to %" GST_TIME_FORMAT,
3091 GST_TIME_ARGS (demux->segment.start),
3092 GST_TIME_ARGS (demux->segment.stop));
3093 demux->new_seg_event = gst_event_new_segment (&demux->segment);
3097 GST_OBJECT_LOCK (demux);
3098 seeking = demux->seeking && !seeking;
3099 demux->seeking = FALSE;
3100 GST_OBJECT_UNLOCK (demux);
3102 /* if we detect an external seek having started (and possibly already having
3103 * flushed), do not restart task to give it a chance.
3104 * Otherwise external one's flushing will take care to pause task */
3106 gst_pad_pause_task (demux->sinkpad);
3108 gst_pad_start_task (demux->sinkpad,
3109 (GstTaskFunction) gst_flv_demux_loop, demux->sinkpad, NULL);
3112 GST_PAD_STREAM_UNLOCK (demux->sinkpad);
3114 gst_event_unref (event);
3120 GST_WARNING_OBJECT (demux, "we only support seeking in TIME format");
3121 gst_event_unref (event);
3126 /* If we can pull that's prefered */
3128 gst_flv_demux_sink_activate (GstPad * sinkpad, GstObject * parent)
3133 query = gst_query_new_scheduling ();
3135 if (!gst_pad_peer_query (sinkpad, query)) {
3136 gst_query_unref (query);
3140 pull_mode = gst_query_has_scheduling_mode_with_flags (query,
3141 GST_PAD_MODE_PULL, GST_SCHEDULING_FLAG_SEEKABLE);
3142 gst_query_unref (query);
3147 GST_DEBUG_OBJECT (sinkpad, "activating pull");
3148 return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PULL, TRUE);
3152 GST_DEBUG_OBJECT (sinkpad, "activating push");
3153 return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PUSH, TRUE);
3158 gst_flv_demux_sink_activate_mode (GstPad * sinkpad, GstObject * parent,
3159 GstPadMode mode, gboolean active)
3164 demux = GST_FLV_DEMUX (parent);
3167 case GST_PAD_MODE_PUSH:
3168 demux->random_access = FALSE;
3171 case GST_PAD_MODE_PULL:
3173 demux->random_access = TRUE;
3174 res = gst_pad_start_task (sinkpad, (GstTaskFunction) gst_flv_demux_loop,
3177 demux->random_access = FALSE;
3178 res = gst_pad_stop_task (sinkpad);
3189 gst_flv_demux_sink_event (GstPad * pad, GstObject * parent, GstEvent * event)
3192 gboolean ret = FALSE;
3194 demux = GST_FLV_DEMUX (parent);
3196 GST_DEBUG_OBJECT (demux, "handling event %s", GST_EVENT_TYPE_NAME (event));
3198 switch (GST_EVENT_TYPE (event)) {
3199 case GST_EVENT_FLUSH_START:
3200 GST_DEBUG_OBJECT (demux, "trying to force chain function to exit");
3201 demux->flushing = TRUE;
3202 ret = gst_flv_demux_push_src_event (demux, event);
3204 case GST_EVENT_FLUSH_STOP:
3205 GST_DEBUG_OBJECT (demux, "flushing FLV demuxer");
3206 gst_flv_demux_flush (demux, TRUE);
3207 ret = gst_flv_demux_push_src_event (demux, event);
3213 GST_DEBUG_OBJECT (demux, "received EOS");
3215 index = gst_flv_demux_get_index (GST_ELEMENT (demux));
3218 GST_DEBUG_OBJECT (demux, "committing index");
3219 gst_index_commit (index, demux->index_id);
3220 gst_object_unref (index);
3223 if (!demux->audio_pad && !demux->video_pad) {
3224 GST_ELEMENT_ERROR (demux, STREAM, FAILED,
3225 ("Internal data stream error."), ("Got EOS before any data"));
3226 gst_event_unref (event);
3228 if (!demux->no_more_pads) {
3229 gst_element_no_more_pads (GST_ELEMENT (demux));
3230 demux->no_more_pads = TRUE;
3233 if (!gst_flv_demux_push_src_event (demux, event))
3234 GST_WARNING_OBJECT (demux, "failed pushing EOS on streams");
3239 case GST_EVENT_SEGMENT:
3241 GstSegment in_segment;
3243 GST_DEBUG_OBJECT (demux, "received new segment");
3245 gst_event_copy_segment (event, &in_segment);
3247 if (in_segment.format == GST_FORMAT_TIME) {
3248 /* time segment, this is perfect, copy over the values. */
3249 memcpy (&demux->segment, &in_segment, sizeof (in_segment));
3251 GST_DEBUG_OBJECT (demux, "NEWSEGMENT: %" GST_SEGMENT_FORMAT,
3255 ret = gst_flv_demux_push_src_event (demux, event);
3257 /* non-time format */
3258 demux->audio_need_segment = TRUE;
3259 demux->video_need_segment = TRUE;
3261 gst_event_unref (event);
3262 if (demux->new_seg_event) {
3263 gst_event_unref (demux->new_seg_event);
3264 demux->new_seg_event = NULL;
3267 gst_flow_combiner_reset (demux->flowcombiner);
3271 ret = gst_pad_event_default (pad, parent, event);
3279 gst_flv_demux_src_event (GstPad * pad, GstObject * parent, GstEvent * event)
3282 gboolean ret = FALSE;
3284 demux = GST_FLV_DEMUX (parent);
3286 GST_DEBUG_OBJECT (demux, "handling event %s", GST_EVENT_TYPE_NAME (event));
3288 switch (GST_EVENT_TYPE (event)) {
3289 case GST_EVENT_SEEK:
3290 /* Try to push upstream first */
3291 gst_event_ref (event);
3292 ret = gst_pad_push_event (demux->sinkpad, event);
3294 gst_event_unref (event);
3297 if (demux->random_access) {
3298 ret = gst_flv_demux_handle_seek_pull (demux, event, TRUE);
3300 ret = gst_flv_demux_handle_seek_push (demux, event);
3304 ret = gst_pad_push_event (demux->sinkpad, event);
3312 gst_flv_demux_query (GstPad * pad, GstObject * parent, GstQuery * query)
3314 gboolean res = TRUE;
3317 demux = GST_FLV_DEMUX (parent);
3319 switch (GST_QUERY_TYPE (query)) {
3320 case GST_QUERY_DURATION:
3324 gst_query_parse_duration (query, &format, NULL);
3326 /* duration is time only */
3327 if (format != GST_FORMAT_TIME) {
3328 GST_DEBUG_OBJECT (demux, "duration query only supported for time "
3334 /* Try to push upstream first */
3335 res = gst_pad_peer_query (demux->sinkpad, query);
3339 GST_DEBUG_OBJECT (pad, "duration query, replying %" GST_TIME_FORMAT,
3340 GST_TIME_ARGS (demux->duration));
3342 gst_query_set_duration (query, GST_FORMAT_TIME, demux->duration);
3346 case GST_QUERY_POSITION:
3350 gst_query_parse_position (query, &format, NULL);
3352 /* position is time only */
3353 if (format != GST_FORMAT_TIME) {
3354 GST_DEBUG_OBJECT (demux, "position query only supported for time "
3360 GST_DEBUG_OBJECT (pad, "position query, replying %" GST_TIME_FORMAT,
3361 GST_TIME_ARGS (demux->segment.position));
3363 gst_query_set_position (query, GST_FORMAT_TIME, demux->segment.position);
3368 case GST_QUERY_SEEKING:{
3371 gst_query_parse_seeking (query, &fmt, NULL, NULL, NULL);
3373 /* First ask upstream */
3374 if (fmt == GST_FORMAT_TIME && gst_pad_peer_query (demux->sinkpad, query)) {
3377 gst_query_parse_seeking (query, NULL, &seekable, NULL, NULL);
3384 /* FIXME, check index this way is not thread safe */
3385 if (fmt != GST_FORMAT_TIME || !demux->index) {
3386 gst_query_set_seeking (query, fmt, FALSE, -1, -1);
3387 } else if (demux->random_access) {
3388 gst_query_set_seeking (query, GST_FORMAT_TIME, TRUE, 0,
3391 GstQuery *peerquery = gst_query_new_seeking (GST_FORMAT_BYTES);
3392 gboolean seekable = gst_pad_peer_query (demux->sinkpad, peerquery);
3395 gst_query_parse_seeking (peerquery, NULL, &seekable, NULL, NULL);
3396 gst_query_unref (peerquery);
3399 gst_query_set_seeking (query, GST_FORMAT_TIME, seekable, 0,
3402 gst_query_set_seeking (query, GST_FORMAT_TIME, FALSE, -1, -1);
3406 case GST_QUERY_SEGMENT:
3411 format = demux->segment.format;
3414 gst_segment_to_stream_time (&demux->segment, format,
3415 demux->segment.start);
3416 if ((stop = demux->segment.stop) == -1)
3417 stop = demux->segment.duration;
3419 stop = gst_segment_to_stream_time (&demux->segment, format, stop);
3421 gst_query_set_segment (query, demux->segment.rate, format, start, stop);
3425 case GST_QUERY_LATENCY:
3427 res = gst_pad_query_default (pad, parent, query);
3436 static GstStateChangeReturn
3437 gst_flv_demux_change_state (GstElement * element, GstStateChange transition)
3440 GstStateChangeReturn ret;
3442 demux = GST_FLV_DEMUX (element);
3444 switch (transition) {
3445 case GST_STATE_CHANGE_READY_TO_PAUSED:
3446 /* If this is our own index destroy it as the
3447 * old entries might be wrong for the new stream */
3448 if (demux->own_index) {
3449 gst_object_unref (demux->index);
3450 demux->index = NULL;
3451 demux->own_index = FALSE;
3454 /* If no index was created, generate one */
3455 if (G_UNLIKELY (!demux->index)) {
3456 GST_DEBUG_OBJECT (demux, "no index provided creating our own");
3458 demux->index = g_object_new (gst_mem_index_get_type (), NULL);
3460 gst_index_get_writer_id (demux->index, GST_OBJECT (demux),
3462 demux->own_index = TRUE;
3464 gst_flv_demux_cleanup (demux);
3470 ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
3471 if (ret == GST_STATE_CHANGE_FAILURE)
3474 switch (transition) {
3475 case GST_STATE_CHANGE_PAUSED_TO_READY:
3476 gst_flv_demux_cleanup (demux);
3487 gst_flv_demux_set_index (GstElement * element, GstIndex * index)
3489 GstFlvDemux *demux = GST_FLV_DEMUX (element);
3490 GstIndex *old_index;
3492 GST_OBJECT_LOCK (demux);
3494 old_index = demux->index;
3497 demux->index = gst_object_ref (index);
3498 demux->own_index = FALSE;
3500 demux->index = NULL;
3503 gst_object_unref (demux->index);
3505 gst_object_ref (index);
3507 GST_OBJECT_UNLOCK (demux);
3509 /* object lock might be taken again */
3511 gst_index_get_writer_id (index, GST_OBJECT (element), &demux->index_id);
3513 GST_DEBUG_OBJECT (demux, "Set index %" GST_PTR_FORMAT, demux->index);
3515 gst_object_unref (index);
3520 gst_flv_demux_get_index (GstElement * element)
3522 GstIndex *result = NULL;
3524 GstFlvDemux *demux = GST_FLV_DEMUX (element);
3526 GST_OBJECT_LOCK (demux);
3528 result = gst_object_ref (demux->index);
3529 GST_OBJECT_UNLOCK (demux);
3535 gst_flv_demux_dispose (GObject * object)
3537 GstFlvDemux *demux = GST_FLV_DEMUX (object);
3539 GST_DEBUG_OBJECT (demux, "disposing FLV demuxer");
3541 if (demux->adapter) {
3542 gst_adapter_clear (demux->adapter);
3543 g_object_unref (demux->adapter);
3544 demux->adapter = NULL;
3547 if (demux->taglist) {
3548 gst_tag_list_unref (demux->taglist);
3549 demux->taglist = NULL;
3552 if (demux->audio_tags) {
3553 gst_tag_list_unref (demux->audio_tags);
3554 demux->audio_tags = NULL;
3557 if (demux->video_tags) {
3558 gst_tag_list_unref (demux->video_tags);
3559 demux->video_tags = NULL;
3562 if (demux->flowcombiner) {
3563 gst_flow_combiner_free (demux->flowcombiner);
3564 demux->flowcombiner = NULL;
3567 if (demux->new_seg_event) {
3568 gst_event_unref (demux->new_seg_event);
3569 demux->new_seg_event = NULL;
3572 if (demux->audio_codec_data) {
3573 gst_buffer_unref (demux->audio_codec_data);
3574 demux->audio_codec_data = NULL;
3577 if (demux->video_codec_data) {
3578 gst_buffer_unref (demux->video_codec_data);
3579 demux->video_codec_data = NULL;
3582 if (demux->audio_pad) {
3583 gst_object_unref (demux->audio_pad);
3584 demux->audio_pad = NULL;
3587 if (demux->video_pad) {
3588 gst_object_unref (demux->video_pad);
3589 demux->video_pad = NULL;
3593 gst_object_unref (demux->index);
3594 demux->index = NULL;
3598 g_array_free (demux->times, TRUE);
3599 demux->times = NULL;
3602 if (demux->filepositions) {
3603 g_array_free (demux->filepositions, TRUE);
3604 demux->filepositions = NULL;
3607 GST_CALL_PARENT (G_OBJECT_CLASS, dispose, (object));
3611 gst_flv_demux_class_init (GstFlvDemuxClass * klass)
3613 GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass);
3614 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
3616 gobject_class->dispose = gst_flv_demux_dispose;
3618 gstelement_class->change_state =
3619 GST_DEBUG_FUNCPTR (gst_flv_demux_change_state);
3622 gstelement_class->set_index = GST_DEBUG_FUNCPTR (gst_flv_demux_set_index);
3623 gstelement_class->get_index = GST_DEBUG_FUNCPTR (gst_flv_demux_get_index);
3626 gst_element_class_add_static_pad_template (gstelement_class,
3627 &flv_sink_template);
3628 gst_element_class_add_static_pad_template (gstelement_class,
3629 &audio_src_template);
3630 gst_element_class_add_static_pad_template (gstelement_class,
3631 &video_src_template);
3632 gst_element_class_set_static_metadata (gstelement_class, "FLV Demuxer",
3633 "Codec/Demuxer", "Demux FLV feeds into digital streams",
3634 "Julien Moutte <julien@moutte.net>");
3638 gst_flv_demux_init (GstFlvDemux * demux)
3641 gst_pad_new_from_static_template (&flv_sink_template, "sink");
3643 gst_pad_set_event_function (demux->sinkpad,
3644 GST_DEBUG_FUNCPTR (gst_flv_demux_sink_event));
3645 gst_pad_set_chain_function (demux->sinkpad,
3646 GST_DEBUG_FUNCPTR (gst_flv_demux_chain));
3647 gst_pad_set_activate_function (demux->sinkpad,
3648 GST_DEBUG_FUNCPTR (gst_flv_demux_sink_activate));
3649 gst_pad_set_activatemode_function (demux->sinkpad,
3650 GST_DEBUG_FUNCPTR (gst_flv_demux_sink_activate_mode));
3652 gst_element_add_pad (GST_ELEMENT (demux), demux->sinkpad);
3654 demux->adapter = gst_adapter_new ();
3655 demux->flowcombiner = gst_flow_combiner_new ();
3657 demux->own_index = FALSE;
3659 GST_OBJECT_FLAG_SET (demux, GST_ELEMENT_FLAG_INDEXABLE);
3661 gst_flv_demux_cleanup (demux);
3665 plugin_init (GstPlugin * plugin)
3667 GST_DEBUG_CATEGORY_INIT (flvdemux_debug, "flvdemux", 0, "FLV demuxer");
3669 if (!gst_element_register (plugin, "flvdemux", GST_RANK_PRIMARY,
3670 gst_flv_demux_get_type ()) ||
3671 !gst_element_register (plugin, "flvmux", GST_RANK_PRIMARY,
3672 gst_flv_mux_get_type ()))
3678 GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, GST_VERSION_MINOR,
3679 flv, "FLV muxing and demuxing plugin",
3680 plugin_init, VERSION, "LGPL", GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN)