1 /* GStreamer ASF/WMV/WMA demuxer
2 * Copyright (C) 1999 Erik Walthinsen <omega@cse.ogi.edu>
3 * Copyright (C) 2006-2009 Tim-Philipp Müller <tim centricular net>
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Library General Public License for more details.
15 * You should have received a copy of the GNU Library General Public
16 * License along with this library; if not, write to the
17 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
18 * Boston, MA 02110-1301, USA.
24 * stop if at end of segment if != end of file, ie. demux->segment.stop
26 * - fix packet parsing:
27 * there's something wrong with timestamps for packets with keyframes,
35 #include <gst/gstutils.h>
36 #include <gst/base/gstbytereader.h>
37 #include <gst/base/gsttypefindhelper.h>
38 #include <gst/riff/riff-media.h>
39 #include <gst/tag/tag.h>
40 #include <gst/gst-i18n-plugin.h>
45 #include "gstasfdemux.h"
46 #include "asfheaders.h"
47 #include "asfpacket.h"
49 static GstStaticPadTemplate gst_asf_demux_sink_template =
50 GST_STATIC_PAD_TEMPLATE ("sink",
53 GST_STATIC_CAPS ("video/x-ms-asf")
56 static GstStaticPadTemplate audio_src_template =
57 GST_STATIC_PAD_TEMPLATE ("audio_%u",
62 static GstStaticPadTemplate video_src_template =
63 GST_STATIC_PAD_TEMPLATE ("video_%u",
68 /* size of an ASF object header, ie. GUID (16 bytes) + object size (8 bytes) */
69 #define ASF_OBJECT_HEADER_SIZE (16+8)
71 /* FIXME: get rid of this */
72 /* abuse this GstFlowReturn enum for internal usage */
73 #define ASF_FLOW_NEED_MORE_DATA 99
75 #define gst_asf_get_flow_name(flow) \
76 (flow == ASF_FLOW_NEED_MORE_DATA) ? \
77 "need-more-data" : gst_flow_get_name (flow)
79 GST_DEBUG_CATEGORY (asfdemux_dbg);
81 static GstStateChangeReturn gst_asf_demux_change_state (GstElement * element,
82 GstStateChange transition);
83 static gboolean gst_asf_demux_element_send_event (GstElement * element,
85 static gboolean gst_asf_demux_send_event_unlocked (GstASFDemux * demux,
87 static gboolean gst_asf_demux_handle_src_query (GstPad * pad,
88 GstObject * parent, GstQuery * query);
89 static GstFlowReturn gst_asf_demux_chain (GstPad * pad, GstObject * parent,
91 static gboolean gst_asf_demux_sink_event (GstPad * pad, GstObject * parent,
93 static GstFlowReturn gst_asf_demux_process_object (GstASFDemux * demux,
94 guint8 ** p_data, guint64 * p_size);
95 static gboolean gst_asf_demux_activate (GstPad * sinkpad, GstObject * parent);
96 static gboolean gst_asf_demux_activate_mode (GstPad * sinkpad,
97 GstObject * parent, GstPadMode mode, gboolean active);
98 static void gst_asf_demux_loop (GstASFDemux * demux);
100 gst_asf_demux_process_queued_extended_stream_objects (GstASFDemux * demux);
101 static gboolean gst_asf_demux_pull_headers (GstASFDemux * demux);
102 static void gst_asf_demux_pull_indices (GstASFDemux * demux);
103 static void gst_asf_demux_reset_stream_state_after_discont (GstASFDemux * asf);
105 gst_asf_demux_parse_data_object_start (GstASFDemux * demux, guint8 * data);
106 static void gst_asf_demux_descramble_buffer (GstASFDemux * demux,
107 AsfStream * stream, GstBuffer ** p_buffer);
108 static void gst_asf_demux_activate_stream (GstASFDemux * demux,
110 static GstStructure *gst_asf_demux_get_metadata_for_stream (GstASFDemux * d,
112 static GstFlowReturn gst_asf_demux_push_complete_payloads (GstASFDemux * demux,
115 #define gst_asf_demux_parent_class parent_class
116 G_DEFINE_TYPE (GstASFDemux, gst_asf_demux, GST_TYPE_ELEMENT);
119 gst_asf_demux_class_init (GstASFDemuxClass * klass)
121 GstElementClass *gstelement_class;
123 gstelement_class = (GstElementClass *) klass;
125 gst_element_class_set_static_metadata (gstelement_class, "ASF Demuxer",
127 "Demultiplexes ASF Streams", "Owen Fraser-Green <owen@discobabe.net>");
129 gst_element_class_add_pad_template (gstelement_class,
130 gst_static_pad_template_get (&audio_src_template));
131 gst_element_class_add_pad_template (gstelement_class,
132 gst_static_pad_template_get (&video_src_template));
133 gst_element_class_add_pad_template (gstelement_class,
134 gst_static_pad_template_get (&gst_asf_demux_sink_template));
136 gstelement_class->change_state =
137 GST_DEBUG_FUNCPTR (gst_asf_demux_change_state);
138 gstelement_class->send_event =
139 GST_DEBUG_FUNCPTR (gst_asf_demux_element_send_event);
143 gst_asf_demux_free_stream (GstASFDemux * demux, AsfStream * stream)
145 gst_caps_replace (&stream->caps, NULL);
146 if (stream->pending_tags) {
147 gst_tag_list_unref (stream->pending_tags);
148 stream->pending_tags = NULL;
150 if (stream->streamheader) {
151 gst_buffer_unref (stream->streamheader);
152 stream->streamheader = NULL;
155 if (stream->active) {
156 gst_element_remove_pad (GST_ELEMENT_CAST (demux), stream->pad);
157 gst_flow_combiner_remove_pad (demux->flowcombiner, stream->pad);
159 gst_object_unref (stream->pad);
163 if (stream->payloads) {
164 while (stream->payloads->len > 0) {
168 last = stream->payloads->len - 1;
169 payload = &g_array_index (stream->payloads, AsfPayload, last);
170 gst_buffer_replace (&payload->buf, NULL);
171 g_array_remove_index (stream->payloads, last);
173 g_array_free (stream->payloads, TRUE);
174 stream->payloads = NULL;
176 if (stream->ext_props.valid) {
177 g_free (stream->ext_props.payload_extensions);
178 stream->ext_props.payload_extensions = NULL;
183 gst_asf_demux_reset (GstASFDemux * demux, gboolean chain_reset)
185 GST_LOG_OBJECT (demux, "resetting");
187 gst_segment_init (&demux->segment, GST_FORMAT_UNDEFINED);
188 demux->segment_running = FALSE;
189 if (demux->adapter && !chain_reset) {
190 gst_adapter_clear (demux->adapter);
191 g_object_unref (demux->adapter);
192 demux->adapter = NULL;
194 if (demux->taglist) {
195 gst_tag_list_unref (demux->taglist);
196 demux->taglist = NULL;
198 if (demux->metadata) {
199 gst_caps_unref (demux->metadata);
200 demux->metadata = NULL;
202 if (demux->global_metadata) {
203 gst_structure_free (demux->global_metadata);
204 demux->global_metadata = NULL;
207 demux->state = GST_ASF_DEMUX_STATE_HEADER;
208 g_free (demux->objpath);
209 demux->objpath = NULL;
210 g_strfreev (demux->languages);
211 demux->languages = NULL;
212 demux->num_languages = 0;
213 g_slist_foreach (demux->ext_stream_props, (GFunc) gst_mini_object_unref,
215 g_slist_free (demux->ext_stream_props);
216 demux->ext_stream_props = NULL;
218 while (demux->old_num_streams > 0) {
219 gst_asf_demux_free_stream (demux,
220 &demux->old_stream[demux->old_num_streams - 1]);
221 --demux->old_num_streams;
223 memset (demux->old_stream, 0, sizeof (demux->old_stream));
224 demux->old_num_streams = 0;
226 /* when resetting for a new chained asf, we don't want to remove the pads
227 * before adding the new ones */
229 memcpy (demux->old_stream, demux->stream, sizeof (demux->stream));
230 demux->old_num_streams = demux->num_streams;
231 demux->num_streams = 0;
234 while (demux->num_streams > 0) {
235 gst_asf_demux_free_stream (demux, &demux->stream[demux->num_streams - 1]);
236 --demux->num_streams;
238 memset (demux->stream, 0, sizeof (demux->stream));
240 /* do not remove those for not adding pads with same name */
241 demux->num_audio_streams = 0;
242 demux->num_video_streams = 0;
243 demux->have_group_id = FALSE;
244 demux->group_id = G_MAXUINT;
246 demux->num_streams = 0;
247 demux->activated_streams = FALSE;
248 demux->first_ts = GST_CLOCK_TIME_NONE;
249 demux->segment_ts = GST_CLOCK_TIME_NONE;
252 gst_segment_init (&demux->in_segment, GST_FORMAT_UNDEFINED);
253 demux->state = GST_ASF_DEMUX_STATE_HEADER;
254 demux->seekable = FALSE;
255 demux->broadcast = FALSE;
256 demux->sidx_interval = 0;
257 demux->sidx_num_entries = 0;
258 g_free (demux->sidx_entries);
259 demux->sidx_entries = NULL;
261 demux->speed_packets = 1;
264 GST_LOG_OBJECT (demux, "Restarting");
265 gst_segment_init (&demux->segment, GST_FORMAT_TIME);
266 demux->need_newsegment = TRUE;
267 demux->segment_seqnum = 0;
268 demux->segment_running = FALSE;
269 demux->accurate = FALSE;
270 demux->metadata = gst_caps_new_empty ();
271 demux->global_metadata = gst_structure_new_empty ("metadata");
272 demux->data_size = 0;
273 demux->data_offset = 0;
274 demux->index_offset = 0;
276 demux->base_offset = 0;
279 g_slist_free (demux->other_streams);
280 demux->other_streams = NULL;
284 gst_asf_demux_init (GstASFDemux * demux)
287 gst_pad_new_from_static_template (&gst_asf_demux_sink_template, "sink");
288 gst_pad_set_chain_function (demux->sinkpad,
289 GST_DEBUG_FUNCPTR (gst_asf_demux_chain));
290 gst_pad_set_event_function (demux->sinkpad,
291 GST_DEBUG_FUNCPTR (gst_asf_demux_sink_event));
292 gst_pad_set_activate_function (demux->sinkpad,
293 GST_DEBUG_FUNCPTR (gst_asf_demux_activate));
294 gst_pad_set_activatemode_function (demux->sinkpad,
295 GST_DEBUG_FUNCPTR (gst_asf_demux_activate_mode));
296 gst_element_add_pad (GST_ELEMENT (demux), demux->sinkpad);
298 /* set initial state */
299 gst_asf_demux_reset (demux, FALSE);
303 gst_asf_demux_activate (GstPad * sinkpad, GstObject * parent)
308 query = gst_query_new_scheduling ();
310 if (!gst_pad_peer_query (sinkpad, query)) {
311 gst_query_unref (query);
315 pull_mode = gst_query_has_scheduling_mode_with_flags (query,
316 GST_PAD_MODE_PULL, GST_SCHEDULING_FLAG_SEEKABLE);
317 gst_query_unref (query);
322 GST_DEBUG_OBJECT (sinkpad, "activating pull");
323 return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PULL, TRUE);
327 GST_DEBUG_OBJECT (sinkpad, "activating push");
328 return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PUSH, TRUE);
333 gst_asf_demux_activate_mode (GstPad * sinkpad, GstObject * parent,
334 GstPadMode mode, gboolean active)
339 demux = GST_ASF_DEMUX (parent);
342 case GST_PAD_MODE_PUSH:
343 demux->state = GST_ASF_DEMUX_STATE_HEADER;
344 demux->streaming = TRUE;
347 case GST_PAD_MODE_PULL:
349 demux->state = GST_ASF_DEMUX_STATE_HEADER;
350 demux->streaming = FALSE;
352 res = gst_pad_start_task (sinkpad, (GstTaskFunction) gst_asf_demux_loop,
355 res = gst_pad_stop_task (sinkpad);
366 gst_asf_demux_sink_event (GstPad * pad, GstObject * parent, GstEvent * event)
371 demux = GST_ASF_DEMUX (parent);
373 GST_LOG_OBJECT (demux, "handling %s event", GST_EVENT_TYPE_NAME (event));
374 switch (GST_EVENT_TYPE (event)) {
375 case GST_EVENT_SEGMENT:{
376 const GstSegment *segment;
378 gst_event_parse_segment (event, &segment);
380 if (segment->format == GST_FORMAT_BYTES) {
381 if (demux->packet_size && segment->start > demux->data_offset)
382 demux->packet = (segment->start - demux->data_offset) /
386 } else if (segment->format == GST_FORMAT_TIME) {
387 /* do not know packet position, not really a problem */
390 GST_WARNING_OBJECT (demux, "unsupported newsegment format, ignoring");
391 gst_event_unref (event);
395 /* record upstream segment for interpolation */
396 if (segment->format != demux->in_segment.format)
397 gst_segment_init (&demux->in_segment, GST_FORMAT_UNDEFINED);
398 gst_segment_copy_into (segment, &demux->in_segment);
400 /* in either case, clear some state and generate newsegment later on */
401 GST_OBJECT_LOCK (demux);
402 demux->segment_ts = GST_CLOCK_TIME_NONE;
403 demux->in_gap = GST_CLOCK_TIME_NONE;
404 demux->need_newsegment = TRUE;
405 demux->segment_seqnum = gst_event_get_seqnum (event);
406 gst_asf_demux_reset_stream_state_after_discont (demux);
407 GST_OBJECT_UNLOCK (demux);
409 gst_event_unref (event);
415 if (demux->state == GST_ASF_DEMUX_STATE_HEADER) {
416 GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
417 (_("This stream contains no data.")),
418 ("got eos and didn't receive a complete header object"));
421 flow = gst_asf_demux_push_complete_payloads (demux, TRUE);
422 if (flow < GST_FLOW_EOS || flow == GST_FLOW_NOT_LINKED) {
423 GST_ELEMENT_ERROR (demux, STREAM, FAILED,
424 (_("Internal data stream error.")),
425 ("streaming stopped, reason %s", gst_flow_get_name (flow)));
429 GST_OBJECT_LOCK (demux);
430 gst_adapter_clear (demux->adapter);
431 GST_OBJECT_UNLOCK (demux);
432 gst_asf_demux_send_event_unlocked (demux, event);
436 case GST_EVENT_FLUSH_STOP:
437 GST_OBJECT_LOCK (demux);
438 gst_asf_demux_reset_stream_state_after_discont (demux);
439 GST_OBJECT_UNLOCK (demux);
440 gst_asf_demux_send_event_unlocked (demux, event);
441 /* upon activation, latency is no longer introduced, e.g. after seek */
442 if (demux->activated_streams)
447 ret = gst_pad_event_default (pad, parent, event);
455 gst_asf_demux_seek_index_lookup (GstASFDemux * demux, guint * packet,
456 GstClockTime seek_time, GstClockTime * p_idx_time, guint * speed,
457 gboolean next, gboolean * eos)
459 GstClockTime idx_time;
465 if (G_UNLIKELY (demux->sidx_num_entries == 0 || demux->sidx_interval == 0))
468 idx = (guint) ((seek_time + demux->preroll) / demux->sidx_interval);
471 /* if we want the next keyframe, we have to go forward till we find
472 a different packet number */
474 if (idx >= demux->sidx_num_entries - 1) {
475 /* If we get here, we're asking for next keyframe after the last one. There isn't one. */
480 for (idx2 = idx + 1; idx2 < demux->sidx_num_entries; ++idx2) {
481 if (demux->sidx_entries[idx].packet != demux->sidx_entries[idx2].packet) {
488 if (G_UNLIKELY (idx >= demux->sidx_num_entries)) {
494 *packet = demux->sidx_entries[idx].packet;
496 *speed = demux->sidx_entries[idx].count;
498 /* so we get closer to the actual time of the packet ... actually, let's not
499 * do this, since we throw away superfluous payloads before the seek position
500 * anyway; this way, our key unit seek 'snap resolution' is a bit better
501 * (ie. same as index resolution) */
503 while (idx > 0 && demux->sidx_entries[idx-1] == demux->sidx_entries[idx])
507 idx_time = demux->sidx_interval * idx;
508 if (G_LIKELY (idx_time >= demux->preroll))
509 idx_time -= demux->preroll;
511 GST_DEBUG_OBJECT (demux, "%" GST_TIME_FORMAT " => packet %u at %"
512 GST_TIME_FORMAT, GST_TIME_ARGS (seek_time), *packet,
513 GST_TIME_ARGS (idx_time));
515 if (G_LIKELY (p_idx_time))
516 *p_idx_time = idx_time;
522 gst_asf_demux_reset_stream_state_after_discont (GstASFDemux * demux)
526 gst_adapter_clear (demux->adapter);
528 GST_DEBUG_OBJECT (demux, "reset stream state");
530 for (n = 0; n < demux->num_streams; n++) {
531 demux->stream[n].discont = TRUE;
532 demux->stream[n].first_buffer = TRUE;
534 while (demux->stream[n].payloads->len > 0) {
538 last = demux->stream[n].payloads->len - 1;
539 payload = &g_array_index (demux->stream[n].payloads, AsfPayload, last);
540 gst_buffer_replace (&payload->buf, NULL);
541 g_array_remove_index (demux->stream[n].payloads, last);
547 gst_asf_demux_mark_discont (GstASFDemux * demux)
551 GST_DEBUG_OBJECT (demux, "Mark stream discont");
553 for (n = 0; n < demux->num_streams; n++)
554 demux->stream[n].discont = TRUE;
557 /* do a seek in push based mode */
559 gst_asf_demux_handle_seek_push (GstASFDemux * demux, GstEvent * event)
564 GstSeekType cur_type, stop_type;
568 GstEvent *byte_event;
570 gst_event_parse_seek (event, &rate, &format, &flags, &cur_type, &cur,
573 stop_type = GST_SEEK_TYPE_NONE;
576 GST_DEBUG_OBJECT (demux, "seeking to %" GST_TIME_FORMAT, GST_TIME_ARGS (cur));
578 /* determine packet, by index or by estimation */
579 if (!gst_asf_demux_seek_index_lookup (demux, &packet, cur, NULL, NULL, FALSE,
582 (guint) gst_util_uint64_scale (demux->num_packets, cur,
586 if (packet > demux->num_packets) {
587 GST_DEBUG_OBJECT (demux, "could not determine packet to seek to, "
592 GST_DEBUG_OBJECT (demux, "seeking to packet %d", packet);
594 cur = demux->data_offset + (packet * demux->packet_size);
596 GST_DEBUG_OBJECT (demux, "Pushing BYTE seek rate %g, "
597 "start %" G_GINT64_FORMAT ", stop %" G_GINT64_FORMAT, rate, cur, stop);
598 /* BYTE seek event */
599 byte_event = gst_event_new_seek (rate, GST_FORMAT_BYTES, flags, cur_type,
600 cur, stop_type, stop);
601 gst_event_set_seqnum (byte_event, gst_event_get_seqnum (event));
602 res = gst_pad_push_event (demux->sinkpad, byte_event);
608 gst_asf_demux_handle_seek_event (GstASFDemux * demux, GstEvent * event)
610 GstClockTime idx_time;
613 GstSeekType cur_type, stop_type;
615 gboolean only_need_update;
616 gboolean keyunit_sync, after, before, next;
621 guint packet, speed_count = 1;
626 gst_event_parse_seek (event, &rate, &format, &flags, &cur_type, &cur,
629 if (G_UNLIKELY (format != GST_FORMAT_TIME)) {
630 GST_LOG_OBJECT (demux, "seeking is only supported in TIME format");
634 /* upstream might handle TIME seek, e.g. mms or rtsp, or not, e.g. http,
635 * so first try to let it handle the seek event. */
636 if (gst_pad_push_event (demux->sinkpad, gst_event_ref (event)))
639 if (G_UNLIKELY (demux->seekable == FALSE || demux->packet_size == 0 ||
640 demux->num_packets == 0 || demux->play_time == 0)) {
641 GST_LOG_OBJECT (demux, "stream is not seekable");
645 if (G_UNLIKELY (!demux->activated_streams)) {
646 GST_LOG_OBJECT (demux, "streams not yet activated, ignoring seek");
650 if (G_UNLIKELY (rate <= 0.0)) {
651 GST_LOG_OBJECT (demux, "backward playback is not supported yet");
655 seqnum = gst_event_get_seqnum (event);
656 flush = ((flags & GST_SEEK_FLAG_FLUSH) == GST_SEEK_FLAG_FLUSH);
658 ((flags & GST_SEEK_FLAG_ACCURATE) == GST_SEEK_FLAG_ACCURATE);
659 keyunit_sync = ((flags & GST_SEEK_FLAG_KEY_UNIT) == GST_SEEK_FLAG_KEY_UNIT);
660 after = ((flags & GST_SEEK_FLAG_SNAP_AFTER) == GST_SEEK_FLAG_SNAP_AFTER);
661 before = ((flags & GST_SEEK_FLAG_SNAP_BEFORE) == GST_SEEK_FLAG_SNAP_BEFORE);
662 next = after && !before;
664 if (G_UNLIKELY (demux->streaming)) {
665 /* support it safely needs more segment handling, e.g. closing etc */
667 GST_LOG_OBJECT (demux, "streaming; non-flushing seek not supported");
670 /* we can (re)construct the start later on, but not the end */
671 if (stop_type != GST_SEEK_TYPE_NONE &&
672 (stop_type != GST_SEEK_TYPE_SET || GST_CLOCK_TIME_IS_VALID (stop))) {
673 GST_LOG_OBJECT (demux, "streaming; end position must be NONE");
676 return gst_asf_demux_handle_seek_push (demux, event);
679 /* unlock the streaming thread */
680 if (G_LIKELY (flush)) {
681 fevent = gst_event_new_flush_start ();
683 gst_event_set_seqnum (fevent, seqnum);
684 gst_pad_push_event (demux->sinkpad, gst_event_ref (fevent));
685 gst_asf_demux_send_event_unlocked (demux, fevent);
687 gst_pad_pause_task (demux->sinkpad);
690 /* grab the stream lock so that streaming cannot continue, for
691 * non flushing seeks when the element is in PAUSED this could block
693 GST_PAD_STREAM_LOCK (demux->sinkpad);
695 /* we now can stop flushing, since we have the stream lock now */
696 fevent = gst_event_new_flush_stop (TRUE);
697 gst_event_set_seqnum (fevent, seqnum);
698 gst_pad_push_event (demux->sinkpad, gst_event_ref (fevent));
700 if (G_LIKELY (flush))
701 gst_asf_demux_send_event_unlocked (demux, fevent);
703 gst_event_unref (fevent);
705 /* operating on copy of segment until we know the seek worked */
706 segment = demux->segment;
708 if (G_UNLIKELY (demux->segment_running && !flush)) {
709 GstSegment newsegment;
712 /* create the segment event to close the current segment */
713 gst_segment_copy_into (&segment, &newsegment);
714 newseg = gst_event_new_segment (&newsegment);
715 gst_event_set_seqnum (newseg, seqnum);
717 gst_asf_demux_send_event_unlocked (demux, newseg);
720 gst_segment_do_seek (&segment, rate, format, flags, cur_type,
721 cur, stop_type, stop, &only_need_update);
723 GST_DEBUG_OBJECT (demux, "seeking to time %" GST_TIME_FORMAT ", segment: "
724 "%" GST_SEGMENT_FORMAT, GST_TIME_ARGS (segment.start), &segment);
726 if (cur_type != GST_SEEK_TYPE_SET)
727 seek_time = segment.start;
731 /* FIXME: should check the KEY_UNIT flag; need to adjust position to
732 * real start of data and segment_start to indexed time for key unit seek*/
733 if (G_UNLIKELY (!gst_asf_demux_seek_index_lookup (demux, &packet, seek_time,
734 &idx_time, &speed_count, next, &eos))) {
738 demux->packet = demux->num_packets;
742 /* First try to query our source to see if it can convert for us. This is
743 the case when our source is an mms stream, notice that in this case
744 gstmms will do a time based seek to get the byte offset, this is not a
745 problem as the seek to this offset needs to happen anway. */
746 if (gst_pad_peer_query_convert (demux->sinkpad, GST_FORMAT_TIME, seek_time,
747 GST_FORMAT_BYTES, &offset)) {
748 packet = (offset - demux->data_offset) / demux->packet_size;
749 GST_LOG_OBJECT (demux, "convert %" GST_TIME_FORMAT
750 " to bytes query result: %" G_GINT64_FORMAT ", data_ofset: %"
751 G_GINT64_FORMAT ", packet_size: %u," " resulting packet: %u\n",
752 GST_TIME_ARGS (seek_time), offset, demux->data_offset,
753 demux->packet_size, packet);
755 /* FIXME: For streams containing video, seek to an earlier position in
756 * the hope of hitting a keyframe and let the sinks throw away the stuff
757 * before the segment start. For audio-only this is unnecessary as every
759 if (flush && (demux->accurate || (keyunit_sync && !next))
760 && demux->num_video_streams > 0) {
761 seek_time -= 5 * GST_SECOND;
766 packet = (guint) gst_util_uint64_scale (demux->num_packets,
767 seek_time, demux->play_time);
769 if (packet > demux->num_packets)
770 packet = demux->num_packets;
773 if (G_LIKELY (keyunit_sync)) {
774 GST_DEBUG_OBJECT (demux, "key unit seek, adjust seek_time = %"
775 GST_TIME_FORMAT " to index_time = %" GST_TIME_FORMAT,
776 GST_TIME_ARGS (seek_time), GST_TIME_ARGS (idx_time));
777 segment.start = idx_time;
778 segment.position = idx_time;
779 segment.time = idx_time;
783 GST_DEBUG_OBJECT (demux, "seeking to packet %u (%d)", packet, speed_count);
785 GST_OBJECT_LOCK (demux);
786 demux->segment = segment;
787 demux->packet = packet;
788 demux->need_newsegment = TRUE;
789 demux->segment_seqnum = seqnum;
790 demux->speed_packets = speed_count;
791 gst_asf_demux_reset_stream_state_after_discont (demux);
792 GST_OBJECT_UNLOCK (demux);
795 /* restart our task since it might have been stopped when we did the flush */
796 gst_pad_start_task (demux->sinkpad, (GstTaskFunction) gst_asf_demux_loop,
799 /* streaming can continue now */
800 GST_PAD_STREAM_UNLOCK (demux->sinkpad);
806 gst_asf_demux_handle_src_event (GstPad * pad, GstObject * parent,
812 demux = GST_ASF_DEMUX (parent);
814 switch (GST_EVENT_TYPE (event)) {
816 GST_LOG_OBJECT (pad, "seek event");
817 ret = gst_asf_demux_handle_seek_event (demux, event);
818 gst_event_unref (event);
821 case GST_EVENT_NAVIGATION:
822 /* just drop these two silently */
823 gst_event_unref (event);
827 GST_LOG_OBJECT (pad, "%s event", GST_EVENT_TYPE_NAME (event));
828 ret = gst_pad_event_default (pad, parent, event);
835 static inline guint32
836 gst_asf_demux_identify_guid (const ASFGuidHash * guids, ASFGuid * guid)
840 ret = gst_asf_identify_guid (guids, guid);
842 GST_LOG ("%s 0x%08x-0x%08x-0x%08x-0x%08x",
843 gst_asf_get_guid_nick (guids, ret),
844 guid->v1, guid->v2, guid->v3, guid->v4);
856 /* expect is true when the user is expeting an object,
857 * when false, it will give no warnings if the object
861 asf_demux_peek_object (GstASFDemux * demux, const guint8 * data,
862 guint data_len, AsfObject * object, gboolean expect)
866 if (data_len < ASF_OBJECT_HEADER_SIZE)
869 guid.v1 = GST_READ_UINT32_LE (data + 0);
870 guid.v2 = GST_READ_UINT32_LE (data + 4);
871 guid.v3 = GST_READ_UINT32_LE (data + 8);
872 guid.v4 = GST_READ_UINT32_LE (data + 12);
874 object->size = GST_READ_UINT64_LE (data + 16);
876 /* FIXME: make asf_demux_identify_object_guid() */
877 object->id = gst_asf_demux_identify_guid (asf_object_guids, &guid);
878 if (object->id == ASF_OBJ_UNDEFINED && expect) {
879 GST_WARNING_OBJECT (demux, "Unknown object %08x-%08x-%08x-%08x",
880 guid.v1, guid.v2, guid.v3, guid.v4);
887 gst_asf_demux_release_old_pads (GstASFDemux * demux)
889 GST_DEBUG_OBJECT (demux, "Releasing old pads");
891 while (demux->old_num_streams > 0) {
892 gst_pad_push_event (demux->old_stream[demux->old_num_streams - 1].pad,
893 gst_event_new_eos ());
894 gst_asf_demux_free_stream (demux,
895 &demux->old_stream[demux->old_num_streams - 1]);
896 --demux->old_num_streams;
898 memset (demux->old_stream, 0, sizeof (demux->old_stream));
899 demux->old_num_streams = 0;
903 gst_asf_demux_chain_headers (GstASFDemux * demux)
907 guint8 *header_data, *data = NULL;
908 const guint8 *cdata = NULL;
911 cdata = (guint8 *) gst_adapter_map (demux->adapter, ASF_OBJECT_HEADER_SIZE);
915 asf_demux_peek_object (demux, cdata, ASF_OBJECT_HEADER_SIZE, &obj, TRUE);
916 if (obj.id != ASF_OBJ_HEADER)
919 GST_LOG_OBJECT (demux, "header size = %u", (guint) obj.size);
921 /* + 50 for non-packet data at beginning of ASF_OBJ_DATA */
922 if (gst_adapter_available (demux->adapter) < obj.size + 50)
925 data = gst_adapter_take (demux->adapter, obj.size + 50);
928 header_size = obj.size;
929 flow = gst_asf_demux_process_object (demux, &header_data, &header_size);
930 if (flow != GST_FLOW_OK)
933 /* calculate where the packet data starts */
934 demux->data_offset = obj.size + 50;
936 /* now parse the beginning of the ASF_OBJ_DATA object */
937 if (!gst_asf_demux_parse_data_object_start (demux, data + obj.size))
940 if (demux->num_streams == 0)
949 GST_LOG_OBJECT (demux, "not enough data in adapter yet");
956 GST_ELEMENT_ERROR (demux, STREAM, WRONG_TYPE, (NULL),
957 ("This doesn't seem to be an ASF file"));
959 return GST_FLOW_ERROR;
964 GST_ELEMENT_ERROR (demux, STREAM, DEMUX, (NULL),
965 ("header parsing failed, or no streams found, flow = %s",
966 gst_flow_get_name (flow)));
968 return GST_FLOW_ERROR;
973 gst_asf_demux_pull_data (GstASFDemux * demux, guint64 offset, guint size,
974 GstBuffer ** p_buf, GstFlowReturn * p_flow)
979 GST_LOG_OBJECT (demux, "pulling buffer at %" G_GUINT64_FORMAT "+%u",
982 flow = gst_pad_pull_range (demux->sinkpad, offset, size, p_buf);
984 if (G_LIKELY (p_flow))
987 if (G_UNLIKELY (flow != GST_FLOW_OK)) {
988 GST_DEBUG_OBJECT (demux, "flow %s pulling buffer at %" G_GUINT64_FORMAT
989 "+%u", gst_flow_get_name (flow), offset, size);
994 g_assert (*p_buf != NULL);
996 buffer_size = gst_buffer_get_size (*p_buf);
997 if (G_UNLIKELY (buffer_size < size)) {
998 GST_DEBUG_OBJECT (demux, "short read pulling buffer at %" G_GUINT64_FORMAT
999 "+%u (got only %" G_GSIZE_FORMAT " bytes)", offset, size, buffer_size);
1000 gst_buffer_unref (*p_buf);
1001 if (G_LIKELY (p_flow))
1002 *p_flow = GST_FLOW_EOS;
1011 gst_asf_demux_pull_indices (GstASFDemux * demux)
1013 GstBuffer *buf = NULL;
1017 offset = demux->index_offset;
1019 if (G_UNLIKELY (offset == 0)) {
1020 GST_DEBUG_OBJECT (demux, "can't read indices, don't know index offset");
1024 while (gst_asf_demux_pull_data (demux, offset, 16 + 8, &buf, NULL)) {
1030 gst_buffer_map (buf, &map, GST_MAP_READ);
1031 g_assert (map.size >= 16 + 8);
1032 asf_demux_peek_object (demux, map.data, 16 + 8, &obj, TRUE);
1033 gst_buffer_unmap (buf, &map);
1034 gst_buffer_replace (&buf, NULL);
1036 /* check for sanity */
1037 if (G_UNLIKELY (obj.size > (5 * 1024 * 1024))) {
1038 GST_DEBUG_OBJECT (demux, "implausible index object size, bailing out");
1042 if (G_UNLIKELY (!gst_asf_demux_pull_data (demux, offset, obj.size, &buf,
1046 GST_LOG_OBJECT (demux, "index object at offset 0x%" G_GINT64_MODIFIER "X"
1047 ", size %u", offset, (guint) obj.size);
1049 offset += obj.size; /* increase before _process_object changes it */
1051 gst_buffer_map (buf, &map, GST_MAP_READ);
1052 g_assert (map.size >= obj.size);
1053 bufdata = (guint8 *) map.data;
1054 flow = gst_asf_demux_process_object (demux, &bufdata, &obj.size);
1055 gst_buffer_unmap (buf, &map);
1056 gst_buffer_replace (&buf, NULL);
1058 if (G_UNLIKELY (flow != GST_FLOW_OK))
1063 GST_DEBUG_OBJECT (demux, "read %u index objects", num_read);
1067 gst_asf_demux_parse_data_object_start (GstASFDemux * demux, guint8 * data)
1071 asf_demux_peek_object (demux, data, 50, &obj, TRUE);
1072 if (obj.id != ASF_OBJ_DATA) {
1073 GST_WARNING_OBJECT (demux, "headers not followed by a DATA object");
1077 demux->state = GST_ASF_DEMUX_STATE_DATA;
1079 if (!demux->broadcast && obj.size > 50) {
1080 demux->data_size = obj.size - 50;
1081 /* CHECKME: for at least one file this is off by +158 bytes?! */
1082 demux->index_offset = demux->data_offset + demux->data_size;
1084 demux->data_size = 0;
1085 demux->index_offset = 0;
1090 if (!demux->broadcast) {
1091 /* skip object header (24 bytes) and file GUID (16 bytes) */
1092 demux->num_packets = GST_READ_UINT64_LE (data + (16 + 8) + 16);
1094 demux->num_packets = 0;
1097 if (demux->num_packets == 0)
1098 demux->seekable = FALSE;
1100 /* fallback in the unlikely case that headers are inconsistent, can't hurt */
1101 if (demux->data_size == 0 && demux->num_packets > 0) {
1102 demux->data_size = demux->num_packets * demux->packet_size;
1103 demux->index_offset = demux->data_offset + demux->data_size;
1106 /* process pending stream objects and create pads for those */
1107 gst_asf_demux_process_queued_extended_stream_objects (demux);
1109 GST_INFO_OBJECT (demux, "Stream has %" G_GUINT64_FORMAT " packets, "
1110 "data_offset=%" G_GINT64_FORMAT ", data_size=%" G_GINT64_FORMAT
1111 ", index_offset=%" G_GUINT64_FORMAT, demux->num_packets,
1112 demux->data_offset, demux->data_size, demux->index_offset);
1118 gst_asf_demux_pull_headers (GstASFDemux * demux)
1122 GstBuffer *buf = NULL;
1127 GST_LOG_OBJECT (demux, "reading headers");
1129 /* pull HEADER object header, so we know its size */
1130 if (!gst_asf_demux_pull_data (demux, demux->base_offset, 16 + 8, &buf, NULL))
1133 gst_buffer_map (buf, &map, GST_MAP_READ);
1134 g_assert (map.size >= 16 + 8);
1135 asf_demux_peek_object (demux, map.data, 16 + 8, &obj, TRUE);
1136 gst_buffer_unmap (buf, &map);
1137 gst_buffer_replace (&buf, NULL);
1139 if (obj.id != ASF_OBJ_HEADER)
1142 GST_LOG_OBJECT (demux, "header size = %u", (guint) obj.size);
1144 /* pull HEADER object */
1145 if (!gst_asf_demux_pull_data (demux, demux->base_offset, obj.size, &buf,
1149 size = obj.size; /* don't want obj.size changed */
1150 gst_buffer_map (buf, &map, GST_MAP_READ);
1151 g_assert (map.size >= size);
1152 bufdata = (guint8 *) map.data;
1153 flow = gst_asf_demux_process_object (demux, &bufdata, &size);
1154 gst_buffer_unmap (buf, &map);
1155 gst_buffer_replace (&buf, NULL);
1157 if (flow != GST_FLOW_OK) {
1158 GST_WARNING_OBJECT (demux, "process_object: %s", gst_flow_get_name (flow));
1162 /* calculate where the packet data starts */
1163 demux->data_offset = demux->base_offset + obj.size + 50;
1165 /* now pull beginning of DATA object before packet data */
1166 if (!gst_asf_demux_pull_data (demux, demux->base_offset + obj.size, 50, &buf,
1170 gst_buffer_map (buf, &map, GST_MAP_READ);
1171 g_assert (map.size >= size);
1172 bufdata = (guint8 *) map.data;
1173 if (!gst_asf_demux_parse_data_object_start (demux, bufdata))
1176 if (demux->num_streams == 0)
1179 gst_buffer_unmap (buf, &map);
1180 gst_buffer_replace (&buf, NULL);
1188 gst_buffer_unmap (buf, &map);
1189 gst_buffer_replace (&buf, NULL);
1191 GST_ELEMENT_ERROR (demux, STREAM, WRONG_TYPE, (NULL),
1192 ("This doesn't seem to be an ASF file"));
1201 gst_buffer_unmap (buf, &map);
1202 gst_buffer_replace (&buf, NULL);
1203 GST_ELEMENT_ERROR (demux, STREAM, DEMUX, (NULL), (NULL));
1209 all_streams_prerolled (GstASFDemux * demux)
1211 GstClockTime preroll_time;
1212 guint i, num_no_data = 0;
1214 /* Allow at least 500ms of preroll_time */
1215 preroll_time = MAX (demux->preroll, 500 * GST_MSECOND);
1217 /* returns TRUE as long as there isn't a stream which (a) has data queued
1218 * and (b) the timestamp of last piece of data queued is < demux->preroll
1219 * AND there is at least one other stream with data queued */
1220 for (i = 0; i < demux->num_streams; ++i) {
1221 AsfPayload *last_payload = NULL;
1225 stream = &demux->stream[i];
1226 if (G_UNLIKELY (stream->payloads->len == 0)) {
1228 GST_LOG_OBJECT (stream->pad, "no data queued");
1232 /* find last payload with timestamp */
1233 for (last_idx = stream->payloads->len - 1;
1234 last_idx >= 0 && (last_payload == NULL
1235 || !GST_CLOCK_TIME_IS_VALID (last_payload->ts)); --last_idx) {
1236 last_payload = &g_array_index (stream->payloads, AsfPayload, last_idx);
1239 GST_LOG_OBJECT (stream->pad, "checking if %" GST_TIME_FORMAT " > %"
1240 GST_TIME_FORMAT, GST_TIME_ARGS (last_payload->ts),
1241 GST_TIME_ARGS (preroll_time));
1242 if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (last_payload->ts)
1243 || last_payload->ts <= preroll_time)) {
1244 GST_LOG_OBJECT (stream->pad, "not beyond preroll point yet");
1249 if (G_UNLIKELY (num_no_data > 0))
1257 gst_asf_demux_have_mutually_exclusive_active_stream (GstASFDemux * demux,
1262 for (l = demux->mut_ex_streams; l != NULL; l = l->next) {
1265 /* check for each mutual exclusion group whether it affects this stream */
1266 for (mes = (guint8 *) l->data; mes != NULL && *mes != 0xff; ++mes) {
1267 if (*mes == stream->id) {
1268 /* we are in this group; let's check if we've already activated streams
1269 * that are in the same group (and hence mutually exclusive to this
1271 for (mes = (guint8 *) l->data; mes != NULL && *mes != 0xff; ++mes) {
1274 for (i = 0; i < demux->num_streams; ++i) {
1275 if (demux->stream[i].id == *mes && demux->stream[i].active) {
1276 GST_LOG_OBJECT (demux, "stream with ID %d is mutually exclusive "
1277 "to already active stream with ID %d", stream->id,
1278 demux->stream[i].id);
1283 /* we can only be in this group once, let's break out and move on to
1284 * the next mutual exclusion group */
1295 gst_asf_demux_check_segment_ts (GstASFDemux * demux, GstClockTime payload_ts)
1297 /* remember the first queued timestamp for the segment */
1298 if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (demux->segment_ts) &&
1299 GST_CLOCK_TIME_IS_VALID (demux->first_ts))) {
1300 GST_DEBUG_OBJECT (demux, "segment ts: %" GST_TIME_FORMAT,
1301 GST_TIME_ARGS (demux->first_ts));
1302 demux->segment_ts = payload_ts;
1303 /* always note, but only determines segment when streaming */
1304 if (demux->streaming)
1305 gst_segment_do_seek (&demux->segment, demux->in_segment.rate,
1306 GST_FORMAT_TIME, (GstSeekFlags) demux->segment.flags,
1307 GST_SEEK_TYPE_SET, demux->segment_ts, GST_SEEK_TYPE_NONE, 0, NULL);
1312 gst_asf_demux_check_first_ts (GstASFDemux * demux, gboolean force)
1314 if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (demux->first_ts))) {
1315 GstClockTime first_ts = GST_CLOCK_TIME_NONE;
1318 /* go trhough each stream, find smallest timestamp */
1319 for (i = 0; i < demux->num_streams; ++i) {
1322 GstClockTime stream_min_ts = GST_CLOCK_TIME_NONE;
1323 GstClockTime stream_min_ts2 = GST_CLOCK_TIME_NONE; /* second smallest timestamp */
1324 stream = &demux->stream[i];
1326 for (j = 0; j < stream->payloads->len; ++j) {
1327 AsfPayload *payload = &g_array_index (stream->payloads, AsfPayload, j);
1328 if (GST_CLOCK_TIME_IS_VALID (payload->ts) &&
1329 (!GST_CLOCK_TIME_IS_VALID (stream_min_ts)
1330 || stream_min_ts > payload->ts)) {
1331 stream_min_ts = payload->ts;
1333 if (GST_CLOCK_TIME_IS_VALID (payload->ts) &&
1334 payload->ts > stream_min_ts &&
1335 (!GST_CLOCK_TIME_IS_VALID (stream_min_ts2)
1336 || stream_min_ts2 > payload->ts)) {
1337 stream_min_ts2 = payload->ts;
1341 /* there are some DVR ms files where first packet has TS of 0 (instead of -1) while subsequent packets have
1342 regular (singificantly larger) timestamps. If we don't deal with it, we may end up with huge gap in timestamps
1343 which makes playback stuck. The 0 timestamp may also be valid though, if the second packet timestamp continues
1344 from it. I havent found a better way to distinguish between these two, except to set an arbitrary boundary
1345 and disregard the first 0 timestamp if the second timestamp is bigger than the boundary) */
1347 if (stream_min_ts == 0 && stream_min_ts2 == GST_CLOCK_TIME_NONE && !force) /* still waiting for the second timestamp */
1350 if (stream_min_ts == 0 && stream_min_ts2 > GST_SECOND) /* first timestamp is 0 and second is significantly larger, disregard the 0 */
1351 stream_min_ts = stream_min_ts2;
1353 /* if we don't have timestamp for this stream, wait for more data */
1354 if (!GST_CLOCK_TIME_IS_VALID (stream_min_ts) && !force)
1357 if (GST_CLOCK_TIME_IS_VALID (stream_min_ts) &&
1358 (!GST_CLOCK_TIME_IS_VALID (first_ts) || first_ts > stream_min_ts))
1359 first_ts = stream_min_ts;
1362 if (!GST_CLOCK_TIME_IS_VALID (first_ts)) /* can happen with force = TRUE */
1365 demux->first_ts = first_ts;
1367 /* update packets queued before we knew first timestamp */
1368 for (i = 0; i < demux->num_streams; ++i) {
1371 stream = &demux->stream[i];
1373 for (j = 0; j < stream->payloads->len; ++j) {
1374 AsfPayload *payload = &g_array_index (stream->payloads, AsfPayload, j);
1375 if (GST_CLOCK_TIME_IS_VALID (payload->ts)) {
1376 if (payload->ts > first_ts)
1377 payload->ts -= first_ts;
1385 gst_asf_demux_check_segment_ts (demux, 0);
1391 gst_asf_demux_update_caps_from_payload (GstASFDemux * demux, AsfStream * stream)
1393 /* try to determine whether the stream is AC-3 or MPEG; In dvr-ms the codecTag is unreliable
1394 and often set wrong, inspecting the data is the only way that seem to be working */
1395 GstTypeFindProbability prob = GST_TYPE_FIND_NONE;
1396 GstCaps *caps = NULL;
1398 GstAdapter *adapter = gst_adapter_new ();
1400 for (i = 0; i < stream->payloads->len && prob < GST_TYPE_FIND_LIKELY; ++i) {
1402 AsfPayload *payload;
1405 payload = &g_array_index (stream->payloads, AsfPayload, i);
1406 gst_adapter_push (adapter, gst_buffer_ref (payload->buf));
1407 len = gst_adapter_available (adapter);
1408 data = gst_adapter_map (adapter, len);
1412 #define MIN_LENGTH 128
1414 /* look for the sync points */
1416 if (len < MIN_LENGTH || /* give typefind something to work on */
1417 (data[0] == 0x0b && data[1] == 0x77) || /* AC-3 sync point */
1418 (data[0] == 0xFF && ((data[1] & 0xF0) >> 4) == 0xF)) /* MPEG sync point */
1424 gst_caps_take (&caps, gst_type_find_helper_for_data (GST_OBJECT (demux),
1427 if (prob < GST_TYPE_FIND_LIKELY) {
1430 if (len > MIN_LENGTH)
1431 /* this wasn't it, look for another sync point */
1435 gst_adapter_unmap (adapter);
1438 gst_object_unref (adapter);
1441 gst_caps_take (&stream->caps, caps);
1449 gst_asf_demux_check_activate_streams (GstASFDemux * demux, gboolean force)
1453 if (demux->activated_streams)
1456 if (G_UNLIKELY (!gst_asf_demux_check_first_ts (demux, force)))
1459 if (!all_streams_prerolled (demux) && !force) {
1460 GST_DEBUG_OBJECT (demux, "not all streams with data beyond preroll yet");
1464 for (i = 0; i < demux->num_streams; ++i) {
1465 AsfStream *stream = &demux->stream[i];
1467 if (stream->payloads->len > 0) {
1469 if (stream->inspect_payload && /* dvr-ms required payload inspection */
1470 !stream->active && /* do not inspect active streams (caps were already set) */
1471 !gst_asf_demux_update_caps_from_payload (demux, stream) && /* failed to determine caps */
1472 stream->payloads->len < 20) { /* if we couldn't determine the caps from 20 packets then just give up and use whatever was in codecTag */
1473 /* try to gather some more data */
1476 /* we don't check mutual exclusion stuff here; either we have data for
1477 * a stream, then we active it, or we don't, then we'll ignore it */
1478 GST_LOG_OBJECT (stream->pad, "is prerolled - activate!");
1479 gst_asf_demux_activate_stream (demux, stream);
1481 GST_LOG_OBJECT (stream->pad, "no data, ignoring stream");
1485 gst_asf_demux_release_old_pads (demux);
1487 demux->activated_streams = TRUE;
1488 GST_LOG_OBJECT (demux, "signalling no more pads");
1489 gst_element_no_more_pads (GST_ELEMENT (demux));
1493 /* returns the stream that has a complete payload with the lowest timestamp
1494 * queued, or NULL (we push things by timestamp because during the internal
1495 * prerolling we might accumulate more data then the external queues can take,
1496 * so we'd lock up if we pushed all accumulated data for stream N in one go) */
1498 gst_asf_demux_find_stream_with_complete_payload (GstASFDemux * demux)
1500 AsfPayload *best_payload = NULL;
1501 AsfStream *best_stream = NULL;
1504 for (i = 0; i < demux->num_streams; ++i) {
1508 stream = &demux->stream[i];
1510 /* Don't push any data until we have at least one payload that falls within
1511 * the current segment. This way we can remove out-of-segment payloads that
1512 * don't need to be decoded after a seek, sending only data from the
1513 * keyframe directly before our segment start */
1514 if (stream->payloads->len > 0) {
1515 AsfPayload *payload = NULL;
1518 /* find last payload with timestamp */
1519 for (last_idx = stream->payloads->len - 1;
1520 last_idx >= 0 && (payload == NULL
1521 || !GST_CLOCK_TIME_IS_VALID (payload->ts)); --last_idx) {
1522 payload = &g_array_index (stream->payloads, AsfPayload, last_idx);
1525 /* if this is first payload after seek we might need to update the segment */
1526 if (GST_CLOCK_TIME_IS_VALID (payload->ts))
1527 gst_asf_demux_check_segment_ts (demux, payload->ts);
1529 if (G_UNLIKELY (GST_CLOCK_TIME_IS_VALID (payload->ts) &&
1530 (payload->ts < demux->segment.start))) {
1531 if (G_UNLIKELY ((!demux->accurate) && payload->keyframe)) {
1532 GST_DEBUG_OBJECT (stream->pad,
1533 "Found keyframe, updating segment start to %" GST_TIME_FORMAT,
1534 GST_TIME_ARGS (payload->ts));
1535 demux->segment.start = payload->ts;
1536 demux->segment.time = payload->ts;
1538 GST_DEBUG_OBJECT (stream->pad, "Last queued payload has timestamp %"
1539 GST_TIME_FORMAT " which is before our segment start %"
1540 GST_TIME_FORMAT ", not pushing yet", GST_TIME_ARGS (payload->ts),
1541 GST_TIME_ARGS (demux->segment.start));
1546 /* Now see if there's a complete payload queued for this stream */
1549 /* find first complete payload with timestamp */
1551 j < stream->payloads->len && (payload == NULL
1552 || !GST_CLOCK_TIME_IS_VALID (payload->ts)); ++j) {
1553 payload = &g_array_index (stream->payloads, AsfPayload, j);
1556 if (!gst_asf_payload_is_complete (payload))
1559 /* ... and whether its timestamp is lower than the current best */
1560 if (best_stream == NULL || best_payload->ts > payload->ts) {
1561 best_stream = stream;
1562 best_payload = payload;
1570 static GstFlowReturn
1571 gst_asf_demux_push_complete_payloads (GstASFDemux * demux, gboolean force)
1574 GstFlowReturn ret = GST_FLOW_OK;
1576 if (G_UNLIKELY (!demux->activated_streams)) {
1577 if (!gst_asf_demux_check_activate_streams (demux, force))
1579 /* streams are now activated */
1582 while ((stream = gst_asf_demux_find_stream_with_complete_payload (demux))) {
1583 AsfPayload *payload;
1585 /* wait until we had a chance to "lock on" some payload's timestamp */
1586 if (G_UNLIKELY (demux->need_newsegment
1587 && !GST_CLOCK_TIME_IS_VALID (demux->segment_ts)))
1590 payload = &g_array_index (stream->payloads, AsfPayload, 0);
1592 /* do we need to send a newsegment event */
1593 if ((G_UNLIKELY (demux->need_newsegment))) {
1594 GstEvent *segment_event;
1596 /* safe default if insufficient upstream info */
1597 if (!GST_CLOCK_TIME_IS_VALID (demux->in_gap))
1600 if (demux->segment.stop == GST_CLOCK_TIME_NONE &&
1601 demux->segment.duration > 0) {
1602 /* slight HACK; prevent clipping of last bit */
1603 demux->segment.stop = demux->segment.duration + demux->in_gap;
1606 /* FIXME : only if ACCURATE ! */
1607 if (G_LIKELY (!demux->accurate
1608 && (GST_CLOCK_TIME_IS_VALID (payload->ts)))) {
1609 GST_DEBUG ("Adjusting newsegment start to %" GST_TIME_FORMAT,
1610 GST_TIME_ARGS (payload->ts));
1611 demux->segment.start = payload->ts;
1612 demux->segment.time = payload->ts;
1615 GST_DEBUG_OBJECT (demux, "sending new-segment event %" GST_SEGMENT_FORMAT,
1618 /* note: we fix up all timestamps to start from 0, so this should be ok */
1619 segment_event = gst_event_new_segment (&demux->segment);
1620 if (demux->segment_seqnum)
1621 gst_event_set_seqnum (segment_event, demux->segment_seqnum);
1622 gst_asf_demux_send_event_unlocked (demux, segment_event);
1624 /* now post any global tags we may have found */
1625 if (demux->taglist == NULL) {
1626 demux->taglist = gst_tag_list_new_empty ();
1627 gst_tag_list_set_scope (demux->taglist, GST_TAG_SCOPE_GLOBAL);
1630 gst_tag_list_add (demux->taglist, GST_TAG_MERGE_REPLACE,
1631 GST_TAG_CONTAINER_FORMAT, "ASF", NULL);
1633 GST_DEBUG_OBJECT (demux, "global tags: %" GST_PTR_FORMAT, demux->taglist);
1634 gst_asf_demux_send_event_unlocked (demux,
1635 gst_event_new_tag (demux->taglist));
1636 demux->taglist = NULL;
1638 demux->need_newsegment = FALSE;
1639 demux->segment_seqnum = 0;
1640 demux->segment_running = TRUE;
1643 /* Do we have tags pending for this stream? */
1644 if (G_UNLIKELY (stream->pending_tags)) {
1645 GST_LOG_OBJECT (stream->pad, "%" GST_PTR_FORMAT, stream->pending_tags);
1646 gst_pad_push_event (stream->pad,
1647 gst_event_new_tag (stream->pending_tags));
1648 stream->pending_tags = NULL;
1651 /* We have the whole packet now so we should push the packet to
1652 * the src pad now. First though we should check if we need to do
1654 if (G_UNLIKELY (stream->span > 1)) {
1655 gst_asf_demux_descramble_buffer (demux, stream, &payload->buf);
1658 payload->buf = gst_buffer_make_writable (payload->buf);
1660 if (G_LIKELY (!payload->keyframe)) {
1661 GST_BUFFER_FLAG_SET (payload->buf, GST_BUFFER_FLAG_DELTA_UNIT);
1664 if (G_UNLIKELY (stream->discont)) {
1665 GST_DEBUG_OBJECT (stream->pad, "marking DISCONT on stream");
1666 GST_BUFFER_FLAG_SET (payload->buf, GST_BUFFER_FLAG_DISCONT);
1667 stream->discont = FALSE;
1670 if (G_UNLIKELY (stream->is_video && payload->par_x && payload->par_y &&
1671 (payload->par_x != stream->par_x) &&
1672 (payload->par_y != stream->par_y))) {
1673 GST_DEBUG ("Updating PAR (%d/%d => %d/%d)",
1674 stream->par_x, stream->par_y, payload->par_x, payload->par_y);
1675 stream->par_x = payload->par_x;
1676 stream->par_y = payload->par_y;
1677 stream->caps = gst_caps_make_writable (stream->caps);
1678 gst_caps_set_simple (stream->caps, "pixel-aspect-ratio",
1679 GST_TYPE_FRACTION, stream->par_x, stream->par_y, NULL);
1680 gst_pad_set_caps (stream->pad, stream->caps);
1683 if (G_UNLIKELY (stream->interlaced != payload->interlaced)) {
1684 GST_DEBUG ("Updating interlaced status (%d => %d)", stream->interlaced,
1685 payload->interlaced);
1686 stream->interlaced = payload->interlaced;
1687 stream->caps = gst_caps_make_writable (stream->caps);
1688 gst_caps_set_simple (stream->caps, "interlace-mode", G_TYPE_BOOLEAN,
1689 (stream->interlaced ? "mixed" : "progressive"), NULL);
1690 gst_pad_set_caps (stream->pad, stream->caps);
1693 /* (sort of) interpolate timestamps using upstream "frame of reference",
1694 * typically useful for live src, but might (unavoidably) mess with
1695 * position reporting if a live src is playing not so live content
1696 * (e.g. rtspsrc taking some time to fall back to tcp) */
1697 GST_BUFFER_PTS (payload->buf) = payload->ts;
1698 if (GST_BUFFER_PTS_IS_VALID (payload->buf)) {
1699 GST_BUFFER_PTS (payload->buf) += demux->in_gap;
1701 if (payload->duration == GST_CLOCK_TIME_NONE
1702 && stream->ext_props.avg_time_per_frame != 0)
1703 GST_BUFFER_DURATION (payload->buf) =
1704 stream->ext_props.avg_time_per_frame * 100;
1706 GST_BUFFER_DURATION (payload->buf) = payload->duration;
1708 /* FIXME: we should really set durations on buffers if we can */
1710 GST_LOG_OBJECT (stream->pad, "pushing buffer, %" GST_PTR_FORMAT,
1713 if (stream->active) {
1714 if (G_UNLIKELY (stream->first_buffer)) {
1715 if (stream->streamheader != NULL) {
1716 GST_DEBUG_OBJECT (stream->pad,
1717 "Pushing streamheader before first buffer");
1718 gst_pad_push (stream->pad, gst_buffer_ref (stream->streamheader));
1720 stream->first_buffer = FALSE;
1723 ret = gst_pad_push (stream->pad, payload->buf);
1724 ret = gst_flow_combiner_update_flow (demux->flowcombiner, ret);
1726 gst_buffer_unref (payload->buf);
1729 payload->buf = NULL;
1730 g_array_remove_index (stream->payloads, 0);
1732 /* Break out as soon as we have an issue */
1733 if (G_UNLIKELY (ret != GST_FLOW_OK))
1741 gst_asf_demux_check_buffer_is_header (GstASFDemux * demux, GstBuffer * buf)
1745 g_assert (buf != NULL);
1747 GST_LOG_OBJECT (demux, "Checking if buffer is a header");
1749 gst_buffer_map (buf, &map, GST_MAP_READ);
1751 /* we return false on buffer too small */
1752 if (map.size < ASF_OBJECT_HEADER_SIZE) {
1753 gst_buffer_unmap (buf, &map);
1757 /* check if it is a header */
1758 asf_demux_peek_object (demux, map.data, ASF_OBJECT_HEADER_SIZE, &obj, TRUE);
1759 gst_buffer_unmap (buf, &map);
1760 if (obj.id == ASF_OBJ_HEADER) {
1767 gst_asf_demux_check_chained_asf (GstASFDemux * demux)
1769 guint64 off = demux->data_offset + (demux->packet * demux->packet_size);
1770 GstFlowReturn ret = GST_FLOW_OK;
1771 GstBuffer *buf = NULL;
1772 gboolean header = FALSE;
1774 /* TODO maybe we should skip index objects after the data and look
1775 * further for a new header */
1776 if (gst_asf_demux_pull_data (demux, off, ASF_OBJECT_HEADER_SIZE, &buf, &ret)) {
1777 g_assert (buf != NULL);
1778 /* check if it is a header */
1779 if (gst_asf_demux_check_buffer_is_header (demux, buf)) {
1780 GST_DEBUG_OBJECT (demux, "new base offset: %" G_GUINT64_FORMAT, off);
1781 demux->base_offset = off;
1785 gst_buffer_unref (buf);
1792 gst_asf_demux_loop (GstASFDemux * demux)
1794 GstFlowReturn flow = GST_FLOW_OK;
1795 GstBuffer *buf = NULL;
1797 gboolean sent_eos = FALSE;
1799 if (G_UNLIKELY (demux->state == GST_ASF_DEMUX_STATE_HEADER)) {
1800 if (!gst_asf_demux_pull_headers (demux)) {
1801 flow = GST_FLOW_ERROR;
1805 gst_asf_demux_pull_indices (demux);
1808 g_assert (demux->state == GST_ASF_DEMUX_STATE_DATA);
1810 if (G_UNLIKELY (demux->num_packets != 0
1811 && demux->packet >= demux->num_packets))
1814 GST_LOG_OBJECT (demux, "packet %u/%u", (guint) demux->packet + 1,
1815 (guint) demux->num_packets);
1817 off = demux->data_offset + (demux->packet * demux->packet_size);
1819 if (G_UNLIKELY (!gst_asf_demux_pull_data (demux, off,
1820 demux->packet_size * demux->speed_packets, &buf, &flow))) {
1821 GST_DEBUG_OBJECT (demux, "got flow %s", gst_flow_get_name (flow));
1822 if (flow == GST_FLOW_EOS)
1824 else if (flow == GST_FLOW_FLUSHING) {
1825 GST_DEBUG_OBJECT (demux, "Not fatal");
1831 if (G_LIKELY (demux->speed_packets == 1)) {
1832 GstAsfDemuxParsePacketError err;
1833 err = gst_asf_demux_parse_packet (demux, buf);
1834 if (G_UNLIKELY (err != GST_ASF_DEMUX_PARSE_PACKET_ERROR_NONE)) {
1835 /* when we don't know when the data object ends, we should check
1836 * for a chained asf */
1837 if (demux->num_packets == 0) {
1838 if (gst_asf_demux_check_buffer_is_header (demux, buf)) {
1839 GST_INFO_OBJECT (demux, "Chained asf found");
1840 demux->base_offset = off;
1841 gst_asf_demux_reset (demux, TRUE);
1842 gst_buffer_unref (buf);
1846 /* FIXME: We should tally up fatal errors and error out only
1847 * after a few broken packets in a row? */
1849 GST_INFO_OBJECT (demux, "Ignoring recoverable parse error");
1850 gst_buffer_unref (buf);
1855 flow = gst_asf_demux_push_complete_payloads (demux, FALSE);
1861 for (n = 0; n < demux->speed_packets; n++) {
1863 GstAsfDemuxParsePacketError err;
1866 gst_buffer_copy_region (buf, GST_BUFFER_COPY_ALL,
1867 n * demux->packet_size, demux->packet_size);
1868 err = gst_asf_demux_parse_packet (demux, sub);
1869 if (G_UNLIKELY (err != GST_ASF_DEMUX_PARSE_PACKET_ERROR_NONE)) {
1870 /* when we don't know when the data object ends, we should check
1871 * for a chained asf */
1872 if (demux->num_packets == 0) {
1873 if (gst_asf_demux_check_buffer_is_header (demux, sub)) {
1874 GST_INFO_OBJECT (demux, "Chained asf found");
1875 demux->base_offset = off + n * demux->packet_size;
1876 gst_asf_demux_reset (demux, TRUE);
1877 gst_buffer_unref (sub);
1878 gst_buffer_unref (buf);
1882 /* FIXME: We should tally up fatal errors and error out only
1883 * after a few broken packets in a row? */
1885 GST_INFO_OBJECT (demux, "Ignoring recoverable parse error");
1889 gst_buffer_unref (sub);
1891 if (err == GST_ASF_DEMUX_PARSE_PACKET_ERROR_NONE)
1892 flow = gst_asf_demux_push_complete_payloads (demux, FALSE);
1898 /* reset speed pull */
1899 demux->speed_packets = 1;
1902 gst_buffer_unref (buf);
1904 if (G_UNLIKELY (demux->num_packets > 0
1905 && demux->packet >= demux->num_packets)) {
1906 GST_LOG_OBJECT (demux, "reached EOS");
1910 if (G_UNLIKELY (flow != GST_FLOW_OK)) {
1911 GST_DEBUG_OBJECT (demux, "pushing complete payloads failed");
1915 /* check if we're at the end of the configured segment */
1916 /* FIXME: check if segment end reached etc. */
1922 /* if we haven't activated our streams yet, this might be because we have
1923 * less data queued than required for preroll; force stream activation and
1924 * send any pending payloads before sending EOS */
1925 if (!demux->activated_streams)
1926 gst_asf_demux_push_complete_payloads (demux, TRUE);
1928 /* we want to push an eos or post a segment-done in any case */
1929 if (demux->segment.flags & GST_SEEK_FLAG_SEGMENT) {
1932 /* for segment playback we need to post when (in stream time)
1933 * we stopped, this is either stop (when set) or the duration. */
1934 if ((stop = demux->segment.stop) == -1)
1935 stop = demux->segment.duration;
1937 GST_INFO_OBJECT (demux, "Posting segment-done, at end of segment");
1938 gst_element_post_message (GST_ELEMENT_CAST (demux),
1939 gst_message_new_segment_done (GST_OBJECT (demux), GST_FORMAT_TIME,
1941 gst_asf_demux_send_event_unlocked (demux,
1942 gst_event_new_segment_done (GST_FORMAT_TIME, stop));
1943 } else if (flow != GST_FLOW_EOS) {
1944 /* check if we have a chained asf, in case, we don't eos yet */
1945 if (gst_asf_demux_check_chained_asf (demux)) {
1946 GST_INFO_OBJECT (demux, "Chained ASF starting");
1947 gst_asf_demux_reset (demux, TRUE);
1951 /* normal playback, send EOS to all linked pads */
1952 GST_INFO_OBJECT (demux, "Sending EOS, at end of stream");
1953 gst_asf_demux_send_event_unlocked (demux, gst_event_new_eos ());
1955 /* ... and fall through to pause */
1959 GST_DEBUG_OBJECT (demux, "pausing task, flow return: %s",
1960 gst_flow_get_name (flow));
1961 demux->segment_running = FALSE;
1962 gst_pad_pause_task (demux->sinkpad);
1964 /* For the error cases (not EOS) */
1966 if (flow == GST_FLOW_EOS)
1967 gst_asf_demux_send_event_unlocked (demux, gst_event_new_eos ());
1968 else if (flow < GST_FLOW_EOS || flow == GST_FLOW_NOT_LINKED) {
1969 /* Post an error. Hopefully something else already has, but if not... */
1970 GST_ELEMENT_ERROR (demux, STREAM, FAILED,
1971 (_("Internal data stream error.")),
1972 ("streaming stopped, reason %s", gst_flow_get_name (flow)));
1981 GST_DEBUG_OBJECT (demux, "Read failed, doh");
1982 gst_asf_demux_send_event_unlocked (demux, gst_event_new_eos ());
1983 flow = GST_FLOW_EOS;
1987 /* See FIXMEs above */
1990 gst_buffer_unref (buf);
1991 GST_ELEMENT_ERROR (demux, STREAM, DEMUX, (NULL),
1992 ("Error parsing ASF packet %u", (guint) demux->packet));
1993 gst_asf_demux_send_event_unlocked (demux, gst_event_new_eos ());
1994 flow = GST_FLOW_ERROR;
2000 #define GST_ASF_DEMUX_CHECK_HEADER_YES 0
2001 #define GST_ASF_DEMUX_CHECK_HEADER_NO 1
2002 #define GST_ASF_DEMUX_CHECK_HEADER_NEED_DATA 2
2005 gst_asf_demux_check_header (GstASFDemux * demux)
2008 guint8 *cdata = (guint8 *) gst_adapter_map (demux->adapter,
2009 ASF_OBJECT_HEADER_SIZE);
2010 if (cdata == NULL) /* need more data */
2011 return GST_ASF_DEMUX_CHECK_HEADER_NEED_DATA;
2013 asf_demux_peek_object (demux, cdata, ASF_OBJECT_HEADER_SIZE, &obj, FALSE);
2014 if (obj.id != ASF_OBJ_HEADER) {
2015 return GST_ASF_DEMUX_CHECK_HEADER_NO;
2017 return GST_ASF_DEMUX_CHECK_HEADER_YES;
2021 static GstFlowReturn
2022 gst_asf_demux_chain (GstPad * pad, GstObject * parent, GstBuffer * buf)
2024 GstFlowReturn ret = GST_FLOW_OK;
2027 demux = GST_ASF_DEMUX (parent);
2029 GST_LOG_OBJECT (demux,
2030 "buffer: size=%" G_GSIZE_FORMAT ", offset=%" G_GINT64_FORMAT ", time=%"
2031 GST_TIME_FORMAT, gst_buffer_get_size (buf), GST_BUFFER_OFFSET (buf),
2032 GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)));
2034 if (G_UNLIKELY (GST_BUFFER_IS_DISCONT (buf))) {
2035 GST_DEBUG_OBJECT (demux, "received DISCONT");
2036 gst_asf_demux_mark_discont (demux);
2039 if (G_UNLIKELY ((!GST_CLOCK_TIME_IS_VALID (demux->in_gap) &&
2040 GST_BUFFER_TIMESTAMP_IS_VALID (buf)))) {
2041 demux->in_gap = GST_BUFFER_TIMESTAMP (buf) - demux->in_segment.start;
2042 GST_DEBUG_OBJECT (demux, "upstream segment start %" GST_TIME_FORMAT
2043 ", interpolation gap: %" GST_TIME_FORMAT,
2044 GST_TIME_ARGS (demux->in_segment.start), GST_TIME_ARGS (demux->in_gap));
2047 gst_adapter_push (demux->adapter, buf);
2049 switch (demux->state) {
2050 case GST_ASF_DEMUX_STATE_INDEX:{
2051 gint result = gst_asf_demux_check_header (demux);
2052 if (result == GST_ASF_DEMUX_CHECK_HEADER_NEED_DATA) /* need more data */
2055 if (result == GST_ASF_DEMUX_CHECK_HEADER_NO) {
2056 /* we don't care about this, probably an index */
2057 /* TODO maybe would be smarter to skip all the indices
2058 * until we got a new header or EOS to decide */
2059 GST_LOG_OBJECT (demux, "Received index object, its EOS");
2062 GST_INFO_OBJECT (demux, "Chained asf starting");
2063 /* cleanup and get ready for a chained asf */
2064 gst_asf_demux_reset (demux, TRUE);
2068 case GST_ASF_DEMUX_STATE_HEADER:{
2069 ret = gst_asf_demux_chain_headers (demux);
2070 if (demux->state != GST_ASF_DEMUX_STATE_DATA)
2072 /* otherwise fall through */
2074 case GST_ASF_DEMUX_STATE_DATA:
2078 data_size = demux->packet_size;
2080 while (gst_adapter_available (demux->adapter) >= data_size) {
2082 GstAsfDemuxParsePacketError err;
2084 /* we don't know the length of the stream
2085 * check for a chained asf everytime */
2086 if (demux->num_packets == 0) {
2087 gint result = gst_asf_demux_check_header (demux);
2089 if (result == GST_ASF_DEMUX_CHECK_HEADER_YES) {
2090 GST_INFO_OBJECT (demux, "Chained asf starting");
2091 /* cleanup and get ready for a chained asf */
2092 gst_asf_demux_reset (demux, TRUE);
2095 } else if (G_UNLIKELY (demux->num_packets != 0 && demux->packet >= 0
2096 && demux->packet >= demux->num_packets)) {
2097 /* do not overshoot data section when streaming */
2101 buf = gst_adapter_take_buffer (demux->adapter, data_size);
2103 /* FIXME: We should tally up fatal errors and error out only
2104 * after a few broken packets in a row? */
2105 err = gst_asf_demux_parse_packet (demux, buf);
2107 gst_buffer_unref (buf);
2109 if (G_LIKELY (err == GST_ASF_DEMUX_PARSE_PACKET_ERROR_NONE))
2110 ret = gst_asf_demux_push_complete_payloads (demux, FALSE);
2112 GST_WARNING_OBJECT (demux, "Parse error");
2114 if (demux->packet >= 0)
2117 if (G_UNLIKELY (demux->num_packets != 0 && demux->packet >= 0
2118 && demux->packet >= demux->num_packets)) {
2119 demux->state = GST_ASF_DEMUX_STATE_INDEX;
2124 g_assert_not_reached ();
2128 if (ret != GST_FLOW_OK)
2129 GST_DEBUG_OBJECT (demux, "flow: %s", gst_flow_get_name (ret));
2135 GST_DEBUG_OBJECT (demux, "Handled last packet, setting EOS");
2141 static inline gboolean
2142 gst_asf_demux_skip_bytes (guint num_bytes, guint8 ** p_data, guint64 * p_size)
2144 if (*p_size < num_bytes)
2147 *p_data += num_bytes;
2148 *p_size -= num_bytes;
2152 static inline guint8
2153 gst_asf_demux_get_uint8 (guint8 ** p_data, guint64 * p_size)
2157 g_assert (*p_size >= 1);
2158 ret = GST_READ_UINT8 (*p_data);
2159 *p_data += sizeof (guint8);
2160 *p_size -= sizeof (guint8);
2164 static inline guint16
2165 gst_asf_demux_get_uint16 (guint8 ** p_data, guint64 * p_size)
2169 g_assert (*p_size >= 2);
2170 ret = GST_READ_UINT16_LE (*p_data);
2171 *p_data += sizeof (guint16);
2172 *p_size -= sizeof (guint16);
2176 static inline guint32
2177 gst_asf_demux_get_uint32 (guint8 ** p_data, guint64 * p_size)
2181 g_assert (*p_size >= 4);
2182 ret = GST_READ_UINT32_LE (*p_data);
2183 *p_data += sizeof (guint32);
2184 *p_size -= sizeof (guint32);
2188 static inline guint64
2189 gst_asf_demux_get_uint64 (guint8 ** p_data, guint64 * p_size)
2193 g_assert (*p_size >= 8);
2194 ret = GST_READ_UINT64_LE (*p_data);
2195 *p_data += sizeof (guint64);
2196 *p_size -= sizeof (guint64);
2201 gst_asf_demux_get_buffer (GstBuffer ** p_buf, guint num_bytes_to_read,
2202 guint8 ** p_data, guint64 * p_size)
2206 if (*p_size < num_bytes_to_read)
2209 *p_buf = gst_buffer_new_and_alloc (num_bytes_to_read);
2210 gst_buffer_fill (*p_buf, 0, *p_data, num_bytes_to_read);
2212 *p_data += num_bytes_to_read;
2213 *p_size -= num_bytes_to_read;
2219 gst_asf_demux_get_bytes (guint8 ** p_buf, guint num_bytes_to_read,
2220 guint8 ** p_data, guint64 * p_size)
2224 if (*p_size < num_bytes_to_read)
2227 *p_buf = g_memdup (*p_data, num_bytes_to_read);
2228 *p_data += num_bytes_to_read;
2229 *p_size -= num_bytes_to_read;
2234 gst_asf_demux_get_string (gchar ** p_str, guint16 * p_strlen,
2235 guint8 ** p_data, guint64 * p_size)
2245 s_length = gst_asf_demux_get_uint16 (p_data, p_size);
2248 *p_strlen = s_length;
2250 if (s_length == 0) {
2251 GST_WARNING ("zero-length string");
2252 *p_str = g_strdup ("");
2256 if (!gst_asf_demux_get_bytes (&s, s_length, p_data, p_size))
2259 g_assert (s != NULL);
2261 /* just because They don't exist doesn't
2262 * mean They are not out to get you ... */
2263 if (s[s_length - 1] != '\0') {
2264 s = g_realloc (s, s_length + 1);
2268 *p_str = (gchar *) s;
2274 gst_asf_demux_get_guid (ASFGuid * guid, guint8 ** p_data, guint64 * p_size)
2276 g_assert (*p_size >= 4 * sizeof (guint32));
2278 guid->v1 = gst_asf_demux_get_uint32 (p_data, p_size);
2279 guid->v2 = gst_asf_demux_get_uint32 (p_data, p_size);
2280 guid->v3 = gst_asf_demux_get_uint32 (p_data, p_size);
2281 guid->v4 = gst_asf_demux_get_uint32 (p_data, p_size);
2285 gst_asf_demux_get_stream_audio (asf_stream_audio * audio, guint8 ** p_data,
2288 if (*p_size < (2 + 2 + 4 + 4 + 2 + 2 + 2))
2291 /* WAVEFORMATEX Structure */
2292 audio->codec_tag = gst_asf_demux_get_uint16 (p_data, p_size);
2293 audio->channels = gst_asf_demux_get_uint16 (p_data, p_size);
2294 audio->sample_rate = gst_asf_demux_get_uint32 (p_data, p_size);
2295 audio->byte_rate = gst_asf_demux_get_uint32 (p_data, p_size);
2296 audio->block_align = gst_asf_demux_get_uint16 (p_data, p_size);
2297 audio->word_size = gst_asf_demux_get_uint16 (p_data, p_size);
2298 /* Codec specific data size */
2299 audio->size = gst_asf_demux_get_uint16 (p_data, p_size);
2304 gst_asf_demux_get_stream_video (asf_stream_video * video, guint8 ** p_data,
2307 if (*p_size < (4 + 4 + 1 + 2))
2310 video->width = gst_asf_demux_get_uint32 (p_data, p_size);
2311 video->height = gst_asf_demux_get_uint32 (p_data, p_size);
2312 video->unknown = gst_asf_demux_get_uint8 (p_data, p_size);
2313 video->size = gst_asf_demux_get_uint16 (p_data, p_size);
2318 gst_asf_demux_get_stream_video_format (asf_stream_video_format * fmt,
2319 guint8 ** p_data, guint64 * p_size)
2321 if (*p_size < (4 + 4 + 4 + 2 + 2 + 4 + 4 + 4 + 4 + 4 + 4))
2324 fmt->size = gst_asf_demux_get_uint32 (p_data, p_size);
2325 fmt->width = gst_asf_demux_get_uint32 (p_data, p_size);
2326 fmt->height = gst_asf_demux_get_uint32 (p_data, p_size);
2327 fmt->planes = gst_asf_demux_get_uint16 (p_data, p_size);
2328 fmt->depth = gst_asf_demux_get_uint16 (p_data, p_size);
2329 fmt->tag = gst_asf_demux_get_uint32 (p_data, p_size);
2330 fmt->image_size = gst_asf_demux_get_uint32 (p_data, p_size);
2331 fmt->xpels_meter = gst_asf_demux_get_uint32 (p_data, p_size);
2332 fmt->ypels_meter = gst_asf_demux_get_uint32 (p_data, p_size);
2333 fmt->num_colors = gst_asf_demux_get_uint32 (p_data, p_size);
2334 fmt->imp_colors = gst_asf_demux_get_uint32 (p_data, p_size);
2339 gst_asf_demux_get_stream (GstASFDemux * demux, guint16 id)
2343 for (i = 0; i < demux->num_streams; i++) {
2344 if (demux->stream[i].id == id)
2345 return &demux->stream[i];
2348 if (gst_asf_demux_is_unknown_stream (demux, id))
2349 GST_WARNING ("Segment found for undefined stream: (%d)", id);
2354 gst_asf_demux_setup_pad (GstASFDemux * demux, GstPad * src_pad,
2355 GstCaps * caps, guint16 id, gboolean is_video, GstBuffer * streamheader,
2360 gst_pad_use_fixed_caps (src_pad);
2361 gst_pad_set_caps (src_pad, caps);
2363 gst_pad_set_event_function (src_pad,
2364 GST_DEBUG_FUNCPTR (gst_asf_demux_handle_src_event));
2365 gst_pad_set_query_function (src_pad,
2366 GST_DEBUG_FUNCPTR (gst_asf_demux_handle_src_query));
2368 stream = &demux->stream[demux->num_streams];
2369 stream->caps = caps;
2370 stream->pad = src_pad;
2372 stream->fps_known = !is_video; /* bit hacky for audio */
2373 stream->is_video = is_video;
2374 stream->pending_tags = tags;
2375 stream->discont = TRUE;
2376 stream->first_buffer = TRUE;
2377 stream->streamheader = streamheader;
2378 if (stream->streamheader) {
2379 stream->streamheader = gst_buffer_make_writable (streamheader);
2380 GST_BUFFER_FLAG_SET (stream->streamheader, GST_BUFFER_FLAG_HEADER);
2385 st = gst_caps_get_structure (caps, 0);
2386 if (gst_structure_get_fraction (st, "pixel-aspect-ratio", &par_x, &par_y) &&
2387 par_x > 0 && par_y > 0) {
2388 GST_DEBUG ("PAR %d/%d", par_x, par_y);
2389 stream->par_x = par_x;
2390 stream->par_y = par_y;
2394 stream->payloads = g_array_new (FALSE, FALSE, sizeof (AsfPayload));
2396 GST_INFO ("Created pad %s for stream %u with caps %" GST_PTR_FORMAT,
2397 GST_PAD_NAME (src_pad), demux->num_streams, caps);
2399 ++demux->num_streams;
2401 stream->active = FALSE;
2407 gst_asf_demux_add_stream_headers_to_caps (GstASFDemux * demux,
2408 GstBuffer * buffer, GstStructure * structure)
2410 GValue arr_val = G_VALUE_INIT;
2411 GValue buf_val = G_VALUE_INIT;
2413 g_value_init (&arr_val, GST_TYPE_ARRAY);
2414 g_value_init (&buf_val, GST_TYPE_BUFFER);
2416 gst_value_set_buffer (&buf_val, buffer);
2417 gst_value_array_append_and_take_value (&arr_val, &buf_val);
2419 gst_structure_take_value (structure, "streamheader", &arr_val);
2423 gst_asf_demux_add_audio_stream (GstASFDemux * demux,
2424 asf_stream_audio * audio, guint16 id, guint8 ** p_data, guint64 * p_size)
2426 GstTagList *tags = NULL;
2427 GstBuffer *extradata = NULL;
2430 guint16 size_left = 0;
2431 gchar *codec_name = NULL;
2434 size_left = audio->size;
2436 /* Create the audio pad */
2437 name = g_strdup_printf ("audio_%u", demux->num_audio_streams);
2439 src_pad = gst_pad_new_from_static_template (&audio_src_template, name);
2442 /* Swallow up any left over data and set up the
2443 * standard properties from the header info */
2445 GST_INFO_OBJECT (demux, "Audio header contains %d bytes of "
2446 "codec specific data", size_left);
2448 g_assert (size_left <= *p_size);
2449 gst_asf_demux_get_buffer (&extradata, size_left, p_data, p_size);
2452 /* asf_stream_audio is the same as gst_riff_strf_auds, but with an
2453 * additional two bytes indicating extradata. */
2454 /* FIXME: Handle the channel reorder map here */
2455 caps = gst_riff_create_audio_caps (audio->codec_tag, NULL,
2456 (gst_riff_strf_auds *) audio, extradata, NULL, &codec_name, NULL);
2459 caps = gst_caps_new_simple ("audio/x-asf-unknown", "codec_id",
2460 G_TYPE_INT, (gint) audio->codec_tag, NULL);
2463 /* Informing about that audio format we just added */
2465 tags = gst_tag_list_new (GST_TAG_AUDIO_CODEC, codec_name, NULL);
2466 g_free (codec_name);
2470 gst_buffer_unref (extradata);
2472 GST_INFO ("Adding audio stream #%u, id %u codec %u (0x%04x), tags=%"
2473 GST_PTR_FORMAT, demux->num_audio_streams, id, audio->codec_tag,
2474 audio->codec_tag, tags);
2476 ++demux->num_audio_streams;
2478 return gst_asf_demux_setup_pad (demux, src_pad, caps, id, FALSE, NULL, tags);
2482 gst_asf_demux_add_video_stream (GstASFDemux * demux,
2483 asf_stream_video_format * video, guint16 id,
2484 guint8 ** p_data, guint64 * p_size)
2486 GstTagList *tags = NULL;
2487 GstStructure *caps_s;
2488 GstBuffer *extradata = NULL;
2493 gchar *codec_name = NULL;
2494 gint size_left = video->size - 40;
2495 GstBuffer *streamheader = NULL;
2497 /* Create the video pad */
2498 name = g_strdup_printf ("video_%u", demux->num_video_streams);
2499 src_pad = gst_pad_new_from_static_template (&video_src_template, name);
2502 /* Now try some gstreamer formatted MIME types (from gst_avi_demux_strf_vids) */
2504 GST_LOG ("Video header has %d bytes of codec specific data", size_left);
2505 g_assert (size_left <= *p_size);
2506 gst_asf_demux_get_buffer (&extradata, size_left, p_data, p_size);
2509 GST_DEBUG ("video codec %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (video->tag));
2511 /* yes, asf_stream_video_format and gst_riff_strf_vids are the same */
2512 caps = gst_riff_create_video_caps (video->tag, NULL,
2513 (gst_riff_strf_vids *) video, extradata, NULL, &codec_name);
2516 caps = gst_caps_new_simple ("video/x-asf-unknown", "fourcc",
2517 G_TYPE_UINT, video->tag, NULL);
2522 s = gst_asf_demux_get_metadata_for_stream (demux, id);
2523 if (gst_structure_get_int (s, "AspectRatioX", &ax) &&
2524 gst_structure_get_int (s, "AspectRatioY", &ay) && (ax > 0 && ay > 0)) {
2525 gst_caps_set_simple (caps, "pixel-aspect-ratio", GST_TYPE_FRACTION,
2530 /* retry with the global metadata */
2531 GST_DEBUG ("Retrying with global metadata %" GST_PTR_FORMAT,
2532 demux->global_metadata);
2533 s = demux->global_metadata;
2534 if (gst_structure_get_uint (s, "AspectRatioX", &ax) &&
2535 gst_structure_get_uint (s, "AspectRatioY", &ay)) {
2536 GST_DEBUG ("ax:%d, ay:%d", ax, ay);
2537 if (ax > 0 && ay > 0)
2538 gst_caps_set_simple (caps, "pixel-aspect-ratio", GST_TYPE_FRACTION,
2542 s = gst_caps_get_structure (caps, 0);
2543 gst_structure_remove_field (s, "framerate");
2546 caps_s = gst_caps_get_structure (caps, 0);
2548 /* add format field with fourcc to WMV/VC1 caps to differentiate variants */
2549 if (gst_structure_has_name (caps_s, "video/x-wmv")) {
2550 str = g_strdup_printf ("%" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (video->tag));
2551 gst_caps_set_simple (caps, "format", G_TYPE_STRING, str, NULL);
2554 /* check if h264 has codec_data (avc) or streamheaders (bytestream) */
2555 } else if (gst_structure_has_name (caps_s, "video/x-h264")) {
2556 const GValue *value = gst_structure_get_value (caps_s, "codec_data");
2557 GstBuffer *buf = gst_value_get_buffer (value);
2560 if (gst_buffer_map (buf, &mapinfo, GST_MAP_READ)) {
2561 if (mapinfo.size >= 4 && GST_READ_UINT32_BE (mapinfo.data) == 1) {
2562 /* this looks like a bytestream start */
2563 streamheader = gst_buffer_ref (buf);
2564 gst_asf_demux_add_stream_headers_to_caps (demux, buf, caps_s);
2565 gst_structure_remove_field (caps_s, "codec_data");
2568 gst_buffer_unmap (buf, &mapinfo);
2573 tags = gst_tag_list_new (GST_TAG_VIDEO_CODEC, codec_name, NULL);
2574 g_free (codec_name);
2578 gst_buffer_unref (extradata);
2580 GST_INFO ("Adding video stream #%u, id %u, codec %"
2581 GST_FOURCC_FORMAT " (0x%08x)", demux->num_video_streams, id,
2582 GST_FOURCC_ARGS (video->tag), video->tag);
2584 ++demux->num_video_streams;
2586 return gst_asf_demux_setup_pad (demux, src_pad, caps, id, TRUE,
2587 streamheader, tags);
2591 gst_asf_demux_activate_stream (GstASFDemux * demux, AsfStream * stream)
2593 if (!stream->active) {
2597 GST_INFO_OBJECT (demux, "Activating stream %2u, pad %s, caps %"
2598 GST_PTR_FORMAT, stream->id, GST_PAD_NAME (stream->pad), stream->caps);
2599 gst_pad_set_active (stream->pad, TRUE);
2602 gst_pad_create_stream_id_printf (stream->pad, GST_ELEMENT_CAST (demux),
2603 "%03u", stream->id);
2606 gst_pad_get_sticky_event (demux->sinkpad, GST_EVENT_STREAM_START, 0);
2608 if (gst_event_parse_group_id (event, &demux->group_id))
2609 demux->have_group_id = TRUE;
2611 demux->have_group_id = FALSE;
2612 gst_event_unref (event);
2613 } else if (!demux->have_group_id) {
2614 demux->have_group_id = TRUE;
2615 demux->group_id = gst_util_group_id_next ();
2618 event = gst_event_new_stream_start (stream_id);
2619 if (demux->have_group_id)
2620 gst_event_set_group_id (event, demux->group_id);
2622 gst_pad_push_event (stream->pad, event);
2624 gst_pad_set_caps (stream->pad, stream->caps);
2626 gst_element_add_pad (GST_ELEMENT_CAST (demux), stream->pad);
2627 gst_flow_combiner_add_pad (demux->flowcombiner, stream->pad);
2628 stream->active = TRUE;
2633 gst_asf_demux_parse_stream_object (GstASFDemux * demux, guint8 * data,
2636 AsfCorrectionType correction_type;
2637 AsfStreamType stream_type;
2638 GstClockTime time_offset;
2639 gboolean is_encrypted G_GNUC_UNUSED;
2643 guint stream_specific_size;
2644 guint type_specific_size G_GNUC_UNUSED;
2645 guint unknown G_GNUC_UNUSED;
2646 gboolean inspect_payload = FALSE;
2647 AsfStream *stream = NULL;
2649 /* Get the rest of the header's header */
2650 if (size < (16 + 16 + 8 + 4 + 4 + 2 + 4))
2651 goto not_enough_data;
2653 gst_asf_demux_get_guid (&guid, &data, &size);
2654 stream_type = gst_asf_demux_identify_guid (asf_stream_guids, &guid);
2656 gst_asf_demux_get_guid (&guid, &data, &size);
2657 correction_type = gst_asf_demux_identify_guid (asf_correction_guids, &guid);
2659 time_offset = gst_asf_demux_get_uint64 (&data, &size) * 100;
2661 type_specific_size = gst_asf_demux_get_uint32 (&data, &size);
2662 stream_specific_size = gst_asf_demux_get_uint32 (&data, &size);
2664 flags = gst_asf_demux_get_uint16 (&data, &size);
2665 stream_id = flags & 0x7f;
2666 is_encrypted = ! !((flags & 0x8000) << 15);
2667 unknown = gst_asf_demux_get_uint32 (&data, &size);
2669 GST_DEBUG_OBJECT (demux, "Found stream %u, time_offset=%" GST_TIME_FORMAT,
2670 stream_id, GST_TIME_ARGS (time_offset));
2672 /* dvr-ms has audio stream declared in stream specific data */
2673 if (stream_type == ASF_STREAM_EXT_EMBED_HEADER) {
2674 AsfExtStreamType ext_stream_type;
2675 gst_asf_demux_get_guid (&guid, &data, &size);
2676 ext_stream_type = gst_asf_demux_identify_guid (asf_ext_stream_guids, &guid);
2678 if (ext_stream_type == ASF_EXT_STREAM_AUDIO) {
2679 inspect_payload = TRUE;
2681 gst_asf_demux_get_guid (&guid, &data, &size);
2682 gst_asf_demux_get_uint32 (&data, &size);
2683 gst_asf_demux_get_uint32 (&data, &size);
2684 gst_asf_demux_get_uint32 (&data, &size);
2685 gst_asf_demux_get_guid (&guid, &data, &size);
2686 gst_asf_demux_get_uint32 (&data, &size);
2687 stream_type = ASF_STREAM_AUDIO;
2691 switch (stream_type) {
2692 case ASF_STREAM_AUDIO:{
2693 asf_stream_audio audio_object;
2695 if (!gst_asf_demux_get_stream_audio (&audio_object, &data, &size))
2696 goto not_enough_data;
2698 GST_INFO ("Object is an audio stream with %u bytes of additional data",
2701 stream = gst_asf_demux_add_audio_stream (demux, &audio_object, stream_id,
2704 switch (correction_type) {
2705 case ASF_CORRECTION_ON:{
2706 guint span, packet_size, chunk_size, data_size, silence_data;
2708 GST_INFO ("Using error correction");
2710 if (size < (1 + 2 + 2 + 2 + 1))
2711 goto not_enough_data;
2713 span = gst_asf_demux_get_uint8 (&data, &size);
2714 packet_size = gst_asf_demux_get_uint16 (&data, &size);
2715 chunk_size = gst_asf_demux_get_uint16 (&data, &size);
2716 data_size = gst_asf_demux_get_uint16 (&data, &size);
2717 silence_data = gst_asf_demux_get_uint8 (&data, &size);
2719 stream->span = span;
2721 GST_DEBUG_OBJECT (demux, "Descrambling ps:%u cs:%u ds:%u s:%u sd:%u",
2722 packet_size, chunk_size, data_size, span, silence_data);
2724 if (stream->span > 1) {
2725 if (chunk_size == 0 || ((packet_size / chunk_size) <= 1)) {
2726 /* Disable descrambling */
2729 /* FIXME: this else branch was added for
2730 * weird_al_yankovic - the saga begins.asf */
2731 stream->ds_packet_size = packet_size;
2732 stream->ds_chunk_size = chunk_size;
2735 /* Descambling is enabled */
2736 stream->ds_packet_size = packet_size;
2737 stream->ds_chunk_size = chunk_size;
2740 /* Now skip the rest of the silence data */
2742 gst_bytestream_flush (demux->bs, data_size - 1);
2744 /* FIXME: CHECKME. And why -1? */
2745 if (data_size > 1) {
2746 if (!gst_asf_demux_skip_bytes (data_size - 1, &data, &size)) {
2747 goto not_enough_data;
2753 case ASF_CORRECTION_OFF:{
2754 GST_INFO ("Error correction off");
2755 if (!gst_asf_demux_skip_bytes (stream_specific_size, &data, &size))
2756 goto not_enough_data;
2760 GST_ELEMENT_ERROR (demux, STREAM, DEMUX, (NULL),
2761 ("Audio stream using unknown error correction"));
2768 case ASF_STREAM_VIDEO:{
2769 asf_stream_video_format video_format_object;
2770 asf_stream_video video_object;
2773 if (!gst_asf_demux_get_stream_video (&video_object, &data, &size))
2774 goto not_enough_data;
2776 vsize = video_object.size - 40; /* Byte order gets offset by single byte */
2778 GST_INFO ("object is a video stream with %u bytes of "
2779 "additional data", vsize);
2781 if (!gst_asf_demux_get_stream_video_format (&video_format_object,
2783 goto not_enough_data;
2786 stream = gst_asf_demux_add_video_stream (demux, &video_format_object,
2787 stream_id, &data, &size);
2793 GST_WARNING_OBJECT (demux, "Unknown stream type for stream %u",
2795 demux->other_streams =
2796 g_slist_append (demux->other_streams, GINT_TO_POINTER (stream_id));
2801 stream->inspect_payload = inspect_payload;
2806 GST_WARNING_OBJECT (demux, "Unexpected end of data parsing stream object");
2807 /* we'll error out later if we found no streams */
2812 static const gchar *
2813 gst_asf_demux_get_gst_tag_from_tag_name (const gchar * name_utf8)
2817 const gchar *asf_name;
2818 const gchar *gst_name;
2821 "WM/Genre", GST_TAG_GENRE}, {
2822 "WM/AlbumTitle", GST_TAG_ALBUM}, {
2823 "WM/AlbumArtist", GST_TAG_ARTIST}, {
2824 "WM/Picture", GST_TAG_IMAGE}, {
2825 "WM/Track", GST_TAG_TRACK_NUMBER}, {
2826 "WM/TrackNumber", GST_TAG_TRACK_NUMBER}, {
2827 "WM/Year", GST_TAG_DATE_TIME}
2828 /* { "WM/Composer", GST_TAG_COMPOSER } */
2833 if (name_utf8 == NULL) {
2834 GST_WARNING ("Failed to convert name to UTF8, skipping");
2838 out = strlen (name_utf8);
2840 for (i = 0; i < G_N_ELEMENTS (tags); ++i) {
2841 if (strncmp (tags[i].asf_name, name_utf8, out) == 0) {
2842 GST_LOG ("map tagname '%s' -> '%s'", name_utf8, tags[i].gst_name);
2843 return tags[i].gst_name;
2850 /* gst_asf_demux_add_global_tags() takes ownership of taglist! */
2852 gst_asf_demux_add_global_tags (GstASFDemux * demux, GstTagList * taglist)
2856 GST_DEBUG_OBJECT (demux, "adding global tags: %" GST_PTR_FORMAT, taglist);
2858 if (taglist == NULL)
2861 if (gst_tag_list_is_empty (taglist)) {
2862 gst_tag_list_unref (taglist);
2866 t = gst_tag_list_merge (demux->taglist, taglist, GST_TAG_MERGE_APPEND);
2867 gst_tag_list_set_scope (t, GST_TAG_SCOPE_GLOBAL);
2869 gst_tag_list_unref (demux->taglist);
2870 gst_tag_list_unref (taglist);
2872 GST_LOG_OBJECT (demux, "global tags now: %" GST_PTR_FORMAT, demux->taglist);
2875 #define ASF_DEMUX_DATA_TYPE_UTF16LE_STRING 0
2876 #define ASF_DEMUX_DATA_TYPE_BYTE_ARRAY 1
2877 #define ASF_DEMUX_DATA_TYPE_DWORD 3
2880 asf_demux_parse_picture_tag (GstTagList * tags, const guint8 * tag_data,
2884 const guint8 *img_data = NULL;
2885 guint32 img_data_len = 0;
2886 guint8 pic_type = 0;
2888 gst_byte_reader_init (&r, tag_data, tag_data_len);
2890 /* skip mime type string (we don't trust it and do our own typefinding),
2891 * and also skip the description string, since we don't use it */
2892 if (!gst_byte_reader_get_uint8 (&r, &pic_type) ||
2893 !gst_byte_reader_get_uint32_le (&r, &img_data_len) ||
2894 !gst_byte_reader_skip_string_utf16 (&r) ||
2895 !gst_byte_reader_skip_string_utf16 (&r) ||
2896 !gst_byte_reader_get_data (&r, img_data_len, &img_data)) {
2897 goto not_enough_data;
2901 if (!gst_tag_list_add_id3_image (tags, img_data, img_data_len, pic_type))
2902 GST_DEBUG ("failed to add image extracted from WM/Picture tag to taglist");
2908 GST_DEBUG ("Failed to read WM/Picture tag: not enough data");
2909 GST_MEMDUMP ("WM/Picture data", tag_data, tag_data_len);
2914 /* Extended Content Description Object */
2915 static GstFlowReturn
2916 gst_asf_demux_process_ext_content_desc (GstASFDemux * demux, guint8 * data,
2919 /* Other known (and unused) 'text/unicode' metadata available :
2922 * WM/MediaPrimaryClassID = {D1607DBC-E323-4BE2-86A1-48A42A28441E}
2923 * WMFSDKVersion = 9.00.00.2980
2924 * WMFSDKNeeded = 0.0.0.0000
2925 * WM/UniqueFileIdentifier = AMGa_id=R 15334;AMGp_id=P 5149;AMGt_id=T 2324984
2926 * WM/Publisher = 4AD
2928 * WM/ProviderRating = 8
2929 * WM/ProviderStyle = Rock (similar to WM/Genre)
2930 * WM/GenreID (similar to WM/Genre)
2931 * WM/TrackNumber (same as WM/Track but as a string)
2933 * Other known (and unused) 'non-text' metadata available :
2939 * We might want to read WM/TrackNumber and use atoi() if we don't have
2943 GstTagList *taglist;
2944 guint16 blockcount, i;
2946 GST_INFO_OBJECT (demux, "object is an extended content description");
2948 taglist = gst_tag_list_new_empty ();
2950 /* Content Descriptor Count */
2952 goto not_enough_data;
2954 blockcount = gst_asf_demux_get_uint16 (&data, &size);
2956 for (i = 1; i <= blockcount; ++i) {
2957 const gchar *gst_tag_name;
2961 GValue tag_value = { 0, };
2964 gchar *name_utf8 = NULL;
2968 if (!gst_asf_demux_get_string (&name, &name_len, &data, &size))
2969 goto not_enough_data;
2973 goto not_enough_data;
2975 /* Descriptor Value Data Type */
2976 datatype = gst_asf_demux_get_uint16 (&data, &size);
2978 /* Descriptor Value (not really a string, but same thing reading-wise) */
2979 if (!gst_asf_demux_get_string (&value, &value_len, &data, &size)) {
2981 goto not_enough_data;
2985 g_convert (name, name_len, "UTF-8", "UTF-16LE", &in, &out, NULL);
2987 if (name_utf8 != NULL) {
2988 GST_DEBUG ("Found tag/metadata %s", name_utf8);
2990 gst_tag_name = gst_asf_demux_get_gst_tag_from_tag_name (name_utf8);
2991 GST_DEBUG ("gst_tag_name %s", GST_STR_NULL (gst_tag_name));
2994 case ASF_DEMUX_DATA_TYPE_UTF16LE_STRING:{
2997 value_utf8 = g_convert (value, value_len, "UTF-8", "UTF-16LE",
3000 /* get rid of tags with empty value */
3001 if (value_utf8 != NULL && *value_utf8 != '\0') {
3002 GST_DEBUG ("string value %s", value_utf8);
3004 value_utf8[out] = '\0';
3006 if (gst_tag_name != NULL) {
3007 if (strcmp (gst_tag_name, GST_TAG_DATE_TIME) == 0) {
3008 guint year = atoi (value_utf8);
3011 g_value_init (&tag_value, GST_TYPE_DATE_TIME);
3012 g_value_take_boxed (&tag_value, gst_date_time_new_y (year));
3014 } else if (strcmp (gst_tag_name, GST_TAG_GENRE) == 0) {
3015 guint id3v1_genre_id;
3016 const gchar *genre_str;
3018 if (sscanf (value_utf8, "(%u)", &id3v1_genre_id) == 1 &&
3019 ((genre_str = gst_tag_id3_genre_get (id3v1_genre_id)))) {
3020 GST_DEBUG ("Genre: %s -> %s", value_utf8, genre_str);
3021 g_free (value_utf8);
3022 value_utf8 = g_strdup (genre_str);
3027 /* convert tag from string to other type if required */
3028 tag_type = gst_tag_get_type (gst_tag_name);
3029 g_value_init (&tag_value, tag_type);
3030 if (!gst_value_deserialize (&tag_value, value_utf8)) {
3031 GValue from_val = { 0, };
3033 g_value_init (&from_val, G_TYPE_STRING);
3034 g_value_set_string (&from_val, value_utf8);
3035 if (!g_value_transform (&from_val, &tag_value)) {
3036 GST_WARNING_OBJECT (demux,
3037 "Could not transform string tag to " "%s tag type %s",
3038 gst_tag_name, g_type_name (tag_type));
3039 g_value_unset (&tag_value);
3041 g_value_unset (&from_val);
3046 GST_DEBUG ("Setting metadata");
3047 g_value_init (&tag_value, G_TYPE_STRING);
3048 g_value_set_string (&tag_value, value_utf8);
3050 } else if (value_utf8 == NULL) {
3051 GST_WARNING ("Failed to convert string value to UTF8, skipping");
3053 GST_DEBUG ("Skipping empty string value for %s",
3054 GST_STR_NULL (gst_tag_name));
3056 g_free (value_utf8);
3059 case ASF_DEMUX_DATA_TYPE_BYTE_ARRAY:{
3061 if (!g_str_equal (gst_tag_name, GST_TAG_IMAGE)) {
3062 GST_FIXME ("Unhandled byte array tag %s",
3063 GST_STR_NULL (gst_tag_name));
3066 asf_demux_parse_picture_tag (taglist, (guint8 *) value,
3072 case ASF_DEMUX_DATA_TYPE_DWORD:{
3073 guint uint_val = GST_READ_UINT32_LE (value);
3075 /* this is the track number */
3076 g_value_init (&tag_value, G_TYPE_UINT);
3078 /* WM/Track counts from 0 */
3079 if (!strcmp (name_utf8, "WM/Track"))
3082 g_value_set_uint (&tag_value, uint_val);
3086 GST_DEBUG ("Skipping tag %s of type %d", gst_tag_name, datatype);
3091 if (G_IS_VALUE (&tag_value)) {
3093 GstTagMergeMode merge_mode = GST_TAG_MERGE_APPEND;
3095 /* WM/TrackNumber is more reliable than WM/Track, since the latter
3096 * is supposed to have a 0 base but is often wrongly written to start
3097 * from 1 as well, so prefer WM/TrackNumber when we have it: either
3098 * replace the value added earlier from WM/Track or put it first in
3099 * the list, so that it will get picked up by _get_uint() */
3100 if (strcmp (name_utf8, "WM/TrackNumber") == 0)
3101 merge_mode = GST_TAG_MERGE_REPLACE;
3103 gst_tag_list_add_values (taglist, merge_mode, gst_tag_name,
3106 GST_DEBUG ("Setting global metadata %s", name_utf8);
3107 gst_structure_set_value (demux->global_metadata, name_utf8,
3111 g_value_unset (&tag_value);
3120 gst_asf_demux_add_global_tags (demux, taglist);
3127 GST_WARNING ("Unexpected end of data parsing ext content desc object");
3128 gst_tag_list_unref (taglist);
3129 return GST_FLOW_OK; /* not really fatal */
3133 static GstStructure *
3134 gst_asf_demux_get_metadata_for_stream (GstASFDemux * demux, guint stream_num)
3139 g_snprintf (sname, sizeof (sname), "stream-%u", stream_num);
3141 for (i = 0; i < gst_caps_get_size (demux->metadata); ++i) {
3144 s = gst_caps_get_structure (demux->metadata, i);
3145 if (gst_structure_has_name (s, sname))
3149 gst_caps_append_structure (demux->metadata, gst_structure_new_empty (sname));
3151 /* try lookup again; demux->metadata took ownership of the structure, so we
3152 * can't really make any assumptions about what happened to it, so we can't
3153 * just return it directly after appending it */
3154 return gst_asf_demux_get_metadata_for_stream (demux, stream_num);
3157 static GstFlowReturn
3158 gst_asf_demux_process_metadata (GstASFDemux * demux, guint8 * data,
3161 guint16 blockcount, i;
3163 GST_INFO_OBJECT (demux, "object is a metadata object");
3165 /* Content Descriptor Count */
3167 goto not_enough_data;
3169 blockcount = gst_asf_demux_get_uint16 (&data, &size);
3171 for (i = 0; i < blockcount; ++i) {
3173 guint16 stream_num, name_len, data_type, lang_idx G_GNUC_UNUSED;
3174 guint32 data_len, ival;
3177 if (size < (2 + 2 + 2 + 2 + 4))
3178 goto not_enough_data;
3180 lang_idx = gst_asf_demux_get_uint16 (&data, &size);
3181 stream_num = gst_asf_demux_get_uint16 (&data, &size);
3182 name_len = gst_asf_demux_get_uint16 (&data, &size);
3183 data_type = gst_asf_demux_get_uint16 (&data, &size);
3184 data_len = gst_asf_demux_get_uint32 (&data, &size);
3186 if (size < name_len + data_len)
3187 goto not_enough_data;
3189 /* convert name to UTF-8 */
3190 name_utf8 = g_convert ((gchar *) data, name_len, "UTF-8", "UTF-16LE",
3192 gst_asf_demux_skip_bytes (name_len, &data, &size);
3194 if (name_utf8 == NULL) {
3195 GST_WARNING ("Failed to convert value name to UTF8, skipping");
3196 gst_asf_demux_skip_bytes (data_len, &data, &size);
3200 if (data_type != ASF_DEMUX_DATA_TYPE_DWORD) {
3201 gst_asf_demux_skip_bytes (data_len, &data, &size);
3209 goto not_enough_data;
3212 ival = gst_asf_demux_get_uint32 (&data, &size);
3214 /* skip anything else there may be, just in case */
3215 gst_asf_demux_skip_bytes (data_len - 4, &data, &size);
3217 s = gst_asf_demux_get_metadata_for_stream (demux, stream_num);
3218 gst_structure_set (s, name_utf8, G_TYPE_INT, ival, NULL);
3222 GST_INFO_OBJECT (demux, "metadata = %" GST_PTR_FORMAT, demux->metadata);
3228 GST_WARNING ("Unexpected end of data parsing metadata object");
3229 return GST_FLOW_OK; /* not really fatal */
3233 static GstFlowReturn
3234 gst_asf_demux_process_header (GstASFDemux * demux, guint8 * data, guint64 size)
3236 GstFlowReturn ret = GST_FLOW_OK;
3237 guint32 i, num_objects;
3238 guint8 unknown G_GNUC_UNUSED;
3240 /* Get the rest of the header's header */
3241 if (size < (4 + 1 + 1))
3242 goto not_enough_data;
3244 num_objects = gst_asf_demux_get_uint32 (&data, &size);
3245 unknown = gst_asf_demux_get_uint8 (&data, &size);
3246 unknown = gst_asf_demux_get_uint8 (&data, &size);
3248 GST_INFO_OBJECT (demux, "object is a header with %u parts", num_objects);
3250 /* Loop through the header's objects, processing those */
3251 for (i = 0; i < num_objects; ++i) {
3252 GST_INFO_OBJECT (demux, "reading header part %u", i);
3253 ret = gst_asf_demux_process_object (demux, &data, &size);
3254 if (ret != GST_FLOW_OK) {
3255 GST_WARNING ("process_object returned %s", gst_asf_get_flow_name (ret));
3264 GST_ELEMENT_ERROR (demux, STREAM, DEMUX, (NULL),
3265 ("short read parsing HEADER object"));
3266 return GST_FLOW_ERROR;
3270 static GstFlowReturn
3271 gst_asf_demux_process_file (GstASFDemux * demux, guint8 * data, guint64 size)
3273 guint64 creation_time G_GNUC_UNUSED;
3274 guint64 file_size G_GNUC_UNUSED;
3275 guint64 send_time G_GNUC_UNUSED;
3276 guint64 packets_count, play_time, preroll;
3277 guint32 flags, min_pktsize, max_pktsize, min_bitrate G_GNUC_UNUSED;
3279 if (size < (16 + 8 + 8 + 8 + 8 + 8 + 8 + 4 + 4 + 4 + 4))
3280 goto not_enough_data;
3282 gst_asf_demux_skip_bytes (16, &data, &size); /* skip GUID */
3283 file_size = gst_asf_demux_get_uint64 (&data, &size);
3284 creation_time = gst_asf_demux_get_uint64 (&data, &size);
3285 packets_count = gst_asf_demux_get_uint64 (&data, &size);
3286 play_time = gst_asf_demux_get_uint64 (&data, &size);
3287 send_time = gst_asf_demux_get_uint64 (&data, &size);
3288 preroll = gst_asf_demux_get_uint64 (&data, &size);
3289 flags = gst_asf_demux_get_uint32 (&data, &size);
3290 min_pktsize = gst_asf_demux_get_uint32 (&data, &size);
3291 max_pktsize = gst_asf_demux_get_uint32 (&data, &size);
3292 min_bitrate = gst_asf_demux_get_uint32 (&data, &size);
3294 demux->broadcast = ! !(flags & 0x01);
3295 demux->seekable = ! !(flags & 0x02);
3297 GST_DEBUG_OBJECT (demux, "min_pktsize = %u", min_pktsize);
3298 GST_DEBUG_OBJECT (demux, "flags::broadcast = %d", demux->broadcast);
3299 GST_DEBUG_OBJECT (demux, "flags::seekable = %d", demux->seekable);
3301 if (demux->broadcast) {
3302 /* these fields are invalid if the broadcast flag is set */
3307 if (min_pktsize != max_pktsize)
3308 goto non_fixed_packet_size;
3310 demux->packet_size = max_pktsize;
3312 /* FIXME: do we need send_time as well? what is it? */
3313 if ((play_time * 100) >= (preroll * GST_MSECOND))
3314 demux->play_time = (play_time * 100) - (preroll * GST_MSECOND);
3316 demux->play_time = 0;
3318 demux->preroll = preroll * GST_MSECOND;
3320 /* initial latency */
3321 demux->latency = demux->preroll;
3323 if (demux->play_time == 0)
3324 demux->seekable = FALSE;
3326 GST_DEBUG_OBJECT (demux, "play_time %" GST_TIME_FORMAT,
3327 GST_TIME_ARGS (demux->play_time));
3328 GST_DEBUG_OBJECT (demux, "preroll %" GST_TIME_FORMAT,
3329 GST_TIME_ARGS (demux->preroll));
3331 if (demux->play_time > 0) {
3332 demux->segment.duration = demux->play_time;
3335 GST_INFO ("object is a file with %" G_GUINT64_FORMAT " data packets",
3337 GST_INFO ("preroll = %" G_GUINT64_FORMAT, demux->preroll);
3342 non_fixed_packet_size:
3344 GST_ELEMENT_ERROR (demux, STREAM, DEMUX, (NULL),
3345 ("packet size must be fixed"));
3346 return GST_FLOW_ERROR;
3350 GST_ELEMENT_ERROR (demux, STREAM, DEMUX, (NULL),
3351 ("short read parsing FILE object"));
3352 return GST_FLOW_ERROR;
3356 /* Content Description Object */
3357 static GstFlowReturn
3358 gst_asf_demux_process_comment (GstASFDemux * demux, guint8 * data, guint64 size)
3362 const gchar *gst_tag;
3367 GST_TAG_TITLE, 0, NULL}, {
3368 GST_TAG_ARTIST, 0, NULL}, {
3369 GST_TAG_COPYRIGHT, 0, NULL}, {
3370 GST_TAG_DESCRIPTION, 0, NULL}, {
3371 GST_TAG_COMMENT, 0, NULL}
3373 GstTagList *taglist;
3374 GValue value = { 0 };
3378 GST_INFO_OBJECT (demux, "object is a comment");
3380 if (size < (2 + 2 + 2 + 2 + 2))
3381 goto not_enough_data;
3383 tags[0].val_length = gst_asf_demux_get_uint16 (&data, &size);
3384 tags[1].val_length = gst_asf_demux_get_uint16 (&data, &size);
3385 tags[2].val_length = gst_asf_demux_get_uint16 (&data, &size);
3386 tags[3].val_length = gst_asf_demux_get_uint16 (&data, &size);
3387 tags[4].val_length = gst_asf_demux_get_uint16 (&data, &size);
3389 GST_DEBUG_OBJECT (demux, "Comment lengths: title=%d author=%d copyright=%d "
3390 "description=%d rating=%d", tags[0].val_length, tags[1].val_length,
3391 tags[2].val_length, tags[3].val_length, tags[4].val_length);
3393 for (i = 0; i < G_N_ELEMENTS (tags); ++i) {
3394 if (size < tags[i].val_length)
3395 goto not_enough_data;
3397 /* might be just '/0', '/0'... */
3398 if (tags[i].val_length > 2 && tags[i].val_length % 2 == 0) {
3399 /* convert to UTF-8 */
3400 tags[i].val_utf8 = g_convert ((gchar *) data, tags[i].val_length,
3401 "UTF-8", "UTF-16LE", &in, &out, NULL);
3403 gst_asf_demux_skip_bytes (tags[i].val_length, &data, &size);
3406 /* parse metadata into taglist */
3407 taglist = gst_tag_list_new_empty ();
3408 g_value_init (&value, G_TYPE_STRING);
3409 for (i = 0; i < G_N_ELEMENTS (tags); ++i) {
3410 if (tags[i].val_utf8 && strlen (tags[i].val_utf8) > 0 && tags[i].gst_tag) {
3411 g_value_set_string (&value, tags[i].val_utf8);
3412 gst_tag_list_add_values (taglist, GST_TAG_MERGE_APPEND,
3413 tags[i].gst_tag, &value, NULL);
3416 g_value_unset (&value);
3418 gst_asf_demux_add_global_tags (demux, taglist);
3420 for (i = 0; i < G_N_ELEMENTS (tags); ++i)
3421 g_free (tags[i].val_utf8);
3427 GST_WARNING_OBJECT (demux, "unexpectedly short of data while processing "
3428 "comment tag section %d, skipping comment object", i);
3429 for (i = 0; i < G_N_ELEMENTS (tags); i++)
3430 g_free (tags[i].val_utf8);
3431 return GST_FLOW_OK; /* not really fatal */
3435 static GstFlowReturn
3436 gst_asf_demux_process_bitrate_props_object (GstASFDemux * demux, guint8 * data,
3439 guint16 num_streams, i;
3443 goto not_enough_data;
3445 num_streams = gst_asf_demux_get_uint16 (&data, &size);
3447 GST_INFO ("object is a bitrate properties object with %u streams",
3450 if (size < (num_streams * (2 + 4)))
3451 goto not_enough_data;
3453 for (i = 0; i < num_streams; ++i) {
3457 stream_id = gst_asf_demux_get_uint16 (&data, &size);
3458 bitrate = gst_asf_demux_get_uint32 (&data, &size);
3460 if (stream_id < GST_ASF_DEMUX_NUM_STREAM_IDS) {
3461 GST_DEBUG_OBJECT (demux, "bitrate of stream %u = %u", stream_id, bitrate);
3462 stream = gst_asf_demux_get_stream (demux, stream_id);
3464 if (stream->pending_tags == NULL) {
3465 stream->pending_tags =
3466 gst_tag_list_new (GST_TAG_BITRATE, bitrate, NULL);
3469 GST_WARNING_OBJECT (demux, "Stream id %u wasn't found", stream_id);
3472 GST_WARNING ("stream id %u is too large", stream_id);
3480 GST_WARNING_OBJECT (demux, "short read parsing bitrate props object!");
3481 return GST_FLOW_OK; /* not really fatal */
3485 static GstFlowReturn
3486 gst_asf_demux_process_header_ext (GstASFDemux * demux, guint8 * data,
3489 GstFlowReturn ret = GST_FLOW_OK;
3492 /* Get the rest of the header's header */
3493 if (size < (16 + 2 + 4))
3494 goto not_enough_data;
3496 /* skip GUID and two other bytes */
3497 gst_asf_demux_skip_bytes (16 + 2, &data, &size);
3498 hdr_size = gst_asf_demux_get_uint32 (&data, &size);
3500 GST_INFO ("extended header object with a size of %u bytes", (guint) size);
3502 /* FIXME: does data_size include the rest of the header that we have read? */
3503 if (hdr_size > size)
3504 goto not_enough_data;
3506 while (hdr_size > 0) {
3507 ret = gst_asf_demux_process_object (demux, &data, &hdr_size);
3508 if (ret != GST_FLOW_OK)
3516 GST_ELEMENT_ERROR (demux, STREAM, DEMUX, (NULL),
3517 ("short read parsing extended header object"));
3518 return GST_FLOW_ERROR;
3522 static GstFlowReturn
3523 gst_asf_demux_process_language_list (GstASFDemux * demux, guint8 * data,
3529 goto not_enough_data;
3531 if (demux->languages) {
3532 GST_WARNING ("More than one LANGUAGE_LIST object in stream");
3533 g_strfreev (demux->languages);
3534 demux->languages = NULL;
3535 demux->num_languages = 0;
3538 demux->num_languages = gst_asf_demux_get_uint16 (&data, &size);
3539 GST_LOG ("%u languages:", demux->num_languages);
3541 demux->languages = g_new0 (gchar *, demux->num_languages + 1);
3542 for (i = 0; i < demux->num_languages; ++i) {
3543 guint8 len, *lang_data = NULL;
3546 goto not_enough_data;
3547 len = gst_asf_demux_get_uint8 (&data, &size);
3548 if (gst_asf_demux_get_bytes (&lang_data, len, &data, &size)) {
3551 utf8 = g_convert ((gchar *) lang_data, len, "UTF-8", "UTF-16LE", NULL,
3554 /* truncate "en-us" etc. to just "en" */
3555 if (utf8 && strlen (utf8) >= 5 && (utf8[2] == '-' || utf8[2] == '_')) {
3558 GST_DEBUG ("[%u] %s", i, GST_STR_NULL (utf8));
3559 demux->languages[i] = utf8;
3562 goto not_enough_data;
3570 GST_WARNING_OBJECT (demux, "short read parsing language list object!");
3571 g_free (demux->languages);
3572 demux->languages = NULL;
3573 return GST_FLOW_OK; /* not fatal */
3577 static GstFlowReturn
3578 gst_asf_demux_process_simple_index (GstASFDemux * demux, guint8 * data,
3581 GstClockTime interval;
3584 if (size < (16 + 8 + 4 + 4))
3585 goto not_enough_data;
3588 gst_asf_demux_skip_bytes (16, &data, &size);
3589 interval = gst_asf_demux_get_uint64 (&data, &size) * (GstClockTime) 100;
3590 gst_asf_demux_skip_bytes (4, &data, &size);
3591 count = gst_asf_demux_get_uint32 (&data, &size);
3593 demux->sidx_interval = interval;
3594 demux->sidx_num_entries = count;
3595 g_free (demux->sidx_entries);
3596 demux->sidx_entries = g_new0 (AsfSimpleIndexEntry, count);
3598 for (i = 0; i < count; ++i) {
3599 if (G_UNLIKELY (size < 6)) {
3600 /* adjust for broken files, to avoid having entries at the end
3601 * of the parsed index that point to time=0. Resulting in seeking to
3602 * the end of the file leading back to the beginning */
3603 demux->sidx_num_entries -= (count - i);
3606 demux->sidx_entries[i].packet = gst_asf_demux_get_uint32 (&data, &size);
3607 demux->sidx_entries[i].count = gst_asf_demux_get_uint16 (&data, &size);
3608 GST_LOG_OBJECT (demux, "%" GST_TIME_FORMAT " = packet %4u count : %2d",
3609 GST_TIME_ARGS (i * interval), demux->sidx_entries[i].packet,
3610 demux->sidx_entries[i].count);
3613 GST_DEBUG_OBJECT (demux, "simple index object with 0 entries");
3620 GST_WARNING_OBJECT (demux, "short read parsing simple index object!");
3621 return GST_FLOW_OK; /* not fatal */
3625 static GstFlowReturn
3626 gst_asf_demux_process_advanced_mutual_exclusion (GstASFDemux * demux,
3627 guint8 * data, guint64 size)
3633 if (size < 16 + 2 + (2 * 2))
3634 goto not_enough_data;
3636 gst_asf_demux_get_guid (&guid, &data, &size);
3637 num = gst_asf_demux_get_uint16 (&data, &size);
3640 GST_WARNING_OBJECT (demux, "nonsensical mutually exclusive streams count");
3644 if (size < (num * sizeof (guint16)))
3645 goto not_enough_data;
3647 /* read mutually exclusive stream numbers */
3648 mes = g_new (guint8, num + 1);
3649 for (i = 0; i < num; ++i) {
3650 mes[i] = gst_asf_demux_get_uint16 (&data, &size) & 0x7f;
3651 GST_LOG_OBJECT (demux, "mutually exclusive: stream #%d", mes[i]);
3654 /* add terminator so we can easily get the count or know when to stop */
3655 mes[i] = (guint8) - 1;
3657 demux->mut_ex_streams = g_slist_append (demux->mut_ex_streams, mes);
3664 GST_WARNING_OBJECT (demux, "short read parsing advanced mutual exclusion");
3665 return GST_FLOW_OK; /* not absolutely fatal */
3670 gst_asf_demux_is_unknown_stream (GstASFDemux * demux, guint stream_num)
3672 return g_slist_find (demux->other_streams,
3673 GINT_TO_POINTER (stream_num)) == NULL;
3676 static GstFlowReturn
3677 gst_asf_demux_process_ext_stream_props (GstASFDemux * demux, guint8 * data,
3680 AsfStreamExtProps esp;
3681 AsfStream *stream = NULL;
3682 AsfObject stream_obj;
3683 guint16 stream_name_count;
3684 guint16 num_payload_ext;
3686 guint8 *stream_obj_data = NULL;
3689 guint i, stream_num;
3692 obj_size = (guint) size;
3695 goto not_enough_data;
3698 esp.start_time = gst_asf_demux_get_uint64 (&data, &size) * GST_MSECOND;
3699 esp.end_time = gst_asf_demux_get_uint64 (&data, &size) * GST_MSECOND;
3700 esp.data_bitrate = gst_asf_demux_get_uint32 (&data, &size);
3701 esp.buffer_size = gst_asf_demux_get_uint32 (&data, &size);
3702 esp.intial_buf_fullness = gst_asf_demux_get_uint32 (&data, &size);
3703 esp.data_bitrate2 = gst_asf_demux_get_uint32 (&data, &size);
3704 esp.buffer_size2 = gst_asf_demux_get_uint32 (&data, &size);
3705 esp.intial_buf_fullness2 = gst_asf_demux_get_uint32 (&data, &size);
3706 esp.max_obj_size = gst_asf_demux_get_uint32 (&data, &size);
3707 esp.flags = gst_asf_demux_get_uint32 (&data, &size);
3708 stream_num = gst_asf_demux_get_uint16 (&data, &size);
3709 esp.lang_idx = gst_asf_demux_get_uint16 (&data, &size);
3710 esp.avg_time_per_frame = gst_asf_demux_get_uint64 (&data, &size);
3711 stream_name_count = gst_asf_demux_get_uint16 (&data, &size);
3712 num_payload_ext = gst_asf_demux_get_uint16 (&data, &size);
3714 GST_INFO ("start_time = %" GST_TIME_FORMAT,
3715 GST_TIME_ARGS (esp.start_time));
3716 GST_INFO ("end_time = %" GST_TIME_FORMAT,
3717 GST_TIME_ARGS (esp.end_time));
3718 GST_INFO ("flags = %08x", esp.flags);
3719 GST_INFO ("average time per frame = %" GST_TIME_FORMAT,
3720 GST_TIME_ARGS (esp.avg_time_per_frame * 100));
3721 GST_INFO ("stream number = %u", stream_num);
3722 GST_INFO ("stream language ID idx = %u (%s)", esp.lang_idx,
3723 (esp.lang_idx < demux->num_languages) ?
3724 GST_STR_NULL (demux->languages[esp.lang_idx]) : "??");
3725 GST_INFO ("stream name count = %u", stream_name_count);
3727 /* read stream names */
3728 for (i = 0; i < stream_name_count; ++i) {
3729 guint16 stream_lang_idx G_GNUC_UNUSED;
3730 gchar *stream_name = NULL;
3733 goto not_enough_data;
3734 stream_lang_idx = gst_asf_demux_get_uint16 (&data, &size);
3735 if (!gst_asf_demux_get_string (&stream_name, NULL, &data, &size))
3736 goto not_enough_data;
3737 GST_INFO ("stream name %d: %s", i, GST_STR_NULL (stream_name));
3738 g_free (stream_name); /* TODO: store names in struct */
3741 /* read payload extension systems stuff */
3742 GST_LOG ("payload extension systems count = %u", num_payload_ext);
3744 if (num_payload_ext > 0)
3745 esp.payload_extensions = g_new0 (AsfPayloadExtension, num_payload_ext + 1);
3747 esp.payload_extensions = NULL;
3749 for (i = 0; i < num_payload_ext; ++i) {
3750 AsfPayloadExtension ext;
3752 guint32 sys_info_len;
3754 if (size < 16 + 2 + 4)
3755 goto not_enough_data;
3757 gst_asf_demux_get_guid (&ext_guid, &data, &size);
3758 ext.id = gst_asf_demux_identify_guid (asf_payload_ext_guids, &ext_guid);
3759 ext.len = gst_asf_demux_get_uint16 (&data, &size);
3761 sys_info_len = gst_asf_demux_get_uint32 (&data, &size);
3762 GST_LOG ("payload systems info len = %u", sys_info_len);
3763 if (!gst_asf_demux_skip_bytes (sys_info_len, &data, &size))
3764 goto not_enough_data;
3766 esp.payload_extensions[i] = ext;
3769 GST_LOG ("bytes read: %u/%u", (guint) (data - data_start), obj_size);
3771 /* there might be an optional STREAM_INFO object here now; if not, we
3772 * should have parsed the corresponding stream info object already (since
3773 * we are parsing the extended stream properties objects delayed) */
3775 stream = gst_asf_demux_get_stream (demux, stream_num);
3779 /* get size of the stream object */
3780 if (!asf_demux_peek_object (demux, data, size, &stream_obj, TRUE))
3781 goto not_enough_data;
3783 if (stream_obj.id != ASF_OBJ_STREAM)
3784 goto expected_stream_object;
3786 if (stream_obj.size < ASF_OBJECT_HEADER_SIZE ||
3787 stream_obj.size > (10 * 1024 * 1024))
3788 goto not_enough_data;
3790 gst_asf_demux_skip_bytes (ASF_OBJECT_HEADER_SIZE, &data, &size);
3792 /* process this stream object later after all the other 'normal' ones
3793 * have been processed (since the others are more important/non-hidden) */
3794 len = stream_obj.size - ASF_OBJECT_HEADER_SIZE;
3795 if (!gst_asf_demux_get_bytes (&stream_obj_data, len, &data, &size))
3796 goto not_enough_data;
3798 /* parse stream object */
3799 stream = gst_asf_demux_parse_stream_object (demux, stream_obj_data, len);
3800 g_free (stream_obj_data);
3805 stream->ext_props = esp;
3807 /* try to set the framerate */
3808 if (stream->is_video && stream->caps) {
3809 GValue framerate = { 0 };
3813 g_value_init (&framerate, GST_TYPE_FRACTION);
3815 num = GST_SECOND / 100;
3816 denom = esp.avg_time_per_frame;
3818 /* avoid division by 0, assume 25/1 framerate */
3819 denom = GST_SECOND / 2500;
3822 gst_value_set_fraction (&framerate, num, denom);
3824 stream->caps = gst_caps_make_writable (stream->caps);
3825 s = gst_caps_get_structure (stream->caps, 0);
3826 gst_structure_set_value (s, "framerate", &framerate);
3827 g_value_unset (&framerate);
3828 GST_DEBUG_OBJECT (demux, "setting framerate of %d/%d = %f",
3829 num, denom, ((gdouble) num) / denom);
3832 /* add language info now if we have it */
3833 if (stream->ext_props.lang_idx < demux->num_languages) {
3834 if (stream->pending_tags == NULL)
3835 stream->pending_tags = gst_tag_list_new_empty ();
3836 GST_LOG_OBJECT (demux, "stream %u has language '%s'", stream->id,
3837 demux->languages[stream->ext_props.lang_idx]);
3838 gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_APPEND,
3839 GST_TAG_LANGUAGE_CODE, demux->languages[stream->ext_props.lang_idx],
3842 } else if (gst_asf_demux_is_unknown_stream (demux, stream_num)) {
3843 GST_WARNING_OBJECT (demux, "Ext. stream properties for unknown stream");
3851 GST_WARNING_OBJECT (demux, "short read parsing ext stream props object!");
3852 return GST_FLOW_OK; /* not absolutely fatal */
3854 expected_stream_object:
3856 GST_WARNING_OBJECT (demux, "error parsing extended stream properties "
3857 "object: expected embedded stream object, but got %s object instead!",
3858 gst_asf_get_guid_nick (asf_object_guids, stream_obj.id));
3859 return GST_FLOW_OK; /* not absolutely fatal */
3863 static const gchar *
3864 gst_asf_demux_push_obj (GstASFDemux * demux, guint32 obj_id)
3868 nick = gst_asf_get_guid_nick (asf_object_guids, obj_id);
3869 if (g_str_has_prefix (nick, "ASF_OBJ_"))
3870 nick += strlen ("ASF_OBJ_");
3872 if (demux->objpath == NULL) {
3873 demux->objpath = g_strdup (nick);
3877 newpath = g_strdup_printf ("%s/%s", demux->objpath, nick);
3878 g_free (demux->objpath);
3879 demux->objpath = newpath;
3882 return (const gchar *) demux->objpath;
3886 gst_asf_demux_pop_obj (GstASFDemux * demux)
3890 if ((s = g_strrstr (demux->objpath, "/"))) {
3893 g_free (demux->objpath);
3894 demux->objpath = NULL;
3899 gst_asf_demux_process_queued_extended_stream_objects (GstASFDemux * demux)
3904 /* Parse the queued extended stream property objects and add the info
3905 * to the existing streams or add the new embedded streams, but without
3906 * activating them yet */
3907 GST_LOG_OBJECT (demux, "%u queued extended stream properties objects",
3908 g_slist_length (demux->ext_stream_props));
3910 for (l = demux->ext_stream_props, i = 0; l != NULL; l = l->next, ++i) {
3911 GstBuffer *buf = GST_BUFFER (l->data);
3914 gst_buffer_map (buf, &map, GST_MAP_READ);
3916 GST_LOG_OBJECT (demux, "parsing ext. stream properties object #%u", i);
3917 gst_asf_demux_process_ext_stream_props (demux, map.data, map.size);
3918 gst_buffer_unmap (buf, &map);
3919 gst_buffer_unref (buf);
3921 g_slist_free (demux->ext_stream_props);
3922 demux->ext_stream_props = NULL;
3927 gst_asf_demux_activate_ext_props_streams (GstASFDemux * demux)
3931 for (i = 0; i < demux->num_streams; ++i) {
3936 stream = &demux->stream[i];
3938 GST_LOG_OBJECT (demux, "checking stream %2u", stream->id);
3940 if (stream->active) {
3941 GST_LOG_OBJECT (demux, "stream %2u is already activated", stream->id);
3946 for (x = demux->mut_ex_streams; x != NULL; x = x->next) {
3949 /* check for each mutual exclusion whether it affects this stream */
3950 for (mes = (guint8 *) x->data; mes != NULL && *mes != 0xff; ++mes) {
3951 if (*mes == stream->id) {
3952 /* if yes, check if we've already added streams that are mutually
3953 * exclusive with the stream we're about to add */
3954 for (mes = (guint8 *) x->data; mes != NULL && *mes != 0xff; ++mes) {
3955 for (j = 0; j < demux->num_streams; ++j) {
3956 /* if the broadcast flag is set, assume the hidden streams aren't
3957 * actually streamed and hide them (or playbin won't work right),
3958 * otherwise assume their data is available */
3959 if (demux->stream[j].id == *mes && demux->broadcast) {
3961 GST_LOG_OBJECT (demux, "broadcast stream ID %d to be added is "
3962 "mutually exclusive with already existing stream ID %d, "
3963 "hiding stream", stream->id, demux->stream[j].id);
3975 /* FIXME: we should do stream activation based on preroll data in
3976 * streaming mode too */
3977 if (demux->streaming && !is_hidden)
3978 gst_asf_demux_activate_stream (demux, stream);
3983 static GstFlowReturn
3984 gst_asf_demux_process_object (GstASFDemux * demux, guint8 ** p_data,
3987 GstFlowReturn ret = GST_FLOW_OK;
3989 guint64 obj_data_size;
3991 if (*p_size < ASF_OBJECT_HEADER_SIZE)
3992 return ASF_FLOW_NEED_MORE_DATA;
3994 asf_demux_peek_object (demux, *p_data, ASF_OBJECT_HEADER_SIZE, &obj, TRUE);
3995 gst_asf_demux_skip_bytes (ASF_OBJECT_HEADER_SIZE, p_data, p_size);
3997 obj_data_size = obj.size - ASF_OBJECT_HEADER_SIZE;
3999 if (*p_size < obj_data_size)
4000 return ASF_FLOW_NEED_MORE_DATA;
4002 gst_asf_demux_push_obj (demux, obj.id);
4004 GST_INFO ("%s: size %" G_GUINT64_FORMAT, demux->objpath, obj.size);
4007 case ASF_OBJ_STREAM:
4008 gst_asf_demux_parse_stream_object (demux, *p_data, obj_data_size);
4012 ret = gst_asf_demux_process_file (demux, *p_data, obj_data_size);
4014 case ASF_OBJ_HEADER:
4015 ret = gst_asf_demux_process_header (demux, *p_data, obj_data_size);
4017 case ASF_OBJ_COMMENT:
4018 ret = gst_asf_demux_process_comment (demux, *p_data, obj_data_size);
4021 ret = gst_asf_demux_process_header_ext (demux, *p_data, obj_data_size);
4023 case ASF_OBJ_BITRATE_PROPS:
4025 gst_asf_demux_process_bitrate_props_object (demux, *p_data,
4028 case ASF_OBJ_EXT_CONTENT_DESC:
4030 gst_asf_demux_process_ext_content_desc (demux, *p_data,
4033 case ASF_OBJ_METADATA_OBJECT:
4034 ret = gst_asf_demux_process_metadata (demux, *p_data, obj_data_size);
4036 case ASF_OBJ_EXTENDED_STREAM_PROPS:{
4039 /* process these later, we might not have parsed the corresponding
4040 * stream object yet */
4041 GST_LOG ("%s: queued for later parsing", demux->objpath);
4042 buf = gst_buffer_new_and_alloc (obj_data_size);
4043 gst_buffer_fill (buf, 0, *p_data, obj_data_size);
4044 demux->ext_stream_props = g_slist_append (demux->ext_stream_props, buf);
4048 case ASF_OBJ_LANGUAGE_LIST:
4049 ret = gst_asf_demux_process_language_list (demux, *p_data, obj_data_size);
4051 case ASF_OBJ_ADVANCED_MUTUAL_EXCLUSION:
4052 ret = gst_asf_demux_process_advanced_mutual_exclusion (demux, *p_data,
4055 case ASF_OBJ_SIMPLE_INDEX:
4056 ret = gst_asf_demux_process_simple_index (demux, *p_data, obj_data_size);
4058 case ASF_OBJ_CONTENT_ENCRYPTION:
4059 case ASF_OBJ_EXT_CONTENT_ENCRYPTION:
4060 case ASF_OBJ_DIGITAL_SIGNATURE_OBJECT:
4061 case ASF_OBJ_UNKNOWN_ENCRYPTION_OBJECT:
4062 goto error_encrypted;
4063 case ASF_OBJ_CONCEAL_NONE:
4065 case ASF_OBJ_UNDEFINED:
4066 case ASF_OBJ_CODEC_COMMENT:
4068 case ASF_OBJ_PADDING:
4069 case ASF_OBJ_BITRATE_MUTEX:
4070 case ASF_OBJ_COMPATIBILITY:
4071 case ASF_OBJ_INDEX_PLACEHOLDER:
4072 case ASF_OBJ_INDEX_PARAMETERS:
4073 case ASF_OBJ_STREAM_PRIORITIZATION:
4074 case ASF_OBJ_SCRIPT_COMMAND:
4075 case ASF_OBJ_METADATA_LIBRARY_OBJECT:
4077 /* Unknown/unhandled object, skip it and hope for the best */
4078 GST_INFO ("%s: skipping object", demux->objpath);
4083 /* this can't fail, we checked the number of bytes available before */
4084 gst_asf_demux_skip_bytes (obj_data_size, p_data, p_size);
4086 GST_LOG ("%s: ret = %s", demux->objpath, gst_asf_get_flow_name (ret));
4088 gst_asf_demux_pop_obj (demux);
4095 GST_ELEMENT_ERROR (demux, STREAM, DECRYPT, (NULL), (NULL));
4096 return GST_FLOW_ERROR;
4101 gst_asf_demux_descramble_buffer (GstASFDemux * demux, AsfStream * stream,
4102 GstBuffer ** p_buffer)
4104 GstBuffer *descrambled_buffer;
4105 GstBuffer *scrambled_buffer;
4106 GstBuffer *sub_buffer;
4113 /* descrambled_buffer is initialised in the first iteration */
4114 descrambled_buffer = NULL;
4115 scrambled_buffer = *p_buffer;
4117 if (gst_buffer_get_size (scrambled_buffer) <
4118 stream->ds_packet_size * stream->span)
4121 for (offset = 0; offset < gst_buffer_get_size (scrambled_buffer);
4122 offset += stream->ds_chunk_size) {
4123 off = offset / stream->ds_chunk_size;
4124 row = off / stream->span;
4125 col = off % stream->span;
4126 idx = row + col * stream->ds_packet_size / stream->ds_chunk_size;
4127 GST_DEBUG ("idx=%u, row=%u, col=%u, off=%u, ds_chunk_size=%u", idx, row,
4128 col, off, stream->ds_chunk_size);
4129 GST_DEBUG ("scrambled buffer size=%" G_GSIZE_FORMAT
4130 ", span=%u, packet_size=%u", gst_buffer_get_size (scrambled_buffer),
4131 stream->span, stream->ds_packet_size);
4132 GST_DEBUG ("gst_buffer_get_size (scrambled_buffer) = %" G_GSIZE_FORMAT,
4133 gst_buffer_get_size (scrambled_buffer));
4135 gst_buffer_copy_region (scrambled_buffer, GST_BUFFER_COPY_MEMORY,
4136 idx * stream->ds_chunk_size, stream->ds_chunk_size);
4138 descrambled_buffer = sub_buffer;
4140 descrambled_buffer = gst_buffer_append (descrambled_buffer, sub_buffer);
4144 GST_BUFFER_TIMESTAMP (descrambled_buffer) =
4145 GST_BUFFER_TIMESTAMP (scrambled_buffer);
4146 GST_BUFFER_DURATION (descrambled_buffer) =
4147 GST_BUFFER_DURATION (scrambled_buffer);
4148 GST_BUFFER_OFFSET (descrambled_buffer) = GST_BUFFER_OFFSET (scrambled_buffer);
4149 GST_BUFFER_OFFSET_END (descrambled_buffer) =
4150 GST_BUFFER_OFFSET_END (scrambled_buffer);
4152 /* FIXME/CHECK: do we need to transfer buffer flags here too? */
4154 gst_buffer_unref (scrambled_buffer);
4155 *p_buffer = descrambled_buffer;
4159 gst_asf_demux_element_send_event (GstElement * element, GstEvent * event)
4161 GstASFDemux *demux = GST_ASF_DEMUX (element);
4164 GST_DEBUG ("handling element event of type %s", GST_EVENT_TYPE_NAME (event));
4166 for (i = 0; i < demux->num_streams; ++i) {
4167 gst_event_ref (event);
4168 if (gst_asf_demux_handle_src_event (demux->stream[i].pad,
4169 GST_OBJECT_CAST (element), event)) {
4170 gst_event_unref (event);
4175 gst_event_unref (event);
4179 /* takes ownership of the passed event */
4181 gst_asf_demux_send_event_unlocked (GstASFDemux * demux, GstEvent * event)
4183 gboolean ret = TRUE;
4186 GST_DEBUG_OBJECT (demux, "sending %s event to all source pads",
4187 GST_EVENT_TYPE_NAME (event));
4189 for (i = 0; i < demux->num_streams; ++i) {
4190 gst_event_ref (event);
4191 ret &= gst_pad_push_event (demux->stream[i].pad, event);
4193 gst_event_unref (event);
4198 gst_asf_demux_handle_src_query (GstPad * pad, GstObject * parent,
4202 gboolean res = FALSE;
4204 demux = GST_ASF_DEMUX (parent);
4206 GST_DEBUG ("handling %s query",
4207 gst_query_type_get_name (GST_QUERY_TYPE (query)));
4209 switch (GST_QUERY_TYPE (query)) {
4210 case GST_QUERY_DURATION:
4214 gst_query_parse_duration (query, &format, NULL);
4216 if (format != GST_FORMAT_TIME) {
4217 GST_LOG ("only support duration queries in TIME format");
4221 res = gst_pad_query_default (pad, parent, query);
4223 GST_OBJECT_LOCK (demux);
4225 if (demux->segment.duration != GST_CLOCK_TIME_NONE) {
4226 GST_LOG ("returning duration: %" GST_TIME_FORMAT,
4227 GST_TIME_ARGS (demux->segment.duration));
4229 gst_query_set_duration (query, GST_FORMAT_TIME,
4230 demux->segment.duration);
4234 GST_LOG ("duration not known yet");
4237 GST_OBJECT_UNLOCK (demux);
4242 case GST_QUERY_POSITION:{
4245 gst_query_parse_position (query, &format, NULL);
4247 if (format != GST_FORMAT_TIME) {
4248 GST_LOG ("only support position queries in TIME format");
4252 GST_OBJECT_LOCK (demux);
4254 if (demux->segment.position != GST_CLOCK_TIME_NONE) {
4255 GST_LOG ("returning position: %" GST_TIME_FORMAT,
4256 GST_TIME_ARGS (demux->segment.position));
4258 gst_query_set_position (query, GST_FORMAT_TIME,
4259 demux->segment.position);
4263 GST_LOG ("position not known yet");
4266 GST_OBJECT_UNLOCK (demux);
4270 case GST_QUERY_SEEKING:{
4273 gst_query_parse_seeking (query, &format, NULL, NULL, NULL);
4274 if (format == GST_FORMAT_TIME) {
4277 GST_OBJECT_LOCK (demux);
4278 duration = demux->segment.duration;
4279 GST_OBJECT_UNLOCK (demux);
4281 if (!demux->streaming || !demux->seekable) {
4282 gst_query_set_seeking (query, GST_FORMAT_TIME, demux->seekable, 0,
4289 /* try downstream first in TIME */
4290 res = gst_pad_query_default (pad, parent, query);
4292 gst_query_parse_seeking (query, &fmt, &seekable, NULL, NULL);
4293 GST_LOG_OBJECT (demux, "upstream %s seekable %d",
4294 GST_STR_NULL (gst_format_get_name (fmt)), seekable);
4295 /* if no luck, maybe in BYTES */
4296 if (!seekable || fmt != GST_FORMAT_TIME) {
4299 q = gst_query_new_seeking (GST_FORMAT_BYTES);
4300 if ((res = gst_pad_peer_query (demux->sinkpad, q))) {
4301 gst_query_parse_seeking (q, &fmt, &seekable, NULL, NULL);
4302 GST_LOG_OBJECT (demux, "upstream %s seekable %d",
4303 GST_STR_NULL (gst_format_get_name (fmt)), seekable);
4304 if (fmt != GST_FORMAT_BYTES)
4307 gst_query_unref (q);
4308 gst_query_set_seeking (query, GST_FORMAT_TIME, seekable, 0,
4314 GST_LOG_OBJECT (demux, "only support seeking in TIME format");
4318 case GST_QUERY_LATENCY:
4321 GstClockTime min, max;
4323 /* preroll delay does not matter in non-live pipeline,
4324 * but we might end up in a live (rtsp) one ... */
4327 res = gst_pad_query_default (pad, parent, query);
4331 gst_query_parse_latency (query, &live, &min, &max);
4333 GST_DEBUG_OBJECT (demux, "Peer latency: live %d, min %"
4334 GST_TIME_FORMAT " max %" GST_TIME_FORMAT, live,
4335 GST_TIME_ARGS (min), GST_TIME_ARGS (max));
4337 GST_OBJECT_LOCK (demux);
4339 min += demux->latency;
4341 max += demux->latency;
4342 GST_OBJECT_UNLOCK (demux);
4344 gst_query_set_latency (query, live, min, max);
4347 case GST_QUERY_SEGMENT:
4352 format = demux->segment.format;
4355 gst_segment_to_stream_time (&demux->segment, format,
4356 demux->segment.start);
4357 if ((stop = demux->segment.stop) == -1)
4358 stop = demux->segment.duration;
4360 stop = gst_segment_to_stream_time (&demux->segment, format, stop);
4362 gst_query_set_segment (query, demux->segment.rate, format, start, stop);
4367 res = gst_pad_query_default (pad, parent, query);
4374 static GstStateChangeReturn
4375 gst_asf_demux_change_state (GstElement * element, GstStateChange transition)
4377 GstASFDemux *demux = GST_ASF_DEMUX (element);
4378 GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
4380 switch (transition) {
4381 case GST_STATE_CHANGE_NULL_TO_READY:{
4382 gst_segment_init (&demux->segment, GST_FORMAT_TIME);
4383 demux->need_newsegment = TRUE;
4384 demux->segment_running = FALSE;
4385 demux->accurate = FALSE;
4386 demux->adapter = gst_adapter_new ();
4387 demux->metadata = gst_caps_new_empty ();
4388 demux->global_metadata = gst_structure_new_empty ("metadata");
4389 demux->data_size = 0;
4390 demux->data_offset = 0;
4391 demux->index_offset = 0;
4392 demux->base_offset = 0;
4393 demux->flowcombiner = gst_flow_combiner_new ();
4400 ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
4401 if (ret == GST_STATE_CHANGE_FAILURE)
4404 switch (transition) {
4405 case GST_STATE_CHANGE_PAUSED_TO_READY:
4406 gst_asf_demux_reset (demux, FALSE);
4409 case GST_STATE_CHANGE_READY_TO_NULL:
4410 gst_asf_demux_reset (demux, FALSE);
4411 gst_flow_combiner_free (demux->flowcombiner);
4412 demux->flowcombiner = NULL;