]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - glsdk/gst-plugins-ugly0-10.git/blob - gst/asfdemux/gstasfdemux.c
asfdemux: Do not try to free const pointer
[glsdk/gst-plugins-ugly0-10.git] / gst / asfdemux / gstasfdemux.c
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>
4  *
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.
9  *
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.
14  *
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.
19  */
21 /* TODO:
22  *
23  * - _loop():
24  *   stop if at end of segment if != end of file, ie. demux->segment.stop
25  *
26  * - fix packet parsing:
27  *   there's something wrong with timestamps for packets with keyframes,
28  *   and durations too.
29  */
31 #ifdef HAVE_CONFIG_H
32 #include "config.h"
33 #endif
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>
40 #include <stdlib.h>
41 #include <string.h>
43 #include "gstasfdemux.h"
44 #include "asfheaders.h"
45 #include "asfpacket.h"
47 static GstStaticPadTemplate gst_asf_demux_sink_template =
48 GST_STATIC_PAD_TEMPLATE ("sink",
49     GST_PAD_SINK,
50     GST_PAD_ALWAYS,
51     GST_STATIC_CAPS ("video/x-ms-asf")
52     );
54 static GstStaticPadTemplate audio_src_template =
55 GST_STATIC_PAD_TEMPLATE ("audio_%02d",
56     GST_PAD_SRC,
57     GST_PAD_SOMETIMES,
58     GST_STATIC_CAPS_ANY);
60 static GstStaticPadTemplate video_src_template =
61 GST_STATIC_PAD_TEMPLATE ("video_%02d",
62     GST_PAD_SRC,
63     GST_PAD_SOMETIMES,
64     GST_STATIC_CAPS_ANY);
66 /* size of an ASF object header, ie. GUID (16 bytes) + object size (8 bytes) */
67 #define ASF_OBJECT_HEADER_SIZE  (16+8)
69 /* FIXME: get rid of this */
70 /* abuse this GstFlowReturn enum for internal usage */
71 #define ASF_FLOW_NEED_MORE_DATA  99
73 #define gst_asf_get_flow_name(flow)    \
74   (flow == ASF_FLOW_NEED_MORE_DATA) ?  \
75   "need-more-data" : gst_flow_get_name (flow)
77 GST_DEBUG_CATEGORY (asfdemux_dbg);
79 static GstStateChangeReturn gst_asf_demux_change_state (GstElement * element,
80     GstStateChange transition);
81 static gboolean gst_asf_demux_element_send_event (GstElement * element,
82     GstEvent * event);
83 static gboolean gst_asf_demux_send_event_unlocked (GstASFDemux * demux,
84     GstEvent * event);
85 static gboolean gst_asf_demux_handle_src_query (GstPad * pad, GstQuery * query);
86 static const GstQueryType *gst_asf_demux_get_src_query_types (GstPad * pad);
87 static GstFlowReturn gst_asf_demux_chain (GstPad * pad, GstBuffer * buf);
88 static gboolean gst_asf_demux_sink_event (GstPad * pad, GstEvent * event);
89 static GstFlowReturn gst_asf_demux_process_object (GstASFDemux * demux,
90     guint8 ** p_data, guint64 * p_size);
91 static gboolean gst_asf_demux_activate (GstPad * sinkpad);
92 static gboolean gst_asf_demux_activate_push (GstPad * sinkpad, gboolean active);
93 static gboolean gst_asf_demux_activate_pull (GstPad * sinkpad, gboolean active);
94 static void gst_asf_demux_loop (GstASFDemux * demux);
95 static void
96 gst_asf_demux_process_queued_extended_stream_objects (GstASFDemux * demux);
97 static gboolean gst_asf_demux_pull_headers (GstASFDemux * demux);
98 static void gst_asf_demux_pull_indices (GstASFDemux * demux);
99 static void gst_asf_demux_reset_stream_state_after_discont (GstASFDemux * asf);
100 static gboolean
101 gst_asf_demux_parse_data_object_start (GstASFDemux * demux, guint8 * data);
102 static void gst_asf_demux_descramble_buffer (GstASFDemux * demux,
103     AsfStream * stream, GstBuffer ** p_buffer);
104 static void gst_asf_demux_activate_stream (GstASFDemux * demux,
105     AsfStream * stream);
106 static GstStructure *gst_asf_demux_get_metadata_for_stream (GstASFDemux * d,
107     guint stream_num);
109 GST_BOILERPLATE (GstASFDemux, gst_asf_demux, GstElement, GST_TYPE_ELEMENT);
111 static void
112 gst_asf_demux_base_init (gpointer g_class)
114   GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
115   static GstElementDetails gst_asf_demux_details = {
116     "ASF Demuxer",
117     "Codec/Demuxer",
118     "Demultiplexes ASF Streams",
119     "Owen Fraser-Green <owen@discobabe.net>"
120   };
122   gst_element_class_add_pad_template (element_class,
123       gst_static_pad_template_get (&audio_src_template));
124   gst_element_class_add_pad_template (element_class,
125       gst_static_pad_template_get (&video_src_template));
126   gst_element_class_add_pad_template (element_class,
127       gst_static_pad_template_get (&gst_asf_demux_sink_template));
129   gst_element_class_set_details (element_class, &gst_asf_demux_details);
132 static void
133 gst_asf_demux_class_init (GstASFDemuxClass * klass)
135   GstElementClass *gstelement_class;
137   gstelement_class = (GstElementClass *) klass;
139   gstelement_class->change_state =
140       GST_DEBUG_FUNCPTR (gst_asf_demux_change_state);
141   gstelement_class->send_event =
142       GST_DEBUG_FUNCPTR (gst_asf_demux_element_send_event);
145 static void
146 gst_asf_demux_free_stream (GstASFDemux * demux, AsfStream * stream)
148   gst_caps_replace (&stream->caps, NULL);
149   if (stream->pending_tags) {
150     gst_tag_list_free (stream->pending_tags);
151     stream->pending_tags = NULL;
152   }
153   if (stream->pad) {
154     if (stream->active)
155       gst_element_remove_pad (GST_ELEMENT_CAST (demux), stream->pad);
156     else
157       gst_object_unref (stream->pad);
158     stream->pad = NULL;
159   }
160   if (stream->payloads) {
161     g_array_free (stream->payloads, TRUE);
162     stream->payloads = NULL;
163   }
164   if (stream->ext_props.valid) {
165     g_free (stream->ext_props.payload_extensions);
166     stream->ext_props.payload_extensions = NULL;
167   }
170 static void
171 gst_asf_demux_reset (GstASFDemux * demux)
173   GST_LOG_OBJECT (demux, "resetting");
175   gst_segment_init (&demux->segment, GST_FORMAT_UNDEFINED);
176   demux->segment_running = FALSE;
177   if (demux->adapter) {
178     gst_adapter_clear (demux->adapter);
179     g_object_unref (demux->adapter);
180     demux->adapter = NULL;
181   }
182   if (demux->taglist) {
183     gst_tag_list_free (demux->taglist);
184     demux->taglist = NULL;
185   }
186   if (demux->metadata) {
187     gst_caps_unref (demux->metadata);
188     demux->metadata = NULL;
189   }
190   if (demux->global_metadata) {
191     gst_structure_free (demux->global_metadata);
192     demux->global_metadata = NULL;
193   }
195   demux->state = GST_ASF_DEMUX_STATE_HEADER;
196   g_free (demux->objpath);
197   demux->objpath = NULL;
198   g_strfreev (demux->languages);
199   demux->languages = NULL;
200   demux->num_languages = 0;
201   g_slist_foreach (demux->ext_stream_props, (GFunc) gst_mini_object_unref,
202       NULL);
203   g_slist_free (demux->ext_stream_props);
204   demux->ext_stream_props = NULL;
205   while (demux->num_streams > 0) {
206     gst_asf_demux_free_stream (demux, &demux->stream[demux->num_streams - 1]);
207     --demux->num_streams;
208   }
209   memset (demux->stream, 0, sizeof (demux->stream));
210   demux->num_audio_streams = 0;
211   demux->num_video_streams = 0;
212   demux->num_streams = 0;
213   demux->activated_streams = FALSE;
214   demux->first_ts = GST_CLOCK_TIME_NONE;
215   demux->segment_ts = GST_CLOCK_TIME_NONE;
216   demux->in_gap = 0;
217   gst_segment_init (&demux->in_segment, GST_FORMAT_UNDEFINED);
218   demux->state = GST_ASF_DEMUX_STATE_HEADER;
219   demux->seekable = FALSE;
220   demux->broadcast = FALSE;
221   demux->sidx_interval = 0;
222   demux->sidx_num_entries = 0;
223   g_free (demux->sidx_entries);
224   demux->sidx_entries = NULL;
227 static void
228 gst_asf_demux_init (GstASFDemux * demux, GstASFDemuxClass * klass)
230   demux->sinkpad =
231       gst_pad_new_from_static_template (&gst_asf_demux_sink_template, "sink");
232   gst_pad_set_chain_function (demux->sinkpad,
233       GST_DEBUG_FUNCPTR (gst_asf_demux_chain));
234   gst_pad_set_event_function (demux->sinkpad,
235       GST_DEBUG_FUNCPTR (gst_asf_demux_sink_event));
236   gst_pad_set_activate_function (demux->sinkpad,
237       GST_DEBUG_FUNCPTR (gst_asf_demux_activate));
238   gst_pad_set_activatepull_function (demux->sinkpad,
239       GST_DEBUG_FUNCPTR (gst_asf_demux_activate_pull));
240   gst_pad_set_activatepush_function (demux->sinkpad,
241       GST_DEBUG_FUNCPTR (gst_asf_demux_activate_push));
242   gst_element_add_pad (GST_ELEMENT (demux), demux->sinkpad);
244   /* set initial state */
245   gst_asf_demux_reset (demux);
248 static gboolean
249 gst_asf_demux_activate (GstPad * sinkpad)
251   if (gst_pad_check_pull_range (sinkpad)) {
252     return gst_pad_activate_pull (sinkpad, TRUE);
253   } else {
254     return gst_pad_activate_push (sinkpad, TRUE);
255   }
258 static gboolean
259 gst_asf_demux_activate_push (GstPad * sinkpad, gboolean active)
261   GstASFDemux *demux;
263   demux = GST_ASF_DEMUX (GST_OBJECT_PARENT (sinkpad));
265   demux->state = GST_ASF_DEMUX_STATE_HEADER;
266   demux->streaming = TRUE;
268   return TRUE;
271 static gboolean
272 gst_asf_demux_activate_pull (GstPad * pad, gboolean active)
274   GstASFDemux *demux;
276   demux = GST_ASF_DEMUX (GST_OBJECT_PARENT (pad));
278   if (active) {
279     demux->state = GST_ASF_DEMUX_STATE_HEADER;
280     demux->streaming = FALSE;
282     return gst_pad_start_task (pad, (GstTaskFunction) gst_asf_demux_loop,
283         demux);
284   } else {
285     return gst_pad_stop_task (pad);
286   }
290 static gboolean
291 gst_asf_demux_sink_event (GstPad * pad, GstEvent * event)
293   GstASFDemux *demux;
294   gboolean ret = TRUE;
296   demux = GST_ASF_DEMUX (gst_pad_get_parent (pad));
298   GST_LOG_OBJECT (demux, "handling %s event", GST_EVENT_TYPE_NAME (event));
299   switch (GST_EVENT_TYPE (event)) {
300     case GST_EVENT_NEWSEGMENT:{
301       GstFormat newsegment_format;
302       gint64 newsegment_start, stop, time;
303       gdouble rate, arate;
304       gboolean update;
306       gst_event_parse_new_segment_full (event, &update, &rate, &arate,
307           &newsegment_format, &newsegment_start, &stop, &time);
309       if (newsegment_format == GST_FORMAT_BYTES) {
310         if (demux->packet_size && newsegment_start > demux->data_offset)
311           demux->packet = (newsegment_start - demux->data_offset) /
312               demux->packet_size;
313         else
314           demux->packet = 0;
315       } else if (newsegment_format == GST_FORMAT_TIME) {
316         /* do not know packet position, not really a problem */
317         demux->packet = -1;
318       } else {
319         GST_WARNING_OBJECT (demux, "unsupported newsegment format, ignoring");
320         gst_event_unref (event);
321         break;
322       }
324       /* record upstream segment for interpolation */
325       if (newsegment_format != demux->in_segment.format)
326         gst_segment_init (&demux->in_segment, GST_FORMAT_UNDEFINED);
327       gst_segment_set_newsegment_full (&demux->in_segment, update, rate, arate,
328           newsegment_format, newsegment_start, stop, time);
330       /* in either case, clear some state and generate newsegment later on */
331       GST_OBJECT_LOCK (demux);
332       demux->segment_ts = GST_CLOCK_TIME_NONE;
333       demux->in_gap = GST_CLOCK_TIME_NONE;
334       demux->need_newsegment = TRUE;
335       gst_asf_demux_reset_stream_state_after_discont (demux);
336       GST_OBJECT_UNLOCK (demux);
338       gst_event_unref (event);
339       break;
340     }
341     case GST_EVENT_EOS:{
342       if (demux->state == GST_ASF_DEMUX_STATE_HEADER) {
343         GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
344             (_("This stream contains no data.")),
345             ("got eos and didn't receive a complete header object"));
346         break;
347       }
348       GST_OBJECT_LOCK (demux);
349       gst_adapter_clear (demux->adapter);
350       GST_OBJECT_UNLOCK (demux);
351       gst_asf_demux_send_event_unlocked (demux, event);
352       break;
353     }
355     case GST_EVENT_FLUSH_STOP:
356       GST_OBJECT_LOCK (demux);
357       gst_asf_demux_reset_stream_state_after_discont (demux);
358       GST_OBJECT_UNLOCK (demux);
359       gst_asf_demux_send_event_unlocked (demux, event);
360       /* upon activation, latency is no longer introduced, e.g. after seek */
361       if (demux->activated_streams)
362         demux->latency = 0;
363       break;
365     default:
366       ret = gst_pad_event_default (pad, event);
367       break;
368   }
370   gst_object_unref (demux);
371   return ret;
374 static gboolean
375 gst_asf_demux_seek_index_lookup (GstASFDemux * demux, guint * packet,
376     GstClockTime seek_time, GstClockTime * p_idx_time)
378   GstClockTime idx_time;
379   guint idx;
381   if (demux->sidx_num_entries == 0 || demux->sidx_interval == 0)
382     return FALSE;
384   idx = (guint) ((seek_time + demux->preroll) / demux->sidx_interval);
386   /* FIXME: seek beyond end of file should result in immediate EOS from
387    * streaming thread instead of a failed seek */
388   if (idx >= demux->sidx_num_entries)
389     return FALSE;
391   *packet = demux->sidx_entries[idx];
393   /* so we get closer to the actual time of the packet ... actually, let's not
394    * do this, since we throw away superfluous payloads before the seek position
395    * anyway; this way, our key unit seek 'snap resolution' is a bit better
396    * (ie. same as index resolution) */
397   /*
398      while (idx > 0 && demux->sidx_entries[idx-1] == demux->sidx_entries[idx])
399      --idx;
400    */
402   idx_time = demux->sidx_interval * idx;
403   if (G_LIKELY (idx_time >= demux->preroll))
404     idx_time -= demux->preroll;
406   GST_DEBUG_OBJECT (demux, "%" GST_TIME_FORMAT " => packet %u at %"
407       GST_TIME_FORMAT, GST_TIME_ARGS (seek_time), *packet,
408       GST_TIME_ARGS (idx_time));
410   if (p_idx_time)
411     *p_idx_time = idx_time;
413   return TRUE;
416 static void
417 gst_asf_demux_reset_stream_state_after_discont (GstASFDemux * demux)
419   guint n;
421   gst_adapter_clear (demux->adapter);
423   GST_DEBUG_OBJECT (demux, "reset stream state");
425   for (n = 0; n < demux->num_streams; n++) {
426     demux->stream[n].discont = TRUE;
427     demux->stream[n].last_flow = GST_FLOW_OK;
429     while (demux->stream[n].payloads->len > 0) {
430       AsfPayload *payload;
431       guint last;
433       last = demux->stream[n].payloads->len - 1;
434       payload = &g_array_index (demux->stream[n].payloads, AsfPayload, last);
435       gst_buffer_replace (&payload->buf, NULL);
436       g_array_remove_index (demux->stream[n].payloads, last);
437     }
438   }
441 static void
442 gst_asf_demux_mark_discont (GstASFDemux * demux)
444   guint n;
446   GST_DEBUG_OBJECT (demux, "Mark stream discont");
448   for (n = 0; n < demux->num_streams; n++)
449     demux->stream[n].discont = TRUE;
452 /* do a seek in push based mode */
453 static gboolean
454 gst_asf_demux_handle_seek_push (GstASFDemux * demux, GstEvent * event)
456   gdouble rate;
457   GstFormat format;
458   GstSeekFlags flags;
459   GstSeekType cur_type, stop_type;
460   gint64 cur, stop;
461   guint packet;
462   gboolean res;
464   gst_event_parse_seek (event, &rate, &format, &flags, &cur_type, &cur,
465       &stop_type, &stop);
467   stop_type = GST_SEEK_TYPE_NONE;
468   stop = -1;
470   GST_DEBUG_OBJECT (demux, "seeking to %" GST_TIME_FORMAT, GST_TIME_ARGS (cur));
472   /* determine packet, by index or by estimation */
473   if (!gst_asf_demux_seek_index_lookup (demux, &packet, cur, NULL)) {
474     packet = (guint) gst_util_uint64_scale (demux->num_packets,
475         cur, demux->play_time);
476   }
478   if (packet > demux->num_packets) {
479     GST_DEBUG_OBJECT (demux, "could not determine packet to seek to, "
480         "seek aborted.");
481     return FALSE;
482   }
484   GST_DEBUG_OBJECT (demux, "seeking to packet %d", packet);
486   cur = demux->data_offset + (packet * demux->packet_size);
488   GST_DEBUG_OBJECT (demux, "Pushing BYTE seek rate %g, "
489       "start %" G_GINT64_FORMAT ", stop %" G_GINT64_FORMAT, rate, cur, stop);
490   /* BYTE seek event */
491   event = gst_event_new_seek (rate, GST_FORMAT_BYTES, flags, cur_type, cur,
492       stop_type, stop);
493   res = gst_pad_push_event (demux->sinkpad, event);
495   return res;
498 static gboolean
499 gst_asf_demux_handle_seek_event (GstASFDemux * demux, GstEvent * event)
501   GstClockTime idx_time;
502   GstSegment segment;
503   GstSeekFlags flags;
504   GstSeekType cur_type, stop_type;
505   GstFormat format;
506   gboolean only_need_update;
507   gboolean keyunit_sync;
508   gboolean accurate;
509   gboolean flush;
510   gdouble rate;
511   gint64 cur, stop;
512   gint64 seek_time;
513   guint packet;
515   if (demux->seekable == FALSE || demux->packet_size == 0 ||
516       demux->num_packets == 0 || demux->play_time == 0) {
517     GST_LOG_OBJECT (demux, "stream is not seekable");
518     return FALSE;
519   }
521   if (!demux->activated_streams) {
522     GST_LOG_OBJECT (demux, "streams not yet activated, ignoring seek");
523     return FALSE;
524   }
526   gst_event_parse_seek (event, &rate, &format, &flags, &cur_type, &cur,
527       &stop_type, &stop);
529   if (format != GST_FORMAT_TIME) {
530     GST_LOG_OBJECT (demux, "seeking is only supported in TIME format");
531     return FALSE;
532   }
534   if (rate <= 0.0) {
535     GST_LOG_OBJECT (demux, "backward playback is not supported yet");
536     return FALSE;
537   }
539   flush = ((flags & GST_SEEK_FLAG_FLUSH) == GST_SEEK_FLAG_FLUSH);
540   accurate = ((flags & GST_SEEK_FLAG_ACCURATE) == GST_SEEK_FLAG_ACCURATE);
541   keyunit_sync = ((flags & GST_SEEK_FLAG_KEY_UNIT) == GST_SEEK_FLAG_KEY_UNIT);
543   if (demux->streaming) {
544     /* support it safely needs more segment handling, e.g. closing etc */
545     if (!flush) {
546       GST_LOG_OBJECT (demux, "streaming; non-flushing seek not supported");
547       return FALSE;
548     }
549     /* we can (re)construct the start later on, but not the end */
550     if (stop_type != GST_SEEK_TYPE_NONE) {
551       GST_LOG_OBJECT (demux, "streaming; end type must be NONE");
552       return FALSE;
553     }
554     gst_event_ref (event);
555     /* upstream might handle TIME seek, e.g. mms or rtsp,
556      * or not, e.g. http, then we give it a hand */
557     if (!gst_pad_push_event (demux->sinkpad, event))
558       return gst_asf_demux_handle_seek_push (demux, event);
559     else
560       return TRUE;
561   }
563   /* unlock the streaming thread */
564   if (flush) {
565     gst_pad_push_event (demux->sinkpad, gst_event_new_flush_start ());
566     gst_asf_demux_send_event_unlocked (demux, gst_event_new_flush_start ());
567   } else {
568     gst_pad_pause_task (demux->sinkpad);
569   }
571   /* grab the stream lock so that streaming cannot continue, for
572    * non flushing seeks when the element is in PAUSED this could block
573    * forever */
574   GST_PAD_STREAM_LOCK (demux->sinkpad);
576   /* we now can stop flushing, since we have the stream lock now */
577   gst_pad_push_event (demux->sinkpad, gst_event_new_flush_stop ());
579   if (flush)
580     gst_asf_demux_send_event_unlocked (demux, gst_event_new_flush_stop ());
582   /* operating on copy of segment until we know the seek worked */
583   segment = demux->segment;
585   if (demux->segment_running && !flush) {
586     GstEvent *newseg;
588     /* create the segment event to close the current segment */
589     newseg = gst_event_new_new_segment (TRUE, segment.rate,
590         GST_FORMAT_TIME, segment.start, segment.last_stop, segment.time);
592     gst_asf_demux_send_event_unlocked (demux, newseg);
593   }
595   gst_segment_set_seek (&segment, rate, format, flags, cur_type,
596       cur, stop_type, stop, &only_need_update);
598   GST_DEBUG_OBJECT (demux, "seeking to time %" GST_TIME_FORMAT ", segment: "
599       "%" GST_SEGMENT_FORMAT, GST_TIME_ARGS (segment.start), &segment);
601   seek_time = segment.start;
603   /* FIXME: should check the KEY_UNIT flag; need to adjust last_stop to
604    * real start of data and segment_start to indexed time for key unit seek*/
605   if (!gst_asf_demux_seek_index_lookup (demux, &packet, seek_time, &idx_time)) {
606     /* First try to query our source to see if it can convert for us. This is
607        the case when our source is an mms stream, notice that in this case
608        gstmms will do a time based seek to get the byte offset, this is not a
609        problem as the seek to this offset needs to happen anway. */
610     gint64 offset;
611     GstFormat dest_format = GST_FORMAT_BYTES;
613     if (gst_pad_query_peer_convert (demux->sinkpad, GST_FORMAT_TIME, seek_time,
614             &dest_format, &offset) && dest_format == GST_FORMAT_BYTES) {
615       packet = (offset - demux->data_offset) / demux->packet_size;
616       GST_LOG_OBJECT (demux, "convert %" GST_TIME_FORMAT
617           " to bytes query result: %lld, data_ofset: %llu, packet_size: %u,"
618           " resulting packet: %u\n", GST_TIME_ARGS (seek_time), offset,
619           demux->data_offset, demux->packet_size, packet);
620     } else {
621       /* Hackety hack, this sucks. We just seek to an earlier position
622        *  and let the sinks throw away the stuff before the segment start */
623       if (flush && (accurate || keyunit_sync)) {
624         seek_time -= 5 * GST_SECOND;
625         if (seek_time < 0)
626           seek_time = 0;
627       }
629       packet = (guint) gst_util_uint64_scale (demux->num_packets,
630           seek_time, demux->play_time);
632       if (packet > demux->num_packets)
633         packet = demux->num_packets;
634     }
635   } else {
636     if (keyunit_sync) {
637       GST_DEBUG_OBJECT (demux, "key unit seek, adjust seek_time = %"
638           GST_TIME_FORMAT " to index_time = %" GST_TIME_FORMAT,
639           GST_TIME_ARGS (seek_time), GST_TIME_ARGS (idx_time));
640       segment.start = idx_time;
641       segment.last_stop = idx_time;
642       segment.time = idx_time;
643     }
644   }
646   GST_DEBUG_OBJECT (demux, "seeking to packet %u", packet);
648   GST_OBJECT_LOCK (demux);
649   demux->segment = segment;
650   demux->packet = packet;
651   demux->need_newsegment = TRUE;
652   gst_asf_demux_reset_stream_state_after_discont (demux);
653   GST_OBJECT_UNLOCK (demux);
655   /* restart our task since it might have been stopped when we did the flush */
656   gst_pad_start_task (demux->sinkpad, (GstTaskFunction) gst_asf_demux_loop,
657       demux);
659   /* streaming can continue now */
660   GST_PAD_STREAM_UNLOCK (demux->sinkpad);
662   return TRUE;
665 static gboolean
666 gst_asf_demux_handle_src_event (GstPad * pad, GstEvent * event)
668   GstASFDemux *demux;
669   gboolean ret;
671   demux = GST_ASF_DEMUX (gst_pad_get_parent (pad));
673   switch (GST_EVENT_TYPE (event)) {
674     case GST_EVENT_SEEK:
675       GST_LOG_OBJECT (pad, "seek event");
676       ret = gst_asf_demux_handle_seek_event (demux, event);
677       gst_event_unref (event);
678       break;
679     case GST_EVENT_QOS:
680     case GST_EVENT_NAVIGATION:
681       /* just drop these two silently */
682       gst_event_unref (event);
683       ret = FALSE;
684       break;
685     default:
686       GST_LOG_OBJECT (pad, "%s event", GST_EVENT_TYPE_NAME (event));
687       ret = gst_pad_event_default (pad, event);
688       break;
689   }
691   gst_object_unref (demux);
692   return ret;
695 static inline guint32
696 gst_asf_demux_identify_guid (const ASFGuidHash * guids, ASFGuid * guid)
698   guint32 ret;
700   ret = gst_asf_identify_guid (guids, guid);
702   GST_LOG ("%s  0x%08x-0x%08x-0x%08x-0x%08x",
703       gst_asf_get_guid_nick (guids, ret),
704       guid->v1, guid->v2, guid->v3, guid->v4);
706   return ret;
709 typedef struct
711   AsfObjectID id;
712   guint64 size;
713 } AsfObject;
715 static gboolean
716 asf_demux_peek_object (GstASFDemux * demux, const guint8 * data,
717     guint data_len, AsfObject * object)
719   ASFGuid guid;
721   if (data_len < ASF_OBJECT_HEADER_SIZE)
722     return FALSE;
724   guid.v1 = GST_READ_UINT32_LE (data + 0);
725   guid.v2 = GST_READ_UINT32_LE (data + 4);
726   guid.v3 = GST_READ_UINT32_LE (data + 8);
727   guid.v4 = GST_READ_UINT32_LE (data + 12);
729   object->size = GST_READ_UINT64_LE (data + 16);
731   /* FIXME: make asf_demux_identify_object_guid() */
732   object->id = gst_asf_demux_identify_guid (asf_object_guids, &guid);
733   if (object->id == ASF_OBJ_UNDEFINED) {
734     GST_WARNING_OBJECT (demux, "Unknown object %08x-%08x-%08x-%08x",
735         guid.v1, guid.v2, guid.v3, guid.v4);
736   }
738   return TRUE;
741 static GstFlowReturn
742 gst_asf_demux_chain_headers (GstASFDemux * demux)
744   GstFlowReturn flow;
745   AsfObject obj;
746   guint8 *header_data, *data = NULL;
747   const guint8 *cdata = NULL;
748   guint64 header_size;
750   cdata = (guint8 *) gst_adapter_peek (demux->adapter, ASF_OBJECT_HEADER_SIZE);
751   if (cdata == NULL)
752     goto need_more_data;
754   asf_demux_peek_object (demux, cdata, ASF_OBJECT_HEADER_SIZE, &obj);
755   if (obj.id != ASF_OBJ_HEADER)
756     goto wrong_type;
758   GST_LOG_OBJECT (demux, "header size = %u", (guint) obj.size);
760   /* + 50 for non-packet data at beginning of ASF_OBJ_DATA */
761   if (gst_adapter_available (demux->adapter) < obj.size + 50)
762     goto need_more_data;
764   data = gst_adapter_take (demux->adapter, obj.size + 50);
766   header_data = data;
767   header_size = obj.size;
768   flow = gst_asf_demux_process_object (demux, &header_data, &header_size);
769   if (flow != GST_FLOW_OK)
770     goto parse_failed;
772   /* calculate where the packet data starts */
773   demux->data_offset = obj.size + 50;
775   /* now parse the beginning of the ASF_OBJ_DATA object */
776   if (!gst_asf_demux_parse_data_object_start (demux, data + obj.size))
777     goto wrong_type;
779   if (demux->num_streams == 0)
780     goto no_streams;
782   g_free (data);
783   return GST_FLOW_OK;
785 /* NON-FATAL */
786 need_more_data:
787   {
788     GST_LOG_OBJECT (demux, "not enough data in adapter yet");
789     return GST_FLOW_OK;
790   }
792 /* ERRORS */
793 wrong_type:
794   {
795     GST_ELEMENT_ERROR (demux, STREAM, WRONG_TYPE, (NULL),
796         ("This doesn't seem to be an ASF file"));
797     g_free (data);
798     return GST_FLOW_ERROR;
799   }
800 no_streams:
801 parse_failed:
802   {
803     GST_ELEMENT_ERROR (demux, STREAM, DEMUX, (NULL),
804         ("header parsing failed, or no streams found, flow = %s",
805             gst_flow_get_name (flow)));
806     g_free (data);
807     return GST_FLOW_ERROR;
808   }
811 static GstFlowReturn
812 gst_asf_demux_aggregate_flow_return (GstASFDemux * demux)
814   int i;
815   GST_DEBUG_OBJECT (demux, "Aggregating");
817   for (i = 0; i < demux->num_streams; i++) {
818     if (demux->stream[i].active) {
819       GstFlowReturn flowret = demux->stream[i].last_flow;
820       GST_DEBUG_OBJECT (demux, "Aggregating: flow %i return %s", i,
821           gst_flow_get_name (flowret));
822       if (flowret != GST_FLOW_NOT_LINKED)
823         return flowret;
824     }
825   }
827   /* If we got here, then all our active streams are not linked */
828   return GST_FLOW_NOT_LINKED;
831 static gboolean
832 gst_asf_demux_pull_data (GstASFDemux * demux, guint64 offset, guint size,
833     GstBuffer ** p_buf, GstFlowReturn * p_flow)
835   GstFlowReturn flow;
837   GST_LOG_OBJECT (demux, "pulling buffer at %" G_GUINT64_FORMAT "+%u",
838       offset, size);
840   flow = gst_pad_pull_range (demux->sinkpad, offset, size, p_buf);
842   if (p_flow)
843     *p_flow = flow;
845   if (flow != GST_FLOW_OK) {
846     GST_DEBUG_OBJECT (demux, "flow %s pulling buffer at %" G_GUINT64_FORMAT
847         "+%u", gst_flow_get_name (flow), offset, size);
848     *p_buf = NULL;
849     return FALSE;
850   }
852   g_assert (*p_buf != NULL);
854   if (GST_BUFFER_SIZE (*p_buf) < size) {
855     GST_DEBUG_OBJECT (demux, "short read pulling buffer at %" G_GUINT64_FORMAT
856         "+%u (got only %u bytes)", offset, size, GST_BUFFER_SIZE (*p_buf));
857     gst_buffer_unref (*p_buf);
858     if (p_flow)
859       *p_flow = GST_FLOW_UNEXPECTED;
860     *p_buf = NULL;
861     return FALSE;
862   }
864   return TRUE;
867 static void
868 gst_asf_demux_pull_indices (GstASFDemux * demux)
870   GstBuffer *buf = NULL;
871   guint64 offset;
872   guint num_read = 0;
874   offset = demux->index_offset;
876   if (offset == 0) {
877     GST_DEBUG_OBJECT (demux, "can't read indices, don't know index offset");
878     return;
879   }
881   while (gst_asf_demux_pull_data (demux, offset, 16 + 8, &buf, NULL)) {
882     GstFlowReturn flow;
883     AsfObject obj;
885     asf_demux_peek_object (demux, GST_BUFFER_DATA (buf), 16 + 8, &obj);
886     gst_buffer_replace (&buf, NULL);
888     /* check for sanity */
889     if (obj.size > (5 * 1024 * 1024)) {
890       GST_DEBUG_OBJECT (demux, "implausible index object size, bailing out");
891       break;
892     }
894     if (!gst_asf_demux_pull_data (demux, offset, obj.size, &buf, NULL))
895       break;
897     GST_LOG_OBJECT (demux, "index object at offset 0x%" G_GINT64_MODIFIER "X"
898         ", size %u", offset, (guint) obj.size);
900     offset += obj.size;         /* increase before _process_object changes it */
902     flow = gst_asf_demux_process_object (demux, &buf->data, &obj.size);
903     gst_buffer_replace (&buf, NULL);
905     if (flow != GST_FLOW_OK)
906       break;
908     ++num_read;
909   }
910   GST_DEBUG_OBJECT (demux, "read %u index objects", num_read);
913 static gboolean
914 gst_asf_demux_parse_data_object_start (GstASFDemux * demux, guint8 * data)
916   AsfObject obj;
918   asf_demux_peek_object (demux, data, 50, &obj);
919   if (obj.id != ASF_OBJ_DATA) {
920     GST_WARNING_OBJECT (demux, "headers not followed by a DATA object");
921     return FALSE;
922   }
924   demux->state = GST_ASF_DEMUX_STATE_DATA;
926   if (!demux->broadcast && obj.size > 50) {
927     demux->data_size = obj.size - 50;
928     /* CHECKME: for at least one file this is off by +158 bytes?! */
929     demux->index_offset = demux->data_offset + demux->data_size;
930   } else {
931     demux->data_size = 0;
932     demux->index_offset = 0;
933   }
935   demux->packet = 0;
937   if (!demux->broadcast) {
938     /* skip object header (24 bytes) and file GUID (16 bytes) */
939     demux->num_packets = GST_READ_UINT64_LE (data + (16 + 8) + 16);
940   } else {
941     demux->num_packets = 0;
942   }
944   if (demux->num_packets == 0)
945     demux->seekable = FALSE;
947   /* fallback in the unlikely case that headers are inconsistent, can't hurt */
948   if (demux->data_size == 0 && demux->num_packets > 0) {
949     demux->data_size = demux->num_packets * demux->packet_size;
950     demux->index_offset = demux->data_offset + demux->data_size;
951   }
953   /* process pending stream objects and create pads for those */
954   gst_asf_demux_process_queued_extended_stream_objects (demux);
956   GST_INFO_OBJECT (demux, "Stream has %" G_GUINT64_FORMAT " packets, "
957       "data_offset=%" G_GINT64_FORMAT ", data_size=%" G_GINT64_FORMAT
958       ", index_offset=%" G_GUINT64_FORMAT, demux->num_packets,
959       demux->data_offset, demux->data_size, demux->index_offset);
961   return TRUE;
964 static gboolean
965 gst_asf_demux_pull_headers (GstASFDemux * demux)
967   GstFlowReturn flow;
968   AsfObject obj;
969   GstBuffer *buf = NULL;
970   guint64 size;
972   GST_LOG_OBJECT (demux, "reading headers");
974   /* pull HEADER object header, so we know its size */
975   if (!gst_asf_demux_pull_data (demux, 0, 16 + 8, &buf, NULL))
976     goto read_failed;
978   asf_demux_peek_object (demux, GST_BUFFER_DATA (buf), 16 + 8, &obj);
979   gst_buffer_replace (&buf, NULL);
981   if (obj.id != ASF_OBJ_HEADER)
982     goto wrong_type;
984   GST_LOG_OBJECT (demux, "header size = %u", (guint) obj.size);
986   /* pull HEADER object */
987   if (!gst_asf_demux_pull_data (demux, 0, obj.size, &buf, NULL))
988     goto read_failed;
990   size = obj.size;              /* don't want obj.size changed */
991   flow = gst_asf_demux_process_object (demux, &buf->data, &size);
992   gst_buffer_replace (&buf, NULL);
994   if (flow != GST_FLOW_OK) {
995     GST_WARNING_OBJECT (demux, "process_object: %s", gst_flow_get_name (flow));
996     goto parse_failed;
997   }
999   /* calculate where the packet data starts */
1000   demux->data_offset = obj.size + 50;
1002   /* now pull beginning of DATA object before packet data */
1003   if (!gst_asf_demux_pull_data (demux, obj.size, 50, &buf, NULL))
1004     goto read_failed;
1006   if (!gst_asf_demux_parse_data_object_start (demux, GST_BUFFER_DATA (buf)))
1007     goto wrong_type;
1009   if (demux->num_streams == 0)
1010     goto no_streams;
1012   gst_buffer_replace (&buf, NULL);
1013   return TRUE;
1015 /* ERRORS */
1016 wrong_type:
1017   {
1018     gst_buffer_replace (&buf, NULL);
1019     GST_ELEMENT_ERROR (demux, STREAM, WRONG_TYPE, (NULL),
1020         ("This doesn't seem to be an ASF file"));
1021     return FALSE;
1022   }
1023 no_streams:
1024 read_failed:
1025 parse_failed:
1026   {
1027     GST_ELEMENT_ERROR (demux, STREAM, DEMUX, (NULL), (NULL));
1028     return FALSE;
1029   }
1032 static gboolean
1033 all_streams_prerolled (GstASFDemux * demux)
1035   GstClockTime preroll_time;
1036   guint i, num_no_data = 0;
1038   preroll_time = demux->preroll;
1040   /* returns TRUE as long as there isn't a stream which (a) has data queued
1041    * and (b) the timestamp of last piece of data queued is < demux->preroll
1042    * AND there is at least one other stream with data queued */
1043   for (i = 0; i < demux->num_streams; ++i) {
1044     AsfPayload *last_payload;
1045     AsfStream *stream;
1046     guint last_idx;
1048     stream = &demux->stream[i];
1049     if (stream->payloads->len == 0) {
1050       ++num_no_data;
1051       GST_LOG_OBJECT (stream->pad, "no data queued");
1052       continue;
1053     }
1055     last_idx = stream->payloads->len - 1;
1056     last_payload = &g_array_index (stream->payloads, AsfPayload, last_idx);
1058     GST_LOG_OBJECT (stream->pad, "checking if %" GST_TIME_FORMAT " > %"
1059         GST_TIME_FORMAT, GST_TIME_ARGS (last_payload->ts),
1060         GST_TIME_ARGS (preroll_time));
1061     if (last_payload->ts <= preroll_time) {
1062       GST_LOG_OBJECT (stream->pad, "not beyond preroll point yet");
1063       return FALSE;
1064     }
1065   }
1067   if (num_no_data == demux->num_streams)
1068     return FALSE;
1070   return TRUE;
1073 #if 0
1074 static gboolean
1075 gst_asf_demux_have_mutually_exclusive_active_stream (GstASFDemux * demux,
1076     AsfStream * stream)
1078   GSList *l;
1080   for (l = demux->mut_ex_streams; l != NULL; l = l->next) {
1081     guint8 *mes;
1083     /* check for each mutual exclusion group whether it affects this stream */
1084     for (mes = (guint8 *) l->data; mes != NULL && *mes != 0xff; ++mes) {
1085       if (*mes == stream->id) {
1086         /* we are in this group; let's check if we've already activated streams
1087          * that are in the same group (and hence mutually exclusive to this
1088          * one) */
1089         for (mes = (guint8 *) l->data; mes != NULL && *mes != 0xff; ++mes) {
1090           guint i;
1092           for (i = 0; i < demux->num_streams; ++i) {
1093             if (demux->stream[i].id == *mes && demux->stream[i].active) {
1094               GST_LOG_OBJECT (demux, "stream with ID %d is mutually exclusive "
1095                   "to already active stream with ID %d", stream->id,
1096                   demux->stream[i].id);
1097               return TRUE;
1098             }
1099           }
1100         }
1101         /* we can only be in this group once, let's break out and move on to
1102          * the next mutual exclusion group */
1103         break;
1104       }
1105     }
1106   }
1108   return FALSE;
1110 #endif
1112 static gboolean
1113 gst_asf_demux_check_activate_streams (GstASFDemux * demux, gboolean force)
1115   guint i;
1117   if (demux->activated_streams)
1118     return TRUE;
1120   if (!all_streams_prerolled (demux) && !force) {
1121     GST_DEBUG_OBJECT (demux, "not all streams with data beyond preroll yet");
1122     return FALSE;
1123   }
1125   for (i = 0; i < demux->num_streams; ++i) {
1126     AsfStream *stream = &demux->stream[i];
1128     if (stream->payloads->len > 0) {
1129       /* we don't check mutual exclusion stuff here; either we have data for
1130        * a stream, then we active it, or we don't, then we'll ignore it */
1131       GST_LOG_OBJECT (stream->pad, "is prerolled - activate!");
1132       gst_asf_demux_activate_stream (demux, stream);
1133     } else {
1134       GST_LOG_OBJECT (stream->pad, "no data, ignoring stream");
1135     }
1136   }
1138   demux->activated_streams = TRUE;
1139   GST_LOG_OBJECT (demux, "signalling no more pads");
1140   gst_element_no_more_pads (GST_ELEMENT (demux));
1141   return TRUE;
1144 /* returns the stream that has a complete payload with the lowest timestamp
1145  * queued, or NULL (we push things by timestamp because during the internal
1146  * prerolling we might accumulate more data then the external queues can take,
1147  * so we'd lock up if we pushed all accumulated data for stream N in one go) */
1148 static AsfStream *
1149 gst_asf_demux_find_stream_with_complete_payload (GstASFDemux * demux)
1151   AsfPayload *best_payload = NULL;
1152   AsfStream *best_stream = NULL;
1153   guint i;
1155   for (i = 0; i < demux->num_streams; ++i) {
1156     AsfStream *stream;
1158     stream = &demux->stream[i];
1160     /* Don't push any data until we have at least one payload that falls within
1161      * the current segment. This way we can remove out-of-segment payloads that
1162      * don't need to be decoded after a seek, sending only data from the
1163      * keyframe directly before our segment start */
1164     if (stream->payloads->len > 0) {
1165       AsfPayload *payload;
1166       guint last_idx;
1168       last_idx = stream->payloads->len - 1;
1169       payload = &g_array_index (stream->payloads, AsfPayload, last_idx);
1170       if (GST_CLOCK_TIME_IS_VALID (payload->ts) &&
1171           payload->ts < demux->segment.start) {
1172         GST_DEBUG_OBJECT (stream->pad, "Last queued payload has timestamp %"
1173             GST_TIME_FORMAT " which is before our segment start %"
1174             GST_TIME_FORMAT ", not pushing yet", GST_TIME_ARGS (payload->ts),
1175             GST_TIME_ARGS (demux->segment.start));
1176         continue;
1177       }
1178     }
1180     /* Now see if there's a complete payload queued for this stream */
1181     if (stream->payloads->len > 0) {
1182       AsfPayload *payload;
1184       payload = &g_array_index (stream->payloads, AsfPayload, 0);
1185       if (!gst_asf_payload_is_complete (payload))
1186         continue;
1188       /* ... and whether its timestamp is lower than the current best */
1189       if (best_stream == NULL || best_payload->ts > payload->ts) {
1190         best_stream = stream;
1191         best_payload = payload;
1192       }
1193     }
1194   }
1196   return best_stream;
1199 static GstFlowReturn
1200 gst_asf_demux_push_complete_payloads (GstASFDemux * demux, gboolean force)
1202   AsfStream *stream;
1204   if (G_UNLIKELY (!demux->activated_streams)) {
1205     if (!gst_asf_demux_check_activate_streams (demux, force))
1206       return GST_FLOW_OK;
1207     /* streams are now activated */
1208   }
1210   /* do we need to send a newsegment event */
1211   if (demux->need_newsegment) {
1213     /* wait until we had a chance to "lock on" some payload's timestamp */
1214     if (!GST_CLOCK_TIME_IS_VALID (demux->segment_ts))
1215       return GST_FLOW_OK;
1216     else {
1217       /* safe default if insufficient upstream info */
1218       if (!GST_CLOCK_TIME_IS_VALID (demux->in_gap))
1219         demux->in_gap = 0;
1220     }
1222     if (demux->segment.stop == GST_CLOCK_TIME_NONE &&
1223         demux->segment.duration > 0) {
1224       /* slight HACK; prevent clipping of last bit */
1225       demux->segment.stop = demux->segment.duration + demux->in_gap;
1226     }
1228     GST_DEBUG_OBJECT (demux, "sending new-segment event %" GST_SEGMENT_FORMAT,
1229         &demux->segment);
1231     /* note: we fix up all timestamps to start from 0, so this should be ok */
1232     gst_asf_demux_send_event_unlocked (demux,
1233         gst_event_new_new_segment (FALSE, demux->segment.rate,
1234             GST_FORMAT_TIME, demux->segment.start, demux->segment.stop,
1235             demux->segment.start));
1237     /* now post any global tags we may have found */
1238     if (demux->taglist == NULL)
1239       demux->taglist = gst_tag_list_new ();
1241     gst_tag_list_add (demux->taglist, GST_TAG_MERGE_REPLACE,
1242         GST_TAG_CONTAINER_FORMAT, "ASF", NULL);
1244     GST_DEBUG_OBJECT (demux, "global tags: %" GST_PTR_FORMAT, demux->taglist);
1245     gst_element_found_tags (GST_ELEMENT (demux), demux->taglist);
1246     demux->taglist = NULL;
1248     demux->need_newsegment = FALSE;
1249     demux->segment_running = TRUE;
1250   }
1252   while ((stream = gst_asf_demux_find_stream_with_complete_payload (demux))) {
1253     AsfPayload *payload;
1255     payload = &g_array_index (stream->payloads, AsfPayload, 0);
1257     /* Do we have tags pending for this stream? */
1258     if (stream->pending_tags) {
1259       GST_LOG_OBJECT (stream->pad, "%" GST_PTR_FORMAT, stream->pending_tags);
1260       gst_element_found_tags_for_pad (GST_ELEMENT (demux), stream->pad,
1261           stream->pending_tags);
1262       stream->pending_tags = NULL;
1263     }
1265     /* We have the whole packet now so we should push the packet to
1266      * the src pad now. First though we should check if we need to do
1267      * descrambling */
1268     if (demux->span > 1) {
1269       gst_asf_demux_descramble_buffer (demux, stream, &payload->buf);
1270     }
1272     payload->buf = gst_buffer_make_metadata_writable (payload->buf);
1274     if (!payload->keyframe) {
1275       GST_BUFFER_FLAG_SET (payload->buf, GST_BUFFER_FLAG_DELTA_UNIT);
1276     }
1278     if (stream->discont) {
1279       GST_DEBUG_OBJECT (stream->pad, "marking DISCONT on stream");
1280       GST_BUFFER_FLAG_SET (payload->buf, GST_BUFFER_FLAG_DISCONT);
1281       stream->discont = FALSE;
1282     }
1284     if (G_UNLIKELY (stream->is_video && payload->par_x && payload->par_y &&
1285             (payload->par_x != stream->par_x) &&
1286             (payload->par_y != stream->par_y))) {
1287       GST_DEBUG ("Updating PAR (%d/%d => %d/%d)",
1288           stream->par_x, stream->par_y, payload->par_x, payload->par_y);
1289       stream->par_x = payload->par_x;
1290       stream->par_y = payload->par_y;
1291       gst_caps_set_simple (stream->caps, "pixel-aspect-ratio",
1292           GST_TYPE_FRACTION, stream->par_x, stream->par_y, NULL);
1293       gst_pad_set_caps (stream->pad, stream->caps);
1294     }
1296     if (G_UNLIKELY (stream->interlaced != payload->interlaced)) {
1297       GST_DEBUG ("Updating interlaced status (%d => %d)", stream->interlaced,
1298           payload->interlaced);
1299       stream->interlaced = payload->interlaced;
1300       gst_caps_set_simple (stream->caps, "interlaced", G_TYPE_BOOLEAN,
1301           stream->interlaced, NULL);
1302     }
1304     gst_buffer_set_caps (payload->buf, stream->caps);
1306     /* (sort of) interpolate timestamps using upstream "frame of reference",
1307      * typically useful for live src, but might (unavoidably) mess with
1308      * position reporting if a live src is playing not so live content
1309      * (e.g. rtspsrc taking some time to fall back to tcp) */
1310     GST_BUFFER_TIMESTAMP (payload->buf) = payload->ts + demux->in_gap;
1311     GST_BUFFER_DURATION (payload->buf) = payload->duration;
1313     /* FIXME: we should really set durations on buffers if we can */
1315     GST_LOG_OBJECT (stream->pad, "pushing buffer, ts=%" GST_TIME_FORMAT
1316         ", dur=%" GST_TIME_FORMAT " size=%u",
1317         GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (payload->buf)),
1318         GST_TIME_ARGS (GST_BUFFER_DURATION (payload->buf)),
1319         GST_BUFFER_SIZE (payload->buf));
1321     stream->last_flow = gst_pad_push (stream->pad, payload->buf);
1322     payload->buf = NULL;
1323     g_array_remove_index (stream->payloads, 0);
1324   }
1326   return gst_asf_demux_aggregate_flow_return (demux);
1329 static void
1330 gst_asf_demux_loop (GstASFDemux * demux)
1332   GstFlowReturn flow = GST_FLOW_OK;
1333   GstBuffer *buf = NULL;
1334   guint64 off;
1336   if (demux->state == GST_ASF_DEMUX_STATE_HEADER) {
1337     if (!gst_asf_demux_pull_headers (demux)) {
1338       flow = GST_FLOW_ERROR;
1339       goto pause;
1340     }
1342     gst_asf_demux_pull_indices (demux);
1343   }
1345   g_assert (demux->state == GST_ASF_DEMUX_STATE_DATA);
1347   if (demux->num_packets != 0 && demux->packet >= demux->num_packets)
1348     goto eos;
1350   GST_LOG_OBJECT (demux, "packet %u/%u", (guint) demux->packet + 1,
1351       (guint) demux->num_packets);
1353   off = demux->data_offset + (demux->packet * demux->packet_size);
1355   if (!gst_asf_demux_pull_data (demux, off, demux->packet_size, &buf, &flow)) {
1356     GST_DEBUG_OBJECT (demux, "got flow %s", gst_flow_get_name (flow));
1357     if (flow == GST_FLOW_UNEXPECTED)
1358       goto eos;
1359     else if (!GST_FLOW_IS_FATAL (flow)) {
1360       GST_DEBUG_OBJECT (demux, "Not fatal");
1361       goto pause;
1362     } else
1363       goto read_failed;
1364   }
1366   /* FIXME: maybe we should just skip broken packets and error out only
1367    * after a few broken packets in a row? */
1368   if (!gst_asf_demux_parse_packet (demux, buf))
1369     goto parse_error;
1371   gst_buffer_unref (buf);
1373   flow = gst_asf_demux_push_complete_payloads (demux, FALSE);
1375   ++demux->packet;
1377   if (demux->num_packets > 0 && demux->packet >= demux->num_packets) {
1378     GST_LOG_OBJECT (demux, "reached EOS");
1379     goto eos;
1380   }
1382   if (flow != GST_FLOW_OK) {
1383     GST_DEBUG_OBJECT (demux, "pushing complete payloads failed");
1384     goto pause;
1385   }
1387   /* check if we're at the end of the configured segment */
1388   /* FIXME: check if segment end reached etc. */
1390   return;
1392 eos:
1393   {
1394     /* if we haven't activated our streams yet, this might be because we have
1395      * less data queued than required for preroll; force stream activation and
1396      * send any pending payloads before sending EOS */
1397     if (!demux->activated_streams)
1398       gst_asf_demux_push_complete_payloads (demux, TRUE);
1400     /* we want to push an eos or post a segment-done in any case */
1401     if (demux->segment.flags & GST_SEEK_FLAG_SEGMENT) {
1402       gint64 stop;
1404       /* for segment playback we need to post when (in stream time)
1405        * we stopped, this is either stop (when set) or the duration. */
1406       if ((stop = demux->segment.stop) == -1)
1407         stop = demux->segment.duration;
1409       GST_INFO_OBJECT (demux, "Posting segment-done, at end of segment");
1410       gst_element_post_message (GST_ELEMENT_CAST (demux),
1411           gst_message_new_segment_done (GST_OBJECT (demux), GST_FORMAT_TIME,
1412               stop));
1413     } else {
1414       /* normal playback, send EOS to all linked pads */
1415       GST_INFO_OBJECT (demux, "Sending EOS, at end of stream");
1416       gst_asf_demux_send_event_unlocked (demux, gst_event_new_eos ());
1417     }
1418     /* ... and fall through to pause */
1419     GST_DEBUG_OBJECT (demux, "EOSing");
1420   }
1421 pause:
1422   {
1423     GST_DEBUG_OBJECT (demux, "pausing task");
1424     demux->segment_running = FALSE;
1425     gst_pad_pause_task (demux->sinkpad);
1427     /* For the error cases (not EOS) */
1428     if (GST_FLOW_IS_FATAL (flow) || flow == GST_FLOW_NOT_LINKED) {
1429       /* Post an error. Hopefully something else already has, but if not... */
1430       GST_ELEMENT_ERROR (demux, STREAM, FAILED,
1431           (_("Internal data stream error.")),
1432           ("streaming stopped, reason %s", gst_flow_get_name (flow)));
1433     }
1434     return;
1435   }
1437 /* ERRORS */
1438 read_failed:
1439   {
1440     GST_DEBUG_OBJECT (demux, "Read failed, doh");
1441     gst_asf_demux_send_event_unlocked (demux, gst_event_new_eos ());
1442     flow = GST_FLOW_UNEXPECTED;
1443     goto pause;
1444   }
1445 parse_error:
1446   {
1447     gst_buffer_unref (buf);
1448     GST_ELEMENT_ERROR (demux, STREAM, DEMUX, (NULL),
1449         ("Error parsing ASF packet %u", (guint) demux->packet));
1450     gst_asf_demux_send_event_unlocked (demux, gst_event_new_eos ());
1451     flow = GST_FLOW_ERROR;
1452     goto pause;
1453   }
1456 static GstFlowReturn
1457 gst_asf_demux_chain (GstPad * pad, GstBuffer * buf)
1459   GstFlowReturn ret = GST_FLOW_OK;
1460   GstASFDemux *demux;
1462   demux = GST_ASF_DEMUX (GST_PAD_PARENT (pad));
1464   GST_LOG_OBJECT (demux, "buffer: size=%u, offset=%" G_GINT64_FORMAT ", time=%"
1465       GST_TIME_FORMAT, GST_BUFFER_SIZE (buf), GST_BUFFER_OFFSET (buf),
1466       GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)));
1468   if (GST_BUFFER_IS_DISCONT (buf)) {
1469     GST_DEBUG_OBJECT (demux, "received DISCONT");
1470     gst_asf_demux_mark_discont (demux);
1471   }
1473   if (!GST_CLOCK_TIME_IS_VALID (demux->in_gap) &&
1474       GST_BUFFER_TIMESTAMP_IS_VALID (buf)) {
1475     demux->in_gap = GST_BUFFER_TIMESTAMP (buf) - demux->in_segment.start;
1476     GST_DEBUG_OBJECT (demux, "upstream segment start %" GST_TIME_FORMAT
1477         ", interpolation gap: %" GST_TIME_FORMAT,
1478         GST_TIME_ARGS (demux->in_segment.start), GST_TIME_ARGS (demux->in_gap));
1479   }
1481   gst_adapter_push (demux->adapter, buf);
1483   switch (demux->state) {
1484     case GST_ASF_DEMUX_STATE_HEADER:{
1485       ret = gst_asf_demux_chain_headers (demux);
1486       if (demux->state != GST_ASF_DEMUX_STATE_DATA)
1487         break;
1488       /* otherwise fall through */
1489     }
1490     case GST_ASF_DEMUX_STATE_DATA:
1491     {
1492       guint64 data_size;
1494       data_size = demux->packet_size;
1496       while (gst_adapter_available (demux->adapter) >= data_size) {
1497         GstBuffer *buf;
1499         /* do not overshoot data section when streaming */
1500         if (demux->num_packets != 0 && demux->packet >= 0
1501             && demux->packet >= demux->num_packets)
1502           goto eos;
1504         buf = gst_adapter_take_buffer (demux->adapter, data_size);
1506         /* FIXME: maybe we should just skip broken packets and error out only
1507          * after a few broken packets in a row? */
1508         if (!gst_asf_demux_parse_packet (demux, buf)) {
1509           GST_WARNING_OBJECT (demux, "Parse error");
1510         }
1512         gst_buffer_unref (buf);
1514         ret = gst_asf_demux_push_complete_payloads (demux, FALSE);
1516         if (demux->packet >= 0)
1517           ++demux->packet;
1518       }
1519       break;
1520     }
1521     default:
1522       g_assert_not_reached ();
1523   }
1525 done:
1526   if (ret != GST_FLOW_OK)
1527     GST_DEBUG_OBJECT (demux, "flow: %s", gst_flow_get_name (ret));
1529   return ret;
1531 eos:
1532   {
1533     GST_DEBUG_OBJECT (demux, "Handled last packet, setting EOS");
1534     ret = GST_FLOW_UNEXPECTED;
1535     goto done;
1536   }
1539 static inline gboolean
1540 gst_asf_demux_skip_bytes (guint num_bytes, guint8 ** p_data, guint64 * p_size)
1542   if (*p_size < num_bytes)
1543     return FALSE;
1545   *p_data += num_bytes;
1546   *p_size -= num_bytes;
1547   return TRUE;
1550 static inline guint8
1551 gst_asf_demux_get_uint8 (guint8 ** p_data, guint64 * p_size)
1553   guint8 ret;
1555   g_assert (*p_size >= 1);
1556   ret = GST_READ_UINT8 (*p_data);
1557   *p_data += sizeof (guint8);
1558   *p_size -= sizeof (guint8);
1559   return ret;
1562 static inline guint16
1563 gst_asf_demux_get_uint16 (guint8 ** p_data, guint64 * p_size)
1565   guint16 ret;
1567   g_assert (*p_size >= 2);
1568   ret = GST_READ_UINT16_LE (*p_data);
1569   *p_data += sizeof (guint16);
1570   *p_size -= sizeof (guint16);
1571   return ret;
1574 static inline guint32
1575 gst_asf_demux_get_uint32 (guint8 ** p_data, guint64 * p_size)
1577   guint32 ret;
1579   g_assert (*p_size >= 4);
1580   ret = GST_READ_UINT32_LE (*p_data);
1581   *p_data += sizeof (guint32);
1582   *p_size -= sizeof (guint32);
1583   return ret;
1586 static inline guint64
1587 gst_asf_demux_get_uint64 (guint8 ** p_data, guint64 * p_size)
1589   guint64 ret;
1591   g_assert (*p_size >= 8);
1592   ret = GST_READ_UINT64_LE (*p_data);
1593   *p_data += sizeof (guint64);
1594   *p_size -= sizeof (guint64);
1595   return ret;
1598 static inline guint32
1599 gst_asf_demux_get_var_length (guint8 type, guint8 ** p_data, guint64 * p_size)
1601   switch (type) {
1602     case 0:
1603       return 0;
1605     case 1:
1606       g_assert (*p_size >= 1);
1607       return gst_asf_demux_get_uint8 (p_data, p_size);
1609     case 2:
1610       g_assert (*p_size >= 2);
1611       return gst_asf_demux_get_uint16 (p_data, p_size);
1613     case 3:
1614       g_assert (*p_size >= 4);
1615       return gst_asf_demux_get_uint32 (p_data, p_size);
1617     default:
1618       break;
1619   }
1621   g_assert_not_reached ();
1624 static gboolean
1625 gst_asf_demux_get_buffer (GstBuffer ** p_buf, guint num_bytes_to_read,
1626     guint8 ** p_data, guint64 * p_size)
1628   *p_buf = NULL;
1630   if (*p_size < num_bytes_to_read)
1631     return FALSE;
1633   *p_buf = gst_buffer_new_and_alloc (num_bytes_to_read);
1634   memcpy (GST_BUFFER_DATA (*p_buf), *p_data, num_bytes_to_read);
1635   *p_data += num_bytes_to_read;
1636   *p_size -= num_bytes_to_read;
1637   return TRUE;
1640 static gboolean
1641 gst_asf_demux_get_bytes (guint8 ** p_buf, guint num_bytes_to_read,
1642     guint8 ** p_data, guint64 * p_size)
1644   *p_buf = NULL;
1646   if (*p_size < num_bytes_to_read)
1647     return FALSE;
1649   *p_buf = g_memdup (*p_data, num_bytes_to_read);
1650   *p_data += num_bytes_to_read;
1651   *p_size -= num_bytes_to_read;
1652   return TRUE;
1655 static gboolean
1656 gst_asf_demux_get_string (gchar ** p_str, guint16 * p_strlen,
1657     guint8 ** p_data, guint64 * p_size)
1659   guint16 s_length;
1660   guint8 *s;
1662   *p_str = NULL;
1664   if (*p_size < 2)
1665     return FALSE;
1667   s_length = gst_asf_demux_get_uint16 (p_data, p_size);
1669   if (p_strlen)
1670     *p_strlen = s_length;
1672   if (s_length == 0) {
1673     GST_WARNING ("zero-length string");
1674     *p_str = g_strdup ("");
1675     return TRUE;
1676   }
1678   if (!gst_asf_demux_get_bytes (&s, s_length, p_data, p_size))
1679     return FALSE;
1681   g_assert (s != NULL);
1683   /* just because They don't exist doesn't
1684    * mean They are not out to get you ... */
1685   if (s[s_length - 1] != '\0') {
1686     s = g_realloc (s, s_length + 1);
1687     s[s_length] = '\0';
1688   }
1690   *p_str = (gchar *) s;
1691   return TRUE;
1695 static void
1696 gst_asf_demux_get_guid (ASFGuid * guid, guint8 ** p_data, guint64 * p_size)
1698   g_assert (*p_size >= 4 * sizeof (guint32));
1700   guid->v1 = gst_asf_demux_get_uint32 (p_data, p_size);
1701   guid->v2 = gst_asf_demux_get_uint32 (p_data, p_size);
1702   guid->v3 = gst_asf_demux_get_uint32 (p_data, p_size);
1703   guid->v4 = gst_asf_demux_get_uint32 (p_data, p_size);
1706 static gboolean
1707 gst_asf_demux_get_stream_audio (asf_stream_audio * audio, guint8 ** p_data,
1708     guint64 * p_size)
1710   if (*p_size < (2 + 2 + 4 + 4 + 2 + 2 + 2))
1711     return FALSE;
1713   /* WAVEFORMATEX Structure */
1714   audio->codec_tag = gst_asf_demux_get_uint16 (p_data, p_size);
1715   audio->channels = gst_asf_demux_get_uint16 (p_data, p_size);
1716   audio->sample_rate = gst_asf_demux_get_uint32 (p_data, p_size);
1717   audio->byte_rate = gst_asf_demux_get_uint32 (p_data, p_size);
1718   audio->block_align = gst_asf_demux_get_uint16 (p_data, p_size);
1719   audio->word_size = gst_asf_demux_get_uint16 (p_data, p_size);
1720   /* Codec specific data size */
1721   audio->size = gst_asf_demux_get_uint16 (p_data, p_size);
1722   return TRUE;
1725 static gboolean
1726 gst_asf_demux_get_stream_video (asf_stream_video * video, guint8 ** p_data,
1727     guint64 * p_size)
1729   if (*p_size < (4 + 4 + 1 + 2))
1730     return FALSE;
1732   video->width = gst_asf_demux_get_uint32 (p_data, p_size);
1733   video->height = gst_asf_demux_get_uint32 (p_data, p_size);
1734   video->unknown = gst_asf_demux_get_uint8 (p_data, p_size);
1735   video->size = gst_asf_demux_get_uint16 (p_data, p_size);
1736   return TRUE;
1739 static gboolean
1740 gst_asf_demux_get_stream_video_format (asf_stream_video_format * fmt,
1741     guint8 ** p_data, guint64 * p_size)
1743   if (*p_size < (4 + 4 + 4 + 2 + 2 + 4 + 4 + 4 + 4 + 4 + 4))
1744     return FALSE;
1746   fmt->size = gst_asf_demux_get_uint32 (p_data, p_size);
1747   fmt->width = gst_asf_demux_get_uint32 (p_data, p_size);
1748   fmt->height = gst_asf_demux_get_uint32 (p_data, p_size);
1749   fmt->planes = gst_asf_demux_get_uint16 (p_data, p_size);
1750   fmt->depth = gst_asf_demux_get_uint16 (p_data, p_size);
1751   fmt->tag = gst_asf_demux_get_uint32 (p_data, p_size);
1752   fmt->image_size = gst_asf_demux_get_uint32 (p_data, p_size);
1753   fmt->xpels_meter = gst_asf_demux_get_uint32 (p_data, p_size);
1754   fmt->ypels_meter = gst_asf_demux_get_uint32 (p_data, p_size);
1755   fmt->num_colors = gst_asf_demux_get_uint32 (p_data, p_size);
1756   fmt->imp_colors = gst_asf_demux_get_uint32 (p_data, p_size);
1757   return TRUE;
1760 AsfStream *
1761 gst_asf_demux_get_stream (GstASFDemux * demux, guint16 id)
1763   guint i;
1765   for (i = 0; i < demux->num_streams; i++) {
1766     if (demux->stream[i].id == id)
1767       return &demux->stream[i];
1768   }
1770   GST_WARNING ("Segment found for undefined stream: (%d)", id);
1771   return NULL;
1774 static void
1775 gst_asf_demux_setup_pad (GstASFDemux * demux, GstPad * src_pad,
1776     GstCaps * caps, guint16 id, gboolean is_video, GstTagList * tags)
1778   AsfStream *stream;
1780   gst_pad_use_fixed_caps (src_pad);
1781   gst_pad_set_caps (src_pad, caps);
1783   gst_pad_set_event_function (src_pad,
1784       GST_DEBUG_FUNCPTR (gst_asf_demux_handle_src_event));
1785   gst_pad_set_query_type_function (src_pad,
1786       GST_DEBUG_FUNCPTR (gst_asf_demux_get_src_query_types));
1787   gst_pad_set_query_function (src_pad,
1788       GST_DEBUG_FUNCPTR (gst_asf_demux_handle_src_query));
1790   stream = &demux->stream[demux->num_streams];
1791   stream->caps = caps;
1792   stream->pad = src_pad;
1793   stream->id = id;
1794   stream->fps_known = !is_video;        /* bit hacky for audio */
1795   stream->is_video = is_video;
1796   stream->pending_tags = tags;
1797   stream->discont = TRUE;
1798   if (is_video) {
1799     GstStructure *st;
1800     gint par_x, par_y;
1801     st = gst_caps_get_structure (caps, 0);
1802     if (gst_structure_get_fraction (st, "pixel-aspect-ratio", &par_x, &par_y) &&
1803         par_x > 0 && par_y > 0) {
1804       GST_DEBUG ("PAR %d/%d", par_x, par_y);
1805       stream->par_x = par_x;
1806       stream->par_y = par_y;
1807     }
1808   }
1810   stream->payloads = g_array_new (FALSE, FALSE, sizeof (AsfPayload));
1812   GST_INFO ("Created pad %s for stream %u with caps %" GST_PTR_FORMAT,
1813       GST_PAD_NAME (src_pad), demux->num_streams, caps);
1815   ++demux->num_streams;
1817   stream->active = FALSE;
1820 static void
1821 gst_asf_demux_add_audio_stream (GstASFDemux * demux,
1822     asf_stream_audio * audio, guint16 id, guint8 ** p_data, guint64 * p_size)
1824   GstTagList *tags = NULL;
1825   GstBuffer *extradata = NULL;
1826   GstPad *src_pad;
1827   GstCaps *caps;
1828   guint16 size_left = 0;
1829   gchar *codec_name = NULL;
1830   gchar *name = NULL;
1832   size_left = audio->size;
1834   /* Create the audio pad */
1835   name = g_strdup_printf ("audio_%02d", demux->num_audio_streams);
1837   src_pad = gst_pad_new_from_static_template (&audio_src_template, name);
1838   g_free (name);
1840   /* Swallow up any left over data and set up the 
1841    * standard properties from the header info */
1842   if (size_left) {
1843     GST_INFO_OBJECT (demux, "Audio header contains %d bytes of "
1844         "codec specific data", size_left);
1846     g_assert (size_left <= *p_size);
1847     gst_asf_demux_get_buffer (&extradata, size_left, p_data, p_size);
1848   }
1850   /* asf_stream_audio is the same as gst_riff_strf_auds, but with an
1851    * additional two bytes indicating extradata. */
1852   caps = gst_riff_create_audio_caps (audio->codec_tag, NULL,
1853       (gst_riff_strf_auds *) audio, extradata, NULL, &codec_name);
1855   if (caps == NULL) {
1856     caps = gst_caps_new_simple ("audio/x-asf-unknown", "codec_id",
1857         G_TYPE_INT, (gint) audio->codec_tag, NULL);
1858   }
1860   /* Informing about that audio format we just added */
1861   if (codec_name) {
1862     tags = gst_tag_list_new ();
1863     gst_tag_list_add (tags, GST_TAG_MERGE_APPEND, GST_TAG_AUDIO_CODEC,
1864         codec_name, NULL);
1865     g_free (codec_name);
1866   }
1868   if (extradata)
1869     gst_buffer_unref (extradata);
1871   GST_INFO ("Adding audio stream #%u, id %u codec %u (0x%04x), tags=%"
1872       GST_PTR_FORMAT, demux->num_audio_streams, id, audio->codec_tag,
1873       audio->codec_tag, tags);
1875   ++demux->num_audio_streams;
1877   gst_asf_demux_setup_pad (demux, src_pad, caps, id, FALSE, tags);
1880 static void
1881 gst_asf_demux_add_video_stream (GstASFDemux * demux,
1882     asf_stream_video_format * video, guint16 id,
1883     guint8 ** p_data, guint64 * p_size)
1885   GstTagList *tags = NULL;
1886   GstBuffer *extradata = NULL;
1887   GstPad *src_pad;
1888   GstCaps *caps;
1889   gchar *name = NULL;
1890   gchar *codec_name = NULL;
1891   gint size_left = video->size - 40;
1893   /* Create the video pad */
1894   name = g_strdup_printf ("video_%02d", demux->num_video_streams);
1895   src_pad = gst_pad_new_from_static_template (&video_src_template, name);
1896   g_free (name);
1898   /* Now try some gstreamer formatted MIME types (from gst_avi_demux_strf_vids) */
1899   if (size_left) {
1900     GST_LOG ("Video header has %d bytes of codec specific data", size_left);
1901     g_assert (size_left <= *p_size);
1902     gst_asf_demux_get_buffer (&extradata, size_left, p_data, p_size);
1903   }
1905   GST_DEBUG ("video codec %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (video->tag));
1907   /* yes, asf_stream_video_format and gst_riff_strf_vids are the same */
1908   caps = gst_riff_create_video_caps (video->tag, NULL,
1909       (gst_riff_strf_vids *) video, extradata, NULL, &codec_name);
1911   if (caps == NULL) {
1912     caps = gst_caps_new_simple ("video/x-asf-unknown", "fourcc",
1913         GST_TYPE_FOURCC, video->tag, NULL);
1914   } else {
1915     GstStructure *s;
1916     gint ax, ay;
1918     s = gst_asf_demux_get_metadata_for_stream (demux, id);
1919     if (gst_structure_get_int (s, "AspectRatioX", &ax) &&
1920         gst_structure_get_int (s, "AspectRatioY", &ay) && (ax > 0 && ay > 0)) {
1921       gst_caps_set_simple (caps, "pixel-aspect-ratio", GST_TYPE_FRACTION,
1922           ax, ay, NULL);
1924     } else {
1925       guint ax, ay;
1926       /* retry with the global metadata */
1927       GST_DEBUG ("Retrying with global metadata %" GST_PTR_FORMAT,
1928           demux->global_metadata);
1929       s = demux->global_metadata;
1930       if (gst_structure_get_uint (s, "AspectRatioX", &ax) &&
1931           gst_structure_get_uint (s, "AspectRatioY", &ay)) {
1932         GST_DEBUG ("ax:%d, ay:%d", ax, ay);
1933         if (ax > 0 && ay > 0)
1934           gst_caps_set_simple (caps, "pixel-aspect-ratio", GST_TYPE_FRACTION,
1935               ax, ay, NULL);
1936       }
1937     }
1938     s = gst_caps_get_structure (caps, 0);
1939     gst_structure_remove_field (s, "framerate");
1940   }
1942   /* add fourcc format to caps, some proprietary decoders seem to need it */
1943   gst_caps_set_simple (caps, "format", GST_TYPE_FOURCC, video->tag, NULL);
1945   if (codec_name) {
1946     tags = gst_tag_list_new ();
1947     gst_tag_list_add (tags, GST_TAG_MERGE_APPEND, GST_TAG_VIDEO_CODEC,
1948         codec_name, NULL);
1949     g_free (codec_name);
1950   }
1952   if (extradata)
1953     gst_buffer_unref (extradata);
1955   GST_INFO ("Adding video stream #%u, id %u, codec %"
1956       GST_FOURCC_FORMAT " (0x%08x)", demux->num_video_streams, id,
1957       GST_FOURCC_ARGS (video->tag), video->tag);
1959   ++demux->num_video_streams;
1961   gst_asf_demux_setup_pad (demux, src_pad, caps, id, TRUE, tags);
1964 static void
1965 gst_asf_demux_activate_stream (GstASFDemux * demux, AsfStream * stream)
1967   if (!stream->active) {
1968     GST_INFO_OBJECT (demux, "Activating stream %2u, pad %s, caps %"
1969         GST_PTR_FORMAT, stream->id, GST_PAD_NAME (stream->pad), stream->caps);
1970     gst_pad_set_active (stream->pad, TRUE);
1971     gst_element_add_pad (GST_ELEMENT_CAST (demux), stream->pad);
1972     stream->active = TRUE;
1973   }
1976 static AsfStream *
1977 gst_asf_demux_parse_stream_object (GstASFDemux * demux, guint8 * data,
1978     guint64 size)
1980   AsfCorrectionType correction_type;
1981   AsfStreamType stream_type;
1982   GstClockTime time_offset;
1983   gboolean is_encrypted;
1984   guint16 stream_id;
1985   guint16 flags;
1986   ASFGuid guid;
1987   guint stream_specific_size;
1988   guint type_specific_size;
1989   guint unknown;
1991   /* Get the rest of the header's header */
1992   if (size < (16 + 16 + 8 + 4 + 4 + 2 + 4))
1993     goto not_enough_data;
1995   gst_asf_demux_get_guid (&guid, &data, &size);
1996   stream_type = gst_asf_demux_identify_guid (asf_stream_guids, &guid);
1998   gst_asf_demux_get_guid (&guid, &data, &size);
1999   correction_type = gst_asf_demux_identify_guid (asf_correction_guids, &guid);
2001   time_offset = gst_asf_demux_get_uint64 (&data, &size) * 100;
2003   type_specific_size = gst_asf_demux_get_uint32 (&data, &size);
2004   stream_specific_size = gst_asf_demux_get_uint32 (&data, &size);
2006   flags = gst_asf_demux_get_uint16 (&data, &size);
2007   stream_id = flags & 0x7f;
2008   is_encrypted = !!((flags & 0x8000) << 15);
2009   unknown = gst_asf_demux_get_uint32 (&data, &size);
2011   GST_DEBUG_OBJECT (demux, "Found stream %u, time_offset=%" GST_TIME_FORMAT,
2012       stream_id, GST_TIME_ARGS (time_offset));
2014   switch (stream_type) {
2015     case ASF_STREAM_AUDIO:{
2016       asf_stream_audio audio_object;
2018       if (!gst_asf_demux_get_stream_audio (&audio_object, &data, &size))
2019         goto not_enough_data;
2021       GST_INFO ("Object is an audio stream with %u bytes of additional data",
2022           audio_object.size);
2024       gst_asf_demux_add_audio_stream (demux, &audio_object, stream_id,
2025           &data, &size);
2027       switch (correction_type) {
2028         case ASF_CORRECTION_ON:{
2029           guint span, packet_size, chunk_size, data_size, silence_data;
2031           GST_INFO ("Using error correction");
2033           if (size < (1 + 2 + 2 + 2 + 1))
2034             goto not_enough_data;
2036           span = gst_asf_demux_get_uint8 (&data, &size);
2037           packet_size = gst_asf_demux_get_uint16 (&data, &size);
2038           chunk_size = gst_asf_demux_get_uint16 (&data, &size);
2039           data_size = gst_asf_demux_get_uint16 (&data, &size);
2040           silence_data = gst_asf_demux_get_uint8 (&data, &size);
2042           /* FIXME: shouldn't this be per-stream? */
2043           demux->span = span;
2045           GST_DEBUG_OBJECT (demux, "Descrambling ps:%u cs:%u ds:%u s:%u sd:%u",
2046               packet_size, chunk_size, data_size, span, silence_data);
2048           if (demux->span > 1) {
2049             if (chunk_size == 0 || ((packet_size / chunk_size) <= 1)) {
2050               /* Disable descrambling */
2051               demux->span = 0;
2052             } else {
2053               /* FIXME: this else branch was added for
2054                * weird_al_yankovic - the saga begins.asf */
2055               demux->ds_packet_size = packet_size;
2056               demux->ds_chunk_size = chunk_size;
2057             }
2058           } else {
2059             /* Descambling is enabled */
2060             demux->ds_packet_size = packet_size;
2061             demux->ds_chunk_size = chunk_size;
2062           }
2063 #if 0
2064           /* Now skip the rest of the silence data */
2065           if (data_size > 1)
2066             gst_bytestream_flush (demux->bs, data_size - 1);
2067 #else
2068           /* FIXME: CHECKME. And why -1? */
2069           if (data_size > 1) {
2070             if (!gst_asf_demux_skip_bytes (data_size - 1, &data, &size)) {
2071               goto not_enough_data;
2072             }
2073           }
2074 #endif
2075           break;
2076         }
2077         case ASF_CORRECTION_OFF:{
2078           GST_INFO ("Error correction off");
2079           if (!gst_asf_demux_skip_bytes (stream_specific_size, &data, &size))
2080             goto not_enough_data;
2081           break;
2082         }
2083         default:
2084           GST_ELEMENT_ERROR (demux, STREAM, DEMUX, (NULL),
2085               ("Audio stream using unknown error correction"));
2086           return NULL;
2087       }
2089       break;
2090     }
2092     case ASF_STREAM_VIDEO:{
2093       asf_stream_video_format video_format_object;
2094       asf_stream_video video_object;
2095       guint16 vsize;
2097       if (!gst_asf_demux_get_stream_video (&video_object, &data, &size))
2098         goto not_enough_data;
2100       vsize = video_object.size - 40;   /* Byte order gets offset by single byte */
2102       GST_INFO ("object is a video stream with %u bytes of "
2103           "additional data", vsize);
2105       if (!gst_asf_demux_get_stream_video_format (&video_format_object,
2106               &data, &size)) {
2107         goto not_enough_data;
2108       }
2110       gst_asf_demux_add_video_stream (demux, &video_format_object, stream_id,
2111           &data, &size);
2113       break;
2114     }
2116     default:
2117       GST_WARNING_OBJECT (demux, "Unknown stream type for stream %u",
2118           stream_id);
2119       break;
2120   }
2122   return gst_asf_demux_get_stream (demux, stream_id);
2124 not_enough_data:
2125   {
2126     GST_WARNING_OBJECT (demux, "Unexpected end of data parsing stream object");
2127     /* we'll error out later if we found no streams */
2128     return NULL;
2129   }
2132 static const gchar *
2133 gst_asf_demux_get_gst_tag_from_tag_name (const gchar * name_utf8)
2135   const struct
2136   {
2137     const gchar *asf_name;
2138     const gchar *gst_name;
2139   } tags[] = {
2140     {
2141     "WM/Genre", GST_TAG_GENRE}, {
2142     "WM/AlbumTitle", GST_TAG_ALBUM}, {
2143     "WM/AlbumArtist", GST_TAG_ARTIST}, {
2144     "WM/Picture", GST_TAG_IMAGE}, {
2145     "WM/Track", GST_TAG_TRACK_NUMBER}, {
2146     "WM/Year", GST_TAG_DATE}
2147     /* { "WM/Composer", GST_TAG_COMPOSER } */
2148   };
2149   gsize out = strlen (name_utf8);
2150   guint i;
2152   if (name_utf8 == NULL) {
2153     GST_WARNING ("Failed to convert name to UTF8, skipping");
2154     return NULL;
2155   }
2157   for (i = 0; i < G_N_ELEMENTS (tags); ++i) {
2158     if (strncmp (tags[i].asf_name, name_utf8, out) == 0) {
2159       GST_LOG ("map tagname '%s' -> '%s'", name_utf8, tags[i].gst_name);
2160       return tags[i].gst_name;
2161     }
2162   }
2164   return NULL;
2167 /* gst_asf_demux_add_global_tags() takes ownership of taglist! */
2168 static void
2169 gst_asf_demux_add_global_tags (GstASFDemux * demux, GstTagList * taglist)
2171   GstTagList *t;
2173   GST_DEBUG_OBJECT (demux, "adding global tags: %" GST_PTR_FORMAT, taglist);
2175   if (taglist == NULL)
2176     return;
2178   if (gst_tag_list_is_empty (taglist)) {
2179     gst_tag_list_free (taglist);
2180     return;
2181   }
2183   t = gst_tag_list_merge (demux->taglist, taglist, GST_TAG_MERGE_APPEND);
2184   if (demux->taglist)
2185     gst_tag_list_free (demux->taglist);
2186   gst_tag_list_free (taglist);
2187   demux->taglist = t;
2188   GST_LOG_OBJECT (demux, "global tags now: %" GST_PTR_FORMAT, demux->taglist);
2191 #define ASF_DEMUX_DATA_TYPE_UTF16LE_STRING  0
2192 #define ASF_DEMUX_DATA_TYPE_BYTE_ARRAY      1
2193 #define ASF_DEMUX_DATA_TYPE_DWORD           3
2195 static void
2196 asf_demux_parse_picture_tag (GstTagList * tags, const guint8 * tag_data,
2197     guint tag_data_len)
2199   GstByteReader r;
2200   const guint8 *img_data;
2201   guint32 img_data_len;
2202   guint8 pic_type;
2204   gst_byte_reader_init (&r, tag_data, tag_data_len);
2206   /* skip mime type string (we don't trust it and do our own typefinding),
2207    * and also skip the description string, since we don't use it */
2208   if (!gst_byte_reader_get_uint8 (&r, &pic_type) ||
2209       !gst_byte_reader_get_uint32_le (&r, &img_data_len) ||
2210       !gst_byte_reader_skip_string_utf16 (&r) ||
2211       !gst_byte_reader_skip_string_utf16 (&r) ||
2212       !gst_byte_reader_get_data (&r, img_data_len, &img_data)) {
2213     goto not_enough_data;
2214   }
2217   if (!gst_tag_list_add_id3_image (tags, img_data, img_data_len, pic_type))
2218     GST_DEBUG ("failed to add image extracted from WM/Picture tag to taglist");
2220   return;
2222 not_enough_data:
2223   {
2224     GST_DEBUG ("Failed to read WM/Picture tag: not enough data");
2225     GST_MEMDUMP ("WM/Picture data", tag_data, tag_data_len);
2226     return;
2227   }
2230 /* Extended Content Description Object */
2231 static GstFlowReturn
2232 gst_asf_demux_process_ext_content_desc (GstASFDemux * demux, guint8 * data,
2233     guint64 size)
2235   /* Other known (and unused) 'text/unicode' metadata available :
2236    *
2237    *   WM/Lyrics =
2238    *   WM/MediaPrimaryClassID = {D1607DBC-E323-4BE2-86A1-48A42A28441E}
2239    *   WMFSDKVersion = 9.00.00.2980
2240    *   WMFSDKNeeded = 0.0.0.0000
2241    *   WM/UniqueFileIdentifier = AMGa_id=R    15334;AMGp_id=P     5149;AMGt_id=T  2324984
2242    *   WM/Publisher = 4AD
2243    *   WM/Provider = AMG
2244    *   WM/ProviderRating = 8
2245    *   WM/ProviderStyle = Rock (similar to WM/Genre)
2246    *   WM/GenreID (similar to WM/Genre)
2247    *   WM/TrackNumber (same as WM/Track but as a string)
2248    *
2249    * Other known (and unused) 'non-text' metadata available :
2250    *
2251    *   WM/EncodingTime
2252    *   WM/MCDI
2253    *   IsVBR
2254    *
2255    * We might want to read WM/TrackNumber and use atoi() if we don't have
2256    * WM/Track
2257    */
2259   GstTagList *taglist;
2260   guint16 blockcount, i;
2262   GST_INFO_OBJECT (demux, "object is an extended content description");
2264   taglist = gst_tag_list_new ();
2266   /* Content Descriptor Count */
2267   if (size < 2)
2268     goto not_enough_data;
2270   blockcount = gst_asf_demux_get_uint16 (&data, &size);
2272   for (i = 1; i <= blockcount; ++i) {
2273     const gchar *gst_tag_name;
2274     guint16 datatype;
2275     guint16 value_len;
2276     guint16 name_len;
2277     GValue tag_value = { 0, };
2278     gsize in, out;
2279     gchar *name;
2280     gchar *name_utf8 = NULL;
2281     gchar *value;
2283     /* Descriptor */
2284     if (!gst_asf_demux_get_string (&name, &name_len, &data, &size))
2285       goto not_enough_data;
2287     if (size < 2) {
2288       g_free (name);
2289       goto not_enough_data;
2290     }
2291     /* Descriptor Value Data Type */
2292     datatype = gst_asf_demux_get_uint16 (&data, &size);
2294     /* Descriptor Value (not really a string, but same thing reading-wise) */
2295     if (!gst_asf_demux_get_string (&value, &value_len, &data, &size)) {
2296       g_free (name);
2297       goto not_enough_data;
2298     }
2300     name_utf8 =
2301         g_convert (name, name_len, "UTF-8", "UTF-16LE", &in, &out, NULL);
2303     GST_DEBUG ("Found tag/metadata %s", name_utf8);
2305     gst_tag_name = gst_asf_demux_get_gst_tag_from_tag_name (name_utf8);
2307     GST_DEBUG ("gst_tag_name %s", gst_tag_name);
2309     if (name_utf8 != NULL) {
2310       switch (datatype) {
2311         case ASF_DEMUX_DATA_TYPE_UTF16LE_STRING:{
2312           gchar *value_utf8;
2314           value_utf8 = g_convert (value, value_len, "UTF-8", "UTF-16LE",
2315               &in, &out, NULL);
2317           GST_DEBUG ("string value %s", value_utf8);
2319           /* get rid of tags with empty value */
2320           if (value_utf8 != NULL && *value_utf8 != '\0') {
2321             value_utf8[out] = '\0';
2323             if (gst_tag_name != NULL) {
2324               if (strcmp (gst_tag_name, GST_TAG_DATE) == 0) {
2325                 guint year = atoi (value_utf8);
2327                 if (year > 0) {
2328                   GDate *date = g_date_new_dmy (1, 1, year);
2330                   g_value_init (&tag_value, GST_TYPE_DATE);
2331                   gst_value_set_date (&tag_value, date);
2332                   g_date_free (date);
2333                 }
2334               } else if (strcmp (gst_tag_name, GST_TAG_GENRE) == 0) {
2335                 guint id3v1_genre_id;
2336                 const gchar *genre_str;
2338                 if (sscanf (value_utf8, "(%u)", &id3v1_genre_id) == 1 &&
2339                     ((genre_str = gst_tag_id3_genre_get (id3v1_genre_id)))) {
2340                   GST_DEBUG ("Genre: %s -> %s", value_utf8, genre_str);
2341                   g_free (value_utf8);
2342                   value_utf8 = g_strdup (genre_str);
2343                 }
2344               } else {
2345                 GType tag_type;
2347                 /* convert tag from string to other type if required */
2348                 tag_type = gst_tag_get_type (gst_tag_name);
2349                 g_value_init (&tag_value, tag_type);
2350                 if (!gst_value_deserialize (&tag_value, value_utf8)) {
2351                   GValue from_val = { 0, };
2353                   g_value_init (&from_val, G_TYPE_STRING);
2354                   g_value_set_string (&from_val, value_utf8);
2355                   if (!g_value_transform (&from_val, &tag_value)) {
2356                     GST_WARNING_OBJECT (demux,
2357                         "Could not transform string tag to " "%s tag type %s",
2358                         gst_tag_name, g_type_name (tag_type));
2359                     g_value_unset (&tag_value);
2360                   }
2361                   g_value_unset (&from_val);
2362                 }
2363               }
2364             } else {
2365               /* metadata ! */
2366               GST_DEBUG ("Setting metadata");
2367               g_value_init (&tag_value, G_TYPE_STRING);
2368               g_value_set_string (&tag_value, value_utf8);
2369             }
2370           } else if (value_utf8 == NULL) {
2371             GST_WARNING ("Failed to convert string value to UTF8, skipping");
2372           } else {
2373             GST_DEBUG ("Skipping empty string value for %s", gst_tag_name);
2374           }
2375           g_free (value_utf8);
2376           break;
2377         }
2378         case ASF_DEMUX_DATA_TYPE_BYTE_ARRAY:{
2379           if (gst_tag_name) {
2380             if (!g_str_equal (gst_tag_name, GST_TAG_IMAGE)) {
2381               GST_FIXME ("Unhandled byte array tag %s", gst_tag_name);
2382               break;
2383             } else {
2384               asf_demux_parse_picture_tag (taglist, (guint8 *) value,
2385                   value_len);
2386             }
2387           }
2388           break;
2389         }
2390         case ASF_DEMUX_DATA_TYPE_DWORD:{
2391           /* this is the track number */
2392           g_value_init (&tag_value, G_TYPE_UINT);
2393           g_value_set_uint (&tag_value, (guint) GST_READ_UINT32_LE (value));
2394           break;
2395         }
2396         default:{
2397           GST_DEBUG ("Skipping tag %s of type %d", gst_tag_name, datatype);
2398           break;
2399         }
2400       }
2402       if (G_IS_VALUE (&tag_value)) {
2403         if (gst_tag_name) {
2404           gst_tag_list_add_values (taglist, GST_TAG_MERGE_APPEND,
2405               gst_tag_name, &tag_value, NULL);
2407           g_value_unset (&tag_value);
2408         } else {
2409           GST_DEBUG ("Setting global metadata %s", name_utf8);
2410           gst_structure_set_value (demux->global_metadata, name_utf8,
2411               &tag_value);
2412         }
2413       }
2414     }
2416     g_free (name);
2417     g_free (value);
2418   }
2420   gst_asf_demux_add_global_tags (demux, taglist);
2422   return GST_FLOW_OK;
2424   /* Errors */
2425 not_enough_data:
2426   {
2427     GST_WARNING ("Unexpected end of data parsing ext content desc object");
2428     gst_tag_list_free (taglist);
2429     return GST_FLOW_OK;         /* not really fatal */
2430   }
2433 static GstStructure *
2434 gst_asf_demux_get_metadata_for_stream (GstASFDemux * demux, guint stream_num)
2436   gchar sname[32];
2437   guint i;
2439   g_snprintf (sname, sizeof (sname), "stream-%u", stream_num);
2441   for (i = 0; i < gst_caps_get_size (demux->metadata); ++i) {
2442     GstStructure *s;
2444     s = gst_caps_get_structure (demux->metadata, i);
2445     if (gst_structure_has_name (s, sname))
2446       return s;
2447   }
2449   gst_caps_append_structure (demux->metadata, gst_structure_empty_new (sname));
2451   /* try lookup again; demux->metadata took ownership of the structure, so we
2452    * can't really make any assumptions about what happened to it, so we can't
2453    * just return it directly after appending it */
2454   return gst_asf_demux_get_metadata_for_stream (demux, stream_num);
2457 static GstFlowReturn
2458 gst_asf_demux_process_metadata (GstASFDemux * demux, guint8 * data,
2459     guint64 size)
2461   guint16 blockcount, i;
2463   GST_INFO_OBJECT (demux, "object is a metadata object");
2465   /* Content Descriptor Count */
2466   if (size < 2)
2467     goto not_enough_data;
2469   blockcount = gst_asf_demux_get_uint16 (&data, &size);
2471   for (i = 0; i < blockcount; ++i) {
2472     GstStructure *s;
2473     guint16 lang_idx, stream_num, name_len, data_type;
2474     guint32 data_len, ival;
2475     gchar *name_utf8;
2477     if (size < (2 + 2 + 2 + 2 + 4))
2478       goto not_enough_data;
2480     lang_idx = gst_asf_demux_get_uint16 (&data, &size);
2481     stream_num = gst_asf_demux_get_uint16 (&data, &size);
2482     name_len = gst_asf_demux_get_uint16 (&data, &size);
2483     data_type = gst_asf_demux_get_uint16 (&data, &size);
2484     data_len = gst_asf_demux_get_uint32 (&data, &size);
2486     if (size < name_len + data_len)
2487       goto not_enough_data;
2489     /* convert name to UTF-8 */
2490     name_utf8 = g_convert ((gchar *) data, name_len, "UTF-8", "UTF-16LE",
2491         NULL, NULL, NULL);
2492     gst_asf_demux_skip_bytes (name_len, &data, &size);
2494     if (name_utf8 == NULL) {
2495       GST_WARNING ("Failed to convert value name to UTF8, skipping");
2496       gst_asf_demux_skip_bytes (data_len, &data, &size);
2497       continue;
2498     }
2500     if (data_type != ASF_DEMUX_DATA_TYPE_DWORD) {
2501       gst_asf_demux_skip_bytes (data_len, &data, &size);
2502       g_free (name_utf8);
2503       continue;
2504     }
2506     /* read DWORD */
2507     if (size < 4) {
2508       g_free (name_utf8);
2509       goto not_enough_data;
2510     }
2512     ival = gst_asf_demux_get_uint32 (&data, &size);
2514     /* skip anything else there may be, just in case */
2515     gst_asf_demux_skip_bytes (data_len - 4, &data, &size);
2517     s = gst_asf_demux_get_metadata_for_stream (demux, stream_num);
2518     gst_structure_set (s, name_utf8, G_TYPE_INT, ival, NULL);
2519     g_free (name_utf8);
2520   }
2522   GST_INFO_OBJECT (demux, "metadata = %" GST_PTR_FORMAT, demux->metadata);
2523   return GST_FLOW_OK;
2525   /* Errors */
2526 not_enough_data:
2527   {
2528     GST_WARNING ("Unexpected end of data parsing metadata object");
2529     return GST_FLOW_OK;         /* not really fatal */
2530   }
2533 static GstFlowReturn
2534 gst_asf_demux_process_header (GstASFDemux * demux, guint8 * data, guint64 size)
2536   GstFlowReturn ret = GST_FLOW_OK;
2537   guint32 i, num_objects;
2538   guint8 unknown;
2540   /* Get the rest of the header's header */
2541   if (size < (4 + 1 + 1))
2542     goto not_enough_data;
2544   num_objects = gst_asf_demux_get_uint32 (&data, &size);
2545   unknown = gst_asf_demux_get_uint8 (&data, &size);
2546   unknown = gst_asf_demux_get_uint8 (&data, &size);
2548   GST_INFO_OBJECT (demux, "object is a header with %u parts", num_objects);
2550   /* Loop through the header's objects, processing those */
2551   for (i = 0; i < num_objects; ++i) {
2552     GST_INFO_OBJECT (demux, "reading header part %u", i);
2553     ret = gst_asf_demux_process_object (demux, &data, &size);
2554     if (ret != GST_FLOW_OK) {
2555       GST_WARNING ("process_object returned %s", gst_asf_get_flow_name (ret));
2556       break;
2557     }
2558   }
2560   return ret;
2562 not_enough_data:
2563   {
2564     GST_ELEMENT_ERROR (demux, STREAM, DEMUX, (NULL),
2565         ("short read parsing HEADER object"));
2566     return GST_FLOW_ERROR;
2567   }
2570 static GstFlowReturn
2571 gst_asf_demux_process_file (GstASFDemux * demux, guint8 * data, guint64 size)
2573   guint64 file_size, creation_time, packets_count;
2574   guint64 play_time, send_time, preroll;
2575   guint32 flags, min_pktsize, max_pktsize, min_bitrate;
2577   if (size < (16 + 8 + 8 + 8 + 8 + 8 + 8 + 4 + 4 + 4 + 4))
2578     goto not_enough_data;
2580   gst_asf_demux_skip_bytes (16, &data, &size);  /* skip GUID */
2581   file_size = gst_asf_demux_get_uint64 (&data, &size);
2582   creation_time = gst_asf_demux_get_uint64 (&data, &size);
2583   packets_count = gst_asf_demux_get_uint64 (&data, &size);
2584   play_time = gst_asf_demux_get_uint64 (&data, &size);
2585   send_time = gst_asf_demux_get_uint64 (&data, &size);
2586   preroll = gst_asf_demux_get_uint64 (&data, &size);
2587   flags = gst_asf_demux_get_uint32 (&data, &size);
2588   min_pktsize = gst_asf_demux_get_uint32 (&data, &size);
2589   max_pktsize = gst_asf_demux_get_uint32 (&data, &size);
2590   min_bitrate = gst_asf_demux_get_uint32 (&data, &size);
2592   demux->broadcast = !!(flags & 0x01);
2593   demux->seekable = !!(flags & 0x02);
2595   GST_DEBUG_OBJECT (demux, "min_pktsize = %u", min_pktsize);
2596   GST_DEBUG_OBJECT (demux, "flags::broadcast = %d", demux->broadcast);
2597   GST_DEBUG_OBJECT (demux, "flags::seekable  = %d", demux->seekable);
2599   if (demux->broadcast) {
2600     /* these fields are invalid if the broadcast flag is set */
2601     play_time = 0;
2602     file_size = 0;
2603   }
2605   if (min_pktsize != max_pktsize)
2606     goto non_fixed_packet_size;
2608   demux->packet_size = max_pktsize;
2610   /* FIXME: do we need send_time as well? what is it? */
2611   if ((play_time * 100) >= (preroll * GST_MSECOND))
2612     demux->play_time = (play_time * 100) - (preroll * GST_MSECOND);
2613   else
2614     demux->play_time = 0;
2616   demux->preroll = preroll * GST_MSECOND;
2618   /* initial latency */
2619   demux->latency = demux->preroll;
2621   if (demux->play_time == 0)
2622     demux->seekable = FALSE;
2624   GST_DEBUG_OBJECT (demux, "play_time %" GST_TIME_FORMAT,
2625       GST_TIME_ARGS (demux->play_time));
2626   GST_DEBUG_OBJECT (demux, "preroll   %" GST_TIME_FORMAT,
2627       GST_TIME_ARGS (demux->preroll));
2629   if (demux->play_time > 0) {
2630     gst_segment_set_duration (&demux->segment, GST_FORMAT_TIME,
2631         demux->play_time);
2632   }
2634   GST_INFO ("object is a file with %" G_GUINT64_FORMAT " data packets",
2635       packets_count);
2636   GST_INFO ("preroll = %" G_GUINT64_FORMAT, demux->preroll);
2638   return GST_FLOW_OK;
2640 /* ERRORS */
2641 non_fixed_packet_size:
2642   {
2643     GST_ELEMENT_ERROR (demux, STREAM, DEMUX, (NULL),
2644         ("packet size must be fixed"));
2645     return GST_FLOW_ERROR;
2646   }
2647 not_enough_data:
2648   {
2649     GST_ELEMENT_ERROR (demux, STREAM, DEMUX, (NULL),
2650         ("short read parsing FILE object"));
2651     return GST_FLOW_ERROR;
2652   }
2655 /* Content Description Object */
2656 static GstFlowReturn
2657 gst_asf_demux_process_comment (GstASFDemux * demux, guint8 * data, guint64 size)
2659   struct
2660   {
2661     const gchar *gst_tag;
2662     guint16 val_length;
2663     gchar *val_utf8;
2664   } tags[5] = {
2665     {
2666     GST_TAG_TITLE, 0, NULL}, {
2667     GST_TAG_ARTIST, 0, NULL}, {
2668     GST_TAG_COPYRIGHT, 0, NULL}, {
2669     GST_TAG_DESCRIPTION, 0, NULL}, {
2670     GST_TAG_COMMENT, 0, NULL}
2671   };
2672   GstTagList *taglist;
2673   GValue value = { 0 };
2674   gsize in, out;
2675   gint i = -1;
2677   GST_INFO_OBJECT (demux, "object is a comment");
2679   if (size < (2 + 2 + 2 + 2 + 2))
2680     goto not_enough_data;
2682   tags[0].val_length = gst_asf_demux_get_uint16 (&data, &size);
2683   tags[1].val_length = gst_asf_demux_get_uint16 (&data, &size);
2684   tags[2].val_length = gst_asf_demux_get_uint16 (&data, &size);
2685   tags[3].val_length = gst_asf_demux_get_uint16 (&data, &size);
2686   tags[4].val_length = gst_asf_demux_get_uint16 (&data, &size);
2688   GST_DEBUG_OBJECT (demux, "Comment lengths: title=%d author=%d copyright=%d "
2689       "description=%d rating=%d", tags[0].val_length, tags[1].val_length,
2690       tags[2].val_length, tags[3].val_length, tags[4].val_length);
2692   for (i = 0; i < G_N_ELEMENTS (tags); ++i) {
2693     if (size < tags[i].val_length)
2694       goto not_enough_data;
2696     /* might be just '/0', '/0'... */
2697     if (tags[i].val_length > 2 && tags[i].val_length % 2 == 0) {
2698       /* convert to UTF-8 */
2699       tags[i].val_utf8 = g_convert ((gchar *) data, tags[i].val_length,
2700           "UTF-8", "UTF-16LE", &in, &out, NULL);
2701     }
2702     gst_asf_demux_skip_bytes (tags[i].val_length, &data, &size);
2703   }
2705   /* parse metadata into taglist */
2706   taglist = gst_tag_list_new ();
2707   g_value_init (&value, G_TYPE_STRING);
2708   for (i = 0; i < G_N_ELEMENTS (tags); ++i) {
2709     if (tags[i].val_utf8 && strlen (tags[i].val_utf8) > 0 && tags[i].gst_tag) {
2710       g_value_set_string (&value, tags[i].val_utf8);
2711       gst_tag_list_add_values (taglist, GST_TAG_MERGE_APPEND,
2712           tags[i].gst_tag, &value, NULL);
2713     }
2714   }
2715   g_value_unset (&value);
2717   gst_asf_demux_add_global_tags (demux, taglist);
2719   for (i = 0; i < G_N_ELEMENTS (tags); ++i)
2720     g_free (tags[i].val_utf8);
2722   return GST_FLOW_OK;
2724 not_enough_data:
2725   {
2726     GST_WARNING_OBJECT (demux, "unexpectedly short of data while processing "
2727         "comment tag section %d, skipping comment object", i);
2728     for (i = 0; i < G_N_ELEMENTS (tags); i++)
2729       g_free (tags[i].val_utf8);
2730     return GST_FLOW_OK;         /* not really fatal */
2731   }
2734 static GstFlowReturn
2735 gst_asf_demux_process_bitrate_props_object (GstASFDemux * demux, guint8 * data,
2736     guint64 size)
2738   guint16 num_streams, i;
2740   if (size < 2)
2741     goto not_enough_data;
2743   num_streams = gst_asf_demux_get_uint16 (&data, &size);
2745   GST_INFO ("object is a bitrate properties object with %u streams",
2746       num_streams);
2748   if (size < (num_streams * (2 + 4)))
2749     goto not_enough_data;
2751   for (i = 0; i < num_streams; ++i) {
2752     guint32 bitrate;
2753     guint16 stream_id;
2755     stream_id = gst_asf_demux_get_uint16 (&data, &size);
2756     bitrate = gst_asf_demux_get_uint32 (&data, &size);
2758     if (stream_id < GST_ASF_DEMUX_NUM_STREAM_IDS) {
2759       demux->bitrate[stream_id] = bitrate;
2760       GST_DEBUG ("bitrate[%u] = %u", stream_id, bitrate);
2761     } else {
2762       GST_WARNING ("stream id %u is too large", stream_id);
2763     }
2764   }
2766   return GST_FLOW_OK;
2768 not_enough_data:
2769   {
2770     GST_WARNING_OBJECT (demux, "short read parsing bitrate props object!");
2771     return GST_FLOW_OK;         /* not really fatal */
2772   }
2775 static GstFlowReturn
2776 gst_asf_demux_process_header_ext (GstASFDemux * demux, guint8 * data,
2777     guint64 size)
2779   GstFlowReturn ret = GST_FLOW_OK;
2780   guint64 hdr_size;
2782   /* Get the rest of the header's header */
2783   if (size < (16 + 2 + 4))
2784     goto not_enough_data;
2786   /* skip GUID and two other bytes */
2787   gst_asf_demux_skip_bytes (16 + 2, &data, &size);
2788   hdr_size = gst_asf_demux_get_uint32 (&data, &size);
2790   GST_INFO ("extended header object with a size of %u bytes", (guint) size);
2792   /* FIXME: does data_size include the rest of the header that we have read? */
2793   if (hdr_size > size)
2794     goto not_enough_data;
2796   while (hdr_size > 0) {
2797     ret = gst_asf_demux_process_object (demux, &data, &hdr_size);
2798     if (ret != GST_FLOW_OK)
2799       break;
2800   }
2802   return ret;
2804 not_enough_data:
2805   {
2806     GST_ELEMENT_ERROR (demux, STREAM, DEMUX, (NULL),
2807         ("short read parsing extended header object"));
2808     return GST_FLOW_ERROR;
2809   }
2812 static GstFlowReturn
2813 gst_asf_demux_process_language_list (GstASFDemux * demux, guint8 * data,
2814     guint64 size)
2816   guint i;
2818   if (size < 2)
2819     goto not_enough_data;
2821   if (demux->languages) {
2822     GST_WARNING ("More than one LANGUAGE_LIST object in stream");
2823     g_strfreev (demux->languages);
2824     demux->languages = NULL;
2825     demux->num_languages = 0;
2826   }
2828   demux->num_languages = gst_asf_demux_get_uint16 (&data, &size);
2829   GST_LOG ("%u languages:", demux->num_languages);
2831   demux->languages = g_new0 (gchar *, demux->num_languages + 1);
2832   for (i = 0; i < demux->num_languages; ++i) {
2833     guint8 len, *lang_data = NULL;
2835     if (size < 1)
2836       goto not_enough_data;
2837     len = gst_asf_demux_get_uint8 (&data, &size);
2838     if (gst_asf_demux_get_bytes (&lang_data, len, &data, &size)) {
2839       gchar *utf8;
2841       utf8 = g_convert ((gchar *) lang_data, len, "UTF-8", "UTF-16LE", NULL,
2842           NULL, NULL);
2844       /* truncate "en-us" etc. to just "en" */
2845       if (utf8 && strlen (utf8) >= 5 && (utf8[2] == '-' || utf8[2] == '_')) {
2846         utf8[2] = '\0';
2847       }
2848       GST_DEBUG ("[%u] %s", i, GST_STR_NULL (utf8));
2849       demux->languages[i] = utf8;
2850       g_free (lang_data);
2851     } else {
2852       goto not_enough_data;
2853     }
2854   }
2856   return GST_FLOW_OK;
2858 not_enough_data:
2859   {
2860     GST_WARNING_OBJECT (demux, "short read parsing language list object!");
2861     g_free (demux->languages);
2862     demux->languages = NULL;
2863     return GST_FLOW_OK;         /* not fatal */
2864   }
2867 static GstFlowReturn
2868 gst_asf_demux_process_simple_index (GstASFDemux * demux, guint8 * data,
2869     guint64 size)
2871   GstClockTime interval;
2872   guint32 x, count, i;
2874   if (size < (16 + 8 + 4 + 4))
2875     goto not_enough_data;
2877   /* skip file id */
2878   gst_asf_demux_skip_bytes (16, &data, &size);
2879   interval = gst_asf_demux_get_uint64 (&data, &size) * (GstClockTime) 100;
2880   x = gst_asf_demux_get_uint32 (&data, &size);
2881   count = gst_asf_demux_get_uint32 (&data, &size);
2882   if (count > 0) {
2883     demux->sidx_interval = interval;
2884     demux->sidx_num_entries = count;
2885     g_free (demux->sidx_entries);
2886     demux->sidx_entries = g_new0 (guint32, count);
2888     for (i = 0; i < count && size > (4 + 2); ++i) {
2889       demux->sidx_entries[i] = gst_asf_demux_get_uint32 (&data, &size);
2890       x = (guint32) gst_asf_demux_get_uint16 (&data, &size);
2891       GST_LOG_OBJECT (demux, "%" GST_TIME_FORMAT " = packet %4u",
2892           GST_TIME_ARGS (i * interval), demux->sidx_entries[i]);
2893     }
2894   } else {
2895     GST_DEBUG_OBJECT (demux, "simple index object with 0 entries");
2896   }
2898   return GST_FLOW_OK;
2900 not_enough_data:
2901   {
2902     GST_WARNING_OBJECT (demux, "short read parsing simple index object!");
2903     return GST_FLOW_OK;         /* not fatal */
2904   }
2907 static GstFlowReturn
2908 gst_asf_demux_process_advanced_mutual_exclusion (GstASFDemux * demux,
2909     guint8 * data, guint64 size)
2911   ASFGuid guid;
2912   guint16 num, i;
2913   guint8 *mes;
2915   if (size < 16 + 2 + (2 * 2))
2916     goto not_enough_data;
2918   gst_asf_demux_get_guid (&guid, &data, &size);
2919   num = gst_asf_demux_get_uint16 (&data, &size);
2921   if (num < 2) {
2922     GST_WARNING_OBJECT (demux, "nonsensical mutually exclusive streams count");
2923     return GST_FLOW_OK;
2924   }
2926   if (size < (num * sizeof (guint16)))
2927     goto not_enough_data;
2929   /* read mutually exclusive stream numbers */
2930   mes = g_new (guint8, num + 1);
2931   for (i = 0; i < num; ++i) {
2932     mes[i] = gst_asf_demux_get_uint16 (&data, &size) & 0x7f;
2933     GST_LOG_OBJECT (demux, "mutually exclusive: stream #%d", mes[i]);
2934   }
2936   /* add terminator so we can easily get the count or know when to stop */
2937   mes[i] = (guint8) - 1;
2939   demux->mut_ex_streams = g_slist_append (demux->mut_ex_streams, mes);
2941   return GST_FLOW_OK;
2943   /* Errors */
2944 not_enough_data:
2945   {
2946     GST_WARNING_OBJECT (demux, "short read parsing advanced mutual exclusion");
2947     return GST_FLOW_OK;         /* not absolutely fatal */
2948   }
2951 static GstFlowReturn
2952 gst_asf_demux_process_ext_stream_props (GstASFDemux * demux, guint8 * data,
2953     guint64 size)
2955   AsfStreamExtProps esp;
2956   AsfStream *stream = NULL;
2957   AsfObject stream_obj;
2958   guint16 stream_name_count;
2959   guint16 num_payload_ext;
2960   guint64 len;
2961   guint8 *stream_obj_data = NULL;
2962   guint8 *data_start;
2963   guint obj_size;
2964   guint i, stream_num;
2966   data_start = data;
2967   obj_size = (guint) size;
2969   if (size < 64)
2970     goto not_enough_data;
2972   esp.valid = TRUE;
2973   esp.start_time = gst_asf_demux_get_uint64 (&data, &size) * GST_MSECOND;
2974   esp.end_time = gst_asf_demux_get_uint64 (&data, &size) * GST_MSECOND;
2975   esp.data_bitrate = gst_asf_demux_get_uint32 (&data, &size);
2976   esp.buffer_size = gst_asf_demux_get_uint32 (&data, &size);
2977   esp.intial_buf_fullness = gst_asf_demux_get_uint32 (&data, &size);
2978   esp.data_bitrate2 = gst_asf_demux_get_uint32 (&data, &size);
2979   esp.buffer_size2 = gst_asf_demux_get_uint32 (&data, &size);
2980   esp.intial_buf_fullness2 = gst_asf_demux_get_uint32 (&data, &size);
2981   esp.max_obj_size = gst_asf_demux_get_uint32 (&data, &size);
2982   esp.flags = gst_asf_demux_get_uint32 (&data, &size);
2983   stream_num = gst_asf_demux_get_uint16 (&data, &size);
2984   esp.lang_idx = gst_asf_demux_get_uint16 (&data, &size);
2985   esp.avg_time_per_frame = gst_asf_demux_get_uint64 (&data, &size);
2986   stream_name_count = gst_asf_demux_get_uint16 (&data, &size);
2987   num_payload_ext = gst_asf_demux_get_uint16 (&data, &size);
2989   GST_INFO ("start_time             = %" GST_TIME_FORMAT,
2990       GST_TIME_ARGS (esp.start_time));
2991   GST_INFO ("end_time               = %" GST_TIME_FORMAT,
2992       GST_TIME_ARGS (esp.end_time));
2993   GST_INFO ("flags                  = %08x", esp.flags);
2994   GST_INFO ("average time per frame = %" GST_TIME_FORMAT,
2995       GST_TIME_ARGS (esp.avg_time_per_frame * 100));
2996   GST_INFO ("stream number          = %u", stream_num);
2997   GST_INFO ("stream language ID idx = %u (%s)", esp.lang_idx,
2998       (esp.lang_idx < demux->num_languages) ?
2999       GST_STR_NULL (demux->languages[esp.lang_idx]) : "??");
3000   GST_INFO ("stream name count      = %u", stream_name_count);
3002   /* read stream names */
3003   for (i = 0; i < stream_name_count; ++i) {
3004     guint16 stream_lang_idx;
3005     gchar *stream_name = NULL;
3007     if (size < 2)
3008       goto not_enough_data;
3009     stream_lang_idx = gst_asf_demux_get_uint16 (&data, &size);
3010     if (!gst_asf_demux_get_string (&stream_name, NULL, &data, &size))
3011       goto not_enough_data;
3012     GST_INFO ("stream name %d: %s", i, GST_STR_NULL (stream_name));
3013     g_free (stream_name);       /* TODO: store names in struct */
3014   }
3016   /* read payload extension systems stuff */
3017   GST_LOG ("payload extension systems count = %u", num_payload_ext);
3019   if (num_payload_ext > 0)
3020     esp.payload_extensions = g_new0 (AsfPayloadExtension, num_payload_ext + 1);
3021   else
3022     esp.payload_extensions = NULL;
3024   for (i = 0; i < num_payload_ext; ++i) {
3025     AsfPayloadExtension ext;
3026     ASFGuid ext_guid;
3027     guint32 sys_info_len;
3029     if (size < 16 + 2 + 4)
3030       goto not_enough_data;
3032     gst_asf_demux_get_guid (&ext_guid, &data, &size);
3033     ext.id = gst_asf_demux_identify_guid (asf_payload_ext_guids, &ext_guid);
3034     ext.len = gst_asf_demux_get_uint16 (&data, &size);
3036     sys_info_len = gst_asf_demux_get_uint32 (&data, &size);
3037     GST_LOG ("payload systems info len = %u", sys_info_len);
3038     if (!gst_asf_demux_skip_bytes (sys_info_len, &data, &size))
3039       goto not_enough_data;
3041     esp.payload_extensions[i] = ext;
3042   }
3044   GST_LOG ("bytes read: %u/%u", (guint) (data - data_start), obj_size);
3046   /* there might be an optional STREAM_INFO object here now; if not, we
3047    * should have parsed the corresponding stream info object already (since
3048    * we are parsing the extended stream properties objects delayed) */
3049   if (size == 0) {
3050     stream = gst_asf_demux_get_stream (demux, stream_num);
3051     goto done;
3052   }
3054   /* get size of the stream object */
3055   if (!asf_demux_peek_object (demux, data, size, &stream_obj))
3056     goto not_enough_data;
3058   if (stream_obj.id != ASF_OBJ_STREAM)
3059     goto expected_stream_object;
3061   if (stream_obj.size < ASF_OBJECT_HEADER_SIZE ||
3062       stream_obj.size > (10 * 1024 * 1024))
3063     goto not_enough_data;
3065   gst_asf_demux_skip_bytes (ASF_OBJECT_HEADER_SIZE, &data, &size);
3067   /* process this stream object later after all the other 'normal' ones
3068    * have been processed (since the others are more important/non-hidden) */
3069   len = stream_obj.size - ASF_OBJECT_HEADER_SIZE;
3070   if (!gst_asf_demux_get_bytes (&stream_obj_data, len, &data, &size))
3071     goto not_enough_data;
3073   /* parse stream object */
3074   stream = gst_asf_demux_parse_stream_object (demux, stream_obj_data, len);
3075   g_free (stream_obj_data);
3077 done:
3079   if (stream) {
3080     stream->ext_props = esp;
3082     /* try to set the framerate */
3083     if (stream->is_video && stream->caps) {
3084       GValue framerate = { 0 };
3085       GstStructure *s;
3086       gint num, denom;
3088       g_value_init (&framerate, GST_TYPE_FRACTION);
3090       num = GST_SECOND / 100;
3091       denom = esp.avg_time_per_frame;
3092       if (denom == 0) {
3093         /* avoid division by 0, assume 25/1 framerate */
3094         denom = GST_SECOND / 2500;
3095       }
3097       gst_value_set_fraction (&framerate, num, denom);
3099       stream->caps = gst_caps_make_writable (stream->caps);
3100       s = gst_caps_get_structure (stream->caps, 0);
3101       gst_structure_set_value (s, "framerate", &framerate);
3102       g_value_unset (&framerate);
3103       GST_DEBUG_OBJECT (demux, "setting framerate of %d/%d = %f",
3104           num, denom, ((gdouble) num) / denom);
3105     }
3107     /* add language info now if we have it */
3108     if (stream->ext_props.lang_idx < demux->num_languages) {
3109       if (stream->pending_tags == NULL)
3110         stream->pending_tags = gst_tag_list_new ();
3111       GST_LOG_OBJECT (demux, "stream %u has language '%s'", stream->id,
3112           demux->languages[stream->ext_props.lang_idx]);
3113       gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_APPEND,
3114           GST_TAG_LANGUAGE_CODE, demux->languages[stream->ext_props.lang_idx],
3115           NULL);
3116     }
3117   } else {
3118     GST_WARNING_OBJECT (demux, "Ext. stream properties for unknown stream");
3119   }
3121   return GST_FLOW_OK;
3123   /* Errors */
3124 not_enough_data:
3125   {
3126     GST_WARNING_OBJECT (demux, "short read parsing ext stream props object!");
3127     return GST_FLOW_OK;         /* not absolutely fatal */
3128   }
3129 expected_stream_object:
3130   {
3131     GST_WARNING_OBJECT (demux, "error parsing extended stream properties "
3132         "object: expected embedded stream object, but got %s object instead!",
3133         gst_asf_get_guid_nick (asf_object_guids, stream_obj.id));
3134     return GST_FLOW_OK;         /* not absolutely fatal */
3135   }
3138 static const gchar *
3139 gst_asf_demux_push_obj (GstASFDemux * demux, guint32 obj_id)
3141   const gchar *nick;
3143   nick = gst_asf_get_guid_nick (asf_object_guids, obj_id);
3144   if (g_str_has_prefix (nick, "ASF_OBJ_"))
3145     nick += strlen ("ASF_OBJ_");
3147   if (demux->objpath == NULL) {
3148     demux->objpath = g_strdup (nick);
3149   } else {
3150     gchar *newpath;
3152     newpath = g_strdup_printf ("%s/%s", demux->objpath, nick);
3153     g_free (demux->objpath);
3154     demux->objpath = newpath;
3155   }
3157   return (const gchar *) demux->objpath;
3160 static void
3161 gst_asf_demux_pop_obj (GstASFDemux * demux)
3163   gchar *s;
3165   if ((s = g_strrstr (demux->objpath, "/"))) {
3166     *s = '\0';
3167   } else {
3168     g_free (demux->objpath);
3169     demux->objpath = NULL;
3170   }
3173 static void
3174 gst_asf_demux_process_queued_extended_stream_objects (GstASFDemux * demux)
3176   GSList *l;
3177   guint i;
3179   /* Parse the queued extended stream property objects and add the info
3180    * to the existing streams or add the new embedded streams, but without
3181    * activating them yet */
3182   GST_LOG_OBJECT (demux, "%u queued extended stream properties objects",
3183       g_slist_length (demux->ext_stream_props));
3185   for (l = demux->ext_stream_props, i = 0; l != NULL; l = l->next, ++i) {
3186     GstBuffer *buf = GST_BUFFER (l->data);
3188     GST_LOG_OBJECT (demux, "parsing ext. stream properties object #%u", i);
3189     gst_asf_demux_process_ext_stream_props (demux, GST_BUFFER_DATA (buf),
3190         GST_BUFFER_SIZE (buf));
3191     gst_buffer_unref (buf);
3192   }
3193   g_slist_free (demux->ext_stream_props);
3194   demux->ext_stream_props = NULL;
3197 #if 0
3198 static void
3199 gst_asf_demux_activate_ext_props_streams (GstASFDemux * demux)
3201   guint i, j;
3203   for (i = 0; i < demux->num_streams; ++i) {
3204     AsfStream *stream;
3205     gboolean is_hidden;
3206     GSList *x;
3208     stream = &demux->stream[i];
3210     GST_LOG_OBJECT (demux, "checking  stream %2u", stream->id);
3212     if (stream->active) {
3213       GST_LOG_OBJECT (demux, "stream %2u is already activated", stream->id);
3214       continue;
3215     }
3217     is_hidden = FALSE;
3218     for (x = demux->mut_ex_streams; x != NULL; x = x->next) {
3219       guint8 *mes;
3221       /* check for each mutual exclusion whether it affects this stream */
3222       for (mes = (guint8 *) x->data; mes != NULL && *mes != 0xff; ++mes) {
3223         if (*mes == stream->id) {
3224           /* if yes, check if we've already added streams that are mutually
3225            * exclusive with the stream we're about to add */
3226           for (mes = (guint8 *) x->data; mes != NULL && *mes != 0xff; ++mes) {
3227             for (j = 0; j < demux->num_streams; ++j) {
3228               /* if the broadcast flag is set, assume the hidden streams aren't
3229                * actually streamed and hide them (or playbin won't work right),
3230                * otherwise assume their data is available */
3231               if (demux->stream[j].id == *mes && demux->broadcast) {
3232                 is_hidden = TRUE;
3233                 GST_LOG_OBJECT (demux, "broadcast stream ID %d to be added is "
3234                     "mutually exclusive with already existing stream ID %d, "
3235                     "hiding stream", stream->id, demux->stream[j].id);
3236                 goto next;
3237               }
3238             }
3239           }
3240           break;
3241         }
3242       }
3243     }
3245   next:
3247     /* FIXME: we should do stream activation based on preroll data in
3248      * streaming mode too */
3249     if (demux->streaming && !is_hidden)
3250       gst_asf_demux_activate_stream (demux, stream);
3251   }
3253 #endif
3255 static GstFlowReturn
3256 gst_asf_demux_process_object (GstASFDemux * demux, guint8 ** p_data,
3257     guint64 * p_size)
3259   GstFlowReturn ret = GST_FLOW_OK;
3260   AsfObject obj;
3261   guint64 obj_data_size;
3263   if (*p_size < ASF_OBJECT_HEADER_SIZE)
3264     return ASF_FLOW_NEED_MORE_DATA;
3266   asf_demux_peek_object (demux, *p_data, ASF_OBJECT_HEADER_SIZE, &obj);
3267   gst_asf_demux_skip_bytes (ASF_OBJECT_HEADER_SIZE, p_data, p_size);
3269   obj_data_size = obj.size - ASF_OBJECT_HEADER_SIZE;
3271   if (*p_size < obj_data_size)
3272     return ASF_FLOW_NEED_MORE_DATA;
3274   gst_asf_demux_push_obj (demux, obj.id);
3276   GST_INFO ("%s: size %" G_GUINT64_FORMAT, demux->objpath, obj.size);
3278   switch (obj.id) {
3279     case ASF_OBJ_STREAM:{
3280       AsfStream *stream;
3282       stream =
3283           gst_asf_demux_parse_stream_object (demux, *p_data, obj_data_size);
3285       ret = GST_FLOW_OK;
3286       break;
3287     }
3288     case ASF_OBJ_FILE:
3289       ret = gst_asf_demux_process_file (demux, *p_data, obj_data_size);
3290       break;
3291     case ASF_OBJ_HEADER:
3292       ret = gst_asf_demux_process_header (demux, *p_data, obj_data_size);
3293       break;
3294     case ASF_OBJ_COMMENT:
3295       ret = gst_asf_demux_process_comment (demux, *p_data, obj_data_size);
3296       break;
3297     case ASF_OBJ_HEAD1:
3298       ret = gst_asf_demux_process_header_ext (demux, *p_data, obj_data_size);
3299       break;
3300     case ASF_OBJ_BITRATE_PROPS:
3301       ret =
3302           gst_asf_demux_process_bitrate_props_object (demux, *p_data,
3303           obj_data_size);
3304       break;
3305     case ASF_OBJ_EXT_CONTENT_DESC:
3306       ret =
3307           gst_asf_demux_process_ext_content_desc (demux, *p_data,
3308           obj_data_size);
3309       break;
3310     case ASF_OBJ_METADATA_OBJECT:
3311       ret = gst_asf_demux_process_metadata (demux, *p_data, obj_data_size);
3312       break;
3313     case ASF_OBJ_EXTENDED_STREAM_PROPS:{
3314       GstBuffer *buf;
3316       /* process these later, we might not have parsed the corresponding
3317        * stream object yet */
3318       GST_LOG ("%s: queued for later parsing", demux->objpath);
3319       buf = gst_buffer_new_and_alloc (obj_data_size);
3320       memcpy (GST_BUFFER_DATA (buf), *p_data, obj_data_size);
3321       demux->ext_stream_props = g_slist_append (demux->ext_stream_props, buf);
3322       ret = GST_FLOW_OK;
3323       break;
3324     }
3325     case ASF_OBJ_LANGUAGE_LIST:
3326       ret = gst_asf_demux_process_language_list (demux, *p_data, obj_data_size);
3327       break;
3328     case ASF_OBJ_ADVANCED_MUTUAL_EXCLUSION:
3329       ret = gst_asf_demux_process_advanced_mutual_exclusion (demux, *p_data,
3330           obj_data_size);
3331       break;
3332     case ASF_OBJ_SIMPLE_INDEX:
3333       ret = gst_asf_demux_process_simple_index (demux, *p_data, obj_data_size);
3334       break;
3335     case ASF_OBJ_CONTENT_ENCRYPTION:
3336     case ASF_OBJ_EXT_CONTENT_ENCRYPTION:
3337     case ASF_OBJ_DIGITAL_SIGNATURE_OBJECT:
3338       goto error_encrypted;
3339     case ASF_OBJ_CONCEAL_NONE:
3340     case ASF_OBJ_HEAD2:
3341     case ASF_OBJ_UNDEFINED:
3342     case ASF_OBJ_CODEC_COMMENT:
3343     case ASF_OBJ_INDEX:
3344     case ASF_OBJ_PADDING:
3345     case ASF_OBJ_BITRATE_MUTEX:
3346     case ASF_OBJ_COMPATIBILITY:
3347     case ASF_OBJ_INDEX_PLACEHOLDER:
3348     case ASF_OBJ_INDEX_PARAMETERS:
3349     case ASF_OBJ_STREAM_PRIORITIZATION:
3350     case ASF_OBJ_SCRIPT_COMMAND:
3351     default:
3352       /* Unknown/unhandled object, skip it and hope for the best */
3353       GST_INFO ("%s: skipping object", demux->objpath);
3354       ret = GST_FLOW_OK;
3355       break;
3356   }
3358   /* this can't fail, we checked the number of bytes available before */
3359   gst_asf_demux_skip_bytes (obj_data_size, p_data, p_size);
3361   GST_LOG ("%s: ret = %s", demux->objpath, gst_asf_get_flow_name (ret));
3363   gst_asf_demux_pop_obj (demux);
3365   return ret;
3367 /* ERRORS */
3368 error_encrypted:
3369   {
3370     GST_ELEMENT_ERROR (demux, STREAM, DECRYPT, (NULL), (NULL));
3371     return GST_FLOW_ERROR;
3372   }
3375 static void
3376 gst_asf_demux_descramble_buffer (GstASFDemux * demux, AsfStream * stream,
3377     GstBuffer ** p_buffer)
3379   GstBuffer *descrambled_buffer;
3380   GstBuffer *scrambled_buffer;
3381   GstBuffer *sub_buffer;
3382   guint offset;
3383   guint off;
3384   guint row;
3385   guint col;
3386   guint idx;
3388   /* descrambled_buffer is initialised in the first iteration */
3389   descrambled_buffer = NULL;
3390   scrambled_buffer = *p_buffer;
3392   if (GST_BUFFER_SIZE (scrambled_buffer) < demux->ds_packet_size * demux->span)
3393     return;
3395   for (offset = 0; offset < GST_BUFFER_SIZE (scrambled_buffer);
3396       offset += demux->ds_chunk_size) {
3397     off = offset / demux->ds_chunk_size;
3398     row = off / demux->span;
3399     col = off % demux->span;
3400     idx = row + col * demux->ds_packet_size / demux->ds_chunk_size;
3401     GST_DEBUG ("idx=%u, row=%u, col=%u, off=%u, ds_chunk_size=%u", idx, row,
3402         col, off, demux->ds_chunk_size);
3403     GST_DEBUG ("scrambled buffer size=%u, span=%u, packet_size=%u",
3404         GST_BUFFER_SIZE (scrambled_buffer), demux->span, demux->ds_packet_size);
3405     GST_DEBUG ("GST_BUFFER_SIZE (scrambled_buffer) = %u",
3406         GST_BUFFER_SIZE (scrambled_buffer));
3407     sub_buffer =
3408         gst_buffer_create_sub (scrambled_buffer, idx * demux->ds_chunk_size,
3409         demux->ds_chunk_size);
3410     if (!offset) {
3411       descrambled_buffer = sub_buffer;
3412     } else {
3413       descrambled_buffer = gst_buffer_join (descrambled_buffer, sub_buffer);
3414     }
3415   }
3417   gst_buffer_copy_metadata (descrambled_buffer, scrambled_buffer,
3418       GST_BUFFER_COPY_TIMESTAMPS);
3420   /* FIXME/CHECK: do we need to transfer buffer flags here too? */
3422   gst_buffer_unref (scrambled_buffer);
3423   *p_buffer = descrambled_buffer;
3426 static gboolean
3427 gst_asf_demux_element_send_event (GstElement * element, GstEvent * event)
3429   GstASFDemux *demux = GST_ASF_DEMUX (element);
3430   gint i;
3432   GST_DEBUG ("handling element event of type %s", GST_EVENT_TYPE_NAME (event));
3434   for (i = 0; i < demux->num_streams; ++i) {
3435     gst_event_ref (event);
3436     if (gst_asf_demux_handle_src_event (demux->stream[i].pad, event)) {
3437       gst_event_unref (event);
3438       return TRUE;
3439     }
3440   }
3442   gst_event_unref (event);
3443   return FALSE;
3446 /* takes ownership of the passed event */
3447 static gboolean
3448 gst_asf_demux_send_event_unlocked (GstASFDemux * demux, GstEvent * event)
3450   gboolean ret = TRUE;
3451   gint i;
3453   GST_DEBUG_OBJECT (demux, "sending %s event to all source pads",
3454       GST_EVENT_TYPE_NAME (event));
3456   for (i = 0; i < demux->num_streams; ++i) {
3457     gst_event_ref (event);
3458     ret &= gst_pad_push_event (demux->stream[i].pad, event);
3459   }
3460   gst_event_unref (event);
3461   return ret;
3464 static const GstQueryType *
3465 gst_asf_demux_get_src_query_types (GstPad * pad)
3467   static const GstQueryType types[] = {
3468     GST_QUERY_POSITION,
3469     GST_QUERY_DURATION,
3470     GST_QUERY_SEEKING,
3471     0
3472   };
3474   return types;
3477 static gboolean
3478 gst_asf_demux_handle_src_query (GstPad * pad, GstQuery * query)
3480   GstASFDemux *demux;
3481   gboolean res = FALSE;
3483   demux = GST_ASF_DEMUX (gst_pad_get_parent (pad));
3485   GST_DEBUG ("handling %s query",
3486       gst_query_type_get_name (GST_QUERY_TYPE (query)));
3488   switch (GST_QUERY_TYPE (query)) {
3489     case GST_QUERY_DURATION:
3490     {
3491       GstFormat format;
3493       gst_query_parse_duration (query, &format, NULL);
3495       if (format != GST_FORMAT_TIME) {
3496         GST_LOG ("only support duration queries in TIME format");
3497         break;
3498       }
3500       GST_OBJECT_LOCK (demux);
3502       if (demux->segment.duration != GST_CLOCK_TIME_NONE) {
3503         GST_LOG ("returning duration: %" GST_TIME_FORMAT,
3504             GST_TIME_ARGS (demux->segment.duration));
3506         gst_query_set_duration (query, GST_FORMAT_TIME,
3507             demux->segment.duration);
3509         res = TRUE;
3510       } else {
3511         GST_LOG ("duration not known yet");
3512       }
3514       GST_OBJECT_UNLOCK (demux);
3515       break;
3516     }
3518     case GST_QUERY_POSITION:{
3519       GstFormat format;
3521       gst_query_parse_position (query, &format, NULL);
3523       if (format != GST_FORMAT_TIME) {
3524         GST_LOG ("only support position queries in TIME format");
3525         break;
3526       }
3528       GST_OBJECT_LOCK (demux);
3530       if (demux->segment.last_stop != GST_CLOCK_TIME_NONE) {
3531         GST_LOG ("returning position: %" GST_TIME_FORMAT,
3532             GST_TIME_ARGS (demux->segment.last_stop));
3534         gst_query_set_position (query, GST_FORMAT_TIME,
3535             demux->segment.last_stop);
3537         res = TRUE;
3538       } else {
3539         GST_LOG ("position not known yet");
3540       }
3542       GST_OBJECT_UNLOCK (demux);
3543       break;
3544     }
3546     case GST_QUERY_SEEKING:{
3547       GstFormat format;
3549       gst_query_parse_seeking (query, &format, NULL, NULL, NULL);
3550       if (format == GST_FORMAT_TIME) {
3551         gint64 duration;
3553         GST_OBJECT_LOCK (demux);
3554         duration = demux->segment.duration;
3555         GST_OBJECT_UNLOCK (demux);
3557         if (!demux->streaming || !demux->seekable) {
3558           gst_query_set_seeking (query, GST_FORMAT_TIME, demux->seekable, 0,
3559               duration);
3560           res = TRUE;
3561         } else {
3562           GstFormat fmt;
3563           gboolean seekable;
3565           /* try downstream first in TIME */
3566           res = gst_pad_query_default (pad, query);
3568           gst_query_parse_seeking (query, &fmt, &seekable, NULL, NULL);
3569           GST_LOG_OBJECT (demux, "upstream %s seekable %d",
3570               GST_STR_NULL (gst_format_get_name (fmt)), seekable);
3571           /* if no luck, maybe in BYTES */
3572           if (!seekable || fmt != GST_FORMAT_TIME) {
3573             GstQuery *q;
3575             q = gst_query_new_seeking (GST_FORMAT_BYTES);
3576             if ((res = gst_pad_peer_query (demux->sinkpad, q))) {
3577               gst_query_parse_seeking (q, &fmt, &seekable, NULL, NULL);
3578               GST_LOG_OBJECT (demux, "upstream %s seekable %d",
3579                   GST_STR_NULL (gst_format_get_name (fmt)), seekable);
3580               if (fmt != GST_FORMAT_BYTES)
3581                 seekable = FALSE;
3582             }
3583             gst_query_unref (q);
3584             gst_query_set_seeking (query, GST_FORMAT_TIME, seekable, 0,
3585                 duration);
3586             res = TRUE;
3587           }
3588         }
3589       } else
3590         GST_LOG_OBJECT (demux, "only support seeking in TIME format");
3591       break;
3592     }
3594     case GST_QUERY_LATENCY:
3595     {
3596       gboolean live;
3597       GstClockTime min, max;
3599       /* preroll delay does not matter in non-live pipeline,
3600        * but we might end up in a live (rtsp) one ... */
3602       /* first forward */
3603       res = gst_pad_query_default (pad, query);
3604       if (!res)
3605         break;
3607       gst_query_parse_latency (query, &live, &min, &max);
3609       GST_DEBUG_OBJECT (demux, "Peer latency: live %d, min %"
3610           GST_TIME_FORMAT " max %" GST_TIME_FORMAT, live,
3611           GST_TIME_ARGS (min), GST_TIME_ARGS (max));
3613       GST_OBJECT_LOCK (demux);
3614       if (min != -1)
3615         min += demux->latency;
3616       if (max != -1)
3617         max += demux->latency;
3618       GST_OBJECT_UNLOCK (demux);
3620       gst_query_set_latency (query, live, min, max);
3621       break;
3622     }
3623     default:
3624       res = gst_pad_query_default (pad, query);
3625       break;
3626   }
3628   gst_object_unref (demux);
3629   return res;
3632 static GstStateChangeReturn
3633 gst_asf_demux_change_state (GstElement * element, GstStateChange transition)
3635   GstASFDemux *demux = GST_ASF_DEMUX (element);
3636   GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
3638   switch (transition) {
3639     case GST_STATE_CHANGE_NULL_TO_READY:{
3640       gst_segment_init (&demux->segment, GST_FORMAT_TIME);
3641       demux->need_newsegment = TRUE;
3642       demux->segment_running = FALSE;
3643       demux->adapter = gst_adapter_new ();
3644       demux->metadata = gst_caps_new_empty ();
3645       demux->global_metadata = gst_structure_empty_new ("metadata");
3646       demux->data_size = 0;
3647       demux->data_offset = 0;
3648       demux->index_offset = 0;
3649       break;
3650     }
3651     default:
3652       break;
3653   }
3655   ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
3656   if (ret == GST_STATE_CHANGE_FAILURE)
3657     return ret;
3659   switch (transition) {
3660     case GST_STATE_CHANGE_PAUSED_TO_READY:
3661     case GST_STATE_CHANGE_READY_TO_NULL:
3662       gst_asf_demux_reset (demux);
3663       break;
3664     default:
3665       break;
3666   }
3668   return ret;