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., 59 Temple Place - Suite 330,
18 * Boston, MA 02111-1307, 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_%02d",
61 static GstStaticPadTemplate video_src_template =
62 GST_STATIC_PAD_TEMPLATE ("video_%02d",
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, GstQuery * query);
87 static const GstQueryType *gst_asf_demux_get_src_query_types (GstPad * pad);
88 static GstFlowReturn gst_asf_demux_chain (GstPad * pad, GstBuffer * buf);
89 static gboolean gst_asf_demux_sink_event (GstPad * pad, GstEvent * event);
90 static GstFlowReturn gst_asf_demux_process_object (GstASFDemux * demux,
91 guint8 ** p_data, guint64 * p_size);
92 static gboolean gst_asf_demux_activate (GstPad * sinkpad);
93 static gboolean gst_asf_demux_activate_push (GstPad * sinkpad, gboolean active);
94 static gboolean gst_asf_demux_activate_pull (GstPad * sinkpad, gboolean active);
95 static void gst_asf_demux_loop (GstASFDemux * demux);
97 gst_asf_demux_process_queued_extended_stream_objects (GstASFDemux * demux);
98 static gboolean gst_asf_demux_pull_headers (GstASFDemux * demux);
99 static void gst_asf_demux_pull_indices (GstASFDemux * demux);
100 static void gst_asf_demux_reset_stream_state_after_discont (GstASFDemux * asf);
102 gst_asf_demux_parse_data_object_start (GstASFDemux * demux, guint8 * data);
103 static void gst_asf_demux_descramble_buffer (GstASFDemux * demux,
104 AsfStream * stream, GstBuffer ** p_buffer);
105 static void gst_asf_demux_activate_stream (GstASFDemux * demux,
107 static GstStructure *gst_asf_demux_get_metadata_for_stream (GstASFDemux * d,
109 static GstFlowReturn gst_asf_demux_push_complete_payloads (GstASFDemux * demux,
112 GST_BOILERPLATE (GstASFDemux, gst_asf_demux, GstElement, GST_TYPE_ELEMENT);
115 gst_asf_demux_base_init (gpointer g_class)
117 GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
119 gst_element_class_add_pad_template (element_class,
120 gst_static_pad_template_get (&audio_src_template));
121 gst_element_class_add_pad_template (element_class,
122 gst_static_pad_template_get (&video_src_template));
123 gst_element_class_add_pad_template (element_class,
124 gst_static_pad_template_get (&gst_asf_demux_sink_template));
126 gst_element_class_set_details_simple (element_class, "ASF Demuxer",
128 "Demultiplexes ASF Streams", "Owen Fraser-Green <owen@discobabe.net>");
132 gst_asf_demux_class_init (GstASFDemuxClass * klass)
134 GstElementClass *gstelement_class;
136 gstelement_class = (GstElementClass *) klass;
138 gstelement_class->change_state =
139 GST_DEBUG_FUNCPTR (gst_asf_demux_change_state);
140 gstelement_class->send_event =
141 GST_DEBUG_FUNCPTR (gst_asf_demux_element_send_event);
145 gst_asf_demux_free_stream (GstASFDemux * demux, AsfStream * stream)
147 gst_caps_replace (&stream->caps, NULL);
148 if (stream->pending_tags) {
149 gst_tag_list_free (stream->pending_tags);
150 stream->pending_tags = NULL;
154 gst_element_remove_pad (GST_ELEMENT_CAST (demux), stream->pad);
156 gst_object_unref (stream->pad);
159 if (stream->payloads) {
160 g_array_free (stream->payloads, TRUE);
161 stream->payloads = NULL;
163 if (stream->ext_props.valid) {
164 g_free (stream->ext_props.payload_extensions);
165 stream->ext_props.payload_extensions = NULL;
170 gst_asf_demux_reset (GstASFDemux * demux, gboolean chain_reset)
172 GST_LOG_OBJECT (demux, "resetting");
174 gst_segment_init (&demux->segment, GST_FORMAT_UNDEFINED);
175 demux->segment_running = FALSE;
176 if (demux->adapter && !chain_reset) {
177 gst_adapter_clear (demux->adapter);
178 g_object_unref (demux->adapter);
179 demux->adapter = NULL;
181 if (demux->taglist) {
182 gst_tag_list_free (demux->taglist);
183 demux->taglist = NULL;
185 if (demux->metadata) {
186 gst_caps_unref (demux->metadata);
187 demux->metadata = NULL;
189 if (demux->global_metadata) {
190 gst_structure_free (demux->global_metadata);
191 demux->global_metadata = NULL;
194 demux->state = GST_ASF_DEMUX_STATE_HEADER;
195 g_free (demux->objpath);
196 demux->objpath = NULL;
197 g_strfreev (demux->languages);
198 demux->languages = NULL;
199 demux->num_languages = 0;
200 g_slist_foreach (demux->ext_stream_props, (GFunc) gst_mini_object_unref,
202 g_slist_free (demux->ext_stream_props);
203 demux->ext_stream_props = NULL;
205 while (demux->old_num_streams > 0) {
206 gst_asf_demux_free_stream (demux,
207 &demux->old_stream[demux->old_num_streams - 1]);
208 --demux->old_num_streams;
210 memset (demux->old_stream, 0, sizeof (demux->old_stream));
211 demux->old_num_streams = 0;
213 /* when resetting for a new chained asf, we don't want to remove the pads
214 * before adding the new ones */
216 memcpy (demux->old_stream, demux->stream, sizeof (demux->stream));
217 demux->old_num_streams = demux->num_streams;
218 demux->num_streams = 0;
221 while (demux->num_streams > 0) {
222 gst_asf_demux_free_stream (demux, &demux->stream[demux->num_streams - 1]);
223 --demux->num_streams;
225 memset (demux->stream, 0, sizeof (demux->stream));
227 /* do not remove those for not adding pads with same name */
228 demux->num_audio_streams = 0;
229 demux->num_video_streams = 0;
231 demux->num_streams = 0;
232 demux->activated_streams = FALSE;
233 demux->first_ts = GST_CLOCK_TIME_NONE;
234 demux->segment_ts = GST_CLOCK_TIME_NONE;
237 gst_segment_init (&demux->in_segment, GST_FORMAT_UNDEFINED);
238 demux->state = GST_ASF_DEMUX_STATE_HEADER;
239 demux->seekable = FALSE;
240 demux->broadcast = FALSE;
241 demux->sidx_interval = 0;
242 demux->sidx_num_entries = 0;
243 g_free (demux->sidx_entries);
244 demux->sidx_entries = NULL;
246 demux->speed_packets = 1;
249 GST_LOG_OBJECT (demux, "Restarting");
250 gst_segment_init (&demux->segment, GST_FORMAT_TIME);
251 demux->need_newsegment = TRUE;
252 demux->segment_running = FALSE;
253 demux->accurate = FALSE;
254 demux->metadata = gst_caps_new_empty ();
255 demux->global_metadata = gst_structure_empty_new ("metadata");
256 demux->data_size = 0;
257 demux->data_offset = 0;
258 demux->index_offset = 0;
260 demux->base_offset = 0;
265 gst_asf_demux_init (GstASFDemux * demux, GstASFDemuxClass * klass)
268 gst_pad_new_from_static_template (&gst_asf_demux_sink_template, "sink");
269 gst_pad_set_chain_function (demux->sinkpad,
270 GST_DEBUG_FUNCPTR (gst_asf_demux_chain));
271 gst_pad_set_event_function (demux->sinkpad,
272 GST_DEBUG_FUNCPTR (gst_asf_demux_sink_event));
273 gst_pad_set_activate_function (demux->sinkpad,
274 GST_DEBUG_FUNCPTR (gst_asf_demux_activate));
275 gst_pad_set_activatepull_function (demux->sinkpad,
276 GST_DEBUG_FUNCPTR (gst_asf_demux_activate_pull));
277 gst_pad_set_activatepush_function (demux->sinkpad,
278 GST_DEBUG_FUNCPTR (gst_asf_demux_activate_push));
279 gst_element_add_pad (GST_ELEMENT (demux), demux->sinkpad);
281 /* set initial state */
282 gst_asf_demux_reset (demux, FALSE);
286 gst_asf_demux_activate (GstPad * sinkpad)
288 if (gst_pad_check_pull_range (sinkpad)) {
289 return gst_pad_activate_pull (sinkpad, TRUE);
291 return gst_pad_activate_push (sinkpad, TRUE);
296 gst_asf_demux_activate_push (GstPad * sinkpad, gboolean active)
300 demux = GST_ASF_DEMUX (GST_OBJECT_PARENT (sinkpad));
302 demux->state = GST_ASF_DEMUX_STATE_HEADER;
303 demux->streaming = TRUE;
309 gst_asf_demux_activate_pull (GstPad * pad, gboolean active)
313 demux = GST_ASF_DEMUX (GST_OBJECT_PARENT (pad));
316 demux->state = GST_ASF_DEMUX_STATE_HEADER;
317 demux->streaming = FALSE;
319 return gst_pad_start_task (pad, (GstTaskFunction) gst_asf_demux_loop,
322 return gst_pad_stop_task (pad);
328 gst_asf_demux_sink_event (GstPad * pad, GstEvent * event)
333 demux = GST_ASF_DEMUX (gst_pad_get_parent (pad));
335 GST_LOG_OBJECT (demux, "handling %s event", GST_EVENT_TYPE_NAME (event));
336 switch (GST_EVENT_TYPE (event)) {
337 case GST_EVENT_NEWSEGMENT:{
338 GstFormat newsegment_format;
339 gint64 newsegment_start, stop, time;
343 gst_event_parse_new_segment_full (event, &update, &rate, &arate,
344 &newsegment_format, &newsegment_start, &stop, &time);
346 if (newsegment_format == GST_FORMAT_BYTES) {
347 if (demux->packet_size && newsegment_start > demux->data_offset)
348 demux->packet = (newsegment_start - demux->data_offset) /
352 } else if (newsegment_format == GST_FORMAT_TIME) {
353 /* do not know packet position, not really a problem */
356 GST_WARNING_OBJECT (demux, "unsupported newsegment format, ignoring");
357 gst_event_unref (event);
361 /* record upstream segment for interpolation */
362 if (newsegment_format != demux->in_segment.format)
363 gst_segment_init (&demux->in_segment, GST_FORMAT_UNDEFINED);
364 gst_segment_set_newsegment_full (&demux->in_segment, update, rate, arate,
365 newsegment_format, newsegment_start, stop, time);
367 /* in either case, clear some state and generate newsegment later on */
368 GST_OBJECT_LOCK (demux);
369 demux->segment_ts = GST_CLOCK_TIME_NONE;
370 demux->in_gap = GST_CLOCK_TIME_NONE;
371 demux->need_newsegment = TRUE;
372 gst_asf_demux_reset_stream_state_after_discont (demux);
373 GST_OBJECT_UNLOCK (demux);
375 gst_event_unref (event);
381 if (demux->state == GST_ASF_DEMUX_STATE_HEADER) {
382 GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
383 (_("This stream contains no data.")),
384 ("got eos and didn't receive a complete header object"));
387 flow = gst_asf_demux_push_complete_payloads (demux, TRUE);
388 if (flow < GST_FLOW_UNEXPECTED || flow == GST_FLOW_NOT_LINKED) {
389 GST_ELEMENT_ERROR (demux, STREAM, FAILED,
390 (_("Internal data stream error.")),
391 ("streaming stopped, reason %s", gst_flow_get_name (flow)));
395 GST_OBJECT_LOCK (demux);
396 gst_adapter_clear (demux->adapter);
397 GST_OBJECT_UNLOCK (demux);
398 gst_asf_demux_send_event_unlocked (demux, event);
402 case GST_EVENT_FLUSH_STOP:
403 GST_OBJECT_LOCK (demux);
404 gst_asf_demux_reset_stream_state_after_discont (demux);
405 GST_OBJECT_UNLOCK (demux);
406 gst_asf_demux_send_event_unlocked (demux, event);
407 /* upon activation, latency is no longer introduced, e.g. after seek */
408 if (demux->activated_streams)
413 ret = gst_pad_event_default (pad, event);
417 gst_object_unref (demux);
422 gst_asf_demux_seek_index_lookup (GstASFDemux * demux, guint * packet,
423 GstClockTime seek_time, GstClockTime * p_idx_time, guint * speed)
425 GstClockTime idx_time;
428 if (G_UNLIKELY (demux->sidx_num_entries == 0 || demux->sidx_interval == 0))
431 idx = (guint) ((seek_time + demux->preroll) / demux->sidx_interval);
433 /* FIXME: seek beyond end of file should result in immediate EOS from
434 * streaming thread instead of a failed seek */
435 if (G_UNLIKELY (idx >= demux->sidx_num_entries))
438 *packet = demux->sidx_entries[idx].packet;
440 *speed = demux->sidx_entries[idx].count;
442 /* so we get closer to the actual time of the packet ... actually, let's not
443 * do this, since we throw away superfluous payloads before the seek position
444 * anyway; this way, our key unit seek 'snap resolution' is a bit better
445 * (ie. same as index resolution) */
447 while (idx > 0 && demux->sidx_entries[idx-1] == demux->sidx_entries[idx])
451 idx_time = demux->sidx_interval * idx;
452 if (G_LIKELY (idx_time >= demux->preroll))
453 idx_time -= demux->preroll;
455 GST_DEBUG_OBJECT (demux, "%" GST_TIME_FORMAT " => packet %u at %"
456 GST_TIME_FORMAT, GST_TIME_ARGS (seek_time), *packet,
457 GST_TIME_ARGS (idx_time));
459 if (G_LIKELY (p_idx_time))
460 *p_idx_time = idx_time;
466 gst_asf_demux_reset_stream_state_after_discont (GstASFDemux * demux)
470 gst_adapter_clear (demux->adapter);
472 GST_DEBUG_OBJECT (demux, "reset stream state");
474 for (n = 0; n < demux->num_streams; n++) {
475 demux->stream[n].discont = TRUE;
476 demux->stream[n].last_flow = GST_FLOW_OK;
478 while (demux->stream[n].payloads->len > 0) {
482 last = demux->stream[n].payloads->len - 1;
483 payload = &g_array_index (demux->stream[n].payloads, AsfPayload, last);
484 gst_buffer_replace (&payload->buf, NULL);
485 g_array_remove_index (demux->stream[n].payloads, last);
491 gst_asf_demux_mark_discont (GstASFDemux * demux)
495 GST_DEBUG_OBJECT (demux, "Mark stream discont");
497 for (n = 0; n < demux->num_streams; n++)
498 demux->stream[n].discont = TRUE;
501 /* do a seek in push based mode */
503 gst_asf_demux_handle_seek_push (GstASFDemux * demux, GstEvent * event)
508 GstSeekType cur_type, stop_type;
513 gst_event_parse_seek (event, &rate, &format, &flags, &cur_type, &cur,
516 stop_type = GST_SEEK_TYPE_NONE;
519 GST_DEBUG_OBJECT (demux, "seeking to %" GST_TIME_FORMAT, GST_TIME_ARGS (cur));
521 /* determine packet, by index or by estimation */
522 if (!gst_asf_demux_seek_index_lookup (demux, &packet, cur, NULL, NULL)) {
523 packet = (guint) gst_util_uint64_scale (demux->num_packets,
524 cur, demux->play_time);
527 if (packet > demux->num_packets) {
528 GST_DEBUG_OBJECT (demux, "could not determine packet to seek to, "
533 GST_DEBUG_OBJECT (demux, "seeking to packet %d", packet);
535 cur = demux->data_offset + (packet * demux->packet_size);
537 GST_DEBUG_OBJECT (demux, "Pushing BYTE seek rate %g, "
538 "start %" G_GINT64_FORMAT ", stop %" G_GINT64_FORMAT, rate, cur, stop);
539 /* BYTE seek event */
540 event = gst_event_new_seek (rate, GST_FORMAT_BYTES, flags, cur_type, cur,
542 res = gst_pad_push_event (demux->sinkpad, event);
548 gst_asf_demux_handle_seek_event (GstASFDemux * demux, GstEvent * event)
550 GstClockTime idx_time;
553 GstSeekType cur_type, stop_type;
555 gboolean only_need_update;
556 gboolean keyunit_sync;
561 guint packet, speed_count = 1;
563 if (G_UNLIKELY (demux->seekable == FALSE || demux->packet_size == 0 ||
564 demux->num_packets == 0 || demux->play_time == 0)) {
565 GST_LOG_OBJECT (demux, "stream is not seekable");
569 if (G_UNLIKELY (!demux->activated_streams)) {
570 GST_LOG_OBJECT (demux, "streams not yet activated, ignoring seek");
574 gst_event_parse_seek (event, &rate, &format, &flags, &cur_type, &cur,
577 if (G_UNLIKELY (format != GST_FORMAT_TIME)) {
578 GST_LOG_OBJECT (demux, "seeking is only supported in TIME format");
582 if (G_UNLIKELY (rate <= 0.0)) {
583 GST_LOG_OBJECT (demux, "backward playback is not supported yet");
587 flush = ((flags & GST_SEEK_FLAG_FLUSH) == GST_SEEK_FLAG_FLUSH);
589 ((flags & GST_SEEK_FLAG_ACCURATE) == GST_SEEK_FLAG_ACCURATE);
590 keyunit_sync = ((flags & GST_SEEK_FLAG_KEY_UNIT) == GST_SEEK_FLAG_KEY_UNIT);
592 if (G_UNLIKELY (demux->streaming)) {
593 /* support it safely needs more segment handling, e.g. closing etc */
595 GST_LOG_OBJECT (demux, "streaming; non-flushing seek not supported");
598 /* we can (re)construct the start later on, but not the end */
599 if (stop_type != GST_SEEK_TYPE_NONE) {
600 GST_LOG_OBJECT (demux, "streaming; end type must be NONE");
603 gst_event_ref (event);
604 /* upstream might handle TIME seek, e.g. mms or rtsp,
605 * or not, e.g. http, then we give it a hand */
606 if (!gst_pad_push_event (demux->sinkpad, event))
607 return gst_asf_demux_handle_seek_push (demux, event);
612 /* unlock the streaming thread */
613 if (G_LIKELY (flush)) {
614 gst_pad_push_event (demux->sinkpad, gst_event_new_flush_start ());
615 gst_asf_demux_send_event_unlocked (demux, gst_event_new_flush_start ());
617 gst_pad_pause_task (demux->sinkpad);
620 /* grab the stream lock so that streaming cannot continue, for
621 * non flushing seeks when the element is in PAUSED this could block
623 GST_PAD_STREAM_LOCK (demux->sinkpad);
625 /* we now can stop flushing, since we have the stream lock now */
626 gst_pad_push_event (demux->sinkpad, gst_event_new_flush_stop ());
628 if (G_LIKELY (flush))
629 gst_asf_demux_send_event_unlocked (demux, gst_event_new_flush_stop ());
631 /* operating on copy of segment until we know the seek worked */
632 segment = demux->segment;
634 if (G_UNLIKELY (demux->segment_running && !flush)) {
637 /* create the segment event to close the current segment */
638 newseg = gst_event_new_new_segment (TRUE, segment.rate,
639 GST_FORMAT_TIME, segment.start, segment.last_stop, segment.time);
641 gst_asf_demux_send_event_unlocked (demux, newseg);
644 gst_segment_set_seek (&segment, rate, format, flags, cur_type,
645 cur, stop_type, stop, &only_need_update);
647 GST_DEBUG_OBJECT (demux, "seeking to time %" GST_TIME_FORMAT ", segment: "
648 "%" GST_SEGMENT_FORMAT, GST_TIME_ARGS (segment.start), &segment);
650 seek_time = segment.start;
652 /* FIXME: should check the KEY_UNIT flag; need to adjust last_stop to
653 * real start of data and segment_start to indexed time for key unit seek*/
654 if (G_UNLIKELY (!gst_asf_demux_seek_index_lookup (demux, &packet, seek_time,
655 &idx_time, &speed_count))) {
656 /* First try to query our source to see if it can convert for us. This is
657 the case when our source is an mms stream, notice that in this case
658 gstmms will do a time based seek to get the byte offset, this is not a
659 problem as the seek to this offset needs to happen anway. */
661 GstFormat dest_format = GST_FORMAT_BYTES;
663 if (gst_pad_query_peer_convert (demux->sinkpad, GST_FORMAT_TIME, seek_time,
664 &dest_format, &offset) && dest_format == GST_FORMAT_BYTES) {
665 packet = (offset - demux->data_offset) / demux->packet_size;
666 GST_LOG_OBJECT (demux, "convert %" GST_TIME_FORMAT
667 " to bytes query result: %" G_GINT64_FORMAT ", data_ofset: %"
668 G_GINT64_FORMAT ", packet_size: %u," " resulting packet: %u\n",
669 GST_TIME_ARGS (seek_time), offset, demux->data_offset,
670 demux->packet_size, packet);
672 /* FIXME: For streams containing video, seek to an earlier position in
673 * the hope of hitting a keyframe and let the sinks throw away the stuff
674 * before the segment start. For audio-only this is unnecessary as every
676 if (flush && (demux->accurate || keyunit_sync)
677 && demux->num_video_streams > 0) {
678 seek_time -= 5 * GST_SECOND;
683 packet = (guint) gst_util_uint64_scale (demux->num_packets,
684 seek_time, demux->play_time);
686 if (packet > demux->num_packets)
687 packet = demux->num_packets;
690 if (G_LIKELY (keyunit_sync)) {
691 GST_DEBUG_OBJECT (demux, "key unit seek, adjust seek_time = %"
692 GST_TIME_FORMAT " to index_time = %" GST_TIME_FORMAT,
693 GST_TIME_ARGS (seek_time), GST_TIME_ARGS (idx_time));
694 segment.start = idx_time;
695 segment.last_stop = idx_time;
696 segment.time = idx_time;
700 GST_DEBUG_OBJECT (demux, "seeking to packet %u (%d)", packet, speed_count);
702 GST_OBJECT_LOCK (demux);
703 demux->segment = segment;
704 demux->packet = packet;
705 demux->need_newsegment = TRUE;
706 demux->speed_packets = speed_count;
707 gst_asf_demux_reset_stream_state_after_discont (demux);
708 GST_OBJECT_UNLOCK (demux);
710 /* restart our task since it might have been stopped when we did the flush */
711 gst_pad_start_task (demux->sinkpad, (GstTaskFunction) gst_asf_demux_loop,
714 /* streaming can continue now */
715 GST_PAD_STREAM_UNLOCK (demux->sinkpad);
721 gst_asf_demux_handle_src_event (GstPad * pad, GstEvent * event)
726 demux = GST_ASF_DEMUX (gst_pad_get_parent (pad));
728 switch (GST_EVENT_TYPE (event)) {
730 GST_LOG_OBJECT (pad, "seek event");
731 ret = gst_asf_demux_handle_seek_event (demux, event);
732 gst_event_unref (event);
735 case GST_EVENT_NAVIGATION:
736 /* just drop these two silently */
737 gst_event_unref (event);
741 GST_LOG_OBJECT (pad, "%s event", GST_EVENT_TYPE_NAME (event));
742 ret = gst_pad_event_default (pad, event);
746 gst_object_unref (demux);
750 static inline guint32
751 gst_asf_demux_identify_guid (const ASFGuidHash * guids, ASFGuid * guid)
755 ret = gst_asf_identify_guid (guids, guid);
757 GST_LOG ("%s 0x%08x-0x%08x-0x%08x-0x%08x",
758 gst_asf_get_guid_nick (guids, ret),
759 guid->v1, guid->v2, guid->v3, guid->v4);
771 /* expect is true when the user is expeting an object,
772 * when false, it will give no warnings if the object
776 asf_demux_peek_object (GstASFDemux * demux, const guint8 * data,
777 guint data_len, AsfObject * object, gboolean expect)
781 if (data_len < ASF_OBJECT_HEADER_SIZE)
784 guid.v1 = GST_READ_UINT32_LE (data + 0);
785 guid.v2 = GST_READ_UINT32_LE (data + 4);
786 guid.v3 = GST_READ_UINT32_LE (data + 8);
787 guid.v4 = GST_READ_UINT32_LE (data + 12);
789 object->size = GST_READ_UINT64_LE (data + 16);
791 /* FIXME: make asf_demux_identify_object_guid() */
792 object->id = gst_asf_demux_identify_guid (asf_object_guids, &guid);
793 if (object->id == ASF_OBJ_UNDEFINED && expect) {
794 GST_WARNING_OBJECT (demux, "Unknown object %08x-%08x-%08x-%08x",
795 guid.v1, guid.v2, guid.v3, guid.v4);
802 gst_asf_demux_release_old_pads (GstASFDemux * demux)
804 GST_DEBUG_OBJECT (demux, "Releasing old pads");
806 while (demux->old_num_streams > 0) {
807 gst_pad_push_event (demux->old_stream[demux->old_num_streams - 1].pad,
808 gst_event_new_eos ());
809 gst_asf_demux_free_stream (demux,
810 &demux->old_stream[demux->old_num_streams - 1]);
811 --demux->old_num_streams;
813 memset (demux->old_stream, 0, sizeof (demux->old_stream));
814 demux->old_num_streams = 0;
818 gst_asf_demux_chain_headers (GstASFDemux * demux)
822 guint8 *header_data, *data = NULL;
823 const guint8 *cdata = NULL;
826 cdata = (guint8 *) gst_adapter_peek (demux->adapter, ASF_OBJECT_HEADER_SIZE);
830 asf_demux_peek_object (demux, cdata, ASF_OBJECT_HEADER_SIZE, &obj, TRUE);
831 if (obj.id != ASF_OBJ_HEADER)
834 GST_LOG_OBJECT (demux, "header size = %u", (guint) obj.size);
836 /* + 50 for non-packet data at beginning of ASF_OBJ_DATA */
837 if (gst_adapter_available (demux->adapter) < obj.size + 50)
840 data = gst_adapter_take (demux->adapter, obj.size + 50);
843 header_size = obj.size;
844 flow = gst_asf_demux_process_object (demux, &header_data, &header_size);
845 if (flow != GST_FLOW_OK)
848 /* calculate where the packet data starts */
849 demux->data_offset = obj.size + 50;
851 /* now parse the beginning of the ASF_OBJ_DATA object */
852 if (!gst_asf_demux_parse_data_object_start (demux, data + obj.size))
855 if (demux->num_streams == 0)
864 GST_LOG_OBJECT (demux, "not enough data in adapter yet");
871 GST_ELEMENT_ERROR (demux, STREAM, WRONG_TYPE, (NULL),
872 ("This doesn't seem to be an ASF file"));
874 return GST_FLOW_ERROR;
879 GST_ELEMENT_ERROR (demux, STREAM, DEMUX, (NULL),
880 ("header parsing failed, or no streams found, flow = %s",
881 gst_flow_get_name (flow)));
883 return GST_FLOW_ERROR;
888 gst_asf_demux_aggregate_flow_return (GstASFDemux * demux, AsfStream * stream,
893 GST_DEBUG_OBJECT (demux, "Aggregating");
895 /* Store the value */
896 stream->last_flow = flow;
898 /* any other error that is not not-linked can be returned right away */
899 if (flow != GST_FLOW_NOT_LINKED)
902 for (i = 0; i < demux->num_streams; i++) {
903 if (demux->stream[i].active) {
904 flow = demux->stream[i].last_flow;
905 GST_DEBUG_OBJECT (demux, "Aggregating: flow %i return %s", i,
906 gst_flow_get_name (flow));
907 if (flow != GST_FLOW_NOT_LINKED)
912 /* If we got here, then all our active streams are not linked */
918 gst_asf_demux_pull_data (GstASFDemux * demux, guint64 offset, guint size,
919 GstBuffer ** p_buf, GstFlowReturn * p_flow)
923 GST_LOG_OBJECT (demux, "pulling buffer at %" G_GUINT64_FORMAT "+%u",
926 flow = gst_pad_pull_range (demux->sinkpad, offset, size, p_buf);
928 if (G_LIKELY (p_flow))
931 if (G_UNLIKELY (flow != GST_FLOW_OK)) {
932 GST_DEBUG_OBJECT (demux, "flow %s pulling buffer at %" G_GUINT64_FORMAT
933 "+%u", gst_flow_get_name (flow), offset, size);
938 g_assert (*p_buf != NULL);
940 if (G_UNLIKELY (GST_BUFFER_SIZE (*p_buf) < size)) {
941 GST_DEBUG_OBJECT (demux, "short read pulling buffer at %" G_GUINT64_FORMAT
942 "+%u (got only %u bytes)", offset, size, GST_BUFFER_SIZE (*p_buf));
943 gst_buffer_unref (*p_buf);
944 if (G_LIKELY (p_flow))
945 *p_flow = GST_FLOW_UNEXPECTED;
954 gst_asf_demux_pull_indices (GstASFDemux * demux)
956 GstBuffer *buf = NULL;
960 offset = demux->index_offset;
962 if (G_UNLIKELY (offset == 0)) {
963 GST_DEBUG_OBJECT (demux, "can't read indices, don't know index offset");
967 while (gst_asf_demux_pull_data (demux, offset, 16 + 8, &buf, NULL)) {
971 asf_demux_peek_object (demux, GST_BUFFER_DATA (buf), 16 + 8, &obj, TRUE);
972 gst_buffer_replace (&buf, NULL);
974 /* check for sanity */
975 if (G_UNLIKELY (obj.size > (5 * 1024 * 1024))) {
976 GST_DEBUG_OBJECT (demux, "implausible index object size, bailing out");
980 if (G_UNLIKELY (!gst_asf_demux_pull_data (demux, offset, obj.size, &buf,
984 GST_LOG_OBJECT (demux, "index object at offset 0x%" G_GINT64_MODIFIER "X"
985 ", size %u", offset, (guint) obj.size);
987 offset += obj.size; /* increase before _process_object changes it */
989 flow = gst_asf_demux_process_object (demux, &buf->data, &obj.size);
990 gst_buffer_replace (&buf, NULL);
992 if (G_UNLIKELY (flow != GST_FLOW_OK))
997 GST_DEBUG_OBJECT (demux, "read %u index objects", num_read);
1001 gst_asf_demux_parse_data_object_start (GstASFDemux * demux, guint8 * data)
1005 asf_demux_peek_object (demux, data, 50, &obj, TRUE);
1006 if (obj.id != ASF_OBJ_DATA) {
1007 GST_WARNING_OBJECT (demux, "headers not followed by a DATA object");
1011 demux->state = GST_ASF_DEMUX_STATE_DATA;
1013 if (!demux->broadcast && obj.size > 50) {
1014 demux->data_size = obj.size - 50;
1015 /* CHECKME: for at least one file this is off by +158 bytes?! */
1016 demux->index_offset = demux->data_offset + demux->data_size;
1018 demux->data_size = 0;
1019 demux->index_offset = 0;
1024 if (!demux->broadcast) {
1025 /* skip object header (24 bytes) and file GUID (16 bytes) */
1026 demux->num_packets = GST_READ_UINT64_LE (data + (16 + 8) + 16);
1028 demux->num_packets = 0;
1031 if (demux->num_packets == 0)
1032 demux->seekable = FALSE;
1034 /* fallback in the unlikely case that headers are inconsistent, can't hurt */
1035 if (demux->data_size == 0 && demux->num_packets > 0) {
1036 demux->data_size = demux->num_packets * demux->packet_size;
1037 demux->index_offset = demux->data_offset + demux->data_size;
1040 /* process pending stream objects and create pads for those */
1041 gst_asf_demux_process_queued_extended_stream_objects (demux);
1043 GST_INFO_OBJECT (demux, "Stream has %" G_GUINT64_FORMAT " packets, "
1044 "data_offset=%" G_GINT64_FORMAT ", data_size=%" G_GINT64_FORMAT
1045 ", index_offset=%" G_GUINT64_FORMAT, demux->num_packets,
1046 demux->data_offset, demux->data_size, demux->index_offset);
1052 gst_asf_demux_pull_headers (GstASFDemux * demux)
1056 GstBuffer *buf = NULL;
1059 GST_LOG_OBJECT (demux, "reading headers");
1061 /* pull HEADER object header, so we know its size */
1062 if (!gst_asf_demux_pull_data (demux, demux->base_offset, 16 + 8, &buf, NULL))
1065 asf_demux_peek_object (demux, GST_BUFFER_DATA (buf), 16 + 8, &obj, TRUE);
1066 gst_buffer_replace (&buf, NULL);
1068 if (obj.id != ASF_OBJ_HEADER)
1071 GST_LOG_OBJECT (demux, "header size = %u", (guint) obj.size);
1073 /* pull HEADER object */
1074 if (!gst_asf_demux_pull_data (demux, demux->base_offset, obj.size, &buf,
1078 size = obj.size; /* don't want obj.size changed */
1079 flow = gst_asf_demux_process_object (demux, &buf->data, &size);
1080 gst_buffer_replace (&buf, NULL);
1082 if (flow != GST_FLOW_OK) {
1083 GST_WARNING_OBJECT (demux, "process_object: %s", gst_flow_get_name (flow));
1087 /* calculate where the packet data starts */
1088 demux->data_offset = demux->base_offset + obj.size + 50;
1090 /* now pull beginning of DATA object before packet data */
1091 if (!gst_asf_demux_pull_data (demux, demux->base_offset + obj.size, 50, &buf,
1095 if (!gst_asf_demux_parse_data_object_start (demux, GST_BUFFER_DATA (buf)))
1098 if (demux->num_streams == 0)
1101 gst_buffer_replace (&buf, NULL);
1107 gst_buffer_replace (&buf, NULL);
1108 GST_ELEMENT_ERROR (demux, STREAM, WRONG_TYPE, (NULL),
1109 ("This doesn't seem to be an ASF file"));
1116 GST_ELEMENT_ERROR (demux, STREAM, DEMUX, (NULL), (NULL));
1122 all_streams_prerolled (GstASFDemux * demux)
1124 GstClockTime preroll_time;
1125 guint i, num_no_data = 0;
1127 /* Allow at least 500ms of preroll_time */
1128 preroll_time = MAX (demux->preroll, 500 * GST_MSECOND);
1130 /* returns TRUE as long as there isn't a stream which (a) has data queued
1131 * and (b) the timestamp of last piece of data queued is < demux->preroll
1132 * AND there is at least one other stream with data queued */
1133 for (i = 0; i < demux->num_streams; ++i) {
1134 AsfPayload *last_payload;
1138 stream = &demux->stream[i];
1139 if (G_UNLIKELY (stream->payloads->len == 0)) {
1141 GST_LOG_OBJECT (stream->pad, "no data queued");
1145 last_idx = stream->payloads->len - 1;
1146 last_payload = &g_array_index (stream->payloads, AsfPayload, last_idx);
1148 GST_LOG_OBJECT (stream->pad, "checking if %" GST_TIME_FORMAT " > %"
1149 GST_TIME_FORMAT, GST_TIME_ARGS (last_payload->ts),
1150 GST_TIME_ARGS (preroll_time));
1151 if (G_UNLIKELY (last_payload->ts <= preroll_time)) {
1152 GST_LOG_OBJECT (stream->pad, "not beyond preroll point yet");
1157 if (G_UNLIKELY (num_no_data == demux->num_streams))
1165 gst_asf_demux_have_mutually_exclusive_active_stream (GstASFDemux * demux,
1170 for (l = demux->mut_ex_streams; l != NULL; l = l->next) {
1173 /* check for each mutual exclusion group whether it affects this stream */
1174 for (mes = (guint8 *) l->data; mes != NULL && *mes != 0xff; ++mes) {
1175 if (*mes == stream->id) {
1176 /* we are in this group; let's check if we've already activated streams
1177 * that are in the same group (and hence mutually exclusive to this
1179 for (mes = (guint8 *) l->data; mes != NULL && *mes != 0xff; ++mes) {
1182 for (i = 0; i < demux->num_streams; ++i) {
1183 if (demux->stream[i].id == *mes && demux->stream[i].active) {
1184 GST_LOG_OBJECT (demux, "stream with ID %d is mutually exclusive "
1185 "to already active stream with ID %d", stream->id,
1186 demux->stream[i].id);
1191 /* we can only be in this group once, let's break out and move on to
1192 * the next mutual exclusion group */
1203 gst_asf_demux_check_activate_streams (GstASFDemux * demux, gboolean force)
1207 if (demux->activated_streams)
1210 if (!all_streams_prerolled (demux) && !force) {
1211 GST_DEBUG_OBJECT (demux, "not all streams with data beyond preroll yet");
1215 for (i = 0; i < demux->num_streams; ++i) {
1216 AsfStream *stream = &demux->stream[i];
1218 if (stream->payloads->len > 0) {
1219 /* we don't check mutual exclusion stuff here; either we have data for
1220 * a stream, then we active it, or we don't, then we'll ignore it */
1221 GST_LOG_OBJECT (stream->pad, "is prerolled - activate!");
1222 gst_asf_demux_activate_stream (demux, stream);
1224 GST_LOG_OBJECT (stream->pad, "no data, ignoring stream");
1228 gst_asf_demux_release_old_pads (demux);
1230 demux->activated_streams = TRUE;
1231 GST_LOG_OBJECT (demux, "signalling no more pads");
1232 gst_element_no_more_pads (GST_ELEMENT (demux));
1236 /* returns the stream that has a complete payload with the lowest timestamp
1237 * queued, or NULL (we push things by timestamp because during the internal
1238 * prerolling we might accumulate more data then the external queues can take,
1239 * so we'd lock up if we pushed all accumulated data for stream N in one go) */
1241 gst_asf_demux_find_stream_with_complete_payload (GstASFDemux * demux)
1243 AsfPayload *best_payload = NULL;
1244 AsfStream *best_stream = NULL;
1247 for (i = 0; i < demux->num_streams; ++i) {
1250 stream = &demux->stream[i];
1252 /* Don't push any data until we have at least one payload that falls within
1253 * the current segment. This way we can remove out-of-segment payloads that
1254 * don't need to be decoded after a seek, sending only data from the
1255 * keyframe directly before our segment start */
1256 if (stream->payloads->len > 0) {
1257 AsfPayload *payload;
1260 last_idx = stream->payloads->len - 1;
1261 payload = &g_array_index (stream->payloads, AsfPayload, last_idx);
1262 if (G_UNLIKELY (GST_CLOCK_TIME_IS_VALID (payload->ts) &&
1263 (payload->ts < demux->segment.start))) {
1264 if (G_UNLIKELY ((!demux->accurate) && payload->keyframe)) {
1265 GST_DEBUG_OBJECT (stream->pad,
1266 "Found keyframe, updating segment start to %" GST_TIME_FORMAT,
1267 GST_TIME_ARGS (payload->ts));
1268 demux->segment.start = payload->ts;
1269 demux->segment.time = payload->ts;
1271 GST_DEBUG_OBJECT (stream->pad, "Last queued payload has timestamp %"
1272 GST_TIME_FORMAT " which is before our segment start %"
1273 GST_TIME_FORMAT ", not pushing yet", GST_TIME_ARGS (payload->ts),
1274 GST_TIME_ARGS (demux->segment.start));
1279 /* Now see if there's a complete payload queued for this stream */
1281 payload = &g_array_index (stream->payloads, AsfPayload, 0);
1282 if (!gst_asf_payload_is_complete (payload))
1285 /* ... and whether its timestamp is lower than the current best */
1286 if (best_stream == NULL || best_payload->ts > payload->ts) {
1287 best_stream = stream;
1288 best_payload = payload;
1296 static GstFlowReturn
1297 gst_asf_demux_push_complete_payloads (GstASFDemux * demux, gboolean force)
1300 GstFlowReturn ret = GST_FLOW_OK;
1302 if (G_UNLIKELY (!demux->activated_streams)) {
1303 if (!gst_asf_demux_check_activate_streams (demux, force))
1305 /* streams are now activated */
1308 /* wait until we had a chance to "lock on" some payload's timestamp */
1309 if (G_UNLIKELY (demux->need_newsegment
1310 && !GST_CLOCK_TIME_IS_VALID (demux->segment_ts)))
1313 while ((stream = gst_asf_demux_find_stream_with_complete_payload (demux))) {
1314 AsfPayload *payload;
1316 payload = &g_array_index (stream->payloads, AsfPayload, 0);
1318 /* do we need to send a newsegment event */
1319 if ((G_UNLIKELY (demux->need_newsegment))) {
1321 /* safe default if insufficient upstream info */
1322 if (!GST_CLOCK_TIME_IS_VALID (demux->in_gap))
1325 if (demux->segment.stop == GST_CLOCK_TIME_NONE &&
1326 demux->segment.duration > 0) {
1327 /* slight HACK; prevent clipping of last bit */
1328 demux->segment.stop = demux->segment.duration + demux->in_gap;
1331 /* FIXME : only if ACCURATE ! */
1332 if (G_LIKELY (!demux->accurate
1333 && (GST_CLOCK_TIME_IS_VALID (payload->ts)))) {
1334 GST_DEBUG ("Adjusting newsegment start to %" GST_TIME_FORMAT,
1335 GST_TIME_ARGS (payload->ts));
1336 demux->segment.start = payload->ts;
1337 demux->segment.time = payload->ts;
1340 GST_DEBUG_OBJECT (demux, "sending new-segment event %" GST_SEGMENT_FORMAT,
1343 /* note: we fix up all timestamps to start from 0, so this should be ok */
1344 gst_asf_demux_send_event_unlocked (demux,
1345 gst_event_new_new_segment (FALSE, demux->segment.rate,
1346 GST_FORMAT_TIME, demux->segment.start, demux->segment.stop,
1347 demux->segment.start));
1349 /* now post any global tags we may have found */
1350 if (demux->taglist == NULL)
1351 demux->taglist = gst_tag_list_new ();
1353 gst_tag_list_add (demux->taglist, GST_TAG_MERGE_REPLACE,
1354 GST_TAG_CONTAINER_FORMAT, "ASF", NULL);
1356 GST_DEBUG_OBJECT (demux, "global tags: %" GST_PTR_FORMAT, demux->taglist);
1357 gst_element_found_tags (GST_ELEMENT (demux), demux->taglist);
1358 demux->taglist = NULL;
1360 demux->need_newsegment = FALSE;
1361 demux->segment_running = TRUE;
1364 /* Do we have tags pending for this stream? */
1365 if (G_UNLIKELY (stream->pending_tags)) {
1366 GST_LOG_OBJECT (stream->pad, "%" GST_PTR_FORMAT, stream->pending_tags);
1367 gst_element_found_tags_for_pad (GST_ELEMENT (demux), stream->pad,
1368 stream->pending_tags);
1369 stream->pending_tags = NULL;
1372 /* We have the whole packet now so we should push the packet to
1373 * the src pad now. First though we should check if we need to do
1375 if (G_UNLIKELY (demux->span > 1)) {
1376 gst_asf_demux_descramble_buffer (demux, stream, &payload->buf);
1379 payload->buf = gst_buffer_make_metadata_writable (payload->buf);
1381 if (G_LIKELY (!payload->keyframe)) {
1382 GST_BUFFER_FLAG_SET (payload->buf, GST_BUFFER_FLAG_DELTA_UNIT);
1385 if (G_UNLIKELY (stream->discont)) {
1386 GST_DEBUG_OBJECT (stream->pad, "marking DISCONT on stream");
1387 GST_BUFFER_FLAG_SET (payload->buf, GST_BUFFER_FLAG_DISCONT);
1388 stream->discont = FALSE;
1391 if (G_UNLIKELY (stream->is_video && payload->par_x && payload->par_y &&
1392 (payload->par_x != stream->par_x) &&
1393 (payload->par_y != stream->par_y))) {
1394 GST_DEBUG ("Updating PAR (%d/%d => %d/%d)",
1395 stream->par_x, stream->par_y, payload->par_x, payload->par_y);
1396 stream->par_x = payload->par_x;
1397 stream->par_y = payload->par_y;
1398 gst_caps_set_simple (stream->caps, "pixel-aspect-ratio",
1399 GST_TYPE_FRACTION, stream->par_x, stream->par_y, NULL);
1400 gst_pad_set_caps (stream->pad, stream->caps);
1403 if (G_UNLIKELY (stream->interlaced != payload->interlaced)) {
1404 GST_DEBUG ("Updating interlaced status (%d => %d)", stream->interlaced,
1405 payload->interlaced);
1406 stream->interlaced = payload->interlaced;
1407 gst_caps_set_simple (stream->caps, "interlaced", G_TYPE_BOOLEAN,
1408 stream->interlaced, NULL);
1411 gst_buffer_set_caps (payload->buf, stream->caps);
1413 /* (sort of) interpolate timestamps using upstream "frame of reference",
1414 * typically useful for live src, but might (unavoidably) mess with
1415 * position reporting if a live src is playing not so live content
1416 * (e.g. rtspsrc taking some time to fall back to tcp) */
1417 GST_BUFFER_TIMESTAMP (payload->buf) = payload->ts + demux->in_gap;
1418 if (payload->duration == GST_CLOCK_TIME_NONE
1419 && stream->ext_props.avg_time_per_frame != 0)
1420 GST_BUFFER_DURATION (payload->buf) =
1421 stream->ext_props.avg_time_per_frame * 100;
1423 GST_BUFFER_DURATION (payload->buf) = payload->duration;
1425 /* FIXME: we should really set durations on buffers if we can */
1427 GST_LOG_OBJECT (stream->pad, "pushing buffer, ts=%" GST_TIME_FORMAT
1428 ", dur=%" GST_TIME_FORMAT " size=%u",
1429 GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (payload->buf)),
1430 GST_TIME_ARGS (GST_BUFFER_DURATION (payload->buf)),
1431 GST_BUFFER_SIZE (payload->buf));
1433 ret = gst_pad_push (stream->pad, payload->buf);
1434 ret = gst_asf_demux_aggregate_flow_return (demux, stream, ret);
1435 payload->buf = NULL;
1436 g_array_remove_index (stream->payloads, 0);
1438 /* Break out as soon as we have an issue */
1439 if (G_UNLIKELY (ret != GST_FLOW_OK))
1447 gst_asf_demux_check_buffer_is_header (GstASFDemux * demux, GstBuffer * buf)
1450 g_assert (buf != NULL);
1452 GST_LOG_OBJECT (demux, "Checking if buffer is a header");
1454 /* we return false on buffer too small */
1455 if (GST_BUFFER_SIZE (buf) < ASF_OBJECT_HEADER_SIZE)
1458 /* check if it is a header */
1459 asf_demux_peek_object (demux, GST_BUFFER_DATA (buf),
1460 ASF_OBJECT_HEADER_SIZE, &obj, TRUE);
1461 if (obj.id == ASF_OBJ_HEADER) {
1468 gst_asf_demux_check_chained_asf (GstASFDemux * demux)
1470 guint64 off = demux->data_offset + (demux->packet * demux->packet_size);
1471 GstFlowReturn ret = GST_FLOW_OK;
1472 GstBuffer *buf = NULL;
1473 gboolean header = FALSE;
1475 /* TODO maybe we should skip index objects after the data and look
1476 * further for a new header */
1477 if (gst_asf_demux_pull_data (demux, off, ASF_OBJECT_HEADER_SIZE, &buf, &ret)) {
1478 g_assert (buf != NULL);
1479 /* check if it is a header */
1480 if (gst_asf_demux_check_buffer_is_header (demux, buf)) {
1481 GST_DEBUG_OBJECT (demux, "new base offset: %" G_GUINT64_FORMAT, off);
1482 demux->base_offset = off;
1486 gst_buffer_unref (buf);
1493 gst_asf_demux_loop (GstASFDemux * demux)
1495 GstFlowReturn flow = GST_FLOW_OK;
1496 GstBuffer *buf = NULL;
1498 gboolean sent_eos = FALSE;
1500 if (G_UNLIKELY (demux->state == GST_ASF_DEMUX_STATE_HEADER)) {
1501 if (!gst_asf_demux_pull_headers (demux)) {
1502 flow = GST_FLOW_ERROR;
1506 gst_asf_demux_pull_indices (demux);
1509 g_assert (demux->state == GST_ASF_DEMUX_STATE_DATA);
1511 if (G_UNLIKELY (demux->num_packets != 0
1512 && demux->packet >= demux->num_packets))
1515 GST_LOG_OBJECT (demux, "packet %u/%u", (guint) demux->packet + 1,
1516 (guint) demux->num_packets);
1518 off = demux->data_offset + (demux->packet * demux->packet_size);
1520 if (G_UNLIKELY (!gst_asf_demux_pull_data (demux, off,
1521 demux->packet_size * demux->speed_packets, &buf, &flow))) {
1522 GST_DEBUG_OBJECT (demux, "got flow %s", gst_flow_get_name (flow));
1523 if (flow == GST_FLOW_UNEXPECTED)
1525 else if (flow == GST_FLOW_WRONG_STATE) {
1526 GST_DEBUG_OBJECT (demux, "Not fatal");
1532 if (G_LIKELY (demux->speed_packets == 1)) {
1533 /* FIXME: maybe we should just skip broken packets and error out only
1534 * after a few broken packets in a row? */
1535 if (G_UNLIKELY (!gst_asf_demux_parse_packet (demux, buf))) {
1536 /* when we don't know when the data object ends, we should check
1537 * for a chained asf */
1538 if (demux->num_packets == 0) {
1539 if (gst_asf_demux_check_buffer_is_header (demux, buf)) {
1540 GST_INFO_OBJECT (demux, "Chained asf found");
1541 demux->base_offset = off;
1542 gst_asf_demux_reset (demux, TRUE);
1543 gst_buffer_unref (buf);
1550 flow = gst_asf_demux_push_complete_payloads (demux, FALSE);
1556 for (n = 0; n < demux->speed_packets; n++) {
1560 gst_buffer_create_sub (buf, n * demux->packet_size,
1561 demux->packet_size);
1562 /* FIXME: maybe we should just skip broken packets and error out only
1563 * after a few broken packets in a row? */
1564 if (G_UNLIKELY (!gst_asf_demux_parse_packet (demux, sub))) {
1565 /* when we don't know when the data object ends, we should check
1566 * for a chained asf */
1567 if (demux->num_packets == 0) {
1568 if (gst_asf_demux_check_buffer_is_header (demux, sub)) {
1569 GST_INFO_OBJECT (demux, "Chained asf found");
1570 demux->base_offset = off + n * demux->packet_size;
1571 gst_asf_demux_reset (demux, TRUE);
1572 gst_buffer_unref (sub);
1573 gst_buffer_unref (buf);
1580 gst_buffer_unref (sub);
1582 flow = gst_asf_demux_push_complete_payloads (demux, FALSE);
1588 /* reset speed pull */
1589 demux->speed_packets = 1;
1592 gst_buffer_unref (buf);
1594 if (G_UNLIKELY (demux->num_packets > 0
1595 && demux->packet >= demux->num_packets)) {
1596 GST_LOG_OBJECT (demux, "reached EOS");
1600 if (G_UNLIKELY (flow != GST_FLOW_OK)) {
1601 GST_DEBUG_OBJECT (demux, "pushing complete payloads failed");
1605 /* check if we're at the end of the configured segment */
1606 /* FIXME: check if segment end reached etc. */
1612 /* if we haven't activated our streams yet, this might be because we have
1613 * less data queued than required for preroll; force stream activation and
1614 * send any pending payloads before sending EOS */
1615 if (!demux->activated_streams)
1616 gst_asf_demux_push_complete_payloads (demux, TRUE);
1618 /* we want to push an eos or post a segment-done in any case */
1619 if (demux->segment.flags & GST_SEEK_FLAG_SEGMENT) {
1622 /* for segment playback we need to post when (in stream time)
1623 * we stopped, this is either stop (when set) or the duration. */
1624 if ((stop = demux->segment.stop) == -1)
1625 stop = demux->segment.duration;
1627 GST_INFO_OBJECT (demux, "Posting segment-done, at end of segment");
1628 gst_element_post_message (GST_ELEMENT_CAST (demux),
1629 gst_message_new_segment_done (GST_OBJECT (demux), GST_FORMAT_TIME,
1631 } else if (flow != GST_FLOW_UNEXPECTED) {
1632 /* check if we have a chained asf, in case, we don't eos yet */
1633 if (gst_asf_demux_check_chained_asf (demux)) {
1634 GST_INFO_OBJECT (demux, "Chained ASF starting");
1635 gst_asf_demux_reset (demux, TRUE);
1639 /* normal playback, send EOS to all linked pads */
1640 GST_INFO_OBJECT (demux, "Sending EOS, at end of stream");
1641 gst_asf_demux_send_event_unlocked (demux, gst_event_new_eos ());
1643 /* ... and fall through to pause */
1647 GST_DEBUG_OBJECT (demux, "pausing task, flow return: %s",
1648 gst_flow_get_name (flow));
1649 demux->segment_running = FALSE;
1650 gst_pad_pause_task (demux->sinkpad);
1652 /* For the error cases (not EOS) */
1654 if (flow == GST_FLOW_UNEXPECTED)
1655 gst_asf_demux_send_event_unlocked (demux, gst_event_new_eos ());
1656 else if (flow < GST_FLOW_UNEXPECTED || flow == GST_FLOW_NOT_LINKED) {
1657 /* Post an error. Hopefully something else already has, but if not... */
1658 GST_ELEMENT_ERROR (demux, STREAM, FAILED,
1659 (_("Internal data stream error.")),
1660 ("streaming stopped, reason %s", gst_flow_get_name (flow)));
1669 GST_DEBUG_OBJECT (demux, "Read failed, doh");
1670 gst_asf_demux_send_event_unlocked (demux, gst_event_new_eos ());
1671 flow = GST_FLOW_UNEXPECTED;
1676 gst_buffer_unref (buf);
1677 GST_ELEMENT_ERROR (demux, STREAM, DEMUX, (NULL),
1678 ("Error parsing ASF packet %u", (guint) demux->packet));
1679 gst_asf_demux_send_event_unlocked (demux, gst_event_new_eos ());
1680 flow = GST_FLOW_ERROR;
1685 #define GST_ASF_DEMUX_CHECK_HEADER_YES 0
1686 #define GST_ASF_DEMUX_CHECK_HEADER_NO 1
1687 #define GST_ASF_DEMUX_CHECK_HEADER_NEED_DATA 2
1690 gst_asf_demux_check_header (GstASFDemux * demux)
1693 guint8 *cdata = (guint8 *) gst_adapter_peek (demux->adapter,
1694 ASF_OBJECT_HEADER_SIZE);
1695 if (cdata == NULL) /* need more data */
1696 return GST_ASF_DEMUX_CHECK_HEADER_NEED_DATA;
1698 asf_demux_peek_object (demux, cdata, ASF_OBJECT_HEADER_SIZE, &obj, FALSE);
1699 if (obj.id != ASF_OBJ_HEADER) {
1700 return GST_ASF_DEMUX_CHECK_HEADER_NO;
1702 return GST_ASF_DEMUX_CHECK_HEADER_YES;
1706 static GstFlowReturn
1707 gst_asf_demux_chain (GstPad * pad, GstBuffer * buf)
1709 GstFlowReturn ret = GST_FLOW_OK;
1712 demux = GST_ASF_DEMUX (GST_PAD_PARENT (pad));
1714 GST_LOG_OBJECT (demux, "buffer: size=%u, offset=%" G_GINT64_FORMAT ", time=%"
1715 GST_TIME_FORMAT, GST_BUFFER_SIZE (buf), GST_BUFFER_OFFSET (buf),
1716 GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)));
1718 if (G_UNLIKELY (GST_BUFFER_IS_DISCONT (buf))) {
1719 GST_DEBUG_OBJECT (demux, "received DISCONT");
1720 gst_asf_demux_mark_discont (demux);
1723 if (G_UNLIKELY ((!GST_CLOCK_TIME_IS_VALID (demux->in_gap) &&
1724 GST_BUFFER_TIMESTAMP_IS_VALID (buf)))) {
1725 demux->in_gap = GST_BUFFER_TIMESTAMP (buf) - demux->in_segment.start;
1726 GST_DEBUG_OBJECT (demux, "upstream segment start %" GST_TIME_FORMAT
1727 ", interpolation gap: %" GST_TIME_FORMAT,
1728 GST_TIME_ARGS (demux->in_segment.start), GST_TIME_ARGS (demux->in_gap));
1731 gst_adapter_push (demux->adapter, buf);
1733 switch (demux->state) {
1734 case GST_ASF_DEMUX_STATE_INDEX:{
1735 gint result = gst_asf_demux_check_header (demux);
1736 if (result == GST_ASF_DEMUX_CHECK_HEADER_NEED_DATA) /* need more data */
1739 if (result == GST_ASF_DEMUX_CHECK_HEADER_NO) {
1740 /* we don't care about this, probably an index */
1741 /* TODO maybe would be smarter to skip all the indices
1742 * until we got a new header or EOS to decide */
1743 GST_LOG_OBJECT (demux, "Received index object, its EOS");
1746 GST_INFO_OBJECT (demux, "Chained asf starting");
1747 /* cleanup and get ready for a chained asf */
1748 gst_asf_demux_reset (demux, TRUE);
1752 case GST_ASF_DEMUX_STATE_HEADER:{
1753 ret = gst_asf_demux_chain_headers (demux);
1754 if (demux->state != GST_ASF_DEMUX_STATE_DATA)
1756 /* otherwise fall through */
1758 case GST_ASF_DEMUX_STATE_DATA:
1762 data_size = demux->packet_size;
1764 while (gst_adapter_available (demux->adapter) >= data_size) {
1767 /* we don't know the length of the stream
1768 * check for a chained asf everytime */
1769 if (demux->num_packets == 0) {
1770 gint result = gst_asf_demux_check_header (demux);
1772 if (result == GST_ASF_DEMUX_CHECK_HEADER_YES) {
1773 GST_INFO_OBJECT (demux, "Chained asf starting");
1774 /* cleanup and get ready for a chained asf */
1775 gst_asf_demux_reset (demux, TRUE);
1778 } else if (G_UNLIKELY (demux->num_packets != 0 && demux->packet >= 0
1779 && demux->packet >= demux->num_packets)) {
1780 /* do not overshoot data section when streaming */
1784 buf = gst_adapter_take_buffer (demux->adapter, data_size);
1786 /* FIXME: maybe we should just skip broken packets and error out only
1787 * after a few broken packets in a row? */
1788 if (G_UNLIKELY (!gst_asf_demux_parse_packet (demux, buf))) {
1789 GST_WARNING_OBJECT (demux, "Parse error");
1792 gst_buffer_unref (buf);
1794 ret = gst_asf_demux_push_complete_payloads (demux, FALSE);
1796 if (demux->packet >= 0)
1799 if (G_UNLIKELY (demux->num_packets != 0 && demux->packet >= 0
1800 && demux->packet >= demux->num_packets)) {
1801 demux->state = GST_ASF_DEMUX_STATE_INDEX;
1806 g_assert_not_reached ();
1810 if (ret != GST_FLOW_OK)
1811 GST_DEBUG_OBJECT (demux, "flow: %s", gst_flow_get_name (ret));
1817 GST_DEBUG_OBJECT (demux, "Handled last packet, setting EOS");
1818 ret = GST_FLOW_UNEXPECTED;
1823 static inline gboolean
1824 gst_asf_demux_skip_bytes (guint num_bytes, guint8 ** p_data, guint64 * p_size)
1826 if (*p_size < num_bytes)
1829 *p_data += num_bytes;
1830 *p_size -= num_bytes;
1834 static inline guint8
1835 gst_asf_demux_get_uint8 (guint8 ** p_data, guint64 * p_size)
1839 g_assert (*p_size >= 1);
1840 ret = GST_READ_UINT8 (*p_data);
1841 *p_data += sizeof (guint8);
1842 *p_size -= sizeof (guint8);
1846 static inline guint16
1847 gst_asf_demux_get_uint16 (guint8 ** p_data, guint64 * p_size)
1851 g_assert (*p_size >= 2);
1852 ret = GST_READ_UINT16_LE (*p_data);
1853 *p_data += sizeof (guint16);
1854 *p_size -= sizeof (guint16);
1858 static inline guint32
1859 gst_asf_demux_get_uint32 (guint8 ** p_data, guint64 * p_size)
1863 g_assert (*p_size >= 4);
1864 ret = GST_READ_UINT32_LE (*p_data);
1865 *p_data += sizeof (guint32);
1866 *p_size -= sizeof (guint32);
1870 static inline guint64
1871 gst_asf_demux_get_uint64 (guint8 ** p_data, guint64 * p_size)
1875 g_assert (*p_size >= 8);
1876 ret = GST_READ_UINT64_LE (*p_data);
1877 *p_data += sizeof (guint64);
1878 *p_size -= sizeof (guint64);
1882 static inline guint32
1883 gst_asf_demux_get_var_length (guint8 type, guint8 ** p_data, guint64 * p_size)
1890 g_assert (*p_size >= 1);
1891 return gst_asf_demux_get_uint8 (p_data, p_size);
1894 g_assert (*p_size >= 2);
1895 return gst_asf_demux_get_uint16 (p_data, p_size);
1898 g_assert (*p_size >= 4);
1899 return gst_asf_demux_get_uint32 (p_data, p_size);
1902 g_assert_not_reached ();
1909 gst_asf_demux_get_buffer (GstBuffer ** p_buf, guint num_bytes_to_read,
1910 guint8 ** p_data, guint64 * p_size)
1914 if (*p_size < num_bytes_to_read)
1917 *p_buf = gst_buffer_new_and_alloc (num_bytes_to_read);
1918 memcpy (GST_BUFFER_DATA (*p_buf), *p_data, num_bytes_to_read);
1919 *p_data += num_bytes_to_read;
1920 *p_size -= num_bytes_to_read;
1925 gst_asf_demux_get_bytes (guint8 ** p_buf, guint num_bytes_to_read,
1926 guint8 ** p_data, guint64 * p_size)
1930 if (*p_size < num_bytes_to_read)
1933 *p_buf = g_memdup (*p_data, num_bytes_to_read);
1934 *p_data += num_bytes_to_read;
1935 *p_size -= num_bytes_to_read;
1940 gst_asf_demux_get_string (gchar ** p_str, guint16 * p_strlen,
1941 guint8 ** p_data, guint64 * p_size)
1951 s_length = gst_asf_demux_get_uint16 (p_data, p_size);
1954 *p_strlen = s_length;
1956 if (s_length == 0) {
1957 GST_WARNING ("zero-length string");
1958 *p_str = g_strdup ("");
1962 if (!gst_asf_demux_get_bytes (&s, s_length, p_data, p_size))
1965 g_assert (s != NULL);
1967 /* just because They don't exist doesn't
1968 * mean They are not out to get you ... */
1969 if (s[s_length - 1] != '\0') {
1970 s = g_realloc (s, s_length + 1);
1974 *p_str = (gchar *) s;
1980 gst_asf_demux_get_guid (ASFGuid * guid, guint8 ** p_data, guint64 * p_size)
1982 g_assert (*p_size >= 4 * sizeof (guint32));
1984 guid->v1 = gst_asf_demux_get_uint32 (p_data, p_size);
1985 guid->v2 = gst_asf_demux_get_uint32 (p_data, p_size);
1986 guid->v3 = gst_asf_demux_get_uint32 (p_data, p_size);
1987 guid->v4 = gst_asf_demux_get_uint32 (p_data, p_size);
1991 gst_asf_demux_get_stream_audio (asf_stream_audio * audio, guint8 ** p_data,
1994 if (*p_size < (2 + 2 + 4 + 4 + 2 + 2 + 2))
1997 /* WAVEFORMATEX Structure */
1998 audio->codec_tag = gst_asf_demux_get_uint16 (p_data, p_size);
1999 audio->channels = gst_asf_demux_get_uint16 (p_data, p_size);
2000 audio->sample_rate = gst_asf_demux_get_uint32 (p_data, p_size);
2001 audio->byte_rate = gst_asf_demux_get_uint32 (p_data, p_size);
2002 audio->block_align = gst_asf_demux_get_uint16 (p_data, p_size);
2003 audio->word_size = gst_asf_demux_get_uint16 (p_data, p_size);
2004 /* Codec specific data size */
2005 audio->size = gst_asf_demux_get_uint16 (p_data, p_size);
2010 gst_asf_demux_get_stream_video (asf_stream_video * video, guint8 ** p_data,
2013 if (*p_size < (4 + 4 + 1 + 2))
2016 video->width = gst_asf_demux_get_uint32 (p_data, p_size);
2017 video->height = gst_asf_demux_get_uint32 (p_data, p_size);
2018 video->unknown = gst_asf_demux_get_uint8 (p_data, p_size);
2019 video->size = gst_asf_demux_get_uint16 (p_data, p_size);
2024 gst_asf_demux_get_stream_video_format (asf_stream_video_format * fmt,
2025 guint8 ** p_data, guint64 * p_size)
2027 if (*p_size < (4 + 4 + 4 + 2 + 2 + 4 + 4 + 4 + 4 + 4 + 4))
2030 fmt->size = gst_asf_demux_get_uint32 (p_data, p_size);
2031 fmt->width = gst_asf_demux_get_uint32 (p_data, p_size);
2032 fmt->height = gst_asf_demux_get_uint32 (p_data, p_size);
2033 fmt->planes = gst_asf_demux_get_uint16 (p_data, p_size);
2034 fmt->depth = gst_asf_demux_get_uint16 (p_data, p_size);
2035 fmt->tag = gst_asf_demux_get_uint32 (p_data, p_size);
2036 fmt->image_size = gst_asf_demux_get_uint32 (p_data, p_size);
2037 fmt->xpels_meter = gst_asf_demux_get_uint32 (p_data, p_size);
2038 fmt->ypels_meter = gst_asf_demux_get_uint32 (p_data, p_size);
2039 fmt->num_colors = gst_asf_demux_get_uint32 (p_data, p_size);
2040 fmt->imp_colors = gst_asf_demux_get_uint32 (p_data, p_size);
2045 gst_asf_demux_get_stream (GstASFDemux * demux, guint16 id)
2049 for (i = 0; i < demux->num_streams; i++) {
2050 if (demux->stream[i].id == id)
2051 return &demux->stream[i];
2054 GST_WARNING ("Segment found for undefined stream: (%d)", id);
2059 gst_asf_demux_setup_pad (GstASFDemux * demux, GstPad * src_pad,
2060 GstCaps * caps, guint16 id, gboolean is_video, GstTagList * tags)
2064 gst_pad_use_fixed_caps (src_pad);
2065 gst_pad_set_caps (src_pad, caps);
2067 gst_pad_set_event_function (src_pad,
2068 GST_DEBUG_FUNCPTR (gst_asf_demux_handle_src_event));
2069 gst_pad_set_query_type_function (src_pad,
2070 GST_DEBUG_FUNCPTR (gst_asf_demux_get_src_query_types));
2071 gst_pad_set_query_function (src_pad,
2072 GST_DEBUG_FUNCPTR (gst_asf_demux_handle_src_query));
2074 stream = &demux->stream[demux->num_streams];
2075 stream->caps = caps;
2076 stream->pad = src_pad;
2078 stream->fps_known = !is_video; /* bit hacky for audio */
2079 stream->is_video = is_video;
2080 stream->pending_tags = tags;
2081 stream->discont = TRUE;
2085 st = gst_caps_get_structure (caps, 0);
2086 if (gst_structure_get_fraction (st, "pixel-aspect-ratio", &par_x, &par_y) &&
2087 par_x > 0 && par_y > 0) {
2088 GST_DEBUG ("PAR %d/%d", par_x, par_y);
2089 stream->par_x = par_x;
2090 stream->par_y = par_y;
2094 stream->payloads = g_array_new (FALSE, FALSE, sizeof (AsfPayload));
2096 GST_INFO ("Created pad %s for stream %u with caps %" GST_PTR_FORMAT,
2097 GST_PAD_NAME (src_pad), demux->num_streams, caps);
2099 ++demux->num_streams;
2101 stream->active = FALSE;
2105 gst_asf_demux_add_audio_stream (GstASFDemux * demux,
2106 asf_stream_audio * audio, guint16 id, guint8 ** p_data, guint64 * p_size)
2108 GstTagList *tags = NULL;
2109 GstBuffer *extradata = NULL;
2112 guint16 size_left = 0;
2113 gchar *codec_name = NULL;
2116 size_left = audio->size;
2118 /* Create the audio pad */
2119 name = g_strdup_printf ("audio_%02d", demux->num_audio_streams);
2121 src_pad = gst_pad_new_from_static_template (&audio_src_template, name);
2124 /* Swallow up any left over data and set up the
2125 * standard properties from the header info */
2127 GST_INFO_OBJECT (demux, "Audio header contains %d bytes of "
2128 "codec specific data", size_left);
2130 g_assert (size_left <= *p_size);
2131 gst_asf_demux_get_buffer (&extradata, size_left, p_data, p_size);
2134 /* asf_stream_audio is the same as gst_riff_strf_auds, but with an
2135 * additional two bytes indicating extradata. */
2136 caps = gst_riff_create_audio_caps (audio->codec_tag, NULL,
2137 (gst_riff_strf_auds *) audio, extradata, NULL, &codec_name);
2140 caps = gst_caps_new_simple ("audio/x-asf-unknown", "codec_id",
2141 G_TYPE_INT, (gint) audio->codec_tag, NULL);
2144 /* Informing about that audio format we just added */
2146 tags = gst_tag_list_new ();
2147 gst_tag_list_add (tags, GST_TAG_MERGE_APPEND, GST_TAG_AUDIO_CODEC,
2149 g_free (codec_name);
2153 gst_buffer_unref (extradata);
2155 GST_INFO ("Adding audio stream #%u, id %u codec %u (0x%04x), tags=%"
2156 GST_PTR_FORMAT, demux->num_audio_streams, id, audio->codec_tag,
2157 audio->codec_tag, tags);
2159 ++demux->num_audio_streams;
2161 gst_asf_demux_setup_pad (demux, src_pad, caps, id, FALSE, tags);
2165 gst_asf_demux_add_video_stream (GstASFDemux * demux,
2166 asf_stream_video_format * video, guint16 id,
2167 guint8 ** p_data, guint64 * p_size)
2169 GstTagList *tags = NULL;
2170 GstBuffer *extradata = NULL;
2174 gchar *codec_name = NULL;
2175 gint size_left = video->size - 40;
2177 /* Create the video pad */
2178 name = g_strdup_printf ("video_%02d", demux->num_video_streams);
2179 src_pad = gst_pad_new_from_static_template (&video_src_template, name);
2182 /* Now try some gstreamer formatted MIME types (from gst_avi_demux_strf_vids) */
2184 GST_LOG ("Video header has %d bytes of codec specific data", size_left);
2185 g_assert (size_left <= *p_size);
2186 gst_asf_demux_get_buffer (&extradata, size_left, p_data, p_size);
2189 GST_DEBUG ("video codec %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (video->tag));
2191 /* yes, asf_stream_video_format and gst_riff_strf_vids are the same */
2192 caps = gst_riff_create_video_caps (video->tag, NULL,
2193 (gst_riff_strf_vids *) video, extradata, NULL, &codec_name);
2196 caps = gst_caps_new_simple ("video/x-asf-unknown", "fourcc",
2197 GST_TYPE_FOURCC, video->tag, NULL);
2202 s = gst_asf_demux_get_metadata_for_stream (demux, id);
2203 if (gst_structure_get_int (s, "AspectRatioX", &ax) &&
2204 gst_structure_get_int (s, "AspectRatioY", &ay) && (ax > 0 && ay > 0)) {
2205 gst_caps_set_simple (caps, "pixel-aspect-ratio", GST_TYPE_FRACTION,
2210 /* retry with the global metadata */
2211 GST_DEBUG ("Retrying with global metadata %" GST_PTR_FORMAT,
2212 demux->global_metadata);
2213 s = demux->global_metadata;
2214 if (gst_structure_get_uint (s, "AspectRatioX", &ax) &&
2215 gst_structure_get_uint (s, "AspectRatioY", &ay)) {
2216 GST_DEBUG ("ax:%d, ay:%d", ax, ay);
2217 if (ax > 0 && ay > 0)
2218 gst_caps_set_simple (caps, "pixel-aspect-ratio", GST_TYPE_FRACTION,
2222 s = gst_caps_get_structure (caps, 0);
2223 gst_structure_remove_field (s, "framerate");
2226 /* add fourcc format to caps, some proprietary decoders seem to need it */
2227 gst_caps_set_simple (caps, "format", GST_TYPE_FOURCC, video->tag, NULL);
2230 tags = gst_tag_list_new ();
2231 gst_tag_list_add (tags, GST_TAG_MERGE_APPEND, GST_TAG_VIDEO_CODEC,
2233 g_free (codec_name);
2237 gst_buffer_unref (extradata);
2239 GST_INFO ("Adding video stream #%u, id %u, codec %"
2240 GST_FOURCC_FORMAT " (0x%08x)", demux->num_video_streams, id,
2241 GST_FOURCC_ARGS (video->tag), video->tag);
2243 ++demux->num_video_streams;
2245 gst_asf_demux_setup_pad (demux, src_pad, caps, id, TRUE, tags);
2249 gst_asf_demux_activate_stream (GstASFDemux * demux, AsfStream * stream)
2251 if (!stream->active) {
2252 GST_INFO_OBJECT (demux, "Activating stream %2u, pad %s, caps %"
2253 GST_PTR_FORMAT, stream->id, GST_PAD_NAME (stream->pad), stream->caps);
2254 gst_pad_set_active (stream->pad, TRUE);
2255 gst_element_add_pad (GST_ELEMENT_CAST (demux), stream->pad);
2256 stream->active = TRUE;
2261 gst_asf_demux_parse_stream_object (GstASFDemux * demux, guint8 * data,
2264 AsfCorrectionType correction_type;
2265 AsfStreamType stream_type;
2266 GstClockTime time_offset;
2267 gboolean is_encrypted;
2271 guint stream_specific_size;
2272 guint type_specific_size;
2275 /* Get the rest of the header's header */
2276 if (size < (16 + 16 + 8 + 4 + 4 + 2 + 4))
2277 goto not_enough_data;
2279 gst_asf_demux_get_guid (&guid, &data, &size);
2280 stream_type = gst_asf_demux_identify_guid (asf_stream_guids, &guid);
2282 gst_asf_demux_get_guid (&guid, &data, &size);
2283 correction_type = gst_asf_demux_identify_guid (asf_correction_guids, &guid);
2285 time_offset = gst_asf_demux_get_uint64 (&data, &size) * 100;
2287 type_specific_size = gst_asf_demux_get_uint32 (&data, &size);
2288 stream_specific_size = gst_asf_demux_get_uint32 (&data, &size);
2290 flags = gst_asf_demux_get_uint16 (&data, &size);
2291 stream_id = flags & 0x7f;
2292 is_encrypted = !!((flags & 0x8000) << 15);
2293 unknown = gst_asf_demux_get_uint32 (&data, &size);
2295 GST_DEBUG_OBJECT (demux, "Found stream %u, time_offset=%" GST_TIME_FORMAT,
2296 stream_id, GST_TIME_ARGS (time_offset));
2298 switch (stream_type) {
2299 case ASF_STREAM_AUDIO:{
2300 asf_stream_audio audio_object;
2302 if (!gst_asf_demux_get_stream_audio (&audio_object, &data, &size))
2303 goto not_enough_data;
2305 GST_INFO ("Object is an audio stream with %u bytes of additional data",
2308 gst_asf_demux_add_audio_stream (demux, &audio_object, stream_id,
2311 switch (correction_type) {
2312 case ASF_CORRECTION_ON:{
2313 guint span, packet_size, chunk_size, data_size, silence_data;
2315 GST_INFO ("Using error correction");
2317 if (size < (1 + 2 + 2 + 2 + 1))
2318 goto not_enough_data;
2320 span = gst_asf_demux_get_uint8 (&data, &size);
2321 packet_size = gst_asf_demux_get_uint16 (&data, &size);
2322 chunk_size = gst_asf_demux_get_uint16 (&data, &size);
2323 data_size = gst_asf_demux_get_uint16 (&data, &size);
2324 silence_data = gst_asf_demux_get_uint8 (&data, &size);
2326 /* FIXME: shouldn't this be per-stream? */
2329 GST_DEBUG_OBJECT (demux, "Descrambling ps:%u cs:%u ds:%u s:%u sd:%u",
2330 packet_size, chunk_size, data_size, span, silence_data);
2332 if (demux->span > 1) {
2333 if (chunk_size == 0 || ((packet_size / chunk_size) <= 1)) {
2334 /* Disable descrambling */
2337 /* FIXME: this else branch was added for
2338 * weird_al_yankovic - the saga begins.asf */
2339 demux->ds_packet_size = packet_size;
2340 demux->ds_chunk_size = chunk_size;
2343 /* Descambling is enabled */
2344 demux->ds_packet_size = packet_size;
2345 demux->ds_chunk_size = chunk_size;
2348 /* Now skip the rest of the silence data */
2350 gst_bytestream_flush (demux->bs, data_size - 1);
2352 /* FIXME: CHECKME. And why -1? */
2353 if (data_size > 1) {
2354 if (!gst_asf_demux_skip_bytes (data_size - 1, &data, &size)) {
2355 goto not_enough_data;
2361 case ASF_CORRECTION_OFF:{
2362 GST_INFO ("Error correction off");
2363 if (!gst_asf_demux_skip_bytes (stream_specific_size, &data, &size))
2364 goto not_enough_data;
2368 GST_ELEMENT_ERROR (demux, STREAM, DEMUX, (NULL),
2369 ("Audio stream using unknown error correction"));
2376 case ASF_STREAM_VIDEO:{
2377 asf_stream_video_format video_format_object;
2378 asf_stream_video video_object;
2381 if (!gst_asf_demux_get_stream_video (&video_object, &data, &size))
2382 goto not_enough_data;
2384 vsize = video_object.size - 40; /* Byte order gets offset by single byte */
2386 GST_INFO ("object is a video stream with %u bytes of "
2387 "additional data", vsize);
2389 if (!gst_asf_demux_get_stream_video_format (&video_format_object,
2391 goto not_enough_data;
2394 gst_asf_demux_add_video_stream (demux, &video_format_object, stream_id,
2401 GST_WARNING_OBJECT (demux, "Unknown stream type for stream %u",
2406 return gst_asf_demux_get_stream (demux, stream_id);
2410 GST_WARNING_OBJECT (demux, "Unexpected end of data parsing stream object");
2411 /* we'll error out later if we found no streams */
2416 static const gchar *
2417 gst_asf_demux_get_gst_tag_from_tag_name (const gchar * name_utf8)
2421 const gchar *asf_name;
2422 const gchar *gst_name;
2425 "WM/Genre", GST_TAG_GENRE}, {
2426 "WM/AlbumTitle", GST_TAG_ALBUM}, {
2427 "WM/AlbumArtist", GST_TAG_ARTIST}, {
2428 "WM/Picture", GST_TAG_IMAGE}, {
2429 "WM/Track", GST_TAG_TRACK_NUMBER}, {
2430 "WM/TrackNumber", GST_TAG_TRACK_NUMBER}, {
2431 "WM/Year", GST_TAG_DATE}
2432 /* { "WM/Composer", GST_TAG_COMPOSER } */
2437 if (name_utf8 == NULL) {
2438 GST_WARNING ("Failed to convert name to UTF8, skipping");
2442 out = strlen (name_utf8);
2444 for (i = 0; i < G_N_ELEMENTS (tags); ++i) {
2445 if (strncmp (tags[i].asf_name, name_utf8, out) == 0) {
2446 GST_LOG ("map tagname '%s' -> '%s'", name_utf8, tags[i].gst_name);
2447 return tags[i].gst_name;
2454 /* gst_asf_demux_add_global_tags() takes ownership of taglist! */
2456 gst_asf_demux_add_global_tags (GstASFDemux * demux, GstTagList * taglist)
2460 GST_DEBUG_OBJECT (demux, "adding global tags: %" GST_PTR_FORMAT, taglist);
2462 if (taglist == NULL)
2465 if (gst_tag_list_is_empty (taglist)) {
2466 gst_tag_list_free (taglist);
2470 t = gst_tag_list_merge (demux->taglist, taglist, GST_TAG_MERGE_APPEND);
2472 gst_tag_list_free (demux->taglist);
2473 gst_tag_list_free (taglist);
2475 GST_LOG_OBJECT (demux, "global tags now: %" GST_PTR_FORMAT, demux->taglist);
2478 #define ASF_DEMUX_DATA_TYPE_UTF16LE_STRING 0
2479 #define ASF_DEMUX_DATA_TYPE_BYTE_ARRAY 1
2480 #define ASF_DEMUX_DATA_TYPE_DWORD 3
2483 asf_demux_parse_picture_tag (GstTagList * tags, const guint8 * tag_data,
2487 const guint8 *img_data = NULL;
2488 guint32 img_data_len = 0;
2489 guint8 pic_type = 0;
2491 gst_byte_reader_init (&r, tag_data, tag_data_len);
2493 /* skip mime type string (we don't trust it and do our own typefinding),
2494 * and also skip the description string, since we don't use it */
2495 if (!gst_byte_reader_get_uint8 (&r, &pic_type) ||
2496 !gst_byte_reader_get_uint32_le (&r, &img_data_len) ||
2497 !gst_byte_reader_skip_string_utf16 (&r) ||
2498 !gst_byte_reader_skip_string_utf16 (&r) ||
2499 !gst_byte_reader_get_data (&r, img_data_len, &img_data)) {
2500 goto not_enough_data;
2504 if (!gst_tag_list_add_id3_image (tags, img_data, img_data_len, pic_type))
2505 GST_DEBUG ("failed to add image extracted from WM/Picture tag to taglist");
2511 GST_DEBUG ("Failed to read WM/Picture tag: not enough data");
2512 GST_MEMDUMP ("WM/Picture data", tag_data, tag_data_len);
2517 /* Extended Content Description Object */
2518 static GstFlowReturn
2519 gst_asf_demux_process_ext_content_desc (GstASFDemux * demux, guint8 * data,
2522 /* Other known (and unused) 'text/unicode' metadata available :
2525 * WM/MediaPrimaryClassID = {D1607DBC-E323-4BE2-86A1-48A42A28441E}
2526 * WMFSDKVersion = 9.00.00.2980
2527 * WMFSDKNeeded = 0.0.0.0000
2528 * WM/UniqueFileIdentifier = AMGa_id=R 15334;AMGp_id=P 5149;AMGt_id=T 2324984
2529 * WM/Publisher = 4AD
2531 * WM/ProviderRating = 8
2532 * WM/ProviderStyle = Rock (similar to WM/Genre)
2533 * WM/GenreID (similar to WM/Genre)
2534 * WM/TrackNumber (same as WM/Track but as a string)
2536 * Other known (and unused) 'non-text' metadata available :
2542 * We might want to read WM/TrackNumber and use atoi() if we don't have
2546 GstTagList *taglist;
2547 guint16 blockcount, i;
2549 GST_INFO_OBJECT (demux, "object is an extended content description");
2551 taglist = gst_tag_list_new ();
2553 /* Content Descriptor Count */
2555 goto not_enough_data;
2557 blockcount = gst_asf_demux_get_uint16 (&data, &size);
2559 for (i = 1; i <= blockcount; ++i) {
2560 const gchar *gst_tag_name;
2564 GValue tag_value = { 0, };
2567 gchar *name_utf8 = NULL;
2571 if (!gst_asf_demux_get_string (&name, &name_len, &data, &size))
2572 goto not_enough_data;
2576 goto not_enough_data;
2578 /* Descriptor Value Data Type */
2579 datatype = gst_asf_demux_get_uint16 (&data, &size);
2581 /* Descriptor Value (not really a string, but same thing reading-wise) */
2582 if (!gst_asf_demux_get_string (&value, &value_len, &data, &size)) {
2584 goto not_enough_data;
2588 g_convert (name, name_len, "UTF-8", "UTF-16LE", &in, &out, NULL);
2590 if (name_utf8 != NULL) {
2591 GST_DEBUG ("Found tag/metadata %s", name_utf8);
2593 gst_tag_name = gst_asf_demux_get_gst_tag_from_tag_name (name_utf8);
2594 GST_DEBUG ("gst_tag_name %s", GST_STR_NULL (gst_tag_name));
2597 case ASF_DEMUX_DATA_TYPE_UTF16LE_STRING:{
2600 value_utf8 = g_convert (value, value_len, "UTF-8", "UTF-16LE",
2603 /* get rid of tags with empty value */
2604 if (value_utf8 != NULL && *value_utf8 != '\0') {
2605 GST_DEBUG ("string value %s", value_utf8);
2607 value_utf8[out] = '\0';
2609 if (gst_tag_name != NULL) {
2610 if (strcmp (gst_tag_name, GST_TAG_DATE) == 0) {
2611 guint year = atoi (value_utf8);
2614 GDate *date = g_date_new_dmy (1, 1, year);
2616 g_value_init (&tag_value, GST_TYPE_DATE);
2617 gst_value_set_date (&tag_value, date);
2620 } else if (strcmp (gst_tag_name, GST_TAG_GENRE) == 0) {
2621 guint id3v1_genre_id;
2622 const gchar *genre_str;
2624 if (sscanf (value_utf8, "(%u)", &id3v1_genre_id) == 1 &&
2625 ((genre_str = gst_tag_id3_genre_get (id3v1_genre_id)))) {
2626 GST_DEBUG ("Genre: %s -> %s", value_utf8, genre_str);
2627 g_free (value_utf8);
2628 value_utf8 = g_strdup (genre_str);
2633 /* convert tag from string to other type if required */
2634 tag_type = gst_tag_get_type (gst_tag_name);
2635 g_value_init (&tag_value, tag_type);
2636 if (!gst_value_deserialize (&tag_value, value_utf8)) {
2637 GValue from_val = { 0, };
2639 g_value_init (&from_val, G_TYPE_STRING);
2640 g_value_set_string (&from_val, value_utf8);
2641 if (!g_value_transform (&from_val, &tag_value)) {
2642 GST_WARNING_OBJECT (demux,
2643 "Could not transform string tag to " "%s tag type %s",
2644 gst_tag_name, g_type_name (tag_type));
2645 g_value_unset (&tag_value);
2647 g_value_unset (&from_val);
2652 GST_DEBUG ("Setting metadata");
2653 g_value_init (&tag_value, G_TYPE_STRING);
2654 g_value_set_string (&tag_value, value_utf8);
2656 } else if (value_utf8 == NULL) {
2657 GST_WARNING ("Failed to convert string value to UTF8, skipping");
2659 GST_DEBUG ("Skipping empty string value for %s",
2660 GST_STR_NULL (gst_tag_name));
2662 g_free (value_utf8);
2665 case ASF_DEMUX_DATA_TYPE_BYTE_ARRAY:{
2667 if (!g_str_equal (gst_tag_name, GST_TAG_IMAGE)) {
2668 GST_FIXME ("Unhandled byte array tag %s",
2669 GST_STR_NULL (gst_tag_name));
2672 asf_demux_parse_picture_tag (taglist, (guint8 *) value,
2678 case ASF_DEMUX_DATA_TYPE_DWORD:{
2679 guint uint_val = GST_READ_UINT32_LE (value);
2681 /* this is the track number */
2682 g_value_init (&tag_value, G_TYPE_UINT);
2684 /* WM/Track counts from 0 */
2685 if (!strcmp (name_utf8, "WM/Track"))
2688 g_value_set_uint (&tag_value, uint_val);
2692 GST_DEBUG ("Skipping tag %s of type %d", gst_tag_name, datatype);
2697 if (G_IS_VALUE (&tag_value)) {
2699 GstTagMergeMode merge_mode = GST_TAG_MERGE_APPEND;
2701 /* WM/TrackNumber is more reliable than WM/Track, since the latter
2702 * is supposed to have a 0 base but is often wrongly written to start
2703 * from 1 as well, so prefer WM/TrackNumber when we have it: either
2704 * replace the value added earlier from WM/Track or put it first in
2705 * the list, so that it will get picked up by _get_uint() */
2706 if (strcmp (name_utf8, "WM/TrackNumber") == 0)
2707 merge_mode = GST_TAG_MERGE_REPLACE;
2709 gst_tag_list_add_values (taglist, merge_mode, gst_tag_name,
2712 GST_DEBUG ("Setting global metadata %s", name_utf8);
2713 gst_structure_set_value (demux->global_metadata, name_utf8,
2717 g_value_unset (&tag_value);
2726 gst_asf_demux_add_global_tags (demux, taglist);
2733 GST_WARNING ("Unexpected end of data parsing ext content desc object");
2734 gst_tag_list_free (taglist);
2735 return GST_FLOW_OK; /* not really fatal */
2739 static GstStructure *
2740 gst_asf_demux_get_metadata_for_stream (GstASFDemux * demux, guint stream_num)
2745 g_snprintf (sname, sizeof (sname), "stream-%u", stream_num);
2747 for (i = 0; i < gst_caps_get_size (demux->metadata); ++i) {
2750 s = gst_caps_get_structure (demux->metadata, i);
2751 if (gst_structure_has_name (s, sname))
2755 gst_caps_append_structure (demux->metadata, gst_structure_empty_new (sname));
2757 /* try lookup again; demux->metadata took ownership of the structure, so we
2758 * can't really make any assumptions about what happened to it, so we can't
2759 * just return it directly after appending it */
2760 return gst_asf_demux_get_metadata_for_stream (demux, stream_num);
2763 static GstFlowReturn
2764 gst_asf_demux_process_metadata (GstASFDemux * demux, guint8 * data,
2767 guint16 blockcount, i;
2769 GST_INFO_OBJECT (demux, "object is a metadata object");
2771 /* Content Descriptor Count */
2773 goto not_enough_data;
2775 blockcount = gst_asf_demux_get_uint16 (&data, &size);
2777 for (i = 0; i < blockcount; ++i) {
2779 guint16 lang_idx, stream_num, name_len, data_type;
2780 guint32 data_len, ival;
2783 if (size < (2 + 2 + 2 + 2 + 4))
2784 goto not_enough_data;
2786 lang_idx = gst_asf_demux_get_uint16 (&data, &size);
2787 stream_num = gst_asf_demux_get_uint16 (&data, &size);
2788 name_len = gst_asf_demux_get_uint16 (&data, &size);
2789 data_type = gst_asf_demux_get_uint16 (&data, &size);
2790 data_len = gst_asf_demux_get_uint32 (&data, &size);
2792 if (size < name_len + data_len)
2793 goto not_enough_data;
2795 /* convert name to UTF-8 */
2796 name_utf8 = g_convert ((gchar *) data, name_len, "UTF-8", "UTF-16LE",
2798 gst_asf_demux_skip_bytes (name_len, &data, &size);
2800 if (name_utf8 == NULL) {
2801 GST_WARNING ("Failed to convert value name to UTF8, skipping");
2802 gst_asf_demux_skip_bytes (data_len, &data, &size);
2806 if (data_type != ASF_DEMUX_DATA_TYPE_DWORD) {
2807 gst_asf_demux_skip_bytes (data_len, &data, &size);
2815 goto not_enough_data;
2818 ival = gst_asf_demux_get_uint32 (&data, &size);
2820 /* skip anything else there may be, just in case */
2821 gst_asf_demux_skip_bytes (data_len - 4, &data, &size);
2823 s = gst_asf_demux_get_metadata_for_stream (demux, stream_num);
2824 gst_structure_set (s, name_utf8, G_TYPE_INT, ival, NULL);
2828 GST_INFO_OBJECT (demux, "metadata = %" GST_PTR_FORMAT, demux->metadata);
2834 GST_WARNING ("Unexpected end of data parsing metadata object");
2835 return GST_FLOW_OK; /* not really fatal */
2839 static GstFlowReturn
2840 gst_asf_demux_process_header (GstASFDemux * demux, guint8 * data, guint64 size)
2842 GstFlowReturn ret = GST_FLOW_OK;
2843 guint32 i, num_objects;
2846 /* Get the rest of the header's header */
2847 if (size < (4 + 1 + 1))
2848 goto not_enough_data;
2850 num_objects = gst_asf_demux_get_uint32 (&data, &size);
2851 unknown = gst_asf_demux_get_uint8 (&data, &size);
2852 unknown = gst_asf_demux_get_uint8 (&data, &size);
2854 GST_INFO_OBJECT (demux, "object is a header with %u parts", num_objects);
2856 /* Loop through the header's objects, processing those */
2857 for (i = 0; i < num_objects; ++i) {
2858 GST_INFO_OBJECT (demux, "reading header part %u", i);
2859 ret = gst_asf_demux_process_object (demux, &data, &size);
2860 if (ret != GST_FLOW_OK) {
2861 GST_WARNING ("process_object returned %s", gst_asf_get_flow_name (ret));
2870 GST_ELEMENT_ERROR (demux, STREAM, DEMUX, (NULL),
2871 ("short read parsing HEADER object"));
2872 return GST_FLOW_ERROR;
2876 static GstFlowReturn
2877 gst_asf_demux_process_file (GstASFDemux * demux, guint8 * data, guint64 size)
2879 guint64 file_size, creation_time, packets_count;
2880 guint64 play_time, send_time, preroll;
2881 guint32 flags, min_pktsize, max_pktsize, min_bitrate;
2883 if (size < (16 + 8 + 8 + 8 + 8 + 8 + 8 + 4 + 4 + 4 + 4))
2884 goto not_enough_data;
2886 gst_asf_demux_skip_bytes (16, &data, &size); /* skip GUID */
2887 file_size = gst_asf_demux_get_uint64 (&data, &size);
2888 creation_time = gst_asf_demux_get_uint64 (&data, &size);
2889 packets_count = gst_asf_demux_get_uint64 (&data, &size);
2890 play_time = gst_asf_demux_get_uint64 (&data, &size);
2891 send_time = gst_asf_demux_get_uint64 (&data, &size);
2892 preroll = gst_asf_demux_get_uint64 (&data, &size);
2893 flags = gst_asf_demux_get_uint32 (&data, &size);
2894 min_pktsize = gst_asf_demux_get_uint32 (&data, &size);
2895 max_pktsize = gst_asf_demux_get_uint32 (&data, &size);
2896 min_bitrate = gst_asf_demux_get_uint32 (&data, &size);
2898 demux->broadcast = !!(flags & 0x01);
2899 demux->seekable = !!(flags & 0x02);
2901 GST_DEBUG_OBJECT (demux, "min_pktsize = %u", min_pktsize);
2902 GST_DEBUG_OBJECT (demux, "flags::broadcast = %d", demux->broadcast);
2903 GST_DEBUG_OBJECT (demux, "flags::seekable = %d", demux->seekable);
2905 if (demux->broadcast) {
2906 /* these fields are invalid if the broadcast flag is set */
2911 if (min_pktsize != max_pktsize)
2912 goto non_fixed_packet_size;
2914 demux->packet_size = max_pktsize;
2916 /* FIXME: do we need send_time as well? what is it? */
2917 if ((play_time * 100) >= (preroll * GST_MSECOND))
2918 demux->play_time = (play_time * 100) - (preroll * GST_MSECOND);
2920 demux->play_time = 0;
2922 demux->preroll = preroll * GST_MSECOND;
2924 /* initial latency */
2925 demux->latency = demux->preroll;
2927 if (demux->play_time == 0)
2928 demux->seekable = FALSE;
2930 GST_DEBUG_OBJECT (demux, "play_time %" GST_TIME_FORMAT,
2931 GST_TIME_ARGS (demux->play_time));
2932 GST_DEBUG_OBJECT (demux, "preroll %" GST_TIME_FORMAT,
2933 GST_TIME_ARGS (demux->preroll));
2935 if (demux->play_time > 0) {
2936 gst_segment_set_duration (&demux->segment, GST_FORMAT_TIME,
2940 GST_INFO ("object is a file with %" G_GUINT64_FORMAT " data packets",
2942 GST_INFO ("preroll = %" G_GUINT64_FORMAT, demux->preroll);
2947 non_fixed_packet_size:
2949 GST_ELEMENT_ERROR (demux, STREAM, DEMUX, (NULL),
2950 ("packet size must be fixed"));
2951 return GST_FLOW_ERROR;
2955 GST_ELEMENT_ERROR (demux, STREAM, DEMUX, (NULL),
2956 ("short read parsing FILE object"));
2957 return GST_FLOW_ERROR;
2961 /* Content Description Object */
2962 static GstFlowReturn
2963 gst_asf_demux_process_comment (GstASFDemux * demux, guint8 * data, guint64 size)
2967 const gchar *gst_tag;
2972 GST_TAG_TITLE, 0, NULL}, {
2973 GST_TAG_ARTIST, 0, NULL}, {
2974 GST_TAG_COPYRIGHT, 0, NULL}, {
2975 GST_TAG_DESCRIPTION, 0, NULL}, {
2976 GST_TAG_COMMENT, 0, NULL}
2978 GstTagList *taglist;
2979 GValue value = { 0 };
2983 GST_INFO_OBJECT (demux, "object is a comment");
2985 if (size < (2 + 2 + 2 + 2 + 2))
2986 goto not_enough_data;
2988 tags[0].val_length = gst_asf_demux_get_uint16 (&data, &size);
2989 tags[1].val_length = gst_asf_demux_get_uint16 (&data, &size);
2990 tags[2].val_length = gst_asf_demux_get_uint16 (&data, &size);
2991 tags[3].val_length = gst_asf_demux_get_uint16 (&data, &size);
2992 tags[4].val_length = gst_asf_demux_get_uint16 (&data, &size);
2994 GST_DEBUG_OBJECT (demux, "Comment lengths: title=%d author=%d copyright=%d "
2995 "description=%d rating=%d", tags[0].val_length, tags[1].val_length,
2996 tags[2].val_length, tags[3].val_length, tags[4].val_length);
2998 for (i = 0; i < G_N_ELEMENTS (tags); ++i) {
2999 if (size < tags[i].val_length)
3000 goto not_enough_data;
3002 /* might be just '/0', '/0'... */
3003 if (tags[i].val_length > 2 && tags[i].val_length % 2 == 0) {
3004 /* convert to UTF-8 */
3005 tags[i].val_utf8 = g_convert ((gchar *) data, tags[i].val_length,
3006 "UTF-8", "UTF-16LE", &in, &out, NULL);
3008 gst_asf_demux_skip_bytes (tags[i].val_length, &data, &size);
3011 /* parse metadata into taglist */
3012 taglist = gst_tag_list_new ();
3013 g_value_init (&value, G_TYPE_STRING);
3014 for (i = 0; i < G_N_ELEMENTS (tags); ++i) {
3015 if (tags[i].val_utf8 && strlen (tags[i].val_utf8) > 0 && tags[i].gst_tag) {
3016 g_value_set_string (&value, tags[i].val_utf8);
3017 gst_tag_list_add_values (taglist, GST_TAG_MERGE_APPEND,
3018 tags[i].gst_tag, &value, NULL);
3021 g_value_unset (&value);
3023 gst_asf_demux_add_global_tags (demux, taglist);
3025 for (i = 0; i < G_N_ELEMENTS (tags); ++i)
3026 g_free (tags[i].val_utf8);
3032 GST_WARNING_OBJECT (demux, "unexpectedly short of data while processing "
3033 "comment tag section %d, skipping comment object", i);
3034 for (i = 0; i < G_N_ELEMENTS (tags); i++)
3035 g_free (tags[i].val_utf8);
3036 return GST_FLOW_OK; /* not really fatal */
3040 static GstFlowReturn
3041 gst_asf_demux_process_bitrate_props_object (GstASFDemux * demux, guint8 * data,
3044 guint16 num_streams, i;
3048 goto not_enough_data;
3050 num_streams = gst_asf_demux_get_uint16 (&data, &size);
3052 GST_INFO ("object is a bitrate properties object with %u streams",
3055 if (size < (num_streams * (2 + 4)))
3056 goto not_enough_data;
3058 for (i = 0; i < num_streams; ++i) {
3062 stream_id = gst_asf_demux_get_uint16 (&data, &size);
3063 bitrate = gst_asf_demux_get_uint32 (&data, &size);
3065 if (stream_id < GST_ASF_DEMUX_NUM_STREAM_IDS) {
3066 GST_DEBUG_OBJECT (demux, "bitrate of stream %u = %u", stream_id, bitrate);
3067 stream = gst_asf_demux_get_stream (demux, stream_id);
3069 if (stream->pending_tags == NULL)
3070 stream->pending_tags = gst_tag_list_new ();
3071 gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
3072 GST_TAG_BITRATE, bitrate, NULL);
3074 GST_WARNING_OBJECT (demux, "Stream id %u wasn't found", stream_id);
3077 GST_WARNING ("stream id %u is too large", stream_id);
3085 GST_WARNING_OBJECT (demux, "short read parsing bitrate props object!");
3086 return GST_FLOW_OK; /* not really fatal */
3090 static GstFlowReturn
3091 gst_asf_demux_process_header_ext (GstASFDemux * demux, guint8 * data,
3094 GstFlowReturn ret = GST_FLOW_OK;
3097 /* Get the rest of the header's header */
3098 if (size < (16 + 2 + 4))
3099 goto not_enough_data;
3101 /* skip GUID and two other bytes */
3102 gst_asf_demux_skip_bytes (16 + 2, &data, &size);
3103 hdr_size = gst_asf_demux_get_uint32 (&data, &size);
3105 GST_INFO ("extended header object with a size of %u bytes", (guint) size);
3107 /* FIXME: does data_size include the rest of the header that we have read? */
3108 if (hdr_size > size)
3109 goto not_enough_data;
3111 while (hdr_size > 0) {
3112 ret = gst_asf_demux_process_object (demux, &data, &hdr_size);
3113 if (ret != GST_FLOW_OK)
3121 GST_ELEMENT_ERROR (demux, STREAM, DEMUX, (NULL),
3122 ("short read parsing extended header object"));
3123 return GST_FLOW_ERROR;
3127 static GstFlowReturn
3128 gst_asf_demux_process_language_list (GstASFDemux * demux, guint8 * data,
3134 goto not_enough_data;
3136 if (demux->languages) {
3137 GST_WARNING ("More than one LANGUAGE_LIST object in stream");
3138 g_strfreev (demux->languages);
3139 demux->languages = NULL;
3140 demux->num_languages = 0;
3143 demux->num_languages = gst_asf_demux_get_uint16 (&data, &size);
3144 GST_LOG ("%u languages:", demux->num_languages);
3146 demux->languages = g_new0 (gchar *, demux->num_languages + 1);
3147 for (i = 0; i < demux->num_languages; ++i) {
3148 guint8 len, *lang_data = NULL;
3151 goto not_enough_data;
3152 len = gst_asf_demux_get_uint8 (&data, &size);
3153 if (gst_asf_demux_get_bytes (&lang_data, len, &data, &size)) {
3156 utf8 = g_convert ((gchar *) lang_data, len, "UTF-8", "UTF-16LE", NULL,
3159 /* truncate "en-us" etc. to just "en" */
3160 if (utf8 && strlen (utf8) >= 5 && (utf8[2] == '-' || utf8[2] == '_')) {
3163 GST_DEBUG ("[%u] %s", i, GST_STR_NULL (utf8));
3164 demux->languages[i] = utf8;
3167 goto not_enough_data;
3175 GST_WARNING_OBJECT (demux, "short read parsing language list object!");
3176 g_free (demux->languages);
3177 demux->languages = NULL;
3178 return GST_FLOW_OK; /* not fatal */
3182 static GstFlowReturn
3183 gst_asf_demux_process_simple_index (GstASFDemux * demux, guint8 * data,
3186 GstClockTime interval;
3187 guint32 x, count, i;
3189 if (size < (16 + 8 + 4 + 4))
3190 goto not_enough_data;
3193 gst_asf_demux_skip_bytes (16, &data, &size);
3194 interval = gst_asf_demux_get_uint64 (&data, &size) * (GstClockTime) 100;
3195 x = gst_asf_demux_get_uint32 (&data, &size);
3196 count = gst_asf_demux_get_uint32 (&data, &size);
3198 demux->sidx_interval = interval;
3199 demux->sidx_num_entries = count;
3200 g_free (demux->sidx_entries);
3201 demux->sidx_entries = g_new0 (AsfSimpleIndexEntry, count);
3203 for (i = 0; i < count; ++i) {
3204 if (G_UNLIKELY (size <= 6))
3206 demux->sidx_entries[i].packet = gst_asf_demux_get_uint32 (&data, &size);
3207 demux->sidx_entries[i].count = gst_asf_demux_get_uint16 (&data, &size);
3208 GST_LOG_OBJECT (demux, "%" GST_TIME_FORMAT " = packet %4u count : %2d",
3209 GST_TIME_ARGS (i * interval), demux->sidx_entries[i].packet,
3210 demux->sidx_entries[i].count);
3213 GST_DEBUG_OBJECT (demux, "simple index object with 0 entries");
3220 GST_WARNING_OBJECT (demux, "short read parsing simple index object!");
3221 return GST_FLOW_OK; /* not fatal */
3225 static GstFlowReturn
3226 gst_asf_demux_process_advanced_mutual_exclusion (GstASFDemux * demux,
3227 guint8 * data, guint64 size)
3233 if (size < 16 + 2 + (2 * 2))
3234 goto not_enough_data;
3236 gst_asf_demux_get_guid (&guid, &data, &size);
3237 num = gst_asf_demux_get_uint16 (&data, &size);
3240 GST_WARNING_OBJECT (demux, "nonsensical mutually exclusive streams count");
3244 if (size < (num * sizeof (guint16)))
3245 goto not_enough_data;
3247 /* read mutually exclusive stream numbers */
3248 mes = g_new (guint8, num + 1);
3249 for (i = 0; i < num; ++i) {
3250 mes[i] = gst_asf_demux_get_uint16 (&data, &size) & 0x7f;
3251 GST_LOG_OBJECT (demux, "mutually exclusive: stream #%d", mes[i]);
3254 /* add terminator so we can easily get the count or know when to stop */
3255 mes[i] = (guint8) - 1;
3257 demux->mut_ex_streams = g_slist_append (demux->mut_ex_streams, mes);
3264 GST_WARNING_OBJECT (demux, "short read parsing advanced mutual exclusion");
3265 return GST_FLOW_OK; /* not absolutely fatal */
3269 static GstFlowReturn
3270 gst_asf_demux_process_ext_stream_props (GstASFDemux * demux, guint8 * data,
3273 AsfStreamExtProps esp;
3274 AsfStream *stream = NULL;
3275 AsfObject stream_obj;
3276 guint16 stream_name_count;
3277 guint16 num_payload_ext;
3279 guint8 *stream_obj_data = NULL;
3282 guint i, stream_num;
3285 obj_size = (guint) size;
3288 goto not_enough_data;
3291 esp.start_time = gst_asf_demux_get_uint64 (&data, &size) * GST_MSECOND;
3292 esp.end_time = gst_asf_demux_get_uint64 (&data, &size) * GST_MSECOND;
3293 esp.data_bitrate = gst_asf_demux_get_uint32 (&data, &size);
3294 esp.buffer_size = gst_asf_demux_get_uint32 (&data, &size);
3295 esp.intial_buf_fullness = gst_asf_demux_get_uint32 (&data, &size);
3296 esp.data_bitrate2 = gst_asf_demux_get_uint32 (&data, &size);
3297 esp.buffer_size2 = gst_asf_demux_get_uint32 (&data, &size);
3298 esp.intial_buf_fullness2 = gst_asf_demux_get_uint32 (&data, &size);
3299 esp.max_obj_size = gst_asf_demux_get_uint32 (&data, &size);
3300 esp.flags = gst_asf_demux_get_uint32 (&data, &size);
3301 stream_num = gst_asf_demux_get_uint16 (&data, &size);
3302 esp.lang_idx = gst_asf_demux_get_uint16 (&data, &size);
3303 esp.avg_time_per_frame = gst_asf_demux_get_uint64 (&data, &size);
3304 stream_name_count = gst_asf_demux_get_uint16 (&data, &size);
3305 num_payload_ext = gst_asf_demux_get_uint16 (&data, &size);
3307 GST_INFO ("start_time = %" GST_TIME_FORMAT,
3308 GST_TIME_ARGS (esp.start_time));
3309 GST_INFO ("end_time = %" GST_TIME_FORMAT,
3310 GST_TIME_ARGS (esp.end_time));
3311 GST_INFO ("flags = %08x", esp.flags);
3312 GST_INFO ("average time per frame = %" GST_TIME_FORMAT,
3313 GST_TIME_ARGS (esp.avg_time_per_frame * 100));
3314 GST_INFO ("stream number = %u", stream_num);
3315 GST_INFO ("stream language ID idx = %u (%s)", esp.lang_idx,
3316 (esp.lang_idx < demux->num_languages) ?
3317 GST_STR_NULL (demux->languages[esp.lang_idx]) : "??");
3318 GST_INFO ("stream name count = %u", stream_name_count);
3320 /* read stream names */
3321 for (i = 0; i < stream_name_count; ++i) {
3322 guint16 stream_lang_idx;
3323 gchar *stream_name = NULL;
3326 goto not_enough_data;
3327 stream_lang_idx = gst_asf_demux_get_uint16 (&data, &size);
3328 if (!gst_asf_demux_get_string (&stream_name, NULL, &data, &size))
3329 goto not_enough_data;
3330 GST_INFO ("stream name %d: %s", i, GST_STR_NULL (stream_name));
3331 g_free (stream_name); /* TODO: store names in struct */
3334 /* read payload extension systems stuff */
3335 GST_LOG ("payload extension systems count = %u", num_payload_ext);
3337 if (num_payload_ext > 0)
3338 esp.payload_extensions = g_new0 (AsfPayloadExtension, num_payload_ext + 1);
3340 esp.payload_extensions = NULL;
3342 for (i = 0; i < num_payload_ext; ++i) {
3343 AsfPayloadExtension ext;
3345 guint32 sys_info_len;
3347 if (size < 16 + 2 + 4)
3348 goto not_enough_data;
3350 gst_asf_demux_get_guid (&ext_guid, &data, &size);
3351 ext.id = gst_asf_demux_identify_guid (asf_payload_ext_guids, &ext_guid);
3352 ext.len = gst_asf_demux_get_uint16 (&data, &size);
3354 sys_info_len = gst_asf_demux_get_uint32 (&data, &size);
3355 GST_LOG ("payload systems info len = %u", sys_info_len);
3356 if (!gst_asf_demux_skip_bytes (sys_info_len, &data, &size))
3357 goto not_enough_data;
3359 esp.payload_extensions[i] = ext;
3362 GST_LOG ("bytes read: %u/%u", (guint) (data - data_start), obj_size);
3364 /* there might be an optional STREAM_INFO object here now; if not, we
3365 * should have parsed the corresponding stream info object already (since
3366 * we are parsing the extended stream properties objects delayed) */
3368 stream = gst_asf_demux_get_stream (demux, stream_num);
3372 /* get size of the stream object */
3373 if (!asf_demux_peek_object (demux, data, size, &stream_obj, TRUE))
3374 goto not_enough_data;
3376 if (stream_obj.id != ASF_OBJ_STREAM)
3377 goto expected_stream_object;
3379 if (stream_obj.size < ASF_OBJECT_HEADER_SIZE ||
3380 stream_obj.size > (10 * 1024 * 1024))
3381 goto not_enough_data;
3383 gst_asf_demux_skip_bytes (ASF_OBJECT_HEADER_SIZE, &data, &size);
3385 /* process this stream object later after all the other 'normal' ones
3386 * have been processed (since the others are more important/non-hidden) */
3387 len = stream_obj.size - ASF_OBJECT_HEADER_SIZE;
3388 if (!gst_asf_demux_get_bytes (&stream_obj_data, len, &data, &size))
3389 goto not_enough_data;
3391 /* parse stream object */
3392 stream = gst_asf_demux_parse_stream_object (demux, stream_obj_data, len);
3393 g_free (stream_obj_data);
3398 stream->ext_props = esp;
3400 /* try to set the framerate */
3401 if (stream->is_video && stream->caps) {
3402 GValue framerate = { 0 };
3406 g_value_init (&framerate, GST_TYPE_FRACTION);
3408 num = GST_SECOND / 100;
3409 denom = esp.avg_time_per_frame;
3411 /* avoid division by 0, assume 25/1 framerate */
3412 denom = GST_SECOND / 2500;
3415 gst_value_set_fraction (&framerate, num, denom);
3417 stream->caps = gst_caps_make_writable (stream->caps);
3418 s = gst_caps_get_structure (stream->caps, 0);
3419 gst_structure_set_value (s, "framerate", &framerate);
3420 g_value_unset (&framerate);
3421 GST_DEBUG_OBJECT (demux, "setting framerate of %d/%d = %f",
3422 num, denom, ((gdouble) num) / denom);
3425 /* add language info now if we have it */
3426 if (stream->ext_props.lang_idx < demux->num_languages) {
3427 if (stream->pending_tags == NULL)
3428 stream->pending_tags = gst_tag_list_new ();
3429 GST_LOG_OBJECT (demux, "stream %u has language '%s'", stream->id,
3430 demux->languages[stream->ext_props.lang_idx]);
3431 gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_APPEND,
3432 GST_TAG_LANGUAGE_CODE, demux->languages[stream->ext_props.lang_idx],
3436 GST_WARNING_OBJECT (demux, "Ext. stream properties for unknown stream");
3444 GST_WARNING_OBJECT (demux, "short read parsing ext stream props object!");
3445 return GST_FLOW_OK; /* not absolutely fatal */
3447 expected_stream_object:
3449 GST_WARNING_OBJECT (demux, "error parsing extended stream properties "
3450 "object: expected embedded stream object, but got %s object instead!",
3451 gst_asf_get_guid_nick (asf_object_guids, stream_obj.id));
3452 return GST_FLOW_OK; /* not absolutely fatal */
3456 static const gchar *
3457 gst_asf_demux_push_obj (GstASFDemux * demux, guint32 obj_id)
3461 nick = gst_asf_get_guid_nick (asf_object_guids, obj_id);
3462 if (g_str_has_prefix (nick, "ASF_OBJ_"))
3463 nick += strlen ("ASF_OBJ_");
3465 if (demux->objpath == NULL) {
3466 demux->objpath = g_strdup (nick);
3470 newpath = g_strdup_printf ("%s/%s", demux->objpath, nick);
3471 g_free (demux->objpath);
3472 demux->objpath = newpath;
3475 return (const gchar *) demux->objpath;
3479 gst_asf_demux_pop_obj (GstASFDemux * demux)
3483 if ((s = g_strrstr (demux->objpath, "/"))) {
3486 g_free (demux->objpath);
3487 demux->objpath = NULL;
3492 gst_asf_demux_process_queued_extended_stream_objects (GstASFDemux * demux)
3497 /* Parse the queued extended stream property objects and add the info
3498 * to the existing streams or add the new embedded streams, but without
3499 * activating them yet */
3500 GST_LOG_OBJECT (demux, "%u queued extended stream properties objects",
3501 g_slist_length (demux->ext_stream_props));
3503 for (l = demux->ext_stream_props, i = 0; l != NULL; l = l->next, ++i) {
3504 GstBuffer *buf = GST_BUFFER (l->data);
3506 GST_LOG_OBJECT (demux, "parsing ext. stream properties object #%u", i);
3507 gst_asf_demux_process_ext_stream_props (demux, GST_BUFFER_DATA (buf),
3508 GST_BUFFER_SIZE (buf));
3509 gst_buffer_unref (buf);
3511 g_slist_free (demux->ext_stream_props);
3512 demux->ext_stream_props = NULL;
3517 gst_asf_demux_activate_ext_props_streams (GstASFDemux * demux)
3521 for (i = 0; i < demux->num_streams; ++i) {
3526 stream = &demux->stream[i];
3528 GST_LOG_OBJECT (demux, "checking stream %2u", stream->id);
3530 if (stream->active) {
3531 GST_LOG_OBJECT (demux, "stream %2u is already activated", stream->id);
3536 for (x = demux->mut_ex_streams; x != NULL; x = x->next) {
3539 /* check for each mutual exclusion whether it affects this stream */
3540 for (mes = (guint8 *) x->data; mes != NULL && *mes != 0xff; ++mes) {
3541 if (*mes == stream->id) {
3542 /* if yes, check if we've already added streams that are mutually
3543 * exclusive with the stream we're about to add */
3544 for (mes = (guint8 *) x->data; mes != NULL && *mes != 0xff; ++mes) {
3545 for (j = 0; j < demux->num_streams; ++j) {
3546 /* if the broadcast flag is set, assume the hidden streams aren't
3547 * actually streamed and hide them (or playbin won't work right),
3548 * otherwise assume their data is available */
3549 if (demux->stream[j].id == *mes && demux->broadcast) {
3551 GST_LOG_OBJECT (demux, "broadcast stream ID %d to be added is "
3552 "mutually exclusive with already existing stream ID %d, "
3553 "hiding stream", stream->id, demux->stream[j].id);
3565 /* FIXME: we should do stream activation based on preroll data in
3566 * streaming mode too */
3567 if (demux->streaming && !is_hidden)
3568 gst_asf_demux_activate_stream (demux, stream);
3573 static GstFlowReturn
3574 gst_asf_demux_process_object (GstASFDemux * demux, guint8 ** p_data,
3577 GstFlowReturn ret = GST_FLOW_OK;
3579 guint64 obj_data_size;
3581 if (*p_size < ASF_OBJECT_HEADER_SIZE)
3582 return ASF_FLOW_NEED_MORE_DATA;
3584 asf_demux_peek_object (demux, *p_data, ASF_OBJECT_HEADER_SIZE, &obj, TRUE);
3585 gst_asf_demux_skip_bytes (ASF_OBJECT_HEADER_SIZE, p_data, p_size);
3587 obj_data_size = obj.size - ASF_OBJECT_HEADER_SIZE;
3589 if (*p_size < obj_data_size)
3590 return ASF_FLOW_NEED_MORE_DATA;
3592 gst_asf_demux_push_obj (demux, obj.id);
3594 GST_INFO ("%s: size %" G_GUINT64_FORMAT, demux->objpath, obj.size);
3597 case ASF_OBJ_STREAM:{
3601 gst_asf_demux_parse_stream_object (demux, *p_data, obj_data_size);
3607 ret = gst_asf_demux_process_file (demux, *p_data, obj_data_size);
3609 case ASF_OBJ_HEADER:
3610 ret = gst_asf_demux_process_header (demux, *p_data, obj_data_size);
3612 case ASF_OBJ_COMMENT:
3613 ret = gst_asf_demux_process_comment (demux, *p_data, obj_data_size);
3616 ret = gst_asf_demux_process_header_ext (demux, *p_data, obj_data_size);
3618 case ASF_OBJ_BITRATE_PROPS:
3620 gst_asf_demux_process_bitrate_props_object (demux, *p_data,
3623 case ASF_OBJ_EXT_CONTENT_DESC:
3625 gst_asf_demux_process_ext_content_desc (demux, *p_data,
3628 case ASF_OBJ_METADATA_OBJECT:
3629 ret = gst_asf_demux_process_metadata (demux, *p_data, obj_data_size);
3631 case ASF_OBJ_EXTENDED_STREAM_PROPS:{
3634 /* process these later, we might not have parsed the corresponding
3635 * stream object yet */
3636 GST_LOG ("%s: queued for later parsing", demux->objpath);
3637 buf = gst_buffer_new_and_alloc (obj_data_size);
3638 memcpy (GST_BUFFER_DATA (buf), *p_data, obj_data_size);
3639 demux->ext_stream_props = g_slist_append (demux->ext_stream_props, buf);
3643 case ASF_OBJ_LANGUAGE_LIST:
3644 ret = gst_asf_demux_process_language_list (demux, *p_data, obj_data_size);
3646 case ASF_OBJ_ADVANCED_MUTUAL_EXCLUSION:
3647 ret = gst_asf_demux_process_advanced_mutual_exclusion (demux, *p_data,
3650 case ASF_OBJ_SIMPLE_INDEX:
3651 ret = gst_asf_demux_process_simple_index (demux, *p_data, obj_data_size);
3653 case ASF_OBJ_CONTENT_ENCRYPTION:
3654 case ASF_OBJ_EXT_CONTENT_ENCRYPTION:
3655 case ASF_OBJ_DIGITAL_SIGNATURE_OBJECT:
3656 case ASF_OBJ_UNKNOWN_ENCRYPTION_OBJECT:
3657 goto error_encrypted;
3658 case ASF_OBJ_CONCEAL_NONE:
3660 case ASF_OBJ_UNDEFINED:
3661 case ASF_OBJ_CODEC_COMMENT:
3663 case ASF_OBJ_PADDING:
3664 case ASF_OBJ_BITRATE_MUTEX:
3665 case ASF_OBJ_COMPATIBILITY:
3666 case ASF_OBJ_INDEX_PLACEHOLDER:
3667 case ASF_OBJ_INDEX_PARAMETERS:
3668 case ASF_OBJ_STREAM_PRIORITIZATION:
3669 case ASF_OBJ_SCRIPT_COMMAND:
3671 /* Unknown/unhandled object, skip it and hope for the best */
3672 GST_INFO ("%s: skipping object", demux->objpath);
3677 /* this can't fail, we checked the number of bytes available before */
3678 gst_asf_demux_skip_bytes (obj_data_size, p_data, p_size);
3680 GST_LOG ("%s: ret = %s", demux->objpath, gst_asf_get_flow_name (ret));
3682 gst_asf_demux_pop_obj (demux);
3689 GST_ELEMENT_ERROR (demux, STREAM, DECRYPT, (NULL), (NULL));
3690 return GST_FLOW_ERROR;
3695 gst_asf_demux_descramble_buffer (GstASFDemux * demux, AsfStream * stream,
3696 GstBuffer ** p_buffer)
3698 GstBuffer *descrambled_buffer;
3699 GstBuffer *scrambled_buffer;
3700 GstBuffer *sub_buffer;
3707 /* descrambled_buffer is initialised in the first iteration */
3708 descrambled_buffer = NULL;
3709 scrambled_buffer = *p_buffer;
3711 if (GST_BUFFER_SIZE (scrambled_buffer) < demux->ds_packet_size * demux->span)
3714 for (offset = 0; offset < GST_BUFFER_SIZE (scrambled_buffer);
3715 offset += demux->ds_chunk_size) {
3716 off = offset / demux->ds_chunk_size;
3717 row = off / demux->span;
3718 col = off % demux->span;
3719 idx = row + col * demux->ds_packet_size / demux->ds_chunk_size;
3720 GST_DEBUG ("idx=%u, row=%u, col=%u, off=%u, ds_chunk_size=%u", idx, row,
3721 col, off, demux->ds_chunk_size);
3722 GST_DEBUG ("scrambled buffer size=%u, span=%u, packet_size=%u",
3723 GST_BUFFER_SIZE (scrambled_buffer), demux->span, demux->ds_packet_size);
3724 GST_DEBUG ("GST_BUFFER_SIZE (scrambled_buffer) = %u",
3725 GST_BUFFER_SIZE (scrambled_buffer));
3727 gst_buffer_create_sub (scrambled_buffer, idx * demux->ds_chunk_size,
3728 demux->ds_chunk_size);
3730 descrambled_buffer = sub_buffer;
3732 descrambled_buffer = gst_buffer_join (descrambled_buffer, sub_buffer);
3736 gst_buffer_copy_metadata (descrambled_buffer, scrambled_buffer,
3737 GST_BUFFER_COPY_TIMESTAMPS);
3739 /* FIXME/CHECK: do we need to transfer buffer flags here too? */
3741 gst_buffer_unref (scrambled_buffer);
3742 *p_buffer = descrambled_buffer;
3746 gst_asf_demux_element_send_event (GstElement * element, GstEvent * event)
3748 GstASFDemux *demux = GST_ASF_DEMUX (element);
3751 GST_DEBUG ("handling element event of type %s", GST_EVENT_TYPE_NAME (event));
3753 for (i = 0; i < demux->num_streams; ++i) {
3754 gst_event_ref (event);
3755 if (gst_asf_demux_handle_src_event (demux->stream[i].pad, event)) {
3756 gst_event_unref (event);
3761 gst_event_unref (event);
3765 /* takes ownership of the passed event */
3767 gst_asf_demux_send_event_unlocked (GstASFDemux * demux, GstEvent * event)
3769 gboolean ret = TRUE;
3772 GST_DEBUG_OBJECT (demux, "sending %s event to all source pads",
3773 GST_EVENT_TYPE_NAME (event));
3775 for (i = 0; i < demux->num_streams; ++i) {
3776 gst_event_ref (event);
3777 ret &= gst_pad_push_event (demux->stream[i].pad, event);
3779 gst_event_unref (event);
3783 static const GstQueryType *
3784 gst_asf_demux_get_src_query_types (GstPad * pad)
3786 static const GstQueryType types[] = {
3797 gst_asf_demux_handle_src_query (GstPad * pad, GstQuery * query)
3800 gboolean res = FALSE;
3802 demux = GST_ASF_DEMUX (gst_pad_get_parent (pad));
3804 GST_DEBUG ("handling %s query",
3805 gst_query_type_get_name (GST_QUERY_TYPE (query)));
3807 switch (GST_QUERY_TYPE (query)) {
3808 case GST_QUERY_DURATION:
3812 gst_query_parse_duration (query, &format, NULL);
3814 if (format != GST_FORMAT_TIME) {
3815 GST_LOG ("only support duration queries in TIME format");
3819 GST_OBJECT_LOCK (demux);
3821 if (demux->segment.duration != GST_CLOCK_TIME_NONE) {
3822 GST_LOG ("returning duration: %" GST_TIME_FORMAT,
3823 GST_TIME_ARGS (demux->segment.duration));
3825 gst_query_set_duration (query, GST_FORMAT_TIME,
3826 demux->segment.duration);
3830 GST_LOG ("duration not known yet");
3833 GST_OBJECT_UNLOCK (demux);
3837 case GST_QUERY_POSITION:{
3840 gst_query_parse_position (query, &format, NULL);
3842 if (format != GST_FORMAT_TIME) {
3843 GST_LOG ("only support position queries in TIME format");
3847 GST_OBJECT_LOCK (demux);
3849 if (demux->segment.last_stop != GST_CLOCK_TIME_NONE) {
3850 GST_LOG ("returning position: %" GST_TIME_FORMAT,
3851 GST_TIME_ARGS (demux->segment.last_stop));
3853 gst_query_set_position (query, GST_FORMAT_TIME,
3854 demux->segment.last_stop);
3858 GST_LOG ("position not known yet");
3861 GST_OBJECT_UNLOCK (demux);
3865 case GST_QUERY_SEEKING:{
3868 gst_query_parse_seeking (query, &format, NULL, NULL, NULL);
3869 if (format == GST_FORMAT_TIME) {
3872 GST_OBJECT_LOCK (demux);
3873 duration = demux->segment.duration;
3874 GST_OBJECT_UNLOCK (demux);
3876 if (!demux->streaming || !demux->seekable) {
3877 gst_query_set_seeking (query, GST_FORMAT_TIME, demux->seekable, 0,
3884 /* try downstream first in TIME */
3885 res = gst_pad_query_default (pad, query);
3887 gst_query_parse_seeking (query, &fmt, &seekable, NULL, NULL);
3888 GST_LOG_OBJECT (demux, "upstream %s seekable %d",
3889 GST_STR_NULL (gst_format_get_name (fmt)), seekable);
3890 /* if no luck, maybe in BYTES */
3891 if (!seekable || fmt != GST_FORMAT_TIME) {
3894 q = gst_query_new_seeking (GST_FORMAT_BYTES);
3895 if ((res = gst_pad_peer_query (demux->sinkpad, q))) {
3896 gst_query_parse_seeking (q, &fmt, &seekable, NULL, NULL);
3897 GST_LOG_OBJECT (demux, "upstream %s seekable %d",
3898 GST_STR_NULL (gst_format_get_name (fmt)), seekable);
3899 if (fmt != GST_FORMAT_BYTES)
3902 gst_query_unref (q);
3903 gst_query_set_seeking (query, GST_FORMAT_TIME, seekable, 0,
3909 GST_LOG_OBJECT (demux, "only support seeking in TIME format");
3913 case GST_QUERY_LATENCY:
3916 GstClockTime min, max;
3918 /* preroll delay does not matter in non-live pipeline,
3919 * but we might end up in a live (rtsp) one ... */
3922 res = gst_pad_query_default (pad, query);
3926 gst_query_parse_latency (query, &live, &min, &max);
3928 GST_DEBUG_OBJECT (demux, "Peer latency: live %d, min %"
3929 GST_TIME_FORMAT " max %" GST_TIME_FORMAT, live,
3930 GST_TIME_ARGS (min), GST_TIME_ARGS (max));
3932 GST_OBJECT_LOCK (demux);
3934 min += demux->latency;
3936 max += demux->latency;
3937 GST_OBJECT_UNLOCK (demux);
3939 gst_query_set_latency (query, live, min, max);
3943 res = gst_pad_query_default (pad, query);
3947 gst_object_unref (demux);
3951 static GstStateChangeReturn
3952 gst_asf_demux_change_state (GstElement * element, GstStateChange transition)
3954 GstASFDemux *demux = GST_ASF_DEMUX (element);
3955 GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
3957 switch (transition) {
3958 case GST_STATE_CHANGE_NULL_TO_READY:{
3959 gst_segment_init (&demux->segment, GST_FORMAT_TIME);
3960 demux->need_newsegment = TRUE;
3961 demux->segment_running = FALSE;
3962 demux->accurate = FALSE;
3963 demux->adapter = gst_adapter_new ();
3964 demux->metadata = gst_caps_new_empty ();
3965 demux->global_metadata = gst_structure_empty_new ("metadata");
3966 demux->data_size = 0;
3967 demux->data_offset = 0;
3968 demux->index_offset = 0;
3969 demux->base_offset = 0;
3976 ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
3977 if (ret == GST_STATE_CHANGE_FAILURE)
3980 switch (transition) {
3981 case GST_STATE_CHANGE_PAUSED_TO_READY:
3982 case GST_STATE_CHANGE_READY_TO_NULL:
3983 gst_asf_demux_reset (demux, FALSE);