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) { 5512, 11025, 22050, 44100 }; "
74 "audio/x-mulaw, channels = (int) { 1, 2 }, rate = (int) { 5512, 11025, 22050, 44100 }; "
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);
118 gst_flv_demux_parse_and_add_index_entry (GstFlvDemux * demux, GstClockTime ts,
119 guint64 pos, gboolean keyframe)
121 GstIndexAssociation associations[2];
123 GstIndexEntry *entry;
125 GST_LOG_OBJECT (demux,
126 "adding key=%d association %" GST_TIME_FORMAT "-> %" G_GUINT64_FORMAT,
127 keyframe, GST_TIME_ARGS (ts), pos);
129 /* if upstream is not seekable there is no point in building an index */
130 if (!demux->upstream_seekable)
133 index = gst_flv_demux_get_index (GST_ELEMENT (demux));
138 /* entry may already have been added before, avoid adding indefinitely */
139 entry = gst_index_get_assoc_entry (index, demux->index_id,
140 GST_INDEX_LOOKUP_EXACT, GST_ASSOCIATION_FLAG_NONE, GST_FORMAT_BYTES, pos);
143 #ifndef GST_DISABLE_GST_DEBUG
147 gst_index_entry_assoc_map (entry, GST_FORMAT_TIME, &time);
148 key = ! !(GST_INDEX_ASSOC_FLAGS (entry) & GST_ASSOCIATION_FLAG_KEY_UNIT);
149 GST_LOG_OBJECT (demux, "position already mapped to time %" GST_TIME_FORMAT
150 ", keyframe %d", GST_TIME_ARGS (time), key);
151 /* there is not really a way to delete the existing one */
152 if (time != ts || key != ! !keyframe)
153 GST_DEBUG_OBJECT (demux, "metadata mismatch");
155 gst_object_unref (index);
159 associations[0].format = GST_FORMAT_TIME;
160 associations[0].value = ts;
161 associations[1].format = GST_FORMAT_BYTES;
162 associations[1].value = pos;
164 gst_index_add_associationv (index, demux->index_id,
165 (keyframe) ? GST_ASSOCIATION_FLAG_KEY_UNIT :
166 GST_ASSOCIATION_FLAG_DELTA_UNIT, 2,
167 (const GstIndexAssociation *) &associations);
169 if (pos > demux->index_max_pos)
170 demux->index_max_pos = pos;
171 if (ts > demux->index_max_time)
172 demux->index_max_time = ts;
174 gst_object_unref (index);
178 FLV_GET_STRING (GstByteReader * reader)
180 guint16 string_size = 0;
181 gchar *string = NULL;
182 const guint8 *str = NULL;
184 g_return_val_if_fail (reader != NULL, NULL);
186 if (G_UNLIKELY (!gst_byte_reader_get_uint16_be (reader, &string_size)))
189 if (G_UNLIKELY (string_size > gst_byte_reader_get_remaining (reader)))
192 string = g_try_malloc0 (string_size + 1);
193 if (G_UNLIKELY (!string)) {
197 if (G_UNLIKELY (!gst_byte_reader_get_data (reader, string_size, &str))) {
202 memcpy (string, str, string_size);
203 if (!g_utf8_validate (string, string_size, NULL)) {
212 gst_flv_demux_check_seekability (GstFlvDemux * demux)
215 gint64 start = -1, stop = -1;
217 demux->upstream_seekable = FALSE;
219 query = gst_query_new_seeking (GST_FORMAT_BYTES);
220 if (!gst_pad_peer_query (demux->sinkpad, query)) {
221 GST_DEBUG_OBJECT (demux, "seeking query failed");
222 gst_query_unref (query);
226 gst_query_parse_seeking (query, NULL, &demux->upstream_seekable,
229 gst_query_unref (query);
231 /* try harder to query upstream size if we didn't get it the first time */
232 if (demux->upstream_seekable && stop == -1) {
233 GST_DEBUG_OBJECT (demux, "doing duration query to fix up unset stop");
234 gst_pad_peer_query_duration (demux->sinkpad, GST_FORMAT_BYTES, &stop);
237 /* if upstream doesn't know the size, it's likely that it's not seekable in
238 * practice even if it technically may be seekable */
239 if (demux->upstream_seekable && (start != 0 || stop <= start)) {
240 GST_DEBUG_OBJECT (demux, "seekable but unknown start/stop -> disable");
241 demux->upstream_seekable = FALSE;
244 GST_DEBUG_OBJECT (demux, "upstream seekable: %d", demux->upstream_seekable);
248 parse_flv_demux_parse_date_string (const gchar * s)
250 static const gchar months[12][4] = {
251 "Jan", "Feb", "Mar", "Apr",
252 "May", "Jun", "Jul", "Aug",
253 "Sep", "Oct", "Nov", "Dec"
255 GstDateTime *dt = NULL;
258 gchar *endptr, *stripped;
260 gint year = -1, month = -1, day = -1;
261 gint hour = -1, minute = -1, seconds = -1;
263 stripped = g_strstrip (g_strdup (s));
265 /* "Fri Oct 15 15:13:16 2004" needs to be parsed */
266 tokens = g_strsplit (stripped, " ", -1);
270 if (g_strv_length (tokens) != 5)
274 d = g_ascii_strtoull (tokens[4], &endptr, 10);
275 if (d == 0 && *endptr != '\0')
281 if (strlen (tokens[1]) != 3)
283 for (i = 0; i < 12; i++) {
284 if (!strcmp (tokens[1], months[i])) {
294 d = g_ascii_strtoull (tokens[2], &endptr, 10);
295 if (d == 0 && *endptr != '\0')
302 if (sscanf (tokens[3], "%d:%d:%d", &hh, &mm, &ss) < 2)
304 if (hh >= 0 && hh < 24 && mm >= 0 && mm < 60 && ss >= 0 && ss < 60) {
316 dt = gst_date_time_new (0.0, year, month, day, hour, minute, seconds);
322 gst_flv_demux_parse_metadata_item (GstFlvDemux * demux, GstByteReader * reader,
323 gboolean * end_marker)
325 gchar *tag_name = NULL;
328 /* Initialize the end_marker flag to FALSE */
331 /* Name of the tag */
332 tag_name = FLV_GET_STRING (reader);
333 if (G_UNLIKELY (!tag_name)) {
334 GST_WARNING_OBJECT (demux, "failed reading tag name");
338 /* What kind of object is that */
339 if (!gst_byte_reader_get_uint8 (reader, &tag_type))
342 GST_DEBUG_OBJECT (demux, "tag name %s, tag type %d", tag_name, tag_type);
346 { /* Use a union to read the uint64 and then as a double */
349 if (!gst_byte_reader_get_float64_be (reader, &d))
352 GST_DEBUG_OBJECT (demux, "%s => (double) %f", tag_name, d);
354 if (!strcmp (tag_name, "duration")) {
355 demux->duration = d * GST_SECOND;
357 gst_tag_list_add (demux->taglist, GST_TAG_MERGE_REPLACE,
358 GST_TAG_DURATION, demux->duration, NULL);
359 } else if (!strcmp (tag_name, "AspectRatioX")) {
361 demux->got_par = TRUE;
362 } else if (!strcmp (tag_name, "AspectRatioY")) {
364 demux->got_par = TRUE;
365 } else if (!strcmp (tag_name, "width")) {
367 } else if (!strcmp (tag_name, "height")) {
369 } else if (!strcmp (tag_name, "framerate")) {
370 demux->framerate = d;
372 GST_INFO_OBJECT (demux, "Tag \'%s\' not handled", tag_name);
377 case 1: /* Boolean */
381 if (!gst_byte_reader_get_uint8 (reader, &b))
384 GST_DEBUG_OBJECT (demux, "%s => (boolean) %d", tag_name, b);
386 GST_INFO_OBJECT (demux, "Tag \'%s\' not handled", tag_name);
394 s = FLV_GET_STRING (reader);
398 GST_DEBUG_OBJECT (demux, "%s => (string) %s", tag_name, s);
400 if (!strcmp (tag_name, "creationdate")) {
403 dt = parse_flv_demux_parse_date_string (s);
405 GST_DEBUG_OBJECT (demux, "Failed to parse '%s' into datetime", s);
407 gst_tag_list_add (demux->taglist, GST_TAG_MERGE_REPLACE,
408 GST_TAG_DATE_TIME, dt, NULL);
409 gst_date_time_unref (dt);
411 } else if (!strcmp (tag_name, "creator")) {
412 gst_tag_list_add (demux->taglist, GST_TAG_MERGE_REPLACE,
413 GST_TAG_ARTIST, s, NULL);
414 } else if (!strcmp (tag_name, "title")) {
415 gst_tag_list_add (demux->taglist, GST_TAG_MERGE_REPLACE,
416 GST_TAG_TITLE, s, NULL);
417 } else if (!strcmp (tag_name, "metadatacreator")) {
418 gst_tag_list_add (demux->taglist, GST_TAG_MERGE_REPLACE,
419 GST_TAG_ENCODER, s, NULL);
421 GST_INFO_OBJECT (demux, "Tag \'%s\' not handled", tag_name);
430 gboolean end_of_object_marker = FALSE;
432 while (!end_of_object_marker) {
433 gboolean ok = gst_flv_demux_parse_metadata_item (demux, reader,
434 &end_of_object_marker);
436 if (G_UNLIKELY (!ok)) {
437 GST_WARNING_OBJECT (demux, "failed reading a tag, skipping");
444 case 8: /* ECMA array */
446 guint32 nb_elems = 0;
447 gboolean end_of_object_marker = FALSE;
449 if (!gst_byte_reader_get_uint32_be (reader, &nb_elems))
452 GST_DEBUG_OBJECT (demux, "there are approx. %d elements in the array",
455 while (!end_of_object_marker) {
456 gboolean ok = gst_flv_demux_parse_metadata_item (demux, reader,
457 &end_of_object_marker);
459 if (G_UNLIKELY (!ok)) {
460 GST_WARNING_OBJECT (demux, "failed reading a tag, skipping");
467 case 9: /* End marker */
469 GST_DEBUG_OBJECT (demux, "end marker ?");
470 if (tag_name[0] == '\0') {
472 GST_DEBUG_OBJECT (demux, "end marker detected");
481 guint32 nb_elems = 0;
483 if (!gst_byte_reader_get_uint32_be (reader, &nb_elems))
486 GST_DEBUG_OBJECT (demux, "array has %d elements", nb_elems);
488 if (!strcmp (tag_name, "times")) {
490 g_array_free (demux->times, TRUE);
492 demux->times = g_array_new (FALSE, TRUE, sizeof (gdouble));
493 } else if (!strcmp (tag_name, "filepositions")) {
494 if (demux->filepositions) {
495 g_array_free (demux->filepositions, TRUE);
497 demux->filepositions = g_array_new (FALSE, TRUE, sizeof (gdouble));
501 guint8 elem_type = 0;
503 if (!gst_byte_reader_get_uint8 (reader, &elem_type))
511 if (!gst_byte_reader_get_float64_be (reader, &d))
514 GST_DEBUG_OBJECT (demux, "element is a double %f", d);
516 if (!strcmp (tag_name, "times") && demux->times) {
517 g_array_append_val (demux->times, d);
518 } else if (!strcmp (tag_name, "filepositions") &&
519 demux->filepositions) {
520 g_array_append_val (demux->filepositions, d);
525 GST_WARNING_OBJECT (demux, "unsupported array element type %d",
537 if (!gst_byte_reader_get_float64_be (reader, &d))
540 if (!gst_byte_reader_get_int16_be (reader, &i))
543 GST_DEBUG_OBJECT (demux,
544 "%s => (date as a double) %f, timezone offset %d", tag_name, d, i);
546 GST_INFO_OBJECT (demux, "Tag \'%s\' not handled", tag_name);
551 GST_WARNING_OBJECT (demux, "unsupported tag type %d", tag_type);
565 gst_flv_demux_parse_tag_script (GstFlvDemux * demux, GstBuffer * buffer)
567 GstFlowReturn ret = GST_FLOW_OK;
568 GstByteReader reader;
572 g_return_val_if_fail (gst_buffer_get_size (buffer) >= 7, GST_FLOW_ERROR);
574 gst_buffer_map (buffer, &map, GST_MAP_READ);
575 gst_byte_reader_init (&reader, map.data, map.size);
577 gst_byte_reader_skip_unchecked (&reader, 7);
579 GST_LOG_OBJECT (demux, "parsing a script tag");
581 if (!gst_byte_reader_get_uint8 (&reader, &type))
586 gchar *function_name;
589 function_name = FLV_GET_STRING (&reader);
591 GST_LOG_OBJECT (demux, "function name is %s", GST_STR_NULL (function_name));
593 if (function_name != NULL && strcmp (function_name, "onMetaData") == 0) {
594 gboolean end_marker = FALSE;
595 GST_DEBUG_OBJECT (demux, "we have a metadata script object");
597 if (!gst_byte_reader_get_uint8 (&reader, &type)) {
598 g_free (function_name);
605 guint32 nb_elems = 0;
608 if (!gst_byte_reader_get_uint32_be (&reader, &nb_elems)) {
609 g_free (function_name);
613 /* The number of elements is just a hint, some files have
614 nb_elements == 0 and actually contain items. */
615 GST_DEBUG_OBJECT (demux, "there are approx. %d elements in the array",
618 /* fallthrough to read data */
622 while (!end_marker) {
624 gst_flv_demux_parse_metadata_item (demux, &reader, &end_marker);
626 if (G_UNLIKELY (!ok)) {
627 GST_WARNING_OBJECT (demux, "failed reading a tag, skipping");
634 GST_DEBUG_OBJECT (demux, "Unhandled script data type : %d", type);
635 g_free (function_name);
639 demux->push_tags = TRUE;
642 g_free (function_name);
644 if (demux->times && demux->filepositions) {
647 /* If an index was found, insert associations */
648 num = MIN (demux->times->len, demux->filepositions->len);
649 for (i = 0; i < num; i++) {
650 guint64 time, fileposition;
652 time = g_array_index (demux->times, gdouble, i) * GST_SECOND;
653 fileposition = g_array_index (demux->filepositions, gdouble, i);
654 gst_flv_demux_parse_and_add_index_entry (demux, time, fileposition,
657 demux->indexed = TRUE;
662 gst_buffer_unmap (buffer, &map);
668 have_group_id (GstFlvDemux * demux)
672 event = gst_pad_get_sticky_event (demux->sinkpad, GST_EVENT_STREAM_START, 0);
674 if (gst_event_parse_group_id (event, &demux->group_id))
675 demux->have_group_id = TRUE;
677 demux->have_group_id = FALSE;
678 gst_event_unref (event);
679 } else if (!demux->have_group_id) {
680 demux->have_group_id = TRUE;
681 demux->group_id = gst_util_group_id_next ();
684 return demux->have_group_id;
688 gst_flv_demux_audio_negotiate (GstFlvDemux * demux, guint32 codec_tag,
689 guint32 rate, guint32 channels, guint32 width)
691 GstCaps *caps = NULL, *old_caps;
692 gchar *codec_name = NULL;
693 gboolean ret = FALSE;
694 guint adjusted_rate = rate;
700 caps = gst_caps_new_simple ("audio/x-adpcm", "layout", G_TYPE_STRING,
705 caps = gst_caps_new_simple ("audio/mpeg",
706 "mpegversion", G_TYPE_INT, 1, "layer", G_TYPE_INT, 3,
707 "parsed", G_TYPE_BOOLEAN, TRUE, NULL);
712 GstAudioFormat format;
714 /* Assuming little endian for 0 (aka endianness of the
715 * system on which the file was created) as most people
716 * are probably using little endian machines */
717 format = gst_audio_format_build_integer ((width == 8) ? FALSE : TRUE,
718 G_LITTLE_ENDIAN, width, width);
720 caps = gst_caps_new_simple ("audio/x-raw",
721 "format", G_TYPE_STRING, gst_audio_format_to_string (format),
722 "layout", G_TYPE_STRING, "interleaved", NULL);
728 caps = gst_caps_new_empty_simple ("audio/x-nellymoser");
733 if (!demux->audio_codec_data) {
734 GST_DEBUG_OBJECT (demux, "don't have AAC codec data yet");
739 gst_buffer_map (demux->audio_codec_data, &map, GST_MAP_READ);
741 /* use codec-data to extract and verify samplerate */
745 freq_index = GST_READ_UINT16_BE (map.data);
746 freq_index = (freq_index & 0x0780) >> 7;
748 gst_codec_utils_aac_get_sample_rate_from_index (freq_index);
750 if (adjusted_rate && (rate != adjusted_rate)) {
751 GST_LOG_OBJECT (demux, "Ajusting AAC sample rate %d -> %d", rate,
754 adjusted_rate = rate;
757 gst_buffer_unmap (demux->audio_codec_data, &map);
759 caps = gst_caps_new_simple ("audio/mpeg",
760 "mpegversion", G_TYPE_INT, 4, "framed", G_TYPE_BOOLEAN, TRUE,
761 "stream-format", G_TYPE_STRING, "raw", NULL);
765 caps = gst_caps_new_empty_simple ("audio/x-alaw");
768 caps = gst_caps_new_empty_simple ("audio/x-mulaw");
772 GValue streamheader = G_VALUE_INIT;
773 GValue value = G_VALUE_INIT;
775 GstStructure *structure;
779 caps = gst_caps_new_empty_simple ("audio/x-speex");
780 structure = gst_caps_get_structure (caps, 0);
782 GST_DEBUG_OBJECT (demux, "generating speex header");
784 /* Speex decoder expects streamheader to be { [header], [comment] } */
785 g_value_init (&streamheader, GST_TYPE_ARRAY);
788 gst_byte_writer_init_with_size (&w, 80, TRUE);
789 gst_byte_writer_put_data (&w, (guint8 *) "Speex ", 8);
790 gst_byte_writer_put_data (&w, (guint8 *) "1.1.12", 7);
791 gst_byte_writer_fill (&w, 0, 13);
792 gst_byte_writer_put_uint32_le (&w, 1); /* version */
793 gst_byte_writer_put_uint32_le (&w, 80); /* header_size */
794 gst_byte_writer_put_uint32_le (&w, 16000); /* rate */
795 gst_byte_writer_put_uint32_le (&w, 1); /* mode: Wideband */
796 gst_byte_writer_put_uint32_le (&w, 4); /* mode_bitstream_version */
797 gst_byte_writer_put_uint32_le (&w, 1); /* nb_channels: 1 */
798 gst_byte_writer_put_uint32_le (&w, -1); /* bitrate */
799 gst_byte_writer_put_uint32_le (&w, 0x50); /* frame_size */
800 gst_byte_writer_put_uint32_le (&w, 0); /* VBR */
801 gst_byte_writer_put_uint32_le (&w, 1); /* frames_per_packet */
802 gst_byte_writer_put_uint32_le (&w, 0); /* extra_headers */
803 gst_byte_writer_put_uint32_le (&w, 0); /* reserved1 */
804 gst_byte_writer_put_uint32_le (&w, 0); /* reserved2 */
805 g_assert (gst_byte_writer_get_size (&w) == 80);
807 g_value_init (&value, GST_TYPE_BUFFER);
808 g_value_take_boxed (&value, gst_byte_writer_reset_and_get_buffer (&w));
809 gst_value_array_append_value (&streamheader, &value);
810 g_value_unset (&value);
813 g_value_init (&value, GST_TYPE_BUFFER);
814 tags = gst_tag_list_new_empty ();
815 buf = gst_tag_list_to_vorbiscomment_buffer (tags, NULL, 0, "No comments");
816 gst_tag_list_unref (tags);
817 g_value_take_boxed (&value, buf);
818 gst_value_array_append_value (&streamheader, &value);
819 g_value_unset (&value);
821 gst_structure_take_value (structure, "streamheader", &streamheader);
824 adjusted_rate = 16000;
828 GST_WARNING_OBJECT (demux, "unsupported audio codec tag %u", codec_tag);
832 if (G_UNLIKELY (!caps)) {
833 GST_WARNING_OBJECT (demux, "failed creating caps for audio pad");
837 gst_caps_set_simple (caps, "rate", G_TYPE_INT, adjusted_rate,
838 "channels", G_TYPE_INT, channels, NULL);
840 if (demux->audio_codec_data) {
841 gst_caps_set_simple (caps, "codec_data", GST_TYPE_BUFFER,
842 demux->audio_codec_data, NULL);
845 old_caps = gst_pad_get_current_caps (demux->audio_pad);
848 gst_pad_create_stream_id (demux->audio_pad, GST_ELEMENT_CAST (demux),
851 event = gst_event_new_stream_start (stream_id);
852 if (have_group_id (demux))
853 gst_event_set_group_id (event, demux->group_id);
854 gst_pad_push_event (demux->audio_pad, event);
857 if (!old_caps || !gst_caps_is_equal (old_caps, caps))
858 ret = gst_pad_set_caps (demux->audio_pad, caps);
863 gst_caps_unref (old_caps);
866 if (G_LIKELY (ret)) {
867 /* Store the caps we got from tags */
868 demux->audio_codec_tag = codec_tag;
870 demux->channels = channels;
871 demux->width = width;
874 codec_name = gst_pb_utils_get_codec_description (caps);
877 if (demux->taglist == NULL)
878 demux->taglist = gst_tag_list_new_empty ();
879 gst_tag_list_add (demux->taglist, GST_TAG_MERGE_REPLACE,
880 GST_TAG_AUDIO_CODEC, codec_name, NULL);
884 GST_DEBUG_OBJECT (demux->audio_pad, "successfully negotiated caps %"
885 GST_PTR_FORMAT, caps);
887 GST_DEBUG_OBJECT (demux->audio_pad, "delayed setting caps");
890 GST_WARNING_OBJECT (demux->audio_pad, "failed negotiating caps %"
891 GST_PTR_FORMAT, caps);
895 gst_caps_unref (caps);
902 gst_flv_demux_push_src_event (GstFlvDemux * demux, GstEvent * event)
906 if (demux->audio_pad)
907 ret |= gst_pad_push_event (demux->audio_pad, gst_event_ref (event));
909 if (demux->video_pad)
910 ret |= gst_pad_push_event (demux->video_pad, gst_event_ref (event));
912 gst_event_unref (event);
918 gst_flv_demux_push_tags (GstFlvDemux * demux)
920 if (demux->has_audio && !demux->audio_pad) {
921 GST_DEBUG_OBJECT (demux,
922 "Waiting for audio stream pad to come up before we can push tags");
925 if (demux->has_video && !demux->video_pad) {
926 GST_DEBUG_OBJECT (demux,
927 "Waiting for video stream pad to come up before we can push tags");
930 if (demux->taglist) {
931 GST_DEBUG_OBJECT (demux, "pushing tags out %" GST_PTR_FORMAT,
933 gst_tag_list_set_scope (demux->taglist, GST_TAG_SCOPE_GLOBAL);
934 gst_flv_demux_push_src_event (demux, gst_event_new_tag (demux->taglist));
935 demux->taglist = gst_tag_list_new_empty ();
936 demux->push_tags = FALSE;
941 gst_flv_demux_update_resync (GstFlvDemux * demux, guint32 dts, gboolean discont,
942 guint32 * last, GstClockTime * offset)
944 gboolean ret = FALSE;
945 gint32 ddts = dts - *last;
946 if (!discont && ddts <= -RESYNC_THRESHOLD) {
947 /* Theoretically, we should use substract the duration of the last buffer,
948 but this demuxer sends no durations on buffers, not sure if it cannot
949 know, or just does not care to calculate. */
950 *offset -= ddts * GST_MSECOND;
951 GST_WARNING_OBJECT (demux,
952 "Large dts gap (%" G_GINT32_FORMAT " ms), assuming resync, offset now %"
953 GST_TIME_FORMAT "", ddts, GST_TIME_ARGS (*offset));
963 gst_flv_demux_parse_tag_audio (GstFlvDemux * demux, GstBuffer * buffer)
965 GstFlowReturn ret = GST_FLOW_OK;
966 guint32 pts = 0, codec_tag = 0, rate = 5512, width = 8, channels = 1;
967 guint32 codec_data = 0, pts_ext = 0;
973 GST_LOG_OBJECT (demux, "parsing an audio tag");
975 if (G_UNLIKELY (!demux->audio_pad && demux->no_more_pads)) {
976 #ifndef GST_DISABLE_DEBUG
977 if (G_UNLIKELY (!demux->no_audio_warned)) {
978 GST_WARNING_OBJECT (demux,
979 "Signaled no-more-pads already but had no audio pad -- ignoring");
980 demux->no_audio_warned = TRUE;
986 g_return_val_if_fail (gst_buffer_get_size (buffer) == demux->tag_size,
989 /* Error out on tags with too small headers */
990 if (gst_buffer_get_size (buffer) < 11) {
991 GST_ERROR_OBJECT (demux, "Too small tag size (%" G_GSIZE_FORMAT ")",
992 gst_buffer_get_size (buffer));
993 return GST_FLOW_ERROR;
996 gst_buffer_map (buffer, &map, GST_MAP_READ);
999 /* Grab information about audio tag */
1000 pts = GST_READ_UINT24_BE (data);
1001 /* read the pts extension to 32 bits integer */
1002 pts_ext = GST_READ_UINT8 (data + 3);
1004 pts |= pts_ext << 24;
1006 GST_LOG_OBJECT (demux, "pts bytes %02X %02X %02X %02X (%d)", data[0], data[1],
1007 data[2], data[3], pts);
1009 /* Skip the stream id and go directly to the flags */
1010 flags = GST_READ_UINT8 (data + 7);
1012 /* Silently skip buffers with no data */
1025 if ((flags & 0x0C) == 0x0C) {
1027 } else if ((flags & 0x0C) == 0x08) {
1029 } else if ((flags & 0x0C) == 0x04) {
1033 codec_tag = flags >> 4;
1034 if (codec_tag == 10) { /* AAC has an extra byte for packet type */
1040 /* codec tags with special rates */
1041 if (codec_tag == 5 || codec_tag == 14)
1043 else if ((codec_tag == 4) || (codec_tag == 11))
1046 GST_LOG_OBJECT (demux, "audio tag with %d channels, %dHz sampling rate, "
1047 "%d bits width, codec tag %u (flags %02X)", channels, rate, width,
1050 if (codec_tag == 10) {
1051 guint8 aac_packet_type = GST_READ_UINT8 (data + 8);
1053 switch (aac_packet_type) {
1056 /* AudioSpecificConfig data */
1057 GST_LOG_OBJECT (demux, "got an AAC codec data packet");
1058 if (demux->audio_codec_data) {
1059 gst_buffer_unref (demux->audio_codec_data);
1061 demux->audio_codec_data = gst_buffer_copy_region (buffer, GST_BUFFER_COPY_MEMORY,
1062 7 + codec_data, demux->tag_data_size - codec_data);
1064 /* Use that buffer data in the caps */
1065 if (demux->audio_pad)
1066 gst_flv_demux_audio_negotiate (demux, codec_tag, rate, channels, width);
1070 if (!demux->audio_codec_data) {
1071 GST_ERROR_OBJECT (demux, "got AAC audio packet before codec data");
1075 /* AAC raw packet */
1076 GST_LOG_OBJECT (demux, "got a raw AAC audio packet");
1079 GST_WARNING_OBJECT (demux, "invalid AAC packet type %u",
1084 /* If we don't have our audio pad created, then create it. */
1085 if (G_UNLIKELY (!demux->audio_pad)) {
1087 gst_pad_new_from_template (gst_element_class_get_pad_template
1088 (GST_ELEMENT_GET_CLASS (demux), "audio"), "audio");
1089 if (G_UNLIKELY (!demux->audio_pad)) {
1090 GST_WARNING_OBJECT (demux, "failed creating audio pad");
1091 ret = GST_FLOW_ERROR;
1095 /* Set functions on the pad */
1096 gst_pad_set_query_function (demux->audio_pad,
1097 GST_DEBUG_FUNCPTR (gst_flv_demux_query));
1098 gst_pad_set_event_function (demux->audio_pad,
1099 GST_DEBUG_FUNCPTR (gst_flv_demux_src_event));
1101 gst_pad_use_fixed_caps (demux->audio_pad);
1103 /* Make it active */
1104 gst_pad_set_active (demux->audio_pad, TRUE);
1106 /* Negotiate caps */
1107 if (!gst_flv_demux_audio_negotiate (demux, codec_tag, rate, channels,
1109 gst_object_unref (demux->audio_pad);
1110 demux->audio_pad = NULL;
1111 ret = GST_FLOW_ERROR;
1114 #ifndef GST_DISABLE_GST_DEBUG
1118 caps = gst_pad_get_current_caps (demux->audio_pad);
1119 GST_DEBUG_OBJECT (demux, "created audio pad with caps %" GST_PTR_FORMAT,
1122 gst_caps_unref (caps);
1126 /* We need to set caps before adding */
1127 gst_element_add_pad (GST_ELEMENT (demux),
1128 gst_object_ref (demux->audio_pad));
1129 gst_flow_combiner_add_pad (demux->flowcombiner, demux->audio_pad);
1131 /* We only emit no more pads when we have audio and video. Indeed we can
1132 * not trust the FLV header to tell us if there will be only audio or
1133 * only video and we would just break discovery of some files */
1134 if (demux->audio_pad && demux->video_pad) {
1135 GST_DEBUG_OBJECT (demux, "emitting no more pads");
1136 gst_element_no_more_pads (GST_ELEMENT (demux));
1137 demux->no_more_pads = TRUE;
1138 demux->push_tags = TRUE;
1142 /* Check if caps have changed */
1143 if (G_UNLIKELY (rate != demux->rate || channels != demux->channels ||
1144 codec_tag != demux->audio_codec_tag || width != demux->width)) {
1145 GST_DEBUG_OBJECT (demux, "audio settings have changed, changing caps");
1147 gst_buffer_replace (&demux->audio_codec_data, NULL);
1149 /* Negotiate caps */
1150 if (!gst_flv_demux_audio_negotiate (demux, codec_tag, rate, channels,
1152 ret = GST_FLOW_ERROR;
1157 /* Push taglist if present */
1158 if (G_UNLIKELY (demux->push_tags))
1159 gst_flv_demux_push_tags (demux);
1161 /* Check if we have anything to push */
1162 if (demux->tag_data_size <= codec_data) {
1163 GST_LOG_OBJECT (demux, "Nothing left in this tag, returning");
1167 /* Create buffer from pad */
1168 outbuf = gst_buffer_copy_region (buffer, GST_BUFFER_COPY_MEMORY,
1169 7 + codec_data, demux->tag_data_size - codec_data);
1171 /* detect (and deem to be resyncs) large pts gaps */
1172 if (gst_flv_demux_update_resync (demux, pts, demux->audio_need_discont,
1173 &demux->last_audio_pts, &demux->audio_time_offset)) {
1174 GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_RESYNC);
1177 /* Fill buffer with data */
1178 GST_BUFFER_PTS (outbuf) = pts * GST_MSECOND + demux->audio_time_offset;
1179 GST_BUFFER_DTS (outbuf) = GST_BUFFER_PTS (outbuf);
1180 GST_BUFFER_DURATION (outbuf) = GST_CLOCK_TIME_NONE;
1181 GST_BUFFER_OFFSET (outbuf) = demux->audio_offset++;
1182 GST_BUFFER_OFFSET_END (outbuf) = demux->audio_offset;
1184 if (demux->duration == GST_CLOCK_TIME_NONE ||
1185 demux->duration < GST_BUFFER_TIMESTAMP (outbuf))
1186 demux->duration = GST_BUFFER_TIMESTAMP (outbuf);
1188 /* Only add audio frames to the index if we have no video,
1189 * and if the index is not yet complete */
1190 if (!demux->has_video && !demux->indexed) {
1191 gst_flv_demux_parse_and_add_index_entry (demux,
1192 GST_BUFFER_TIMESTAMP (outbuf), demux->cur_tag_offset, TRUE);
1195 if (G_UNLIKELY (demux->audio_need_discont)) {
1196 GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_DISCONT);
1197 demux->audio_need_discont = FALSE;
1200 demux->segment.position = GST_BUFFER_TIMESTAMP (outbuf);
1202 /* Do we need a newsegment event ? */
1203 if (G_UNLIKELY (demux->audio_need_segment)) {
1204 if (!demux->new_seg_event) {
1205 GST_DEBUG_OBJECT (demux, "pushing newsegment from %"
1206 GST_TIME_FORMAT " to %" GST_TIME_FORMAT,
1207 GST_TIME_ARGS (demux->segment.position),
1208 GST_TIME_ARGS (demux->segment.stop));
1209 demux->segment.start = demux->segment.time = demux->segment.position;
1210 demux->new_seg_event = gst_event_new_segment (&demux->segment);
1212 GST_DEBUG_OBJECT (demux, "pushing pre-generated newsegment event");
1215 gst_pad_push_event (demux->audio_pad, gst_event_ref (demux->new_seg_event));
1217 demux->audio_need_segment = FALSE;
1220 GST_LOG_OBJECT (demux,
1221 "pushing %" G_GSIZE_FORMAT " bytes buffer at pts %" GST_TIME_FORMAT
1222 " with duration %" GST_TIME_FORMAT ", offset %" G_GUINT64_FORMAT,
1223 gst_buffer_get_size (outbuf),
1224 GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (outbuf)),
1225 GST_TIME_ARGS (GST_BUFFER_DURATION (outbuf)), GST_BUFFER_OFFSET (outbuf));
1227 if (!GST_CLOCK_TIME_IS_VALID (demux->audio_start)) {
1228 demux->audio_start = GST_BUFFER_TIMESTAMP (outbuf);
1230 if (!GST_CLOCK_TIME_IS_VALID (demux->audio_first_ts)) {
1231 demux->audio_first_ts = GST_BUFFER_TIMESTAMP (outbuf);
1234 if (G_UNLIKELY (!demux->no_more_pads
1235 && (GST_CLOCK_DIFF (demux->audio_start,
1236 GST_BUFFER_TIMESTAMP (outbuf)) > NO_MORE_PADS_THRESHOLD))) {
1237 GST_DEBUG_OBJECT (demux,
1238 "Signalling no-more-pads because no video stream was found"
1239 " after 6 seconds of audio");
1240 gst_element_no_more_pads (GST_ELEMENT_CAST (demux));
1241 demux->no_more_pads = TRUE;
1242 demux->push_tags = TRUE;
1245 /* Push downstream */
1246 ret = gst_pad_push (demux->audio_pad, outbuf);
1248 if (G_UNLIKELY (ret != GST_FLOW_OK) &&
1249 demux->segment.rate < 0.0 && ret == GST_FLOW_EOS &&
1250 demux->segment.position > demux->segment.stop) {
1251 /* In reverse playback we can get a GST_FLOW_EOS when
1252 * we are at the end of the segment, so we just need to jump
1253 * back to the previous section. */
1254 GST_DEBUG_OBJECT (demux, "downstream has reached end of segment");
1255 demux->audio_done = TRUE;
1260 ret = gst_flow_combiner_update_pad_flow (demux->flowcombiner,
1261 demux->audio_pad, ret);
1264 gst_buffer_unmap (buffer, &map);
1270 gst_flv_demux_video_negotiate (GstFlvDemux * demux, guint32 codec_tag)
1272 gboolean ret = FALSE;
1273 GstCaps *caps = NULL, *old_caps;
1274 gchar *codec_name = NULL;
1278 /* Generate caps for that pad */
1279 switch (codec_tag) {
1282 gst_caps_new_simple ("video/x-flash-video", "flvversion", G_TYPE_INT,
1286 caps = gst_caps_new_empty_simple ("video/x-flash-screen");
1289 caps = gst_caps_new_empty_simple ("video/x-vp6-flash");
1292 caps = gst_caps_new_empty_simple ("video/x-vp6-alpha");
1295 if (!demux->video_codec_data) {
1296 GST_DEBUG_OBJECT (demux, "don't have h264 codec data yet");
1301 gst_caps_new_simple ("video/x-h264", "stream-format", G_TYPE_STRING,
1305 GST_WARNING_OBJECT (demux, "unsupported video codec tag %u", codec_tag);
1308 if (G_UNLIKELY (!caps)) {
1309 GST_WARNING_OBJECT (demux, "failed creating caps for video pad");
1313 gst_caps_set_simple (caps, "pixel-aspect-ratio", GST_TYPE_FRACTION,
1314 demux->par_x, demux->par_y, NULL);
1316 if (G_LIKELY (demux->w)) {
1317 gst_caps_set_simple (caps, "width", G_TYPE_INT, demux->w, NULL);
1320 if (G_LIKELY (demux->h)) {
1321 gst_caps_set_simple (caps, "height", G_TYPE_INT, demux->h, NULL);
1324 if (G_LIKELY (demux->framerate)) {
1325 gint num = 0, den = 0;
1327 gst_video_guess_framerate (GST_SECOND / demux->framerate, &num, &den);
1328 GST_DEBUG_OBJECT (demux->video_pad,
1329 "fps to be used on caps %f (as a fraction = %d/%d)", demux->framerate,
1332 gst_caps_set_simple (caps, "framerate", GST_TYPE_FRACTION, num, den, NULL);
1335 if (demux->video_codec_data) {
1336 gst_caps_set_simple (caps, "codec_data", GST_TYPE_BUFFER,
1337 demux->video_codec_data, NULL);
1340 old_caps = gst_pad_get_current_caps (demux->video_pad);
1343 gst_pad_create_stream_id (demux->video_pad, GST_ELEMENT_CAST (demux),
1345 event = gst_event_new_stream_start (stream_id);
1348 if (have_group_id (demux))
1349 gst_event_set_group_id (event, demux->group_id);
1350 gst_pad_push_event (demux->video_pad, event);
1353 if (!old_caps || !gst_caps_is_equal (old_caps, caps))
1354 ret = gst_pad_set_caps (demux->video_pad, caps);
1359 gst_caps_unref (old_caps);
1362 if (G_LIKELY (ret)) {
1363 /* Store the caps we have set */
1364 demux->video_codec_tag = codec_tag;
1367 codec_name = gst_pb_utils_get_codec_description (caps);
1370 if (demux->taglist == NULL)
1371 demux->taglist = gst_tag_list_new_empty ();
1372 gst_tag_list_add (demux->taglist, GST_TAG_MERGE_REPLACE,
1373 GST_TAG_VIDEO_CODEC, codec_name, NULL);
1374 g_free (codec_name);
1377 GST_DEBUG_OBJECT (demux->video_pad, "successfully negotiated caps %"
1378 GST_PTR_FORMAT, caps);
1380 GST_DEBUG_OBJECT (demux->video_pad, "delayed setting caps");
1383 GST_WARNING_OBJECT (demux->video_pad, "failed negotiating caps %"
1384 GST_PTR_FORMAT, caps);
1388 gst_caps_unref (caps);
1394 static GstFlowReturn
1395 gst_flv_demux_parse_tag_video (GstFlvDemux * demux, GstBuffer * buffer)
1397 GstFlowReturn ret = GST_FLOW_OK;
1398 guint32 dts = 0, codec_data = 1, dts_ext = 0;
1400 gboolean keyframe = FALSE;
1401 guint8 flags = 0, codec_tag = 0;
1406 g_return_val_if_fail (gst_buffer_get_size (buffer) == demux->tag_size,
1409 GST_LOG_OBJECT (demux, "parsing a video tag");
1412 (!demux->video_pad && demux->no_more_pads) {
1413 #ifndef GST_DISABLE_DEBUG
1415 (!demux->no_video_warned) {
1416 GST_WARNING_OBJECT (demux,
1417 "Signaled no-more-pads already but had no video pad -- ignoring");
1418 demux->no_video_warned = TRUE;
1424 if (gst_buffer_get_size (buffer) < 12) {
1425 GST_ERROR_OBJECT (demux, "Too small tag size");
1426 return GST_FLOW_ERROR;
1429 gst_buffer_map (buffer, &map, GST_MAP_READ);
1432 /* Grab information about video tag */
1433 dts = GST_READ_UINT24_BE (data);
1434 /* read the dts extension to 32 bits integer */
1435 dts_ext = GST_READ_UINT8 (data + 3);
1437 dts |= dts_ext << 24;
1439 GST_LOG_OBJECT (demux, "dts bytes %02X %02X %02X %02X (%d)", data[0], data[1],
1440 data[2], data[3], dts);
1442 /* Skip the stream id and go directly to the flags */
1443 flags = GST_READ_UINT8 (data + 7);
1446 if ((flags >> 4) == 1) {
1450 codec_tag = flags & 0x0F;
1451 if (codec_tag == 4 || codec_tag == 5) {
1453 } else if (codec_tag == 7) {
1456 cts = GST_READ_UINT24_BE (data + 9);
1457 cts = (cts + 0xff800000) ^ 0xff800000;
1459 GST_LOG_OBJECT (demux, "got cts %d", cts);
1462 GST_LOG_OBJECT (demux, "video tag with codec tag %u, keyframe (%d) "
1463 "(flags %02X)", codec_tag, keyframe, flags);
1465 if (codec_tag == 7) {
1466 guint8 avc_packet_type = GST_READ_UINT8 (data + 8);
1468 switch (avc_packet_type) {
1471 /* AVCDecoderConfigurationRecord data */
1472 GST_LOG_OBJECT (demux, "got an H.264 codec data packet");
1473 if (demux->video_codec_data) {
1474 gst_buffer_unref (demux->video_codec_data);
1476 demux->video_codec_data = gst_buffer_copy_region (buffer,
1477 GST_BUFFER_COPY_MEMORY, 7 + codec_data,
1478 demux->tag_data_size - codec_data);;
1479 /* Use that buffer data in the caps */
1480 if (demux->video_pad)
1481 gst_flv_demux_video_negotiate (demux, codec_tag);
1485 /* H.264 NALU packet */
1486 if (!demux->video_codec_data) {
1487 GST_ERROR_OBJECT (demux, "got H.264 video packet before codec data");
1491 GST_LOG_OBJECT (demux, "got a H.264 NALU video packet");
1494 GST_WARNING_OBJECT (demux, "invalid video packet type %u",
1499 /* If we don't have our video pad created, then create it. */
1500 if (G_UNLIKELY (!demux->video_pad)) {
1502 gst_pad_new_from_template (gst_element_class_get_pad_template
1503 (GST_ELEMENT_GET_CLASS (demux), "video"), "video");
1504 if (G_UNLIKELY (!demux->video_pad)) {
1505 GST_WARNING_OBJECT (demux, "failed creating video pad");
1506 ret = GST_FLOW_ERROR;
1510 /* Set functions on the pad */
1511 gst_pad_set_query_function (demux->video_pad,
1512 GST_DEBUG_FUNCPTR (gst_flv_demux_query));
1513 gst_pad_set_event_function (demux->video_pad,
1514 GST_DEBUG_FUNCPTR (gst_flv_demux_src_event));
1516 gst_pad_use_fixed_caps (demux->video_pad);
1518 /* Make it active */
1519 gst_pad_set_active (demux->video_pad, TRUE);
1521 /* Needs to be active before setting caps */
1522 if (!gst_flv_demux_video_negotiate (demux, codec_tag)) {
1523 gst_object_unref (demux->video_pad);
1524 demux->video_pad = NULL;
1525 ret = GST_FLOW_ERROR;
1529 /* When we ve set pixel-aspect-ratio we use that boolean to detect a
1530 * metadata tag that would come later and trigger a caps change */
1531 demux->got_par = FALSE;
1533 #ifndef GST_DISABLE_GST_DEBUG
1537 caps = gst_pad_get_current_caps (demux->video_pad);
1538 GST_DEBUG_OBJECT (demux, "created video pad with caps %" GST_PTR_FORMAT,
1541 gst_caps_unref (caps);
1545 /* We need to set caps before adding */
1546 gst_element_add_pad (GST_ELEMENT (demux),
1547 gst_object_ref (demux->video_pad));
1548 gst_flow_combiner_add_pad (demux->flowcombiner, demux->video_pad);
1550 /* We only emit no more pads when we have audio and video. Indeed we can
1551 * not trust the FLV header to tell us if there will be only audio or
1552 * only video and we would just break discovery of some files */
1553 if (demux->audio_pad && demux->video_pad) {
1554 GST_DEBUG_OBJECT (demux, "emitting no more pads");
1555 gst_element_no_more_pads (GST_ELEMENT (demux));
1556 demux->no_more_pads = TRUE;
1557 demux->push_tags = TRUE;
1561 /* Check if caps have changed */
1562 if (G_UNLIKELY (codec_tag != demux->video_codec_tag || demux->got_par)) {
1563 GST_DEBUG_OBJECT (demux, "video settings have changed, changing caps");
1564 gst_buffer_replace (&demux->video_codec_data, NULL);
1566 if (!gst_flv_demux_video_negotiate (demux, codec_tag)) {
1567 ret = GST_FLOW_ERROR;
1571 /* When we ve set pixel-aspect-ratio we use that boolean to detect a
1572 * metadata tag that would come later and trigger a caps change */
1573 demux->got_par = FALSE;
1576 /* Push taglist if present */
1577 if (G_UNLIKELY (demux->push_tags))
1578 gst_flv_demux_push_tags (demux);
1580 /* Check if we have anything to push */
1581 if (demux->tag_data_size <= codec_data) {
1582 GST_LOG_OBJECT (demux, "Nothing left in this tag, returning");
1586 /* Create buffer from pad */
1587 outbuf = gst_buffer_copy_region (buffer, GST_BUFFER_COPY_MEMORY,
1588 7 + codec_data, demux->tag_data_size - codec_data);
1590 /* detect (and deem to be resyncs) large dts gaps */
1591 if (gst_flv_demux_update_resync (demux, dts, demux->video_need_discont,
1592 &demux->last_video_dts, &demux->video_time_offset)) {
1593 GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_RESYNC);
1596 /* Fill buffer with data */
1597 GST_LOG_OBJECT (demux, "dts %u pts %u cts %d", dts, dts + cts, cts);
1599 GST_BUFFER_PTS (outbuf) =
1600 (dts + cts) * GST_MSECOND + demux->video_time_offset;
1601 GST_BUFFER_DTS (outbuf) = dts * GST_MSECOND + demux->video_time_offset;
1602 GST_BUFFER_DURATION (outbuf) = GST_CLOCK_TIME_NONE;
1603 GST_BUFFER_OFFSET (outbuf) = demux->video_offset++;
1604 GST_BUFFER_OFFSET_END (outbuf) = demux->video_offset;
1606 if (demux->duration == GST_CLOCK_TIME_NONE ||
1607 demux->duration < GST_BUFFER_TIMESTAMP (outbuf))
1608 demux->duration = GST_BUFFER_TIMESTAMP (outbuf);
1611 GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_DELTA_UNIT);
1613 if (!demux->indexed) {
1614 gst_flv_demux_parse_and_add_index_entry (demux,
1615 GST_BUFFER_TIMESTAMP (outbuf), demux->cur_tag_offset, keyframe);
1618 if (G_UNLIKELY (demux->video_need_discont)) {
1619 GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_DISCONT);
1620 demux->video_need_discont = FALSE;
1623 demux->segment.position = GST_BUFFER_TIMESTAMP (outbuf);
1625 /* Do we need a newsegment event ? */
1626 if (G_UNLIKELY (demux->video_need_segment)) {
1627 if (!demux->new_seg_event) {
1628 GST_DEBUG_OBJECT (demux, "pushing newsegment from %"
1629 GST_TIME_FORMAT " to %" GST_TIME_FORMAT,
1630 GST_TIME_ARGS (demux->segment.position),
1631 GST_TIME_ARGS (demux->segment.stop));
1632 demux->segment.start = demux->segment.time = demux->segment.position;
1633 demux->new_seg_event = gst_event_new_segment (&demux->segment);
1635 GST_DEBUG_OBJECT (demux, "pushing pre-generated newsegment event");
1638 gst_pad_push_event (demux->video_pad, gst_event_ref (demux->new_seg_event));
1640 demux->video_need_segment = FALSE;
1643 GST_LOG_OBJECT (demux,
1644 "pushing %" G_GSIZE_FORMAT " bytes buffer at dts %" GST_TIME_FORMAT
1645 " with duration %" GST_TIME_FORMAT ", offset %" G_GUINT64_FORMAT
1646 ", keyframe (%d)", gst_buffer_get_size (outbuf),
1647 GST_TIME_ARGS (GST_BUFFER_DTS (outbuf)),
1648 GST_TIME_ARGS (GST_BUFFER_DURATION (outbuf)), GST_BUFFER_OFFSET (outbuf),
1651 if (!GST_CLOCK_TIME_IS_VALID (demux->video_start)) {
1652 demux->video_start = GST_BUFFER_TIMESTAMP (outbuf);
1654 if (!GST_CLOCK_TIME_IS_VALID (demux->audio_first_ts)) {
1655 demux->video_first_ts = GST_BUFFER_TIMESTAMP (outbuf);
1658 if (G_UNLIKELY (!demux->no_more_pads
1659 && (GST_CLOCK_DIFF (demux->video_start,
1660 GST_BUFFER_TIMESTAMP (outbuf)) > NO_MORE_PADS_THRESHOLD))) {
1661 GST_DEBUG_OBJECT (demux,
1662 "Signalling no-more-pads because no audio stream was found"
1663 " after 6 seconds of video");
1664 gst_element_no_more_pads (GST_ELEMENT_CAST (demux));
1665 demux->no_more_pads = TRUE;
1666 demux->push_tags = TRUE;
1669 /* Push downstream */
1670 ret = gst_pad_push (demux->video_pad, outbuf);
1672 if (G_UNLIKELY (ret != GST_FLOW_OK) &&
1673 demux->segment.rate < 0.0 && ret == GST_FLOW_EOS &&
1674 demux->segment.position > demux->segment.stop) {
1675 /* In reverse playback we can get a GST_FLOW_EOS when
1676 * we are at the end of the segment, so we just need to jump
1677 * back to the previous section. */
1678 GST_DEBUG_OBJECT (demux, "downstream has reached end of segment");
1679 demux->video_done = TRUE;
1684 ret = gst_flow_combiner_update_pad_flow (demux->flowcombiner,
1685 demux->video_pad, ret);
1688 gst_buffer_unmap (buffer, &map);
1693 gst_flv_demux_parse_tag_timestamp (GstFlvDemux * demux, gboolean index,
1694 GstBuffer * buffer, size_t * tag_size)
1696 guint32 dts = 0, dts_ext = 0;
1697 guint32 tag_data_size;
1699 gboolean keyframe = TRUE;
1700 GstClockTime ret = GST_CLOCK_TIME_NONE;
1705 g_return_val_if_fail (gst_buffer_get_size (buffer) >= 12,
1706 GST_CLOCK_TIME_NONE);
1708 gst_buffer_map (buffer, &map, GST_MAP_READ);
1714 if (type != 9 && type != 8 && type != 18) {
1715 GST_WARNING_OBJECT (demux, "Unsupported tag type %u", data[0]);
1720 demux->has_video = TRUE;
1722 demux->has_audio = TRUE;
1724 tag_data_size = GST_READ_UINT24_BE (data + 1);
1726 if (size >= tag_data_size + 11 + 4) {
1727 if (GST_READ_UINT32_BE (data + tag_data_size + 11) != tag_data_size + 11) {
1728 GST_WARNING_OBJECT (demux, "Invalid tag size");
1734 *tag_size = tag_data_size + 11 + 4;
1738 GST_LOG_OBJECT (demux, "dts bytes %02X %02X %02X %02X", data[0], data[1],
1741 /* Grab timestamp of tag tag */
1742 dts = GST_READ_UINT24_BE (data);
1743 /* read the dts extension to 32 bits integer */
1744 dts_ext = GST_READ_UINT8 (data + 3);
1746 dts |= dts_ext << 24;
1751 keyframe = ((data[0] >> 4) == 1);
1754 ret = dts * GST_MSECOND;
1755 GST_LOG_OBJECT (demux, "dts: %" GST_TIME_FORMAT, GST_TIME_ARGS (ret));
1757 if (index && !demux->indexed && (type == 9 || (type == 8
1758 && !demux->has_video))) {
1759 gst_flv_demux_parse_and_add_index_entry (demux, ret, demux->offset,
1763 if (demux->duration == GST_CLOCK_TIME_NONE || demux->duration < ret)
1764 demux->duration = ret;
1767 gst_buffer_unmap (buffer, &map);
1771 static GstFlowReturn
1772 gst_flv_demux_parse_tag_type (GstFlvDemux * demux, GstBuffer * buffer)
1774 GstFlowReturn ret = GST_FLOW_OK;
1775 guint8 tag_type = 0;
1778 g_return_val_if_fail (gst_buffer_get_size (buffer) >= 4, GST_FLOW_ERROR);
1780 gst_buffer_map (buffer, &map, GST_MAP_READ);
1782 tag_type = map.data[0];
1784 /* Tag size is 1 byte of type + 3 bytes of size + 7 bytes + tag data size +
1785 * 4 bytes of previous tag size */
1786 demux->tag_data_size = GST_READ_UINT24_BE (map.data + 1);
1787 demux->tag_size = demux->tag_data_size + 11;
1789 GST_LOG_OBJECT (demux, "tag data size is %" G_GUINT64_FORMAT,
1790 demux->tag_data_size);
1792 gst_buffer_unmap (buffer, &map);
1796 demux->state = FLV_STATE_TAG_VIDEO;
1797 demux->has_video = TRUE;
1800 demux->state = FLV_STATE_TAG_AUDIO;
1801 demux->has_audio = TRUE;
1804 demux->state = FLV_STATE_TAG_SCRIPT;
1807 GST_WARNING_OBJECT (demux, "unsupported tag type %u", tag_type);
1808 demux->state = FLV_STATE_SKIP;
1814 static GstFlowReturn
1815 gst_flv_demux_parse_header (GstFlvDemux * demux, GstBuffer * buffer)
1817 GstFlowReturn ret = GST_FLOW_OK;
1820 g_return_val_if_fail (gst_buffer_get_size (buffer) >= 9, GST_FLOW_ERROR);
1822 gst_buffer_map (buffer, &map, GST_MAP_READ);
1824 /* Check for the FLV tag */
1825 if (map.data[0] == 'F' && map.data[1] == 'L' && map.data[2] == 'V') {
1826 GST_DEBUG_OBJECT (demux, "FLV header detected");
1828 if (G_UNLIKELY (demux->strict)) {
1829 GST_WARNING_OBJECT (demux, "invalid header tag detected");
1835 if (map.data[3] == '1') {
1836 GST_DEBUG_OBJECT (demux, "FLV version 1 detected");
1838 if (G_UNLIKELY (demux->strict)) {
1839 GST_WARNING_OBJECT (demux, "invalid header version detected");
1846 /* Now look at audio/video flags */
1848 guint8 flags = map.data[4];
1850 demux->has_video = demux->has_audio = FALSE;
1853 GST_DEBUG_OBJECT (demux, "there is a video stream");
1854 demux->has_video = TRUE;
1857 GST_DEBUG_OBJECT (demux, "there is an audio stream");
1858 demux->has_audio = TRUE;
1862 /* do a one-time seekability check */
1863 gst_flv_demux_check_seekability (demux);
1865 /* We don't care about the rest */
1866 demux->need_header = FALSE;
1869 gst_buffer_unmap (buffer, &map);
1875 gst_flv_demux_flush (GstFlvDemux * demux, gboolean discont)
1877 GST_DEBUG_OBJECT (demux, "flushing queued data in the FLV demuxer");
1879 gst_adapter_clear (demux->adapter);
1881 demux->audio_need_discont = TRUE;
1882 demux->video_need_discont = TRUE;
1884 demux->flushing = FALSE;
1886 /* Only in push mode and if we're not during a seek */
1887 if (!demux->random_access && demux->state != FLV_STATE_SEEK) {
1888 /* After a flush we expect a tag_type */
1889 demux->state = FLV_STATE_TAG_TYPE;
1890 /* We reset the offset and will get one from first push */
1896 gst_flv_demux_cleanup (GstFlvDemux * demux)
1898 GST_DEBUG_OBJECT (demux, "cleaning up FLV demuxer");
1900 demux->state = FLV_STATE_HEADER;
1902 demux->have_group_id = FALSE;
1903 demux->group_id = G_MAXUINT;
1905 demux->flushing = FALSE;
1906 demux->need_header = TRUE;
1907 demux->audio_need_segment = TRUE;
1908 demux->video_need_segment = TRUE;
1909 demux->audio_need_discont = TRUE;
1910 demux->video_need_discont = TRUE;
1912 demux->has_audio = FALSE;
1913 demux->has_video = FALSE;
1914 demux->push_tags = FALSE;
1915 demux->got_par = FALSE;
1917 demux->indexed = FALSE;
1918 demux->upstream_seekable = FALSE;
1919 demux->file_size = 0;
1921 demux->index_max_pos = 0;
1922 demux->index_max_time = 0;
1924 demux->audio_start = demux->video_start = GST_CLOCK_TIME_NONE;
1925 demux->last_audio_pts = demux->last_video_dts = 0;
1926 demux->audio_time_offset = demux->video_time_offset = 0;
1928 demux->no_more_pads = FALSE;
1930 #ifndef GST_DISABLE_DEBUG
1931 demux->no_audio_warned = FALSE;
1932 demux->no_video_warned = FALSE;
1935 gst_segment_init (&demux->segment, GST_FORMAT_TIME);
1937 demux->w = demux->h = 0;
1938 demux->framerate = 0.0;
1939 demux->par_x = demux->par_y = 1;
1940 demux->video_offset = 0;
1941 demux->audio_offset = 0;
1942 demux->offset = demux->cur_tag_offset = 0;
1943 demux->tag_size = demux->tag_data_size = 0;
1944 demux->duration = GST_CLOCK_TIME_NONE;
1946 if (demux->new_seg_event) {
1947 gst_event_unref (demux->new_seg_event);
1948 demux->new_seg_event = NULL;
1951 gst_adapter_clear (demux->adapter);
1953 if (demux->audio_codec_data) {
1954 gst_buffer_unref (demux->audio_codec_data);
1955 demux->audio_codec_data = NULL;
1958 if (demux->video_codec_data) {
1959 gst_buffer_unref (demux->video_codec_data);
1960 demux->video_codec_data = NULL;
1963 if (demux->audio_pad) {
1964 gst_flow_combiner_remove_pad (demux->flowcombiner, demux->audio_pad);
1965 gst_element_remove_pad (GST_ELEMENT (demux), demux->audio_pad);
1966 gst_object_unref (demux->audio_pad);
1967 demux->audio_pad = NULL;
1970 if (demux->video_pad) {
1971 gst_flow_combiner_remove_pad (demux->flowcombiner, demux->video_pad);
1972 gst_element_remove_pad (GST_ELEMENT (demux), demux->video_pad);
1973 gst_object_unref (demux->video_pad);
1974 demux->video_pad = NULL;
1978 g_array_free (demux->times, TRUE);
1979 demux->times = NULL;
1982 if (demux->filepositions) {
1983 g_array_free (demux->filepositions, TRUE);
1984 demux->filepositions = NULL;
1989 * Create and push a flushing seek event upstream
1992 flv_demux_seek_to_offset (GstFlvDemux * demux, guint64 offset)
1997 GST_DEBUG_OBJECT (demux, "Seeking to %" G_GUINT64_FORMAT, offset);
2000 gst_event_new_seek (1.0, GST_FORMAT_BYTES,
2001 GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE, GST_SEEK_TYPE_SET, offset,
2002 GST_SEEK_TYPE_NONE, -1);
2004 res = gst_pad_push_event (demux->sinkpad, event);
2007 demux->offset = offset;
2011 static GstFlowReturn
2012 gst_flv_demux_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer)
2014 GstFlowReturn ret = GST_FLOW_OK;
2015 GstFlvDemux *demux = NULL;
2017 demux = GST_FLV_DEMUX (parent);
2019 GST_LOG_OBJECT (demux,
2020 "received buffer of %" G_GSIZE_FORMAT " bytes at offset %"
2021 G_GUINT64_FORMAT, gst_buffer_get_size (buffer),
2022 GST_BUFFER_OFFSET (buffer));
2024 if (G_UNLIKELY (GST_BUFFER_OFFSET (buffer) == 0)) {
2025 GST_DEBUG_OBJECT (demux, "beginning of file, expect header");
2026 demux->state = FLV_STATE_HEADER;
2030 if (G_UNLIKELY (demux->offset == 0 && GST_BUFFER_OFFSET (buffer) != 0)) {
2031 GST_DEBUG_OBJECT (demux, "offset was zero, synchronizing with buffer's");
2032 demux->offset = GST_BUFFER_OFFSET (buffer);
2035 if (GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_DISCONT)) {
2036 GST_DEBUG_OBJECT (demux, "Discontinuity");
2037 gst_adapter_clear (demux->adapter);
2040 gst_adapter_push (demux->adapter, buffer);
2042 if (demux->seeking) {
2043 demux->state = FLV_STATE_SEEK;
2044 GST_OBJECT_LOCK (demux);
2045 demux->seeking = FALSE;
2046 GST_OBJECT_UNLOCK (demux);
2050 if (G_UNLIKELY (ret != GST_FLOW_OK)) {
2051 GST_DEBUG_OBJECT (demux, "got flow return %s", gst_flow_get_name (ret));
2055 if (G_UNLIKELY (demux->flushing)) {
2056 GST_DEBUG_OBJECT (demux, "we are now flushing, exiting parser loop");
2057 ret = GST_FLOW_FLUSHING;
2061 switch (demux->state) {
2062 case FLV_STATE_HEADER:
2064 if (gst_adapter_available (demux->adapter) >= FLV_HEADER_SIZE) {
2067 buffer = gst_adapter_take_buffer (demux->adapter, FLV_HEADER_SIZE);
2069 ret = gst_flv_demux_parse_header (demux, buffer);
2071 gst_buffer_unref (buffer);
2072 demux->offset += FLV_HEADER_SIZE;
2074 demux->state = FLV_STATE_TAG_TYPE;
2080 case FLV_STATE_TAG_TYPE:
2082 if (gst_adapter_available (demux->adapter) >= FLV_TAG_TYPE_SIZE) {
2085 /* Remember the tag offset in bytes */
2086 demux->cur_tag_offset = demux->offset;
2088 buffer = gst_adapter_take_buffer (demux->adapter, FLV_TAG_TYPE_SIZE);
2090 ret = gst_flv_demux_parse_tag_type (demux, buffer);
2092 gst_buffer_unref (buffer);
2093 demux->offset += FLV_TAG_TYPE_SIZE;
2095 /* last tag is not an index => no index/don't know where the index is
2096 * seek back to the beginning */
2097 if (demux->seek_event && demux->state != FLV_STATE_TAG_SCRIPT)
2105 case FLV_STATE_TAG_VIDEO:
2107 if (gst_adapter_available (demux->adapter) >= demux->tag_size) {
2110 buffer = gst_adapter_take_buffer (demux->adapter, demux->tag_size);
2112 ret = gst_flv_demux_parse_tag_video (demux, buffer);
2114 gst_buffer_unref (buffer);
2115 demux->offset += demux->tag_size;
2117 demux->state = FLV_STATE_TAG_TYPE;
2123 case FLV_STATE_TAG_AUDIO:
2125 if (gst_adapter_available (demux->adapter) >= demux->tag_size) {
2128 buffer = gst_adapter_take_buffer (demux->adapter, demux->tag_size);
2130 ret = gst_flv_demux_parse_tag_audio (demux, buffer);
2132 gst_buffer_unref (buffer);
2133 demux->offset += demux->tag_size;
2135 demux->state = FLV_STATE_TAG_TYPE;
2141 case FLV_STATE_TAG_SCRIPT:
2143 if (gst_adapter_available (demux->adapter) >= demux->tag_size) {
2146 buffer = gst_adapter_take_buffer (demux->adapter, demux->tag_size);
2148 ret = gst_flv_demux_parse_tag_script (demux, buffer);
2150 gst_buffer_unref (buffer);
2151 demux->offset += demux->tag_size;
2153 demux->state = FLV_STATE_TAG_TYPE;
2155 /* if there's a seek event we're here for the index so if we don't have it
2156 * we seek back to the beginning */
2157 if (demux->seek_event) {
2159 demux->state = FLV_STATE_SEEK;
2169 case FLV_STATE_SEEK:
2175 if (!demux->indexed) {
2176 if (demux->offset == demux->file_size - sizeof (guint32)) {
2177 guint64 seek_offset;
2180 data = gst_adapter_take (demux->adapter, 4);
2184 seek_offset = demux->file_size - sizeof (guint32) -
2185 GST_READ_UINT32_BE (data);
2188 GST_INFO_OBJECT (demux,
2189 "Seeking to beginning of last tag at %" G_GUINT64_FORMAT,
2191 demux->state = FLV_STATE_TAG_TYPE;
2192 flv_demux_seek_to_offset (demux, seek_offset);
2198 GST_OBJECT_LOCK (demux);
2199 event = demux->seek_event;
2200 demux->seek_event = NULL;
2201 GST_OBJECT_UNLOCK (demux);
2203 /* calculate and perform seek */
2204 if (!flv_demux_handle_seek_push (demux, event))
2207 gst_event_unref (event);
2208 demux->state = FLV_STATE_TAG_TYPE;
2211 case FLV_STATE_SKIP:
2212 /* Skip unknown tags (set in _parse_tag_type()) */
2213 if (gst_adapter_available (demux->adapter) >= demux->tag_size) {
2214 gst_adapter_flush (demux->adapter, demux->tag_size);
2215 demux->offset += demux->tag_size;
2216 demux->state = FLV_STATE_TAG_TYPE;
2222 GST_DEBUG_OBJECT (demux, "unexpected demuxer state");
2231 GST_OBJECT_LOCK (demux);
2232 demux->seeking = FALSE;
2233 gst_event_unref (demux->seek_event);
2234 demux->seek_event = NULL;
2235 GST_OBJECT_UNLOCK (demux);
2236 GST_WARNING_OBJECT (demux,
2237 "failed to find an index, seeking back to beginning");
2238 flv_demux_seek_to_offset (demux, 0);
2243 GST_ELEMENT_ERROR (demux, STREAM, DEMUX, (NULL), ("seek failed"));
2244 return GST_FLOW_ERROR;
2249 static GstFlowReturn
2250 gst_flv_demux_pull_range (GstFlvDemux * demux, GstPad * pad, guint64 offset,
2251 guint size, GstBuffer ** buffer)
2255 ret = gst_pad_pull_range (pad, offset, size, buffer);
2256 if (G_UNLIKELY (ret != GST_FLOW_OK)) {
2257 GST_WARNING_OBJECT (demux,
2258 "failed when pulling %d bytes from offset %" G_GUINT64_FORMAT ": %s",
2259 size, offset, gst_flow_get_name (ret));
2264 if (G_UNLIKELY (*buffer && gst_buffer_get_size (*buffer) != size)) {
2265 GST_WARNING_OBJECT (demux,
2266 "partial pull got %" G_GSIZE_FORMAT " when expecting %d from offset %"
2267 G_GUINT64_FORMAT, gst_buffer_get_size (*buffer), size, offset);
2268 gst_buffer_unref (*buffer);
2277 static GstFlowReturn
2278 gst_flv_demux_pull_tag (GstPad * pad, GstFlvDemux * demux)
2280 GstBuffer *buffer = NULL;
2281 GstFlowReturn ret = GST_FLOW_OK;
2283 /* Store tag offset */
2284 demux->cur_tag_offset = demux->offset;
2286 /* Get the first 4 bytes to identify tag type and size */
2287 if (G_UNLIKELY ((ret = gst_flv_demux_pull_range (demux, pad, demux->offset,
2288 FLV_TAG_TYPE_SIZE, &buffer)) != GST_FLOW_OK))
2291 /* Identify tag type */
2292 ret = gst_flv_demux_parse_tag_type (demux, buffer);
2294 gst_buffer_unref (buffer);
2296 if (G_UNLIKELY (ret != GST_FLOW_OK))
2299 /* Jump over tag type + size */
2300 demux->offset += FLV_TAG_TYPE_SIZE;
2302 /* Pull the whole tag */
2304 if (G_UNLIKELY ((ret = gst_flv_demux_pull_range (demux, pad, demux->offset,
2305 demux->tag_size, &buffer)) != GST_FLOW_OK))
2308 switch (demux->state) {
2309 case FLV_STATE_TAG_VIDEO:
2310 ret = gst_flv_demux_parse_tag_video (demux, buffer);
2312 case FLV_STATE_TAG_AUDIO:
2313 ret = gst_flv_demux_parse_tag_audio (demux, buffer);
2315 case FLV_STATE_TAG_SCRIPT:
2316 ret = gst_flv_demux_parse_tag_script (demux, buffer);
2319 GST_WARNING_OBJECT (demux, "unexpected state %d", demux->state);
2322 gst_buffer_unref (buffer);
2324 /* Jump over that part we've just parsed */
2325 demux->offset += demux->tag_size;
2327 /* Make sure we reinitialize the tag size */
2328 demux->tag_size = 0;
2330 /* Ready for the next tag */
2331 demux->state = FLV_STATE_TAG_TYPE;
2333 if (G_UNLIKELY (ret == GST_FLOW_NOT_LINKED)) {
2334 GST_WARNING_OBJECT (demux, "parsing this tag returned not-linked and "
2335 "neither video nor audio are linked");
2342 static GstFlowReturn
2343 gst_flv_demux_pull_header (GstPad * pad, GstFlvDemux * demux)
2345 GstBuffer *buffer = NULL;
2346 GstFlowReturn ret = GST_FLOW_OK;
2348 /* Get the first 9 bytes */
2349 if (G_UNLIKELY ((ret = gst_flv_demux_pull_range (demux, pad, demux->offset,
2350 FLV_HEADER_SIZE, &buffer)) != GST_FLOW_OK))
2353 ret = gst_flv_demux_parse_header (demux, buffer);
2355 gst_buffer_unref (buffer);
2357 /* Jump over the header now */
2358 demux->offset += FLV_HEADER_SIZE;
2359 demux->state = FLV_STATE_TAG_TYPE;
2366 gst_flv_demux_move_to_offset (GstFlvDemux * demux, gint64 offset,
2369 demux->offset = offset;
2371 /* Tell all the stream we moved to a different position (discont) */
2372 demux->audio_need_discont = TRUE;
2373 demux->video_need_discont = TRUE;
2375 /* next section setup */
2376 demux->from_offset = -1;
2377 demux->audio_done = demux->video_done = FALSE;
2378 demux->audio_first_ts = demux->video_first_ts = GST_CLOCK_TIME_NONE;
2381 demux->from_offset = -1;
2382 demux->to_offset = G_MAXINT64;
2385 /* If we seeked at the beginning of the file parse the header again */
2386 if (G_UNLIKELY (!demux->offset)) {
2387 demux->state = FLV_STATE_HEADER;
2388 } else { /* or parse a tag */
2389 demux->state = FLV_STATE_TAG_TYPE;
2393 static GstFlowReturn
2394 gst_flv_demux_seek_to_prev_keyframe (GstFlvDemux * demux)
2396 GstFlowReturn ret = GST_FLOW_EOS;
2398 GstIndexEntry *entry = NULL;
2400 GST_DEBUG_OBJECT (demux,
2401 "terminated section started at offset %" G_GINT64_FORMAT,
2402 demux->from_offset);
2404 /* we are done if we got all audio and video */
2405 if ((!GST_CLOCK_TIME_IS_VALID (demux->audio_first_ts) ||
2406 demux->audio_first_ts < demux->segment.start) &&
2407 (!GST_CLOCK_TIME_IS_VALID (demux->video_first_ts) ||
2408 demux->video_first_ts < demux->segment.start))
2411 if (demux->from_offset <= 0)
2414 GST_DEBUG_OBJECT (demux, "locating previous position");
2416 index = gst_flv_demux_get_index (GST_ELEMENT (demux));
2418 /* locate index entry before previous start position */
2420 entry = gst_index_get_assoc_entry (index, demux->index_id,
2421 GST_INDEX_LOOKUP_BEFORE, GST_ASSOCIATION_FLAG_KEY_UNIT,
2422 GST_FORMAT_BYTES, demux->from_offset - 1);
2425 gint64 bytes = 0, time = 0;
2427 gst_index_entry_assoc_map (entry, GST_FORMAT_BYTES, &bytes);
2428 gst_index_entry_assoc_map (entry, GST_FORMAT_TIME, &time);
2430 GST_DEBUG_OBJECT (demux, "found index entry for %" G_GINT64_FORMAT
2431 " at %" GST_TIME_FORMAT ", seeking to %" G_GINT64_FORMAT,
2432 demux->offset - 1, GST_TIME_ARGS (time), bytes);
2434 /* setup for next section */
2435 demux->to_offset = demux->from_offset;
2436 gst_flv_demux_move_to_offset (demux, bytes, FALSE);
2440 gst_object_unref (index);
2447 static GstFlowReturn
2448 gst_flv_demux_create_index (GstFlvDemux * demux, gint64 pos, GstClockTime ts)
2454 GstClockTime tag_time;
2455 GstFlowReturn ret = GST_FLOW_OK;
2457 if (!gst_pad_peer_query_duration (demux->sinkpad, GST_FORMAT_BYTES, &size))
2460 GST_DEBUG_OBJECT (demux, "building index at %" G_GINT64_FORMAT
2461 " looking for time %" GST_TIME_FORMAT, pos, GST_TIME_ARGS (ts));
2463 old_offset = demux->offset;
2464 demux->offset = pos;
2467 while ((ret = gst_flv_demux_pull_range (demux, demux->sinkpad, demux->offset,
2468 12, &buffer)) == GST_FLOW_OK) {
2470 gst_flv_demux_parse_tag_timestamp (demux, TRUE, buffer, &tag_size);
2472 gst_buffer_unref (buffer);
2475 if (G_UNLIKELY (tag_time == GST_CLOCK_TIME_NONE || tag_time > ts))
2478 demux->offset += tag_size;
2481 if (ret == GST_FLOW_EOS) {
2482 /* file ran out, so mark we have complete index */
2483 demux->indexed = TRUE;
2488 demux->offset = old_offset;
2494 gst_flv_demux_get_metadata (GstFlvDemux * demux)
2496 gint64 ret = 0, offset;
2497 size_t tag_size, size;
2498 GstBuffer *buffer = NULL;
2501 if (!gst_pad_peer_query_duration (demux->sinkpad, GST_FORMAT_BYTES, &offset))
2505 GST_DEBUG_OBJECT (demux, "upstream size: %" G_GINT64_FORMAT, offset);
2506 if (G_UNLIKELY (offset < 4))
2510 if (GST_FLOW_OK != gst_flv_demux_pull_range (demux, demux->sinkpad, offset,
2514 gst_buffer_map (buffer, &map, GST_MAP_READ);
2515 tag_size = GST_READ_UINT32_BE (map.data);
2516 gst_buffer_unmap (buffer, &map);
2517 GST_DEBUG_OBJECT (demux, "last tag size: %" G_GSIZE_FORMAT, tag_size);
2518 gst_buffer_unref (buffer);
2522 if (GST_FLOW_OK != gst_flv_demux_pull_range (demux, demux->sinkpad, offset,
2526 /* a consistency check */
2527 gst_buffer_map (buffer, &map, GST_MAP_READ);
2528 size = GST_READ_UINT24_BE (map.data + 1);
2529 if (size != tag_size - 11) {
2530 gst_buffer_unmap (buffer, &map);
2531 GST_DEBUG_OBJECT (demux,
2532 "tag size %" G_GSIZE_FORMAT ", expected %" G_GSIZE_FORMAT
2533 ", corrupt or truncated file", size, tag_size - 11);
2537 /* try to update duration with timestamp in any case */
2538 gst_flv_demux_parse_tag_timestamp (demux, FALSE, buffer, &size);
2540 /* maybe get some more metadata */
2541 if (map.data[0] == 18) {
2542 gst_buffer_unmap (buffer, &map);
2543 gst_buffer_unref (buffer);
2545 GST_DEBUG_OBJECT (demux, "script tag, pulling it to parse");
2547 if (GST_FLOW_OK == gst_flv_demux_pull_range (demux, demux->sinkpad, offset,
2549 gst_flv_demux_parse_tag_script (demux, buffer);
2551 gst_buffer_unmap (buffer, &map);
2556 gst_buffer_unref (buffer);
2562 gst_flv_demux_loop (GstPad * pad)
2564 GstFlvDemux *demux = NULL;
2565 GstFlowReturn ret = GST_FLOW_OK;
2567 demux = GST_FLV_DEMUX (gst_pad_get_parent (pad));
2570 switch (demux->state) {
2571 case FLV_STATE_TAG_TYPE:
2572 if (demux->from_offset == -1)
2573 demux->from_offset = demux->offset;
2574 ret = gst_flv_demux_pull_tag (pad, demux);
2575 /* if we have seen real data, we probably passed a possible metadata
2576 * header located at start. So if we do not yet have an index,
2577 * try to pick up metadata (index, duration) at the end */
2578 if (G_UNLIKELY (!demux->file_size && !demux->indexed &&
2579 (demux->has_video || demux->has_audio)))
2580 demux->file_size = gst_flv_demux_get_metadata (demux);
2582 case FLV_STATE_DONE:
2585 case FLV_STATE_SEEK:
2586 /* seek issued with insufficient index;
2587 * scan for index in task thread from current maximum offset to
2588 * desired time and then perform seek */
2589 /* TODO maybe some buffering message or so to indicate scan progress */
2590 ret = gst_flv_demux_create_index (demux, demux->index_max_pos,
2592 if (ret != GST_FLOW_OK)
2594 /* position and state arranged by seek,
2595 * also unrefs event */
2596 gst_flv_demux_handle_seek_pull (demux, demux->seek_event, FALSE);
2597 demux->seek_event = NULL;
2600 ret = gst_flv_demux_pull_header (pad, demux);
2601 /* index scans start after header */
2602 demux->index_max_pos = demux->offset;
2606 if (demux->segment.rate < 0.0) {
2607 /* check end of section */
2608 if ((gint64) demux->offset >= demux->to_offset ||
2609 demux->segment.position >= demux->segment.stop + 2 * GST_SECOND ||
2610 (demux->audio_done && demux->video_done))
2611 ret = gst_flv_demux_seek_to_prev_keyframe (demux);
2613 /* check EOS condition */
2614 if ((demux->segment.stop != -1) &&
2615 (demux->segment.position >= demux->segment.stop)) {
2620 /* pause if something went wrong or at end */
2621 if (G_UNLIKELY (ret != GST_FLOW_OK))
2624 gst_object_unref (demux);
2630 const gchar *reason = gst_flow_get_name (ret);
2632 GST_LOG_OBJECT (demux, "pausing task, reason %s", reason);
2633 gst_pad_pause_task (pad);
2635 if (ret == GST_FLOW_EOS) {
2636 /* handle end-of-stream/segment */
2637 /* so align our position with the end of it, if there is one
2638 * this ensures a subsequent will arrive at correct base/acc time */
2639 if (demux->segment.rate > 0.0 &&
2640 GST_CLOCK_TIME_IS_VALID (demux->segment.stop))
2641 demux->segment.position = demux->segment.stop;
2642 else if (demux->segment.rate < 0.0)
2643 demux->segment.position = demux->segment.start;
2645 /* perform EOS logic */
2646 if (!demux->no_more_pads) {
2647 gst_element_no_more_pads (GST_ELEMENT_CAST (demux));
2648 demux->no_more_pads = TRUE;
2651 if (demux->segment.flags & GST_SEGMENT_FLAG_SEGMENT) {
2654 /* for segment playback we need to post when (in stream time)
2655 * we stopped, this is either stop (when set) or the duration. */
2656 if ((stop = demux->segment.stop) == -1)
2657 stop = demux->segment.duration;
2659 if (demux->segment.rate >= 0) {
2660 GST_LOG_OBJECT (demux, "Sending segment done, at end of segment");
2661 gst_element_post_message (GST_ELEMENT_CAST (demux),
2662 gst_message_new_segment_done (GST_OBJECT_CAST (demux),
2663 GST_FORMAT_TIME, stop));
2664 gst_flv_demux_push_src_event (demux,
2665 gst_event_new_segment_done (GST_FORMAT_TIME, stop));
2666 } else { /* Reverse playback */
2667 GST_LOG_OBJECT (demux, "Sending segment done, at beginning of "
2669 gst_element_post_message (GST_ELEMENT_CAST (demux),
2670 gst_message_new_segment_done (GST_OBJECT_CAST (demux),
2671 GST_FORMAT_TIME, demux->segment.start));
2672 gst_flv_demux_push_src_event (demux,
2673 gst_event_new_segment_done (GST_FORMAT_TIME,
2674 demux->segment.start));
2677 /* normal playback, send EOS to all linked pads */
2678 if (!demux->no_more_pads) {
2679 gst_element_no_more_pads (GST_ELEMENT (demux));
2680 demux->no_more_pads = TRUE;
2683 GST_LOG_OBJECT (demux, "Sending EOS, at end of stream");
2684 if (!demux->audio_pad && !demux->video_pad)
2685 GST_ELEMENT_ERROR (demux, STREAM, FAILED,
2686 ("Internal data stream error."), ("Got EOS before any data"));
2687 else if (!gst_flv_demux_push_src_event (demux, gst_event_new_eos ()))
2688 GST_WARNING_OBJECT (demux, "failed pushing EOS on streams");
2690 } else if (ret == GST_FLOW_NOT_LINKED || ret < GST_FLOW_EOS) {
2691 GST_ELEMENT_ERROR (demux, STREAM, FAILED,
2692 ("Internal data stream error."),
2693 ("stream stopped, reason %s", reason));
2694 gst_flv_demux_push_src_event (demux, gst_event_new_eos ());
2696 gst_object_unref (demux);
2702 gst_flv_demux_find_offset (GstFlvDemux * demux, GstSegment * segment,
2703 GstSeekFlags seek_flags)
2708 GstIndexEntry *entry;
2710 g_return_val_if_fail (segment != NULL, 0);
2712 time = segment->position;
2714 index = gst_flv_demux_get_index (GST_ELEMENT (demux));
2717 /* Let's check if we have an index entry for that seek time */
2718 entry = gst_index_get_assoc_entry (index, demux->index_id,
2719 seek_flags & GST_SEEK_FLAG_SNAP_AFTER ?
2720 GST_INDEX_LOOKUP_AFTER : GST_INDEX_LOOKUP_BEFORE,
2721 GST_ASSOCIATION_FLAG_KEY_UNIT, GST_FORMAT_TIME, time);
2724 gst_index_entry_assoc_map (entry, GST_FORMAT_BYTES, &bytes);
2725 gst_index_entry_assoc_map (entry, GST_FORMAT_TIME, &time);
2727 GST_DEBUG_OBJECT (demux, "found index entry for %" GST_TIME_FORMAT
2728 " at %" GST_TIME_FORMAT ", seeking to %" G_GINT64_FORMAT,
2729 GST_TIME_ARGS (segment->position), GST_TIME_ARGS (time), bytes);
2731 /* Key frame seeking */
2732 if (seek_flags & GST_SEEK_FLAG_KEY_UNIT) {
2733 /* Adjust the segment so that the keyframe fits in */
2734 segment->start = segment->time = time;
2735 segment->position = time;
2738 GST_DEBUG_OBJECT (demux, "no index entry found for %" GST_TIME_FORMAT,
2739 GST_TIME_ARGS (segment->start));
2742 gst_object_unref (index);
2749 flv_demux_handle_seek_push (GstFlvDemux * demux, GstEvent * event)
2753 GstSeekType start_type, stop_type;
2756 gboolean update, flush, ret;
2757 GstSegment seeksegment;
2759 gst_event_parse_seek (event, &rate, &format, &flags,
2760 &start_type, &start, &stop_type, &stop);
2762 if (format != GST_FORMAT_TIME)
2765 flush = ! !(flags & GST_SEEK_FLAG_FLUSH);
2767 /* Work on a copy until we are sure the seek succeeded. */
2768 memcpy (&seeksegment, &demux->segment, sizeof (GstSegment));
2770 GST_DEBUG_OBJECT (demux, "segment before configure %" GST_SEGMENT_FORMAT,
2773 /* Apply the seek to our segment */
2774 gst_segment_do_seek (&seeksegment, rate, format, flags,
2775 start_type, start, stop_type, stop, &update);
2777 GST_DEBUG_OBJECT (demux, "segment configured %" GST_SEGMENT_FORMAT,
2780 if (flush || seeksegment.position != demux->segment.position) {
2781 /* Do the actual seeking */
2782 guint64 offset = gst_flv_demux_find_offset (demux, &seeksegment, flags);
2784 GST_DEBUG_OBJECT (demux, "generating an upstream seek at position %"
2785 G_GUINT64_FORMAT, offset);
2786 ret = gst_pad_push_event (demux->sinkpad,
2787 gst_event_new_seek (seeksegment.rate, GST_FORMAT_BYTES,
2788 flags | GST_SEEK_FLAG_ACCURATE, GST_SEEK_TYPE_SET,
2789 offset, GST_SEEK_TYPE_NONE, 0));
2790 if (G_UNLIKELY (!ret)) {
2791 GST_WARNING_OBJECT (demux, "upstream seek failed");
2794 gst_flow_combiner_reset (demux->flowcombiner);
2795 /* Tell all the stream we moved to a different position (discont) */
2796 demux->audio_need_discont = TRUE;
2797 demux->video_need_discont = TRUE;
2803 /* Ok seek succeeded, take the newly configured segment */
2804 memcpy (&demux->segment, &seeksegment, sizeof (GstSegment));
2806 /* Tell all the stream a new segment is needed */
2807 demux->audio_need_segment = TRUE;
2808 demux->video_need_segment = TRUE;
2809 /* Clean any potential newsegment event kept for the streams. The first
2810 * stream needing a new segment will create a new one. */
2811 if (G_UNLIKELY (demux->new_seg_event)) {
2812 gst_event_unref (demux->new_seg_event);
2813 demux->new_seg_event = NULL;
2815 GST_DEBUG_OBJECT (demux, "preparing newsegment from %"
2816 GST_TIME_FORMAT " to %" GST_TIME_FORMAT,
2817 GST_TIME_ARGS (demux->segment.start),
2818 GST_TIME_ARGS (demux->segment.stop));
2819 demux->new_seg_event = gst_event_new_segment (&demux->segment);
2820 gst_event_unref (event);
2822 ret = gst_pad_push_event (demux->sinkpad, event);
2830 GST_WARNING_OBJECT (demux, "we only support seeking in TIME format");
2831 gst_event_unref (event);
2837 gst_flv_demux_handle_seek_push (GstFlvDemux * demux, GstEvent * event)
2841 gst_event_parse_seek (event, NULL, &format, NULL, NULL, NULL, NULL, NULL);
2843 if (format != GST_FORMAT_TIME) {
2844 GST_WARNING_OBJECT (demux, "we only support seeking in TIME format");
2845 gst_event_unref (event);
2849 /* First try upstream */
2850 if (gst_pad_push_event (demux->sinkpad, gst_event_ref (event))) {
2851 GST_DEBUG_OBJECT (demux, "Upstream successfully seeked");
2852 gst_event_unref (event);
2856 if (!demux->indexed) {
2857 guint64 seek_offset = 0;
2858 gboolean building_index;
2860 GST_OBJECT_LOCK (demux);
2861 /* handle the seek in the chain function */
2862 demux->seeking = TRUE;
2863 demux->state = FLV_STATE_SEEK;
2865 /* copy the event */
2866 if (demux->seek_event)
2867 gst_event_unref (demux->seek_event);
2868 demux->seek_event = gst_event_ref (event);
2870 /* set the building_index flag so that only one thread can setup the
2871 * structures for index seeking. */
2872 building_index = demux->building_index;
2873 if (!building_index) {
2874 demux->building_index = TRUE;
2875 if (!demux->file_size
2876 && !gst_pad_peer_query_duration (demux->sinkpad, GST_FORMAT_BYTES,
2877 &demux->file_size)) {
2878 GST_WARNING_OBJECT (demux, "Failed to query upstream file size");
2879 GST_OBJECT_UNLOCK (demux);
2883 /* we hope the last tag is a scriptdataobject containing an index
2884 * the size of the last tag is given in the last guint32 bits
2885 * then we seek to the beginning of the tag, parse it and hopefully obtain an index */
2886 seek_offset = demux->file_size - sizeof (guint32);
2887 GST_DEBUG_OBJECT (demux,
2888 "File size obtained, seeking to %" G_GUINT64_FORMAT, seek_offset);
2890 GST_OBJECT_UNLOCK (demux);
2892 if (!building_index) {
2893 GST_INFO_OBJECT (demux, "Seeking to last 4 bytes at %" G_GUINT64_FORMAT,
2895 return flv_demux_seek_to_offset (demux, seek_offset);
2898 /* FIXME: we have to always return true so that we don't block the seek
2900 * Note: maybe it is OK to return true if we're still building the index */
2904 return flv_demux_handle_seek_push (demux, event);
2908 gst_flv_demux_handle_seek_pull (GstFlvDemux * demux, GstEvent * event,
2913 GstSeekType start_type, stop_type;
2916 gboolean update, flush, ret = FALSE;
2917 GstSegment seeksegment;
2919 gst_event_parse_seek (event, &rate, &format, &flags,
2920 &start_type, &start, &stop_type, &stop);
2922 if (format != GST_FORMAT_TIME)
2925 /* mark seeking thread entering flushing/pausing */
2926 GST_OBJECT_LOCK (demux);
2928 demux->seeking = seeking;
2929 GST_OBJECT_UNLOCK (demux);
2931 flush = ! !(flags & GST_SEEK_FLAG_FLUSH);
2934 /* Flush start up and downstream to make sure data flow and loops are
2936 gst_flv_demux_push_src_event (demux, gst_event_new_flush_start ());
2937 gst_pad_push_event (demux->sinkpad, gst_event_new_flush_start ());
2939 /* Pause the pulling task */
2940 gst_pad_pause_task (demux->sinkpad);
2943 /* Take the stream lock */
2944 GST_PAD_STREAM_LOCK (demux->sinkpad);
2947 /* Stop flushing upstream we need to pull */
2948 gst_pad_push_event (demux->sinkpad, gst_event_new_flush_stop (TRUE));
2951 /* Work on a copy until we are sure the seek succeeded. */
2952 memcpy (&seeksegment, &demux->segment, sizeof (GstSegment));
2954 GST_DEBUG_OBJECT (demux, "segment before configure %" GST_SEGMENT_FORMAT,
2957 /* Apply the seek to our segment */
2958 gst_segment_do_seek (&seeksegment, rate, format, flags,
2959 start_type, start, stop_type, stop, &update);
2961 GST_DEBUG_OBJECT (demux, "segment configured %" GST_SEGMENT_FORMAT,
2964 if (flush || seeksegment.position != demux->segment.position) {
2965 /* Do the actual seeking */
2966 /* index is reliable if it is complete or we do not go to far ahead */
2967 if (seeking && !demux->indexed &&
2968 seeksegment.position > demux->index_max_time + 10 * GST_SECOND) {
2969 GST_DEBUG_OBJECT (demux, "delaying seek to post-scan; "
2970 " index only up to %" GST_TIME_FORMAT,
2971 GST_TIME_ARGS (demux->index_max_time));
2972 /* stop flushing for now */
2974 gst_flv_demux_push_src_event (demux, gst_event_new_flush_stop (TRUE));
2975 /* delegate scanning and index building to task thread to avoid
2976 * occupying main (UI) loop */
2977 if (demux->seek_event)
2978 gst_event_unref (demux->seek_event);
2979 demux->seek_event = gst_event_ref (event);
2980 demux->seek_time = seeksegment.position;
2981 demux->state = FLV_STATE_SEEK;
2982 /* do not know about succes yet, but we did care and handled it */
2987 /* now index should be as reliable as it can be for current purpose */
2988 gst_flv_demux_move_to_offset (demux,
2989 gst_flv_demux_find_offset (demux, &seeksegment, flags), TRUE);
2996 /* Stop flushing, the sinks are at time 0 now */
2997 gst_flv_demux_push_src_event (demux, gst_event_new_flush_stop (TRUE));
3001 /* Ok seek succeeded, take the newly configured segment */
3002 memcpy (&demux->segment, &seeksegment, sizeof (GstSegment));
3004 /* Notify about the start of a new segment */
3005 if (demux->segment.flags & GST_SEGMENT_FLAG_SEGMENT) {
3006 gst_element_post_message (GST_ELEMENT (demux),
3007 gst_message_new_segment_start (GST_OBJECT (demux),
3008 demux->segment.format, demux->segment.position));
3011 gst_flow_combiner_reset (demux->flowcombiner);
3012 /* Tell all the stream a new segment is needed */
3013 demux->audio_need_segment = TRUE;
3014 demux->video_need_segment = TRUE;
3015 /* Clean any potential newsegment event kept for the streams. The first
3016 * stream needing a new segment will create a new one. */
3017 if (G_UNLIKELY (demux->new_seg_event)) {
3018 gst_event_unref (demux->new_seg_event);
3019 demux->new_seg_event = NULL;
3021 GST_DEBUG_OBJECT (demux, "preparing newsegment from %"
3022 GST_TIME_FORMAT " to %" GST_TIME_FORMAT,
3023 GST_TIME_ARGS (demux->segment.start),
3024 GST_TIME_ARGS (demux->segment.stop));
3025 demux->new_seg_event = gst_event_new_segment (&demux->segment);
3029 GST_OBJECT_LOCK (demux);
3030 seeking = demux->seeking && !seeking;
3031 demux->seeking = FALSE;
3032 GST_OBJECT_UNLOCK (demux);
3034 /* if we detect an external seek having started (and possibly already having
3035 * flushed), do not restart task to give it a chance.
3036 * Otherwise external one's flushing will take care to pause task */
3038 gst_pad_pause_task (demux->sinkpad);
3040 gst_pad_start_task (demux->sinkpad,
3041 (GstTaskFunction) gst_flv_demux_loop, demux->sinkpad, NULL);
3044 GST_PAD_STREAM_UNLOCK (demux->sinkpad);
3046 gst_event_unref (event);
3052 GST_WARNING_OBJECT (demux, "we only support seeking in TIME format");
3053 gst_event_unref (event);
3058 /* If we can pull that's prefered */
3060 gst_flv_demux_sink_activate (GstPad * sinkpad, GstObject * parent)
3065 query = gst_query_new_scheduling ();
3067 if (!gst_pad_peer_query (sinkpad, query)) {
3068 gst_query_unref (query);
3072 pull_mode = gst_query_has_scheduling_mode_with_flags (query,
3073 GST_PAD_MODE_PULL, GST_SCHEDULING_FLAG_SEEKABLE);
3074 gst_query_unref (query);
3079 GST_DEBUG_OBJECT (sinkpad, "activating pull");
3080 return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PULL, TRUE);
3084 GST_DEBUG_OBJECT (sinkpad, "activating push");
3085 return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PUSH, TRUE);
3090 gst_flv_demux_sink_activate_mode (GstPad * sinkpad, GstObject * parent,
3091 GstPadMode mode, gboolean active)
3096 demux = GST_FLV_DEMUX (parent);
3099 case GST_PAD_MODE_PUSH:
3100 demux->random_access = FALSE;
3103 case GST_PAD_MODE_PULL:
3105 demux->random_access = TRUE;
3106 res = gst_pad_start_task (sinkpad, (GstTaskFunction) gst_flv_demux_loop,
3109 demux->random_access = FALSE;
3110 res = gst_pad_stop_task (sinkpad);
3121 gst_flv_demux_sink_event (GstPad * pad, GstObject * parent, GstEvent * event)
3124 gboolean ret = FALSE;
3126 demux = GST_FLV_DEMUX (parent);
3128 GST_DEBUG_OBJECT (demux, "handling event %s", GST_EVENT_TYPE_NAME (event));
3130 switch (GST_EVENT_TYPE (event)) {
3131 case GST_EVENT_FLUSH_START:
3132 GST_DEBUG_OBJECT (demux, "trying to force chain function to exit");
3133 demux->flushing = TRUE;
3134 ret = gst_flv_demux_push_src_event (demux, event);
3136 case GST_EVENT_FLUSH_STOP:
3137 GST_DEBUG_OBJECT (demux, "flushing FLV demuxer");
3138 gst_flv_demux_flush (demux, TRUE);
3139 ret = gst_flv_demux_push_src_event (demux, event);
3145 GST_DEBUG_OBJECT (demux, "received EOS");
3147 index = gst_flv_demux_get_index (GST_ELEMENT (demux));
3150 GST_DEBUG_OBJECT (demux, "committing index");
3151 gst_index_commit (index, demux->index_id);
3152 gst_object_unref (index);
3155 if (!demux->audio_pad && !demux->video_pad) {
3156 GST_ELEMENT_ERROR (demux, STREAM, FAILED,
3157 ("Internal data stream error."), ("Got EOS before any data"));
3158 gst_event_unref (event);
3160 if (!demux->no_more_pads) {
3161 gst_element_no_more_pads (GST_ELEMENT (demux));
3162 demux->no_more_pads = TRUE;
3165 if (!gst_flv_demux_push_src_event (demux, event))
3166 GST_WARNING_OBJECT (demux, "failed pushing EOS on streams");
3171 case GST_EVENT_SEGMENT:
3173 GstSegment in_segment;
3175 GST_DEBUG_OBJECT (demux, "received new segment");
3177 gst_event_copy_segment (event, &in_segment);
3179 if (in_segment.format == GST_FORMAT_TIME) {
3180 /* time segment, this is perfect, copy over the values. */
3181 memcpy (&demux->segment, &in_segment, sizeof (in_segment));
3183 GST_DEBUG_OBJECT (demux, "NEWSEGMENT: %" GST_SEGMENT_FORMAT,
3187 ret = gst_flv_demux_push_src_event (demux, event);
3189 /* non-time format */
3190 demux->audio_need_segment = TRUE;
3191 demux->video_need_segment = TRUE;
3193 gst_event_unref (event);
3194 if (demux->new_seg_event) {
3195 gst_event_unref (demux->new_seg_event);
3196 demux->new_seg_event = NULL;
3199 gst_flow_combiner_reset (demux->flowcombiner);
3203 ret = gst_pad_event_default (pad, parent, event);
3211 gst_flv_demux_src_event (GstPad * pad, GstObject * parent, GstEvent * event)
3214 gboolean ret = FALSE;
3216 demux = GST_FLV_DEMUX (parent);
3218 GST_DEBUG_OBJECT (demux, "handling event %s", GST_EVENT_TYPE_NAME (event));
3220 switch (GST_EVENT_TYPE (event)) {
3221 case GST_EVENT_SEEK:
3222 /* Try to push upstream first */
3223 gst_event_ref (event);
3224 ret = gst_pad_push_event (demux->sinkpad, event);
3226 gst_event_unref (event);
3229 if (demux->random_access) {
3230 ret = gst_flv_demux_handle_seek_pull (demux, event, TRUE);
3232 ret = gst_flv_demux_handle_seek_push (demux, event);
3236 ret = gst_pad_push_event (demux->sinkpad, event);
3244 gst_flv_demux_query (GstPad * pad, GstObject * parent, GstQuery * query)
3246 gboolean res = TRUE;
3249 demux = GST_FLV_DEMUX (parent);
3251 switch (GST_QUERY_TYPE (query)) {
3252 case GST_QUERY_DURATION:
3256 gst_query_parse_duration (query, &format, NULL);
3258 /* duration is time only */
3259 if (format != GST_FORMAT_TIME) {
3260 GST_DEBUG_OBJECT (demux, "duration query only supported for time "
3266 /* Try to push upstream first */
3267 res = gst_pad_peer_query (demux->sinkpad, query);
3271 GST_DEBUG_OBJECT (pad, "duration query, replying %" GST_TIME_FORMAT,
3272 GST_TIME_ARGS (demux->duration));
3274 gst_query_set_duration (query, GST_FORMAT_TIME, demux->duration);
3278 case GST_QUERY_POSITION:
3282 gst_query_parse_position (query, &format, NULL);
3284 /* position is time only */
3285 if (format != GST_FORMAT_TIME) {
3286 GST_DEBUG_OBJECT (demux, "position query only supported for time "
3292 GST_DEBUG_OBJECT (pad, "position query, replying %" GST_TIME_FORMAT,
3293 GST_TIME_ARGS (demux->segment.position));
3295 gst_query_set_position (query, GST_FORMAT_TIME, demux->segment.position);
3300 case GST_QUERY_SEEKING:{
3303 gst_query_parse_seeking (query, &fmt, NULL, NULL, NULL);
3305 /* First ask upstream */
3306 if (fmt == GST_FORMAT_TIME && gst_pad_peer_query (demux->sinkpad, query)) {
3309 gst_query_parse_seeking (query, NULL, &seekable, NULL, NULL);
3316 /* FIXME, check index this way is not thread safe */
3317 if (fmt != GST_FORMAT_TIME || !demux->index) {
3318 gst_query_set_seeking (query, fmt, FALSE, -1, -1);
3319 } else if (demux->random_access) {
3320 gst_query_set_seeking (query, GST_FORMAT_TIME, TRUE, 0,
3323 GstQuery *peerquery = gst_query_new_seeking (GST_FORMAT_BYTES);
3324 gboolean seekable = gst_pad_peer_query (demux->sinkpad, peerquery);
3327 gst_query_parse_seeking (peerquery, NULL, &seekable, NULL, NULL);
3328 gst_query_unref (peerquery);
3331 gst_query_set_seeking (query, GST_FORMAT_TIME, seekable, 0,
3334 gst_query_set_seeking (query, GST_FORMAT_TIME, FALSE, -1, -1);
3338 case GST_QUERY_SEGMENT:
3343 format = demux->segment.format;
3346 gst_segment_to_stream_time (&demux->segment, format,
3347 demux->segment.start);
3348 if ((stop = demux->segment.stop) == -1)
3349 stop = demux->segment.duration;
3351 stop = gst_segment_to_stream_time (&demux->segment, format, stop);
3353 gst_query_set_segment (query, demux->segment.rate, format, start, stop);
3357 case GST_QUERY_LATENCY:
3359 res = gst_pad_query_default (pad, parent, query);
3368 static GstStateChangeReturn
3369 gst_flv_demux_change_state (GstElement * element, GstStateChange transition)
3372 GstStateChangeReturn ret;
3374 demux = GST_FLV_DEMUX (element);
3376 switch (transition) {
3377 case GST_STATE_CHANGE_READY_TO_PAUSED:
3378 /* If this is our own index destroy it as the
3379 * old entries might be wrong for the new stream */
3380 if (demux->own_index) {
3381 gst_object_unref (demux->index);
3382 demux->index = NULL;
3383 demux->own_index = FALSE;
3386 /* If no index was created, generate one */
3387 if (G_UNLIKELY (!demux->index)) {
3388 GST_DEBUG_OBJECT (demux, "no index provided creating our own");
3390 demux->index = g_object_new (gst_mem_index_get_type (), NULL);
3392 gst_index_get_writer_id (demux->index, GST_OBJECT (demux),
3394 demux->own_index = TRUE;
3396 gst_flv_demux_cleanup (demux);
3402 ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
3403 if (ret == GST_STATE_CHANGE_FAILURE)
3406 switch (transition) {
3407 case GST_STATE_CHANGE_PAUSED_TO_READY:
3408 gst_flv_demux_cleanup (demux);
3419 gst_flv_demux_set_index (GstElement * element, GstIndex * index)
3421 GstFlvDemux *demux = GST_FLV_DEMUX (element);
3422 GstIndex *old_index;
3424 GST_OBJECT_LOCK (demux);
3426 old_index = demux->index;
3429 demux->index = gst_object_ref (index);
3430 demux->own_index = FALSE;
3432 demux->index = NULL;
3435 gst_object_unref (demux->index);
3437 gst_object_ref (index);
3439 GST_OBJECT_UNLOCK (demux);
3441 /* object lock might be taken again */
3443 gst_index_get_writer_id (index, GST_OBJECT (element), &demux->index_id);
3445 GST_DEBUG_OBJECT (demux, "Set index %" GST_PTR_FORMAT, demux->index);
3447 gst_object_unref (index);
3452 gst_flv_demux_get_index (GstElement * element)
3454 GstIndex *result = NULL;
3456 GstFlvDemux *demux = GST_FLV_DEMUX (element);
3458 GST_OBJECT_LOCK (demux);
3460 result = gst_object_ref (demux->index);
3461 GST_OBJECT_UNLOCK (demux);
3467 gst_flv_demux_dispose (GObject * object)
3469 GstFlvDemux *demux = GST_FLV_DEMUX (object);
3471 GST_DEBUG_OBJECT (demux, "disposing FLV demuxer");
3473 if (demux->adapter) {
3474 gst_adapter_clear (demux->adapter);
3475 g_object_unref (demux->adapter);
3476 demux->adapter = NULL;
3479 if (demux->taglist) {
3480 gst_tag_list_unref (demux->taglist);
3481 demux->taglist = NULL;
3484 if (demux->flowcombiner) {
3485 gst_flow_combiner_free (demux->flowcombiner);
3486 demux->flowcombiner = NULL;
3489 if (demux->new_seg_event) {
3490 gst_event_unref (demux->new_seg_event);
3491 demux->new_seg_event = NULL;
3494 if (demux->audio_codec_data) {
3495 gst_buffer_unref (demux->audio_codec_data);
3496 demux->audio_codec_data = NULL;
3499 if (demux->video_codec_data) {
3500 gst_buffer_unref (demux->video_codec_data);
3501 demux->video_codec_data = NULL;
3504 if (demux->audio_pad) {
3505 gst_object_unref (demux->audio_pad);
3506 demux->audio_pad = NULL;
3509 if (demux->video_pad) {
3510 gst_object_unref (demux->video_pad);
3511 demux->video_pad = NULL;
3515 gst_object_unref (demux->index);
3516 demux->index = NULL;
3520 g_array_free (demux->times, TRUE);
3521 demux->times = NULL;
3524 if (demux->filepositions) {
3525 g_array_free (demux->filepositions, TRUE);
3526 demux->filepositions = NULL;
3529 GST_CALL_PARENT (G_OBJECT_CLASS, dispose, (object));
3533 gst_flv_demux_class_init (GstFlvDemuxClass * klass)
3535 GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass);
3536 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
3538 gobject_class->dispose = gst_flv_demux_dispose;
3540 gstelement_class->change_state =
3541 GST_DEBUG_FUNCPTR (gst_flv_demux_change_state);
3544 gstelement_class->set_index = GST_DEBUG_FUNCPTR (gst_flv_demux_set_index);
3545 gstelement_class->get_index = GST_DEBUG_FUNCPTR (gst_flv_demux_get_index);
3548 gst_element_class_add_static_pad_template (gstelement_class,
3549 &flv_sink_template);
3550 gst_element_class_add_static_pad_template (gstelement_class,
3551 &audio_src_template);
3552 gst_element_class_add_static_pad_template (gstelement_class,
3553 &video_src_template);
3554 gst_element_class_set_static_metadata (gstelement_class, "FLV Demuxer",
3555 "Codec/Demuxer", "Demux FLV feeds into digital streams",
3556 "Julien Moutte <julien@moutte.net>");
3560 gst_flv_demux_init (GstFlvDemux * demux)
3563 gst_pad_new_from_static_template (&flv_sink_template, "sink");
3565 gst_pad_set_event_function (demux->sinkpad,
3566 GST_DEBUG_FUNCPTR (gst_flv_demux_sink_event));
3567 gst_pad_set_chain_function (demux->sinkpad,
3568 GST_DEBUG_FUNCPTR (gst_flv_demux_chain));
3569 gst_pad_set_activate_function (demux->sinkpad,
3570 GST_DEBUG_FUNCPTR (gst_flv_demux_sink_activate));
3571 gst_pad_set_activatemode_function (demux->sinkpad,
3572 GST_DEBUG_FUNCPTR (gst_flv_demux_sink_activate_mode));
3574 gst_element_add_pad (GST_ELEMENT (demux), demux->sinkpad);
3576 demux->adapter = gst_adapter_new ();
3577 demux->taglist = gst_tag_list_new_empty ();
3578 demux->flowcombiner = gst_flow_combiner_new ();
3579 gst_segment_init (&demux->segment, GST_FORMAT_TIME);
3581 demux->own_index = FALSE;
3583 GST_OBJECT_FLAG_SET (demux, GST_ELEMENT_FLAG_INDEXABLE);
3585 gst_flv_demux_cleanup (demux);
3589 plugin_init (GstPlugin * plugin)
3591 GST_DEBUG_CATEGORY_INIT (flvdemux_debug, "flvdemux", 0, "FLV demuxer");
3593 if (!gst_element_register (plugin, "flvdemux", GST_RANK_PRIMARY,
3594 gst_flv_demux_get_type ()) ||
3595 !gst_element_register (plugin, "flvmux", GST_RANK_PRIMARY,
3596 gst_flv_mux_get_type ()))
3602 GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, GST_VERSION_MINOR,
3603 flv, "FLV muxing and demuxing plugin",
3604 plugin_init, VERSION, "LGPL", GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN)