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);
117 static void gst_flv_demux_push_tags (GstFlvDemux * demux);
120 gst_flv_demux_parse_and_add_index_entry (GstFlvDemux * demux, GstClockTime ts,
121 guint64 pos, gboolean keyframe)
123 GstIndexAssociation associations[2];
125 GstIndexEntry *entry;
127 GST_LOG_OBJECT (demux,
128 "adding key=%d association %" GST_TIME_FORMAT "-> %" G_GUINT64_FORMAT,
129 keyframe, GST_TIME_ARGS (ts), pos);
131 /* if upstream is not seekable there is no point in building an index */
132 if (!demux->upstream_seekable)
135 index = gst_flv_demux_get_index (GST_ELEMENT (demux));
140 /* entry may already have been added before, avoid adding indefinitely */
141 entry = gst_index_get_assoc_entry (index, demux->index_id,
142 GST_INDEX_LOOKUP_EXACT, GST_ASSOCIATION_FLAG_NONE, GST_FORMAT_BYTES, pos);
145 #ifndef GST_DISABLE_GST_DEBUG
149 gst_index_entry_assoc_map (entry, GST_FORMAT_TIME, &time);
150 key = ! !(GST_INDEX_ASSOC_FLAGS (entry) & GST_ASSOCIATION_FLAG_KEY_UNIT);
151 GST_LOG_OBJECT (demux, "position already mapped to time %" GST_TIME_FORMAT
152 ", keyframe %d", GST_TIME_ARGS (time), key);
153 /* there is not really a way to delete the existing one */
154 if (time != ts || key != ! !keyframe)
155 GST_DEBUG_OBJECT (demux, "metadata mismatch");
157 gst_object_unref (index);
161 associations[0].format = GST_FORMAT_TIME;
162 associations[0].value = ts;
163 associations[1].format = GST_FORMAT_BYTES;
164 associations[1].value = pos;
166 gst_index_add_associationv (index, demux->index_id,
167 (keyframe) ? GST_ASSOCIATION_FLAG_KEY_UNIT :
168 GST_ASSOCIATION_FLAG_DELTA_UNIT, 2,
169 (const GstIndexAssociation *) &associations);
171 if (pos > demux->index_max_pos)
172 demux->index_max_pos = pos;
173 if (ts > demux->index_max_time)
174 demux->index_max_time = ts;
176 gst_object_unref (index);
180 FLV_GET_STRING (GstByteReader * reader)
182 guint16 string_size = 0;
183 gchar *string = NULL;
184 const guint8 *str = NULL;
186 g_return_val_if_fail (reader != NULL, NULL);
188 if (G_UNLIKELY (!gst_byte_reader_get_uint16_be (reader, &string_size)))
191 if (G_UNLIKELY (string_size > gst_byte_reader_get_remaining (reader)))
194 string = g_try_malloc0 (string_size + 1);
195 if (G_UNLIKELY (!string)) {
199 if (G_UNLIKELY (!gst_byte_reader_get_data (reader, string_size, &str))) {
204 memcpy (string, str, string_size);
205 if (!g_utf8_validate (string, string_size, NULL)) {
214 gst_flv_demux_check_seekability (GstFlvDemux * demux)
217 gint64 start = -1, stop = -1;
219 demux->upstream_seekable = FALSE;
221 query = gst_query_new_seeking (GST_FORMAT_BYTES);
222 if (!gst_pad_peer_query (demux->sinkpad, query)) {
223 GST_DEBUG_OBJECT (demux, "seeking query failed");
224 gst_query_unref (query);
228 gst_query_parse_seeking (query, NULL, &demux->upstream_seekable,
231 gst_query_unref (query);
233 /* try harder to query upstream size if we didn't get it the first time */
234 if (demux->upstream_seekable && stop == -1) {
235 GST_DEBUG_OBJECT (demux, "doing duration query to fix up unset stop");
236 gst_pad_peer_query_duration (demux->sinkpad, GST_FORMAT_BYTES, &stop);
239 /* if upstream doesn't know the size, it's likely that it's not seekable in
240 * practice even if it technically may be seekable */
241 if (demux->upstream_seekable && (start != 0 || stop <= start)) {
242 GST_DEBUG_OBJECT (demux, "seekable but unknown start/stop -> disable");
243 demux->upstream_seekable = FALSE;
246 GST_DEBUG_OBJECT (demux, "upstream seekable: %d", demux->upstream_seekable);
250 parse_flv_demux_parse_date_string (const gchar * s)
252 static const gchar months[12][4] = {
253 "Jan", "Feb", "Mar", "Apr",
254 "May", "Jun", "Jul", "Aug",
255 "Sep", "Oct", "Nov", "Dec"
257 GstDateTime *dt = NULL;
260 gchar *endptr, *stripped;
262 gint year = -1, month = -1, day = -1;
263 gint hour = -1, minute = -1, seconds = -1;
265 stripped = g_strstrip (g_strdup (s));
267 /* "Fri Oct 15 15:13:16 2004" needs to be parsed */
268 tokens = g_strsplit (stripped, " ", -1);
272 if (g_strv_length (tokens) != 5)
276 d = g_ascii_strtoull (tokens[4], &endptr, 10);
277 if (d == 0 && *endptr != '\0')
283 if (strlen (tokens[1]) != 3)
285 for (i = 0; i < 12; i++) {
286 if (!strcmp (tokens[1], months[i])) {
296 d = g_ascii_strtoull (tokens[2], &endptr, 10);
297 if (d == 0 && *endptr != '\0')
304 if (sscanf (tokens[3], "%d:%d:%d", &hh, &mm, &ss) < 2)
306 if (hh >= 0 && hh < 24 && mm >= 0 && mm < 60 && ss >= 0 && ss < 60) {
318 dt = gst_date_time_new (0.0, year, month, day, hour, minute, seconds);
324 gst_flv_demux_parse_metadata_item (GstFlvDemux * demux, GstByteReader * reader,
325 gboolean * end_marker)
327 gchar *tag_name = NULL;
330 /* Initialize the end_marker flag to FALSE */
333 /* Name of the tag */
334 tag_name = FLV_GET_STRING (reader);
335 if (G_UNLIKELY (!tag_name)) {
336 GST_WARNING_OBJECT (demux, "failed reading tag name");
340 /* What kind of object is that */
341 if (!gst_byte_reader_get_uint8 (reader, &tag_type))
344 GST_DEBUG_OBJECT (demux, "tag name %s, tag type %d", tag_name, tag_type);
348 { /* Use a union to read the uint64 and then as a double */
351 if (!gst_byte_reader_get_float64_be (reader, &d))
354 GST_DEBUG_OBJECT (demux, "%s => (double) %f", tag_name, d);
356 if (!strcmp (tag_name, "duration")) {
357 demux->duration = d * GST_SECOND;
359 gst_tag_list_add (demux->taglist, GST_TAG_MERGE_REPLACE,
360 GST_TAG_DURATION, demux->duration, NULL);
361 } else if (!strcmp (tag_name, "AspectRatioX")) {
363 demux->got_par = TRUE;
364 } else if (!strcmp (tag_name, "AspectRatioY")) {
366 demux->got_par = TRUE;
367 } else if (!strcmp (tag_name, "width")) {
369 } else if (!strcmp (tag_name, "height")) {
371 } else if (!strcmp (tag_name, "framerate")) {
372 demux->framerate = d;
373 } else if (!strcmp (tag_name, "audiodatarate")) {
374 gst_tag_list_add (demux->audio_tags, GST_TAG_MERGE_REPLACE,
375 GST_TAG_NOMINAL_BITRATE, (guint) (d * 1024), NULL);
376 } else if (!strcmp (tag_name, "videodatarate")) {
377 gst_tag_list_add (demux->video_tags, GST_TAG_MERGE_REPLACE,
378 GST_TAG_NOMINAL_BITRATE, (guint) (d * 1024), NULL);
380 GST_INFO_OBJECT (demux, "Tag \'%s\' not handled", tag_name);
385 case 1: /* Boolean */
389 if (!gst_byte_reader_get_uint8 (reader, &b))
392 GST_DEBUG_OBJECT (demux, "%s => (boolean) %d", tag_name, b);
394 GST_INFO_OBJECT (demux, "Tag \'%s\' not handled", tag_name);
402 s = FLV_GET_STRING (reader);
406 GST_DEBUG_OBJECT (demux, "%s => (string) %s", tag_name, s);
408 if (!strcmp (tag_name, "creationdate")) {
411 dt = parse_flv_demux_parse_date_string (s);
413 GST_DEBUG_OBJECT (demux, "Failed to parse '%s' into datetime", s);
415 gst_tag_list_add (demux->taglist, GST_TAG_MERGE_REPLACE,
416 GST_TAG_DATE_TIME, dt, NULL);
417 gst_date_time_unref (dt);
419 } else if (!strcmp (tag_name, "creator")) {
420 gst_tag_list_add (demux->taglist, GST_TAG_MERGE_REPLACE,
421 GST_TAG_ARTIST, s, NULL);
422 } else if (!strcmp (tag_name, "title")) {
423 gst_tag_list_add (demux->taglist, GST_TAG_MERGE_REPLACE,
424 GST_TAG_TITLE, s, NULL);
425 } else if (!strcmp (tag_name, "metadatacreator")) {
426 gst_tag_list_add (demux->taglist, GST_TAG_MERGE_REPLACE,
427 GST_TAG_ENCODER, s, NULL);
429 GST_INFO_OBJECT (demux, "Tag \'%s\' not handled", tag_name);
438 gboolean end_of_object_marker = FALSE;
440 while (!end_of_object_marker) {
441 gboolean ok = gst_flv_demux_parse_metadata_item (demux, reader,
442 &end_of_object_marker);
444 if (G_UNLIKELY (!ok)) {
445 GST_WARNING_OBJECT (demux, "failed reading a tag, skipping");
452 case 8: /* ECMA array */
454 guint32 nb_elems = 0;
455 gboolean end_of_object_marker = FALSE;
457 if (!gst_byte_reader_get_uint32_be (reader, &nb_elems))
460 GST_DEBUG_OBJECT (demux, "there are approx. %d elements in the array",
463 while (!end_of_object_marker) {
464 gboolean ok = gst_flv_demux_parse_metadata_item (demux, reader,
465 &end_of_object_marker);
467 if (G_UNLIKELY (!ok)) {
468 GST_WARNING_OBJECT (demux, "failed reading a tag, skipping");
475 case 9: /* End marker */
477 GST_DEBUG_OBJECT (demux, "end marker ?");
478 if (tag_name[0] == '\0') {
480 GST_DEBUG_OBJECT (demux, "end marker detected");
489 guint32 nb_elems = 0;
491 if (!gst_byte_reader_get_uint32_be (reader, &nb_elems))
494 GST_DEBUG_OBJECT (demux, "array has %d elements", nb_elems);
496 if (!strcmp (tag_name, "times")) {
498 g_array_free (demux->times, TRUE);
500 demux->times = g_array_new (FALSE, TRUE, sizeof (gdouble));
501 } else if (!strcmp (tag_name, "filepositions")) {
502 if (demux->filepositions) {
503 g_array_free (demux->filepositions, TRUE);
505 demux->filepositions = g_array_new (FALSE, TRUE, sizeof (gdouble));
509 guint8 elem_type = 0;
511 if (!gst_byte_reader_get_uint8 (reader, &elem_type))
519 if (!gst_byte_reader_get_float64_be (reader, &d))
522 GST_DEBUG_OBJECT (demux, "element is a double %f", d);
524 if (!strcmp (tag_name, "times") && demux->times) {
525 g_array_append_val (demux->times, d);
526 } else if (!strcmp (tag_name, "filepositions") &&
527 demux->filepositions) {
528 g_array_append_val (demux->filepositions, d);
533 GST_WARNING_OBJECT (demux, "unsupported array element type %d",
545 if (!gst_byte_reader_get_float64_be (reader, &d))
548 if (!gst_byte_reader_get_int16_be (reader, &i))
551 GST_DEBUG_OBJECT (demux,
552 "%s => (date as a double) %f, timezone offset %d", tag_name, d, i);
554 GST_INFO_OBJECT (demux, "Tag \'%s\' not handled", tag_name);
559 GST_WARNING_OBJECT (demux, "unsupported tag type %d", tag_type);
573 gst_flv_demux_clear_tags (GstFlvDemux * demux)
575 GST_DEBUG_OBJECT (demux, "clearing taglist");
577 if (demux->taglist) {
578 gst_tag_list_unref (demux->taglist);
580 demux->taglist = gst_tag_list_new_empty ();
581 gst_tag_list_set_scope (demux->taglist, GST_TAG_SCOPE_GLOBAL);
583 if (demux->audio_tags) {
584 gst_tag_list_unref (demux->audio_tags);
586 demux->audio_tags = gst_tag_list_new_empty ();
588 if (demux->video_tags) {
589 gst_tag_list_unref (demux->video_tags);
591 demux->video_tags = gst_tag_list_new_empty ();
595 gst_flv_demux_parse_tag_script (GstFlvDemux * demux, GstBuffer * buffer)
597 GstFlowReturn ret = GST_FLOW_OK;
598 GstByteReader reader;
602 g_return_val_if_fail (gst_buffer_get_size (buffer) >= 7, GST_FLOW_ERROR);
604 gst_buffer_map (buffer, &map, GST_MAP_READ);
605 gst_byte_reader_init (&reader, map.data, map.size);
607 gst_byte_reader_skip_unchecked (&reader, 7);
609 GST_LOG_OBJECT (demux, "parsing a script tag");
611 if (!gst_byte_reader_get_uint8 (&reader, &type))
616 gchar *function_name;
619 function_name = FLV_GET_STRING (&reader);
621 GST_LOG_OBJECT (demux, "function name is %s", GST_STR_NULL (function_name));
623 if (function_name != NULL && strcmp (function_name, "onMetaData") == 0) {
624 gboolean end_marker = FALSE;
625 GST_DEBUG_OBJECT (demux, "we have a metadata script object");
627 gst_flv_demux_clear_tags (demux);
629 if (!gst_byte_reader_get_uint8 (&reader, &type)) {
630 g_free (function_name);
637 guint32 nb_elems = 0;
640 if (!gst_byte_reader_get_uint32_be (&reader, &nb_elems)) {
641 g_free (function_name);
645 /* The number of elements is just a hint, some files have
646 nb_elements == 0 and actually contain items. */
647 GST_DEBUG_OBJECT (demux, "there are approx. %d elements in the array",
650 /* fallthrough to read data */
654 while (!end_marker) {
656 gst_flv_demux_parse_metadata_item (demux, &reader, &end_marker);
658 if (G_UNLIKELY (!ok)) {
659 GST_WARNING_OBJECT (demux, "failed reading a tag, skipping");
666 GST_DEBUG_OBJECT (demux, "Unhandled script data type : %d", type);
667 g_free (function_name);
671 gst_flv_demux_push_tags (demux);
674 g_free (function_name);
676 if (demux->times && demux->filepositions) {
679 /* If an index was found, insert associations */
680 num = MIN (demux->times->len, demux->filepositions->len);
681 for (i = 0; i < num; i++) {
682 guint64 time, fileposition;
684 time = g_array_index (demux->times, gdouble, i) * GST_SECOND;
685 fileposition = g_array_index (demux->filepositions, gdouble, i);
686 gst_flv_demux_parse_and_add_index_entry (demux, time, fileposition,
689 demux->indexed = TRUE;
694 gst_buffer_unmap (buffer, &map);
700 have_group_id (GstFlvDemux * demux)
704 event = gst_pad_get_sticky_event (demux->sinkpad, GST_EVENT_STREAM_START, 0);
706 if (gst_event_parse_group_id (event, &demux->group_id))
707 demux->have_group_id = TRUE;
709 demux->have_group_id = FALSE;
710 gst_event_unref (event);
711 } else if (!demux->have_group_id) {
712 demux->have_group_id = TRUE;
713 demux->group_id = gst_util_group_id_next ();
716 return demux->have_group_id;
720 gst_flv_demux_audio_negotiate (GstFlvDemux * demux, guint32 codec_tag,
721 guint32 rate, guint32 channels, guint32 width)
723 GstCaps *caps = NULL, *old_caps;
724 gboolean ret = FALSE;
725 guint adjusted_rate = rate;
731 caps = gst_caps_new_simple ("audio/x-adpcm", "layout", G_TYPE_STRING,
736 caps = gst_caps_new_simple ("audio/mpeg",
737 "mpegversion", G_TYPE_INT, 1, "layer", G_TYPE_INT, 3,
738 "parsed", G_TYPE_BOOLEAN, TRUE, NULL);
743 GstAudioFormat format;
745 /* Assuming little endian for 0 (aka endianness of the
746 * system on which the file was created) as most people
747 * are probably using little endian machines */
748 format = gst_audio_format_build_integer ((width == 8) ? FALSE : TRUE,
749 G_LITTLE_ENDIAN, width, width);
751 caps = gst_caps_new_simple ("audio/x-raw",
752 "format", G_TYPE_STRING, gst_audio_format_to_string (format),
753 "layout", G_TYPE_STRING, "interleaved", NULL);
759 caps = gst_caps_new_empty_simple ("audio/x-nellymoser");
764 if (!demux->audio_codec_data) {
765 GST_DEBUG_OBJECT (demux, "don't have AAC codec data yet");
770 gst_buffer_map (demux->audio_codec_data, &map, GST_MAP_READ);
772 /* use codec-data to extract and verify samplerate */
776 freq_index = GST_READ_UINT16_BE (map.data);
777 freq_index = (freq_index & 0x0780) >> 7;
779 gst_codec_utils_aac_get_sample_rate_from_index (freq_index);
781 if (adjusted_rate && (rate != adjusted_rate)) {
782 GST_LOG_OBJECT (demux, "Ajusting AAC sample rate %d -> %d", rate,
785 adjusted_rate = rate;
788 gst_buffer_unmap (demux->audio_codec_data, &map);
790 caps = gst_caps_new_simple ("audio/mpeg",
791 "mpegversion", G_TYPE_INT, 4, "framed", G_TYPE_BOOLEAN, TRUE,
792 "stream-format", G_TYPE_STRING, "raw", NULL);
796 caps = gst_caps_new_empty_simple ("audio/x-alaw");
799 caps = gst_caps_new_empty_simple ("audio/x-mulaw");
803 GValue streamheader = G_VALUE_INIT;
804 GValue value = G_VALUE_INIT;
806 GstStructure *structure;
810 caps = gst_caps_new_empty_simple ("audio/x-speex");
811 structure = gst_caps_get_structure (caps, 0);
813 GST_DEBUG_OBJECT (demux, "generating speex header");
815 /* Speex decoder expects streamheader to be { [header], [comment] } */
816 g_value_init (&streamheader, GST_TYPE_ARRAY);
819 gst_byte_writer_init_with_size (&w, 80, TRUE);
820 gst_byte_writer_put_data (&w, (guint8 *) "Speex ", 8);
821 gst_byte_writer_put_data (&w, (guint8 *) "1.1.12", 7);
822 gst_byte_writer_fill (&w, 0, 13);
823 gst_byte_writer_put_uint32_le (&w, 1); /* version */
824 gst_byte_writer_put_uint32_le (&w, 80); /* header_size */
825 gst_byte_writer_put_uint32_le (&w, 16000); /* rate */
826 gst_byte_writer_put_uint32_le (&w, 1); /* mode: Wideband */
827 gst_byte_writer_put_uint32_le (&w, 4); /* mode_bitstream_version */
828 gst_byte_writer_put_uint32_le (&w, 1); /* nb_channels: 1 */
829 gst_byte_writer_put_uint32_le (&w, -1); /* bitrate */
830 gst_byte_writer_put_uint32_le (&w, 0x50); /* frame_size */
831 gst_byte_writer_put_uint32_le (&w, 0); /* VBR */
832 gst_byte_writer_put_uint32_le (&w, 1); /* frames_per_packet */
833 gst_byte_writer_put_uint32_le (&w, 0); /* extra_headers */
834 gst_byte_writer_put_uint32_le (&w, 0); /* reserved1 */
835 gst_byte_writer_put_uint32_le (&w, 0); /* reserved2 */
836 g_assert (gst_byte_writer_get_size (&w) == 80);
838 g_value_init (&value, GST_TYPE_BUFFER);
839 g_value_take_boxed (&value, gst_byte_writer_reset_and_get_buffer (&w));
840 gst_value_array_append_value (&streamheader, &value);
841 g_value_unset (&value);
844 g_value_init (&value, GST_TYPE_BUFFER);
845 tags = gst_tag_list_new_empty ();
846 buf = gst_tag_list_to_vorbiscomment_buffer (tags, NULL, 0, "No comments");
847 gst_tag_list_unref (tags);
848 g_value_take_boxed (&value, buf);
849 gst_value_array_append_value (&streamheader, &value);
850 g_value_unset (&value);
852 gst_structure_take_value (structure, "streamheader", &streamheader);
855 adjusted_rate = 16000;
859 GST_WARNING_OBJECT (demux, "unsupported audio codec tag %u", codec_tag);
863 if (G_UNLIKELY (!caps)) {
864 GST_WARNING_OBJECT (demux, "failed creating caps for audio pad");
868 gst_caps_set_simple (caps, "rate", G_TYPE_INT, adjusted_rate,
869 "channels", G_TYPE_INT, channels, NULL);
871 if (demux->audio_codec_data) {
872 gst_caps_set_simple (caps, "codec_data", GST_TYPE_BUFFER,
873 demux->audio_codec_data, NULL);
876 old_caps = gst_pad_get_current_caps (demux->audio_pad);
879 gst_pad_create_stream_id (demux->audio_pad, GST_ELEMENT_CAST (demux),
882 event = gst_event_new_stream_start (stream_id);
883 if (have_group_id (demux))
884 gst_event_set_group_id (event, demux->group_id);
885 gst_pad_push_event (demux->audio_pad, event);
888 if (!old_caps || !gst_caps_is_equal (old_caps, caps))
889 ret = gst_pad_set_caps (demux->audio_pad, caps);
894 gst_caps_unref (old_caps);
897 if (G_LIKELY (ret)) {
898 /* Store the caps we got from tags */
899 demux->audio_codec_tag = codec_tag;
901 demux->channels = channels;
902 demux->width = width;
905 GST_DEBUG_OBJECT (demux->audio_pad, "successfully negotiated caps %"
906 GST_PTR_FORMAT, caps);
908 gst_flv_demux_push_tags (demux);
910 GST_DEBUG_OBJECT (demux->audio_pad, "delayed setting caps");
913 GST_WARNING_OBJECT (demux->audio_pad, "failed negotiating caps %"
914 GST_PTR_FORMAT, caps);
918 gst_caps_unref (caps);
925 gst_flv_demux_push_src_event (GstFlvDemux * demux, GstEvent * event)
929 if (demux->audio_pad)
930 ret |= gst_pad_push_event (demux->audio_pad, gst_event_ref (event));
932 if (demux->video_pad)
933 ret |= gst_pad_push_event (demux->video_pad, gst_event_ref (event));
935 gst_event_unref (event);
941 gst_flv_demux_add_codec_tag (GstFlvDemux * demux, const gchar * tag,
945 GstCaps *caps = gst_pad_get_current_caps (pad);
948 gchar *codec_name = gst_pb_utils_get_codec_description (caps);
951 gst_tag_list_add (demux->taglist, GST_TAG_MERGE_REPLACE,
952 tag, codec_name, NULL);
956 gst_caps_unref (caps);
962 gst_flv_demux_push_tags (GstFlvDemux * demux)
964 gst_flv_demux_add_codec_tag (demux, GST_TAG_AUDIO_CODEC, demux->audio_pad);
965 gst_flv_demux_add_codec_tag (demux, GST_TAG_VIDEO_CODEC, demux->video_pad);
967 GST_DEBUG_OBJECT (demux, "pushing %" GST_PTR_FORMAT, demux->taglist);
969 gst_flv_demux_push_src_event (demux,
970 gst_event_new_tag (gst_tag_list_copy (demux->taglist)));
972 if (demux->audio_pad) {
973 GST_DEBUG_OBJECT (demux->audio_pad, "pushing audio %" GST_PTR_FORMAT,
975 gst_pad_push_event (demux->audio_pad,
976 gst_event_new_tag (gst_tag_list_copy (demux->audio_tags)));
979 if (demux->video_pad) {
980 GST_DEBUG_OBJECT (demux->video_pad, "pushing video %" GST_PTR_FORMAT,
982 gst_pad_push_event (demux->video_pad,
983 gst_event_new_tag (gst_tag_list_copy (demux->video_tags)));
988 gst_flv_demux_update_resync (GstFlvDemux * demux, guint32 dts, gboolean discont,
989 guint32 * last, GstClockTime * offset)
991 gboolean ret = FALSE;
992 gint32 ddts = dts - *last;
993 if (!discont && ddts <= -RESYNC_THRESHOLD) {
994 /* Theoretically, we should use substract the duration of the last buffer,
995 but this demuxer sends no durations on buffers, not sure if it cannot
996 know, or just does not care to calculate. */
997 *offset -= ddts * GST_MSECOND;
998 GST_WARNING_OBJECT (demux,
999 "Large dts gap (%" G_GINT32_FORMAT " ms), assuming resync, offset now %"
1000 GST_TIME_FORMAT "", ddts, GST_TIME_ARGS (*offset));
1009 static GstFlowReturn
1010 gst_flv_demux_parse_tag_audio (GstFlvDemux * demux, GstBuffer * buffer)
1012 GstFlowReturn ret = GST_FLOW_OK;
1013 guint32 pts = 0, codec_tag = 0, rate = 5512, width = 8, channels = 1;
1014 guint32 codec_data = 0, pts_ext = 0;
1020 GST_LOG_OBJECT (demux, "parsing an audio tag");
1022 if (G_UNLIKELY (!demux->audio_pad && demux->no_more_pads)) {
1023 #ifndef GST_DISABLE_DEBUG
1024 if (G_UNLIKELY (!demux->no_audio_warned)) {
1025 GST_WARNING_OBJECT (demux,
1026 "Signaled no-more-pads already but had no audio pad -- ignoring");
1027 demux->no_audio_warned = TRUE;
1033 g_return_val_if_fail (gst_buffer_get_size (buffer) == demux->tag_size,
1036 /* Error out on tags with too small headers */
1037 if (gst_buffer_get_size (buffer) < 11) {
1038 GST_ERROR_OBJECT (demux, "Too small tag size (%" G_GSIZE_FORMAT ")",
1039 gst_buffer_get_size (buffer));
1040 return GST_FLOW_ERROR;
1043 gst_buffer_map (buffer, &map, GST_MAP_READ);
1046 /* Grab information about audio tag */
1047 pts = GST_READ_UINT24_BE (data);
1048 /* read the pts extension to 32 bits integer */
1049 pts_ext = GST_READ_UINT8 (data + 3);
1051 pts |= pts_ext << 24;
1053 GST_LOG_OBJECT (demux, "pts bytes %02X %02X %02X %02X (%d)", data[0], data[1],
1054 data[2], data[3], pts);
1056 /* Skip the stream id and go directly to the flags */
1057 flags = GST_READ_UINT8 (data + 7);
1059 /* Silently skip buffers with no data */
1072 if ((flags & 0x0C) == 0x0C) {
1074 } else if ((flags & 0x0C) == 0x08) {
1076 } else if ((flags & 0x0C) == 0x04) {
1080 codec_tag = flags >> 4;
1081 if (codec_tag == 10) { /* AAC has an extra byte for packet type */
1087 /* codec tags with special rates */
1088 if (codec_tag == 5 || codec_tag == 14)
1090 else if ((codec_tag == 4) || (codec_tag == 11))
1093 GST_LOG_OBJECT (demux, "audio tag with %d channels, %dHz sampling rate, "
1094 "%d bits width, codec tag %u (flags %02X)", channels, rate, width,
1097 if (codec_tag == 10) {
1098 guint8 aac_packet_type = GST_READ_UINT8 (data + 8);
1100 switch (aac_packet_type) {
1103 /* AudioSpecificConfig data */
1104 GST_LOG_OBJECT (demux, "got an AAC codec data packet");
1105 if (demux->audio_codec_data) {
1106 gst_buffer_unref (demux->audio_codec_data);
1108 demux->audio_codec_data =
1109 gst_buffer_copy_region (buffer, GST_BUFFER_COPY_MEMORY,
1110 7 + codec_data, demux->tag_data_size - codec_data);
1112 /* Use that buffer data in the caps */
1113 if (demux->audio_pad)
1114 gst_flv_demux_audio_negotiate (demux, codec_tag, rate, channels,
1119 if (!demux->audio_codec_data) {
1120 GST_ERROR_OBJECT (demux, "got AAC audio packet before codec data");
1124 /* AAC raw packet */
1125 GST_LOG_OBJECT (demux, "got a raw AAC audio packet");
1128 GST_WARNING_OBJECT (demux, "invalid AAC packet type %u",
1133 /* If we don't have our audio pad created, then create it. */
1134 if (G_UNLIKELY (!demux->audio_pad)) {
1136 gst_pad_new_from_template (gst_element_class_get_pad_template
1137 (GST_ELEMENT_GET_CLASS (demux), "audio"), "audio");
1138 if (G_UNLIKELY (!demux->audio_pad)) {
1139 GST_WARNING_OBJECT (demux, "failed creating audio pad");
1140 ret = GST_FLOW_ERROR;
1144 /* Set functions on the pad */
1145 gst_pad_set_query_function (demux->audio_pad,
1146 GST_DEBUG_FUNCPTR (gst_flv_demux_query));
1147 gst_pad_set_event_function (demux->audio_pad,
1148 GST_DEBUG_FUNCPTR (gst_flv_demux_src_event));
1150 gst_pad_use_fixed_caps (demux->audio_pad);
1152 /* Make it active */
1153 gst_pad_set_active (demux->audio_pad, TRUE);
1155 /* Negotiate caps */
1156 if (!gst_flv_demux_audio_negotiate (demux, codec_tag, rate, channels,
1158 gst_object_unref (demux->audio_pad);
1159 demux->audio_pad = NULL;
1160 ret = GST_FLOW_ERROR;
1163 #ifndef GST_DISABLE_GST_DEBUG
1167 caps = gst_pad_get_current_caps (demux->audio_pad);
1168 GST_DEBUG_OBJECT (demux, "created audio pad with caps %" GST_PTR_FORMAT,
1171 gst_caps_unref (caps);
1175 /* We need to set caps before adding */
1176 gst_element_add_pad (GST_ELEMENT (demux),
1177 gst_object_ref (demux->audio_pad));
1178 gst_flow_combiner_add_pad (demux->flowcombiner, demux->audio_pad);
1180 /* We only emit no more pads when we have audio and video. Indeed we can
1181 * not trust the FLV header to tell us if there will be only audio or
1182 * only video and we would just break discovery of some files */
1183 if (demux->audio_pad && demux->video_pad) {
1184 GST_DEBUG_OBJECT (demux, "emitting no more pads");
1185 gst_element_no_more_pads (GST_ELEMENT (demux));
1186 demux->no_more_pads = TRUE;
1190 /* Check if caps have changed */
1191 if (G_UNLIKELY (rate != demux->rate || channels != demux->channels ||
1192 codec_tag != demux->audio_codec_tag || width != demux->width)) {
1193 GST_DEBUG_OBJECT (demux, "audio settings have changed, changing caps");
1195 gst_buffer_replace (&demux->audio_codec_data, NULL);
1197 /* Negotiate caps */
1198 if (!gst_flv_demux_audio_negotiate (demux, codec_tag, rate, channels,
1200 ret = GST_FLOW_ERROR;
1205 /* Check if we have anything to push */
1206 if (demux->tag_data_size <= codec_data) {
1207 GST_LOG_OBJECT (demux, "Nothing left in this tag, returning");
1211 /* Create buffer from pad */
1212 outbuf = gst_buffer_copy_region (buffer, GST_BUFFER_COPY_MEMORY,
1213 7 + codec_data, demux->tag_data_size - codec_data);
1215 /* detect (and deem to be resyncs) large pts gaps */
1216 if (gst_flv_demux_update_resync (demux, pts, demux->audio_need_discont,
1217 &demux->last_audio_pts, &demux->audio_time_offset)) {
1218 GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_RESYNC);
1221 /* Fill buffer with data */
1222 GST_BUFFER_PTS (outbuf) = pts * GST_MSECOND + demux->audio_time_offset;
1223 GST_BUFFER_DTS (outbuf) = GST_BUFFER_PTS (outbuf);
1224 GST_BUFFER_DURATION (outbuf) = GST_CLOCK_TIME_NONE;
1225 GST_BUFFER_OFFSET (outbuf) = demux->audio_offset++;
1226 GST_BUFFER_OFFSET_END (outbuf) = demux->audio_offset;
1228 if (demux->duration == GST_CLOCK_TIME_NONE ||
1229 demux->duration < GST_BUFFER_TIMESTAMP (outbuf))
1230 demux->duration = GST_BUFFER_TIMESTAMP (outbuf);
1232 /* Only add audio frames to the index if we have no video,
1233 * and if the index is not yet complete */
1234 if (!demux->has_video && !demux->indexed) {
1235 gst_flv_demux_parse_and_add_index_entry (demux,
1236 GST_BUFFER_TIMESTAMP (outbuf), demux->cur_tag_offset, TRUE);
1239 if (G_UNLIKELY (demux->audio_need_discont)) {
1240 GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_DISCONT);
1241 demux->audio_need_discont = FALSE;
1244 demux->segment.position = GST_BUFFER_TIMESTAMP (outbuf);
1246 /* Do we need a newsegment event ? */
1247 if (G_UNLIKELY (demux->audio_need_segment)) {
1248 if (!demux->new_seg_event) {
1249 GST_DEBUG_OBJECT (demux, "pushing newsegment from %"
1250 GST_TIME_FORMAT " to %" GST_TIME_FORMAT,
1251 GST_TIME_ARGS (demux->segment.position),
1252 GST_TIME_ARGS (demux->segment.stop));
1253 demux->segment.start = demux->segment.time = demux->segment.position;
1254 demux->new_seg_event = gst_event_new_segment (&demux->segment);
1256 GST_DEBUG_OBJECT (demux, "pushing pre-generated newsegment event");
1259 gst_pad_push_event (demux->audio_pad, gst_event_ref (demux->new_seg_event));
1261 demux->audio_need_segment = FALSE;
1264 GST_LOG_OBJECT (demux,
1265 "pushing %" G_GSIZE_FORMAT " bytes buffer at pts %" GST_TIME_FORMAT
1266 " with duration %" GST_TIME_FORMAT ", offset %" G_GUINT64_FORMAT,
1267 gst_buffer_get_size (outbuf),
1268 GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (outbuf)),
1269 GST_TIME_ARGS (GST_BUFFER_DURATION (outbuf)), GST_BUFFER_OFFSET (outbuf));
1271 if (!GST_CLOCK_TIME_IS_VALID (demux->audio_start)) {
1272 demux->audio_start = GST_BUFFER_TIMESTAMP (outbuf);
1274 if (!GST_CLOCK_TIME_IS_VALID (demux->audio_first_ts)) {
1275 demux->audio_first_ts = GST_BUFFER_TIMESTAMP (outbuf);
1278 if (G_UNLIKELY (!demux->no_more_pads
1279 && (GST_CLOCK_DIFF (demux->audio_start,
1280 GST_BUFFER_TIMESTAMP (outbuf)) > NO_MORE_PADS_THRESHOLD))) {
1281 GST_DEBUG_OBJECT (demux,
1282 "Signalling no-more-pads because no video stream was found"
1283 " after 6 seconds of audio");
1284 gst_element_no_more_pads (GST_ELEMENT_CAST (demux));
1285 demux->no_more_pads = TRUE;
1288 /* Push downstream */
1289 ret = gst_pad_push (demux->audio_pad, outbuf);
1291 if (G_UNLIKELY (ret != GST_FLOW_OK) &&
1292 demux->segment.rate < 0.0 && ret == GST_FLOW_EOS &&
1293 demux->segment.position > demux->segment.stop) {
1294 /* In reverse playback we can get a GST_FLOW_EOS when
1295 * we are at the end of the segment, so we just need to jump
1296 * back to the previous section. */
1297 GST_DEBUG_OBJECT (demux, "downstream has reached end of segment");
1298 demux->audio_done = TRUE;
1303 ret = gst_flow_combiner_update_pad_flow (demux->flowcombiner,
1304 demux->audio_pad, ret);
1307 gst_buffer_unmap (buffer, &map);
1313 gst_flv_demux_video_negotiate (GstFlvDemux * demux, guint32 codec_tag)
1315 gboolean ret = FALSE;
1316 GstCaps *caps = NULL, *old_caps;
1320 /* Generate caps for that pad */
1321 switch (codec_tag) {
1324 gst_caps_new_simple ("video/x-flash-video", "flvversion", G_TYPE_INT,
1328 caps = gst_caps_new_empty_simple ("video/x-flash-screen");
1331 caps = gst_caps_new_empty_simple ("video/x-vp6-flash");
1334 caps = gst_caps_new_empty_simple ("video/x-vp6-alpha");
1337 if (!demux->video_codec_data) {
1338 GST_DEBUG_OBJECT (demux, "don't have h264 codec data yet");
1343 gst_caps_new_simple ("video/x-h264", "stream-format", G_TYPE_STRING,
1346 /* The following two are non-standard but apparently used, see in ffmpeg
1347 * https://git.videolan.org/?p=ffmpeg.git;a=blob;f=libavformat/flvdec.c;h=2bf1e059e1cbeeb79e4af9542da23f4560e1cf59;hb=b18d6c58000beed872d6bb1fe7d0fbe75ae26aef#l254
1348 * https://git.videolan.org/?p=ffmpeg.git;a=blob;f=libavformat/flvdec.c;h=2bf1e059e1cbeeb79e4af9542da23f4560e1cf59;hb=b18d6c58000beed872d6bb1fe7d0fbe75ae26aef#l282
1351 caps = gst_caps_new_empty_simple ("video/x-h263");
1355 gst_caps_new_simple ("video/mpeg", "mpegversion", G_TYPE_INT, 4,
1356 "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
1359 GST_WARNING_OBJECT (demux, "unsupported video codec tag %u", codec_tag);
1362 if (G_UNLIKELY (!caps)) {
1363 GST_WARNING_OBJECT (demux, "failed creating caps for video pad");
1367 if (demux->got_par) {
1368 gst_caps_set_simple (caps, "pixel-aspect-ratio", GST_TYPE_FRACTION,
1369 demux->par_x, demux->par_y, NULL);
1372 if (G_LIKELY (demux->w)) {
1373 gst_caps_set_simple (caps, "width", G_TYPE_INT, demux->w, NULL);
1376 if (G_LIKELY (demux->h)) {
1377 gst_caps_set_simple (caps, "height", G_TYPE_INT, demux->h, NULL);
1380 if (G_LIKELY (demux->framerate)) {
1381 gint num = 0, den = 0;
1383 gst_video_guess_framerate (GST_SECOND / demux->framerate, &num, &den);
1384 GST_DEBUG_OBJECT (demux->video_pad,
1385 "fps to be used on caps %f (as a fraction = %d/%d)", demux->framerate,
1388 gst_caps_set_simple (caps, "framerate", GST_TYPE_FRACTION, num, den, NULL);
1391 if (demux->video_codec_data) {
1392 gst_caps_set_simple (caps, "codec_data", GST_TYPE_BUFFER,
1393 demux->video_codec_data, NULL);
1396 old_caps = gst_pad_get_current_caps (demux->video_pad);
1399 gst_pad_create_stream_id (demux->video_pad, GST_ELEMENT_CAST (demux),
1401 event = gst_event_new_stream_start (stream_id);
1404 if (have_group_id (demux))
1405 gst_event_set_group_id (event, demux->group_id);
1406 gst_pad_push_event (demux->video_pad, event);
1409 if (!old_caps || !gst_caps_is_equal (old_caps, caps))
1410 ret = gst_pad_set_caps (demux->video_pad, caps);
1415 gst_caps_unref (old_caps);
1418 if (G_LIKELY (ret)) {
1419 /* Store the caps we have set */
1420 demux->video_codec_tag = codec_tag;
1423 GST_DEBUG_OBJECT (demux->video_pad, "successfully negotiated caps %"
1424 GST_PTR_FORMAT, caps);
1426 gst_flv_demux_push_tags (demux);
1428 GST_DEBUG_OBJECT (demux->video_pad, "delayed setting caps");
1431 GST_WARNING_OBJECT (demux->video_pad, "failed negotiating caps %"
1432 GST_PTR_FORMAT, caps);
1436 gst_caps_unref (caps);
1442 static GstFlowReturn
1443 gst_flv_demux_parse_tag_video (GstFlvDemux * demux, GstBuffer * buffer)
1445 GstFlowReturn ret = GST_FLOW_OK;
1446 guint32 dts = 0, codec_data = 1, dts_ext = 0;
1448 gboolean keyframe = FALSE;
1449 guint8 flags = 0, codec_tag = 0;
1454 g_return_val_if_fail (gst_buffer_get_size (buffer) == demux->tag_size,
1457 GST_LOG_OBJECT (demux, "parsing a video tag");
1460 (!demux->video_pad && demux->no_more_pads) {
1461 #ifndef GST_DISABLE_DEBUG
1463 (!demux->no_video_warned) {
1464 GST_WARNING_OBJECT (demux,
1465 "Signaled no-more-pads already but had no video pad -- ignoring");
1466 demux->no_video_warned = TRUE;
1472 if (gst_buffer_get_size (buffer) < 12) {
1473 GST_ERROR_OBJECT (demux, "Too small tag size");
1474 return GST_FLOW_ERROR;
1477 gst_buffer_map (buffer, &map, GST_MAP_READ);
1480 /* Grab information about video tag */
1481 dts = GST_READ_UINT24_BE (data);
1482 /* read the dts extension to 32 bits integer */
1483 dts_ext = GST_READ_UINT8 (data + 3);
1485 dts |= dts_ext << 24;
1487 GST_LOG_OBJECT (demux, "dts bytes %02X %02X %02X %02X (%d)", data[0], data[1],
1488 data[2], data[3], dts);
1490 /* Skip the stream id and go directly to the flags */
1491 flags = GST_READ_UINT8 (data + 7);
1494 if ((flags >> 4) == 1) {
1498 codec_tag = flags & 0x0F;
1499 if (codec_tag == 4 || codec_tag == 5) {
1501 } else if (codec_tag == 7) {
1504 cts = GST_READ_UINT24_BE (data + 9);
1505 cts = (cts + 0xff800000) ^ 0xff800000;
1507 if (cts < 0 && ABS (cts) > dts) {
1508 GST_ERROR_OBJECT (demux, "Detected a negative composition time offset "
1509 "'%d' that would lead to negative PTS, fixing", cts);
1510 cts += ABS (cts) - dts;
1513 GST_LOG_OBJECT (demux, "got cts %d", cts);
1516 GST_LOG_OBJECT (demux, "video tag with codec tag %u, keyframe (%d) "
1517 "(flags %02X)", codec_tag, keyframe, flags);
1519 if (codec_tag == 7) {
1520 guint8 avc_packet_type = GST_READ_UINT8 (data + 8);
1522 switch (avc_packet_type) {
1525 if (demux->tag_data_size < codec_data) {
1526 GST_ERROR_OBJECT (demux, "Got invalid H.264 codec, ignoring.");
1530 /* AVCDecoderConfigurationRecord data */
1531 GST_LOG_OBJECT (demux, "got an H.264 codec data packet");
1532 if (demux->video_codec_data) {
1533 gst_buffer_unref (demux->video_codec_data);
1535 demux->video_codec_data = gst_buffer_copy_region (buffer,
1536 GST_BUFFER_COPY_MEMORY, 7 + codec_data,
1537 demux->tag_data_size - codec_data);;
1538 /* Use that buffer data in the caps */
1539 if (demux->video_pad)
1540 gst_flv_demux_video_negotiate (demux, codec_tag);
1544 /* H.264 NALU packet */
1545 if (!demux->video_codec_data) {
1546 GST_ERROR_OBJECT (demux, "got H.264 video packet before codec data");
1550 GST_LOG_OBJECT (demux, "got a H.264 NALU video packet");
1553 GST_WARNING_OBJECT (demux, "invalid video packet type %u",
1558 /* If we don't have our video pad created, then create it. */
1559 if (G_UNLIKELY (!demux->video_pad)) {
1561 gst_pad_new_from_template (gst_element_class_get_pad_template
1562 (GST_ELEMENT_GET_CLASS (demux), "video"), "video");
1563 if (G_UNLIKELY (!demux->video_pad)) {
1564 GST_WARNING_OBJECT (demux, "failed creating video pad");
1565 ret = GST_FLOW_ERROR;
1569 /* Set functions on the pad */
1570 gst_pad_set_query_function (demux->video_pad,
1571 GST_DEBUG_FUNCPTR (gst_flv_demux_query));
1572 gst_pad_set_event_function (demux->video_pad,
1573 GST_DEBUG_FUNCPTR (gst_flv_demux_src_event));
1575 gst_pad_use_fixed_caps (demux->video_pad);
1577 /* Make it active */
1578 gst_pad_set_active (demux->video_pad, TRUE);
1580 /* Needs to be active before setting caps */
1581 if (!gst_flv_demux_video_negotiate (demux, codec_tag)) {
1582 gst_object_unref (demux->video_pad);
1583 demux->video_pad = NULL;
1584 ret = GST_FLOW_ERROR;
1588 /* When we ve set pixel-aspect-ratio we use that boolean to detect a
1589 * metadata tag that would come later and trigger a caps change */
1590 demux->got_par = FALSE;
1592 #ifndef GST_DISABLE_GST_DEBUG
1596 caps = gst_pad_get_current_caps (demux->video_pad);
1597 GST_DEBUG_OBJECT (demux, "created video pad with caps %" GST_PTR_FORMAT,
1600 gst_caps_unref (caps);
1604 /* We need to set caps before adding */
1605 gst_element_add_pad (GST_ELEMENT (demux),
1606 gst_object_ref (demux->video_pad));
1607 gst_flow_combiner_add_pad (demux->flowcombiner, demux->video_pad);
1609 /* We only emit no more pads when we have audio and video. Indeed we can
1610 * not trust the FLV header to tell us if there will be only audio or
1611 * only video and we would just break discovery of some files */
1612 if (demux->audio_pad && demux->video_pad) {
1613 GST_DEBUG_OBJECT (demux, "emitting no more pads");
1614 gst_element_no_more_pads (GST_ELEMENT (demux));
1615 demux->no_more_pads = TRUE;
1619 /* Check if caps have changed */
1620 if (G_UNLIKELY (codec_tag != demux->video_codec_tag || demux->got_par)) {
1621 GST_DEBUG_OBJECT (demux, "video settings have changed, changing caps");
1622 gst_buffer_replace (&demux->video_codec_data, NULL);
1624 if (!gst_flv_demux_video_negotiate (demux, codec_tag)) {
1625 ret = GST_FLOW_ERROR;
1629 /* When we ve set pixel-aspect-ratio we use that boolean to detect a
1630 * metadata tag that would come later and trigger a caps change */
1631 demux->got_par = FALSE;
1634 /* Check if we have anything to push */
1635 if (demux->tag_data_size <= codec_data) {
1636 GST_LOG_OBJECT (demux, "Nothing left in this tag, returning");
1640 /* Create buffer from pad */
1641 outbuf = gst_buffer_copy_region (buffer, GST_BUFFER_COPY_MEMORY,
1642 7 + codec_data, demux->tag_data_size - codec_data);
1644 /* detect (and deem to be resyncs) large dts gaps */
1645 if (gst_flv_demux_update_resync (demux, dts, demux->video_need_discont,
1646 &demux->last_video_dts, &demux->video_time_offset)) {
1647 GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_RESYNC);
1650 /* Fill buffer with data */
1651 GST_LOG_OBJECT (demux, "dts %u pts %u cts %d", dts, dts + cts, cts);
1653 GST_BUFFER_PTS (outbuf) =
1654 (dts + cts) * GST_MSECOND + demux->video_time_offset;
1655 GST_BUFFER_DTS (outbuf) = dts * GST_MSECOND + demux->video_time_offset;
1656 GST_BUFFER_DURATION (outbuf) = GST_CLOCK_TIME_NONE;
1657 GST_BUFFER_OFFSET (outbuf) = demux->video_offset++;
1658 GST_BUFFER_OFFSET_END (outbuf) = demux->video_offset;
1660 if (demux->duration == GST_CLOCK_TIME_NONE ||
1661 demux->duration < GST_BUFFER_TIMESTAMP (outbuf))
1662 demux->duration = GST_BUFFER_TIMESTAMP (outbuf);
1665 GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_DELTA_UNIT);
1667 if (!demux->indexed) {
1668 gst_flv_demux_parse_and_add_index_entry (demux,
1669 GST_BUFFER_TIMESTAMP (outbuf), demux->cur_tag_offset, keyframe);
1672 if (G_UNLIKELY (demux->video_need_discont)) {
1673 GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_DISCONT);
1674 demux->video_need_discont = FALSE;
1677 demux->segment.position = GST_BUFFER_TIMESTAMP (outbuf);
1679 /* Do we need a newsegment event ? */
1680 if (G_UNLIKELY (demux->video_need_segment)) {
1681 if (!demux->new_seg_event) {
1682 GST_DEBUG_OBJECT (demux, "pushing newsegment from %"
1683 GST_TIME_FORMAT " to %" GST_TIME_FORMAT,
1684 GST_TIME_ARGS (demux->segment.position),
1685 GST_TIME_ARGS (demux->segment.stop));
1686 demux->segment.start = demux->segment.time = demux->segment.position;
1687 demux->new_seg_event = gst_event_new_segment (&demux->segment);
1689 GST_DEBUG_OBJECT (demux, "pushing pre-generated newsegment event");
1692 gst_pad_push_event (demux->video_pad, gst_event_ref (demux->new_seg_event));
1694 demux->video_need_segment = FALSE;
1697 GST_LOG_OBJECT (demux,
1698 "pushing %" G_GSIZE_FORMAT " bytes buffer at dts %" GST_TIME_FORMAT
1699 " with duration %" GST_TIME_FORMAT ", offset %" G_GUINT64_FORMAT
1700 ", keyframe (%d)", gst_buffer_get_size (outbuf),
1701 GST_TIME_ARGS (GST_BUFFER_DTS (outbuf)),
1702 GST_TIME_ARGS (GST_BUFFER_DURATION (outbuf)), GST_BUFFER_OFFSET (outbuf),
1705 if (!GST_CLOCK_TIME_IS_VALID (demux->video_start)) {
1706 demux->video_start = GST_BUFFER_TIMESTAMP (outbuf);
1708 if (!GST_CLOCK_TIME_IS_VALID (demux->audio_first_ts)) {
1709 demux->video_first_ts = GST_BUFFER_TIMESTAMP (outbuf);
1712 if (G_UNLIKELY (!demux->no_more_pads
1713 && (GST_CLOCK_DIFF (demux->video_start,
1714 GST_BUFFER_TIMESTAMP (outbuf)) > NO_MORE_PADS_THRESHOLD))) {
1715 GST_DEBUG_OBJECT (demux,
1716 "Signalling no-more-pads because no audio stream was found"
1717 " after 6 seconds of video");
1718 gst_element_no_more_pads (GST_ELEMENT_CAST (demux));
1719 demux->no_more_pads = TRUE;
1722 /* Push downstream */
1723 ret = gst_pad_push (demux->video_pad, outbuf);
1725 if (G_UNLIKELY (ret != GST_FLOW_OK) &&
1726 demux->segment.rate < 0.0 && ret == GST_FLOW_EOS &&
1727 demux->segment.position > demux->segment.stop) {
1728 /* In reverse playback we can get a GST_FLOW_EOS when
1729 * we are at the end of the segment, so we just need to jump
1730 * back to the previous section. */
1731 GST_DEBUG_OBJECT (demux, "downstream has reached end of segment");
1732 demux->video_done = TRUE;
1737 ret = gst_flow_combiner_update_pad_flow (demux->flowcombiner,
1738 demux->video_pad, ret);
1741 gst_buffer_unmap (buffer, &map);
1746 gst_flv_demux_parse_tag_timestamp (GstFlvDemux * demux, gboolean index,
1747 GstBuffer * buffer, size_t * tag_size)
1749 guint32 dts = 0, dts_ext = 0;
1750 guint32 tag_data_size;
1752 gboolean keyframe = TRUE;
1753 GstClockTime ret = GST_CLOCK_TIME_NONE;
1758 g_return_val_if_fail (gst_buffer_get_size (buffer) >= 12,
1759 GST_CLOCK_TIME_NONE);
1761 gst_buffer_map (buffer, &map, GST_MAP_READ);
1767 if (type != 9 && type != 8 && type != 18) {
1768 GST_WARNING_OBJECT (demux, "Unsupported tag type %u", data[0]);
1773 demux->has_video = TRUE;
1775 demux->has_audio = TRUE;
1777 tag_data_size = GST_READ_UINT24_BE (data + 1);
1779 if (size >= tag_data_size + 11 + 4) {
1780 if (GST_READ_UINT32_BE (data + tag_data_size + 11) != tag_data_size + 11) {
1781 GST_WARNING_OBJECT (demux, "Invalid tag size");
1787 *tag_size = tag_data_size + 11 + 4;
1791 GST_LOG_OBJECT (demux, "dts bytes %02X %02X %02X %02X", data[0], data[1],
1794 /* Grab timestamp of tag tag */
1795 dts = GST_READ_UINT24_BE (data);
1796 /* read the dts extension to 32 bits integer */
1797 dts_ext = GST_READ_UINT8 (data + 3);
1799 dts |= dts_ext << 24;
1804 keyframe = ((data[0] >> 4) == 1);
1807 ret = dts * GST_MSECOND;
1808 GST_LOG_OBJECT (demux, "dts: %" GST_TIME_FORMAT, GST_TIME_ARGS (ret));
1810 if (index && !demux->indexed && (type == 9 || (type == 8
1811 && !demux->has_video))) {
1812 gst_flv_demux_parse_and_add_index_entry (demux, ret, demux->offset,
1816 if (demux->duration == GST_CLOCK_TIME_NONE || demux->duration < ret)
1817 demux->duration = ret;
1820 gst_buffer_unmap (buffer, &map);
1824 static GstFlowReturn
1825 gst_flv_demux_parse_tag_type (GstFlvDemux * demux, GstBuffer * buffer)
1827 GstFlowReturn ret = GST_FLOW_OK;
1828 guint8 tag_type = 0;
1831 g_return_val_if_fail (gst_buffer_get_size (buffer) >= 4, GST_FLOW_ERROR);
1833 gst_buffer_map (buffer, &map, GST_MAP_READ);
1835 tag_type = map.data[0];
1837 /* Tag size is 1 byte of type + 3 bytes of size + 7 bytes + tag data size +
1838 * 4 bytes of previous tag size */
1839 demux->tag_data_size = GST_READ_UINT24_BE (map.data + 1);
1840 demux->tag_size = demux->tag_data_size + 11;
1842 GST_LOG_OBJECT (demux, "tag data size is %" G_GUINT64_FORMAT,
1843 demux->tag_data_size);
1845 gst_buffer_unmap (buffer, &map);
1849 demux->state = FLV_STATE_TAG_VIDEO;
1850 demux->has_video = TRUE;
1853 demux->state = FLV_STATE_TAG_AUDIO;
1854 demux->has_audio = TRUE;
1857 demux->state = FLV_STATE_TAG_SCRIPT;
1860 GST_WARNING_OBJECT (demux, "unsupported tag type %u", tag_type);
1861 demux->state = FLV_STATE_SKIP;
1867 static GstFlowReturn
1868 gst_flv_demux_parse_header (GstFlvDemux * demux, GstBuffer * buffer)
1870 GstFlowReturn ret = GST_FLOW_OK;
1873 g_return_val_if_fail (gst_buffer_get_size (buffer) >= 9, GST_FLOW_ERROR);
1875 gst_buffer_map (buffer, &map, GST_MAP_READ);
1877 /* Check for the FLV tag */
1878 if (map.data[0] == 'F' && map.data[1] == 'L' && map.data[2] == 'V') {
1879 GST_DEBUG_OBJECT (demux, "FLV header detected");
1881 if (G_UNLIKELY (demux->strict)) {
1882 GST_WARNING_OBJECT (demux, "invalid header tag detected");
1888 if (map.data[3] == '1') {
1889 GST_DEBUG_OBJECT (demux, "FLV version 1 detected");
1891 if (G_UNLIKELY (demux->strict)) {
1892 GST_WARNING_OBJECT (demux, "invalid header version detected");
1899 /* Now look at audio/video flags */
1901 guint8 flags = map.data[4];
1903 demux->has_video = demux->has_audio = FALSE;
1906 GST_DEBUG_OBJECT (demux, "there is a video stream");
1907 demux->has_video = TRUE;
1910 GST_DEBUG_OBJECT (demux, "there is an audio stream");
1911 demux->has_audio = TRUE;
1915 /* do a one-time seekability check */
1916 gst_flv_demux_check_seekability (demux);
1918 /* We don't care about the rest */
1919 demux->need_header = FALSE;
1922 gst_buffer_unmap (buffer, &map);
1928 gst_flv_demux_flush (GstFlvDemux * demux, gboolean discont)
1930 GST_DEBUG_OBJECT (demux, "flushing queued data in the FLV demuxer");
1932 gst_adapter_clear (demux->adapter);
1934 demux->audio_need_discont = TRUE;
1935 demux->video_need_discont = TRUE;
1937 demux->flushing = FALSE;
1939 /* Only in push mode and if we're not during a seek */
1940 if (!demux->random_access && demux->state != FLV_STATE_SEEK) {
1941 /* After a flush we expect a tag_type */
1942 demux->state = FLV_STATE_TAG_TYPE;
1943 /* We reset the offset and will get one from first push */
1949 gst_flv_demux_cleanup (GstFlvDemux * demux)
1951 GST_DEBUG_OBJECT (demux, "cleaning up FLV demuxer");
1953 demux->state = FLV_STATE_HEADER;
1955 demux->have_group_id = FALSE;
1956 demux->group_id = G_MAXUINT;
1958 demux->flushing = FALSE;
1959 demux->need_header = TRUE;
1960 demux->audio_need_segment = TRUE;
1961 demux->video_need_segment = TRUE;
1962 demux->audio_need_discont = TRUE;
1963 demux->video_need_discont = TRUE;
1965 demux->has_audio = FALSE;
1966 demux->has_video = FALSE;
1967 demux->got_par = FALSE;
1969 demux->indexed = FALSE;
1970 demux->upstream_seekable = FALSE;
1971 demux->file_size = 0;
1973 demux->index_max_pos = 0;
1974 demux->index_max_time = 0;
1976 demux->audio_start = demux->video_start = GST_CLOCK_TIME_NONE;
1977 demux->last_audio_pts = demux->last_video_dts = 0;
1978 demux->audio_time_offset = demux->video_time_offset = 0;
1980 demux->no_more_pads = FALSE;
1982 #ifndef GST_DISABLE_DEBUG
1983 demux->no_audio_warned = FALSE;
1984 demux->no_video_warned = FALSE;
1987 gst_segment_init (&demux->segment, GST_FORMAT_TIME);
1989 demux->w = demux->h = 0;
1990 demux->framerate = 0.0;
1991 demux->par_x = demux->par_y = 1;
1992 demux->video_offset = 0;
1993 demux->audio_offset = 0;
1994 demux->offset = demux->cur_tag_offset = 0;
1995 demux->tag_size = demux->tag_data_size = 0;
1996 demux->duration = GST_CLOCK_TIME_NONE;
1998 if (demux->new_seg_event) {
1999 gst_event_unref (demux->new_seg_event);
2000 demux->new_seg_event = NULL;
2003 gst_adapter_clear (demux->adapter);
2005 if (demux->audio_codec_data) {
2006 gst_buffer_unref (demux->audio_codec_data);
2007 demux->audio_codec_data = NULL;
2010 if (demux->video_codec_data) {
2011 gst_buffer_unref (demux->video_codec_data);
2012 demux->video_codec_data = NULL;
2015 if (demux->audio_pad) {
2016 gst_flow_combiner_remove_pad (demux->flowcombiner, demux->audio_pad);
2017 gst_element_remove_pad (GST_ELEMENT (demux), demux->audio_pad);
2018 gst_object_unref (demux->audio_pad);
2019 demux->audio_pad = NULL;
2022 if (demux->video_pad) {
2023 gst_flow_combiner_remove_pad (demux->flowcombiner, demux->video_pad);
2024 gst_element_remove_pad (GST_ELEMENT (demux), demux->video_pad);
2025 gst_object_unref (demux->video_pad);
2026 demux->video_pad = NULL;
2030 g_array_free (demux->times, TRUE);
2031 demux->times = NULL;
2034 if (demux->filepositions) {
2035 g_array_free (demux->filepositions, TRUE);
2036 demux->filepositions = NULL;
2039 gst_flv_demux_clear_tags (demux);
2043 * Create and push a flushing seek event upstream
2046 flv_demux_seek_to_offset (GstFlvDemux * demux, guint64 offset)
2051 GST_DEBUG_OBJECT (demux, "Seeking to %" G_GUINT64_FORMAT, offset);
2054 gst_event_new_seek (1.0, GST_FORMAT_BYTES,
2055 GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_ACCURATE, GST_SEEK_TYPE_SET, offset,
2056 GST_SEEK_TYPE_NONE, -1);
2058 res = gst_pad_push_event (demux->sinkpad, event);
2061 demux->offset = offset;
2065 static GstFlowReturn
2066 gst_flv_demux_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer)
2068 GstFlowReturn ret = GST_FLOW_OK;
2069 GstFlvDemux *demux = NULL;
2071 demux = GST_FLV_DEMUX (parent);
2073 GST_LOG_OBJECT (demux,
2074 "received buffer of %" G_GSIZE_FORMAT " bytes at offset %"
2075 G_GUINT64_FORMAT, gst_buffer_get_size (buffer),
2076 GST_BUFFER_OFFSET (buffer));
2078 if (G_UNLIKELY (GST_BUFFER_OFFSET (buffer) == 0)) {
2079 GST_DEBUG_OBJECT (demux, "beginning of file, expect header");
2080 demux->state = FLV_STATE_HEADER;
2084 if (G_UNLIKELY (demux->offset == 0 && GST_BUFFER_OFFSET (buffer) != 0)) {
2085 GST_DEBUG_OBJECT (demux, "offset was zero, synchronizing with buffer's");
2086 demux->offset = GST_BUFFER_OFFSET (buffer);
2089 if (GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_DISCONT)) {
2090 GST_DEBUG_OBJECT (demux, "Discontinuity");
2091 gst_adapter_clear (demux->adapter);
2094 gst_adapter_push (demux->adapter, buffer);
2096 if (demux->seeking) {
2097 demux->state = FLV_STATE_SEEK;
2098 GST_OBJECT_LOCK (demux);
2099 demux->seeking = FALSE;
2100 GST_OBJECT_UNLOCK (demux);
2104 if (G_UNLIKELY (ret != GST_FLOW_OK)) {
2105 GST_DEBUG_OBJECT (demux, "got flow return %s", gst_flow_get_name (ret));
2109 if (G_UNLIKELY (demux->flushing)) {
2110 GST_DEBUG_OBJECT (demux, "we are now flushing, exiting parser loop");
2111 ret = GST_FLOW_FLUSHING;
2115 switch (demux->state) {
2116 case FLV_STATE_HEADER:
2118 if (gst_adapter_available (demux->adapter) >= FLV_HEADER_SIZE) {
2121 buffer = gst_adapter_take_buffer (demux->adapter, FLV_HEADER_SIZE);
2123 ret = gst_flv_demux_parse_header (demux, buffer);
2125 gst_buffer_unref (buffer);
2126 demux->offset += FLV_HEADER_SIZE;
2128 demux->state = FLV_STATE_TAG_TYPE;
2134 case FLV_STATE_TAG_TYPE:
2136 if (gst_adapter_available (demux->adapter) >= FLV_TAG_TYPE_SIZE) {
2139 /* Remember the tag offset in bytes */
2140 demux->cur_tag_offset = demux->offset;
2142 buffer = gst_adapter_take_buffer (demux->adapter, FLV_TAG_TYPE_SIZE);
2144 ret = gst_flv_demux_parse_tag_type (demux, buffer);
2146 gst_buffer_unref (buffer);
2147 demux->offset += FLV_TAG_TYPE_SIZE;
2149 /* last tag is not an index => no index/don't know where the index is
2150 * seek back to the beginning */
2151 if (demux->seek_event && demux->state != FLV_STATE_TAG_SCRIPT)
2159 case FLV_STATE_TAG_VIDEO:
2161 if (gst_adapter_available (demux->adapter) >= demux->tag_size) {
2164 buffer = gst_adapter_take_buffer (demux->adapter, demux->tag_size);
2166 ret = gst_flv_demux_parse_tag_video (demux, buffer);
2168 gst_buffer_unref (buffer);
2169 demux->offset += demux->tag_size;
2171 demux->state = FLV_STATE_TAG_TYPE;
2177 case FLV_STATE_TAG_AUDIO:
2179 if (gst_adapter_available (demux->adapter) >= demux->tag_size) {
2182 buffer = gst_adapter_take_buffer (demux->adapter, demux->tag_size);
2184 ret = gst_flv_demux_parse_tag_audio (demux, buffer);
2186 gst_buffer_unref (buffer);
2187 demux->offset += demux->tag_size;
2189 demux->state = FLV_STATE_TAG_TYPE;
2195 case FLV_STATE_TAG_SCRIPT:
2197 if (gst_adapter_available (demux->adapter) >= demux->tag_size) {
2200 buffer = gst_adapter_take_buffer (demux->adapter, demux->tag_size);
2202 ret = gst_flv_demux_parse_tag_script (demux, buffer);
2204 gst_buffer_unref (buffer);
2205 demux->offset += demux->tag_size;
2207 demux->state = FLV_STATE_TAG_TYPE;
2209 /* if there's a seek event we're here for the index so if we don't have it
2210 * we seek back to the beginning */
2211 if (demux->seek_event) {
2213 demux->state = FLV_STATE_SEEK;
2223 case FLV_STATE_SEEK:
2229 if (!demux->indexed) {
2230 if (demux->offset == demux->file_size - sizeof (guint32)) {
2231 guint64 seek_offset;
2234 data = gst_adapter_take (demux->adapter, 4);
2238 seek_offset = demux->file_size - sizeof (guint32) -
2239 GST_READ_UINT32_BE (data);
2242 GST_INFO_OBJECT (demux,
2243 "Seeking to beginning of last tag at %" G_GUINT64_FORMAT,
2245 demux->state = FLV_STATE_TAG_TYPE;
2246 flv_demux_seek_to_offset (demux, seek_offset);
2252 GST_OBJECT_LOCK (demux);
2253 event = demux->seek_event;
2254 demux->seek_event = NULL;
2255 GST_OBJECT_UNLOCK (demux);
2257 /* calculate and perform seek */
2258 if (!flv_demux_handle_seek_push (demux, event))
2261 gst_event_unref (event);
2262 demux->state = FLV_STATE_TAG_TYPE;
2265 case FLV_STATE_SKIP:
2266 /* Skip unknown tags (set in _parse_tag_type()) */
2267 if (gst_adapter_available (demux->adapter) >= demux->tag_size) {
2268 gst_adapter_flush (demux->adapter, demux->tag_size);
2269 demux->offset += demux->tag_size;
2270 demux->state = FLV_STATE_TAG_TYPE;
2276 GST_DEBUG_OBJECT (demux, "unexpected demuxer state");
2285 GST_OBJECT_LOCK (demux);
2286 demux->seeking = FALSE;
2287 gst_event_unref (demux->seek_event);
2288 demux->seek_event = NULL;
2289 GST_OBJECT_UNLOCK (demux);
2290 GST_WARNING_OBJECT (demux,
2291 "failed to find an index, seeking back to beginning");
2292 flv_demux_seek_to_offset (demux, 0);
2297 GST_ELEMENT_ERROR (demux, STREAM, DEMUX, (NULL), ("seek failed"));
2298 return GST_FLOW_ERROR;
2303 static GstFlowReturn
2304 gst_flv_demux_pull_range (GstFlvDemux * demux, GstPad * pad, guint64 offset,
2305 guint size, GstBuffer ** buffer)
2309 ret = gst_pad_pull_range (pad, offset, size, buffer);
2310 if (G_UNLIKELY (ret != GST_FLOW_OK)) {
2311 GST_WARNING_OBJECT (demux,
2312 "failed when pulling %d bytes from offset %" G_GUINT64_FORMAT ": %s",
2313 size, offset, gst_flow_get_name (ret));
2318 if (G_UNLIKELY (*buffer && gst_buffer_get_size (*buffer) != size)) {
2319 GST_WARNING_OBJECT (demux,
2320 "partial pull got %" G_GSIZE_FORMAT " when expecting %d from offset %"
2321 G_GUINT64_FORMAT, gst_buffer_get_size (*buffer), size, offset);
2322 gst_buffer_unref (*buffer);
2331 static GstFlowReturn
2332 gst_flv_demux_pull_tag (GstPad * pad, GstFlvDemux * demux)
2334 GstBuffer *buffer = NULL;
2335 GstFlowReturn ret = GST_FLOW_OK;
2337 /* Store tag offset */
2338 demux->cur_tag_offset = demux->offset;
2340 /* Get the first 4 bytes to identify tag type and size */
2341 if (G_UNLIKELY ((ret = gst_flv_demux_pull_range (demux, pad, demux->offset,
2342 FLV_TAG_TYPE_SIZE, &buffer)) != GST_FLOW_OK))
2345 /* Identify tag type */
2346 ret = gst_flv_demux_parse_tag_type (demux, buffer);
2348 gst_buffer_unref (buffer);
2350 if (G_UNLIKELY (ret != GST_FLOW_OK))
2353 /* Jump over tag type + size */
2354 demux->offset += FLV_TAG_TYPE_SIZE;
2356 /* Pull the whole tag */
2358 if (G_UNLIKELY ((ret = gst_flv_demux_pull_range (demux, pad, demux->offset,
2359 demux->tag_size, &buffer)) != GST_FLOW_OK))
2362 switch (demux->state) {
2363 case FLV_STATE_TAG_VIDEO:
2364 ret = gst_flv_demux_parse_tag_video (demux, buffer);
2366 case FLV_STATE_TAG_AUDIO:
2367 ret = gst_flv_demux_parse_tag_audio (demux, buffer);
2369 case FLV_STATE_TAG_SCRIPT:
2370 ret = gst_flv_demux_parse_tag_script (demux, buffer);
2373 GST_WARNING_OBJECT (demux, "unexpected state %d", demux->state);
2376 gst_buffer_unref (buffer);
2378 /* Jump over that part we've just parsed */
2379 demux->offset += demux->tag_size;
2381 /* Make sure we reinitialize the tag size */
2382 demux->tag_size = 0;
2384 /* Ready for the next tag */
2385 demux->state = FLV_STATE_TAG_TYPE;
2387 if (G_UNLIKELY (ret == GST_FLOW_NOT_LINKED)) {
2388 GST_WARNING_OBJECT (demux, "parsing this tag returned not-linked and "
2389 "neither video nor audio are linked");
2396 static GstFlowReturn
2397 gst_flv_demux_pull_header (GstPad * pad, GstFlvDemux * demux)
2399 GstBuffer *buffer = NULL;
2400 GstFlowReturn ret = GST_FLOW_OK;
2402 /* Get the first 9 bytes */
2403 if (G_UNLIKELY ((ret = gst_flv_demux_pull_range (demux, pad, demux->offset,
2404 FLV_HEADER_SIZE, &buffer)) != GST_FLOW_OK))
2407 ret = gst_flv_demux_parse_header (demux, buffer);
2409 gst_buffer_unref (buffer);
2411 /* Jump over the header now */
2412 demux->offset += FLV_HEADER_SIZE;
2413 demux->state = FLV_STATE_TAG_TYPE;
2420 gst_flv_demux_move_to_offset (GstFlvDemux * demux, gint64 offset,
2423 demux->offset = offset;
2425 /* Tell all the stream we moved to a different position (discont) */
2426 demux->audio_need_discont = TRUE;
2427 demux->video_need_discont = TRUE;
2429 /* next section setup */
2430 demux->from_offset = -1;
2431 demux->audio_done = demux->video_done = FALSE;
2432 demux->audio_first_ts = demux->video_first_ts = GST_CLOCK_TIME_NONE;
2435 demux->from_offset = -1;
2436 demux->to_offset = G_MAXINT64;
2439 /* If we seeked at the beginning of the file parse the header again */
2440 if (G_UNLIKELY (!demux->offset)) {
2441 demux->state = FLV_STATE_HEADER;
2442 } else { /* or parse a tag */
2443 demux->state = FLV_STATE_TAG_TYPE;
2447 static GstFlowReturn
2448 gst_flv_demux_seek_to_prev_keyframe (GstFlvDemux * demux)
2450 GstFlowReturn ret = GST_FLOW_EOS;
2452 GstIndexEntry *entry = NULL;
2454 GST_DEBUG_OBJECT (demux,
2455 "terminated section started at offset %" G_GINT64_FORMAT,
2456 demux->from_offset);
2458 /* we are done if we got all audio and video */
2459 if ((!GST_CLOCK_TIME_IS_VALID (demux->audio_first_ts) ||
2460 demux->audio_first_ts < demux->segment.start) &&
2461 (!GST_CLOCK_TIME_IS_VALID (demux->video_first_ts) ||
2462 demux->video_first_ts < demux->segment.start))
2465 if (demux->from_offset <= 0)
2468 GST_DEBUG_OBJECT (demux, "locating previous position");
2470 index = gst_flv_demux_get_index (GST_ELEMENT (demux));
2472 /* locate index entry before previous start position */
2474 entry = gst_index_get_assoc_entry (index, demux->index_id,
2475 GST_INDEX_LOOKUP_BEFORE, GST_ASSOCIATION_FLAG_KEY_UNIT,
2476 GST_FORMAT_BYTES, demux->from_offset - 1);
2479 gint64 bytes = 0, time = 0;
2481 gst_index_entry_assoc_map (entry, GST_FORMAT_BYTES, &bytes);
2482 gst_index_entry_assoc_map (entry, GST_FORMAT_TIME, &time);
2484 GST_DEBUG_OBJECT (demux, "found index entry for %" G_GINT64_FORMAT
2485 " at %" GST_TIME_FORMAT ", seeking to %" G_GINT64_FORMAT,
2486 demux->offset - 1, GST_TIME_ARGS (time), bytes);
2488 /* setup for next section */
2489 demux->to_offset = demux->from_offset;
2490 gst_flv_demux_move_to_offset (demux, bytes, FALSE);
2494 gst_object_unref (index);
2501 static GstFlowReturn
2502 gst_flv_demux_create_index (GstFlvDemux * demux, gint64 pos, GstClockTime ts)
2508 GstClockTime tag_time;
2509 GstFlowReturn ret = GST_FLOW_OK;
2511 if (!gst_pad_peer_query_duration (demux->sinkpad, GST_FORMAT_BYTES, &size))
2514 GST_DEBUG_OBJECT (demux, "building index at %" G_GINT64_FORMAT
2515 " looking for time %" GST_TIME_FORMAT, pos, GST_TIME_ARGS (ts));
2517 old_offset = demux->offset;
2518 demux->offset = pos;
2521 while ((ret = gst_flv_demux_pull_range (demux, demux->sinkpad, demux->offset,
2522 12, &buffer)) == GST_FLOW_OK) {
2524 gst_flv_demux_parse_tag_timestamp (demux, TRUE, buffer, &tag_size);
2526 gst_buffer_unref (buffer);
2529 if (G_UNLIKELY (tag_time == GST_CLOCK_TIME_NONE || tag_time > ts))
2532 demux->offset += tag_size;
2535 if (ret == GST_FLOW_EOS) {
2536 /* file ran out, so mark we have complete index */
2537 demux->indexed = TRUE;
2542 demux->offset = old_offset;
2548 gst_flv_demux_get_metadata (GstFlvDemux * demux)
2550 gint64 ret = 0, offset;
2551 size_t tag_size, size;
2552 GstBuffer *buffer = NULL;
2555 if (!gst_pad_peer_query_duration (demux->sinkpad, GST_FORMAT_BYTES, &offset))
2559 GST_DEBUG_OBJECT (demux, "upstream size: %" G_GINT64_FORMAT, offset);
2560 if (G_UNLIKELY (offset < 4))
2564 if (GST_FLOW_OK != gst_flv_demux_pull_range (demux, demux->sinkpad, offset,
2568 gst_buffer_map (buffer, &map, GST_MAP_READ);
2569 tag_size = GST_READ_UINT32_BE (map.data);
2570 gst_buffer_unmap (buffer, &map);
2571 GST_DEBUG_OBJECT (demux, "last tag size: %" G_GSIZE_FORMAT, tag_size);
2572 gst_buffer_unref (buffer);
2575 if (G_UNLIKELY (offset < tag_size))
2579 if (GST_FLOW_OK != gst_flv_demux_pull_range (demux, demux->sinkpad, offset,
2583 /* a consistency check */
2584 gst_buffer_map (buffer, &map, GST_MAP_READ);
2585 size = GST_READ_UINT24_BE (map.data + 1);
2586 if (size != tag_size - 11) {
2587 gst_buffer_unmap (buffer, &map);
2588 GST_DEBUG_OBJECT (demux,
2589 "tag size %" G_GSIZE_FORMAT ", expected %" G_GSIZE_FORMAT
2590 ", corrupt or truncated file", size, tag_size - 11);
2594 /* try to update duration with timestamp in any case */
2595 gst_flv_demux_parse_tag_timestamp (demux, FALSE, buffer, &size);
2597 /* maybe get some more metadata */
2598 if (map.data[0] == 18) {
2599 gst_buffer_unmap (buffer, &map);
2600 gst_buffer_unref (buffer);
2602 GST_DEBUG_OBJECT (demux, "script tag, pulling it to parse");
2604 if (GST_FLOW_OK == gst_flv_demux_pull_range (demux, demux->sinkpad, offset,
2606 gst_flv_demux_parse_tag_script (demux, buffer);
2608 gst_buffer_unmap (buffer, &map);
2613 gst_buffer_unref (buffer);
2619 gst_flv_demux_loop (GstPad * pad)
2621 GstFlvDemux *demux = NULL;
2622 GstFlowReturn ret = GST_FLOW_OK;
2624 demux = GST_FLV_DEMUX (gst_pad_get_parent (pad));
2627 switch (demux->state) {
2628 case FLV_STATE_TAG_TYPE:
2629 if (demux->from_offset == -1)
2630 demux->from_offset = demux->offset;
2631 ret = gst_flv_demux_pull_tag (pad, demux);
2632 /* if we have seen real data, we probably passed a possible metadata
2633 * header located at start. So if we do not yet have an index,
2634 * try to pick up metadata (index, duration) at the end */
2635 if (G_UNLIKELY (!demux->file_size && !demux->indexed &&
2636 (demux->has_video || demux->has_audio)))
2637 demux->file_size = gst_flv_demux_get_metadata (demux);
2639 case FLV_STATE_DONE:
2642 case FLV_STATE_SEEK:
2643 /* seek issued with insufficient index;
2644 * scan for index in task thread from current maximum offset to
2645 * desired time and then perform seek */
2646 /* TODO maybe some buffering message or so to indicate scan progress */
2647 ret = gst_flv_demux_create_index (demux, demux->index_max_pos,
2649 if (ret != GST_FLOW_OK)
2651 /* position and state arranged by seek,
2652 * also unrefs event */
2653 gst_flv_demux_handle_seek_pull (demux, demux->seek_event, FALSE);
2654 demux->seek_event = NULL;
2657 ret = gst_flv_demux_pull_header (pad, demux);
2658 /* index scans start after header */
2659 demux->index_max_pos = demux->offset;
2663 if (demux->segment.rate < 0.0) {
2664 /* check end of section */
2665 if ((gint64) demux->offset >= demux->to_offset ||
2666 demux->segment.position >= demux->segment.stop + 2 * GST_SECOND ||
2667 (demux->audio_done && demux->video_done))
2668 ret = gst_flv_demux_seek_to_prev_keyframe (demux);
2670 /* check EOS condition */
2671 if ((demux->segment.stop != -1) &&
2672 (demux->segment.position >= demux->segment.stop)) {
2677 /* pause if something went wrong or at end */
2678 if (G_UNLIKELY (ret != GST_FLOW_OK))
2681 gst_object_unref (demux);
2687 const gchar *reason = gst_flow_get_name (ret);
2689 GST_LOG_OBJECT (demux, "pausing task, reason %s", reason);
2690 gst_pad_pause_task (pad);
2692 if (ret == GST_FLOW_EOS) {
2693 /* handle end-of-stream/segment */
2694 /* so align our position with the end of it, if there is one
2695 * this ensures a subsequent will arrive at correct base/acc time */
2696 if (demux->segment.rate > 0.0 &&
2697 GST_CLOCK_TIME_IS_VALID (demux->segment.stop))
2698 demux->segment.position = demux->segment.stop;
2699 else if (demux->segment.rate < 0.0)
2700 demux->segment.position = demux->segment.start;
2702 /* perform EOS logic */
2703 if (!demux->no_more_pads) {
2704 gst_element_no_more_pads (GST_ELEMENT_CAST (demux));
2705 demux->no_more_pads = TRUE;
2708 if (demux->segment.flags & GST_SEGMENT_FLAG_SEGMENT) {
2711 /* for segment playback we need to post when (in stream time)
2712 * we stopped, this is either stop (when set) or the duration. */
2713 if ((stop = demux->segment.stop) == -1)
2714 stop = demux->segment.duration;
2716 if (demux->segment.rate >= 0) {
2717 GST_LOG_OBJECT (demux, "Sending segment done, at end of segment");
2718 gst_element_post_message (GST_ELEMENT_CAST (demux),
2719 gst_message_new_segment_done (GST_OBJECT_CAST (demux),
2720 GST_FORMAT_TIME, stop));
2721 gst_flv_demux_push_src_event (demux,
2722 gst_event_new_segment_done (GST_FORMAT_TIME, stop));
2723 } else { /* Reverse playback */
2724 GST_LOG_OBJECT (demux, "Sending segment done, at beginning of "
2726 gst_element_post_message (GST_ELEMENT_CAST (demux),
2727 gst_message_new_segment_done (GST_OBJECT_CAST (demux),
2728 GST_FORMAT_TIME, demux->segment.start));
2729 gst_flv_demux_push_src_event (demux,
2730 gst_event_new_segment_done (GST_FORMAT_TIME,
2731 demux->segment.start));
2734 /* normal playback, send EOS to all linked pads */
2735 if (!demux->no_more_pads) {
2736 gst_element_no_more_pads (GST_ELEMENT (demux));
2737 demux->no_more_pads = TRUE;
2740 GST_LOG_OBJECT (demux, "Sending EOS, at end of stream");
2741 if (!demux->audio_pad && !demux->video_pad)
2742 GST_ELEMENT_ERROR (demux, STREAM, FAILED,
2743 ("Internal data stream error."), ("Got EOS before any data"));
2744 else if (!gst_flv_demux_push_src_event (demux, gst_event_new_eos ()))
2745 GST_WARNING_OBJECT (demux, "failed pushing EOS on streams");
2747 } else if (ret == GST_FLOW_NOT_LINKED || ret < GST_FLOW_EOS) {
2748 GST_ELEMENT_FLOW_ERROR (demux, ret);
2749 gst_flv_demux_push_src_event (demux, gst_event_new_eos ());
2751 gst_object_unref (demux);
2757 gst_flv_demux_find_offset (GstFlvDemux * demux, GstSegment * segment,
2758 GstSeekFlags seek_flags)
2763 GstIndexEntry *entry;
2765 g_return_val_if_fail (segment != NULL, 0);
2767 time = segment->position;
2769 index = gst_flv_demux_get_index (GST_ELEMENT (demux));
2772 /* Let's check if we have an index entry for that seek time */
2773 entry = gst_index_get_assoc_entry (index, demux->index_id,
2774 seek_flags & GST_SEEK_FLAG_SNAP_AFTER ?
2775 GST_INDEX_LOOKUP_AFTER : GST_INDEX_LOOKUP_BEFORE,
2776 GST_ASSOCIATION_FLAG_KEY_UNIT, GST_FORMAT_TIME, time);
2779 gst_index_entry_assoc_map (entry, GST_FORMAT_BYTES, &bytes);
2780 gst_index_entry_assoc_map (entry, GST_FORMAT_TIME, &time);
2782 GST_DEBUG_OBJECT (demux, "found index entry for %" GST_TIME_FORMAT
2783 " at %" GST_TIME_FORMAT ", seeking to %" G_GINT64_FORMAT,
2784 GST_TIME_ARGS (segment->position), GST_TIME_ARGS (time), bytes);
2786 /* Key frame seeking */
2787 if (seek_flags & GST_SEEK_FLAG_KEY_UNIT) {
2788 /* Adjust the segment so that the keyframe fits in */
2789 segment->start = segment->time = time;
2790 segment->position = time;
2793 GST_DEBUG_OBJECT (demux, "no index entry found for %" GST_TIME_FORMAT,
2794 GST_TIME_ARGS (segment->start));
2797 gst_object_unref (index);
2804 flv_demux_handle_seek_push (GstFlvDemux * demux, GstEvent * event)
2808 GstSeekType start_type, stop_type;
2811 gboolean update, flush, ret;
2812 GstSegment seeksegment;
2814 gst_event_parse_seek (event, &rate, &format, &flags,
2815 &start_type, &start, &stop_type, &stop);
2817 if (format != GST_FORMAT_TIME)
2820 flush = ! !(flags & GST_SEEK_FLAG_FLUSH);
2822 /* Work on a copy until we are sure the seek succeeded. */
2823 memcpy (&seeksegment, &demux->segment, sizeof (GstSegment));
2825 GST_DEBUG_OBJECT (demux, "segment before configure %" GST_SEGMENT_FORMAT,
2828 /* Apply the seek to our segment */
2829 gst_segment_do_seek (&seeksegment, rate, format, flags,
2830 start_type, start, stop_type, stop, &update);
2832 GST_DEBUG_OBJECT (demux, "segment configured %" GST_SEGMENT_FORMAT,
2835 if (flush || seeksegment.position != demux->segment.position) {
2836 /* Do the actual seeking */
2837 guint64 offset = gst_flv_demux_find_offset (demux, &seeksegment, flags);
2839 GST_DEBUG_OBJECT (demux, "generating an upstream seek at position %"
2840 G_GUINT64_FORMAT, offset);
2841 ret = gst_pad_push_event (demux->sinkpad,
2842 gst_event_new_seek (seeksegment.rate, GST_FORMAT_BYTES,
2843 flags | GST_SEEK_FLAG_ACCURATE, GST_SEEK_TYPE_SET,
2844 offset, GST_SEEK_TYPE_NONE, 0));
2845 if (G_UNLIKELY (!ret)) {
2846 GST_WARNING_OBJECT (demux, "upstream seek failed");
2849 gst_flow_combiner_reset (demux->flowcombiner);
2850 /* Tell all the stream we moved to a different position (discont) */
2851 demux->audio_need_discont = TRUE;
2852 demux->video_need_discont = TRUE;
2858 /* Ok seek succeeded, take the newly configured segment */
2859 memcpy (&demux->segment, &seeksegment, sizeof (GstSegment));
2861 /* Tell all the stream a new segment is needed */
2862 demux->audio_need_segment = TRUE;
2863 demux->video_need_segment = TRUE;
2864 /* Clean any potential newsegment event kept for the streams. The first
2865 * stream needing a new segment will create a new one. */
2866 if (G_UNLIKELY (demux->new_seg_event)) {
2867 gst_event_unref (demux->new_seg_event);
2868 demux->new_seg_event = NULL;
2870 GST_DEBUG_OBJECT (demux, "preparing newsegment from %"
2871 GST_TIME_FORMAT " to %" GST_TIME_FORMAT,
2872 GST_TIME_ARGS (demux->segment.start),
2873 GST_TIME_ARGS (demux->segment.stop));
2874 demux->new_seg_event = gst_event_new_segment (&demux->segment);
2875 gst_event_unref (event);
2877 ret = gst_pad_push_event (demux->sinkpad, event);
2885 GST_WARNING_OBJECT (demux, "we only support seeking in TIME format");
2886 gst_event_unref (event);
2892 gst_flv_demux_handle_seek_push (GstFlvDemux * demux, GstEvent * event)
2896 gst_event_parse_seek (event, NULL, &format, NULL, NULL, NULL, NULL, NULL);
2898 if (format != GST_FORMAT_TIME) {
2899 GST_WARNING_OBJECT (demux, "we only support seeking in TIME format");
2900 gst_event_unref (event);
2904 /* First try upstream */
2905 if (gst_pad_push_event (demux->sinkpad, gst_event_ref (event))) {
2906 GST_DEBUG_OBJECT (demux, "Upstream successfully seeked");
2907 gst_event_unref (event);
2911 if (!demux->indexed) {
2912 guint64 seek_offset = 0;
2913 gboolean building_index;
2915 GST_OBJECT_LOCK (demux);
2916 /* handle the seek in the chain function */
2917 demux->seeking = TRUE;
2918 demux->state = FLV_STATE_SEEK;
2920 /* copy the event */
2921 if (demux->seek_event)
2922 gst_event_unref (demux->seek_event);
2923 demux->seek_event = gst_event_ref (event);
2925 /* set the building_index flag so that only one thread can setup the
2926 * structures for index seeking. */
2927 building_index = demux->building_index;
2928 if (!building_index) {
2929 demux->building_index = TRUE;
2930 if (!demux->file_size
2931 && !gst_pad_peer_query_duration (demux->sinkpad, GST_FORMAT_BYTES,
2932 &demux->file_size)) {
2933 GST_WARNING_OBJECT (demux, "Failed to query upstream file size");
2934 GST_OBJECT_UNLOCK (demux);
2938 /* we hope the last tag is a scriptdataobject containing an index
2939 * the size of the last tag is given in the last guint32 bits
2940 * then we seek to the beginning of the tag, parse it and hopefully obtain an index */
2941 seek_offset = demux->file_size - sizeof (guint32);
2942 GST_DEBUG_OBJECT (demux,
2943 "File size obtained, seeking to %" G_GUINT64_FORMAT, seek_offset);
2945 GST_OBJECT_UNLOCK (demux);
2947 if (!building_index) {
2948 GST_INFO_OBJECT (demux, "Seeking to last 4 bytes at %" G_GUINT64_FORMAT,
2950 return flv_demux_seek_to_offset (demux, seek_offset);
2953 /* FIXME: we have to always return true so that we don't block the seek
2955 * Note: maybe it is OK to return true if we're still building the index */
2959 return flv_demux_handle_seek_push (demux, event);
2963 gst_flv_demux_handle_seek_pull (GstFlvDemux * demux, GstEvent * event,
2968 GstSeekType start_type, stop_type;
2971 gboolean update, flush, ret = FALSE;
2972 GstSegment seeksegment;
2974 gst_event_parse_seek (event, &rate, &format, &flags,
2975 &start_type, &start, &stop_type, &stop);
2977 if (format != GST_FORMAT_TIME)
2980 /* mark seeking thread entering flushing/pausing */
2981 GST_OBJECT_LOCK (demux);
2983 demux->seeking = seeking;
2984 GST_OBJECT_UNLOCK (demux);
2986 flush = ! !(flags & GST_SEEK_FLAG_FLUSH);
2989 /* Flush start up and downstream to make sure data flow and loops are
2991 gst_flv_demux_push_src_event (demux, gst_event_new_flush_start ());
2992 gst_pad_push_event (demux->sinkpad, gst_event_new_flush_start ());
2994 /* Pause the pulling task */
2995 gst_pad_pause_task (demux->sinkpad);
2998 /* Take the stream lock */
2999 GST_PAD_STREAM_LOCK (demux->sinkpad);
3002 /* Stop flushing upstream we need to pull */
3003 gst_pad_push_event (demux->sinkpad, gst_event_new_flush_stop (TRUE));
3006 /* Work on a copy until we are sure the seek succeeded. */
3007 memcpy (&seeksegment, &demux->segment, sizeof (GstSegment));
3009 GST_DEBUG_OBJECT (demux, "segment before configure %" GST_SEGMENT_FORMAT,
3012 /* Apply the seek to our segment */
3013 gst_segment_do_seek (&seeksegment, rate, format, flags,
3014 start_type, start, stop_type, stop, &update);
3016 GST_DEBUG_OBJECT (demux, "segment configured %" GST_SEGMENT_FORMAT,
3019 if (flush || seeksegment.position != demux->segment.position) {
3020 /* Do the actual seeking */
3021 /* index is reliable if it is complete or we do not go to far ahead */
3022 if (seeking && !demux->indexed &&
3023 seeksegment.position > demux->index_max_time + 10 * GST_SECOND) {
3024 GST_DEBUG_OBJECT (demux, "delaying seek to post-scan; "
3025 " index only up to %" GST_TIME_FORMAT,
3026 GST_TIME_ARGS (demux->index_max_time));
3027 /* stop flushing for now */
3029 gst_flv_demux_push_src_event (demux, gst_event_new_flush_stop (TRUE));
3030 /* delegate scanning and index building to task thread to avoid
3031 * occupying main (UI) loop */
3032 if (demux->seek_event)
3033 gst_event_unref (demux->seek_event);
3034 demux->seek_event = gst_event_ref (event);
3035 demux->seek_time = seeksegment.position;
3036 demux->state = FLV_STATE_SEEK;
3037 /* do not know about succes yet, but we did care and handled it */
3042 /* now index should be as reliable as it can be for current purpose */
3043 gst_flv_demux_move_to_offset (demux,
3044 gst_flv_demux_find_offset (demux, &seeksegment, flags), TRUE);
3051 /* Stop flushing, the sinks are at time 0 now */
3052 gst_flv_demux_push_src_event (demux, gst_event_new_flush_stop (TRUE));
3056 /* Ok seek succeeded, take the newly configured segment */
3057 memcpy (&demux->segment, &seeksegment, sizeof (GstSegment));
3059 /* Notify about the start of a new segment */
3060 if (demux->segment.flags & GST_SEGMENT_FLAG_SEGMENT) {
3061 gst_element_post_message (GST_ELEMENT (demux),
3062 gst_message_new_segment_start (GST_OBJECT (demux),
3063 demux->segment.format, demux->segment.position));
3066 gst_flow_combiner_reset (demux->flowcombiner);
3067 /* Tell all the stream a new segment is needed */
3068 demux->audio_need_segment = TRUE;
3069 demux->video_need_segment = TRUE;
3070 /* Clean any potential newsegment event kept for the streams. The first
3071 * stream needing a new segment will create a new one. */
3072 if (G_UNLIKELY (demux->new_seg_event)) {
3073 gst_event_unref (demux->new_seg_event);
3074 demux->new_seg_event = NULL;
3076 GST_DEBUG_OBJECT (demux, "preparing newsegment from %"
3077 GST_TIME_FORMAT " to %" GST_TIME_FORMAT,
3078 GST_TIME_ARGS (demux->segment.start),
3079 GST_TIME_ARGS (demux->segment.stop));
3080 demux->new_seg_event = gst_event_new_segment (&demux->segment);
3084 GST_OBJECT_LOCK (demux);
3085 seeking = demux->seeking && !seeking;
3086 demux->seeking = FALSE;
3087 GST_OBJECT_UNLOCK (demux);
3089 /* if we detect an external seek having started (and possibly already having
3090 * flushed), do not restart task to give it a chance.
3091 * Otherwise external one's flushing will take care to pause task */
3093 gst_pad_pause_task (demux->sinkpad);
3095 gst_pad_start_task (demux->sinkpad,
3096 (GstTaskFunction) gst_flv_demux_loop, demux->sinkpad, NULL);
3099 GST_PAD_STREAM_UNLOCK (demux->sinkpad);
3101 gst_event_unref (event);
3107 GST_WARNING_OBJECT (demux, "we only support seeking in TIME format");
3108 gst_event_unref (event);
3113 /* If we can pull that's prefered */
3115 gst_flv_demux_sink_activate (GstPad * sinkpad, GstObject * parent)
3120 query = gst_query_new_scheduling ();
3122 if (!gst_pad_peer_query (sinkpad, query)) {
3123 gst_query_unref (query);
3127 pull_mode = gst_query_has_scheduling_mode_with_flags (query,
3128 GST_PAD_MODE_PULL, GST_SCHEDULING_FLAG_SEEKABLE);
3129 gst_query_unref (query);
3134 GST_DEBUG_OBJECT (sinkpad, "activating pull");
3135 return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PULL, TRUE);
3139 GST_DEBUG_OBJECT (sinkpad, "activating push");
3140 return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PUSH, TRUE);
3145 gst_flv_demux_sink_activate_mode (GstPad * sinkpad, GstObject * parent,
3146 GstPadMode mode, gboolean active)
3151 demux = GST_FLV_DEMUX (parent);
3154 case GST_PAD_MODE_PUSH:
3155 demux->random_access = FALSE;
3158 case GST_PAD_MODE_PULL:
3160 demux->random_access = TRUE;
3161 res = gst_pad_start_task (sinkpad, (GstTaskFunction) gst_flv_demux_loop,
3164 demux->random_access = FALSE;
3165 res = gst_pad_stop_task (sinkpad);
3176 gst_flv_demux_sink_event (GstPad * pad, GstObject * parent, GstEvent * event)
3179 gboolean ret = FALSE;
3181 demux = GST_FLV_DEMUX (parent);
3183 GST_DEBUG_OBJECT (demux, "handling event %s", GST_EVENT_TYPE_NAME (event));
3185 switch (GST_EVENT_TYPE (event)) {
3186 case GST_EVENT_FLUSH_START:
3187 GST_DEBUG_OBJECT (demux, "trying to force chain function to exit");
3188 demux->flushing = TRUE;
3189 ret = gst_flv_demux_push_src_event (demux, event);
3191 case GST_EVENT_FLUSH_STOP:
3192 GST_DEBUG_OBJECT (demux, "flushing FLV demuxer");
3193 gst_flv_demux_flush (demux, TRUE);
3194 ret = gst_flv_demux_push_src_event (demux, event);
3200 GST_DEBUG_OBJECT (demux, "received EOS");
3202 index = gst_flv_demux_get_index (GST_ELEMENT (demux));
3205 GST_DEBUG_OBJECT (demux, "committing index");
3206 gst_index_commit (index, demux->index_id);
3207 gst_object_unref (index);
3210 if (!demux->audio_pad && !demux->video_pad) {
3211 GST_ELEMENT_ERROR (demux, STREAM, FAILED,
3212 ("Internal data stream error."), ("Got EOS before any data"));
3213 gst_event_unref (event);
3215 if (!demux->no_more_pads) {
3216 gst_element_no_more_pads (GST_ELEMENT (demux));
3217 demux->no_more_pads = TRUE;
3220 if (!gst_flv_demux_push_src_event (demux, event))
3221 GST_WARNING_OBJECT (demux, "failed pushing EOS on streams");
3226 case GST_EVENT_SEGMENT:
3228 GstSegment in_segment;
3230 GST_DEBUG_OBJECT (demux, "received new segment");
3232 gst_event_copy_segment (event, &in_segment);
3234 if (in_segment.format == GST_FORMAT_TIME) {
3235 /* time segment, this is perfect, copy over the values. */
3236 memcpy (&demux->segment, &in_segment, sizeof (in_segment));
3238 GST_DEBUG_OBJECT (demux, "NEWSEGMENT: %" GST_SEGMENT_FORMAT,
3242 ret = gst_flv_demux_push_src_event (demux, event);
3244 /* non-time format */
3245 demux->audio_need_segment = TRUE;
3246 demux->video_need_segment = TRUE;
3248 gst_event_unref (event);
3249 if (demux->new_seg_event) {
3250 gst_event_unref (demux->new_seg_event);
3251 demux->new_seg_event = NULL;
3254 gst_flow_combiner_reset (demux->flowcombiner);
3258 ret = gst_pad_event_default (pad, parent, event);
3266 gst_flv_demux_src_event (GstPad * pad, GstObject * parent, GstEvent * event)
3269 gboolean ret = FALSE;
3271 demux = GST_FLV_DEMUX (parent);
3273 GST_DEBUG_OBJECT (demux, "handling event %s", GST_EVENT_TYPE_NAME (event));
3275 switch (GST_EVENT_TYPE (event)) {
3276 case GST_EVENT_SEEK:
3277 /* Try to push upstream first */
3278 gst_event_ref (event);
3279 ret = gst_pad_push_event (demux->sinkpad, event);
3281 gst_event_unref (event);
3284 if (demux->random_access) {
3285 ret = gst_flv_demux_handle_seek_pull (demux, event, TRUE);
3287 ret = gst_flv_demux_handle_seek_push (demux, event);
3291 ret = gst_pad_push_event (demux->sinkpad, event);
3299 gst_flv_demux_query (GstPad * pad, GstObject * parent, GstQuery * query)
3301 gboolean res = TRUE;
3304 demux = GST_FLV_DEMUX (parent);
3306 switch (GST_QUERY_TYPE (query)) {
3307 case GST_QUERY_DURATION:
3311 gst_query_parse_duration (query, &format, NULL);
3313 /* duration is time only */
3314 if (format != GST_FORMAT_TIME) {
3315 GST_DEBUG_OBJECT (demux, "duration query only supported for time "
3321 /* Try to push upstream first */
3322 res = gst_pad_peer_query (demux->sinkpad, query);
3326 GST_DEBUG_OBJECT (pad, "duration query, replying %" GST_TIME_FORMAT,
3327 GST_TIME_ARGS (demux->duration));
3329 gst_query_set_duration (query, GST_FORMAT_TIME, demux->duration);
3333 case GST_QUERY_POSITION:
3337 gst_query_parse_position (query, &format, NULL);
3339 /* position is time only */
3340 if (format != GST_FORMAT_TIME) {
3341 GST_DEBUG_OBJECT (demux, "position query only supported for time "
3347 GST_DEBUG_OBJECT (pad, "position query, replying %" GST_TIME_FORMAT,
3348 GST_TIME_ARGS (demux->segment.position));
3350 gst_query_set_position (query, GST_FORMAT_TIME, demux->segment.position);
3355 case GST_QUERY_SEEKING:{
3358 gst_query_parse_seeking (query, &fmt, NULL, NULL, NULL);
3360 /* First ask upstream */
3361 if (fmt == GST_FORMAT_TIME && gst_pad_peer_query (demux->sinkpad, query)) {
3364 gst_query_parse_seeking (query, NULL, &seekable, NULL, NULL);
3371 /* FIXME, check index this way is not thread safe */
3372 if (fmt != GST_FORMAT_TIME || !demux->index) {
3373 gst_query_set_seeking (query, fmt, FALSE, -1, -1);
3374 } else if (demux->random_access) {
3375 gst_query_set_seeking (query, GST_FORMAT_TIME, TRUE, 0,
3378 GstQuery *peerquery = gst_query_new_seeking (GST_FORMAT_BYTES);
3379 gboolean seekable = gst_pad_peer_query (demux->sinkpad, peerquery);
3382 gst_query_parse_seeking (peerquery, NULL, &seekable, NULL, NULL);
3383 gst_query_unref (peerquery);
3386 gst_query_set_seeking (query, GST_FORMAT_TIME, seekable, 0,
3389 gst_query_set_seeking (query, GST_FORMAT_TIME, FALSE, -1, -1);
3393 case GST_QUERY_SEGMENT:
3398 format = demux->segment.format;
3401 gst_segment_to_stream_time (&demux->segment, format,
3402 demux->segment.start);
3403 if ((stop = demux->segment.stop) == -1)
3404 stop = demux->segment.duration;
3406 stop = gst_segment_to_stream_time (&demux->segment, format, stop);
3408 gst_query_set_segment (query, demux->segment.rate, format, start, stop);
3412 case GST_QUERY_LATENCY:
3414 res = gst_pad_query_default (pad, parent, query);
3423 static GstStateChangeReturn
3424 gst_flv_demux_change_state (GstElement * element, GstStateChange transition)
3427 GstStateChangeReturn ret;
3429 demux = GST_FLV_DEMUX (element);
3431 switch (transition) {
3432 case GST_STATE_CHANGE_READY_TO_PAUSED:
3433 /* If this is our own index destroy it as the
3434 * old entries might be wrong for the new stream */
3435 if (demux->own_index) {
3436 gst_object_unref (demux->index);
3437 demux->index = NULL;
3438 demux->own_index = FALSE;
3441 /* If no index was created, generate one */
3442 if (G_UNLIKELY (!demux->index)) {
3443 GST_DEBUG_OBJECT (demux, "no index provided creating our own");
3445 demux->index = g_object_new (gst_mem_index_get_type (), NULL);
3447 gst_index_get_writer_id (demux->index, GST_OBJECT (demux),
3449 demux->own_index = TRUE;
3451 gst_flv_demux_cleanup (demux);
3457 ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
3458 if (ret == GST_STATE_CHANGE_FAILURE)
3461 switch (transition) {
3462 case GST_STATE_CHANGE_PAUSED_TO_READY:
3463 gst_flv_demux_cleanup (demux);
3474 gst_flv_demux_set_index (GstElement * element, GstIndex * index)
3476 GstFlvDemux *demux = GST_FLV_DEMUX (element);
3477 GstIndex *old_index;
3479 GST_OBJECT_LOCK (demux);
3481 old_index = demux->index;
3484 demux->index = gst_object_ref (index);
3485 demux->own_index = FALSE;
3487 demux->index = NULL;
3490 gst_object_unref (demux->index);
3492 gst_object_ref (index);
3494 GST_OBJECT_UNLOCK (demux);
3496 /* object lock might be taken again */
3498 gst_index_get_writer_id (index, GST_OBJECT (element), &demux->index_id);
3500 GST_DEBUG_OBJECT (demux, "Set index %" GST_PTR_FORMAT, demux->index);
3502 gst_object_unref (index);
3507 gst_flv_demux_get_index (GstElement * element)
3509 GstIndex *result = NULL;
3511 GstFlvDemux *demux = GST_FLV_DEMUX (element);
3513 GST_OBJECT_LOCK (demux);
3515 result = gst_object_ref (demux->index);
3516 GST_OBJECT_UNLOCK (demux);
3522 gst_flv_demux_dispose (GObject * object)
3524 GstFlvDemux *demux = GST_FLV_DEMUX (object);
3526 GST_DEBUG_OBJECT (demux, "disposing FLV demuxer");
3528 if (demux->adapter) {
3529 gst_adapter_clear (demux->adapter);
3530 g_object_unref (demux->adapter);
3531 demux->adapter = NULL;
3534 if (demux->taglist) {
3535 gst_tag_list_unref (demux->taglist);
3536 demux->taglist = NULL;
3539 if (demux->audio_tags) {
3540 gst_tag_list_unref (demux->audio_tags);
3541 demux->audio_tags = NULL;
3544 if (demux->video_tags) {
3545 gst_tag_list_unref (demux->video_tags);
3546 demux->video_tags = NULL;
3549 if (demux->flowcombiner) {
3550 gst_flow_combiner_free (demux->flowcombiner);
3551 demux->flowcombiner = NULL;
3554 if (demux->new_seg_event) {
3555 gst_event_unref (demux->new_seg_event);
3556 demux->new_seg_event = NULL;
3559 if (demux->audio_codec_data) {
3560 gst_buffer_unref (demux->audio_codec_data);
3561 demux->audio_codec_data = NULL;
3564 if (demux->video_codec_data) {
3565 gst_buffer_unref (demux->video_codec_data);
3566 demux->video_codec_data = NULL;
3569 if (demux->audio_pad) {
3570 gst_object_unref (demux->audio_pad);
3571 demux->audio_pad = NULL;
3574 if (demux->video_pad) {
3575 gst_object_unref (demux->video_pad);
3576 demux->video_pad = NULL;
3580 gst_object_unref (demux->index);
3581 demux->index = NULL;
3585 g_array_free (demux->times, TRUE);
3586 demux->times = NULL;
3589 if (demux->filepositions) {
3590 g_array_free (demux->filepositions, TRUE);
3591 demux->filepositions = NULL;
3594 GST_CALL_PARENT (G_OBJECT_CLASS, dispose, (object));
3598 gst_flv_demux_class_init (GstFlvDemuxClass * klass)
3600 GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass);
3601 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
3603 gobject_class->dispose = gst_flv_demux_dispose;
3605 gstelement_class->change_state =
3606 GST_DEBUG_FUNCPTR (gst_flv_demux_change_state);
3609 gstelement_class->set_index = GST_DEBUG_FUNCPTR (gst_flv_demux_set_index);
3610 gstelement_class->get_index = GST_DEBUG_FUNCPTR (gst_flv_demux_get_index);
3613 gst_element_class_add_static_pad_template (gstelement_class,
3614 &flv_sink_template);
3615 gst_element_class_add_static_pad_template (gstelement_class,
3616 &audio_src_template);
3617 gst_element_class_add_static_pad_template (gstelement_class,
3618 &video_src_template);
3619 gst_element_class_set_static_metadata (gstelement_class, "FLV Demuxer",
3620 "Codec/Demuxer", "Demux FLV feeds into digital streams",
3621 "Julien Moutte <julien@moutte.net>");
3625 gst_flv_demux_init (GstFlvDemux * demux)
3628 gst_pad_new_from_static_template (&flv_sink_template, "sink");
3630 gst_pad_set_event_function (demux->sinkpad,
3631 GST_DEBUG_FUNCPTR (gst_flv_demux_sink_event));
3632 gst_pad_set_chain_function (demux->sinkpad,
3633 GST_DEBUG_FUNCPTR (gst_flv_demux_chain));
3634 gst_pad_set_activate_function (demux->sinkpad,
3635 GST_DEBUG_FUNCPTR (gst_flv_demux_sink_activate));
3636 gst_pad_set_activatemode_function (demux->sinkpad,
3637 GST_DEBUG_FUNCPTR (gst_flv_demux_sink_activate_mode));
3639 gst_element_add_pad (GST_ELEMENT (demux), demux->sinkpad);
3641 demux->adapter = gst_adapter_new ();
3642 demux->flowcombiner = gst_flow_combiner_new ();
3644 demux->own_index = FALSE;
3646 GST_OBJECT_FLAG_SET (demux, GST_ELEMENT_FLAG_INDEXABLE);
3648 gst_flv_demux_cleanup (demux);
3652 plugin_init (GstPlugin * plugin)
3654 GST_DEBUG_CATEGORY_INIT (flvdemux_debug, "flvdemux", 0, "FLV demuxer");
3656 if (!gst_element_register (plugin, "flvdemux", GST_RANK_PRIMARY,
3657 gst_flv_demux_get_type ()) ||
3658 !gst_element_register (plugin, "flvmux", GST_RANK_PRIMARY,
3659 gst_flv_mux_get_type ()))
3665 GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, GST_VERSION_MINOR,
3666 flv, "FLV muxing and demuxing plugin",
3667 plugin_init, VERSION, "LGPL", GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN)