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;
260 gint year = -1, month = -1, day = -1;
261 gint hour = -1, minute = -1, seconds = -1;
263 /* "Fri Oct 15 15:13:16 2004" needs to be parsed */
264 tokens = g_strsplit (s, " ", -1);
266 if (g_strv_length (tokens) != 5)
270 d = g_ascii_strtoull (tokens[4], &endptr, 10);
271 if (d == 0 && *endptr != '\0')
277 if (strlen (tokens[1]) != 3)
279 for (i = 0; i < 12; i++) {
280 if (!strcmp (tokens[1], months[i])) {
290 d = g_ascii_strtoull (tokens[2], &endptr, 10);
291 if (d == 0 && *endptr != '\0')
298 if (sscanf (tokens[3], "%d:%d:%d", &hh, &mm, &ss) < 2)
300 if (hh >= 0 && hh < 24 && mm >= 0 && mm < 60 && ss >= 0 && ss < 60) {
312 dt = gst_date_time_new (0.0, year, month, day, hour, minute, seconds);
318 gst_flv_demux_parse_metadata_item (GstFlvDemux * demux, GstByteReader * reader,
319 gboolean * end_marker)
321 gchar *tag_name = NULL;
324 /* Initialize the end_marker flag to FALSE */
327 /* Name of the tag */
328 tag_name = FLV_GET_STRING (reader);
329 if (G_UNLIKELY (!tag_name)) {
330 GST_WARNING_OBJECT (demux, "failed reading tag name");
334 /* What kind of object is that */
335 if (!gst_byte_reader_get_uint8 (reader, &tag_type))
338 GST_DEBUG_OBJECT (demux, "tag name %s, tag type %d", tag_name, tag_type);
342 { /* Use a union to read the uint64 and then as a double */
345 if (!gst_byte_reader_get_float64_be (reader, &d))
348 GST_DEBUG_OBJECT (demux, "%s => (double) %f", tag_name, d);
350 if (!strcmp (tag_name, "duration")) {
351 demux->duration = d * GST_SECOND;
353 gst_tag_list_add (demux->taglist, GST_TAG_MERGE_REPLACE,
354 GST_TAG_DURATION, demux->duration, NULL);
355 } else if (!strcmp (tag_name, "AspectRatioX")) {
357 demux->got_par = TRUE;
358 } else if (!strcmp (tag_name, "AspectRatioY")) {
360 demux->got_par = TRUE;
361 } else if (!strcmp (tag_name, "width")) {
363 } else if (!strcmp (tag_name, "height")) {
365 } else if (!strcmp (tag_name, "framerate")) {
366 demux->framerate = d;
368 GST_INFO_OBJECT (demux, "Tag \'%s\' not handled", tag_name);
373 case 1: /* Boolean */
377 if (!gst_byte_reader_get_uint8 (reader, &b))
380 GST_DEBUG_OBJECT (demux, "%s => (boolean) %d", tag_name, b);
382 GST_INFO_OBJECT (demux, "Tag \'%s\' not handled", tag_name);
390 s = FLV_GET_STRING (reader);
394 GST_DEBUG_OBJECT (demux, "%s => (string) %s", tag_name, s);
396 if (!strcmp (tag_name, "creationdate")) {
399 dt = parse_flv_demux_parse_date_string (s);
401 GST_DEBUG_OBJECT (demux, "Failed to parse '%s' into datetime", s);
403 gst_tag_list_add (demux->taglist, GST_TAG_MERGE_REPLACE,
404 GST_TAG_DATE_TIME, dt, NULL);
406 gst_date_time_unref (dt);
407 } else if (!strcmp (tag_name, "creator")) {
408 gst_tag_list_add (demux->taglist, GST_TAG_MERGE_REPLACE,
409 GST_TAG_ARTIST, s, NULL);
410 } else if (!strcmp (tag_name, "title")) {
411 gst_tag_list_add (demux->taglist, GST_TAG_MERGE_REPLACE,
412 GST_TAG_TITLE, s, NULL);
413 } else if (!strcmp (tag_name, "metadatacreator")) {
414 gst_tag_list_add (demux->taglist, GST_TAG_MERGE_REPLACE,
415 GST_TAG_ENCODER, s, NULL);
417 GST_INFO_OBJECT (demux, "Tag \'%s\' not handled", tag_name);
426 gboolean end_of_object_marker = FALSE;
428 while (!end_of_object_marker) {
429 gboolean ok = gst_flv_demux_parse_metadata_item (demux, reader,
430 &end_of_object_marker);
432 if (G_UNLIKELY (!ok)) {
433 GST_WARNING_OBJECT (demux, "failed reading a tag, skipping");
440 case 8: /* ECMA array */
442 guint32 nb_elems = 0;
443 gboolean end_of_object_marker = FALSE;
445 if (!gst_byte_reader_get_uint32_be (reader, &nb_elems))
448 GST_DEBUG_OBJECT (demux, "there are approx. %d elements in the array",
451 while (!end_of_object_marker) {
452 gboolean ok = gst_flv_demux_parse_metadata_item (demux, reader,
453 &end_of_object_marker);
455 if (G_UNLIKELY (!ok)) {
456 GST_WARNING_OBJECT (demux, "failed reading a tag, skipping");
463 case 9: /* End marker */
465 GST_DEBUG_OBJECT (demux, "end marker ?");
466 if (tag_name[0] == '\0') {
468 GST_DEBUG_OBJECT (demux, "end marker detected");
477 guint32 nb_elems = 0;
479 if (!gst_byte_reader_get_uint32_be (reader, &nb_elems))
482 GST_DEBUG_OBJECT (demux, "array has %d elements", nb_elems);
484 if (!strcmp (tag_name, "times")) {
486 g_array_free (demux->times, TRUE);
488 demux->times = g_array_new (FALSE, TRUE, sizeof (gdouble));
489 } else if (!strcmp (tag_name, "filepositions")) {
490 if (demux->filepositions) {
491 g_array_free (demux->filepositions, TRUE);
493 demux->filepositions = g_array_new (FALSE, TRUE, sizeof (gdouble));
497 guint8 elem_type = 0;
499 if (!gst_byte_reader_get_uint8 (reader, &elem_type))
507 if (!gst_byte_reader_get_float64_be (reader, &d))
510 GST_DEBUG_OBJECT (demux, "element is a double %f", d);
512 if (!strcmp (tag_name, "times") && demux->times) {
513 g_array_append_val (demux->times, d);
514 } else if (!strcmp (tag_name, "filepositions") &&
515 demux->filepositions) {
516 g_array_append_val (demux->filepositions, d);
521 GST_WARNING_OBJECT (demux, "unsupported array element type %d",
533 if (!gst_byte_reader_get_float64_be (reader, &d))
536 if (!gst_byte_reader_get_int16_be (reader, &i))
539 GST_DEBUG_OBJECT (demux,
540 "%s => (date as a double) %f, timezone offset %d", tag_name, d, i);
542 GST_INFO_OBJECT (demux, "Tag \'%s\' not handled", tag_name);
547 GST_WARNING_OBJECT (demux, "unsupported tag type %d", tag_type);
561 gst_flv_demux_parse_tag_script (GstFlvDemux * demux, GstBuffer * buffer)
563 GstFlowReturn ret = GST_FLOW_OK;
564 GstByteReader reader;
568 g_return_val_if_fail (gst_buffer_get_size (buffer) >= 7, GST_FLOW_ERROR);
570 gst_buffer_map (buffer, &map, GST_MAP_READ);
571 gst_byte_reader_init (&reader, map.data, map.size);
573 gst_byte_reader_skip_unchecked (&reader, 7);
575 GST_LOG_OBJECT (demux, "parsing a script tag");
577 if (!gst_byte_reader_get_uint8 (&reader, &type))
582 gchar *function_name;
585 function_name = FLV_GET_STRING (&reader);
587 GST_LOG_OBJECT (demux, "function name is %s", GST_STR_NULL (function_name));
589 if (function_name != NULL && strcmp (function_name, "onMetaData") == 0) {
590 gboolean end_marker = FALSE;
591 GST_DEBUG_OBJECT (demux, "we have a metadata script object");
593 if (!gst_byte_reader_get_uint8 (&reader, &type)) {
594 g_free (function_name);
601 guint32 nb_elems = 0;
604 if (!gst_byte_reader_get_uint32_be (&reader, &nb_elems)) {
605 g_free (function_name);
609 /* The number of elements is just a hint, some files have
610 nb_elements == 0 and actually contain items. */
611 GST_DEBUG_OBJECT (demux, "there are approx. %d elements in the array",
614 /* fallthrough to read data */
618 while (!end_marker) {
620 gst_flv_demux_parse_metadata_item (demux, &reader, &end_marker);
622 if (G_UNLIKELY (!ok)) {
623 GST_WARNING_OBJECT (demux, "failed reading a tag, skipping");
630 GST_DEBUG_OBJECT (demux, "Unhandled script data type : %d", type);
631 g_free (function_name);
635 demux->push_tags = TRUE;
638 g_free (function_name);
640 if (demux->times && demux->filepositions) {
643 /* If an index was found, insert associations */
644 num = MIN (demux->times->len, demux->filepositions->len);
645 for (i = 0; i < num; i++) {
646 guint64 time, fileposition;
648 time = g_array_index (demux->times, gdouble, i) * GST_SECOND;
649 fileposition = g_array_index (demux->filepositions, gdouble, i);
650 gst_flv_demux_parse_and_add_index_entry (demux, time, fileposition,
653 demux->indexed = TRUE;
658 gst_buffer_unmap (buffer, &map);
664 have_group_id (GstFlvDemux * demux)
668 event = gst_pad_get_sticky_event (demux->sinkpad, GST_EVENT_STREAM_START, 0);
670 if (gst_event_parse_group_id (event, &demux->group_id))
671 demux->have_group_id = TRUE;
673 demux->have_group_id = FALSE;
674 gst_event_unref (event);
675 } else if (!demux->have_group_id) {
676 demux->have_group_id = TRUE;
677 demux->group_id = gst_util_group_id_next ();
680 return demux->have_group_id;
684 gst_flv_demux_audio_negotiate (GstFlvDemux * demux, guint32 codec_tag,
685 guint32 rate, guint32 channels, guint32 width)
687 GstCaps *caps = NULL, *old_caps;
688 gchar *codec_name = NULL;
689 gboolean ret = FALSE;
690 guint adjusted_rate = rate;
696 caps = gst_caps_new_simple ("audio/x-adpcm", "layout", G_TYPE_STRING,
701 caps = gst_caps_new_simple ("audio/mpeg",
702 "mpegversion", G_TYPE_INT, 1, "layer", G_TYPE_INT, 3,
703 "parsed", G_TYPE_BOOLEAN, TRUE, NULL);
708 GstAudioFormat format;
710 /* Assuming little endian for 0 (aka endianness of the
711 * system on which the file was created) as most people
712 * are probably using little endian machines */
713 format = gst_audio_format_build_integer ((width == 8) ? FALSE : TRUE,
714 G_LITTLE_ENDIAN, width, width);
716 caps = gst_caps_new_simple ("audio/x-raw",
717 "format", G_TYPE_STRING, gst_audio_format_to_string (format),
718 "layout", G_TYPE_STRING, "interleaved", NULL);
724 caps = gst_caps_new_empty_simple ("audio/x-nellymoser");
729 if (!demux->audio_codec_data) {
730 GST_DEBUG_OBJECT (demux, "don't have AAC codec data yet");
735 gst_buffer_map (demux->audio_codec_data, &map, GST_MAP_READ);
737 /* use codec-data to extract and verify samplerate */
741 freq_index = GST_READ_UINT16_BE (map.data);
742 freq_index = (freq_index & 0x0780) >> 7;
744 gst_codec_utils_aac_get_sample_rate_from_index (freq_index);
746 if (adjusted_rate && (rate != adjusted_rate)) {
747 GST_LOG_OBJECT (demux, "Ajusting AAC sample rate %d -> %d", rate,
750 adjusted_rate = rate;
753 gst_buffer_unmap (demux->audio_codec_data, &map);
755 caps = gst_caps_new_simple ("audio/mpeg",
756 "mpegversion", G_TYPE_INT, 4, "framed", G_TYPE_BOOLEAN, TRUE,
757 "stream-format", G_TYPE_STRING, "raw", NULL);
761 caps = gst_caps_new_empty_simple ("audio/x-alaw");
764 caps = gst_caps_new_empty_simple ("audio/x-mulaw");
768 GValue streamheader = G_VALUE_INIT;
769 GValue value = G_VALUE_INIT;
771 GstStructure *structure;
775 caps = gst_caps_new_empty_simple ("audio/x-speex");
776 structure = gst_caps_get_structure (caps, 0);
778 GST_DEBUG_OBJECT (demux, "generating speex header");
780 /* Speex decoder expects streamheader to be { [header], [comment] } */
781 g_value_init (&streamheader, GST_TYPE_ARRAY);
784 gst_byte_writer_init_with_size (&w, 80, TRUE);
785 gst_byte_writer_put_data (&w, (guint8 *) "Speex ", 8);
786 gst_byte_writer_put_data (&w, (guint8 *) "1.1.12", 7);
787 gst_byte_writer_fill (&w, 0, 13);
788 gst_byte_writer_put_uint32_le (&w, 1); /* version */
789 gst_byte_writer_put_uint32_le (&w, 80); /* header_size */
790 gst_byte_writer_put_uint32_le (&w, 16000); /* rate */
791 gst_byte_writer_put_uint32_le (&w, 1); /* mode: Wideband */
792 gst_byte_writer_put_uint32_le (&w, 4); /* mode_bitstream_version */
793 gst_byte_writer_put_uint32_le (&w, 1); /* nb_channels: 1 */
794 gst_byte_writer_put_uint32_le (&w, -1); /* bitrate */
795 gst_byte_writer_put_uint32_le (&w, 0x50); /* frame_size */
796 gst_byte_writer_put_uint32_le (&w, 0); /* VBR */
797 gst_byte_writer_put_uint32_le (&w, 1); /* frames_per_packet */
798 gst_byte_writer_put_uint32_le (&w, 0); /* extra_headers */
799 gst_byte_writer_put_uint32_le (&w, 0); /* reserved1 */
800 gst_byte_writer_put_uint32_le (&w, 0); /* reserved2 */
801 g_assert (gst_byte_writer_get_size (&w) == 80);
803 g_value_init (&value, GST_TYPE_BUFFER);
804 g_value_take_boxed (&value, gst_byte_writer_reset_and_get_buffer (&w));
805 gst_value_array_append_value (&streamheader, &value);
806 g_value_unset (&value);
809 g_value_init (&value, GST_TYPE_BUFFER);
810 tags = gst_tag_list_new_empty ();
811 buf = gst_tag_list_to_vorbiscomment_buffer (tags, NULL, 0, "No comments");
812 gst_tag_list_unref (tags);
813 g_value_take_boxed (&value, buf);
814 gst_value_array_append_value (&streamheader, &value);
815 g_value_unset (&value);
817 gst_structure_take_value (structure, "streamheader", &streamheader);
820 adjusted_rate = 16000;
824 GST_WARNING_OBJECT (demux, "unsupported audio codec tag %u", codec_tag);
828 if (G_UNLIKELY (!caps)) {
829 GST_WARNING_OBJECT (demux, "failed creating caps for audio pad");
833 gst_caps_set_simple (caps, "rate", G_TYPE_INT, adjusted_rate,
834 "channels", G_TYPE_INT, channels, NULL);
836 if (demux->audio_codec_data) {
837 gst_caps_set_simple (caps, "codec_data", GST_TYPE_BUFFER,
838 demux->audio_codec_data, NULL);
841 old_caps = gst_pad_get_current_caps (demux->audio_pad);
844 gst_pad_create_stream_id (demux->audio_pad, GST_ELEMENT_CAST (demux),
847 event = gst_event_new_stream_start (stream_id);
848 if (have_group_id (demux))
849 gst_event_set_group_id (event, demux->group_id);
850 gst_pad_push_event (demux->audio_pad, event);
853 if (!old_caps || !gst_caps_is_equal (old_caps, caps))
854 ret = gst_pad_set_caps (demux->audio_pad, caps);
859 gst_caps_unref (old_caps);
862 if (G_LIKELY (ret)) {
863 /* Store the caps we got from tags */
864 demux->audio_codec_tag = codec_tag;
866 demux->channels = channels;
867 demux->width = width;
870 codec_name = gst_pb_utils_get_codec_description (caps);
873 if (demux->taglist == NULL)
874 demux->taglist = gst_tag_list_new_empty ();
875 gst_tag_list_add (demux->taglist, GST_TAG_MERGE_REPLACE,
876 GST_TAG_AUDIO_CODEC, codec_name, NULL);
880 GST_DEBUG_OBJECT (demux->audio_pad, "successfully negotiated caps %"
881 GST_PTR_FORMAT, caps);
883 GST_DEBUG_OBJECT (demux->audio_pad, "delayed setting caps");
886 GST_WARNING_OBJECT (demux->audio_pad, "failed negotiating caps %"
887 GST_PTR_FORMAT, caps);
891 gst_caps_unref (caps);
898 gst_flv_demux_push_src_event (GstFlvDemux * demux, GstEvent * event)
902 if (demux->audio_pad)
903 ret |= gst_pad_push_event (demux->audio_pad, gst_event_ref (event));
905 if (demux->video_pad)
906 ret |= gst_pad_push_event (demux->video_pad, gst_event_ref (event));
908 gst_event_unref (event);
914 gst_flv_demux_push_tags (GstFlvDemux * demux)
916 if (demux->has_audio && !demux->audio_pad) {
917 GST_DEBUG_OBJECT (demux,
918 "Waiting for audio stream pad to come up before we can push tags");
921 if (demux->has_video && !demux->video_pad) {
922 GST_DEBUG_OBJECT (demux,
923 "Waiting for video stream pad to come up before we can push tags");
926 if (demux->taglist) {
927 GST_DEBUG_OBJECT (demux, "pushing tags out %" GST_PTR_FORMAT,
929 gst_tag_list_set_scope (demux->taglist, GST_TAG_SCOPE_GLOBAL);
930 gst_flv_demux_push_src_event (demux, gst_event_new_tag (demux->taglist));
931 demux->taglist = gst_tag_list_new_empty ();
932 demux->push_tags = FALSE;
937 gst_flv_demux_update_resync (GstFlvDemux * demux, guint32 dts, gboolean discont,
938 guint32 * last, GstClockTime * offset)
940 gboolean ret = FALSE;
941 gint32 ddts = dts - *last;
942 if (!discont && ddts <= -RESYNC_THRESHOLD) {
943 /* Theoretically, we should use substract the duration of the last buffer,
944 but this demuxer sends no durations on buffers, not sure if it cannot
945 know, or just does not care to calculate. */
946 *offset -= ddts * GST_MSECOND;
947 GST_WARNING_OBJECT (demux,
948 "Large dts gap (%" G_GINT32_FORMAT " ms), assuming resync, offset now %"
949 GST_TIME_FORMAT "", ddts, GST_TIME_ARGS (*offset));
959 gst_flv_demux_parse_tag_audio (GstFlvDemux * demux, GstBuffer * buffer)
961 GstFlowReturn ret = GST_FLOW_OK;
962 guint32 pts = 0, codec_tag = 0, rate = 5512, width = 8, channels = 1;
963 guint32 codec_data = 0, pts_ext = 0;
969 GST_LOG_OBJECT (demux, "parsing an audio tag");
971 if (G_UNLIKELY (!demux->audio_pad && demux->no_more_pads)) {
972 #ifndef GST_DISABLE_DEBUG
973 if (G_UNLIKELY (!demux->no_audio_warned)) {
974 GST_WARNING_OBJECT (demux,
975 "Signaled no-more-pads already but had no audio pad -- ignoring");
976 demux->no_audio_warned = TRUE;
982 g_return_val_if_fail (gst_buffer_get_size (buffer) == demux->tag_size,
985 /* Error out on tags with too small headers */
986 if (gst_buffer_get_size (buffer) < 11) {
987 GST_ERROR_OBJECT (demux, "Too small tag size (%" G_GSIZE_FORMAT ")",
988 gst_buffer_get_size (buffer));
989 return GST_FLOW_ERROR;
992 gst_buffer_map (buffer, &map, GST_MAP_READ);
995 /* Grab information about audio tag */
996 pts = GST_READ_UINT24_BE (data);
997 /* read the pts extension to 32 bits integer */
998 pts_ext = GST_READ_UINT8 (data + 3);
1000 pts |= pts_ext << 24;
1002 GST_LOG_OBJECT (demux, "pts bytes %02X %02X %02X %02X (%d)", data[0], data[1],
1003 data[2], data[3], pts);
1005 /* Skip the stream id and go directly to the flags */
1006 flags = GST_READ_UINT8 (data + 7);
1008 /* Silently skip buffers with no data */
1021 if ((flags & 0x0C) == 0x0C) {
1023 } else if ((flags & 0x0C) == 0x08) {
1025 } else if ((flags & 0x0C) == 0x04) {
1029 codec_tag = flags >> 4;
1030 if (codec_tag == 10) { /* AAC has an extra byte for packet type */
1036 /* codec tags with special rates */
1037 if (codec_tag == 5 || codec_tag == 14)
1039 else if ((codec_tag == 4) || (codec_tag == 11))
1042 GST_LOG_OBJECT (demux, "audio tag with %d channels, %dHz sampling rate, "
1043 "%d bits width, codec tag %u (flags %02X)", channels, rate, width,
1046 /* If we don't have our audio pad created, then create it. */
1047 if (G_UNLIKELY (!demux->audio_pad)) {
1050 gst_pad_new_from_template (gst_element_class_get_pad_template
1051 (GST_ELEMENT_GET_CLASS (demux), "audio"), "audio");
1052 if (G_UNLIKELY (!demux->audio_pad)) {
1053 GST_WARNING_OBJECT (demux, "failed creating audio pad");
1054 ret = GST_FLOW_ERROR;
1058 /* Set functions on the pad */
1059 gst_pad_set_query_function (demux->audio_pad,
1060 GST_DEBUG_FUNCPTR (gst_flv_demux_query));
1061 gst_pad_set_event_function (demux->audio_pad,
1062 GST_DEBUG_FUNCPTR (gst_flv_demux_src_event));
1064 gst_pad_use_fixed_caps (demux->audio_pad);
1066 /* Make it active */
1067 gst_pad_set_active (demux->audio_pad, TRUE);
1069 /* Negotiate caps */
1070 if (!gst_flv_demux_audio_negotiate (demux, codec_tag, rate, channels,
1072 gst_object_unref (demux->audio_pad);
1073 demux->audio_pad = NULL;
1074 ret = GST_FLOW_ERROR;
1077 #ifndef GST_DISABLE_GST_DEBUG
1081 caps = gst_pad_get_current_caps (demux->audio_pad);
1082 GST_DEBUG_OBJECT (demux, "created audio pad with caps %" GST_PTR_FORMAT,
1085 gst_caps_unref (caps);
1089 /* We need to set caps before adding */
1090 gst_element_add_pad (GST_ELEMENT (demux),
1091 gst_object_ref (demux->audio_pad));
1092 gst_flow_combiner_add_pad (demux->flowcombiner, demux->audio_pad);
1094 /* We only emit no more pads when we have audio and video. Indeed we can
1095 * not trust the FLV header to tell us if there will be only audio or
1096 * only video and we would just break discovery of some files */
1097 if (demux->audio_pad && demux->video_pad) {
1098 GST_DEBUG_OBJECT (demux, "emitting no more pads");
1099 gst_element_no_more_pads (GST_ELEMENT (demux));
1100 demux->no_more_pads = TRUE;
1101 demux->push_tags = TRUE;
1105 /* Check if caps have changed */
1106 if (G_UNLIKELY (rate != demux->rate || channels != demux->channels ||
1107 codec_tag != demux->audio_codec_tag || width != demux->width)) {
1108 GST_DEBUG_OBJECT (demux, "audio settings have changed, changing caps");
1110 gst_buffer_replace (&demux->audio_codec_data, NULL);
1112 /* Negotiate caps */
1113 if (!gst_flv_demux_audio_negotiate (demux, codec_tag, rate, channels,
1115 ret = GST_FLOW_ERROR;
1120 /* Push taglist if present */
1121 if (G_UNLIKELY (demux->push_tags))
1122 gst_flv_demux_push_tags (demux);
1124 /* Check if we have anything to push */
1125 if (demux->tag_data_size <= codec_data) {
1126 GST_LOG_OBJECT (demux, "Nothing left in this tag, returning");
1130 /* Create buffer from pad */
1131 outbuf = gst_buffer_copy_region (buffer, GST_BUFFER_COPY_MEMORY,
1132 7 + codec_data, demux->tag_data_size - codec_data);
1134 if (demux->audio_codec_tag == 10) {
1135 guint8 aac_packet_type = GST_READ_UINT8 (data + 8);
1137 switch (aac_packet_type) {
1140 /* AudioSpecificConfig data */
1141 GST_LOG_OBJECT (demux, "got an AAC codec data packet");
1142 if (demux->audio_codec_data) {
1143 gst_buffer_unref (demux->audio_codec_data);
1145 demux->audio_codec_data = outbuf;
1146 /* Use that buffer data in the caps */
1147 gst_flv_demux_audio_negotiate (demux, codec_tag, rate, channels, width);
1151 if (!demux->audio_codec_data) {
1152 GST_ERROR_OBJECT (demux, "got AAC audio packet before codec data");
1154 gst_buffer_unref (outbuf);
1157 /* AAC raw packet */
1158 GST_LOG_OBJECT (demux, "got a raw AAC audio packet");
1161 GST_WARNING_OBJECT (demux, "invalid AAC packet type %u",
1166 /* detect (and deem to be resyncs) large pts gaps */
1167 if (gst_flv_demux_update_resync (demux, pts, demux->audio_need_discont,
1168 &demux->last_audio_pts, &demux->audio_time_offset)) {
1169 GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_RESYNC);
1172 /* Fill buffer with data */
1173 GST_BUFFER_PTS (outbuf) = pts * GST_MSECOND + demux->audio_time_offset;
1174 GST_BUFFER_DTS (outbuf) = GST_BUFFER_PTS (outbuf);
1175 GST_BUFFER_DURATION (outbuf) = GST_CLOCK_TIME_NONE;
1176 GST_BUFFER_OFFSET (outbuf) = demux->audio_offset++;
1177 GST_BUFFER_OFFSET_END (outbuf) = demux->audio_offset;
1179 if (demux->duration == GST_CLOCK_TIME_NONE ||
1180 demux->duration < GST_BUFFER_TIMESTAMP (outbuf))
1181 demux->duration = GST_BUFFER_TIMESTAMP (outbuf);
1183 /* Only add audio frames to the index if we have no video,
1184 * and if the index is not yet complete */
1185 if (!demux->has_video && !demux->indexed) {
1186 gst_flv_demux_parse_and_add_index_entry (demux,
1187 GST_BUFFER_TIMESTAMP (outbuf), demux->cur_tag_offset, TRUE);
1190 if (G_UNLIKELY (demux->audio_need_discont)) {
1191 GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_DISCONT);
1192 demux->audio_need_discont = FALSE;
1195 demux->segment.position = GST_BUFFER_TIMESTAMP (outbuf);
1197 /* Do we need a newsegment event ? */
1198 if (G_UNLIKELY (demux->audio_need_segment)) {
1199 if (!demux->new_seg_event) {
1200 GST_DEBUG_OBJECT (demux, "pushing newsegment from %"
1201 GST_TIME_FORMAT " to %" GST_TIME_FORMAT,
1202 GST_TIME_ARGS (demux->segment.position),
1203 GST_TIME_ARGS (demux->segment.stop));
1204 demux->segment.start = demux->segment.time = demux->segment.position;
1205 demux->new_seg_event = gst_event_new_segment (&demux->segment);
1207 GST_DEBUG_OBJECT (demux, "pushing pre-generated newsegment event");
1210 gst_pad_push_event (demux->audio_pad, gst_event_ref (demux->new_seg_event));
1212 demux->audio_need_segment = FALSE;
1215 GST_LOG_OBJECT (demux,
1216 "pushing %" G_GSIZE_FORMAT " bytes buffer at pts %" GST_TIME_FORMAT
1217 " with duration %" GST_TIME_FORMAT ", offset %" G_GUINT64_FORMAT,
1218 gst_buffer_get_size (outbuf),
1219 GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (outbuf)),
1220 GST_TIME_ARGS (GST_BUFFER_DURATION (outbuf)), GST_BUFFER_OFFSET (outbuf));
1222 if (!GST_CLOCK_TIME_IS_VALID (demux->audio_start)) {
1223 demux->audio_start = GST_BUFFER_TIMESTAMP (outbuf);
1225 if (!GST_CLOCK_TIME_IS_VALID (demux->audio_first_ts)) {
1226 demux->audio_first_ts = GST_BUFFER_TIMESTAMP (outbuf);
1229 if (G_UNLIKELY (!demux->no_more_pads
1230 && (GST_CLOCK_DIFF (demux->audio_start,
1231 GST_BUFFER_TIMESTAMP (outbuf)) > NO_MORE_PADS_THRESHOLD))) {
1232 GST_DEBUG_OBJECT (demux,
1233 "Signalling no-more-pads because no video stream was found"
1234 " after 6 seconds of audio");
1235 gst_element_no_more_pads (GST_ELEMENT_CAST (demux));
1236 demux->no_more_pads = TRUE;
1237 demux->push_tags = TRUE;
1240 /* Push downstream */
1241 ret = gst_pad_push (demux->audio_pad, outbuf);
1243 if (G_UNLIKELY (ret != GST_FLOW_OK) &&
1244 demux->segment.rate < 0.0 && ret == GST_FLOW_EOS &&
1245 demux->segment.position > demux->segment.stop) {
1246 /* In reverse playback we can get a GST_FLOW_EOS when
1247 * we are at the end of the segment, so we just need to jump
1248 * back to the previous section. */
1249 GST_DEBUG_OBJECT (demux, "downstream has reached end of segment");
1250 demux->audio_done = TRUE;
1255 ret = gst_flow_combiner_update_pad_flow (demux->flowcombiner,
1256 demux->audio_pad, ret);
1259 gst_buffer_unmap (buffer, &map);
1265 gst_flv_demux_video_negotiate (GstFlvDemux * demux, guint32 codec_tag)
1267 gboolean ret = FALSE;
1268 GstCaps *caps = NULL, *old_caps;
1269 gchar *codec_name = NULL;
1273 /* Generate caps for that pad */
1274 switch (codec_tag) {
1277 gst_caps_new_simple ("video/x-flash-video", "flvversion", G_TYPE_INT,
1281 caps = gst_caps_new_empty_simple ("video/x-flash-screen");
1284 caps = gst_caps_new_empty_simple ("video/x-vp6-flash");
1287 caps = gst_caps_new_empty_simple ("video/x-vp6-alpha");
1290 if (!demux->video_codec_data) {
1291 GST_DEBUG_OBJECT (demux, "don't have h264 codec data yet");
1296 gst_caps_new_simple ("video/x-h264", "stream-format", G_TYPE_STRING,
1300 GST_WARNING_OBJECT (demux, "unsupported video codec tag %u", codec_tag);
1303 if (G_UNLIKELY (!caps)) {
1304 GST_WARNING_OBJECT (demux, "failed creating caps for video pad");
1308 gst_caps_set_simple (caps, "pixel-aspect-ratio", GST_TYPE_FRACTION,
1309 demux->par_x, demux->par_y, NULL);
1311 if (G_LIKELY (demux->w)) {
1312 gst_caps_set_simple (caps, "width", G_TYPE_INT, demux->w, NULL);
1315 if (G_LIKELY (demux->h)) {
1316 gst_caps_set_simple (caps, "height", G_TYPE_INT, demux->h, NULL);
1319 if (G_LIKELY (demux->framerate)) {
1320 gint num = 0, den = 0;
1322 gst_video_guess_framerate (GST_SECOND / demux->framerate, &num, &den);
1323 GST_DEBUG_OBJECT (demux->video_pad,
1324 "fps to be used on caps %f (as a fraction = %d/%d)", demux->framerate,
1327 gst_caps_set_simple (caps, "framerate", GST_TYPE_FRACTION, num, den, NULL);
1330 if (demux->video_codec_data) {
1331 gst_caps_set_simple (caps, "codec_data", GST_TYPE_BUFFER,
1332 demux->video_codec_data, NULL);
1335 old_caps = gst_pad_get_current_caps (demux->video_pad);
1338 gst_pad_create_stream_id (demux->video_pad, GST_ELEMENT_CAST (demux),
1340 event = gst_event_new_stream_start (stream_id);
1343 if (have_group_id (demux))
1344 gst_event_set_group_id (event, demux->group_id);
1345 gst_pad_push_event (demux->video_pad, event);
1348 if (!old_caps || !gst_caps_is_equal (old_caps, caps))
1349 ret = gst_pad_set_caps (demux->video_pad, caps);
1354 gst_caps_unref (old_caps);
1357 if (G_LIKELY (ret)) {
1358 /* Store the caps we have set */
1359 demux->video_codec_tag = codec_tag;
1362 codec_name = gst_pb_utils_get_codec_description (caps);
1365 if (demux->taglist == NULL)
1366 demux->taglist = gst_tag_list_new_empty ();
1367 gst_tag_list_add (demux->taglist, GST_TAG_MERGE_REPLACE,
1368 GST_TAG_VIDEO_CODEC, codec_name, NULL);
1369 g_free (codec_name);
1372 GST_DEBUG_OBJECT (demux->video_pad, "successfully negotiated caps %"
1373 GST_PTR_FORMAT, caps);
1375 GST_DEBUG_OBJECT (demux->video_pad, "delayed setting caps");
1378 GST_WARNING_OBJECT (demux->video_pad, "failed negotiating caps %"
1379 GST_PTR_FORMAT, caps);
1383 gst_caps_unref (caps);
1389 static GstFlowReturn
1390 gst_flv_demux_parse_tag_video (GstFlvDemux * demux, GstBuffer * buffer)
1392 GstFlowReturn ret = GST_FLOW_OK;
1393 guint32 dts = 0, codec_data = 1, dts_ext = 0;
1395 gboolean keyframe = FALSE;
1396 guint8 flags = 0, codec_tag = 0;
1401 g_return_val_if_fail (gst_buffer_get_size (buffer) == demux->tag_size,
1404 GST_LOG_OBJECT (demux, "parsing a video tag");
1407 (!demux->video_pad && demux->no_more_pads) {
1408 #ifndef GST_DISABLE_DEBUG
1410 (!demux->no_video_warned) {
1411 GST_WARNING_OBJECT (demux,
1412 "Signaled no-more-pads already but had no video pad -- ignoring");
1413 demux->no_video_warned = TRUE;
1419 if (gst_buffer_get_size (buffer) < 12) {
1420 GST_ERROR_OBJECT (demux, "Too small tag size");
1421 return GST_FLOW_ERROR;
1424 gst_buffer_map (buffer, &map, GST_MAP_READ);
1427 /* Grab information about video tag */
1428 dts = GST_READ_UINT24_BE (data);
1429 /* read the dts extension to 32 bits integer */
1430 dts_ext = GST_READ_UINT8 (data + 3);
1432 dts |= dts_ext << 24;
1434 GST_LOG_OBJECT (demux, "dts bytes %02X %02X %02X %02X (%d)", data[0], data[1],
1435 data[2], data[3], dts);
1437 /* Skip the stream id and go directly to the flags */
1438 flags = GST_READ_UINT8 (data + 7);
1441 if ((flags >> 4) == 1) {
1445 codec_tag = flags & 0x0F;
1446 if (codec_tag == 4 || codec_tag == 5) {
1448 } else if (codec_tag == 7) {
1451 cts = GST_READ_UINT24_BE (data + 9);
1452 cts = (cts + 0xff800000) ^ 0xff800000;
1454 GST_LOG_OBJECT (demux, "got cts %d", cts);
1457 GST_LOG_OBJECT (demux, "video tag with codec tag %u, keyframe (%d) "
1458 "(flags %02X)", codec_tag, keyframe, flags);
1460 /* If we don't have our video pad created, then create it. */
1461 if (G_UNLIKELY (!demux->video_pad)) {
1463 gst_pad_new_from_template (gst_element_class_get_pad_template
1464 (GST_ELEMENT_GET_CLASS (demux), "video"), "video");
1465 if (G_UNLIKELY (!demux->video_pad)) {
1466 GST_WARNING_OBJECT (demux, "failed creating video pad");
1467 ret = GST_FLOW_ERROR;
1471 /* Set functions on the pad */
1472 gst_pad_set_query_function (demux->video_pad,
1473 GST_DEBUG_FUNCPTR (gst_flv_demux_query));
1474 gst_pad_set_event_function (demux->video_pad,
1475 GST_DEBUG_FUNCPTR (gst_flv_demux_src_event));
1477 gst_pad_use_fixed_caps (demux->video_pad);
1479 /* Make it active */
1480 gst_pad_set_active (demux->video_pad, TRUE);
1482 /* Needs to be active before setting caps */
1483 if (!gst_flv_demux_video_negotiate (demux, codec_tag)) {
1484 gst_object_unref (demux->video_pad);
1485 demux->video_pad = NULL;
1486 ret = GST_FLOW_ERROR;
1490 /* When we ve set pixel-aspect-ratio we use that boolean to detect a
1491 * metadata tag that would come later and trigger a caps change */
1492 demux->got_par = FALSE;
1494 #ifndef GST_DISABLE_GST_DEBUG
1498 caps = gst_pad_get_current_caps (demux->video_pad);
1499 GST_DEBUG_OBJECT (demux, "created video pad with caps %" GST_PTR_FORMAT,
1502 gst_caps_unref (caps);
1506 /* We need to set caps before adding */
1507 gst_element_add_pad (GST_ELEMENT (demux),
1508 gst_object_ref (demux->video_pad));
1509 gst_flow_combiner_add_pad (demux->flowcombiner, demux->video_pad);
1511 /* We only emit no more pads when we have audio and video. Indeed we can
1512 * not trust the FLV header to tell us if there will be only audio or
1513 * only video and we would just break discovery of some files */
1514 if (demux->audio_pad && demux->video_pad) {
1515 GST_DEBUG_OBJECT (demux, "emitting no more pads");
1516 gst_element_no_more_pads (GST_ELEMENT (demux));
1517 demux->no_more_pads = TRUE;
1518 demux->push_tags = TRUE;
1522 /* Check if caps have changed */
1523 if (G_UNLIKELY (codec_tag != demux->video_codec_tag || demux->got_par)) {
1524 GST_DEBUG_OBJECT (demux, "video settings have changed, changing caps");
1525 gst_buffer_replace (&demux->video_codec_data, NULL);
1527 if (!gst_flv_demux_video_negotiate (demux, codec_tag)) {
1528 ret = GST_FLOW_ERROR;
1532 /* When we ve set pixel-aspect-ratio we use that boolean to detect a
1533 * metadata tag that would come later and trigger a caps change */
1534 demux->got_par = FALSE;
1537 /* Push taglist if present */
1538 if (G_UNLIKELY (demux->push_tags))
1539 gst_flv_demux_push_tags (demux);
1541 /* Check if we have anything to push */
1542 if (demux->tag_data_size <= codec_data) {
1543 GST_LOG_OBJECT (demux, "Nothing left in this tag, returning");
1547 /* Create buffer from pad */
1548 outbuf = gst_buffer_copy_region (buffer, GST_BUFFER_COPY_MEMORY,
1549 7 + codec_data, demux->tag_data_size - codec_data);
1551 if (demux->video_codec_tag == 7) {
1552 guint8 avc_packet_type = GST_READ_UINT8 (data + 8);
1554 switch (avc_packet_type) {
1557 /* AVCDecoderConfigurationRecord data */
1558 GST_LOG_OBJECT (demux, "got an H.264 codec data packet");
1559 if (demux->video_codec_data) {
1560 gst_buffer_unref (demux->video_codec_data);
1562 demux->video_codec_data = outbuf;
1563 /* Use that buffer data in the caps */
1564 gst_flv_demux_video_negotiate (demux, codec_tag);
1568 /* H.264 NALU packet */
1569 if (!demux->video_codec_data) {
1570 GST_ERROR_OBJECT (demux, "got H.264 video packet before codec data");
1572 gst_buffer_unref (outbuf);
1575 GST_LOG_OBJECT (demux, "got a H.264 NALU video packet");
1578 GST_WARNING_OBJECT (demux, "invalid video packet type %u",
1583 /* detect (and deem to be resyncs) large dts gaps */
1584 if (gst_flv_demux_update_resync (demux, dts, demux->video_need_discont,
1585 &demux->last_video_dts, &demux->video_time_offset)) {
1586 GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_RESYNC);
1589 /* Fill buffer with data */
1590 GST_LOG_OBJECT (demux, "dts %u pts %u cts %d", dts, dts + cts, cts);
1592 GST_BUFFER_PTS (outbuf) =
1593 (dts + cts) * GST_MSECOND + demux->video_time_offset;
1594 GST_BUFFER_DTS (outbuf) = dts * GST_MSECOND + demux->video_time_offset;
1595 GST_BUFFER_DURATION (outbuf) = GST_CLOCK_TIME_NONE;
1596 GST_BUFFER_OFFSET (outbuf) = demux->video_offset++;
1597 GST_BUFFER_OFFSET_END (outbuf) = demux->video_offset;
1599 if (demux->duration == GST_CLOCK_TIME_NONE ||
1600 demux->duration < GST_BUFFER_TIMESTAMP (outbuf))
1601 demux->duration = GST_BUFFER_TIMESTAMP (outbuf);
1604 GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_DELTA_UNIT);
1606 if (!demux->indexed) {
1607 gst_flv_demux_parse_and_add_index_entry (demux,
1608 GST_BUFFER_TIMESTAMP (outbuf), demux->cur_tag_offset, keyframe);
1611 if (G_UNLIKELY (demux->video_need_discont)) {
1612 GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_DISCONT);
1613 demux->video_need_discont = FALSE;
1616 demux->segment.position = GST_BUFFER_TIMESTAMP (outbuf);
1618 /* Do we need a newsegment event ? */
1619 if (G_UNLIKELY (demux->video_need_segment)) {
1620 if (!demux->new_seg_event) {
1621 GST_DEBUG_OBJECT (demux, "pushing newsegment from %"
1622 GST_TIME_FORMAT " to %" GST_TIME_FORMAT,
1623 GST_TIME_ARGS (demux->segment.position),
1624 GST_TIME_ARGS (demux->segment.stop));
1625 demux->segment.start = demux->segment.time = demux->segment.position;
1626 demux->new_seg_event = gst_event_new_segment (&demux->segment);
1628 GST_DEBUG_OBJECT (demux, "pushing pre-generated newsegment event");
1631 gst_pad_push_event (demux->video_pad, gst_event_ref (demux->new_seg_event));
1633 demux->video_need_segment = FALSE;
1636 GST_LOG_OBJECT (demux,
1637 "pushing %" G_GSIZE_FORMAT " bytes buffer at dts %" GST_TIME_FORMAT
1638 " with duration %" GST_TIME_FORMAT ", offset %" G_GUINT64_FORMAT
1639 ", keyframe (%d)", gst_buffer_get_size (outbuf),
1640 GST_TIME_ARGS (GST_BUFFER_DTS (outbuf)),
1641 GST_TIME_ARGS (GST_BUFFER_DURATION (outbuf)), GST_BUFFER_OFFSET (outbuf),
1644 if (!GST_CLOCK_TIME_IS_VALID (demux->video_start)) {
1645 demux->video_start = GST_BUFFER_TIMESTAMP (outbuf);
1647 if (!GST_CLOCK_TIME_IS_VALID (demux->audio_first_ts)) {
1648 demux->video_first_ts = GST_BUFFER_TIMESTAMP (outbuf);
1651 if (G_UNLIKELY (!demux->no_more_pads
1652 && (GST_CLOCK_DIFF (demux->video_start,
1653 GST_BUFFER_TIMESTAMP (outbuf)) > NO_MORE_PADS_THRESHOLD))) {
1654 GST_DEBUG_OBJECT (demux,
1655 "Signalling no-more-pads because no audio stream was found"
1656 " after 6 seconds of video");
1657 gst_element_no_more_pads (GST_ELEMENT_CAST (demux));
1658 demux->no_more_pads = TRUE;
1659 demux->push_tags = TRUE;
1662 /* Push downstream */
1663 ret = gst_pad_push (demux->video_pad, outbuf);
1665 if (G_UNLIKELY (ret != GST_FLOW_OK) &&
1666 demux->segment.rate < 0.0 && ret == GST_FLOW_EOS &&
1667 demux->segment.position > demux->segment.stop) {
1668 /* In reverse playback we can get a GST_FLOW_EOS when
1669 * we are at the end of the segment, so we just need to jump
1670 * back to the previous section. */
1671 GST_DEBUG_OBJECT (demux, "downstream has reached end of segment");
1672 demux->video_done = TRUE;
1677 ret = gst_flow_combiner_update_pad_flow (demux->flowcombiner,
1678 demux->video_pad, ret);
1681 gst_buffer_unmap (buffer, &map);
1686 gst_flv_demux_parse_tag_timestamp (GstFlvDemux * demux, gboolean index,
1687 GstBuffer * buffer, size_t * tag_size)
1689 guint32 dts = 0, dts_ext = 0;
1690 guint32 tag_data_size;
1692 gboolean keyframe = TRUE;
1693 GstClockTime ret = GST_CLOCK_TIME_NONE;
1698 g_return_val_if_fail (gst_buffer_get_size (buffer) >= 12,
1699 GST_CLOCK_TIME_NONE);
1701 gst_buffer_map (buffer, &map, GST_MAP_READ);
1707 if (type != 9 && type != 8 && type != 18) {
1708 GST_WARNING_OBJECT (demux, "Unsupported tag type %u", data[0]);
1713 demux->has_video = TRUE;
1715 demux->has_audio = TRUE;
1717 tag_data_size = GST_READ_UINT24_BE (data + 1);
1719 if (size >= tag_data_size + 11 + 4) {
1720 if (GST_READ_UINT32_BE (data + tag_data_size + 11) != tag_data_size + 11) {
1721 GST_WARNING_OBJECT (demux, "Invalid tag size");
1727 *tag_size = tag_data_size + 11 + 4;
1731 GST_LOG_OBJECT (demux, "dts bytes %02X %02X %02X %02X", data[0], data[1],
1734 /* Grab timestamp of tag tag */
1735 dts = GST_READ_UINT24_BE (data);
1736 /* read the dts extension to 32 bits integer */
1737 dts_ext = GST_READ_UINT8 (data + 3);
1739 dts |= dts_ext << 24;
1744 keyframe = ((data[0] >> 4) == 1);
1747 ret = dts * GST_MSECOND;
1748 GST_LOG_OBJECT (demux, "dts: %" GST_TIME_FORMAT, GST_TIME_ARGS (ret));
1750 if (index && !demux->indexed && (type == 9 || (type == 8
1751 && !demux->has_video))) {
1752 gst_flv_demux_parse_and_add_index_entry (demux, ret, demux->offset,
1756 if (demux->duration == GST_CLOCK_TIME_NONE || demux->duration < ret)
1757 demux->duration = ret;
1760 gst_buffer_unmap (buffer, &map);
1764 static GstFlowReturn
1765 gst_flv_demux_parse_tag_type (GstFlvDemux * demux, GstBuffer * buffer)
1767 GstFlowReturn ret = GST_FLOW_OK;
1768 guint8 tag_type = 0;
1771 g_return_val_if_fail (gst_buffer_get_size (buffer) >= 4, GST_FLOW_ERROR);
1773 gst_buffer_map (buffer, &map, GST_MAP_READ);
1775 tag_type = map.data[0];
1777 /* Tag size is 1 byte of type + 3 bytes of size + 7 bytes + tag data size +
1778 * 4 bytes of previous tag size */
1779 demux->tag_data_size = GST_READ_UINT24_BE (map.data + 1);
1780 demux->tag_size = demux->tag_data_size + 11;
1782 GST_LOG_OBJECT (demux, "tag data size is %" G_GUINT64_FORMAT,
1783 demux->tag_data_size);
1785 gst_buffer_unmap (buffer, &map);
1789 demux->state = FLV_STATE_TAG_VIDEO;
1790 demux->has_video = TRUE;
1793 demux->state = FLV_STATE_TAG_AUDIO;
1794 demux->has_audio = TRUE;
1797 demux->state = FLV_STATE_TAG_SCRIPT;
1800 GST_WARNING_OBJECT (demux, "unsupported tag type %u", tag_type);
1801 demux->state = FLV_STATE_SKIP;
1807 static GstFlowReturn
1808 gst_flv_demux_parse_header (GstFlvDemux * demux, GstBuffer * buffer)
1810 GstFlowReturn ret = GST_FLOW_OK;
1813 g_return_val_if_fail (gst_buffer_get_size (buffer) >= 9, GST_FLOW_ERROR);
1815 gst_buffer_map (buffer, &map, GST_MAP_READ);
1817 /* Check for the FLV tag */
1818 if (map.data[0] == 'F' && map.data[1] == 'L' && map.data[2] == 'V') {
1819 GST_DEBUG_OBJECT (demux, "FLV header detected");
1821 if (G_UNLIKELY (demux->strict)) {
1822 GST_WARNING_OBJECT (demux, "invalid header tag detected");
1828 if (map.data[3] == '1') {
1829 GST_DEBUG_OBJECT (demux, "FLV version 1 detected");
1831 if (G_UNLIKELY (demux->strict)) {
1832 GST_WARNING_OBJECT (demux, "invalid header version detected");
1839 /* Now look at audio/video flags */
1841 guint8 flags = map.data[4];
1843 demux->has_video = demux->has_audio = FALSE;
1846 GST_DEBUG_OBJECT (demux, "there is a video stream");
1847 demux->has_video = TRUE;
1850 GST_DEBUG_OBJECT (demux, "there is an audio stream");
1851 demux->has_audio = TRUE;
1855 /* do a one-time seekability check */
1856 gst_flv_demux_check_seekability (demux);
1858 /* We don't care about the rest */
1859 demux->need_header = FALSE;
1862 gst_buffer_unmap (buffer, &map);
1868 gst_flv_demux_flush (GstFlvDemux * demux, gboolean discont)
1870 GST_DEBUG_OBJECT (demux, "flushing queued data in the FLV demuxer");
1872 gst_adapter_clear (demux->adapter);
1874 demux->audio_need_discont = TRUE;
1875 demux->video_need_discont = TRUE;
1877 demux->flushing = FALSE;
1879 /* Only in push mode and if we're not during a seek */
1880 if (!demux->random_access && demux->state != FLV_STATE_SEEK) {
1881 /* After a flush we expect a tag_type */
1882 demux->state = FLV_STATE_TAG_TYPE;
1883 /* We reset the offset and will get one from first push */
1889 gst_flv_demux_cleanup (GstFlvDemux * demux)
1891 GST_DEBUG_OBJECT (demux, "cleaning up FLV demuxer");
1893 demux->state = FLV_STATE_HEADER;
1895 demux->have_group_id = FALSE;
1896 demux->group_id = G_MAXUINT;
1898 demux->flushing = FALSE;
1899 demux->need_header = TRUE;
1900 demux->audio_need_segment = TRUE;
1901 demux->video_need_segment = TRUE;
1902 demux->audio_need_discont = TRUE;
1903 demux->video_need_discont = TRUE;
1905 demux->has_audio = FALSE;
1906 demux->has_video = FALSE;
1907 demux->push_tags = FALSE;
1908 demux->got_par = FALSE;
1910 demux->indexed = FALSE;
1911 demux->upstream_seekable = FALSE;
1912 demux->file_size = 0;
1914 demux->index_max_pos = 0;
1915 demux->index_max_time = 0;
1917 demux->audio_start = demux->video_start = GST_CLOCK_TIME_NONE;
1918 demux->last_audio_pts = demux->last_video_dts = 0;
1919 demux->audio_time_offset = demux->video_time_offset = 0;
1921 demux->no_more_pads = FALSE;
1923 #ifndef GST_DISABLE_DEBUG
1924 demux->no_audio_warned = FALSE;
1925 demux->no_video_warned = FALSE;
1928 gst_segment_init (&demux->segment, GST_FORMAT_TIME);
1930 demux->w = demux->h = 0;
1931 demux->framerate = 0.0;
1932 demux->par_x = demux->par_y = 1;
1933 demux->video_offset = 0;
1934 demux->audio_offset = 0;
1935 demux->offset = demux->cur_tag_offset = 0;
1936 demux->tag_size = demux->tag_data_size = 0;
1937 demux->duration = GST_CLOCK_TIME_NONE;
1939 if (demux->new_seg_event) {
1940 gst_event_unref (demux->new_seg_event);
1941 demux->new_seg_event = NULL;
1944 gst_adapter_clear (demux->adapter);
1946 if (demux->audio_codec_data) {
1947 gst_buffer_unref (demux->audio_codec_data);
1948 demux->audio_codec_data = NULL;
1951 if (demux->video_codec_data) {
1952 gst_buffer_unref (demux->video_codec_data);
1953 demux->video_codec_data = NULL;
1956 if (demux->audio_pad) {
1957 gst_flow_combiner_remove_pad (demux->flowcombiner, demux->audio_pad);
1958 gst_element_remove_pad (GST_ELEMENT (demux), demux->audio_pad);
1959 gst_object_unref (demux->audio_pad);
1960 demux->audio_pad = NULL;
1963 if (demux->video_pad) {
1964 gst_flow_combiner_remove_pad (demux->flowcombiner, demux->video_pad);
1965 gst_element_remove_pad (GST_ELEMENT (demux), demux->video_pad);
1966 gst_object_unref (demux->video_pad);
1967 demux->video_pad = NULL;
1971 g_array_free (demux->times, TRUE);
1972 demux->times = NULL;
1975 if (demux->filepositions) {
1976 g_array_free (demux->filepositions, TRUE);
1977 demux->filepositions = NULL;
1982 * Create and push a flushing seek event upstream
1985 flv_demux_seek_to_offset (GstFlvDemux * demux, guint64 offset)
1990 GST_DEBUG_OBJECT (demux, "Seeking to %" G_GUINT64_FORMAT, offset);
1993 gst_event_new_seek (1.0, GST_FORMAT_BYTES,
1994 GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE, GST_SEEK_TYPE_SET, offset,
1995 GST_SEEK_TYPE_NONE, -1);
1997 res = gst_pad_push_event (demux->sinkpad, event);
2000 demux->offset = offset;
2004 static GstFlowReturn
2005 gst_flv_demux_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer)
2007 GstFlowReturn ret = GST_FLOW_OK;
2008 GstFlvDemux *demux = NULL;
2010 demux = GST_FLV_DEMUX (parent);
2012 GST_LOG_OBJECT (demux,
2013 "received buffer of %" G_GSIZE_FORMAT " bytes at offset %"
2014 G_GUINT64_FORMAT, gst_buffer_get_size (buffer),
2015 GST_BUFFER_OFFSET (buffer));
2017 if (G_UNLIKELY (GST_BUFFER_OFFSET (buffer) == 0)) {
2018 GST_DEBUG_OBJECT (demux, "beginning of file, expect header");
2019 demux->state = FLV_STATE_HEADER;
2023 if (G_UNLIKELY (demux->offset == 0 && GST_BUFFER_OFFSET (buffer) != 0)) {
2024 GST_DEBUG_OBJECT (demux, "offset was zero, synchronizing with buffer's");
2025 demux->offset = GST_BUFFER_OFFSET (buffer);
2028 if (GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_DISCONT)) {
2029 GST_DEBUG_OBJECT (demux, "Discontinuity");
2030 gst_adapter_clear (demux->adapter);
2033 gst_adapter_push (demux->adapter, buffer);
2035 if (demux->seeking) {
2036 demux->state = FLV_STATE_SEEK;
2037 GST_OBJECT_LOCK (demux);
2038 demux->seeking = FALSE;
2039 GST_OBJECT_UNLOCK (demux);
2043 if (G_UNLIKELY (ret != GST_FLOW_OK)) {
2044 GST_DEBUG_OBJECT (demux, "got flow return %s", gst_flow_get_name (ret));
2048 if (G_UNLIKELY (demux->flushing)) {
2049 GST_DEBUG_OBJECT (demux, "we are now flushing, exiting parser loop");
2050 ret = GST_FLOW_FLUSHING;
2054 switch (demux->state) {
2055 case FLV_STATE_HEADER:
2057 if (gst_adapter_available (demux->adapter) >= FLV_HEADER_SIZE) {
2060 buffer = gst_adapter_take_buffer (demux->adapter, FLV_HEADER_SIZE);
2062 ret = gst_flv_demux_parse_header (demux, buffer);
2064 gst_buffer_unref (buffer);
2065 demux->offset += FLV_HEADER_SIZE;
2067 demux->state = FLV_STATE_TAG_TYPE;
2073 case FLV_STATE_TAG_TYPE:
2075 if (gst_adapter_available (demux->adapter) >= FLV_TAG_TYPE_SIZE) {
2078 /* Remember the tag offset in bytes */
2079 demux->cur_tag_offset = demux->offset;
2081 buffer = gst_adapter_take_buffer (demux->adapter, FLV_TAG_TYPE_SIZE);
2083 ret = gst_flv_demux_parse_tag_type (demux, buffer);
2085 gst_buffer_unref (buffer);
2086 demux->offset += FLV_TAG_TYPE_SIZE;
2088 /* last tag is not an index => no index/don't know where the index is
2089 * seek back to the beginning */
2090 if (demux->seek_event && demux->state != FLV_STATE_TAG_SCRIPT)
2098 case FLV_STATE_TAG_VIDEO:
2100 if (gst_adapter_available (demux->adapter) >= demux->tag_size) {
2103 buffer = gst_adapter_take_buffer (demux->adapter, demux->tag_size);
2105 ret = gst_flv_demux_parse_tag_video (demux, buffer);
2107 gst_buffer_unref (buffer);
2108 demux->offset += demux->tag_size;
2110 demux->state = FLV_STATE_TAG_TYPE;
2116 case FLV_STATE_TAG_AUDIO:
2118 if (gst_adapter_available (demux->adapter) >= demux->tag_size) {
2121 buffer = gst_adapter_take_buffer (demux->adapter, demux->tag_size);
2123 ret = gst_flv_demux_parse_tag_audio (demux, buffer);
2125 gst_buffer_unref (buffer);
2126 demux->offset += demux->tag_size;
2128 demux->state = FLV_STATE_TAG_TYPE;
2134 case FLV_STATE_TAG_SCRIPT:
2136 if (gst_adapter_available (demux->adapter) >= demux->tag_size) {
2139 buffer = gst_adapter_take_buffer (demux->adapter, demux->tag_size);
2141 ret = gst_flv_demux_parse_tag_script (demux, buffer);
2143 gst_buffer_unref (buffer);
2144 demux->offset += demux->tag_size;
2146 demux->state = FLV_STATE_TAG_TYPE;
2148 /* if there's a seek event we're here for the index so if we don't have it
2149 * we seek back to the beginning */
2150 if (demux->seek_event) {
2152 demux->state = FLV_STATE_SEEK;
2162 case FLV_STATE_SEEK:
2168 if (!demux->indexed) {
2169 if (demux->offset == demux->file_size - sizeof (guint32)) {
2170 guint64 seek_offset;
2173 data = gst_adapter_take (demux->adapter, 4);
2177 seek_offset = demux->file_size - sizeof (guint32) -
2178 GST_READ_UINT32_BE (data);
2181 GST_INFO_OBJECT (demux,
2182 "Seeking to beginning of last tag at %" G_GUINT64_FORMAT,
2184 demux->state = FLV_STATE_TAG_TYPE;
2185 flv_demux_seek_to_offset (demux, seek_offset);
2191 GST_OBJECT_LOCK (demux);
2192 event = demux->seek_event;
2193 demux->seek_event = NULL;
2194 GST_OBJECT_UNLOCK (demux);
2196 /* calculate and perform seek */
2197 if (!flv_demux_handle_seek_push (demux, event))
2200 gst_event_unref (event);
2201 demux->state = FLV_STATE_TAG_TYPE;
2204 case FLV_STATE_SKIP:
2205 /* Skip unknown tags (set in _parse_tag_type()) */
2206 if (gst_adapter_available (demux->adapter) >= demux->tag_size) {
2207 gst_adapter_flush (demux->adapter, demux->tag_size);
2208 demux->offset += demux->tag_size;
2209 demux->state = FLV_STATE_TAG_TYPE;
2215 GST_DEBUG_OBJECT (demux, "unexpected demuxer state");
2224 GST_OBJECT_LOCK (demux);
2225 demux->seeking = FALSE;
2226 gst_event_unref (demux->seek_event);
2227 demux->seek_event = NULL;
2228 GST_OBJECT_UNLOCK (demux);
2229 GST_WARNING_OBJECT (demux,
2230 "failed to find an index, seeking back to beginning");
2231 flv_demux_seek_to_offset (demux, 0);
2236 GST_ELEMENT_ERROR (demux, STREAM, DEMUX, (NULL), ("seek failed"));
2237 return GST_FLOW_ERROR;
2242 static GstFlowReturn
2243 gst_flv_demux_pull_range (GstFlvDemux * demux, GstPad * pad, guint64 offset,
2244 guint size, GstBuffer ** buffer)
2248 ret = gst_pad_pull_range (pad, offset, size, buffer);
2249 if (G_UNLIKELY (ret != GST_FLOW_OK)) {
2250 GST_WARNING_OBJECT (demux,
2251 "failed when pulling %d bytes from offset %" G_GUINT64_FORMAT ": %s",
2252 size, offset, gst_flow_get_name (ret));
2257 if (G_UNLIKELY (*buffer && gst_buffer_get_size (*buffer) != size)) {
2258 GST_WARNING_OBJECT (demux,
2259 "partial pull got %" G_GSIZE_FORMAT " when expecting %d from offset %"
2260 G_GUINT64_FORMAT, gst_buffer_get_size (*buffer), size, offset);
2261 gst_buffer_unref (*buffer);
2270 static GstFlowReturn
2271 gst_flv_demux_pull_tag (GstPad * pad, GstFlvDemux * demux)
2273 GstBuffer *buffer = NULL;
2274 GstFlowReturn ret = GST_FLOW_OK;
2276 /* Store tag offset */
2277 demux->cur_tag_offset = demux->offset;
2279 /* Get the first 4 bytes to identify tag type and size */
2280 if (G_UNLIKELY ((ret = gst_flv_demux_pull_range (demux, pad, demux->offset,
2281 FLV_TAG_TYPE_SIZE, &buffer)) != GST_FLOW_OK))
2284 /* Identify tag type */
2285 ret = gst_flv_demux_parse_tag_type (demux, buffer);
2287 gst_buffer_unref (buffer);
2289 if (G_UNLIKELY (ret != GST_FLOW_OK))
2292 /* Jump over tag type + size */
2293 demux->offset += FLV_TAG_TYPE_SIZE;
2295 /* Pull the whole tag */
2297 if (G_UNLIKELY ((ret = gst_flv_demux_pull_range (demux, pad, demux->offset,
2298 demux->tag_size, &buffer)) != GST_FLOW_OK))
2301 switch (demux->state) {
2302 case FLV_STATE_TAG_VIDEO:
2303 ret = gst_flv_demux_parse_tag_video (demux, buffer);
2305 case FLV_STATE_TAG_AUDIO:
2306 ret = gst_flv_demux_parse_tag_audio (demux, buffer);
2308 case FLV_STATE_TAG_SCRIPT:
2309 ret = gst_flv_demux_parse_tag_script (demux, buffer);
2312 GST_WARNING_OBJECT (demux, "unexpected state %d", demux->state);
2315 gst_buffer_unref (buffer);
2317 /* Jump over that part we've just parsed */
2318 demux->offset += demux->tag_size;
2320 /* Make sure we reinitialize the tag size */
2321 demux->tag_size = 0;
2323 /* Ready for the next tag */
2324 demux->state = FLV_STATE_TAG_TYPE;
2326 if (G_UNLIKELY (ret == GST_FLOW_NOT_LINKED)) {
2327 GST_WARNING_OBJECT (demux, "parsing this tag returned not-linked and "
2328 "neither video nor audio are linked");
2335 static GstFlowReturn
2336 gst_flv_demux_pull_header (GstPad * pad, GstFlvDemux * demux)
2338 GstBuffer *buffer = NULL;
2339 GstFlowReturn ret = GST_FLOW_OK;
2341 /* Get the first 9 bytes */
2342 if (G_UNLIKELY ((ret = gst_flv_demux_pull_range (demux, pad, demux->offset,
2343 FLV_HEADER_SIZE, &buffer)) != GST_FLOW_OK))
2346 ret = gst_flv_demux_parse_header (demux, buffer);
2348 gst_buffer_unref (buffer);
2350 /* Jump over the header now */
2351 demux->offset += FLV_HEADER_SIZE;
2352 demux->state = FLV_STATE_TAG_TYPE;
2359 gst_flv_demux_move_to_offset (GstFlvDemux * demux, gint64 offset,
2362 demux->offset = offset;
2364 /* Tell all the stream we moved to a different position (discont) */
2365 demux->audio_need_discont = TRUE;
2366 demux->video_need_discont = TRUE;
2368 /* next section setup */
2369 demux->from_offset = -1;
2370 demux->audio_done = demux->video_done = FALSE;
2371 demux->audio_first_ts = demux->video_first_ts = GST_CLOCK_TIME_NONE;
2374 demux->from_offset = -1;
2375 demux->to_offset = G_MAXINT64;
2378 /* If we seeked at the beginning of the file parse the header again */
2379 if (G_UNLIKELY (!demux->offset)) {
2380 demux->state = FLV_STATE_HEADER;
2381 } else { /* or parse a tag */
2382 demux->state = FLV_STATE_TAG_TYPE;
2386 static GstFlowReturn
2387 gst_flv_demux_seek_to_prev_keyframe (GstFlvDemux * demux)
2389 GstFlowReturn ret = GST_FLOW_EOS;
2391 GstIndexEntry *entry = NULL;
2393 GST_DEBUG_OBJECT (demux,
2394 "terminated section started at offset %" G_GINT64_FORMAT,
2395 demux->from_offset);
2397 /* we are done if we got all audio and video */
2398 if ((!GST_CLOCK_TIME_IS_VALID (demux->audio_first_ts) ||
2399 demux->audio_first_ts < demux->segment.start) &&
2400 (!GST_CLOCK_TIME_IS_VALID (demux->video_first_ts) ||
2401 demux->video_first_ts < demux->segment.start))
2404 if (demux->from_offset <= 0)
2407 GST_DEBUG_OBJECT (demux, "locating previous position");
2409 index = gst_flv_demux_get_index (GST_ELEMENT (demux));
2411 /* locate index entry before previous start position */
2413 entry = gst_index_get_assoc_entry (index, demux->index_id,
2414 GST_INDEX_LOOKUP_BEFORE, GST_ASSOCIATION_FLAG_KEY_UNIT,
2415 GST_FORMAT_BYTES, demux->from_offset - 1);
2418 gint64 bytes = 0, time = 0;
2420 gst_index_entry_assoc_map (entry, GST_FORMAT_BYTES, &bytes);
2421 gst_index_entry_assoc_map (entry, GST_FORMAT_TIME, &time);
2423 GST_DEBUG_OBJECT (demux, "found index entry for %" G_GINT64_FORMAT
2424 " at %" GST_TIME_FORMAT ", seeking to %" G_GINT64_FORMAT,
2425 demux->offset - 1, GST_TIME_ARGS (time), bytes);
2427 /* setup for next section */
2428 demux->to_offset = demux->from_offset;
2429 gst_flv_demux_move_to_offset (demux, bytes, FALSE);
2433 gst_object_unref (index);
2440 static GstFlowReturn
2441 gst_flv_demux_create_index (GstFlvDemux * demux, gint64 pos, GstClockTime ts)
2447 GstClockTime tag_time;
2448 GstFlowReturn ret = GST_FLOW_OK;
2450 if (!gst_pad_peer_query_duration (demux->sinkpad, GST_FORMAT_BYTES, &size))
2453 GST_DEBUG_OBJECT (demux, "building index at %" G_GINT64_FORMAT
2454 " looking for time %" GST_TIME_FORMAT, pos, GST_TIME_ARGS (ts));
2456 old_offset = demux->offset;
2457 demux->offset = pos;
2460 while ((ret = gst_flv_demux_pull_range (demux, demux->sinkpad, demux->offset,
2461 12, &buffer)) == GST_FLOW_OK) {
2463 gst_flv_demux_parse_tag_timestamp (demux, TRUE, buffer, &tag_size);
2465 gst_buffer_unref (buffer);
2468 if (G_UNLIKELY (tag_time == GST_CLOCK_TIME_NONE || tag_time > ts))
2471 demux->offset += tag_size;
2474 if (ret == GST_FLOW_EOS) {
2475 /* file ran out, so mark we have complete index */
2476 demux->indexed = TRUE;
2481 demux->offset = old_offset;
2487 gst_flv_demux_get_metadata (GstFlvDemux * demux)
2489 gint64 ret = 0, offset;
2490 size_t tag_size, size;
2491 GstBuffer *buffer = NULL;
2494 if (!gst_pad_peer_query_duration (demux->sinkpad, GST_FORMAT_BYTES, &offset))
2498 GST_DEBUG_OBJECT (demux, "upstream size: %" G_GINT64_FORMAT, offset);
2499 if (G_UNLIKELY (offset < 4))
2503 if (GST_FLOW_OK != gst_flv_demux_pull_range (demux, demux->sinkpad, offset,
2507 gst_buffer_map (buffer, &map, GST_MAP_READ);
2508 tag_size = GST_READ_UINT32_BE (map.data);
2509 gst_buffer_unmap (buffer, &map);
2510 GST_DEBUG_OBJECT (demux, "last tag size: %" G_GSIZE_FORMAT, tag_size);
2511 gst_buffer_unref (buffer);
2515 if (GST_FLOW_OK != gst_flv_demux_pull_range (demux, demux->sinkpad, offset,
2519 /* a consistency check */
2520 gst_buffer_map (buffer, &map, GST_MAP_READ);
2521 size = GST_READ_UINT24_BE (map.data + 1);
2522 if (size != tag_size - 11) {
2523 gst_buffer_unmap (buffer, &map);
2524 GST_DEBUG_OBJECT (demux,
2525 "tag size %" G_GSIZE_FORMAT ", expected %" G_GSIZE_FORMAT
2526 ", corrupt or truncated file", size, tag_size - 11);
2530 /* try to update duration with timestamp in any case */
2531 gst_flv_demux_parse_tag_timestamp (demux, FALSE, buffer, &size);
2533 /* maybe get some more metadata */
2534 if (map.data[0] == 18) {
2535 gst_buffer_unmap (buffer, &map);
2536 gst_buffer_unref (buffer);
2538 GST_DEBUG_OBJECT (demux, "script tag, pulling it to parse");
2540 if (GST_FLOW_OK == gst_flv_demux_pull_range (demux, demux->sinkpad, offset,
2542 gst_flv_demux_parse_tag_script (demux, buffer);
2544 gst_buffer_unmap (buffer, &map);
2549 gst_buffer_unref (buffer);
2555 gst_flv_demux_loop (GstPad * pad)
2557 GstFlvDemux *demux = NULL;
2558 GstFlowReturn ret = GST_FLOW_OK;
2560 demux = GST_FLV_DEMUX (gst_pad_get_parent (pad));
2563 switch (demux->state) {
2564 case FLV_STATE_TAG_TYPE:
2565 if (demux->from_offset == -1)
2566 demux->from_offset = demux->offset;
2567 ret = gst_flv_demux_pull_tag (pad, demux);
2568 /* if we have seen real data, we probably passed a possible metadata
2569 * header located at start. So if we do not yet have an index,
2570 * try to pick up metadata (index, duration) at the end */
2571 if (G_UNLIKELY (!demux->file_size && !demux->indexed &&
2572 (demux->has_video || demux->has_audio)))
2573 demux->file_size = gst_flv_demux_get_metadata (demux);
2575 case FLV_STATE_DONE:
2578 case FLV_STATE_SEEK:
2579 /* seek issued with insufficient index;
2580 * scan for index in task thread from current maximum offset to
2581 * desired time and then perform seek */
2582 /* TODO maybe some buffering message or so to indicate scan progress */
2583 ret = gst_flv_demux_create_index (demux, demux->index_max_pos,
2585 if (ret != GST_FLOW_OK)
2587 /* position and state arranged by seek,
2588 * also unrefs event */
2589 gst_flv_demux_handle_seek_pull (demux, demux->seek_event, FALSE);
2590 demux->seek_event = NULL;
2593 ret = gst_flv_demux_pull_header (pad, demux);
2594 /* index scans start after header */
2595 demux->index_max_pos = demux->offset;
2599 if (demux->segment.rate < 0.0) {
2600 /* check end of section */
2601 if ((gint64) demux->offset >= demux->to_offset ||
2602 demux->segment.position >= demux->segment.stop + 2 * GST_SECOND ||
2603 (demux->audio_done && demux->video_done))
2604 ret = gst_flv_demux_seek_to_prev_keyframe (demux);
2606 /* check EOS condition */
2607 if ((demux->segment.stop != -1) &&
2608 (demux->segment.position >= demux->segment.stop)) {
2613 /* pause if something went wrong or at end */
2614 if (G_UNLIKELY (ret != GST_FLOW_OK))
2617 gst_object_unref (demux);
2623 const gchar *reason = gst_flow_get_name (ret);
2625 GST_LOG_OBJECT (demux, "pausing task, reason %s", reason);
2626 gst_pad_pause_task (pad);
2628 if (ret == GST_FLOW_EOS) {
2629 /* handle end-of-stream/segment */
2630 /* so align our position with the end of it, if there is one
2631 * this ensures a subsequent will arrive at correct base/acc time */
2632 if (demux->segment.rate > 0.0 &&
2633 GST_CLOCK_TIME_IS_VALID (demux->segment.stop))
2634 demux->segment.position = demux->segment.stop;
2635 else if (demux->segment.rate < 0.0)
2636 demux->segment.position = demux->segment.start;
2638 /* perform EOS logic */
2639 if (!demux->no_more_pads) {
2640 gst_element_no_more_pads (GST_ELEMENT_CAST (demux));
2641 demux->no_more_pads = TRUE;
2644 if (demux->segment.flags & GST_SEGMENT_FLAG_SEGMENT) {
2647 /* for segment playback we need to post when (in stream time)
2648 * we stopped, this is either stop (when set) or the duration. */
2649 if ((stop = demux->segment.stop) == -1)
2650 stop = demux->segment.duration;
2652 if (demux->segment.rate >= 0) {
2653 GST_LOG_OBJECT (demux, "Sending segment done, at end of segment");
2654 gst_element_post_message (GST_ELEMENT_CAST (demux),
2655 gst_message_new_segment_done (GST_OBJECT_CAST (demux),
2656 GST_FORMAT_TIME, stop));
2657 gst_flv_demux_push_src_event (demux,
2658 gst_event_new_segment_done (GST_FORMAT_TIME, stop));
2659 } else { /* Reverse playback */
2660 GST_LOG_OBJECT (demux, "Sending segment done, at beginning of "
2662 gst_element_post_message (GST_ELEMENT_CAST (demux),
2663 gst_message_new_segment_done (GST_OBJECT_CAST (demux),
2664 GST_FORMAT_TIME, demux->segment.start));
2665 gst_flv_demux_push_src_event (demux,
2666 gst_event_new_segment_done (GST_FORMAT_TIME,
2667 demux->segment.start));
2670 /* normal playback, send EOS to all linked pads */
2671 if (!demux->no_more_pads) {
2672 gst_element_no_more_pads (GST_ELEMENT (demux));
2673 demux->no_more_pads = TRUE;
2676 GST_LOG_OBJECT (demux, "Sending EOS, at end of stream");
2677 if (!demux->audio_pad && !demux->video_pad)
2678 GST_ELEMENT_ERROR (demux, STREAM, FAILED,
2679 ("Internal data stream error."), ("Got EOS before any data"));
2680 else if (!gst_flv_demux_push_src_event (demux, gst_event_new_eos ()))
2681 GST_WARNING_OBJECT (demux, "failed pushing EOS on streams");
2683 } else if (ret == GST_FLOW_NOT_LINKED || ret < GST_FLOW_EOS) {
2684 GST_ELEMENT_ERROR (demux, STREAM, FAILED,
2685 ("Internal data stream error."),
2686 ("stream stopped, reason %s", reason));
2687 gst_flv_demux_push_src_event (demux, gst_event_new_eos ());
2689 gst_object_unref (demux);
2695 gst_flv_demux_find_offset (GstFlvDemux * demux, GstSegment * segment,
2696 GstSeekFlags seek_flags)
2701 GstIndexEntry *entry;
2703 g_return_val_if_fail (segment != NULL, 0);
2705 time = segment->position;
2707 index = gst_flv_demux_get_index (GST_ELEMENT (demux));
2710 /* Let's check if we have an index entry for that seek time */
2711 entry = gst_index_get_assoc_entry (index, demux->index_id,
2712 seek_flags & GST_SEEK_FLAG_SNAP_AFTER ?
2713 GST_INDEX_LOOKUP_AFTER : GST_INDEX_LOOKUP_BEFORE,
2714 GST_ASSOCIATION_FLAG_KEY_UNIT, GST_FORMAT_TIME, time);
2717 gst_index_entry_assoc_map (entry, GST_FORMAT_BYTES, &bytes);
2718 gst_index_entry_assoc_map (entry, GST_FORMAT_TIME, &time);
2720 GST_DEBUG_OBJECT (demux, "found index entry for %" GST_TIME_FORMAT
2721 " at %" GST_TIME_FORMAT ", seeking to %" G_GINT64_FORMAT,
2722 GST_TIME_ARGS (segment->position), GST_TIME_ARGS (time), bytes);
2724 /* Key frame seeking */
2725 if (seek_flags & GST_SEEK_FLAG_KEY_UNIT) {
2726 /* Adjust the segment so that the keyframe fits in */
2727 segment->start = segment->time = time;
2728 segment->position = time;
2731 GST_DEBUG_OBJECT (demux, "no index entry found for %" GST_TIME_FORMAT,
2732 GST_TIME_ARGS (segment->start));
2735 gst_object_unref (index);
2742 flv_demux_handle_seek_push (GstFlvDemux * demux, GstEvent * event)
2746 GstSeekType start_type, stop_type;
2749 gboolean update, flush, ret;
2750 GstSegment seeksegment;
2752 gst_event_parse_seek (event, &rate, &format, &flags,
2753 &start_type, &start, &stop_type, &stop);
2755 if (format != GST_FORMAT_TIME)
2758 flush = ! !(flags & GST_SEEK_FLAG_FLUSH);
2760 /* Work on a copy until we are sure the seek succeeded. */
2761 memcpy (&seeksegment, &demux->segment, sizeof (GstSegment));
2763 GST_DEBUG_OBJECT (demux, "segment before configure %" GST_SEGMENT_FORMAT,
2766 /* Apply the seek to our segment */
2767 gst_segment_do_seek (&seeksegment, rate, format, flags,
2768 start_type, start, stop_type, stop, &update);
2770 GST_DEBUG_OBJECT (demux, "segment configured %" GST_SEGMENT_FORMAT,
2773 if (flush || seeksegment.position != demux->segment.position) {
2774 /* Do the actual seeking */
2775 guint64 offset = gst_flv_demux_find_offset (demux, &seeksegment, flags);
2777 GST_DEBUG_OBJECT (demux, "generating an upstream seek at position %"
2778 G_GUINT64_FORMAT, offset);
2779 ret = gst_pad_push_event (demux->sinkpad,
2780 gst_event_new_seek (seeksegment.rate, GST_FORMAT_BYTES,
2781 flags | GST_SEEK_FLAG_ACCURATE, GST_SEEK_TYPE_SET,
2782 offset, GST_SEEK_TYPE_NONE, 0));
2783 if (G_UNLIKELY (!ret)) {
2784 GST_WARNING_OBJECT (demux, "upstream seek failed");
2787 gst_flow_combiner_reset (demux->flowcombiner);
2788 /* Tell all the stream we moved to a different position (discont) */
2789 demux->audio_need_discont = TRUE;
2790 demux->video_need_discont = TRUE;
2796 /* Ok seek succeeded, take the newly configured segment */
2797 memcpy (&demux->segment, &seeksegment, sizeof (GstSegment));
2799 /* Tell all the stream a new segment is needed */
2800 demux->audio_need_segment = TRUE;
2801 demux->video_need_segment = TRUE;
2802 /* Clean any potential newsegment event kept for the streams. The first
2803 * stream needing a new segment will create a new one. */
2804 if (G_UNLIKELY (demux->new_seg_event)) {
2805 gst_event_unref (demux->new_seg_event);
2806 demux->new_seg_event = NULL;
2808 GST_DEBUG_OBJECT (demux, "preparing newsegment from %"
2809 GST_TIME_FORMAT " to %" GST_TIME_FORMAT,
2810 GST_TIME_ARGS (demux->segment.start),
2811 GST_TIME_ARGS (demux->segment.stop));
2812 demux->new_seg_event = gst_event_new_segment (&demux->segment);
2813 gst_event_unref (event);
2815 ret = gst_pad_push_event (demux->sinkpad, event);
2823 GST_WARNING_OBJECT (demux, "we only support seeking in TIME format");
2824 gst_event_unref (event);
2830 gst_flv_demux_handle_seek_push (GstFlvDemux * demux, GstEvent * event)
2834 gst_event_parse_seek (event, NULL, &format, NULL, NULL, NULL, NULL, NULL);
2836 if (format != GST_FORMAT_TIME) {
2837 GST_WARNING_OBJECT (demux, "we only support seeking in TIME format");
2838 gst_event_unref (event);
2842 /* First try upstream */
2843 if (gst_pad_push_event (demux->sinkpad, gst_event_ref (event))) {
2844 GST_DEBUG_OBJECT (demux, "Upstream successfully seeked");
2845 gst_event_unref (event);
2849 if (!demux->indexed) {
2850 guint64 seek_offset = 0;
2851 gboolean building_index;
2853 GST_OBJECT_LOCK (demux);
2854 /* handle the seek in the chain function */
2855 demux->seeking = TRUE;
2856 demux->state = FLV_STATE_SEEK;
2858 /* copy the event */
2859 if (demux->seek_event)
2860 gst_event_unref (demux->seek_event);
2861 demux->seek_event = gst_event_ref (event);
2863 /* set the building_index flag so that only one thread can setup the
2864 * structures for index seeking. */
2865 building_index = demux->building_index;
2866 if (!building_index) {
2867 demux->building_index = TRUE;
2868 if (!demux->file_size
2869 && !gst_pad_peer_query_duration (demux->sinkpad, GST_FORMAT_BYTES,
2870 &demux->file_size)) {
2871 GST_WARNING_OBJECT (demux, "Failed to query upstream file size");
2872 GST_OBJECT_UNLOCK (demux);
2876 /* we hope the last tag is a scriptdataobject containing an index
2877 * the size of the last tag is given in the last guint32 bits
2878 * then we seek to the beginning of the tag, parse it and hopefully obtain an index */
2879 seek_offset = demux->file_size - sizeof (guint32);
2880 GST_DEBUG_OBJECT (demux,
2881 "File size obtained, seeking to %" G_GUINT64_FORMAT, seek_offset);
2883 GST_OBJECT_UNLOCK (demux);
2885 if (!building_index) {
2886 GST_INFO_OBJECT (demux, "Seeking to last 4 bytes at %" G_GUINT64_FORMAT,
2888 return flv_demux_seek_to_offset (demux, seek_offset);
2891 /* FIXME: we have to always return true so that we don't block the seek
2893 * Note: maybe it is OK to return true if we're still building the index */
2897 return flv_demux_handle_seek_push (demux, event);
2901 gst_flv_demux_handle_seek_pull (GstFlvDemux * demux, GstEvent * event,
2906 GstSeekType start_type, stop_type;
2909 gboolean update, flush, ret = FALSE;
2910 GstSegment seeksegment;
2912 gst_event_parse_seek (event, &rate, &format, &flags,
2913 &start_type, &start, &stop_type, &stop);
2915 if (format != GST_FORMAT_TIME)
2918 /* mark seeking thread entering flushing/pausing */
2919 GST_OBJECT_LOCK (demux);
2921 demux->seeking = seeking;
2922 GST_OBJECT_UNLOCK (demux);
2924 flush = ! !(flags & GST_SEEK_FLAG_FLUSH);
2927 /* Flush start up and downstream to make sure data flow and loops are
2929 gst_flv_demux_push_src_event (demux, gst_event_new_flush_start ());
2930 gst_pad_push_event (demux->sinkpad, gst_event_new_flush_start ());
2932 /* Pause the pulling task */
2933 gst_pad_pause_task (demux->sinkpad);
2936 /* Take the stream lock */
2937 GST_PAD_STREAM_LOCK (demux->sinkpad);
2940 /* Stop flushing upstream we need to pull */
2941 gst_pad_push_event (demux->sinkpad, gst_event_new_flush_stop (TRUE));
2944 /* Work on a copy until we are sure the seek succeeded. */
2945 memcpy (&seeksegment, &demux->segment, sizeof (GstSegment));
2947 GST_DEBUG_OBJECT (demux, "segment before configure %" GST_SEGMENT_FORMAT,
2950 /* Apply the seek to our segment */
2951 gst_segment_do_seek (&seeksegment, rate, format, flags,
2952 start_type, start, stop_type, stop, &update);
2954 GST_DEBUG_OBJECT (demux, "segment configured %" GST_SEGMENT_FORMAT,
2957 if (flush || seeksegment.position != demux->segment.position) {
2958 /* Do the actual seeking */
2959 /* index is reliable if it is complete or we do not go to far ahead */
2960 if (seeking && !demux->indexed &&
2961 seeksegment.position > demux->index_max_time + 10 * GST_SECOND) {
2962 GST_DEBUG_OBJECT (demux, "delaying seek to post-scan; "
2963 " index only up to %" GST_TIME_FORMAT,
2964 GST_TIME_ARGS (demux->index_max_time));
2965 /* stop flushing for now */
2967 gst_flv_demux_push_src_event (demux, gst_event_new_flush_stop (TRUE));
2968 /* delegate scanning and index building to task thread to avoid
2969 * occupying main (UI) loop */
2970 if (demux->seek_event)
2971 gst_event_unref (demux->seek_event);
2972 demux->seek_event = gst_event_ref (event);
2973 demux->seek_time = seeksegment.position;
2974 demux->state = FLV_STATE_SEEK;
2975 /* do not know about succes yet, but we did care and handled it */
2980 /* now index should be as reliable as it can be for current purpose */
2981 gst_flv_demux_move_to_offset (demux,
2982 gst_flv_demux_find_offset (demux, &seeksegment, flags), TRUE);
2989 /* Stop flushing, the sinks are at time 0 now */
2990 gst_flv_demux_push_src_event (demux, gst_event_new_flush_stop (TRUE));
2994 /* Ok seek succeeded, take the newly configured segment */
2995 memcpy (&demux->segment, &seeksegment, sizeof (GstSegment));
2997 /* Notify about the start of a new segment */
2998 if (demux->segment.flags & GST_SEGMENT_FLAG_SEGMENT) {
2999 gst_element_post_message (GST_ELEMENT (demux),
3000 gst_message_new_segment_start (GST_OBJECT (demux),
3001 demux->segment.format, demux->segment.position));
3004 gst_flow_combiner_reset (demux->flowcombiner);
3005 /* Tell all the stream a new segment is needed */
3006 demux->audio_need_segment = TRUE;
3007 demux->video_need_segment = TRUE;
3008 /* Clean any potential newsegment event kept for the streams. The first
3009 * stream needing a new segment will create a new one. */
3010 if (G_UNLIKELY (demux->new_seg_event)) {
3011 gst_event_unref (demux->new_seg_event);
3012 demux->new_seg_event = NULL;
3014 GST_DEBUG_OBJECT (demux, "preparing newsegment from %"
3015 GST_TIME_FORMAT " to %" GST_TIME_FORMAT,
3016 GST_TIME_ARGS (demux->segment.start),
3017 GST_TIME_ARGS (demux->segment.stop));
3018 demux->new_seg_event = gst_event_new_segment (&demux->segment);
3022 GST_OBJECT_LOCK (demux);
3023 seeking = demux->seeking && !seeking;
3024 demux->seeking = FALSE;
3025 GST_OBJECT_UNLOCK (demux);
3027 /* if we detect an external seek having started (and possibly already having
3028 * flushed), do not restart task to give it a chance.
3029 * Otherwise external one's flushing will take care to pause task */
3031 gst_pad_pause_task (demux->sinkpad);
3033 gst_pad_start_task (demux->sinkpad,
3034 (GstTaskFunction) gst_flv_demux_loop, demux->sinkpad, NULL);
3037 GST_PAD_STREAM_UNLOCK (demux->sinkpad);
3039 gst_event_unref (event);
3045 GST_WARNING_OBJECT (demux, "we only support seeking in TIME format");
3046 gst_event_unref (event);
3051 /* If we can pull that's prefered */
3053 gst_flv_demux_sink_activate (GstPad * sinkpad, GstObject * parent)
3058 query = gst_query_new_scheduling ();
3060 if (!gst_pad_peer_query (sinkpad, query)) {
3061 gst_query_unref (query);
3065 pull_mode = gst_query_has_scheduling_mode_with_flags (query,
3066 GST_PAD_MODE_PULL, GST_SCHEDULING_FLAG_SEEKABLE);
3067 gst_query_unref (query);
3072 GST_DEBUG_OBJECT (sinkpad, "activating pull");
3073 return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PULL, TRUE);
3077 GST_DEBUG_OBJECT (sinkpad, "activating push");
3078 return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PUSH, TRUE);
3083 gst_flv_demux_sink_activate_mode (GstPad * sinkpad, GstObject * parent,
3084 GstPadMode mode, gboolean active)
3089 demux = GST_FLV_DEMUX (parent);
3092 case GST_PAD_MODE_PUSH:
3093 demux->random_access = FALSE;
3096 case GST_PAD_MODE_PULL:
3098 demux->random_access = TRUE;
3099 res = gst_pad_start_task (sinkpad, (GstTaskFunction) gst_flv_demux_loop,
3102 demux->random_access = FALSE;
3103 res = gst_pad_stop_task (sinkpad);
3114 gst_flv_demux_sink_event (GstPad * pad, GstObject * parent, GstEvent * event)
3117 gboolean ret = FALSE;
3119 demux = GST_FLV_DEMUX (parent);
3121 GST_DEBUG_OBJECT (demux, "handling event %s", GST_EVENT_TYPE_NAME (event));
3123 switch (GST_EVENT_TYPE (event)) {
3124 case GST_EVENT_FLUSH_START:
3125 GST_DEBUG_OBJECT (demux, "trying to force chain function to exit");
3126 demux->flushing = TRUE;
3127 ret = gst_flv_demux_push_src_event (demux, event);
3129 case GST_EVENT_FLUSH_STOP:
3130 GST_DEBUG_OBJECT (demux, "flushing FLV demuxer");
3131 gst_flv_demux_flush (demux, TRUE);
3132 ret = gst_flv_demux_push_src_event (demux, event);
3138 GST_DEBUG_OBJECT (demux, "received EOS");
3140 index = gst_flv_demux_get_index (GST_ELEMENT (demux));
3143 GST_DEBUG_OBJECT (demux, "committing index");
3144 gst_index_commit (index, demux->index_id);
3145 gst_object_unref (index);
3148 if (!demux->audio_pad && !demux->video_pad)
3149 GST_ELEMENT_ERROR (demux, STREAM, FAILED,
3150 ("Internal data stream error."), ("Got EOS before any data"));
3152 if (!demux->no_more_pads) {
3153 gst_element_no_more_pads (GST_ELEMENT (demux));
3154 demux->no_more_pads = TRUE;
3157 if (!gst_flv_demux_push_src_event (demux, event))
3158 GST_WARNING_OBJECT (demux, "failed pushing EOS on streams");
3163 case GST_EVENT_SEGMENT:
3165 GstSegment in_segment;
3167 GST_DEBUG_OBJECT (demux, "received new segment");
3169 gst_event_copy_segment (event, &in_segment);
3171 if (in_segment.format == GST_FORMAT_TIME) {
3172 /* time segment, this is perfect, copy over the values. */
3173 memcpy (&demux->segment, &in_segment, sizeof (in_segment));
3175 GST_DEBUG_OBJECT (demux, "NEWSEGMENT: %" GST_SEGMENT_FORMAT,
3179 ret = gst_flv_demux_push_src_event (demux, event);
3181 /* non-time format */
3182 demux->audio_need_segment = TRUE;
3183 demux->video_need_segment = TRUE;
3185 gst_event_unref (event);
3186 if (demux->new_seg_event) {
3187 gst_event_unref (demux->new_seg_event);
3188 demux->new_seg_event = NULL;
3191 gst_flow_combiner_reset (demux->flowcombiner);
3195 ret = gst_pad_event_default (pad, parent, event);
3203 gst_flv_demux_src_event (GstPad * pad, GstObject * parent, GstEvent * event)
3206 gboolean ret = FALSE;
3208 demux = GST_FLV_DEMUX (parent);
3210 GST_DEBUG_OBJECT (demux, "handling event %s", GST_EVENT_TYPE_NAME (event));
3212 switch (GST_EVENT_TYPE (event)) {
3213 case GST_EVENT_SEEK:
3214 /* Try to push upstream first */
3215 gst_event_ref (event);
3216 ret = gst_pad_push_event (demux->sinkpad, event);
3218 gst_event_unref (event);
3221 if (demux->random_access) {
3222 ret = gst_flv_demux_handle_seek_pull (demux, event, TRUE);
3224 ret = gst_flv_demux_handle_seek_push (demux, event);
3228 ret = gst_pad_push_event (demux->sinkpad, event);
3236 gst_flv_demux_query (GstPad * pad, GstObject * parent, GstQuery * query)
3238 gboolean res = TRUE;
3241 demux = GST_FLV_DEMUX (parent);
3243 switch (GST_QUERY_TYPE (query)) {
3244 case GST_QUERY_DURATION:
3248 gst_query_parse_duration (query, &format, NULL);
3250 /* duration is time only */
3251 if (format != GST_FORMAT_TIME) {
3252 GST_DEBUG_OBJECT (demux, "duration query only supported for time "
3258 /* Try to push upstream first */
3259 res = gst_pad_peer_query (demux->sinkpad, query);
3263 GST_DEBUG_OBJECT (pad, "duration query, replying %" GST_TIME_FORMAT,
3264 GST_TIME_ARGS (demux->duration));
3266 gst_query_set_duration (query, GST_FORMAT_TIME, demux->duration);
3270 case GST_QUERY_POSITION:
3274 gst_query_parse_position (query, &format, NULL);
3276 /* position is time only */
3277 if (format != GST_FORMAT_TIME) {
3278 GST_DEBUG_OBJECT (demux, "position query only supported for time "
3284 GST_DEBUG_OBJECT (pad, "position query, replying %" GST_TIME_FORMAT,
3285 GST_TIME_ARGS (demux->segment.position));
3287 gst_query_set_position (query, GST_FORMAT_TIME, demux->segment.position);
3292 case GST_QUERY_SEEKING:{
3295 gst_query_parse_seeking (query, &fmt, NULL, NULL, NULL);
3297 /* First ask upstream */
3298 if (fmt == GST_FORMAT_TIME && gst_pad_peer_query (demux->sinkpad, query)) {
3301 gst_query_parse_seeking (query, NULL, &seekable, NULL, NULL);
3308 /* FIXME, check index this way is not thread safe */
3309 if (fmt != GST_FORMAT_TIME || !demux->index) {
3310 gst_query_set_seeking (query, fmt, FALSE, -1, -1);
3311 } else if (demux->random_access) {
3312 gst_query_set_seeking (query, GST_FORMAT_TIME, TRUE, 0,
3315 GstQuery *peerquery = gst_query_new_seeking (GST_FORMAT_BYTES);
3316 gboolean seekable = gst_pad_peer_query (demux->sinkpad, peerquery);
3319 gst_query_parse_seeking (peerquery, NULL, &seekable, NULL, NULL);
3320 gst_query_unref (peerquery);
3323 gst_query_set_seeking (query, GST_FORMAT_TIME, seekable, 0,
3326 gst_query_set_seeking (query, GST_FORMAT_TIME, FALSE, -1, -1);
3330 case GST_QUERY_SEGMENT:
3335 format = demux->segment.format;
3338 gst_segment_to_stream_time (&demux->segment, format,
3339 demux->segment.start);
3340 if ((stop = demux->segment.stop) == -1)
3341 stop = demux->segment.duration;
3343 stop = gst_segment_to_stream_time (&demux->segment, format, stop);
3345 gst_query_set_segment (query, demux->segment.rate, format, start, stop);
3349 case GST_QUERY_LATENCY:
3351 res = gst_pad_query_default (pad, parent, query);
3360 static GstStateChangeReturn
3361 gst_flv_demux_change_state (GstElement * element, GstStateChange transition)
3364 GstStateChangeReturn ret;
3366 demux = GST_FLV_DEMUX (element);
3368 switch (transition) {
3369 case GST_STATE_CHANGE_READY_TO_PAUSED:
3370 /* If this is our own index destroy it as the
3371 * old entries might be wrong for the new stream */
3372 if (demux->own_index) {
3373 gst_object_unref (demux->index);
3374 demux->index = NULL;
3375 demux->own_index = FALSE;
3378 /* If no index was created, generate one */
3379 if (G_UNLIKELY (!demux->index)) {
3380 GST_DEBUG_OBJECT (demux, "no index provided creating our own");
3382 demux->index = g_object_new (gst_mem_index_get_type (), NULL);
3384 gst_index_get_writer_id (demux->index, GST_OBJECT (demux),
3386 demux->own_index = TRUE;
3388 gst_flv_demux_cleanup (demux);
3394 ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
3395 if (ret == GST_STATE_CHANGE_FAILURE)
3398 switch (transition) {
3399 case GST_STATE_CHANGE_PAUSED_TO_READY:
3400 gst_flv_demux_cleanup (demux);
3411 gst_flv_demux_set_index (GstElement * element, GstIndex * index)
3413 GstFlvDemux *demux = GST_FLV_DEMUX (element);
3414 GstIndex *old_index;
3416 GST_OBJECT_LOCK (demux);
3418 old_index = demux->index;
3421 demux->index = gst_object_ref (index);
3422 demux->own_index = FALSE;
3424 demux->index = NULL;
3427 gst_object_unref (demux->index);
3429 gst_object_ref (index);
3431 GST_OBJECT_UNLOCK (demux);
3433 /* object lock might be taken again */
3435 gst_index_get_writer_id (index, GST_OBJECT (element), &demux->index_id);
3437 GST_DEBUG_OBJECT (demux, "Set index %" GST_PTR_FORMAT, demux->index);
3439 gst_object_unref (index);
3444 gst_flv_demux_get_index (GstElement * element)
3446 GstIndex *result = NULL;
3448 GstFlvDemux *demux = GST_FLV_DEMUX (element);
3450 GST_OBJECT_LOCK (demux);
3452 result = gst_object_ref (demux->index);
3453 GST_OBJECT_UNLOCK (demux);
3459 gst_flv_demux_dispose (GObject * object)
3461 GstFlvDemux *demux = GST_FLV_DEMUX (object);
3463 GST_DEBUG_OBJECT (demux, "disposing FLV demuxer");
3465 if (demux->adapter) {
3466 gst_adapter_clear (demux->adapter);
3467 g_object_unref (demux->adapter);
3468 demux->adapter = NULL;
3471 if (demux->taglist) {
3472 gst_tag_list_unref (demux->taglist);
3473 demux->taglist = NULL;
3476 if (demux->flowcombiner) {
3477 gst_flow_combiner_free (demux->flowcombiner);
3478 demux->flowcombiner = NULL;
3481 if (demux->new_seg_event) {
3482 gst_event_unref (demux->new_seg_event);
3483 demux->new_seg_event = NULL;
3486 if (demux->audio_codec_data) {
3487 gst_buffer_unref (demux->audio_codec_data);
3488 demux->audio_codec_data = NULL;
3491 if (demux->video_codec_data) {
3492 gst_buffer_unref (demux->video_codec_data);
3493 demux->video_codec_data = NULL;
3496 if (demux->audio_pad) {
3497 gst_object_unref (demux->audio_pad);
3498 demux->audio_pad = NULL;
3501 if (demux->video_pad) {
3502 gst_object_unref (demux->video_pad);
3503 demux->video_pad = NULL;
3507 gst_object_unref (demux->index);
3508 demux->index = NULL;
3512 g_array_free (demux->times, TRUE);
3513 demux->times = NULL;
3516 if (demux->filepositions) {
3517 g_array_free (demux->filepositions, TRUE);
3518 demux->filepositions = NULL;
3521 GST_CALL_PARENT (G_OBJECT_CLASS, dispose, (object));
3525 gst_flv_demux_class_init (GstFlvDemuxClass * klass)
3527 GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass);
3528 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
3530 gobject_class->dispose = gst_flv_demux_dispose;
3532 gstelement_class->change_state =
3533 GST_DEBUG_FUNCPTR (gst_flv_demux_change_state);
3536 gstelement_class->set_index = GST_DEBUG_FUNCPTR (gst_flv_demux_set_index);
3537 gstelement_class->get_index = GST_DEBUG_FUNCPTR (gst_flv_demux_get_index);
3540 gst_element_class_add_pad_template (gstelement_class,
3541 gst_static_pad_template_get (&flv_sink_template));
3542 gst_element_class_add_pad_template (gstelement_class,
3543 gst_static_pad_template_get (&audio_src_template));
3544 gst_element_class_add_pad_template (gstelement_class,
3545 gst_static_pad_template_get (&video_src_template));
3546 gst_element_class_set_static_metadata (gstelement_class, "FLV Demuxer",
3548 "Demux FLV feeds into digital streams",
3549 "Julien Moutte <julien@moutte.net>");
3553 gst_flv_demux_init (GstFlvDemux * demux)
3556 gst_pad_new_from_static_template (&flv_sink_template, "sink");
3558 gst_pad_set_event_function (demux->sinkpad,
3559 GST_DEBUG_FUNCPTR (gst_flv_demux_sink_event));
3560 gst_pad_set_chain_function (demux->sinkpad,
3561 GST_DEBUG_FUNCPTR (gst_flv_demux_chain));
3562 gst_pad_set_activate_function (demux->sinkpad,
3563 GST_DEBUG_FUNCPTR (gst_flv_demux_sink_activate));
3564 gst_pad_set_activatemode_function (demux->sinkpad,
3565 GST_DEBUG_FUNCPTR (gst_flv_demux_sink_activate_mode));
3567 gst_element_add_pad (GST_ELEMENT (demux), demux->sinkpad);
3569 demux->adapter = gst_adapter_new ();
3570 demux->taglist = gst_tag_list_new_empty ();
3571 demux->flowcombiner = gst_flow_combiner_new ();
3572 gst_segment_init (&demux->segment, GST_FORMAT_TIME);
3574 demux->own_index = FALSE;
3576 GST_OBJECT_FLAG_SET (demux, GST_ELEMENT_FLAG_INDEXABLE);
3578 gst_flv_demux_cleanup (demux);
3582 plugin_init (GstPlugin * plugin)
3584 GST_DEBUG_CATEGORY_INIT (flvdemux_debug, "flvdemux", 0, "FLV demuxer");
3586 if (!gst_element_register (plugin, "flvdemux", GST_RANK_PRIMARY,
3587 gst_flv_demux_get_type ()) ||
3588 !gst_element_register (plugin, "flvmux", GST_RANK_PRIMARY,
3589 gst_flv_mux_get_type ()))
3595 GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, GST_VERSION_MINOR,
3596 flv, "FLV muxing and demuxing plugin",
3597 plugin_init, VERSION, "LGPL", GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN)