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/riff/riff-media.h>
38 #include <gst/tag/tag.h>
39 #include <gst/gst-i18n-plugin.h>
44 #include "gstasfdemux.h"
45 #include "asfheaders.h"
46 #include "asfpacket.h"
48 static GstStaticPadTemplate gst_asf_demux_sink_template =
49 GST_STATIC_PAD_TEMPLATE ("sink",
52 GST_STATIC_CAPS ("video/x-ms-asf")
55 static GstStaticPadTemplate audio_src_template =
56 GST_STATIC_PAD_TEMPLATE ("audio_%u",
61 static GstStaticPadTemplate video_src_template =
62 GST_STATIC_PAD_TEMPLATE ("video_%u",
67 /* size of an ASF object header, ie. GUID (16 bytes) + object size (8 bytes) */
68 #define ASF_OBJECT_HEADER_SIZE (16+8)
70 /* FIXME: get rid of this */
71 /* abuse this GstFlowReturn enum for internal usage */
72 #define ASF_FLOW_NEED_MORE_DATA 99
74 #define gst_asf_get_flow_name(flow) \
75 (flow == ASF_FLOW_NEED_MORE_DATA) ? \
76 "need-more-data" : gst_flow_get_name (flow)
78 GST_DEBUG_CATEGORY (asfdemux_dbg);
80 static GstStateChangeReturn gst_asf_demux_change_state (GstElement * element,
81 GstStateChange transition);
82 static gboolean gst_asf_demux_element_send_event (GstElement * element,
84 static gboolean gst_asf_demux_send_event_unlocked (GstASFDemux * demux,
86 static gboolean gst_asf_demux_handle_src_query (GstPad * pad,
87 GstObject * parent, GstQuery * query);
88 static GstFlowReturn gst_asf_demux_chain (GstPad * pad, GstObject * parent,
90 static gboolean gst_asf_demux_sink_event (GstPad * pad, GstObject * parent,
92 static GstFlowReturn gst_asf_demux_process_object (GstASFDemux * demux,
93 guint8 ** p_data, guint64 * p_size);
94 static gboolean gst_asf_demux_activate (GstPad * sinkpad, GstObject * parent);
95 static gboolean gst_asf_demux_activate_mode (GstPad * sinkpad,
96 GstObject * parent, GstPadMode mode, gboolean active);
97 static void gst_asf_demux_loop (GstASFDemux * demux);
99 gst_asf_demux_process_queued_extended_stream_objects (GstASFDemux * demux);
100 static gboolean gst_asf_demux_pull_headers (GstASFDemux * demux);
101 static void gst_asf_demux_pull_indices (GstASFDemux * demux);
102 static void gst_asf_demux_reset_stream_state_after_discont (GstASFDemux * asf);
104 gst_asf_demux_parse_data_object_start (GstASFDemux * demux, guint8 * data);
105 static void gst_asf_demux_descramble_buffer (GstASFDemux * demux,
106 AsfStream * stream, GstBuffer ** p_buffer);
107 static void gst_asf_demux_activate_stream (GstASFDemux * demux,
109 static GstStructure *gst_asf_demux_get_metadata_for_stream (GstASFDemux * d,
111 static GstFlowReturn gst_asf_demux_push_complete_payloads (GstASFDemux * demux,
114 #define gst_asf_demux_parent_class parent_class
115 G_DEFINE_TYPE (GstASFDemux, gst_asf_demux, GST_TYPE_ELEMENT);
118 gst_asf_demux_class_init (GstASFDemuxClass * klass)
120 GstElementClass *gstelement_class;
122 gstelement_class = (GstElementClass *) klass;
124 gst_element_class_set_static_metadata (gstelement_class, "ASF Demuxer",
126 "Demultiplexes ASF Streams", "Owen Fraser-Green <owen@discobabe.net>");
128 gst_element_class_add_pad_template (gstelement_class,
129 gst_static_pad_template_get (&audio_src_template));
130 gst_element_class_add_pad_template (gstelement_class,
131 gst_static_pad_template_get (&video_src_template));
132 gst_element_class_add_pad_template (gstelement_class,
133 gst_static_pad_template_get (&gst_asf_demux_sink_template));
135 gstelement_class->change_state =
136 GST_DEBUG_FUNCPTR (gst_asf_demux_change_state);
137 gstelement_class->send_event =
138 GST_DEBUG_FUNCPTR (gst_asf_demux_element_send_event);
142 gst_asf_demux_free_stream (GstASFDemux * demux, AsfStream * stream)
144 gst_caps_replace (&stream->caps, NULL);
145 if (stream->pending_tags) {
146 gst_tag_list_unref (stream->pending_tags);
147 stream->pending_tags = NULL;
151 gst_element_remove_pad (GST_ELEMENT_CAST (demux), stream->pad);
153 gst_object_unref (stream->pad);
157 while (stream->payloads->len > 0) {
161 last = stream->payloads->len - 1;
162 payload = &g_array_index (stream->payloads, AsfPayload, last);
163 gst_buffer_replace (&payload->buf, NULL);
164 g_array_remove_index (stream->payloads, last);
166 if (stream->payloads) {
167 g_array_free (stream->payloads, TRUE);
168 stream->payloads = NULL;
170 if (stream->ext_props.valid) {
171 g_free (stream->ext_props.payload_extensions);
172 stream->ext_props.payload_extensions = NULL;
177 gst_asf_demux_reset (GstASFDemux * demux, gboolean chain_reset)
179 GST_LOG_OBJECT (demux, "resetting");
181 gst_segment_init (&demux->segment, GST_FORMAT_UNDEFINED);
182 demux->segment_running = FALSE;
183 if (demux->adapter && !chain_reset) {
184 gst_adapter_clear (demux->adapter);
185 g_object_unref (demux->adapter);
186 demux->adapter = NULL;
188 if (demux->taglist) {
189 gst_tag_list_unref (demux->taglist);
190 demux->taglist = NULL;
192 if (demux->metadata) {
193 gst_caps_unref (demux->metadata);
194 demux->metadata = NULL;
196 if (demux->global_metadata) {
197 gst_structure_free (demux->global_metadata);
198 demux->global_metadata = NULL;
201 demux->state = GST_ASF_DEMUX_STATE_HEADER;
202 g_free (demux->objpath);
203 demux->objpath = NULL;
204 g_strfreev (demux->languages);
205 demux->languages = NULL;
206 demux->num_languages = 0;
207 g_slist_foreach (demux->ext_stream_props, (GFunc) gst_mini_object_unref,
209 g_slist_free (demux->ext_stream_props);
210 demux->ext_stream_props = NULL;
212 while (demux->old_num_streams > 0) {
213 gst_asf_demux_free_stream (demux,
214 &demux->old_stream[demux->old_num_streams - 1]);
215 --demux->old_num_streams;
217 memset (demux->old_stream, 0, sizeof (demux->old_stream));
218 demux->old_num_streams = 0;
220 /* when resetting for a new chained asf, we don't want to remove the pads
221 * before adding the new ones */
223 memcpy (demux->old_stream, demux->stream, sizeof (demux->stream));
224 demux->old_num_streams = demux->num_streams;
225 demux->num_streams = 0;
228 while (demux->num_streams > 0) {
229 gst_asf_demux_free_stream (demux, &demux->stream[demux->num_streams - 1]);
230 --demux->num_streams;
232 memset (demux->stream, 0, sizeof (demux->stream));
234 /* do not remove those for not adding pads with same name */
235 demux->num_audio_streams = 0;
236 demux->num_video_streams = 0;
238 demux->num_streams = 0;
239 demux->activated_streams = FALSE;
240 demux->first_ts = GST_CLOCK_TIME_NONE;
241 demux->segment_ts = GST_CLOCK_TIME_NONE;
244 gst_segment_init (&demux->in_segment, GST_FORMAT_UNDEFINED);
245 demux->state = GST_ASF_DEMUX_STATE_HEADER;
246 demux->seekable = FALSE;
247 demux->broadcast = FALSE;
248 demux->sidx_interval = 0;
249 demux->sidx_num_entries = 0;
250 g_free (demux->sidx_entries);
251 demux->sidx_entries = NULL;
253 demux->speed_packets = 1;
256 GST_LOG_OBJECT (demux, "Restarting");
257 gst_segment_init (&demux->segment, GST_FORMAT_TIME);
258 demux->need_newsegment = TRUE;
259 demux->segment_running = FALSE;
260 demux->accurate = FALSE;
261 demux->metadata = gst_caps_new_empty ();
262 demux->global_metadata = gst_structure_new_empty ("metadata");
263 demux->data_size = 0;
264 demux->data_offset = 0;
265 demux->index_offset = 0;
267 demux->base_offset = 0;
272 gst_asf_demux_init (GstASFDemux * demux)
275 gst_pad_new_from_static_template (&gst_asf_demux_sink_template, "sink");
276 gst_pad_set_chain_function (demux->sinkpad,
277 GST_DEBUG_FUNCPTR (gst_asf_demux_chain));
278 gst_pad_set_event_function (demux->sinkpad,
279 GST_DEBUG_FUNCPTR (gst_asf_demux_sink_event));
280 gst_pad_set_activate_function (demux->sinkpad,
281 GST_DEBUG_FUNCPTR (gst_asf_demux_activate));
282 gst_pad_set_activatemode_function (demux->sinkpad,
283 GST_DEBUG_FUNCPTR (gst_asf_demux_activate_mode));
284 gst_element_add_pad (GST_ELEMENT (demux), demux->sinkpad);
286 /* set initial state */
287 gst_asf_demux_reset (demux, FALSE);
291 gst_asf_demux_activate (GstPad * sinkpad, GstObject * parent)
296 query = gst_query_new_scheduling ();
298 if (!gst_pad_peer_query (sinkpad, query)) {
299 gst_query_unref (query);
303 pull_mode = gst_query_has_scheduling_mode_with_flags (query,
304 GST_PAD_MODE_PULL, GST_SCHEDULING_FLAG_SEEKABLE);
305 gst_query_unref (query);
310 GST_DEBUG_OBJECT (sinkpad, "activating pull");
311 return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PULL, TRUE);
315 GST_DEBUG_OBJECT (sinkpad, "activating push");
316 return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PUSH, TRUE);
321 gst_asf_demux_activate_mode (GstPad * sinkpad, GstObject * parent,
322 GstPadMode mode, gboolean active)
327 demux = GST_ASF_DEMUX (parent);
330 case GST_PAD_MODE_PUSH:
331 demux->state = GST_ASF_DEMUX_STATE_HEADER;
332 demux->streaming = TRUE;
335 case GST_PAD_MODE_PULL:
337 demux->state = GST_ASF_DEMUX_STATE_HEADER;
338 demux->streaming = FALSE;
340 res = gst_pad_start_task (sinkpad, (GstTaskFunction) gst_asf_demux_loop,
343 res = gst_pad_stop_task (sinkpad);
354 gst_asf_demux_sink_event (GstPad * pad, GstObject * parent, GstEvent * event)
359 demux = GST_ASF_DEMUX (parent);
361 GST_LOG_OBJECT (demux, "handling %s event", GST_EVENT_TYPE_NAME (event));
362 switch (GST_EVENT_TYPE (event)) {
363 case GST_EVENT_SEGMENT:{
364 const GstSegment *segment;
366 gst_event_parse_segment (event, &segment);
368 if (segment->format == GST_FORMAT_BYTES) {
369 if (demux->packet_size && segment->start > demux->data_offset)
370 demux->packet = (segment->start - demux->data_offset) /
374 } else if (segment->format == GST_FORMAT_TIME) {
375 /* do not know packet position, not really a problem */
378 GST_WARNING_OBJECT (demux, "unsupported newsegment format, ignoring");
379 gst_event_unref (event);
383 /* record upstream segment for interpolation */
384 if (segment->format != demux->in_segment.format)
385 gst_segment_init (&demux->in_segment, GST_FORMAT_UNDEFINED);
386 gst_segment_copy_into (segment, &demux->in_segment);
388 /* in either case, clear some state and generate newsegment later on */
389 GST_OBJECT_LOCK (demux);
390 demux->segment_ts = GST_CLOCK_TIME_NONE;
391 demux->in_gap = GST_CLOCK_TIME_NONE;
392 demux->need_newsegment = TRUE;
393 gst_asf_demux_reset_stream_state_after_discont (demux);
394 GST_OBJECT_UNLOCK (demux);
396 gst_event_unref (event);
402 if (demux->state == GST_ASF_DEMUX_STATE_HEADER) {
403 GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
404 (_("This stream contains no data.")),
405 ("got eos and didn't receive a complete header object"));
408 flow = gst_asf_demux_push_complete_payloads (demux, TRUE);
409 if (flow < GST_FLOW_EOS || flow == GST_FLOW_NOT_LINKED) {
410 GST_ELEMENT_ERROR (demux, STREAM, FAILED,
411 (_("Internal data stream error.")),
412 ("streaming stopped, reason %s", gst_flow_get_name (flow)));
416 GST_OBJECT_LOCK (demux);
417 gst_adapter_clear (demux->adapter);
418 GST_OBJECT_UNLOCK (demux);
419 gst_asf_demux_send_event_unlocked (demux, event);
423 case GST_EVENT_FLUSH_STOP:
424 GST_OBJECT_LOCK (demux);
425 gst_asf_demux_reset_stream_state_after_discont (demux);
426 GST_OBJECT_UNLOCK (demux);
427 gst_asf_demux_send_event_unlocked (demux, event);
428 /* upon activation, latency is no longer introduced, e.g. after seek */
429 if (demux->activated_streams)
434 ret = gst_pad_event_default (pad, parent, event);
442 gst_asf_demux_seek_index_lookup (GstASFDemux * demux, guint * packet,
443 GstClockTime seek_time, GstClockTime * p_idx_time, guint * speed,
444 gboolean next, gboolean * eos)
446 GstClockTime idx_time;
452 if (G_UNLIKELY (demux->sidx_num_entries == 0 || demux->sidx_interval == 0))
455 idx = (guint) ((seek_time + demux->preroll) / demux->sidx_interval);
458 /* if we want the next keyframe, we have to go forward till we find
459 a different packet number */
461 if (idx >= demux->sidx_num_entries - 1) {
462 /* If we get here, we're asking for next keyframe after the last one. There isn't one. */
467 for (idx2 = idx + 1; idx2 < demux->sidx_num_entries; ++idx2) {
468 if (demux->sidx_entries[idx].packet != demux->sidx_entries[idx2].packet) {
475 if (G_UNLIKELY (idx >= demux->sidx_num_entries)) {
481 *packet = demux->sidx_entries[idx].packet;
483 *speed = demux->sidx_entries[idx].count;
485 /* so we get closer to the actual time of the packet ... actually, let's not
486 * do this, since we throw away superfluous payloads before the seek position
487 * anyway; this way, our key unit seek 'snap resolution' is a bit better
488 * (ie. same as index resolution) */
490 while (idx > 0 && demux->sidx_entries[idx-1] == demux->sidx_entries[idx])
494 idx_time = demux->sidx_interval * idx;
495 if (G_LIKELY (idx_time >= demux->preroll))
496 idx_time -= demux->preroll;
498 GST_DEBUG_OBJECT (demux, "%" GST_TIME_FORMAT " => packet %u at %"
499 GST_TIME_FORMAT, GST_TIME_ARGS (seek_time), *packet,
500 GST_TIME_ARGS (idx_time));
502 if (G_LIKELY (p_idx_time))
503 *p_idx_time = idx_time;
509 gst_asf_demux_reset_stream_state_after_discont (GstASFDemux * demux)
513 gst_adapter_clear (demux->adapter);
515 GST_DEBUG_OBJECT (demux, "reset stream state");
517 for (n = 0; n < demux->num_streams; n++) {
518 demux->stream[n].discont = TRUE;
519 demux->stream[n].last_flow = GST_FLOW_OK;
521 while (demux->stream[n].payloads->len > 0) {
525 last = demux->stream[n].payloads->len - 1;
526 payload = &g_array_index (demux->stream[n].payloads, AsfPayload, last);
527 gst_buffer_replace (&payload->buf, NULL);
528 g_array_remove_index (demux->stream[n].payloads, last);
534 gst_asf_demux_mark_discont (GstASFDemux * demux)
538 GST_DEBUG_OBJECT (demux, "Mark stream discont");
540 for (n = 0; n < demux->num_streams; n++)
541 demux->stream[n].discont = TRUE;
544 /* do a seek in push based mode */
546 gst_asf_demux_handle_seek_push (GstASFDemux * demux, GstEvent * event)
551 GstSeekType cur_type, stop_type;
556 gst_event_parse_seek (event, &rate, &format, &flags, &cur_type, &cur,
559 stop_type = GST_SEEK_TYPE_NONE;
562 GST_DEBUG_OBJECT (demux, "seeking to %" GST_TIME_FORMAT, GST_TIME_ARGS (cur));
564 /* determine packet, by index or by estimation */
565 if (!gst_asf_demux_seek_index_lookup (demux, &packet, cur, NULL, NULL, FALSE,
568 (guint) gst_util_uint64_scale (demux->num_packets, cur,
572 if (packet > demux->num_packets) {
573 GST_DEBUG_OBJECT (demux, "could not determine packet to seek to, "
578 GST_DEBUG_OBJECT (demux, "seeking to packet %d", packet);
580 cur = demux->data_offset + (packet * demux->packet_size);
582 GST_DEBUG_OBJECT (demux, "Pushing BYTE seek rate %g, "
583 "start %" G_GINT64_FORMAT ", stop %" G_GINT64_FORMAT, rate, cur, stop);
584 /* BYTE seek event */
585 event = gst_event_new_seek (rate, GST_FORMAT_BYTES, flags, cur_type, cur,
587 res = gst_pad_push_event (demux->sinkpad, event);
593 gst_asf_demux_handle_seek_event (GstASFDemux * demux, GstEvent * event)
595 GstClockTime idx_time;
598 GstSeekType cur_type, stop_type;
600 gboolean only_need_update;
601 gboolean keyunit_sync, after, before, next;
606 guint packet, speed_count = 1;
609 if (G_UNLIKELY (demux->seekable == FALSE || demux->packet_size == 0 ||
610 demux->num_packets == 0 || demux->play_time == 0)) {
611 GST_LOG_OBJECT (demux, "stream is not seekable");
615 if (G_UNLIKELY (!demux->activated_streams)) {
616 GST_LOG_OBJECT (demux, "streams not yet activated, ignoring seek");
620 gst_event_parse_seek (event, &rate, &format, &flags, &cur_type, &cur,
623 if (G_UNLIKELY (format != GST_FORMAT_TIME)) {
624 GST_LOG_OBJECT (demux, "seeking is only supported in TIME format");
628 if (G_UNLIKELY (rate <= 0.0)) {
629 GST_LOG_OBJECT (demux, "backward playback is not supported yet");
633 flush = ((flags & GST_SEEK_FLAG_FLUSH) == GST_SEEK_FLAG_FLUSH);
635 ((flags & GST_SEEK_FLAG_ACCURATE) == GST_SEEK_FLAG_ACCURATE);
636 keyunit_sync = ((flags & GST_SEEK_FLAG_KEY_UNIT) == GST_SEEK_FLAG_KEY_UNIT);
637 after = ((flags & GST_SEEK_FLAG_SNAP_AFTER) == GST_SEEK_FLAG_SNAP_AFTER);
638 before = ((flags & GST_SEEK_FLAG_SNAP_BEFORE) == GST_SEEK_FLAG_SNAP_BEFORE);
639 next = after && !before;
641 if (G_UNLIKELY (demux->streaming)) {
642 /* support it safely needs more segment handling, e.g. closing etc */
644 GST_LOG_OBJECT (demux, "streaming; non-flushing seek not supported");
647 /* we can (re)construct the start later on, but not the end */
648 if (stop_type != GST_SEEK_TYPE_NONE &&
649 (stop_type != GST_SEEK_TYPE_SET || GST_CLOCK_TIME_IS_VALID (stop))) {
650 GST_LOG_OBJECT (demux, "streaming; end position must be NONE");
653 gst_event_ref (event);
654 /* upstream might handle TIME seek, e.g. mms or rtsp,
655 * or not, e.g. http, then we give it a hand */
656 if (!gst_pad_push_event (demux->sinkpad, event))
657 return gst_asf_demux_handle_seek_push (demux, event);
662 /* unlock the streaming thread */
663 if (G_LIKELY (flush)) {
664 gst_pad_push_event (demux->sinkpad, gst_event_new_flush_start ());
665 gst_asf_demux_send_event_unlocked (demux, gst_event_new_flush_start ());
667 gst_pad_pause_task (demux->sinkpad);
670 /* grab the stream lock so that streaming cannot continue, for
671 * non flushing seeks when the element is in PAUSED this could block
673 GST_PAD_STREAM_LOCK (demux->sinkpad);
675 /* we now can stop flushing, since we have the stream lock now */
676 gst_pad_push_event (demux->sinkpad, gst_event_new_flush_stop (TRUE));
678 if (G_LIKELY (flush))
679 gst_asf_demux_send_event_unlocked (demux, gst_event_new_flush_stop (TRUE));
681 /* operating on copy of segment until we know the seek worked */
682 segment = demux->segment;
684 if (G_UNLIKELY (demux->segment_running && !flush)) {
685 GstSegment newsegment;
688 /* create the segment event to close the current segment */
689 gst_segment_copy_into (&segment, &newsegment);
690 newseg = gst_event_new_segment (&newsegment);
692 gst_asf_demux_send_event_unlocked (demux, newseg);
695 gst_segment_do_seek (&segment, rate, format, flags, cur_type,
696 cur, stop_type, stop, &only_need_update);
698 GST_DEBUG_OBJECT (demux, "seeking to time %" GST_TIME_FORMAT ", segment: "
699 "%" GST_SEGMENT_FORMAT, GST_TIME_ARGS (segment.start), &segment);
701 seek_time = segment.start;
703 /* FIXME: should check the KEY_UNIT flag; need to adjust position to
704 * real start of data and segment_start to indexed time for key unit seek*/
705 if (G_UNLIKELY (!gst_asf_demux_seek_index_lookup (demux, &packet, seek_time,
706 &idx_time, &speed_count, next, &eos))) {
710 demux->packet = demux->num_packets;
714 /* First try to query our source to see if it can convert for us. This is
715 the case when our source is an mms stream, notice that in this case
716 gstmms will do a time based seek to get the byte offset, this is not a
717 problem as the seek to this offset needs to happen anway. */
718 if (gst_pad_peer_query_convert (demux->sinkpad, GST_FORMAT_TIME, seek_time,
719 GST_FORMAT_BYTES, &offset)) {
720 packet = (offset - demux->data_offset) / demux->packet_size;
721 GST_LOG_OBJECT (demux, "convert %" GST_TIME_FORMAT
722 " to bytes query result: %" G_GINT64_FORMAT ", data_ofset: %"
723 G_GINT64_FORMAT ", packet_size: %u," " resulting packet: %u\n",
724 GST_TIME_ARGS (seek_time), offset, demux->data_offset,
725 demux->packet_size, packet);
727 /* FIXME: For streams containing video, seek to an earlier position in
728 * the hope of hitting a keyframe and let the sinks throw away the stuff
729 * before the segment start. For audio-only this is unnecessary as every
731 if (flush && (demux->accurate || (keyunit_sync && !next))
732 && demux->num_video_streams > 0) {
733 seek_time -= 5 * GST_SECOND;
738 packet = (guint) gst_util_uint64_scale (demux->num_packets,
739 seek_time, demux->play_time);
741 if (packet > demux->num_packets)
742 packet = demux->num_packets;
745 if (G_LIKELY (keyunit_sync)) {
746 GST_DEBUG_OBJECT (demux, "key unit seek, adjust seek_time = %"
747 GST_TIME_FORMAT " to index_time = %" GST_TIME_FORMAT,
748 GST_TIME_ARGS (seek_time), GST_TIME_ARGS (idx_time));
749 segment.start = idx_time;
750 segment.position = idx_time;
751 segment.time = idx_time;
755 GST_DEBUG_OBJECT (demux, "seeking to packet %u (%d)", packet, speed_count);
757 GST_OBJECT_LOCK (demux);
758 demux->segment = segment;
759 demux->packet = packet;
760 demux->need_newsegment = TRUE;
761 demux->speed_packets = speed_count;
762 gst_asf_demux_reset_stream_state_after_discont (demux);
763 GST_OBJECT_UNLOCK (demux);
766 /* restart our task since it might have been stopped when we did the flush */
767 gst_pad_start_task (demux->sinkpad, (GstTaskFunction) gst_asf_demux_loop,
770 /* streaming can continue now */
771 GST_PAD_STREAM_UNLOCK (demux->sinkpad);
777 gst_asf_demux_handle_src_event (GstPad * pad, GstObject * parent,
783 demux = GST_ASF_DEMUX (parent);
785 switch (GST_EVENT_TYPE (event)) {
787 GST_LOG_OBJECT (pad, "seek event");
788 ret = gst_asf_demux_handle_seek_event (demux, event);
789 gst_event_unref (event);
792 case GST_EVENT_NAVIGATION:
793 /* just drop these two silently */
794 gst_event_unref (event);
798 GST_LOG_OBJECT (pad, "%s event", GST_EVENT_TYPE_NAME (event));
799 ret = gst_pad_event_default (pad, parent, event);
806 static inline guint32
807 gst_asf_demux_identify_guid (const ASFGuidHash * guids, ASFGuid * guid)
811 ret = gst_asf_identify_guid (guids, guid);
813 GST_LOG ("%s 0x%08x-0x%08x-0x%08x-0x%08x",
814 gst_asf_get_guid_nick (guids, ret),
815 guid->v1, guid->v2, guid->v3, guid->v4);
827 /* expect is true when the user is expeting an object,
828 * when false, it will give no warnings if the object
832 asf_demux_peek_object (GstASFDemux * demux, const guint8 * data,
833 guint data_len, AsfObject * object, gboolean expect)
837 if (data_len < ASF_OBJECT_HEADER_SIZE)
840 guid.v1 = GST_READ_UINT32_LE (data + 0);
841 guid.v2 = GST_READ_UINT32_LE (data + 4);
842 guid.v3 = GST_READ_UINT32_LE (data + 8);
843 guid.v4 = GST_READ_UINT32_LE (data + 12);
845 object->size = GST_READ_UINT64_LE (data + 16);
847 /* FIXME: make asf_demux_identify_object_guid() */
848 object->id = gst_asf_demux_identify_guid (asf_object_guids, &guid);
849 if (object->id == ASF_OBJ_UNDEFINED && expect) {
850 GST_WARNING_OBJECT (demux, "Unknown object %08x-%08x-%08x-%08x",
851 guid.v1, guid.v2, guid.v3, guid.v4);
858 gst_asf_demux_release_old_pads (GstASFDemux * demux)
860 GST_DEBUG_OBJECT (demux, "Releasing old pads");
862 while (demux->old_num_streams > 0) {
863 gst_pad_push_event (demux->old_stream[demux->old_num_streams - 1].pad,
864 gst_event_new_eos ());
865 gst_asf_demux_free_stream (demux,
866 &demux->old_stream[demux->old_num_streams - 1]);
867 --demux->old_num_streams;
869 memset (demux->old_stream, 0, sizeof (demux->old_stream));
870 demux->old_num_streams = 0;
874 gst_asf_demux_chain_headers (GstASFDemux * demux)
878 guint8 *header_data, *data = NULL;
879 const guint8 *cdata = NULL;
882 cdata = (guint8 *) gst_adapter_map (demux->adapter, ASF_OBJECT_HEADER_SIZE);
886 asf_demux_peek_object (demux, cdata, ASF_OBJECT_HEADER_SIZE, &obj, TRUE);
887 if (obj.id != ASF_OBJ_HEADER)
890 GST_LOG_OBJECT (demux, "header size = %u", (guint) obj.size);
892 /* + 50 for non-packet data at beginning of ASF_OBJ_DATA */
893 if (gst_adapter_available (demux->adapter) < obj.size + 50)
896 data = gst_adapter_take (demux->adapter, obj.size + 50);
899 header_size = obj.size;
900 flow = gst_asf_demux_process_object (demux, &header_data, &header_size);
901 if (flow != GST_FLOW_OK)
904 /* calculate where the packet data starts */
905 demux->data_offset = obj.size + 50;
907 /* now parse the beginning of the ASF_OBJ_DATA object */
908 if (!gst_asf_demux_parse_data_object_start (demux, data + obj.size))
911 if (demux->num_streams == 0)
920 GST_LOG_OBJECT (demux, "not enough data in adapter yet");
927 GST_ELEMENT_ERROR (demux, STREAM, WRONG_TYPE, (NULL),
928 ("This doesn't seem to be an ASF file"));
930 return GST_FLOW_ERROR;
935 GST_ELEMENT_ERROR (demux, STREAM, DEMUX, (NULL),
936 ("header parsing failed, or no streams found, flow = %s",
937 gst_flow_get_name (flow)));
939 return GST_FLOW_ERROR;
944 gst_asf_demux_aggregate_flow_return (GstASFDemux * demux, AsfStream * stream,
949 GST_DEBUG_OBJECT (demux, "Aggregating");
951 /* Store the value */
952 stream->last_flow = flow;
954 /* any other error that is not not-linked can be returned right away */
955 if (flow != GST_FLOW_NOT_LINKED)
958 for (i = 0; i < demux->num_streams; i++) {
959 if (demux->stream[i].active) {
960 flow = demux->stream[i].last_flow;
961 GST_DEBUG_OBJECT (demux, "Aggregating: flow %i return %s", i,
962 gst_flow_get_name (flow));
963 if (flow != GST_FLOW_NOT_LINKED)
968 /* If we got here, then all our active streams are not linked */
974 gst_asf_demux_pull_data (GstASFDemux * demux, guint64 offset, guint size,
975 GstBuffer ** p_buf, GstFlowReturn * p_flow)
980 GST_LOG_OBJECT (demux, "pulling buffer at %" G_GUINT64_FORMAT "+%u",
983 flow = gst_pad_pull_range (demux->sinkpad, offset, size, p_buf);
985 if (G_LIKELY (p_flow))
988 if (G_UNLIKELY (flow != GST_FLOW_OK)) {
989 GST_DEBUG_OBJECT (demux, "flow %s pulling buffer at %" G_GUINT64_FORMAT
990 "+%u", gst_flow_get_name (flow), offset, size);
995 g_assert (*p_buf != NULL);
997 buffer_size = gst_buffer_get_size (*p_buf);
998 if (G_UNLIKELY (buffer_size < size)) {
999 GST_DEBUG_OBJECT (demux, "short read pulling buffer at %" G_GUINT64_FORMAT
1000 "+%u (got only %" G_GSIZE_FORMAT " bytes)", offset, size, buffer_size);
1001 gst_buffer_unref (*p_buf);
1002 if (G_LIKELY (p_flow))
1003 *p_flow = GST_FLOW_EOS;
1012 gst_asf_demux_pull_indices (GstASFDemux * demux)
1014 GstBuffer *buf = NULL;
1018 offset = demux->index_offset;
1020 if (G_UNLIKELY (offset == 0)) {
1021 GST_DEBUG_OBJECT (demux, "can't read indices, don't know index offset");
1025 while (gst_asf_demux_pull_data (demux, offset, 16 + 8, &buf, NULL)) {
1031 gst_buffer_map (buf, &map, GST_MAP_READ);
1032 g_assert (map.size >= 16 + 8);
1033 asf_demux_peek_object (demux, map.data, 16 + 8, &obj, TRUE);
1034 gst_buffer_unmap (buf, &map);
1035 gst_buffer_replace (&buf, NULL);
1037 /* check for sanity */
1038 if (G_UNLIKELY (obj.size > (5 * 1024 * 1024))) {
1039 GST_DEBUG_OBJECT (demux, "implausible index object size, bailing out");
1043 if (G_UNLIKELY (!gst_asf_demux_pull_data (demux, offset, obj.size, &buf,
1047 GST_LOG_OBJECT (demux, "index object at offset 0x%" G_GINT64_MODIFIER "X"
1048 ", size %u", offset, (guint) obj.size);
1050 offset += obj.size; /* increase before _process_object changes it */
1052 gst_buffer_map (buf, &map, GST_MAP_READ);
1053 g_assert (map.size >= obj.size);
1054 bufdata = (guint8 *) map.data;
1055 flow = gst_asf_demux_process_object (demux, &bufdata, &obj.size);
1056 gst_buffer_unmap (buf, &map);
1057 gst_buffer_replace (&buf, NULL);
1059 if (G_UNLIKELY (flow != GST_FLOW_OK))
1064 GST_DEBUG_OBJECT (demux, "read %u index objects", num_read);
1068 gst_asf_demux_parse_data_object_start (GstASFDemux * demux, guint8 * data)
1072 asf_demux_peek_object (demux, data, 50, &obj, TRUE);
1073 if (obj.id != ASF_OBJ_DATA) {
1074 GST_WARNING_OBJECT (demux, "headers not followed by a DATA object");
1078 demux->state = GST_ASF_DEMUX_STATE_DATA;
1080 if (!demux->broadcast && obj.size > 50) {
1081 demux->data_size = obj.size - 50;
1082 /* CHECKME: for at least one file this is off by +158 bytes?! */
1083 demux->index_offset = demux->data_offset + demux->data_size;
1085 demux->data_size = 0;
1086 demux->index_offset = 0;
1091 if (!demux->broadcast) {
1092 /* skip object header (24 bytes) and file GUID (16 bytes) */
1093 demux->num_packets = GST_READ_UINT64_LE (data + (16 + 8) + 16);
1095 demux->num_packets = 0;
1098 if (demux->num_packets == 0)
1099 demux->seekable = FALSE;
1101 /* fallback in the unlikely case that headers are inconsistent, can't hurt */
1102 if (demux->data_size == 0 && demux->num_packets > 0) {
1103 demux->data_size = demux->num_packets * demux->packet_size;
1104 demux->index_offset = demux->data_offset + demux->data_size;
1107 /* process pending stream objects and create pads for those */
1108 gst_asf_demux_process_queued_extended_stream_objects (demux);
1110 GST_INFO_OBJECT (demux, "Stream has %" G_GUINT64_FORMAT " packets, "
1111 "data_offset=%" G_GINT64_FORMAT ", data_size=%" G_GINT64_FORMAT
1112 ", index_offset=%" G_GUINT64_FORMAT, demux->num_packets,
1113 demux->data_offset, demux->data_size, demux->index_offset);
1119 gst_asf_demux_pull_headers (GstASFDemux * demux)
1123 GstBuffer *buf = NULL;
1128 GST_LOG_OBJECT (demux, "reading headers");
1130 /* pull HEADER object header, so we know its size */
1131 if (!gst_asf_demux_pull_data (demux, demux->base_offset, 16 + 8, &buf, NULL))
1134 gst_buffer_map (buf, &map, GST_MAP_READ);
1135 g_assert (map.size >= 16 + 8);
1136 asf_demux_peek_object (demux, map.data, 16 + 8, &obj, TRUE);
1137 gst_buffer_unmap (buf, &map);
1138 gst_buffer_replace (&buf, NULL);
1140 if (obj.id != ASF_OBJ_HEADER)
1143 GST_LOG_OBJECT (demux, "header size = %u", (guint) obj.size);
1145 /* pull HEADER object */
1146 if (!gst_asf_demux_pull_data (demux, demux->base_offset, obj.size, &buf,
1150 size = obj.size; /* don't want obj.size changed */
1151 gst_buffer_map (buf, &map, GST_MAP_READ);
1152 g_assert (map.size >= size);
1153 bufdata = (guint8 *) map.data;
1154 flow = gst_asf_demux_process_object (demux, &bufdata, &size);
1155 gst_buffer_unmap (buf, &map);
1156 gst_buffer_replace (&buf, NULL);
1158 if (flow != GST_FLOW_OK) {
1159 GST_WARNING_OBJECT (demux, "process_object: %s", gst_flow_get_name (flow));
1163 /* calculate where the packet data starts */
1164 demux->data_offset = demux->base_offset + obj.size + 50;
1166 /* now pull beginning of DATA object before packet data */
1167 if (!gst_asf_demux_pull_data (demux, demux->base_offset + obj.size, 50, &buf,
1171 gst_buffer_map (buf, &map, GST_MAP_READ);
1172 g_assert (map.size >= size);
1173 bufdata = (guint8 *) map.data;
1174 if (!gst_asf_demux_parse_data_object_start (demux, bufdata))
1177 if (demux->num_streams == 0)
1180 gst_buffer_unmap (buf, &map);
1181 gst_buffer_replace (&buf, NULL);
1189 gst_buffer_unmap (buf, &map);
1190 gst_buffer_replace (&buf, NULL);
1192 GST_ELEMENT_ERROR (demux, STREAM, WRONG_TYPE, (NULL),
1193 ("This doesn't seem to be an ASF file"));
1202 gst_buffer_unmap (buf, &map);
1203 gst_buffer_replace (&buf, NULL);
1204 GST_ELEMENT_ERROR (demux, STREAM, DEMUX, (NULL), (NULL));
1210 all_streams_prerolled (GstASFDemux * demux)
1212 GstClockTime preroll_time;
1213 guint i, num_no_data = 0;
1215 /* Allow at least 500ms of preroll_time */
1216 preroll_time = MAX (demux->preroll, 500 * GST_MSECOND);
1218 /* returns TRUE as long as there isn't a stream which (a) has data queued
1219 * and (b) the timestamp of last piece of data queued is < demux->preroll
1220 * AND there is at least one other stream with data queued */
1221 for (i = 0; i < demux->num_streams; ++i) {
1222 AsfPayload *last_payload;
1226 stream = &demux->stream[i];
1227 if (G_UNLIKELY (stream->payloads->len == 0)) {
1229 GST_LOG_OBJECT (stream->pad, "no data queued");
1233 last_idx = stream->payloads->len - 1;
1234 last_payload = &g_array_index (stream->payloads, AsfPayload, last_idx);
1236 GST_LOG_OBJECT (stream->pad, "checking if %" GST_TIME_FORMAT " > %"
1237 GST_TIME_FORMAT, GST_TIME_ARGS (last_payload->ts),
1238 GST_TIME_ARGS (preroll_time));
1239 if (G_UNLIKELY (last_payload->ts <= preroll_time)) {
1240 GST_LOG_OBJECT (stream->pad, "not beyond preroll point yet");
1245 if (G_UNLIKELY (num_no_data == demux->num_streams))
1253 gst_asf_demux_have_mutually_exclusive_active_stream (GstASFDemux * demux,
1258 for (l = demux->mut_ex_streams; l != NULL; l = l->next) {
1261 /* check for each mutual exclusion group whether it affects this stream */
1262 for (mes = (guint8 *) l->data; mes != NULL && *mes != 0xff; ++mes) {
1263 if (*mes == stream->id) {
1264 /* we are in this group; let's check if we've already activated streams
1265 * that are in the same group (and hence mutually exclusive to this
1267 for (mes = (guint8 *) l->data; mes != NULL && *mes != 0xff; ++mes) {
1270 for (i = 0; i < demux->num_streams; ++i) {
1271 if (demux->stream[i].id == *mes && demux->stream[i].active) {
1272 GST_LOG_OBJECT (demux, "stream with ID %d is mutually exclusive "
1273 "to already active stream with ID %d", stream->id,
1274 demux->stream[i].id);
1279 /* we can only be in this group once, let's break out and move on to
1280 * the next mutual exclusion group */
1291 gst_asf_demux_check_activate_streams (GstASFDemux * demux, gboolean force)
1295 if (demux->activated_streams)
1298 if (!all_streams_prerolled (demux) && !force) {
1299 GST_DEBUG_OBJECT (demux, "not all streams with data beyond preroll yet");
1303 for (i = 0; i < demux->num_streams; ++i) {
1304 AsfStream *stream = &demux->stream[i];
1306 if (stream->payloads->len > 0) {
1307 /* we don't check mutual exclusion stuff here; either we have data for
1308 * a stream, then we active it, or we don't, then we'll ignore it */
1309 GST_LOG_OBJECT (stream->pad, "is prerolled - activate!");
1310 gst_asf_demux_activate_stream (demux, stream);
1312 GST_LOG_OBJECT (stream->pad, "no data, ignoring stream");
1316 gst_asf_demux_release_old_pads (demux);
1318 demux->activated_streams = TRUE;
1319 GST_LOG_OBJECT (demux, "signalling no more pads");
1320 gst_element_no_more_pads (GST_ELEMENT (demux));
1324 /* returns the stream that has a complete payload with the lowest timestamp
1325 * queued, or NULL (we push things by timestamp because during the internal
1326 * prerolling we might accumulate more data then the external queues can take,
1327 * so we'd lock up if we pushed all accumulated data for stream N in one go) */
1329 gst_asf_demux_find_stream_with_complete_payload (GstASFDemux * demux)
1331 AsfPayload *best_payload = NULL;
1332 AsfStream *best_stream = NULL;
1335 for (i = 0; i < demux->num_streams; ++i) {
1338 stream = &demux->stream[i];
1340 /* Don't push any data until we have at least one payload that falls within
1341 * the current segment. This way we can remove out-of-segment payloads that
1342 * don't need to be decoded after a seek, sending only data from the
1343 * keyframe directly before our segment start */
1344 if (stream->payloads->len > 0) {
1345 AsfPayload *payload;
1348 last_idx = stream->payloads->len - 1;
1349 payload = &g_array_index (stream->payloads, AsfPayload, last_idx);
1350 if (G_UNLIKELY (GST_CLOCK_TIME_IS_VALID (payload->ts) &&
1351 (payload->ts < demux->segment.start))) {
1352 if (G_UNLIKELY ((!demux->accurate) && payload->keyframe)) {
1353 GST_DEBUG_OBJECT (stream->pad,
1354 "Found keyframe, updating segment start to %" GST_TIME_FORMAT,
1355 GST_TIME_ARGS (payload->ts));
1356 demux->segment.start = payload->ts;
1357 demux->segment.time = payload->ts;
1359 GST_DEBUG_OBJECT (stream->pad, "Last queued payload has timestamp %"
1360 GST_TIME_FORMAT " which is before our segment start %"
1361 GST_TIME_FORMAT ", not pushing yet", GST_TIME_ARGS (payload->ts),
1362 GST_TIME_ARGS (demux->segment.start));
1367 /* Now see if there's a complete payload queued for this stream */
1369 payload = &g_array_index (stream->payloads, AsfPayload, 0);
1370 if (!gst_asf_payload_is_complete (payload))
1373 /* ... and whether its timestamp is lower than the current best */
1374 if (best_stream == NULL || best_payload->ts > payload->ts) {
1375 best_stream = stream;
1376 best_payload = payload;
1384 static GstFlowReturn
1385 gst_asf_demux_push_complete_payloads (GstASFDemux * demux, gboolean force)
1388 GstFlowReturn ret = GST_FLOW_OK;
1390 if (G_UNLIKELY (!demux->activated_streams)) {
1391 if (!gst_asf_demux_check_activate_streams (demux, force))
1393 /* streams are now activated */
1396 /* wait until we had a chance to "lock on" some payload's timestamp */
1397 if (G_UNLIKELY (demux->need_newsegment
1398 && !GST_CLOCK_TIME_IS_VALID (demux->segment_ts)))
1401 while ((stream = gst_asf_demux_find_stream_with_complete_payload (demux))) {
1402 AsfPayload *payload;
1404 payload = &g_array_index (stream->payloads, AsfPayload, 0);
1406 /* do we need to send a newsegment event */
1407 if ((G_UNLIKELY (demux->need_newsegment))) {
1409 /* safe default if insufficient upstream info */
1410 if (!GST_CLOCK_TIME_IS_VALID (demux->in_gap))
1413 if (demux->segment.stop == GST_CLOCK_TIME_NONE &&
1414 demux->segment.duration > 0) {
1415 /* slight HACK; prevent clipping of last bit */
1416 demux->segment.stop = demux->segment.duration + demux->in_gap;
1419 /* FIXME : only if ACCURATE ! */
1420 if (G_LIKELY (!demux->accurate
1421 && (GST_CLOCK_TIME_IS_VALID (payload->ts)))) {
1422 GST_DEBUG ("Adjusting newsegment start to %" GST_TIME_FORMAT,
1423 GST_TIME_ARGS (payload->ts));
1424 demux->segment.start = payload->ts;
1425 demux->segment.time = payload->ts;
1428 GST_DEBUG_OBJECT (demux, "sending new-segment event %" GST_SEGMENT_FORMAT,
1431 /* note: we fix up all timestamps to start from 0, so this should be ok */
1432 gst_asf_demux_send_event_unlocked (demux,
1433 gst_event_new_segment (&demux->segment));
1435 /* now post any global tags we may have found */
1436 if (demux->taglist == NULL) {
1437 demux->taglist = gst_tag_list_new_empty ();
1438 gst_tag_list_set_scope (demux->taglist, GST_TAG_SCOPE_GLOBAL);
1441 gst_tag_list_add (demux->taglist, GST_TAG_MERGE_REPLACE,
1442 GST_TAG_CONTAINER_FORMAT, "ASF", NULL);
1444 GST_DEBUG_OBJECT (demux, "global tags: %" GST_PTR_FORMAT, demux->taglist);
1445 gst_asf_demux_send_event_unlocked (demux,
1446 gst_event_new_tag (demux->taglist));
1447 demux->taglist = NULL;
1449 demux->need_newsegment = FALSE;
1450 demux->segment_running = TRUE;
1453 /* Do we have tags pending for this stream? */
1454 if (G_UNLIKELY (stream->pending_tags)) {
1455 GST_LOG_OBJECT (stream->pad, "%" GST_PTR_FORMAT, stream->pending_tags);
1456 gst_pad_push_event (stream->pad,
1457 gst_event_new_tag (stream->pending_tags));
1458 stream->pending_tags = NULL;
1461 /* We have the whole packet now so we should push the packet to
1462 * the src pad now. First though we should check if we need to do
1464 if (G_UNLIKELY (demux->span > 1)) {
1465 gst_asf_demux_descramble_buffer (demux, stream, &payload->buf);
1468 payload->buf = gst_buffer_make_writable (payload->buf);
1470 if (G_LIKELY (!payload->keyframe)) {
1471 GST_BUFFER_FLAG_SET (payload->buf, GST_BUFFER_FLAG_DELTA_UNIT);
1474 if (G_UNLIKELY (stream->discont)) {
1475 GST_DEBUG_OBJECT (stream->pad, "marking DISCONT on stream");
1476 GST_BUFFER_FLAG_SET (payload->buf, GST_BUFFER_FLAG_DISCONT);
1477 stream->discont = FALSE;
1480 if (G_UNLIKELY (stream->is_video && payload->par_x && payload->par_y &&
1481 (payload->par_x != stream->par_x) &&
1482 (payload->par_y != stream->par_y))) {
1483 GST_DEBUG ("Updating PAR (%d/%d => %d/%d)",
1484 stream->par_x, stream->par_y, payload->par_x, payload->par_y);
1485 stream->par_x = payload->par_x;
1486 stream->par_y = payload->par_y;
1487 stream->caps = gst_caps_make_writable (stream->caps);
1488 gst_caps_set_simple (stream->caps, "pixel-aspect-ratio",
1489 GST_TYPE_FRACTION, stream->par_x, stream->par_y, NULL);
1490 gst_pad_set_caps (stream->pad, stream->caps);
1493 if (G_UNLIKELY (stream->interlaced != payload->interlaced)) {
1494 GST_DEBUG ("Updating interlaced status (%d => %d)", stream->interlaced,
1495 payload->interlaced);
1496 stream->interlaced = payload->interlaced;
1497 stream->caps = gst_caps_make_writable (stream->caps);
1498 gst_caps_set_simple (stream->caps, "interlace-mode", G_TYPE_BOOLEAN,
1499 (stream->interlaced ? "mixed" : "progressive"), NULL);
1500 gst_pad_set_caps (stream->pad, stream->caps);
1503 /* (sort of) interpolate timestamps using upstream "frame of reference",
1504 * typically useful for live src, but might (unavoidably) mess with
1505 * position reporting if a live src is playing not so live content
1506 * (e.g. rtspsrc taking some time to fall back to tcp) */
1507 GST_BUFFER_TIMESTAMP (payload->buf) = payload->ts + demux->in_gap;
1508 if (payload->duration == GST_CLOCK_TIME_NONE
1509 && stream->ext_props.avg_time_per_frame != 0)
1510 GST_BUFFER_DURATION (payload->buf) =
1511 stream->ext_props.avg_time_per_frame * 100;
1513 GST_BUFFER_DURATION (payload->buf) = payload->duration;
1515 /* FIXME: we should really set durations on buffers if we can */
1517 GST_LOG_OBJECT (stream->pad, "pushing buffer, ts=%" GST_TIME_FORMAT
1518 ", dur=%" GST_TIME_FORMAT " size=%" G_GSIZE_FORMAT,
1519 GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (payload->buf)),
1520 GST_TIME_ARGS (GST_BUFFER_DURATION (payload->buf)),
1521 gst_buffer_get_size (payload->buf));
1523 if (stream->active) {
1524 ret = gst_pad_push (stream->pad, payload->buf);
1525 ret = gst_asf_demux_aggregate_flow_return (demux, stream, ret);
1527 gst_buffer_unref (payload->buf);
1530 payload->buf = NULL;
1531 g_array_remove_index (stream->payloads, 0);
1533 /* Break out as soon as we have an issue */
1534 if (G_UNLIKELY (ret != GST_FLOW_OK))
1542 gst_asf_demux_check_buffer_is_header (GstASFDemux * demux, GstBuffer * buf)
1546 g_assert (buf != NULL);
1548 GST_LOG_OBJECT (demux, "Checking if buffer is a header");
1550 gst_buffer_map (buf, &map, GST_MAP_READ);
1552 /* we return false on buffer too small */
1553 if (map.size < ASF_OBJECT_HEADER_SIZE) {
1554 gst_buffer_unmap (buf, &map);
1558 /* check if it is a header */
1559 asf_demux_peek_object (demux, map.data, ASF_OBJECT_HEADER_SIZE, &obj, TRUE);
1560 gst_buffer_unmap (buf, &map);
1561 if (obj.id == ASF_OBJ_HEADER) {
1568 gst_asf_demux_check_chained_asf (GstASFDemux * demux)
1570 guint64 off = demux->data_offset + (demux->packet * demux->packet_size);
1571 GstFlowReturn ret = GST_FLOW_OK;
1572 GstBuffer *buf = NULL;
1573 gboolean header = FALSE;
1575 /* TODO maybe we should skip index objects after the data and look
1576 * further for a new header */
1577 if (gst_asf_demux_pull_data (demux, off, ASF_OBJECT_HEADER_SIZE, &buf, &ret)) {
1578 g_assert (buf != NULL);
1579 /* check if it is a header */
1580 if (gst_asf_demux_check_buffer_is_header (demux, buf)) {
1581 GST_DEBUG_OBJECT (demux, "new base offset: %" G_GUINT64_FORMAT, off);
1582 demux->base_offset = off;
1586 gst_buffer_unref (buf);
1593 gst_asf_demux_loop (GstASFDemux * demux)
1595 GstFlowReturn flow = GST_FLOW_OK;
1596 GstBuffer *buf = NULL;
1598 gboolean sent_eos = FALSE;
1600 if (G_UNLIKELY (demux->state == GST_ASF_DEMUX_STATE_HEADER)) {
1601 if (!gst_asf_demux_pull_headers (demux)) {
1602 flow = GST_FLOW_ERROR;
1606 gst_asf_demux_pull_indices (demux);
1609 g_assert (demux->state == GST_ASF_DEMUX_STATE_DATA);
1611 if (G_UNLIKELY (demux->num_packets != 0
1612 && demux->packet >= demux->num_packets))
1615 GST_LOG_OBJECT (demux, "packet %u/%u", (guint) demux->packet + 1,
1616 (guint) demux->num_packets);
1618 off = demux->data_offset + (demux->packet * demux->packet_size);
1620 if (G_UNLIKELY (!gst_asf_demux_pull_data (demux, off,
1621 demux->packet_size * demux->speed_packets, &buf, &flow))) {
1622 GST_DEBUG_OBJECT (demux, "got flow %s", gst_flow_get_name (flow));
1623 if (flow == GST_FLOW_EOS)
1625 else if (flow == GST_FLOW_FLUSHING) {
1626 GST_DEBUG_OBJECT (demux, "Not fatal");
1632 if (G_LIKELY (demux->speed_packets == 1)) {
1633 GstAsfDemuxParsePacketError err;
1634 err = gst_asf_demux_parse_packet (demux, buf);
1635 if (G_UNLIKELY (err != GST_ASF_DEMUX_PARSE_PACKET_ERROR_NONE)) {
1636 /* when we don't know when the data object ends, we should check
1637 * for a chained asf */
1638 if (demux->num_packets == 0) {
1639 if (gst_asf_demux_check_buffer_is_header (demux, buf)) {
1640 GST_INFO_OBJECT (demux, "Chained asf found");
1641 demux->base_offset = off;
1642 gst_asf_demux_reset (demux, TRUE);
1643 gst_buffer_unref (buf);
1647 /* FIXME: We should tally up fatal errors and error out only
1648 * after a few broken packets in a row? */
1650 GST_INFO_OBJECT (demux, "Ignoring recoverable parse error");
1651 gst_buffer_unref (buf);
1656 flow = gst_asf_demux_push_complete_payloads (demux, FALSE);
1662 for (n = 0; n < demux->speed_packets; n++) {
1664 GstAsfDemuxParsePacketError err;
1667 gst_buffer_copy_region (buf, GST_BUFFER_COPY_ALL,
1668 n * demux->packet_size, demux->packet_size);
1669 err = gst_asf_demux_parse_packet (demux, sub);
1670 if (G_UNLIKELY (err != GST_ASF_DEMUX_PARSE_PACKET_ERROR_NONE)) {
1671 /* when we don't know when the data object ends, we should check
1672 * for a chained asf */
1673 if (demux->num_packets == 0) {
1674 if (gst_asf_demux_check_buffer_is_header (demux, sub)) {
1675 GST_INFO_OBJECT (demux, "Chained asf found");
1676 demux->base_offset = off + n * demux->packet_size;
1677 gst_asf_demux_reset (demux, TRUE);
1678 gst_buffer_unref (sub);
1679 gst_buffer_unref (buf);
1683 /* FIXME: We should tally up fatal errors and error out only
1684 * after a few broken packets in a row? */
1686 GST_INFO_OBJECT (demux, "Ignoring recoverable parse error");
1690 gst_buffer_unref (sub);
1692 if (err == GST_ASF_DEMUX_PARSE_PACKET_ERROR_NONE)
1693 flow = gst_asf_demux_push_complete_payloads (demux, FALSE);
1699 /* reset speed pull */
1700 demux->speed_packets = 1;
1703 gst_buffer_unref (buf);
1705 if (G_UNLIKELY (demux->num_packets > 0
1706 && demux->packet >= demux->num_packets)) {
1707 GST_LOG_OBJECT (demux, "reached EOS");
1711 if (G_UNLIKELY (flow != GST_FLOW_OK)) {
1712 GST_DEBUG_OBJECT (demux, "pushing complete payloads failed");
1716 /* check if we're at the end of the configured segment */
1717 /* FIXME: check if segment end reached etc. */
1723 /* if we haven't activated our streams yet, this might be because we have
1724 * less data queued than required for preroll; force stream activation and
1725 * send any pending payloads before sending EOS */
1726 if (!demux->activated_streams)
1727 gst_asf_demux_push_complete_payloads (demux, TRUE);
1729 /* we want to push an eos or post a segment-done in any case */
1730 if (demux->segment.flags & GST_SEEK_FLAG_SEGMENT) {
1733 /* for segment playback we need to post when (in stream time)
1734 * we stopped, this is either stop (when set) or the duration. */
1735 if ((stop = demux->segment.stop) == -1)
1736 stop = demux->segment.duration;
1738 GST_INFO_OBJECT (demux, "Posting segment-done, at end of segment");
1739 gst_element_post_message (GST_ELEMENT_CAST (demux),
1740 gst_message_new_segment_done (GST_OBJECT (demux), GST_FORMAT_TIME,
1742 gst_asf_demux_send_event_unlocked (demux,
1743 gst_event_new_segment_done (GST_FORMAT_TIME, stop));
1744 } else if (flow != GST_FLOW_EOS) {
1745 /* check if we have a chained asf, in case, we don't eos yet */
1746 if (gst_asf_demux_check_chained_asf (demux)) {
1747 GST_INFO_OBJECT (demux, "Chained ASF starting");
1748 gst_asf_demux_reset (demux, TRUE);
1752 /* normal playback, send EOS to all linked pads */
1753 GST_INFO_OBJECT (demux, "Sending EOS, at end of stream");
1754 gst_asf_demux_send_event_unlocked (demux, gst_event_new_eos ());
1756 /* ... and fall through to pause */
1760 GST_DEBUG_OBJECT (demux, "pausing task, flow return: %s",
1761 gst_flow_get_name (flow));
1762 demux->segment_running = FALSE;
1763 gst_pad_pause_task (demux->sinkpad);
1765 /* For the error cases (not EOS) */
1767 if (flow == GST_FLOW_EOS)
1768 gst_asf_demux_send_event_unlocked (demux, gst_event_new_eos ());
1769 else if (flow < GST_FLOW_EOS || flow == GST_FLOW_NOT_LINKED) {
1770 /* Post an error. Hopefully something else already has, but if not... */
1771 GST_ELEMENT_ERROR (demux, STREAM, FAILED,
1772 (_("Internal data stream error.")),
1773 ("streaming stopped, reason %s", gst_flow_get_name (flow)));
1782 GST_DEBUG_OBJECT (demux, "Read failed, doh");
1783 gst_asf_demux_send_event_unlocked (demux, gst_event_new_eos ());
1784 flow = GST_FLOW_EOS;
1788 /* See FIXMEs above */
1791 gst_buffer_unref (buf);
1792 GST_ELEMENT_ERROR (demux, STREAM, DEMUX, (NULL),
1793 ("Error parsing ASF packet %u", (guint) demux->packet));
1794 gst_asf_demux_send_event_unlocked (demux, gst_event_new_eos ());
1795 flow = GST_FLOW_ERROR;
1801 #define GST_ASF_DEMUX_CHECK_HEADER_YES 0
1802 #define GST_ASF_DEMUX_CHECK_HEADER_NO 1
1803 #define GST_ASF_DEMUX_CHECK_HEADER_NEED_DATA 2
1806 gst_asf_demux_check_header (GstASFDemux * demux)
1809 guint8 *cdata = (guint8 *) gst_adapter_map (demux->adapter,
1810 ASF_OBJECT_HEADER_SIZE);
1811 if (cdata == NULL) /* need more data */
1812 return GST_ASF_DEMUX_CHECK_HEADER_NEED_DATA;
1814 asf_demux_peek_object (demux, cdata, ASF_OBJECT_HEADER_SIZE, &obj, FALSE);
1815 if (obj.id != ASF_OBJ_HEADER) {
1816 return GST_ASF_DEMUX_CHECK_HEADER_NO;
1818 return GST_ASF_DEMUX_CHECK_HEADER_YES;
1822 static GstFlowReturn
1823 gst_asf_demux_chain (GstPad * pad, GstObject * parent, GstBuffer * buf)
1825 GstFlowReturn ret = GST_FLOW_OK;
1828 demux = GST_ASF_DEMUX (parent);
1830 GST_LOG_OBJECT (demux,
1831 "buffer: size=%" G_GSIZE_FORMAT ", offset=%" G_GINT64_FORMAT ", time=%"
1832 GST_TIME_FORMAT, gst_buffer_get_size (buf), GST_BUFFER_OFFSET (buf),
1833 GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)));
1835 if (G_UNLIKELY (GST_BUFFER_IS_DISCONT (buf))) {
1836 GST_DEBUG_OBJECT (demux, "received DISCONT");
1837 gst_asf_demux_mark_discont (demux);
1840 if (G_UNLIKELY ((!GST_CLOCK_TIME_IS_VALID (demux->in_gap) &&
1841 GST_BUFFER_TIMESTAMP_IS_VALID (buf)))) {
1842 demux->in_gap = GST_BUFFER_TIMESTAMP (buf) - demux->in_segment.start;
1843 GST_DEBUG_OBJECT (demux, "upstream segment start %" GST_TIME_FORMAT
1844 ", interpolation gap: %" GST_TIME_FORMAT,
1845 GST_TIME_ARGS (demux->in_segment.start), GST_TIME_ARGS (demux->in_gap));
1848 gst_adapter_push (demux->adapter, buf);
1850 switch (demux->state) {
1851 case GST_ASF_DEMUX_STATE_INDEX:{
1852 gint result = gst_asf_demux_check_header (demux);
1853 if (result == GST_ASF_DEMUX_CHECK_HEADER_NEED_DATA) /* need more data */
1856 if (result == GST_ASF_DEMUX_CHECK_HEADER_NO) {
1857 /* we don't care about this, probably an index */
1858 /* TODO maybe would be smarter to skip all the indices
1859 * until we got a new header or EOS to decide */
1860 GST_LOG_OBJECT (demux, "Received index object, its EOS");
1863 GST_INFO_OBJECT (demux, "Chained asf starting");
1864 /* cleanup and get ready for a chained asf */
1865 gst_asf_demux_reset (demux, TRUE);
1869 case GST_ASF_DEMUX_STATE_HEADER:{
1870 ret = gst_asf_demux_chain_headers (demux);
1871 if (demux->state != GST_ASF_DEMUX_STATE_DATA)
1873 /* otherwise fall through */
1875 case GST_ASF_DEMUX_STATE_DATA:
1879 data_size = demux->packet_size;
1881 while (gst_adapter_available (demux->adapter) >= data_size) {
1883 GstAsfDemuxParsePacketError err;
1885 /* we don't know the length of the stream
1886 * check for a chained asf everytime */
1887 if (demux->num_packets == 0) {
1888 gint result = gst_asf_demux_check_header (demux);
1890 if (result == GST_ASF_DEMUX_CHECK_HEADER_YES) {
1891 GST_INFO_OBJECT (demux, "Chained asf starting");
1892 /* cleanup and get ready for a chained asf */
1893 gst_asf_demux_reset (demux, TRUE);
1896 } else if (G_UNLIKELY (demux->num_packets != 0 && demux->packet >= 0
1897 && demux->packet >= demux->num_packets)) {
1898 /* do not overshoot data section when streaming */
1902 buf = gst_adapter_take_buffer (demux->adapter, data_size);
1904 /* FIXME: We should tally up fatal errors and error out only
1905 * after a few broken packets in a row? */
1906 err = gst_asf_demux_parse_packet (demux, buf);
1908 gst_buffer_unref (buf);
1910 if (G_LIKELY (err == GST_ASF_DEMUX_PARSE_PACKET_ERROR_NONE))
1911 ret = gst_asf_demux_push_complete_payloads (demux, FALSE);
1913 GST_WARNING_OBJECT (demux, "Parse error");
1915 if (demux->packet >= 0)
1918 if (G_UNLIKELY (demux->num_packets != 0 && demux->packet >= 0
1919 && demux->packet >= demux->num_packets)) {
1920 demux->state = GST_ASF_DEMUX_STATE_INDEX;
1925 g_assert_not_reached ();
1929 if (ret != GST_FLOW_OK)
1930 GST_DEBUG_OBJECT (demux, "flow: %s", gst_flow_get_name (ret));
1936 GST_DEBUG_OBJECT (demux, "Handled last packet, setting EOS");
1942 static inline gboolean
1943 gst_asf_demux_skip_bytes (guint num_bytes, guint8 ** p_data, guint64 * p_size)
1945 if (*p_size < num_bytes)
1948 *p_data += num_bytes;
1949 *p_size -= num_bytes;
1953 static inline guint8
1954 gst_asf_demux_get_uint8 (guint8 ** p_data, guint64 * p_size)
1958 g_assert (*p_size >= 1);
1959 ret = GST_READ_UINT8 (*p_data);
1960 *p_data += sizeof (guint8);
1961 *p_size -= sizeof (guint8);
1965 static inline guint16
1966 gst_asf_demux_get_uint16 (guint8 ** p_data, guint64 * p_size)
1970 g_assert (*p_size >= 2);
1971 ret = GST_READ_UINT16_LE (*p_data);
1972 *p_data += sizeof (guint16);
1973 *p_size -= sizeof (guint16);
1977 static inline guint32
1978 gst_asf_demux_get_uint32 (guint8 ** p_data, guint64 * p_size)
1982 g_assert (*p_size >= 4);
1983 ret = GST_READ_UINT32_LE (*p_data);
1984 *p_data += sizeof (guint32);
1985 *p_size -= sizeof (guint32);
1989 static inline guint64
1990 gst_asf_demux_get_uint64 (guint8 ** p_data, guint64 * p_size)
1994 g_assert (*p_size >= 8);
1995 ret = GST_READ_UINT64_LE (*p_data);
1996 *p_data += sizeof (guint64);
1997 *p_size -= sizeof (guint64);
2001 static inline guint32
2002 gst_asf_demux_get_var_length (guint8 type, guint8 ** p_data, guint64 * p_size)
2009 g_assert (*p_size >= 1);
2010 return gst_asf_demux_get_uint8 (p_data, p_size);
2013 g_assert (*p_size >= 2);
2014 return gst_asf_demux_get_uint16 (p_data, p_size);
2017 g_assert (*p_size >= 4);
2018 return gst_asf_demux_get_uint32 (p_data, p_size);
2021 g_assert_not_reached ();
2028 gst_asf_demux_get_buffer (GstBuffer ** p_buf, guint num_bytes_to_read,
2029 guint8 ** p_data, guint64 * p_size)
2033 if (*p_size < num_bytes_to_read)
2036 *p_buf = gst_buffer_new_and_alloc (num_bytes_to_read);
2037 gst_buffer_fill (*p_buf, 0, *p_data, num_bytes_to_read);
2039 *p_data += num_bytes_to_read;
2040 *p_size -= num_bytes_to_read;
2046 gst_asf_demux_get_bytes (guint8 ** p_buf, guint num_bytes_to_read,
2047 guint8 ** p_data, guint64 * p_size)
2051 if (*p_size < num_bytes_to_read)
2054 *p_buf = g_memdup (*p_data, num_bytes_to_read);
2055 *p_data += num_bytes_to_read;
2056 *p_size -= num_bytes_to_read;
2061 gst_asf_demux_get_string (gchar ** p_str, guint16 * p_strlen,
2062 guint8 ** p_data, guint64 * p_size)
2072 s_length = gst_asf_demux_get_uint16 (p_data, p_size);
2075 *p_strlen = s_length;
2077 if (s_length == 0) {
2078 GST_WARNING ("zero-length string");
2079 *p_str = g_strdup ("");
2083 if (!gst_asf_demux_get_bytes (&s, s_length, p_data, p_size))
2086 g_assert (s != NULL);
2088 /* just because They don't exist doesn't
2089 * mean They are not out to get you ... */
2090 if (s[s_length - 1] != '\0') {
2091 s = g_realloc (s, s_length + 1);
2095 *p_str = (gchar *) s;
2101 gst_asf_demux_get_guid (ASFGuid * guid, guint8 ** p_data, guint64 * p_size)
2103 g_assert (*p_size >= 4 * sizeof (guint32));
2105 guid->v1 = gst_asf_demux_get_uint32 (p_data, p_size);
2106 guid->v2 = gst_asf_demux_get_uint32 (p_data, p_size);
2107 guid->v3 = gst_asf_demux_get_uint32 (p_data, p_size);
2108 guid->v4 = gst_asf_demux_get_uint32 (p_data, p_size);
2112 gst_asf_demux_get_stream_audio (asf_stream_audio * audio, guint8 ** p_data,
2115 if (*p_size < (2 + 2 + 4 + 4 + 2 + 2 + 2))
2118 /* WAVEFORMATEX Structure */
2119 audio->codec_tag = gst_asf_demux_get_uint16 (p_data, p_size);
2120 audio->channels = gst_asf_demux_get_uint16 (p_data, p_size);
2121 audio->sample_rate = gst_asf_demux_get_uint32 (p_data, p_size);
2122 audio->byte_rate = gst_asf_demux_get_uint32 (p_data, p_size);
2123 audio->block_align = gst_asf_demux_get_uint16 (p_data, p_size);
2124 audio->word_size = gst_asf_demux_get_uint16 (p_data, p_size);
2125 /* Codec specific data size */
2126 audio->size = gst_asf_demux_get_uint16 (p_data, p_size);
2131 gst_asf_demux_get_stream_video (asf_stream_video * video, guint8 ** p_data,
2134 if (*p_size < (4 + 4 + 1 + 2))
2137 video->width = gst_asf_demux_get_uint32 (p_data, p_size);
2138 video->height = gst_asf_demux_get_uint32 (p_data, p_size);
2139 video->unknown = gst_asf_demux_get_uint8 (p_data, p_size);
2140 video->size = gst_asf_demux_get_uint16 (p_data, p_size);
2145 gst_asf_demux_get_stream_video_format (asf_stream_video_format * fmt,
2146 guint8 ** p_data, guint64 * p_size)
2148 if (*p_size < (4 + 4 + 4 + 2 + 2 + 4 + 4 + 4 + 4 + 4 + 4))
2151 fmt->size = gst_asf_demux_get_uint32 (p_data, p_size);
2152 fmt->width = gst_asf_demux_get_uint32 (p_data, p_size);
2153 fmt->height = gst_asf_demux_get_uint32 (p_data, p_size);
2154 fmt->planes = gst_asf_demux_get_uint16 (p_data, p_size);
2155 fmt->depth = gst_asf_demux_get_uint16 (p_data, p_size);
2156 fmt->tag = gst_asf_demux_get_uint32 (p_data, p_size);
2157 fmt->image_size = gst_asf_demux_get_uint32 (p_data, p_size);
2158 fmt->xpels_meter = gst_asf_demux_get_uint32 (p_data, p_size);
2159 fmt->ypels_meter = gst_asf_demux_get_uint32 (p_data, p_size);
2160 fmt->num_colors = gst_asf_demux_get_uint32 (p_data, p_size);
2161 fmt->imp_colors = gst_asf_demux_get_uint32 (p_data, p_size);
2166 gst_asf_demux_get_stream (GstASFDemux * demux, guint16 id)
2170 for (i = 0; i < demux->num_streams; i++) {
2171 if (demux->stream[i].id == id)
2172 return &demux->stream[i];
2175 GST_WARNING ("Segment found for undefined stream: (%d)", id);
2180 gst_asf_demux_setup_pad (GstASFDemux * demux, GstPad * src_pad,
2181 GstCaps * caps, guint16 id, gboolean is_video, GstTagList * tags)
2185 gst_pad_use_fixed_caps (src_pad);
2186 gst_pad_set_caps (src_pad, caps);
2188 gst_pad_set_event_function (src_pad,
2189 GST_DEBUG_FUNCPTR (gst_asf_demux_handle_src_event));
2190 gst_pad_set_query_function (src_pad,
2191 GST_DEBUG_FUNCPTR (gst_asf_demux_handle_src_query));
2193 stream = &demux->stream[demux->num_streams];
2194 stream->caps = caps;
2195 stream->pad = src_pad;
2197 stream->fps_known = !is_video; /* bit hacky for audio */
2198 stream->is_video = is_video;
2199 stream->pending_tags = tags;
2200 stream->discont = TRUE;
2204 st = gst_caps_get_structure (caps, 0);
2205 if (gst_structure_get_fraction (st, "pixel-aspect-ratio", &par_x, &par_y) &&
2206 par_x > 0 && par_y > 0) {
2207 GST_DEBUG ("PAR %d/%d", par_x, par_y);
2208 stream->par_x = par_x;
2209 stream->par_y = par_y;
2213 stream->payloads = g_array_new (FALSE, FALSE, sizeof (AsfPayload));
2215 GST_INFO ("Created pad %s for stream %u with caps %" GST_PTR_FORMAT,
2216 GST_PAD_NAME (src_pad), demux->num_streams, caps);
2218 ++demux->num_streams;
2220 stream->active = FALSE;
2224 gst_asf_demux_add_audio_stream (GstASFDemux * demux,
2225 asf_stream_audio * audio, guint16 id, guint8 ** p_data, guint64 * p_size)
2227 GstTagList *tags = NULL;
2228 GstBuffer *extradata = NULL;
2231 guint16 size_left = 0;
2232 gchar *codec_name = NULL;
2235 size_left = audio->size;
2237 /* Create the audio pad */
2238 name = g_strdup_printf ("audio_%u", demux->num_audio_streams);
2240 src_pad = gst_pad_new_from_static_template (&audio_src_template, name);
2243 /* Swallow up any left over data and set up the
2244 * standard properties from the header info */
2246 GST_INFO_OBJECT (demux, "Audio header contains %d bytes of "
2247 "codec specific data", size_left);
2249 g_assert (size_left <= *p_size);
2250 gst_asf_demux_get_buffer (&extradata, size_left, p_data, p_size);
2253 /* asf_stream_audio is the same as gst_riff_strf_auds, but with an
2254 * additional two bytes indicating extradata. */
2255 /* FIXME: Handle the channel reorder map here */
2256 caps = gst_riff_create_audio_caps (audio->codec_tag, NULL,
2257 (gst_riff_strf_auds *) audio, extradata, NULL, &codec_name, NULL);
2260 caps = gst_caps_new_simple ("audio/x-asf-unknown", "codec_id",
2261 G_TYPE_INT, (gint) audio->codec_tag, NULL);
2264 /* Informing about that audio format we just added */
2266 tags = gst_tag_list_new (GST_TAG_AUDIO_CODEC, codec_name, NULL);
2267 g_free (codec_name);
2271 gst_buffer_unref (extradata);
2273 GST_INFO ("Adding audio stream #%u, id %u codec %u (0x%04x), tags=%"
2274 GST_PTR_FORMAT, demux->num_audio_streams, id, audio->codec_tag,
2275 audio->codec_tag, tags);
2277 ++demux->num_audio_streams;
2279 gst_asf_demux_setup_pad (demux, src_pad, caps, id, FALSE, tags);
2283 gst_asf_demux_add_video_stream (GstASFDemux * demux,
2284 asf_stream_video_format * video, guint16 id,
2285 guint8 ** p_data, guint64 * p_size)
2287 GstTagList *tags = NULL;
2288 GstBuffer *extradata = NULL;
2293 gchar *codec_name = NULL;
2294 gint size_left = video->size - 40;
2296 /* Create the video pad */
2297 name = g_strdup_printf ("video_%u", demux->num_video_streams);
2298 src_pad = gst_pad_new_from_static_template (&video_src_template, name);
2301 /* Now try some gstreamer formatted MIME types (from gst_avi_demux_strf_vids) */
2303 GST_LOG ("Video header has %d bytes of codec specific data", size_left);
2304 g_assert (size_left <= *p_size);
2305 gst_asf_demux_get_buffer (&extradata, size_left, p_data, p_size);
2308 GST_DEBUG ("video codec %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (video->tag));
2310 /* yes, asf_stream_video_format and gst_riff_strf_vids are the same */
2311 caps = gst_riff_create_video_caps (video->tag, NULL,
2312 (gst_riff_strf_vids *) video, extradata, NULL, &codec_name);
2315 caps = gst_caps_new_simple ("video/x-asf-unknown", "fourcc",
2316 G_TYPE_UINT, video->tag, NULL);
2321 s = gst_asf_demux_get_metadata_for_stream (demux, id);
2322 if (gst_structure_get_int (s, "AspectRatioX", &ax) &&
2323 gst_structure_get_int (s, "AspectRatioY", &ay) && (ax > 0 && ay > 0)) {
2324 gst_caps_set_simple (caps, "pixel-aspect-ratio", GST_TYPE_FRACTION,
2329 /* retry with the global metadata */
2330 GST_DEBUG ("Retrying with global metadata %" GST_PTR_FORMAT,
2331 demux->global_metadata);
2332 s = demux->global_metadata;
2333 if (gst_structure_get_uint (s, "AspectRatioX", &ax) &&
2334 gst_structure_get_uint (s, "AspectRatioY", &ay)) {
2335 GST_DEBUG ("ax:%d, ay:%d", ax, ay);
2336 if (ax > 0 && ay > 0)
2337 gst_caps_set_simple (caps, "pixel-aspect-ratio", GST_TYPE_FRACTION,
2341 s = gst_caps_get_structure (caps, 0);
2342 gst_structure_remove_field (s, "framerate");
2345 /* add fourcc format to caps, some proprietary decoders seem to need it */
2346 str = g_strdup_printf ("%" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (video->tag));
2347 gst_caps_set_simple (caps, "format", G_TYPE_STRING, str, NULL);
2351 tags = gst_tag_list_new (GST_TAG_VIDEO_CODEC, codec_name, NULL);
2352 g_free (codec_name);
2356 gst_buffer_unref (extradata);
2358 GST_INFO ("Adding video stream #%u, id %u, codec %"
2359 GST_FOURCC_FORMAT " (0x%08x)", demux->num_video_streams, id,
2360 GST_FOURCC_ARGS (video->tag), video->tag);
2362 ++demux->num_video_streams;
2364 gst_asf_demux_setup_pad (demux, src_pad, caps, id, TRUE, tags);
2368 gst_asf_demux_activate_stream (GstASFDemux * demux, AsfStream * stream)
2370 if (!stream->active) {
2373 GST_INFO_OBJECT (demux, "Activating stream %2u, pad %s, caps %"
2374 GST_PTR_FORMAT, stream->id, GST_PAD_NAME (stream->pad), stream->caps);
2375 gst_pad_set_active (stream->pad, TRUE);
2378 gst_pad_create_stream_id_printf (stream->pad, GST_ELEMENT_CAST (demux),
2380 gst_pad_push_event (stream->pad, gst_event_new_stream_start (stream_id));
2382 gst_pad_set_caps (stream->pad, stream->caps);
2384 gst_element_add_pad (GST_ELEMENT_CAST (demux), stream->pad);
2385 stream->active = TRUE;
2390 gst_asf_demux_parse_stream_object (GstASFDemux * demux, guint8 * data,
2393 AsfCorrectionType correction_type;
2394 AsfStreamType stream_type;
2395 GstClockTime time_offset;
2396 gboolean is_encrypted G_GNUC_UNUSED;
2400 guint stream_specific_size;
2401 guint type_specific_size G_GNUC_UNUSED;
2402 guint unknown G_GNUC_UNUSED;
2404 /* Get the rest of the header's header */
2405 if (size < (16 + 16 + 8 + 4 + 4 + 2 + 4))
2406 goto not_enough_data;
2408 gst_asf_demux_get_guid (&guid, &data, &size);
2409 stream_type = gst_asf_demux_identify_guid (asf_stream_guids, &guid);
2411 gst_asf_demux_get_guid (&guid, &data, &size);
2412 correction_type = gst_asf_demux_identify_guid (asf_correction_guids, &guid);
2414 time_offset = gst_asf_demux_get_uint64 (&data, &size) * 100;
2416 type_specific_size = gst_asf_demux_get_uint32 (&data, &size);
2417 stream_specific_size = gst_asf_demux_get_uint32 (&data, &size);
2419 flags = gst_asf_demux_get_uint16 (&data, &size);
2420 stream_id = flags & 0x7f;
2421 is_encrypted = ! !((flags & 0x8000) << 15);
2422 unknown = gst_asf_demux_get_uint32 (&data, &size);
2424 GST_DEBUG_OBJECT (demux, "Found stream %u, time_offset=%" GST_TIME_FORMAT,
2425 stream_id, GST_TIME_ARGS (time_offset));
2427 switch (stream_type) {
2428 case ASF_STREAM_AUDIO:{
2429 asf_stream_audio audio_object;
2431 if (!gst_asf_demux_get_stream_audio (&audio_object, &data, &size))
2432 goto not_enough_data;
2434 GST_INFO ("Object is an audio stream with %u bytes of additional data",
2437 gst_asf_demux_add_audio_stream (demux, &audio_object, stream_id,
2440 switch (correction_type) {
2441 case ASF_CORRECTION_ON:{
2442 guint span, packet_size, chunk_size, data_size, silence_data;
2444 GST_INFO ("Using error correction");
2446 if (size < (1 + 2 + 2 + 2 + 1))
2447 goto not_enough_data;
2449 span = gst_asf_demux_get_uint8 (&data, &size);
2450 packet_size = gst_asf_demux_get_uint16 (&data, &size);
2451 chunk_size = gst_asf_demux_get_uint16 (&data, &size);
2452 data_size = gst_asf_demux_get_uint16 (&data, &size);
2453 silence_data = gst_asf_demux_get_uint8 (&data, &size);
2455 /* FIXME: shouldn't this be per-stream? */
2458 GST_DEBUG_OBJECT (demux, "Descrambling ps:%u cs:%u ds:%u s:%u sd:%u",
2459 packet_size, chunk_size, data_size, span, silence_data);
2461 if (demux->span > 1) {
2462 if (chunk_size == 0 || ((packet_size / chunk_size) <= 1)) {
2463 /* Disable descrambling */
2466 /* FIXME: this else branch was added for
2467 * weird_al_yankovic - the saga begins.asf */
2468 demux->ds_packet_size = packet_size;
2469 demux->ds_chunk_size = chunk_size;
2472 /* Descambling is enabled */
2473 demux->ds_packet_size = packet_size;
2474 demux->ds_chunk_size = chunk_size;
2477 /* Now skip the rest of the silence data */
2479 gst_bytestream_flush (demux->bs, data_size - 1);
2481 /* FIXME: CHECKME. And why -1? */
2482 if (data_size > 1) {
2483 if (!gst_asf_demux_skip_bytes (data_size - 1, &data, &size)) {
2484 goto not_enough_data;
2490 case ASF_CORRECTION_OFF:{
2491 GST_INFO ("Error correction off");
2492 if (!gst_asf_demux_skip_bytes (stream_specific_size, &data, &size))
2493 goto not_enough_data;
2497 GST_ELEMENT_ERROR (demux, STREAM, DEMUX, (NULL),
2498 ("Audio stream using unknown error correction"));
2505 case ASF_STREAM_VIDEO:{
2506 asf_stream_video_format video_format_object;
2507 asf_stream_video video_object;
2510 if (!gst_asf_demux_get_stream_video (&video_object, &data, &size))
2511 goto not_enough_data;
2513 vsize = video_object.size - 40; /* Byte order gets offset by single byte */
2515 GST_INFO ("object is a video stream with %u bytes of "
2516 "additional data", vsize);
2518 if (!gst_asf_demux_get_stream_video_format (&video_format_object,
2520 goto not_enough_data;
2523 gst_asf_demux_add_video_stream (demux, &video_format_object, stream_id,
2530 GST_WARNING_OBJECT (demux, "Unknown stream type for stream %u",
2535 return gst_asf_demux_get_stream (demux, stream_id);
2539 GST_WARNING_OBJECT (demux, "Unexpected end of data parsing stream object");
2540 /* we'll error out later if we found no streams */
2545 static const gchar *
2546 gst_asf_demux_get_gst_tag_from_tag_name (const gchar * name_utf8)
2550 const gchar *asf_name;
2551 const gchar *gst_name;
2554 "WM/Genre", GST_TAG_GENRE}, {
2555 "WM/AlbumTitle", GST_TAG_ALBUM}, {
2556 "WM/AlbumArtist", GST_TAG_ARTIST}, {
2557 "WM/Picture", GST_TAG_IMAGE}, {
2558 "WM/Track", GST_TAG_TRACK_NUMBER}, {
2559 "WM/TrackNumber", GST_TAG_TRACK_NUMBER}, {
2560 "WM/Year", GST_TAG_DATE_TIME}
2561 /* { "WM/Composer", GST_TAG_COMPOSER } */
2566 if (name_utf8 == NULL) {
2567 GST_WARNING ("Failed to convert name to UTF8, skipping");
2571 out = strlen (name_utf8);
2573 for (i = 0; i < G_N_ELEMENTS (tags); ++i) {
2574 if (strncmp (tags[i].asf_name, name_utf8, out) == 0) {
2575 GST_LOG ("map tagname '%s' -> '%s'", name_utf8, tags[i].gst_name);
2576 return tags[i].gst_name;
2583 /* gst_asf_demux_add_global_tags() takes ownership of taglist! */
2585 gst_asf_demux_add_global_tags (GstASFDemux * demux, GstTagList * taglist)
2589 GST_DEBUG_OBJECT (demux, "adding global tags: %" GST_PTR_FORMAT, taglist);
2591 if (taglist == NULL)
2594 if (gst_tag_list_is_empty (taglist)) {
2595 gst_tag_list_unref (taglist);
2599 t = gst_tag_list_merge (demux->taglist, taglist, GST_TAG_MERGE_APPEND);
2600 gst_tag_list_set_scope (t, GST_TAG_SCOPE_GLOBAL);
2602 gst_tag_list_unref (demux->taglist);
2603 gst_tag_list_unref (taglist);
2605 GST_LOG_OBJECT (demux, "global tags now: %" GST_PTR_FORMAT, demux->taglist);
2608 #define ASF_DEMUX_DATA_TYPE_UTF16LE_STRING 0
2609 #define ASF_DEMUX_DATA_TYPE_BYTE_ARRAY 1
2610 #define ASF_DEMUX_DATA_TYPE_DWORD 3
2613 asf_demux_parse_picture_tag (GstTagList * tags, const guint8 * tag_data,
2617 const guint8 *img_data = NULL;
2618 guint32 img_data_len = 0;
2619 guint8 pic_type = 0;
2621 gst_byte_reader_init (&r, tag_data, tag_data_len);
2623 /* skip mime type string (we don't trust it and do our own typefinding),
2624 * and also skip the description string, since we don't use it */
2625 if (!gst_byte_reader_get_uint8 (&r, &pic_type) ||
2626 !gst_byte_reader_get_uint32_le (&r, &img_data_len) ||
2627 !gst_byte_reader_skip_string_utf16 (&r) ||
2628 !gst_byte_reader_skip_string_utf16 (&r) ||
2629 !gst_byte_reader_get_data (&r, img_data_len, &img_data)) {
2630 goto not_enough_data;
2634 if (!gst_tag_list_add_id3_image (tags, img_data, img_data_len, pic_type))
2635 GST_DEBUG ("failed to add image extracted from WM/Picture tag to taglist");
2641 GST_DEBUG ("Failed to read WM/Picture tag: not enough data");
2642 GST_MEMDUMP ("WM/Picture data", tag_data, tag_data_len);
2647 /* Extended Content Description Object */
2648 static GstFlowReturn
2649 gst_asf_demux_process_ext_content_desc (GstASFDemux * demux, guint8 * data,
2652 /* Other known (and unused) 'text/unicode' metadata available :
2655 * WM/MediaPrimaryClassID = {D1607DBC-E323-4BE2-86A1-48A42A28441E}
2656 * WMFSDKVersion = 9.00.00.2980
2657 * WMFSDKNeeded = 0.0.0.0000
2658 * WM/UniqueFileIdentifier = AMGa_id=R 15334;AMGp_id=P 5149;AMGt_id=T 2324984
2659 * WM/Publisher = 4AD
2661 * WM/ProviderRating = 8
2662 * WM/ProviderStyle = Rock (similar to WM/Genre)
2663 * WM/GenreID (similar to WM/Genre)
2664 * WM/TrackNumber (same as WM/Track but as a string)
2666 * Other known (and unused) 'non-text' metadata available :
2672 * We might want to read WM/TrackNumber and use atoi() if we don't have
2676 GstTagList *taglist;
2677 guint16 blockcount, i;
2679 GST_INFO_OBJECT (demux, "object is an extended content description");
2681 taglist = gst_tag_list_new_empty ();
2683 /* Content Descriptor Count */
2685 goto not_enough_data;
2687 blockcount = gst_asf_demux_get_uint16 (&data, &size);
2689 for (i = 1; i <= blockcount; ++i) {
2690 const gchar *gst_tag_name;
2694 GValue tag_value = { 0, };
2697 gchar *name_utf8 = NULL;
2701 if (!gst_asf_demux_get_string (&name, &name_len, &data, &size))
2702 goto not_enough_data;
2706 goto not_enough_data;
2708 /* Descriptor Value Data Type */
2709 datatype = gst_asf_demux_get_uint16 (&data, &size);
2711 /* Descriptor Value (not really a string, but same thing reading-wise) */
2712 if (!gst_asf_demux_get_string (&value, &value_len, &data, &size)) {
2714 goto not_enough_data;
2718 g_convert (name, name_len, "UTF-8", "UTF-16LE", &in, &out, NULL);
2720 if (name_utf8 != NULL) {
2721 GST_DEBUG ("Found tag/metadata %s", name_utf8);
2723 gst_tag_name = gst_asf_demux_get_gst_tag_from_tag_name (name_utf8);
2724 GST_DEBUG ("gst_tag_name %s", GST_STR_NULL (gst_tag_name));
2727 case ASF_DEMUX_DATA_TYPE_UTF16LE_STRING:{
2730 value_utf8 = g_convert (value, value_len, "UTF-8", "UTF-16LE",
2733 /* get rid of tags with empty value */
2734 if (value_utf8 != NULL && *value_utf8 != '\0') {
2735 GST_DEBUG ("string value %s", value_utf8);
2737 value_utf8[out] = '\0';
2739 if (gst_tag_name != NULL) {
2740 if (strcmp (gst_tag_name, GST_TAG_DATE_TIME) == 0) {
2741 guint year = atoi (value_utf8);
2744 g_value_init (&tag_value, GST_TYPE_DATE_TIME);
2745 g_value_take_boxed (&tag_value, gst_date_time_new_y (year));
2747 } else if (strcmp (gst_tag_name, GST_TAG_GENRE) == 0) {
2748 guint id3v1_genre_id;
2749 const gchar *genre_str;
2751 if (sscanf (value_utf8, "(%u)", &id3v1_genre_id) == 1 &&
2752 ((genre_str = gst_tag_id3_genre_get (id3v1_genre_id)))) {
2753 GST_DEBUG ("Genre: %s -> %s", value_utf8, genre_str);
2754 g_free (value_utf8);
2755 value_utf8 = g_strdup (genre_str);
2760 /* convert tag from string to other type if required */
2761 tag_type = gst_tag_get_type (gst_tag_name);
2762 g_value_init (&tag_value, tag_type);
2763 if (!gst_value_deserialize (&tag_value, value_utf8)) {
2764 GValue from_val = { 0, };
2766 g_value_init (&from_val, G_TYPE_STRING);
2767 g_value_set_string (&from_val, value_utf8);
2768 if (!g_value_transform (&from_val, &tag_value)) {
2769 GST_WARNING_OBJECT (demux,
2770 "Could not transform string tag to " "%s tag type %s",
2771 gst_tag_name, g_type_name (tag_type));
2772 g_value_unset (&tag_value);
2774 g_value_unset (&from_val);
2779 GST_DEBUG ("Setting metadata");
2780 g_value_init (&tag_value, G_TYPE_STRING);
2781 g_value_set_string (&tag_value, value_utf8);
2783 } else if (value_utf8 == NULL) {
2784 GST_WARNING ("Failed to convert string value to UTF8, skipping");
2786 GST_DEBUG ("Skipping empty string value for %s",
2787 GST_STR_NULL (gst_tag_name));
2789 g_free (value_utf8);
2792 case ASF_DEMUX_DATA_TYPE_BYTE_ARRAY:{
2794 if (!g_str_equal (gst_tag_name, GST_TAG_IMAGE)) {
2795 GST_FIXME ("Unhandled byte array tag %s",
2796 GST_STR_NULL (gst_tag_name));
2799 asf_demux_parse_picture_tag (taglist, (guint8 *) value,
2805 case ASF_DEMUX_DATA_TYPE_DWORD:{
2806 guint uint_val = GST_READ_UINT32_LE (value);
2808 /* this is the track number */
2809 g_value_init (&tag_value, G_TYPE_UINT);
2811 /* WM/Track counts from 0 */
2812 if (!strcmp (name_utf8, "WM/Track"))
2815 g_value_set_uint (&tag_value, uint_val);
2819 GST_DEBUG ("Skipping tag %s of type %d", gst_tag_name, datatype);
2824 if (G_IS_VALUE (&tag_value)) {
2826 GstTagMergeMode merge_mode = GST_TAG_MERGE_APPEND;
2828 /* WM/TrackNumber is more reliable than WM/Track, since the latter
2829 * is supposed to have a 0 base but is often wrongly written to start
2830 * from 1 as well, so prefer WM/TrackNumber when we have it: either
2831 * replace the value added earlier from WM/Track or put it first in
2832 * the list, so that it will get picked up by _get_uint() */
2833 if (strcmp (name_utf8, "WM/TrackNumber") == 0)
2834 merge_mode = GST_TAG_MERGE_REPLACE;
2836 gst_tag_list_add_values (taglist, merge_mode, gst_tag_name,
2839 GST_DEBUG ("Setting global metadata %s", name_utf8);
2840 gst_structure_set_value (demux->global_metadata, name_utf8,
2844 g_value_unset (&tag_value);
2853 gst_asf_demux_add_global_tags (demux, taglist);
2860 GST_WARNING ("Unexpected end of data parsing ext content desc object");
2861 gst_tag_list_unref (taglist);
2862 return GST_FLOW_OK; /* not really fatal */
2866 static GstStructure *
2867 gst_asf_demux_get_metadata_for_stream (GstASFDemux * demux, guint stream_num)
2872 g_snprintf (sname, sizeof (sname), "stream-%u", stream_num);
2874 for (i = 0; i < gst_caps_get_size (demux->metadata); ++i) {
2877 s = gst_caps_get_structure (demux->metadata, i);
2878 if (gst_structure_has_name (s, sname))
2882 gst_caps_append_structure (demux->metadata, gst_structure_new_empty (sname));
2884 /* try lookup again; demux->metadata took ownership of the structure, so we
2885 * can't really make any assumptions about what happened to it, so we can't
2886 * just return it directly after appending it */
2887 return gst_asf_demux_get_metadata_for_stream (demux, stream_num);
2890 static GstFlowReturn
2891 gst_asf_demux_process_metadata (GstASFDemux * demux, guint8 * data,
2894 guint16 blockcount, i;
2896 GST_INFO_OBJECT (demux, "object is a metadata object");
2898 /* Content Descriptor Count */
2900 goto not_enough_data;
2902 blockcount = gst_asf_demux_get_uint16 (&data, &size);
2904 for (i = 0; i < blockcount; ++i) {
2906 guint16 stream_num, name_len, data_type, lang_idx G_GNUC_UNUSED;
2907 guint32 data_len, ival;
2910 if (size < (2 + 2 + 2 + 2 + 4))
2911 goto not_enough_data;
2913 lang_idx = gst_asf_demux_get_uint16 (&data, &size);
2914 stream_num = gst_asf_demux_get_uint16 (&data, &size);
2915 name_len = gst_asf_demux_get_uint16 (&data, &size);
2916 data_type = gst_asf_demux_get_uint16 (&data, &size);
2917 data_len = gst_asf_demux_get_uint32 (&data, &size);
2919 if (size < name_len + data_len)
2920 goto not_enough_data;
2922 /* convert name to UTF-8 */
2923 name_utf8 = g_convert ((gchar *) data, name_len, "UTF-8", "UTF-16LE",
2925 gst_asf_demux_skip_bytes (name_len, &data, &size);
2927 if (name_utf8 == NULL) {
2928 GST_WARNING ("Failed to convert value name to UTF8, skipping");
2929 gst_asf_demux_skip_bytes (data_len, &data, &size);
2933 if (data_type != ASF_DEMUX_DATA_TYPE_DWORD) {
2934 gst_asf_demux_skip_bytes (data_len, &data, &size);
2942 goto not_enough_data;
2945 ival = gst_asf_demux_get_uint32 (&data, &size);
2947 /* skip anything else there may be, just in case */
2948 gst_asf_demux_skip_bytes (data_len - 4, &data, &size);
2950 s = gst_asf_demux_get_metadata_for_stream (demux, stream_num);
2951 gst_structure_set (s, name_utf8, G_TYPE_INT, ival, NULL);
2955 GST_INFO_OBJECT (demux, "metadata = %" GST_PTR_FORMAT, demux->metadata);
2961 GST_WARNING ("Unexpected end of data parsing metadata object");
2962 return GST_FLOW_OK; /* not really fatal */
2966 static GstFlowReturn
2967 gst_asf_demux_process_header (GstASFDemux * demux, guint8 * data, guint64 size)
2969 GstFlowReturn ret = GST_FLOW_OK;
2970 guint32 i, num_objects;
2971 guint8 unknown G_GNUC_UNUSED;
2973 /* Get the rest of the header's header */
2974 if (size < (4 + 1 + 1))
2975 goto not_enough_data;
2977 num_objects = gst_asf_demux_get_uint32 (&data, &size);
2978 unknown = gst_asf_demux_get_uint8 (&data, &size);
2979 unknown = gst_asf_demux_get_uint8 (&data, &size);
2981 GST_INFO_OBJECT (demux, "object is a header with %u parts", num_objects);
2983 /* Loop through the header's objects, processing those */
2984 for (i = 0; i < num_objects; ++i) {
2985 GST_INFO_OBJECT (demux, "reading header part %u", i);
2986 ret = gst_asf_demux_process_object (demux, &data, &size);
2987 if (ret != GST_FLOW_OK) {
2988 GST_WARNING ("process_object returned %s", gst_asf_get_flow_name (ret));
2997 GST_ELEMENT_ERROR (demux, STREAM, DEMUX, (NULL),
2998 ("short read parsing HEADER object"));
2999 return GST_FLOW_ERROR;
3003 static GstFlowReturn
3004 gst_asf_demux_process_file (GstASFDemux * demux, guint8 * data, guint64 size)
3006 guint64 creation_time G_GNUC_UNUSED;
3007 guint64 file_size G_GNUC_UNUSED;
3008 guint64 send_time G_GNUC_UNUSED;
3009 guint64 packets_count, play_time, preroll;
3010 guint32 flags, min_pktsize, max_pktsize, min_bitrate G_GNUC_UNUSED;
3012 if (size < (16 + 8 + 8 + 8 + 8 + 8 + 8 + 4 + 4 + 4 + 4))
3013 goto not_enough_data;
3015 gst_asf_demux_skip_bytes (16, &data, &size); /* skip GUID */
3016 file_size = gst_asf_demux_get_uint64 (&data, &size);
3017 creation_time = gst_asf_demux_get_uint64 (&data, &size);
3018 packets_count = gst_asf_demux_get_uint64 (&data, &size);
3019 play_time = gst_asf_demux_get_uint64 (&data, &size);
3020 send_time = gst_asf_demux_get_uint64 (&data, &size);
3021 preroll = gst_asf_demux_get_uint64 (&data, &size);
3022 flags = gst_asf_demux_get_uint32 (&data, &size);
3023 min_pktsize = gst_asf_demux_get_uint32 (&data, &size);
3024 max_pktsize = gst_asf_demux_get_uint32 (&data, &size);
3025 min_bitrate = gst_asf_demux_get_uint32 (&data, &size);
3027 demux->broadcast = ! !(flags & 0x01);
3028 demux->seekable = ! !(flags & 0x02);
3030 GST_DEBUG_OBJECT (demux, "min_pktsize = %u", min_pktsize);
3031 GST_DEBUG_OBJECT (demux, "flags::broadcast = %d", demux->broadcast);
3032 GST_DEBUG_OBJECT (demux, "flags::seekable = %d", demux->seekable);
3034 if (demux->broadcast) {
3035 /* these fields are invalid if the broadcast flag is set */
3040 if (min_pktsize != max_pktsize)
3041 goto non_fixed_packet_size;
3043 demux->packet_size = max_pktsize;
3045 /* FIXME: do we need send_time as well? what is it? */
3046 if ((play_time * 100) >= (preroll * GST_MSECOND))
3047 demux->play_time = (play_time * 100) - (preroll * GST_MSECOND);
3049 demux->play_time = 0;
3051 demux->preroll = preroll * GST_MSECOND;
3053 /* initial latency */
3054 demux->latency = demux->preroll;
3056 if (demux->play_time == 0)
3057 demux->seekable = FALSE;
3059 GST_DEBUG_OBJECT (demux, "play_time %" GST_TIME_FORMAT,
3060 GST_TIME_ARGS (demux->play_time));
3061 GST_DEBUG_OBJECT (demux, "preroll %" GST_TIME_FORMAT,
3062 GST_TIME_ARGS (demux->preroll));
3064 if (demux->play_time > 0) {
3065 demux->segment.duration = demux->play_time;
3068 GST_INFO ("object is a file with %" G_GUINT64_FORMAT " data packets",
3070 GST_INFO ("preroll = %" G_GUINT64_FORMAT, demux->preroll);
3075 non_fixed_packet_size:
3077 GST_ELEMENT_ERROR (demux, STREAM, DEMUX, (NULL),
3078 ("packet size must be fixed"));
3079 return GST_FLOW_ERROR;
3083 GST_ELEMENT_ERROR (demux, STREAM, DEMUX, (NULL),
3084 ("short read parsing FILE object"));
3085 return GST_FLOW_ERROR;
3089 /* Content Description Object */
3090 static GstFlowReturn
3091 gst_asf_demux_process_comment (GstASFDemux * demux, guint8 * data, guint64 size)
3095 const gchar *gst_tag;
3100 GST_TAG_TITLE, 0, NULL}, {
3101 GST_TAG_ARTIST, 0, NULL}, {
3102 GST_TAG_COPYRIGHT, 0, NULL}, {
3103 GST_TAG_DESCRIPTION, 0, NULL}, {
3104 GST_TAG_COMMENT, 0, NULL}
3106 GstTagList *taglist;
3107 GValue value = { 0 };
3111 GST_INFO_OBJECT (demux, "object is a comment");
3113 if (size < (2 + 2 + 2 + 2 + 2))
3114 goto not_enough_data;
3116 tags[0].val_length = gst_asf_demux_get_uint16 (&data, &size);
3117 tags[1].val_length = gst_asf_demux_get_uint16 (&data, &size);
3118 tags[2].val_length = gst_asf_demux_get_uint16 (&data, &size);
3119 tags[3].val_length = gst_asf_demux_get_uint16 (&data, &size);
3120 tags[4].val_length = gst_asf_demux_get_uint16 (&data, &size);
3122 GST_DEBUG_OBJECT (demux, "Comment lengths: title=%d author=%d copyright=%d "
3123 "description=%d rating=%d", tags[0].val_length, tags[1].val_length,
3124 tags[2].val_length, tags[3].val_length, tags[4].val_length);
3126 for (i = 0; i < G_N_ELEMENTS (tags); ++i) {
3127 if (size < tags[i].val_length)
3128 goto not_enough_data;
3130 /* might be just '/0', '/0'... */
3131 if (tags[i].val_length > 2 && tags[i].val_length % 2 == 0) {
3132 /* convert to UTF-8 */
3133 tags[i].val_utf8 = g_convert ((gchar *) data, tags[i].val_length,
3134 "UTF-8", "UTF-16LE", &in, &out, NULL);
3136 gst_asf_demux_skip_bytes (tags[i].val_length, &data, &size);
3139 /* parse metadata into taglist */
3140 taglist = gst_tag_list_new_empty ();
3141 g_value_init (&value, G_TYPE_STRING);
3142 for (i = 0; i < G_N_ELEMENTS (tags); ++i) {
3143 if (tags[i].val_utf8 && strlen (tags[i].val_utf8) > 0 && tags[i].gst_tag) {
3144 g_value_set_string (&value, tags[i].val_utf8);
3145 gst_tag_list_add_values (taglist, GST_TAG_MERGE_APPEND,
3146 tags[i].gst_tag, &value, NULL);
3149 g_value_unset (&value);
3151 gst_asf_demux_add_global_tags (demux, taglist);
3153 for (i = 0; i < G_N_ELEMENTS (tags); ++i)
3154 g_free (tags[i].val_utf8);
3160 GST_WARNING_OBJECT (demux, "unexpectedly short of data while processing "
3161 "comment tag section %d, skipping comment object", i);
3162 for (i = 0; i < G_N_ELEMENTS (tags); i++)
3163 g_free (tags[i].val_utf8);
3164 return GST_FLOW_OK; /* not really fatal */
3168 static GstFlowReturn
3169 gst_asf_demux_process_bitrate_props_object (GstASFDemux * demux, guint8 * data,
3172 guint16 num_streams, i;
3176 goto not_enough_data;
3178 num_streams = gst_asf_demux_get_uint16 (&data, &size);
3180 GST_INFO ("object is a bitrate properties object with %u streams",
3183 if (size < (num_streams * (2 + 4)))
3184 goto not_enough_data;
3186 for (i = 0; i < num_streams; ++i) {
3190 stream_id = gst_asf_demux_get_uint16 (&data, &size);
3191 bitrate = gst_asf_demux_get_uint32 (&data, &size);
3193 if (stream_id < GST_ASF_DEMUX_NUM_STREAM_IDS) {
3194 GST_DEBUG_OBJECT (demux, "bitrate of stream %u = %u", stream_id, bitrate);
3195 stream = gst_asf_demux_get_stream (demux, stream_id);
3197 if (stream->pending_tags == NULL) {
3198 stream->pending_tags =
3199 gst_tag_list_new (GST_TAG_BITRATE, bitrate, NULL);
3202 GST_WARNING_OBJECT (demux, "Stream id %u wasn't found", stream_id);
3205 GST_WARNING ("stream id %u is too large", stream_id);
3213 GST_WARNING_OBJECT (demux, "short read parsing bitrate props object!");
3214 return GST_FLOW_OK; /* not really fatal */
3218 static GstFlowReturn
3219 gst_asf_demux_process_header_ext (GstASFDemux * demux, guint8 * data,
3222 GstFlowReturn ret = GST_FLOW_OK;
3225 /* Get the rest of the header's header */
3226 if (size < (16 + 2 + 4))
3227 goto not_enough_data;
3229 /* skip GUID and two other bytes */
3230 gst_asf_demux_skip_bytes (16 + 2, &data, &size);
3231 hdr_size = gst_asf_demux_get_uint32 (&data, &size);
3233 GST_INFO ("extended header object with a size of %u bytes", (guint) size);
3235 /* FIXME: does data_size include the rest of the header that we have read? */
3236 if (hdr_size > size)
3237 goto not_enough_data;
3239 while (hdr_size > 0) {
3240 ret = gst_asf_demux_process_object (demux, &data, &hdr_size);
3241 if (ret != GST_FLOW_OK)
3249 GST_ELEMENT_ERROR (demux, STREAM, DEMUX, (NULL),
3250 ("short read parsing extended header object"));
3251 return GST_FLOW_ERROR;
3255 static GstFlowReturn
3256 gst_asf_demux_process_language_list (GstASFDemux * demux, guint8 * data,
3262 goto not_enough_data;
3264 if (demux->languages) {
3265 GST_WARNING ("More than one LANGUAGE_LIST object in stream");
3266 g_strfreev (demux->languages);
3267 demux->languages = NULL;
3268 demux->num_languages = 0;
3271 demux->num_languages = gst_asf_demux_get_uint16 (&data, &size);
3272 GST_LOG ("%u languages:", demux->num_languages);
3274 demux->languages = g_new0 (gchar *, demux->num_languages + 1);
3275 for (i = 0; i < demux->num_languages; ++i) {
3276 guint8 len, *lang_data = NULL;
3279 goto not_enough_data;
3280 len = gst_asf_demux_get_uint8 (&data, &size);
3281 if (gst_asf_demux_get_bytes (&lang_data, len, &data, &size)) {
3284 utf8 = g_convert ((gchar *) lang_data, len, "UTF-8", "UTF-16LE", NULL,
3287 /* truncate "en-us" etc. to just "en" */
3288 if (utf8 && strlen (utf8) >= 5 && (utf8[2] == '-' || utf8[2] == '_')) {
3291 GST_DEBUG ("[%u] %s", i, GST_STR_NULL (utf8));
3292 demux->languages[i] = utf8;
3295 goto not_enough_data;
3303 GST_WARNING_OBJECT (demux, "short read parsing language list object!");
3304 g_free (demux->languages);
3305 demux->languages = NULL;
3306 return GST_FLOW_OK; /* not fatal */
3310 static GstFlowReturn
3311 gst_asf_demux_process_simple_index (GstASFDemux * demux, guint8 * data,
3314 GstClockTime interval;
3317 if (size < (16 + 8 + 4 + 4))
3318 goto not_enough_data;
3321 gst_asf_demux_skip_bytes (16, &data, &size);
3322 interval = gst_asf_demux_get_uint64 (&data, &size) * (GstClockTime) 100;
3323 gst_asf_demux_skip_bytes (4, &data, &size);
3324 count = gst_asf_demux_get_uint32 (&data, &size);
3326 demux->sidx_interval = interval;
3327 demux->sidx_num_entries = count;
3328 g_free (demux->sidx_entries);
3329 demux->sidx_entries = g_new0 (AsfSimpleIndexEntry, count);
3331 for (i = 0; i < count; ++i) {
3332 if (G_UNLIKELY (size <= 6))
3334 demux->sidx_entries[i].packet = gst_asf_demux_get_uint32 (&data, &size);
3335 demux->sidx_entries[i].count = gst_asf_demux_get_uint16 (&data, &size);
3336 GST_LOG_OBJECT (demux, "%" GST_TIME_FORMAT " = packet %4u count : %2d",
3337 GST_TIME_ARGS (i * interval), demux->sidx_entries[i].packet,
3338 demux->sidx_entries[i].count);
3341 GST_DEBUG_OBJECT (demux, "simple index object with 0 entries");
3348 GST_WARNING_OBJECT (demux, "short read parsing simple index object!");
3349 return GST_FLOW_OK; /* not fatal */
3353 static GstFlowReturn
3354 gst_asf_demux_process_advanced_mutual_exclusion (GstASFDemux * demux,
3355 guint8 * data, guint64 size)
3361 if (size < 16 + 2 + (2 * 2))
3362 goto not_enough_data;
3364 gst_asf_demux_get_guid (&guid, &data, &size);
3365 num = gst_asf_demux_get_uint16 (&data, &size);
3368 GST_WARNING_OBJECT (demux, "nonsensical mutually exclusive streams count");
3372 if (size < (num * sizeof (guint16)))
3373 goto not_enough_data;
3375 /* read mutually exclusive stream numbers */
3376 mes = g_new (guint8, num + 1);
3377 for (i = 0; i < num; ++i) {
3378 mes[i] = gst_asf_demux_get_uint16 (&data, &size) & 0x7f;
3379 GST_LOG_OBJECT (demux, "mutually exclusive: stream #%d", mes[i]);
3382 /* add terminator so we can easily get the count or know when to stop */
3383 mes[i] = (guint8) - 1;
3385 demux->mut_ex_streams = g_slist_append (demux->mut_ex_streams, mes);
3392 GST_WARNING_OBJECT (demux, "short read parsing advanced mutual exclusion");
3393 return GST_FLOW_OK; /* not absolutely fatal */
3397 static GstFlowReturn
3398 gst_asf_demux_process_ext_stream_props (GstASFDemux * demux, guint8 * data,
3401 AsfStreamExtProps esp;
3402 AsfStream *stream = NULL;
3403 AsfObject stream_obj;
3404 guint16 stream_name_count;
3405 guint16 num_payload_ext;
3407 guint8 *stream_obj_data = NULL;
3410 guint i, stream_num;
3413 obj_size = (guint) size;
3416 goto not_enough_data;
3419 esp.start_time = gst_asf_demux_get_uint64 (&data, &size) * GST_MSECOND;
3420 esp.end_time = gst_asf_demux_get_uint64 (&data, &size) * GST_MSECOND;
3421 esp.data_bitrate = gst_asf_demux_get_uint32 (&data, &size);
3422 esp.buffer_size = gst_asf_demux_get_uint32 (&data, &size);
3423 esp.intial_buf_fullness = gst_asf_demux_get_uint32 (&data, &size);
3424 esp.data_bitrate2 = gst_asf_demux_get_uint32 (&data, &size);
3425 esp.buffer_size2 = gst_asf_demux_get_uint32 (&data, &size);
3426 esp.intial_buf_fullness2 = gst_asf_demux_get_uint32 (&data, &size);
3427 esp.max_obj_size = gst_asf_demux_get_uint32 (&data, &size);
3428 esp.flags = gst_asf_demux_get_uint32 (&data, &size);
3429 stream_num = gst_asf_demux_get_uint16 (&data, &size);
3430 esp.lang_idx = gst_asf_demux_get_uint16 (&data, &size);
3431 esp.avg_time_per_frame = gst_asf_demux_get_uint64 (&data, &size);
3432 stream_name_count = gst_asf_demux_get_uint16 (&data, &size);
3433 num_payload_ext = gst_asf_demux_get_uint16 (&data, &size);
3435 GST_INFO ("start_time = %" GST_TIME_FORMAT,
3436 GST_TIME_ARGS (esp.start_time));
3437 GST_INFO ("end_time = %" GST_TIME_FORMAT,
3438 GST_TIME_ARGS (esp.end_time));
3439 GST_INFO ("flags = %08x", esp.flags);
3440 GST_INFO ("average time per frame = %" GST_TIME_FORMAT,
3441 GST_TIME_ARGS (esp.avg_time_per_frame * 100));
3442 GST_INFO ("stream number = %u", stream_num);
3443 GST_INFO ("stream language ID idx = %u (%s)", esp.lang_idx,
3444 (esp.lang_idx < demux->num_languages) ?
3445 GST_STR_NULL (demux->languages[esp.lang_idx]) : "??");
3446 GST_INFO ("stream name count = %u", stream_name_count);
3448 /* read stream names */
3449 for (i = 0; i < stream_name_count; ++i) {
3450 guint16 stream_lang_idx G_GNUC_UNUSED;
3451 gchar *stream_name = NULL;
3454 goto not_enough_data;
3455 stream_lang_idx = gst_asf_demux_get_uint16 (&data, &size);
3456 if (!gst_asf_demux_get_string (&stream_name, NULL, &data, &size))
3457 goto not_enough_data;
3458 GST_INFO ("stream name %d: %s", i, GST_STR_NULL (stream_name));
3459 g_free (stream_name); /* TODO: store names in struct */
3462 /* read payload extension systems stuff */
3463 GST_LOG ("payload extension systems count = %u", num_payload_ext);
3465 if (num_payload_ext > 0)
3466 esp.payload_extensions = g_new0 (AsfPayloadExtension, num_payload_ext + 1);
3468 esp.payload_extensions = NULL;
3470 for (i = 0; i < num_payload_ext; ++i) {
3471 AsfPayloadExtension ext;
3473 guint32 sys_info_len;
3475 if (size < 16 + 2 + 4)
3476 goto not_enough_data;
3478 gst_asf_demux_get_guid (&ext_guid, &data, &size);
3479 ext.id = gst_asf_demux_identify_guid (asf_payload_ext_guids, &ext_guid);
3480 ext.len = gst_asf_demux_get_uint16 (&data, &size);
3482 sys_info_len = gst_asf_demux_get_uint32 (&data, &size);
3483 GST_LOG ("payload systems info len = %u", sys_info_len);
3484 if (!gst_asf_demux_skip_bytes (sys_info_len, &data, &size))
3485 goto not_enough_data;
3487 esp.payload_extensions[i] = ext;
3490 GST_LOG ("bytes read: %u/%u", (guint) (data - data_start), obj_size);
3492 /* there might be an optional STREAM_INFO object here now; if not, we
3493 * should have parsed the corresponding stream info object already (since
3494 * we are parsing the extended stream properties objects delayed) */
3496 stream = gst_asf_demux_get_stream (demux, stream_num);
3500 /* get size of the stream object */
3501 if (!asf_demux_peek_object (demux, data, size, &stream_obj, TRUE))
3502 goto not_enough_data;
3504 if (stream_obj.id != ASF_OBJ_STREAM)
3505 goto expected_stream_object;
3507 if (stream_obj.size < ASF_OBJECT_HEADER_SIZE ||
3508 stream_obj.size > (10 * 1024 * 1024))
3509 goto not_enough_data;
3511 gst_asf_demux_skip_bytes (ASF_OBJECT_HEADER_SIZE, &data, &size);
3513 /* process this stream object later after all the other 'normal' ones
3514 * have been processed (since the others are more important/non-hidden) */
3515 len = stream_obj.size - ASF_OBJECT_HEADER_SIZE;
3516 if (!gst_asf_demux_get_bytes (&stream_obj_data, len, &data, &size))
3517 goto not_enough_data;
3519 /* parse stream object */
3520 stream = gst_asf_demux_parse_stream_object (demux, stream_obj_data, len);
3521 g_free (stream_obj_data);
3526 stream->ext_props = esp;
3528 /* try to set the framerate */
3529 if (stream->is_video && stream->caps) {
3530 GValue framerate = { 0 };
3534 g_value_init (&framerate, GST_TYPE_FRACTION);
3536 num = GST_SECOND / 100;
3537 denom = esp.avg_time_per_frame;
3539 /* avoid division by 0, assume 25/1 framerate */
3540 denom = GST_SECOND / 2500;
3543 gst_value_set_fraction (&framerate, num, denom);
3545 stream->caps = gst_caps_make_writable (stream->caps);
3546 s = gst_caps_get_structure (stream->caps, 0);
3547 gst_structure_set_value (s, "framerate", &framerate);
3548 g_value_unset (&framerate);
3549 GST_DEBUG_OBJECT (demux, "setting framerate of %d/%d = %f",
3550 num, denom, ((gdouble) num) / denom);
3553 /* add language info now if we have it */
3554 if (stream->ext_props.lang_idx < demux->num_languages) {
3555 if (stream->pending_tags == NULL)
3556 stream->pending_tags = gst_tag_list_new_empty ();
3557 GST_LOG_OBJECT (demux, "stream %u has language '%s'", stream->id,
3558 demux->languages[stream->ext_props.lang_idx]);
3559 gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_APPEND,
3560 GST_TAG_LANGUAGE_CODE, demux->languages[stream->ext_props.lang_idx],
3564 GST_WARNING_OBJECT (demux, "Ext. stream properties for unknown stream");
3572 GST_WARNING_OBJECT (demux, "short read parsing ext stream props object!");
3573 return GST_FLOW_OK; /* not absolutely fatal */
3575 expected_stream_object:
3577 GST_WARNING_OBJECT (demux, "error parsing extended stream properties "
3578 "object: expected embedded stream object, but got %s object instead!",
3579 gst_asf_get_guid_nick (asf_object_guids, stream_obj.id));
3580 return GST_FLOW_OK; /* not absolutely fatal */
3584 static const gchar *
3585 gst_asf_demux_push_obj (GstASFDemux * demux, guint32 obj_id)
3589 nick = gst_asf_get_guid_nick (asf_object_guids, obj_id);
3590 if (g_str_has_prefix (nick, "ASF_OBJ_"))
3591 nick += strlen ("ASF_OBJ_");
3593 if (demux->objpath == NULL) {
3594 demux->objpath = g_strdup (nick);
3598 newpath = g_strdup_printf ("%s/%s", demux->objpath, nick);
3599 g_free (demux->objpath);
3600 demux->objpath = newpath;
3603 return (const gchar *) demux->objpath;
3607 gst_asf_demux_pop_obj (GstASFDemux * demux)
3611 if ((s = g_strrstr (demux->objpath, "/"))) {
3614 g_free (demux->objpath);
3615 demux->objpath = NULL;
3620 gst_asf_demux_process_queued_extended_stream_objects (GstASFDemux * demux)
3625 /* Parse the queued extended stream property objects and add the info
3626 * to the existing streams or add the new embedded streams, but without
3627 * activating them yet */
3628 GST_LOG_OBJECT (demux, "%u queued extended stream properties objects",
3629 g_slist_length (demux->ext_stream_props));
3631 for (l = demux->ext_stream_props, i = 0; l != NULL; l = l->next, ++i) {
3632 GstBuffer *buf = GST_BUFFER (l->data);
3635 gst_buffer_map (buf, &map, GST_MAP_READ);
3637 GST_LOG_OBJECT (demux, "parsing ext. stream properties object #%u", i);
3638 gst_asf_demux_process_ext_stream_props (demux, map.data, map.size);
3639 gst_buffer_unmap (buf, &map);
3640 gst_buffer_unref (buf);
3642 g_slist_free (demux->ext_stream_props);
3643 demux->ext_stream_props = NULL;
3648 gst_asf_demux_activate_ext_props_streams (GstASFDemux * demux)
3652 for (i = 0; i < demux->num_streams; ++i) {
3657 stream = &demux->stream[i];
3659 GST_LOG_OBJECT (demux, "checking stream %2u", stream->id);
3661 if (stream->active) {
3662 GST_LOG_OBJECT (demux, "stream %2u is already activated", stream->id);
3667 for (x = demux->mut_ex_streams; x != NULL; x = x->next) {
3670 /* check for each mutual exclusion whether it affects this stream */
3671 for (mes = (guint8 *) x->data; mes != NULL && *mes != 0xff; ++mes) {
3672 if (*mes == stream->id) {
3673 /* if yes, check if we've already added streams that are mutually
3674 * exclusive with the stream we're about to add */
3675 for (mes = (guint8 *) x->data; mes != NULL && *mes != 0xff; ++mes) {
3676 for (j = 0; j < demux->num_streams; ++j) {
3677 /* if the broadcast flag is set, assume the hidden streams aren't
3678 * actually streamed and hide them (or playbin won't work right),
3679 * otherwise assume their data is available */
3680 if (demux->stream[j].id == *mes && demux->broadcast) {
3682 GST_LOG_OBJECT (demux, "broadcast stream ID %d to be added is "
3683 "mutually exclusive with already existing stream ID %d, "
3684 "hiding stream", stream->id, demux->stream[j].id);
3696 /* FIXME: we should do stream activation based on preroll data in
3697 * streaming mode too */
3698 if (demux->streaming && !is_hidden)
3699 gst_asf_demux_activate_stream (demux, stream);
3704 static GstFlowReturn
3705 gst_asf_demux_process_object (GstASFDemux * demux, guint8 ** p_data,
3708 GstFlowReturn ret = GST_FLOW_OK;
3710 guint64 obj_data_size;
3712 if (*p_size < ASF_OBJECT_HEADER_SIZE)
3713 return ASF_FLOW_NEED_MORE_DATA;
3715 asf_demux_peek_object (demux, *p_data, ASF_OBJECT_HEADER_SIZE, &obj, TRUE);
3716 gst_asf_demux_skip_bytes (ASF_OBJECT_HEADER_SIZE, p_data, p_size);
3718 obj_data_size = obj.size - ASF_OBJECT_HEADER_SIZE;
3720 if (*p_size < obj_data_size)
3721 return ASF_FLOW_NEED_MORE_DATA;
3723 gst_asf_demux_push_obj (demux, obj.id);
3725 GST_INFO ("%s: size %" G_GUINT64_FORMAT, demux->objpath, obj.size);
3728 case ASF_OBJ_STREAM:
3729 gst_asf_demux_parse_stream_object (demux, *p_data, obj_data_size);
3733 ret = gst_asf_demux_process_file (demux, *p_data, obj_data_size);
3735 case ASF_OBJ_HEADER:
3736 ret = gst_asf_demux_process_header (demux, *p_data, obj_data_size);
3738 case ASF_OBJ_COMMENT:
3739 ret = gst_asf_demux_process_comment (demux, *p_data, obj_data_size);
3742 ret = gst_asf_demux_process_header_ext (demux, *p_data, obj_data_size);
3744 case ASF_OBJ_BITRATE_PROPS:
3746 gst_asf_demux_process_bitrate_props_object (demux, *p_data,
3749 case ASF_OBJ_EXT_CONTENT_DESC:
3751 gst_asf_demux_process_ext_content_desc (demux, *p_data,
3754 case ASF_OBJ_METADATA_OBJECT:
3755 ret = gst_asf_demux_process_metadata (demux, *p_data, obj_data_size);
3757 case ASF_OBJ_EXTENDED_STREAM_PROPS:{
3760 /* process these later, we might not have parsed the corresponding
3761 * stream object yet */
3762 GST_LOG ("%s: queued for later parsing", demux->objpath);
3763 buf = gst_buffer_new_and_alloc (obj_data_size);
3764 gst_buffer_fill (buf, 0, *p_data, obj_data_size);
3765 demux->ext_stream_props = g_slist_append (demux->ext_stream_props, buf);
3769 case ASF_OBJ_LANGUAGE_LIST:
3770 ret = gst_asf_demux_process_language_list (demux, *p_data, obj_data_size);
3772 case ASF_OBJ_ADVANCED_MUTUAL_EXCLUSION:
3773 ret = gst_asf_demux_process_advanced_mutual_exclusion (demux, *p_data,
3776 case ASF_OBJ_SIMPLE_INDEX:
3777 ret = gst_asf_demux_process_simple_index (demux, *p_data, obj_data_size);
3779 case ASF_OBJ_CONTENT_ENCRYPTION:
3780 case ASF_OBJ_EXT_CONTENT_ENCRYPTION:
3781 case ASF_OBJ_DIGITAL_SIGNATURE_OBJECT:
3782 case ASF_OBJ_UNKNOWN_ENCRYPTION_OBJECT:
3783 goto error_encrypted;
3784 case ASF_OBJ_CONCEAL_NONE:
3786 case ASF_OBJ_UNDEFINED:
3787 case ASF_OBJ_CODEC_COMMENT:
3789 case ASF_OBJ_PADDING:
3790 case ASF_OBJ_BITRATE_MUTEX:
3791 case ASF_OBJ_COMPATIBILITY:
3792 case ASF_OBJ_INDEX_PLACEHOLDER:
3793 case ASF_OBJ_INDEX_PARAMETERS:
3794 case ASF_OBJ_STREAM_PRIORITIZATION:
3795 case ASF_OBJ_SCRIPT_COMMAND:
3797 /* Unknown/unhandled object, skip it and hope for the best */
3798 GST_INFO ("%s: skipping object", demux->objpath);
3803 /* this can't fail, we checked the number of bytes available before */
3804 gst_asf_demux_skip_bytes (obj_data_size, p_data, p_size);
3806 GST_LOG ("%s: ret = %s", demux->objpath, gst_asf_get_flow_name (ret));
3808 gst_asf_demux_pop_obj (demux);
3815 GST_ELEMENT_ERROR (demux, STREAM, DECRYPT, (NULL), (NULL));
3816 return GST_FLOW_ERROR;
3821 gst_asf_demux_descramble_buffer (GstASFDemux * demux, AsfStream * stream,
3822 GstBuffer ** p_buffer)
3824 GstBuffer *descrambled_buffer;
3825 GstBuffer *scrambled_buffer;
3826 GstBuffer *sub_buffer;
3833 /* descrambled_buffer is initialised in the first iteration */
3834 descrambled_buffer = NULL;
3835 scrambled_buffer = *p_buffer;
3837 if (gst_buffer_get_size (scrambled_buffer) <
3838 demux->ds_packet_size * demux->span)
3841 for (offset = 0; offset < gst_buffer_get_size (scrambled_buffer);
3842 offset += demux->ds_chunk_size) {
3843 off = offset / demux->ds_chunk_size;
3844 row = off / demux->span;
3845 col = off % demux->span;
3846 idx = row + col * demux->ds_packet_size / demux->ds_chunk_size;
3847 GST_DEBUG ("idx=%u, row=%u, col=%u, off=%u, ds_chunk_size=%u", idx, row,
3848 col, off, demux->ds_chunk_size);
3849 GST_DEBUG ("scrambled buffer size=%" G_GSIZE_FORMAT
3850 ", span=%u, packet_size=%u", gst_buffer_get_size (scrambled_buffer),
3851 demux->span, demux->ds_packet_size);
3852 GST_DEBUG ("gst_buffer_get_size (scrambled_buffer) = %" G_GSIZE_FORMAT,
3853 gst_buffer_get_size (scrambled_buffer));
3855 gst_buffer_copy_region (scrambled_buffer, GST_BUFFER_COPY_NONE,
3856 idx * demux->ds_chunk_size, demux->ds_chunk_size);
3858 descrambled_buffer = sub_buffer;
3860 descrambled_buffer = gst_buffer_append (descrambled_buffer, sub_buffer);
3864 GST_BUFFER_TIMESTAMP (descrambled_buffer) =
3865 GST_BUFFER_TIMESTAMP (scrambled_buffer);
3866 GST_BUFFER_DURATION (descrambled_buffer) =
3867 GST_BUFFER_DURATION (scrambled_buffer);
3868 GST_BUFFER_OFFSET (descrambled_buffer) = GST_BUFFER_OFFSET (scrambled_buffer);
3869 GST_BUFFER_OFFSET_END (descrambled_buffer) =
3870 GST_BUFFER_OFFSET_END (scrambled_buffer);
3872 /* FIXME/CHECK: do we need to transfer buffer flags here too? */
3874 gst_buffer_unref (scrambled_buffer);
3875 *p_buffer = descrambled_buffer;
3879 gst_asf_demux_element_send_event (GstElement * element, GstEvent * event)
3881 GstASFDemux *demux = GST_ASF_DEMUX (element);
3884 GST_DEBUG ("handling element event of type %s", GST_EVENT_TYPE_NAME (event));
3886 for (i = 0; i < demux->num_streams; ++i) {
3887 gst_event_ref (event);
3888 if (gst_asf_demux_handle_src_event (demux->stream[i].pad,
3889 GST_OBJECT_CAST (element), event)) {
3890 gst_event_unref (event);
3895 gst_event_unref (event);
3899 /* takes ownership of the passed event */
3901 gst_asf_demux_send_event_unlocked (GstASFDemux * demux, GstEvent * event)
3903 gboolean ret = TRUE;
3906 GST_DEBUG_OBJECT (demux, "sending %s event to all source pads",
3907 GST_EVENT_TYPE_NAME (event));
3909 for (i = 0; i < demux->num_streams; ++i) {
3910 gst_event_ref (event);
3911 ret &= gst_pad_push_event (demux->stream[i].pad, event);
3913 gst_event_unref (event);
3918 gst_asf_demux_handle_src_query (GstPad * pad, GstObject * parent,
3922 gboolean res = FALSE;
3924 demux = GST_ASF_DEMUX (parent);
3926 GST_DEBUG ("handling %s query",
3927 gst_query_type_get_name (GST_QUERY_TYPE (query)));
3929 switch (GST_QUERY_TYPE (query)) {
3930 case GST_QUERY_DURATION:
3934 gst_query_parse_duration (query, &format, NULL);
3936 if (format != GST_FORMAT_TIME) {
3937 GST_LOG ("only support duration queries in TIME format");
3941 GST_OBJECT_LOCK (demux);
3943 if (demux->segment.duration != GST_CLOCK_TIME_NONE) {
3944 GST_LOG ("returning duration: %" GST_TIME_FORMAT,
3945 GST_TIME_ARGS (demux->segment.duration));
3947 gst_query_set_duration (query, GST_FORMAT_TIME,
3948 demux->segment.duration);
3952 GST_LOG ("duration not known yet");
3955 GST_OBJECT_UNLOCK (demux);
3959 case GST_QUERY_POSITION:{
3962 gst_query_parse_position (query, &format, NULL);
3964 if (format != GST_FORMAT_TIME) {
3965 GST_LOG ("only support position queries in TIME format");
3969 GST_OBJECT_LOCK (demux);
3971 if (demux->segment.position != GST_CLOCK_TIME_NONE) {
3972 GST_LOG ("returning position: %" GST_TIME_FORMAT,
3973 GST_TIME_ARGS (demux->segment.position));
3975 gst_query_set_position (query, GST_FORMAT_TIME,
3976 demux->segment.position);
3980 GST_LOG ("position not known yet");
3983 GST_OBJECT_UNLOCK (demux);
3987 case GST_QUERY_SEEKING:{
3990 gst_query_parse_seeking (query, &format, NULL, NULL, NULL);
3991 if (format == GST_FORMAT_TIME) {
3994 GST_OBJECT_LOCK (demux);
3995 duration = demux->segment.duration;
3996 GST_OBJECT_UNLOCK (demux);
3998 if (!demux->streaming || !demux->seekable) {
3999 gst_query_set_seeking (query, GST_FORMAT_TIME, demux->seekable, 0,
4006 /* try downstream first in TIME */
4007 res = gst_pad_query_default (pad, parent, query);
4009 gst_query_parse_seeking (query, &fmt, &seekable, NULL, NULL);
4010 GST_LOG_OBJECT (demux, "upstream %s seekable %d",
4011 GST_STR_NULL (gst_format_get_name (fmt)), seekable);
4012 /* if no luck, maybe in BYTES */
4013 if (!seekable || fmt != GST_FORMAT_TIME) {
4016 q = gst_query_new_seeking (GST_FORMAT_BYTES);
4017 if ((res = gst_pad_peer_query (demux->sinkpad, q))) {
4018 gst_query_parse_seeking (q, &fmt, &seekable, NULL, NULL);
4019 GST_LOG_OBJECT (demux, "upstream %s seekable %d",
4020 GST_STR_NULL (gst_format_get_name (fmt)), seekable);
4021 if (fmt != GST_FORMAT_BYTES)
4024 gst_query_unref (q);
4025 gst_query_set_seeking (query, GST_FORMAT_TIME, seekable, 0,
4031 GST_LOG_OBJECT (demux, "only support seeking in TIME format");
4035 case GST_QUERY_LATENCY:
4038 GstClockTime min, max;
4040 /* preroll delay does not matter in non-live pipeline,
4041 * but we might end up in a live (rtsp) one ... */
4044 res = gst_pad_query_default (pad, parent, query);
4048 gst_query_parse_latency (query, &live, &min, &max);
4050 GST_DEBUG_OBJECT (demux, "Peer latency: live %d, min %"
4051 GST_TIME_FORMAT " max %" GST_TIME_FORMAT, live,
4052 GST_TIME_ARGS (min), GST_TIME_ARGS (max));
4054 GST_OBJECT_LOCK (demux);
4056 min += demux->latency;
4058 max += demux->latency;
4059 GST_OBJECT_UNLOCK (demux);
4061 gst_query_set_latency (query, live, min, max);
4065 res = gst_pad_query_default (pad, parent, query);
4072 static GstStateChangeReturn
4073 gst_asf_demux_change_state (GstElement * element, GstStateChange transition)
4075 GstASFDemux *demux = GST_ASF_DEMUX (element);
4076 GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
4078 switch (transition) {
4079 case GST_STATE_CHANGE_NULL_TO_READY:{
4080 gst_segment_init (&demux->segment, GST_FORMAT_TIME);
4081 demux->need_newsegment = TRUE;
4082 demux->segment_running = FALSE;
4083 demux->accurate = FALSE;
4084 demux->adapter = gst_adapter_new ();
4085 demux->metadata = gst_caps_new_empty ();
4086 demux->global_metadata = gst_structure_new_empty ("metadata");
4087 demux->data_size = 0;
4088 demux->data_offset = 0;
4089 demux->index_offset = 0;
4090 demux->base_offset = 0;
4097 ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
4098 if (ret == GST_STATE_CHANGE_FAILURE)
4101 switch (transition) {
4102 case GST_STATE_CHANGE_PAUSED_TO_READY:
4103 case GST_STATE_CHANGE_READY_TO_NULL:
4104 gst_asf_demux_reset (demux, FALSE);