asf: don't push on inactive streams
[platform/upstream/gst-plugins-ugly.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  */
20
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  */
30
31 #ifdef HAVE_CONFIG_H
32 #include "config.h"
33 #endif
34
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 <stdio.h>
41 #include <stdlib.h>
42 #include <string.h>
43
44 #include "gstasfdemux.h"
45 #include "asfheaders.h"
46 #include "asfpacket.h"
47
48 static GstStaticPadTemplate gst_asf_demux_sink_template =
49 GST_STATIC_PAD_TEMPLATE ("sink",
50     GST_PAD_SINK,
51     GST_PAD_ALWAYS,
52     GST_STATIC_CAPS ("video/x-ms-asf")
53     );
54
55 static GstStaticPadTemplate audio_src_template =
56 GST_STATIC_PAD_TEMPLATE ("audio_%u",
57     GST_PAD_SRC,
58     GST_PAD_SOMETIMES,
59     GST_STATIC_CAPS_ANY);
60
61 static GstStaticPadTemplate video_src_template =
62 GST_STATIC_PAD_TEMPLATE ("video_%u",
63     GST_PAD_SRC,
64     GST_PAD_SOMETIMES,
65     GST_STATIC_CAPS_ANY);
66
67 /* size of an ASF object header, ie. GUID (16 bytes) + object size (8 bytes) */
68 #define ASF_OBJECT_HEADER_SIZE  (16+8)
69
70 /* FIXME: get rid of this */
71 /* abuse this GstFlowReturn enum for internal usage */
72 #define ASF_FLOW_NEED_MORE_DATA  99
73
74 #define gst_asf_get_flow_name(flow)    \
75   (flow == ASF_FLOW_NEED_MORE_DATA) ?  \
76   "need-more-data" : gst_flow_get_name (flow)
77
78 GST_DEBUG_CATEGORY (asfdemux_dbg);
79
80 static GstStateChangeReturn gst_asf_demux_change_state (GstElement * element,
81     GstStateChange transition);
82 static gboolean gst_asf_demux_element_send_event (GstElement * element,
83     GstEvent * event);
84 static gboolean gst_asf_demux_send_event_unlocked (GstASFDemux * demux,
85     GstEvent * event);
86 static gboolean gst_asf_demux_handle_src_query (GstPad * pad,
87     GstObject * parent, GstQuery * query);
88 static GstFlowReturn gst_asf_demux_chain (GstPad * pad, GstObject * parent,
89     GstBuffer * buf);
90 static gboolean gst_asf_demux_sink_event (GstPad * pad, GstObject * parent,
91     GstEvent * event);
92 static GstFlowReturn gst_asf_demux_process_object (GstASFDemux * demux,
93     guint8 ** p_data, guint64 * p_size);
94 static gboolean gst_asf_demux_activate (GstPad * sinkpad, GstObject * parent);
95 static gboolean gst_asf_demux_activate_mode (GstPad * sinkpad,
96     GstObject * parent, GstPadMode mode, gboolean active);
97 static void gst_asf_demux_loop (GstASFDemux * demux);
98 static void
99 gst_asf_demux_process_queued_extended_stream_objects (GstASFDemux * demux);
100 static gboolean gst_asf_demux_pull_headers (GstASFDemux * demux);
101 static void gst_asf_demux_pull_indices (GstASFDemux * demux);
102 static void gst_asf_demux_reset_stream_state_after_discont (GstASFDemux * asf);
103 static gboolean
104 gst_asf_demux_parse_data_object_start (GstASFDemux * demux, guint8 * data);
105 static void gst_asf_demux_descramble_buffer (GstASFDemux * demux,
106     AsfStream * stream, GstBuffer ** p_buffer);
107 static void gst_asf_demux_activate_stream (GstASFDemux * demux,
108     AsfStream * stream);
109 static GstStructure *gst_asf_demux_get_metadata_for_stream (GstASFDemux * d,
110     guint stream_num);
111 static GstFlowReturn gst_asf_demux_push_complete_payloads (GstASFDemux * demux,
112     gboolean force);
113
114 #define gst_asf_demux_parent_class parent_class
115 G_DEFINE_TYPE (GstASFDemux, gst_asf_demux, GST_TYPE_ELEMENT);
116
117 static void
118 gst_asf_demux_class_init (GstASFDemuxClass * klass)
119 {
120   GstElementClass *gstelement_class;
121
122   gstelement_class = (GstElementClass *) klass;
123
124   gst_element_class_set_static_metadata (gstelement_class, "ASF Demuxer",
125       "Codec/Demuxer",
126       "Demultiplexes ASF Streams", "Owen Fraser-Green <owen@discobabe.net>");
127
128   gst_element_class_add_pad_template (gstelement_class,
129       gst_static_pad_template_get (&audio_src_template));
130   gst_element_class_add_pad_template (gstelement_class,
131       gst_static_pad_template_get (&video_src_template));
132   gst_element_class_add_pad_template (gstelement_class,
133       gst_static_pad_template_get (&gst_asf_demux_sink_template));
134
135   gstelement_class->change_state =
136       GST_DEBUG_FUNCPTR (gst_asf_demux_change_state);
137   gstelement_class->send_event =
138       GST_DEBUG_FUNCPTR (gst_asf_demux_element_send_event);
139 }
140
141 static void
142 gst_asf_demux_free_stream (GstASFDemux * demux, AsfStream * stream)
143 {
144   gst_caps_replace (&stream->caps, NULL);
145   if (stream->pending_tags) {
146     gst_tag_list_free (stream->pending_tags);
147     stream->pending_tags = NULL;
148   }
149   if (stream->pad) {
150     if (stream->active)
151       gst_element_remove_pad (GST_ELEMENT_CAST (demux), stream->pad);
152     else
153       gst_object_unref (stream->pad);
154     stream->pad = NULL;
155   }
156
157   while (stream->payloads->len > 0) {
158     AsfPayload *payload;
159     guint last;
160
161     last = stream->payloads->len - 1;
162     payload = &g_array_index (stream->payloads, AsfPayload, last);
163     gst_buffer_replace (&payload->buf, NULL);
164     g_array_remove_index (stream->payloads, last);
165   }
166   if (stream->payloads) {
167     g_array_free (stream->payloads, TRUE);
168     stream->payloads = NULL;
169   }
170   if (stream->ext_props.valid) {
171     g_free (stream->ext_props.payload_extensions);
172     stream->ext_props.payload_extensions = NULL;
173   }
174 }
175
176 static void
177 gst_asf_demux_reset (GstASFDemux * demux, gboolean chain_reset)
178 {
179   GST_LOG_OBJECT (demux, "resetting");
180
181   gst_segment_init (&demux->segment, GST_FORMAT_UNDEFINED);
182   demux->segment_running = FALSE;
183   if (demux->adapter && !chain_reset) {
184     gst_adapter_clear (demux->adapter);
185     g_object_unref (demux->adapter);
186     demux->adapter = NULL;
187   }
188   if (demux->taglist) {
189     gst_tag_list_free (demux->taglist);
190     demux->taglist = NULL;
191   }
192   if (demux->metadata) {
193     gst_caps_unref (demux->metadata);
194     demux->metadata = NULL;
195   }
196   if (demux->global_metadata) {
197     gst_structure_free (demux->global_metadata);
198     demux->global_metadata = NULL;
199   }
200
201   demux->state = GST_ASF_DEMUX_STATE_HEADER;
202   g_free (demux->objpath);
203   demux->objpath = NULL;
204   g_strfreev (demux->languages);
205   demux->languages = NULL;
206   demux->num_languages = 0;
207   g_slist_foreach (demux->ext_stream_props, (GFunc) gst_mini_object_unref,
208       NULL);
209   g_slist_free (demux->ext_stream_props);
210   demux->ext_stream_props = NULL;
211
212   while (demux->old_num_streams > 0) {
213     gst_asf_demux_free_stream (demux,
214         &demux->old_stream[demux->old_num_streams - 1]);
215     --demux->old_num_streams;
216   }
217   memset (demux->old_stream, 0, sizeof (demux->old_stream));
218   demux->old_num_streams = 0;
219
220   /* when resetting for a new chained asf, we don't want to remove the pads
221    * before adding the new ones */
222   if (chain_reset) {
223     memcpy (demux->old_stream, demux->stream, sizeof (demux->stream));
224     demux->old_num_streams = demux->num_streams;
225     demux->num_streams = 0;
226   }
227
228   while (demux->num_streams > 0) {
229     gst_asf_demux_free_stream (demux, &demux->stream[demux->num_streams - 1]);
230     --demux->num_streams;
231   }
232   memset (demux->stream, 0, sizeof (demux->stream));
233   if (!chain_reset) {
234     /* do not remove those for not adding pads with same name */
235     demux->num_audio_streams = 0;
236     demux->num_video_streams = 0;
237   }
238   demux->num_streams = 0;
239   demux->activated_streams = FALSE;
240   demux->first_ts = GST_CLOCK_TIME_NONE;
241   demux->segment_ts = GST_CLOCK_TIME_NONE;
242   demux->in_gap = 0;
243   if (!chain_reset)
244     gst_segment_init (&demux->in_segment, GST_FORMAT_UNDEFINED);
245   demux->state = GST_ASF_DEMUX_STATE_HEADER;
246   demux->seekable = FALSE;
247   demux->broadcast = FALSE;
248   demux->sidx_interval = 0;
249   demux->sidx_num_entries = 0;
250   g_free (demux->sidx_entries);
251   demux->sidx_entries = NULL;
252
253   demux->speed_packets = 1;
254
255   if (chain_reset) {
256     GST_LOG_OBJECT (demux, "Restarting");
257     gst_segment_init (&demux->segment, GST_FORMAT_TIME);
258     demux->need_newsegment = TRUE;
259     demux->segment_running = FALSE;
260     demux->accurate = FALSE;
261     demux->metadata = gst_caps_new_empty ();
262     demux->global_metadata = gst_structure_new_empty ("metadata");
263     demux->data_size = 0;
264     demux->data_offset = 0;
265     demux->index_offset = 0;
266   } else {
267     demux->base_offset = 0;
268   }
269 }
270
271 static void
272 gst_asf_demux_init (GstASFDemux * demux)
273 {
274   demux->sinkpad =
275       gst_pad_new_from_static_template (&gst_asf_demux_sink_template, "sink");
276   gst_pad_set_chain_function (demux->sinkpad,
277       GST_DEBUG_FUNCPTR (gst_asf_demux_chain));
278   gst_pad_set_event_function (demux->sinkpad,
279       GST_DEBUG_FUNCPTR (gst_asf_demux_sink_event));
280   gst_pad_set_activate_function (demux->sinkpad,
281       GST_DEBUG_FUNCPTR (gst_asf_demux_activate));
282   gst_pad_set_activatemode_function (demux->sinkpad,
283       GST_DEBUG_FUNCPTR (gst_asf_demux_activate_mode));
284   gst_element_add_pad (GST_ELEMENT (demux), demux->sinkpad);
285
286   /* set initial state */
287   gst_asf_demux_reset (demux, FALSE);
288 }
289
290 static gboolean
291 gst_asf_demux_activate (GstPad * sinkpad, GstObject * parent)
292 {
293   GstQuery *query;
294   gboolean pull_mode;
295
296   query = gst_query_new_scheduling ();
297
298   if (!gst_pad_peer_query (sinkpad, query)) {
299     gst_query_unref (query);
300     goto activate_push;
301   }
302
303   pull_mode = gst_query_has_scheduling_mode (query, GST_PAD_MODE_PULL);
304   gst_query_unref (query);
305
306   if (!pull_mode)
307     goto activate_push;
308
309   GST_DEBUG_OBJECT (sinkpad, "activating pull");
310   return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PULL, TRUE);
311
312 activate_push:
313   {
314     GST_DEBUG_OBJECT (sinkpad, "activating push");
315     return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PUSH, TRUE);
316   }
317 }
318
319 static gboolean
320 gst_asf_demux_activate_mode (GstPad * sinkpad, GstObject * parent,
321     GstPadMode mode, gboolean active)
322 {
323   gboolean res;
324   GstASFDemux *demux;
325
326   demux = GST_ASF_DEMUX (parent);
327
328   switch (mode) {
329     case GST_PAD_MODE_PUSH:
330       demux->state = GST_ASF_DEMUX_STATE_HEADER;
331       demux->streaming = TRUE;
332       res = TRUE;
333       break;
334     case GST_PAD_MODE_PULL:
335       if (active) {
336         demux->state = GST_ASF_DEMUX_STATE_HEADER;
337         demux->streaming = FALSE;
338
339         res = gst_pad_start_task (sinkpad, (GstTaskFunction) gst_asf_demux_loop,
340             demux, NULL);
341       } else {
342         res = gst_pad_stop_task (sinkpad);
343       }
344       break;
345     default:
346       res = FALSE;
347       break;
348   }
349   return res;
350 }
351
352 static gboolean
353 gst_asf_demux_sink_event (GstPad * pad, GstObject * parent, GstEvent * event)
354 {
355   GstASFDemux *demux;
356   gboolean ret = TRUE;
357
358   demux = GST_ASF_DEMUX (parent);
359
360   GST_LOG_OBJECT (demux, "handling %s event", GST_EVENT_TYPE_NAME (event));
361   switch (GST_EVENT_TYPE (event)) {
362     case GST_EVENT_SEGMENT:{
363       const GstSegment *segment;
364
365       gst_event_parse_segment (event, &segment);
366
367       if (segment->format == GST_FORMAT_BYTES) {
368         if (demux->packet_size && segment->start > demux->data_offset)
369           demux->packet = (segment->start - demux->data_offset) /
370               demux->packet_size;
371         else
372           demux->packet = 0;
373       } else if (segment->format == GST_FORMAT_TIME) {
374         /* do not know packet position, not really a problem */
375         demux->packet = -1;
376       } else {
377         GST_WARNING_OBJECT (demux, "unsupported newsegment format, ignoring");
378         gst_event_unref (event);
379         break;
380       }
381
382       /* record upstream segment for interpolation */
383       if (segment->format != demux->in_segment.format)
384         gst_segment_init (&demux->in_segment, GST_FORMAT_UNDEFINED);
385       gst_segment_copy_into (segment, &demux->in_segment);
386
387       /* in either case, clear some state and generate newsegment later on */
388       GST_OBJECT_LOCK (demux);
389       demux->segment_ts = GST_CLOCK_TIME_NONE;
390       demux->in_gap = GST_CLOCK_TIME_NONE;
391       demux->need_newsegment = TRUE;
392       gst_asf_demux_reset_stream_state_after_discont (demux);
393       GST_OBJECT_UNLOCK (demux);
394
395       gst_event_unref (event);
396       break;
397     }
398     case GST_EVENT_EOS:{
399       GstFlowReturn flow;
400
401       if (demux->state == GST_ASF_DEMUX_STATE_HEADER) {
402         GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
403             (_("This stream contains no data.")),
404             ("got eos and didn't receive a complete header object"));
405         break;
406       }
407       flow = gst_asf_demux_push_complete_payloads (demux, TRUE);
408       if (flow < GST_FLOW_EOS || flow == GST_FLOW_NOT_LINKED) {
409         GST_ELEMENT_ERROR (demux, STREAM, FAILED,
410             (_("Internal data stream error.")),
411             ("streaming stopped, reason %s", gst_flow_get_name (flow)));
412         break;
413       }
414
415       GST_OBJECT_LOCK (demux);
416       gst_adapter_clear (demux->adapter);
417       GST_OBJECT_UNLOCK (demux);
418       gst_asf_demux_send_event_unlocked (demux, event);
419       break;
420     }
421
422     case GST_EVENT_FLUSH_STOP:
423       GST_OBJECT_LOCK (demux);
424       gst_asf_demux_reset_stream_state_after_discont (demux);
425       GST_OBJECT_UNLOCK (demux);
426       gst_asf_demux_send_event_unlocked (demux, event);
427       /* upon activation, latency is no longer introduced, e.g. after seek */
428       if (demux->activated_streams)
429         demux->latency = 0;
430       break;
431
432     default:
433       ret = gst_pad_event_default (pad, parent, event);
434       break;
435   }
436
437   return ret;
438 }
439
440 static gboolean
441 gst_asf_demux_seek_index_lookup (GstASFDemux * demux, guint * packet,
442     GstClockTime seek_time, GstClockTime * p_idx_time, guint * speed,
443     gboolean next, gboolean * eos)
444 {
445   GstClockTime idx_time;
446   guint idx;
447
448   if (eos)
449     *eos = FALSE;
450
451   if (G_UNLIKELY (demux->sidx_num_entries == 0 || demux->sidx_interval == 0))
452     return FALSE;
453
454   idx = (guint) ((seek_time + demux->preroll) / demux->sidx_interval);
455
456   if (next) {
457     /* if we want the next keyframe, we have to go forward till we find
458        a different packet number */
459     guint idx2 = idx;
460     if (idx >= demux->sidx_num_entries - 1) {
461       /* If we get here, we're asking for next keyframe after the last one. There isn't one. */
462       if (eos)
463         *eos = TRUE;
464       return FALSE;
465     }
466     for (idx2 = idx + 1; idx2 < demux->sidx_num_entries; ++idx2) {
467       if (demux->sidx_entries[idx].packet != demux->sidx_entries[idx2].packet) {
468         idx = idx2;
469         break;
470       }
471     }
472   }
473
474   if (G_UNLIKELY (idx >= demux->sidx_num_entries)) {
475     if (eos)
476       *eos = TRUE;
477     return FALSE;
478   }
479
480   *packet = demux->sidx_entries[idx].packet;
481   if (speed)
482     *speed = demux->sidx_entries[idx].count;
483
484   /* so we get closer to the actual time of the packet ... actually, let's not
485    * do this, since we throw away superfluous payloads before the seek position
486    * anyway; this way, our key unit seek 'snap resolution' is a bit better
487    * (ie. same as index resolution) */
488   /*
489      while (idx > 0 && demux->sidx_entries[idx-1] == demux->sidx_entries[idx])
490      --idx;
491    */
492
493   idx_time = demux->sidx_interval * idx;
494   if (G_LIKELY (idx_time >= demux->preroll))
495     idx_time -= demux->preroll;
496
497   GST_DEBUG_OBJECT (demux, "%" GST_TIME_FORMAT " => packet %u at %"
498       GST_TIME_FORMAT, GST_TIME_ARGS (seek_time), *packet,
499       GST_TIME_ARGS (idx_time));
500
501   if (G_LIKELY (p_idx_time))
502     *p_idx_time = idx_time;
503
504   return TRUE;
505 }
506
507 static void
508 gst_asf_demux_reset_stream_state_after_discont (GstASFDemux * demux)
509 {
510   guint n;
511
512   gst_adapter_clear (demux->adapter);
513
514   GST_DEBUG_OBJECT (demux, "reset stream state");
515
516   for (n = 0; n < demux->num_streams; n++) {
517     demux->stream[n].discont = TRUE;
518     demux->stream[n].last_flow = GST_FLOW_OK;
519
520     while (demux->stream[n].payloads->len > 0) {
521       AsfPayload *payload;
522       guint last;
523
524       last = demux->stream[n].payloads->len - 1;
525       payload = &g_array_index (demux->stream[n].payloads, AsfPayload, last);
526       gst_buffer_replace (&payload->buf, NULL);
527       g_array_remove_index (demux->stream[n].payloads, last);
528     }
529   }
530 }
531
532 static void
533 gst_asf_demux_mark_discont (GstASFDemux * demux)
534 {
535   guint n;
536
537   GST_DEBUG_OBJECT (demux, "Mark stream discont");
538
539   for (n = 0; n < demux->num_streams; n++)
540     demux->stream[n].discont = TRUE;
541 }
542
543 /* do a seek in push based mode */
544 static gboolean
545 gst_asf_demux_handle_seek_push (GstASFDemux * demux, GstEvent * event)
546 {
547   gdouble rate;
548   GstFormat format;
549   GstSeekFlags flags;
550   GstSeekType cur_type, stop_type;
551   gint64 cur, stop;
552   guint packet;
553   gboolean res;
554
555   gst_event_parse_seek (event, &rate, &format, &flags, &cur_type, &cur,
556       &stop_type, &stop);
557
558   stop_type = GST_SEEK_TYPE_NONE;
559   stop = -1;
560
561   GST_DEBUG_OBJECT (demux, "seeking to %" GST_TIME_FORMAT, GST_TIME_ARGS (cur));
562
563   /* determine packet, by index or by estimation */
564   if (!gst_asf_demux_seek_index_lookup (demux, &packet, cur, NULL, NULL, FALSE,
565           NULL)) {
566     packet =
567         (guint) gst_util_uint64_scale (demux->num_packets, cur,
568         demux->play_time);
569   }
570
571   if (packet > demux->num_packets) {
572     GST_DEBUG_OBJECT (demux, "could not determine packet to seek to, "
573         "seek aborted.");
574     return FALSE;
575   }
576
577   GST_DEBUG_OBJECT (demux, "seeking to packet %d", packet);
578
579   cur = demux->data_offset + (packet * demux->packet_size);
580
581   GST_DEBUG_OBJECT (demux, "Pushing BYTE seek rate %g, "
582       "start %" G_GINT64_FORMAT ", stop %" G_GINT64_FORMAT, rate, cur, stop);
583   /* BYTE seek event */
584   event = gst_event_new_seek (rate, GST_FORMAT_BYTES, flags, cur_type, cur,
585       stop_type, stop);
586   res = gst_pad_push_event (demux->sinkpad, event);
587
588   return res;
589 }
590
591 static gboolean
592 gst_asf_demux_handle_seek_event (GstASFDemux * demux, GstEvent * event)
593 {
594   GstClockTime idx_time;
595   GstSegment segment;
596   GstSeekFlags flags;
597   GstSeekType cur_type, stop_type;
598   GstFormat format;
599   gboolean only_need_update;
600   gboolean keyunit_sync, after, before, next;
601   gboolean flush;
602   gdouble rate;
603   gint64 cur, stop;
604   gint64 seek_time;
605   guint packet, speed_count = 1;
606   gboolean eos;
607
608   if (G_UNLIKELY (demux->seekable == FALSE || demux->packet_size == 0 ||
609           demux->num_packets == 0 || demux->play_time == 0)) {
610     GST_LOG_OBJECT (demux, "stream is not seekable");
611     return FALSE;
612   }
613
614   if (G_UNLIKELY (!demux->activated_streams)) {
615     GST_LOG_OBJECT (demux, "streams not yet activated, ignoring seek");
616     return FALSE;
617   }
618
619   gst_event_parse_seek (event, &rate, &format, &flags, &cur_type, &cur,
620       &stop_type, &stop);
621
622   if (G_UNLIKELY (format != GST_FORMAT_TIME)) {
623     GST_LOG_OBJECT (demux, "seeking is only supported in TIME format");
624     return FALSE;
625   }
626
627   if (G_UNLIKELY (rate <= 0.0)) {
628     GST_LOG_OBJECT (demux, "backward playback is not supported yet");
629     return FALSE;
630   }
631
632   flush = ((flags & GST_SEEK_FLAG_FLUSH) == GST_SEEK_FLAG_FLUSH);
633   demux->accurate =
634       ((flags & GST_SEEK_FLAG_ACCURATE) == GST_SEEK_FLAG_ACCURATE);
635   keyunit_sync = ((flags & GST_SEEK_FLAG_KEY_UNIT) == GST_SEEK_FLAG_KEY_UNIT);
636   after = ((flags & GST_SEEK_FLAG_SNAP_AFTER) == GST_SEEK_FLAG_SNAP_AFTER);
637   before = ((flags & GST_SEEK_FLAG_SNAP_BEFORE) == GST_SEEK_FLAG_SNAP_BEFORE);
638   next = after && !before;
639
640   if (G_UNLIKELY (demux->streaming)) {
641     /* support it safely needs more segment handling, e.g. closing etc */
642     if (!flush) {
643       GST_LOG_OBJECT (demux, "streaming; non-flushing seek not supported");
644       return FALSE;
645     }
646     /* we can (re)construct the start later on, but not the end */
647     if (stop_type != GST_SEEK_TYPE_NONE) {
648       GST_LOG_OBJECT (demux, "streaming; end type must be NONE");
649       return FALSE;
650     }
651     gst_event_ref (event);
652     /* upstream might handle TIME seek, e.g. mms or rtsp,
653      * or not, e.g. http, then we give it a hand */
654     if (!gst_pad_push_event (demux->sinkpad, event))
655       return gst_asf_demux_handle_seek_push (demux, event);
656     else
657       return TRUE;
658   }
659
660   /* unlock the streaming thread */
661   if (G_LIKELY (flush)) {
662     gst_pad_push_event (demux->sinkpad, gst_event_new_flush_start ());
663     gst_asf_demux_send_event_unlocked (demux, gst_event_new_flush_start ());
664   } else {
665     gst_pad_pause_task (demux->sinkpad);
666   }
667
668   /* grab the stream lock so that streaming cannot continue, for
669    * non flushing seeks when the element is in PAUSED this could block
670    * forever */
671   GST_PAD_STREAM_LOCK (demux->sinkpad);
672
673   /* we now can stop flushing, since we have the stream lock now */
674   gst_pad_push_event (demux->sinkpad, gst_event_new_flush_stop (TRUE));
675
676   if (G_LIKELY (flush))
677     gst_asf_demux_send_event_unlocked (demux, gst_event_new_flush_stop (TRUE));
678
679   /* operating on copy of segment until we know the seek worked */
680   segment = demux->segment;
681
682   if (G_UNLIKELY (demux->segment_running && !flush)) {
683     GstSegment newsegment;
684     GstEvent *newseg;
685
686     /* create the segment event to close the current segment */
687     gst_segment_copy_into (&segment, &newsegment);
688     newseg = gst_event_new_segment (&newsegment);
689
690     gst_asf_demux_send_event_unlocked (demux, newseg);
691   }
692
693   gst_segment_do_seek (&segment, rate, format, flags, cur_type,
694       cur, stop_type, stop, &only_need_update);
695
696   GST_DEBUG_OBJECT (demux, "seeking to time %" GST_TIME_FORMAT ", segment: "
697       "%" GST_SEGMENT_FORMAT, GST_TIME_ARGS (segment.start), &segment);
698
699   seek_time = segment.start;
700
701   /* FIXME: should check the KEY_UNIT flag; need to adjust position to
702    * real start of data and segment_start to indexed time for key unit seek*/
703   if (G_UNLIKELY (!gst_asf_demux_seek_index_lookup (demux, &packet, seek_time,
704               &idx_time, &speed_count, next, &eos))) {
705     gint64 offset;
706
707     if (eos) {
708       demux->packet = demux->num_packets;
709       goto skip;
710     }
711
712     /* First try to query our source to see if it can convert for us. This is
713        the case when our source is an mms stream, notice that in this case
714        gstmms will do a time based seek to get the byte offset, this is not a
715        problem as the seek to this offset needs to happen anway. */
716     if (gst_pad_peer_query_convert (demux->sinkpad, GST_FORMAT_TIME, seek_time,
717             GST_FORMAT_BYTES, &offset)) {
718       packet = (offset - demux->data_offset) / demux->packet_size;
719       GST_LOG_OBJECT (demux, "convert %" GST_TIME_FORMAT
720           " to bytes query result: %" G_GINT64_FORMAT ", data_ofset: %"
721           G_GINT64_FORMAT ", packet_size: %u," " resulting packet: %u\n",
722           GST_TIME_ARGS (seek_time), offset, demux->data_offset,
723           demux->packet_size, packet);
724     } else {
725       /* FIXME: For streams containing video, seek to an earlier position in
726        * the hope of hitting a keyframe and let the sinks throw away the stuff
727        * before the segment start. For audio-only this is unnecessary as every
728        * frame is 'key'. */
729       if (flush && (demux->accurate || (keyunit_sync && !next))
730           && demux->num_video_streams > 0) {
731         seek_time -= 5 * GST_SECOND;
732         if (seek_time < 0)
733           seek_time = 0;
734       }
735
736       packet = (guint) gst_util_uint64_scale (demux->num_packets,
737           seek_time, demux->play_time);
738
739       if (packet > demux->num_packets)
740         packet = demux->num_packets;
741     }
742   } else {
743     if (G_LIKELY (keyunit_sync)) {
744       GST_DEBUG_OBJECT (demux, "key unit seek, adjust seek_time = %"
745           GST_TIME_FORMAT " to index_time = %" GST_TIME_FORMAT,
746           GST_TIME_ARGS (seek_time), GST_TIME_ARGS (idx_time));
747       segment.start = idx_time;
748       segment.position = idx_time;
749       segment.time = idx_time;
750     }
751   }
752
753   GST_DEBUG_OBJECT (demux, "seeking to packet %u (%d)", packet, speed_count);
754
755   GST_OBJECT_LOCK (demux);
756   demux->segment = segment;
757   demux->packet = packet;
758   demux->need_newsegment = TRUE;
759   demux->speed_packets = speed_count;
760   gst_asf_demux_reset_stream_state_after_discont (demux);
761   GST_OBJECT_UNLOCK (demux);
762
763 skip:
764   /* restart our task since it might have been stopped when we did the flush */
765   gst_pad_start_task (demux->sinkpad, (GstTaskFunction) gst_asf_demux_loop,
766       demux, NULL);
767
768   /* streaming can continue now */
769   GST_PAD_STREAM_UNLOCK (demux->sinkpad);
770
771   return TRUE;
772 }
773
774 static gboolean
775 gst_asf_demux_handle_src_event (GstPad * pad, GstObject * parent,
776     GstEvent * event)
777 {
778   GstASFDemux *demux;
779   gboolean ret;
780
781   demux = GST_ASF_DEMUX (parent);
782
783   switch (GST_EVENT_TYPE (event)) {
784     case GST_EVENT_SEEK:
785       GST_LOG_OBJECT (pad, "seek event");
786       ret = gst_asf_demux_handle_seek_event (demux, event);
787       gst_event_unref (event);
788       break;
789     case GST_EVENT_QOS:
790     case GST_EVENT_NAVIGATION:
791       /* just drop these two silently */
792       gst_event_unref (event);
793       ret = FALSE;
794       break;
795     default:
796       GST_LOG_OBJECT (pad, "%s event", GST_EVENT_TYPE_NAME (event));
797       ret = gst_pad_event_default (pad, parent, event);
798       break;
799   }
800
801   return ret;
802 }
803
804 static inline guint32
805 gst_asf_demux_identify_guid (const ASFGuidHash * guids, ASFGuid * guid)
806 {
807   guint32 ret;
808
809   ret = gst_asf_identify_guid (guids, guid);
810
811   GST_LOG ("%s  0x%08x-0x%08x-0x%08x-0x%08x",
812       gst_asf_get_guid_nick (guids, ret),
813       guid->v1, guid->v2, guid->v3, guid->v4);
814
815   return ret;
816 }
817
818 typedef struct
819 {
820   AsfObjectID id;
821   guint64 size;
822 } AsfObject;
823
824
825 /* expect is true when the user is expeting an object,
826  * when false, it will give no warnings if the object
827  * is not identified
828  */
829 static gboolean
830 asf_demux_peek_object (GstASFDemux * demux, const guint8 * data,
831     guint data_len, AsfObject * object, gboolean expect)
832 {
833   ASFGuid guid;
834
835   if (data_len < ASF_OBJECT_HEADER_SIZE)
836     return FALSE;
837
838   guid.v1 = GST_READ_UINT32_LE (data + 0);
839   guid.v2 = GST_READ_UINT32_LE (data + 4);
840   guid.v3 = GST_READ_UINT32_LE (data + 8);
841   guid.v4 = GST_READ_UINT32_LE (data + 12);
842
843   object->size = GST_READ_UINT64_LE (data + 16);
844
845   /* FIXME: make asf_demux_identify_object_guid() */
846   object->id = gst_asf_demux_identify_guid (asf_object_guids, &guid);
847   if (object->id == ASF_OBJ_UNDEFINED && expect) {
848     GST_WARNING_OBJECT (demux, "Unknown object %08x-%08x-%08x-%08x",
849         guid.v1, guid.v2, guid.v3, guid.v4);
850   }
851
852   return TRUE;
853 }
854
855 static void
856 gst_asf_demux_release_old_pads (GstASFDemux * demux)
857 {
858   GST_DEBUG_OBJECT (demux, "Releasing old pads");
859
860   while (demux->old_num_streams > 0) {
861     gst_pad_push_event (demux->old_stream[demux->old_num_streams - 1].pad,
862         gst_event_new_eos ());
863     gst_asf_demux_free_stream (demux,
864         &demux->old_stream[demux->old_num_streams - 1]);
865     --demux->old_num_streams;
866   }
867   memset (demux->old_stream, 0, sizeof (demux->old_stream));
868   demux->old_num_streams = 0;
869 }
870
871 static GstFlowReturn
872 gst_asf_demux_chain_headers (GstASFDemux * demux)
873 {
874   GstFlowReturn flow;
875   AsfObject obj;
876   guint8 *header_data, *data = NULL;
877   const guint8 *cdata = NULL;
878   guint64 header_size;
879
880   cdata = (guint8 *) gst_adapter_map (demux->adapter, ASF_OBJECT_HEADER_SIZE);
881   if (cdata == NULL)
882     goto need_more_data;
883
884   asf_demux_peek_object (demux, cdata, ASF_OBJECT_HEADER_SIZE, &obj, TRUE);
885   if (obj.id != ASF_OBJ_HEADER)
886     goto wrong_type;
887
888   GST_LOG_OBJECT (demux, "header size = %u", (guint) obj.size);
889
890   /* + 50 for non-packet data at beginning of ASF_OBJ_DATA */
891   if (gst_adapter_available (demux->adapter) < obj.size + 50)
892     goto need_more_data;
893
894   data = gst_adapter_take (demux->adapter, obj.size + 50);
895
896   header_data = data;
897   header_size = obj.size;
898   flow = gst_asf_demux_process_object (demux, &header_data, &header_size);
899   if (flow != GST_FLOW_OK)
900     goto parse_failed;
901
902   /* calculate where the packet data starts */
903   demux->data_offset = obj.size + 50;
904
905   /* now parse the beginning of the ASF_OBJ_DATA object */
906   if (!gst_asf_demux_parse_data_object_start (demux, data + obj.size))
907     goto wrong_type;
908
909   if (demux->num_streams == 0)
910     goto no_streams;
911
912   g_free (data);
913   return GST_FLOW_OK;
914
915 /* NON-FATAL */
916 need_more_data:
917   {
918     GST_LOG_OBJECT (demux, "not enough data in adapter yet");
919     return GST_FLOW_OK;
920   }
921
922 /* ERRORS */
923 wrong_type:
924   {
925     GST_ELEMENT_ERROR (demux, STREAM, WRONG_TYPE, (NULL),
926         ("This doesn't seem to be an ASF file"));
927     g_free (data);
928     return GST_FLOW_ERROR;
929   }
930 no_streams:
931 parse_failed:
932   {
933     GST_ELEMENT_ERROR (demux, STREAM, DEMUX, (NULL),
934         ("header parsing failed, or no streams found, flow = %s",
935             gst_flow_get_name (flow)));
936     g_free (data);
937     return GST_FLOW_ERROR;
938   }
939 }
940
941 static GstFlowReturn
942 gst_asf_demux_aggregate_flow_return (GstASFDemux * demux, AsfStream * stream,
943     GstFlowReturn flow)
944 {
945   int i;
946
947   GST_DEBUG_OBJECT (demux, "Aggregating");
948
949   /* Store the value */
950   stream->last_flow = flow;
951
952   /* any other error that is not not-linked can be returned right away */
953   if (flow != GST_FLOW_NOT_LINKED)
954     goto done;
955
956   for (i = 0; i < demux->num_streams; i++) {
957     if (demux->stream[i].active) {
958       flow = demux->stream[i].last_flow;
959       GST_DEBUG_OBJECT (demux, "Aggregating: flow %i return %s", i,
960           gst_flow_get_name (flow));
961       if (flow != GST_FLOW_NOT_LINKED)
962         goto done;
963     }
964   }
965
966   /* If we got here, then all our active streams are not linked */
967 done:
968   return flow;
969 }
970
971 static gboolean
972 gst_asf_demux_pull_data (GstASFDemux * demux, guint64 offset, guint size,
973     GstBuffer ** p_buf, GstFlowReturn * p_flow)
974 {
975   gsize buffer_size;
976   GstFlowReturn flow;
977
978   GST_LOG_OBJECT (demux, "pulling buffer at %" G_GUINT64_FORMAT "+%u",
979       offset, size);
980
981   flow = gst_pad_pull_range (demux->sinkpad, offset, size, p_buf);
982
983   if (G_LIKELY (p_flow))
984     *p_flow = flow;
985
986   if (G_UNLIKELY (flow != GST_FLOW_OK)) {
987     GST_DEBUG_OBJECT (demux, "flow %s pulling buffer at %" G_GUINT64_FORMAT
988         "+%u", gst_flow_get_name (flow), offset, size);
989     *p_buf = NULL;
990     return FALSE;
991   }
992
993   g_assert (*p_buf != NULL);
994
995   buffer_size = gst_buffer_get_size (*p_buf);
996   if (G_UNLIKELY (buffer_size < size)) {
997     GST_DEBUG_OBJECT (demux, "short read pulling buffer at %" G_GUINT64_FORMAT
998         "+%u (got only %" G_GSIZE_FORMAT " bytes)", offset, size, buffer_size);
999     gst_buffer_unref (*p_buf);
1000     if (G_LIKELY (p_flow))
1001       *p_flow = GST_FLOW_EOS;
1002     *p_buf = NULL;
1003     return FALSE;
1004   }
1005
1006   return TRUE;
1007 }
1008
1009 static void
1010 gst_asf_demux_pull_indices (GstASFDemux * demux)
1011 {
1012   GstBuffer *buf = NULL;
1013   guint64 offset;
1014   guint num_read = 0;
1015
1016   offset = demux->index_offset;
1017
1018   if (G_UNLIKELY (offset == 0)) {
1019     GST_DEBUG_OBJECT (demux, "can't read indices, don't know index offset");
1020     return;
1021   }
1022
1023   while (gst_asf_demux_pull_data (demux, offset, 16 + 8, &buf, NULL)) {
1024     GstFlowReturn flow;
1025     AsfObject obj;
1026     GstMapInfo map;
1027     guint8 *bufdata;
1028
1029     gst_buffer_map (buf, &map, GST_MAP_READ);
1030     g_assert (map.size >= 16 + 8);
1031     asf_demux_peek_object (demux, map.data, 16 + 8, &obj, TRUE);
1032     gst_buffer_unmap (buf, &map);
1033     gst_buffer_replace (&buf, NULL);
1034
1035     /* check for sanity */
1036     if (G_UNLIKELY (obj.size > (5 * 1024 * 1024))) {
1037       GST_DEBUG_OBJECT (demux, "implausible index object size, bailing out");
1038       break;
1039     }
1040
1041     if (G_UNLIKELY (!gst_asf_demux_pull_data (demux, offset, obj.size, &buf,
1042                 NULL)))
1043       break;
1044
1045     GST_LOG_OBJECT (demux, "index object at offset 0x%" G_GINT64_MODIFIER "X"
1046         ", size %u", offset, (guint) obj.size);
1047
1048     offset += obj.size;         /* increase before _process_object changes it */
1049
1050     gst_buffer_map (buf, &map, GST_MAP_READ);
1051     g_assert (map.size >= obj.size);
1052     bufdata = (guint8 *) map.data;
1053     flow = gst_asf_demux_process_object (demux, &bufdata, &obj.size);
1054     gst_buffer_unmap (buf, &map);
1055     gst_buffer_replace (&buf, NULL);
1056
1057     if (G_UNLIKELY (flow != GST_FLOW_OK))
1058       break;
1059
1060     ++num_read;
1061   }
1062   GST_DEBUG_OBJECT (demux, "read %u index objects", num_read);
1063 }
1064
1065 static gboolean
1066 gst_asf_demux_parse_data_object_start (GstASFDemux * demux, guint8 * data)
1067 {
1068   AsfObject obj;
1069
1070   asf_demux_peek_object (demux, data, 50, &obj, TRUE);
1071   if (obj.id != ASF_OBJ_DATA) {
1072     GST_WARNING_OBJECT (demux, "headers not followed by a DATA object");
1073     return FALSE;
1074   }
1075
1076   demux->state = GST_ASF_DEMUX_STATE_DATA;
1077
1078   if (!demux->broadcast && obj.size > 50) {
1079     demux->data_size = obj.size - 50;
1080     /* CHECKME: for at least one file this is off by +158 bytes?! */
1081     demux->index_offset = demux->data_offset + demux->data_size;
1082   } else {
1083     demux->data_size = 0;
1084     demux->index_offset = 0;
1085   }
1086
1087   demux->packet = 0;
1088
1089   if (!demux->broadcast) {
1090     /* skip object header (24 bytes) and file GUID (16 bytes) */
1091     demux->num_packets = GST_READ_UINT64_LE (data + (16 + 8) + 16);
1092   } else {
1093     demux->num_packets = 0;
1094   }
1095
1096   if (demux->num_packets == 0)
1097     demux->seekable = FALSE;
1098
1099   /* fallback in the unlikely case that headers are inconsistent, can't hurt */
1100   if (demux->data_size == 0 && demux->num_packets > 0) {
1101     demux->data_size = demux->num_packets * demux->packet_size;
1102     demux->index_offset = demux->data_offset + demux->data_size;
1103   }
1104
1105   /* process pending stream objects and create pads for those */
1106   gst_asf_demux_process_queued_extended_stream_objects (demux);
1107
1108   GST_INFO_OBJECT (demux, "Stream has %" G_GUINT64_FORMAT " packets, "
1109       "data_offset=%" G_GINT64_FORMAT ", data_size=%" G_GINT64_FORMAT
1110       ", index_offset=%" G_GUINT64_FORMAT, demux->num_packets,
1111       demux->data_offset, demux->data_size, demux->index_offset);
1112
1113   return TRUE;
1114 }
1115
1116 static gboolean
1117 gst_asf_demux_pull_headers (GstASFDemux * demux)
1118 {
1119   GstFlowReturn flow;
1120   AsfObject obj;
1121   GstBuffer *buf = NULL;
1122   guint64 size;
1123   GstMapInfo map;
1124   guint8 *bufdata;
1125
1126   GST_LOG_OBJECT (demux, "reading headers");
1127
1128   /* pull HEADER object header, so we know its size */
1129   if (!gst_asf_demux_pull_data (demux, demux->base_offset, 16 + 8, &buf, NULL))
1130     goto read_failed;
1131
1132   gst_buffer_map (buf, &map, GST_MAP_READ);
1133   g_assert (map.size >= 16 + 8);
1134   asf_demux_peek_object (demux, map.data, 16 + 8, &obj, TRUE);
1135   gst_buffer_unmap (buf, &map);
1136   gst_buffer_replace (&buf, NULL);
1137
1138   if (obj.id != ASF_OBJ_HEADER)
1139     goto wrong_type;
1140
1141   GST_LOG_OBJECT (demux, "header size = %u", (guint) obj.size);
1142
1143   /* pull HEADER object */
1144   if (!gst_asf_demux_pull_data (demux, demux->base_offset, obj.size, &buf,
1145           NULL))
1146     goto read_failed;
1147
1148   size = obj.size;              /* don't want obj.size changed */
1149   gst_buffer_map (buf, &map, GST_MAP_READ);
1150   g_assert (map.size >= size);
1151   bufdata = (guint8 *) map.data;
1152   flow = gst_asf_demux_process_object (demux, &bufdata, &size);
1153   gst_buffer_unmap (buf, &map);
1154   gst_buffer_replace (&buf, NULL);
1155
1156   if (flow != GST_FLOW_OK) {
1157     GST_WARNING_OBJECT (demux, "process_object: %s", gst_flow_get_name (flow));
1158     goto parse_failed;
1159   }
1160
1161   /* calculate where the packet data starts */
1162   demux->data_offset = demux->base_offset + obj.size + 50;
1163
1164   /* now pull beginning of DATA object before packet data */
1165   if (!gst_asf_demux_pull_data (demux, demux->base_offset + obj.size, 50, &buf,
1166           NULL))
1167     goto read_failed;
1168
1169   gst_buffer_map (buf, &map, GST_MAP_READ);
1170   g_assert (map.size >= size);
1171   bufdata = (guint8 *) map.data;
1172   if (!gst_asf_demux_parse_data_object_start (demux, bufdata))
1173     goto wrong_type;
1174
1175   if (demux->num_streams == 0)
1176     goto no_streams;
1177
1178   gst_buffer_unmap (buf, &map);
1179   gst_buffer_replace (&buf, NULL);
1180
1181   return TRUE;
1182
1183 /* ERRORS */
1184 wrong_type:
1185   {
1186     if (buf != NULL) {
1187       gst_buffer_unmap (buf, &map);
1188       gst_buffer_replace (&buf, NULL);
1189     }
1190     GST_ELEMENT_ERROR (demux, STREAM, WRONG_TYPE, (NULL),
1191         ("This doesn't seem to be an ASF file"));
1192     return FALSE;
1193   }
1194
1195 no_streams:
1196 read_failed:
1197 parse_failed:
1198   {
1199     if (buf)
1200       gst_buffer_unmap (buf, &map);
1201     gst_buffer_replace (&buf, NULL);
1202     GST_ELEMENT_ERROR (demux, STREAM, DEMUX, (NULL), (NULL));
1203     return FALSE;
1204   }
1205 }
1206
1207 static gboolean
1208 all_streams_prerolled (GstASFDemux * demux)
1209 {
1210   GstClockTime preroll_time;
1211   guint i, num_no_data = 0;
1212
1213   /* Allow at least 500ms of preroll_time  */
1214   preroll_time = MAX (demux->preroll, 500 * GST_MSECOND);
1215
1216   /* returns TRUE as long as there isn't a stream which (a) has data queued
1217    * and (b) the timestamp of last piece of data queued is < demux->preroll
1218    * AND there is at least one other stream with data queued */
1219   for (i = 0; i < demux->num_streams; ++i) {
1220     AsfPayload *last_payload;
1221     AsfStream *stream;
1222     guint last_idx;
1223
1224     stream = &demux->stream[i];
1225     if (G_UNLIKELY (stream->payloads->len == 0)) {
1226       ++num_no_data;
1227       GST_LOG_OBJECT (stream->pad, "no data queued");
1228       continue;
1229     }
1230
1231     last_idx = stream->payloads->len - 1;
1232     last_payload = &g_array_index (stream->payloads, AsfPayload, last_idx);
1233
1234     GST_LOG_OBJECT (stream->pad, "checking if %" GST_TIME_FORMAT " > %"
1235         GST_TIME_FORMAT, GST_TIME_ARGS (last_payload->ts),
1236         GST_TIME_ARGS (preroll_time));
1237     if (G_UNLIKELY (last_payload->ts <= preroll_time)) {
1238       GST_LOG_OBJECT (stream->pad, "not beyond preroll point yet");
1239       return FALSE;
1240     }
1241   }
1242
1243   if (G_UNLIKELY (num_no_data == demux->num_streams))
1244     return FALSE;
1245
1246   return TRUE;
1247 }
1248
1249 #if 0
1250 static gboolean
1251 gst_asf_demux_have_mutually_exclusive_active_stream (GstASFDemux * demux,
1252     AsfStream * stream)
1253 {
1254   GSList *l;
1255
1256   for (l = demux->mut_ex_streams; l != NULL; l = l->next) {
1257     guint8 *mes;
1258
1259     /* check for each mutual exclusion group whether it affects this stream */
1260     for (mes = (guint8 *) l->data; mes != NULL && *mes != 0xff; ++mes) {
1261       if (*mes == stream->id) {
1262         /* we are in this group; let's check if we've already activated streams
1263          * that are in the same group (and hence mutually exclusive to this
1264          * one) */
1265         for (mes = (guint8 *) l->data; mes != NULL && *mes != 0xff; ++mes) {
1266           guint i;
1267
1268           for (i = 0; i < demux->num_streams; ++i) {
1269             if (demux->stream[i].id == *mes && demux->stream[i].active) {
1270               GST_LOG_OBJECT (demux, "stream with ID %d is mutually exclusive "
1271                   "to already active stream with ID %d", stream->id,
1272                   demux->stream[i].id);
1273               return TRUE;
1274             }
1275           }
1276         }
1277         /* we can only be in this group once, let's break out and move on to
1278          * the next mutual exclusion group */
1279         break;
1280       }
1281     }
1282   }
1283
1284   return FALSE;
1285 }
1286 #endif
1287
1288 static gboolean
1289 gst_asf_demux_check_activate_streams (GstASFDemux * demux, gboolean force)
1290 {
1291   guint i;
1292
1293   if (demux->activated_streams)
1294     return TRUE;
1295
1296   if (!all_streams_prerolled (demux) && !force) {
1297     GST_DEBUG_OBJECT (demux, "not all streams with data beyond preroll yet");
1298     return FALSE;
1299   }
1300
1301   for (i = 0; i < demux->num_streams; ++i) {
1302     AsfStream *stream = &demux->stream[i];
1303
1304     if (stream->payloads->len > 0) {
1305       /* we don't check mutual exclusion stuff here; either we have data for
1306        * a stream, then we active it, or we don't, then we'll ignore it */
1307       GST_LOG_OBJECT (stream->pad, "is prerolled - activate!");
1308       gst_asf_demux_activate_stream (demux, stream);
1309     } else {
1310       GST_LOG_OBJECT (stream->pad, "no data, ignoring stream");
1311     }
1312   }
1313
1314   gst_asf_demux_release_old_pads (demux);
1315
1316   demux->activated_streams = TRUE;
1317   GST_LOG_OBJECT (demux, "signalling no more pads");
1318   gst_element_no_more_pads (GST_ELEMENT (demux));
1319   return TRUE;
1320 }
1321
1322 /* returns the stream that has a complete payload with the lowest timestamp
1323  * queued, or NULL (we push things by timestamp because during the internal
1324  * prerolling we might accumulate more data then the external queues can take,
1325  * so we'd lock up if we pushed all accumulated data for stream N in one go) */
1326 static AsfStream *
1327 gst_asf_demux_find_stream_with_complete_payload (GstASFDemux * demux)
1328 {
1329   AsfPayload *best_payload = NULL;
1330   AsfStream *best_stream = NULL;
1331   guint i;
1332
1333   for (i = 0; i < demux->num_streams; ++i) {
1334     AsfStream *stream;
1335
1336     stream = &demux->stream[i];
1337
1338     /* Don't push any data until we have at least one payload that falls within
1339      * the current segment. This way we can remove out-of-segment payloads that
1340      * don't need to be decoded after a seek, sending only data from the
1341      * keyframe directly before our segment start */
1342     if (stream->payloads->len > 0) {
1343       AsfPayload *payload;
1344       guint last_idx;
1345
1346       last_idx = stream->payloads->len - 1;
1347       payload = &g_array_index (stream->payloads, AsfPayload, last_idx);
1348       if (G_UNLIKELY (GST_CLOCK_TIME_IS_VALID (payload->ts) &&
1349               (payload->ts < demux->segment.start))) {
1350         if (G_UNLIKELY ((!demux->accurate) && payload->keyframe)) {
1351           GST_DEBUG_OBJECT (stream->pad,
1352               "Found keyframe, updating segment start to %" GST_TIME_FORMAT,
1353               GST_TIME_ARGS (payload->ts));
1354           demux->segment.start = payload->ts;
1355           demux->segment.time = payload->ts;
1356         } else {
1357           GST_DEBUG_OBJECT (stream->pad, "Last queued payload has timestamp %"
1358               GST_TIME_FORMAT " which is before our segment start %"
1359               GST_TIME_FORMAT ", not pushing yet", GST_TIME_ARGS (payload->ts),
1360               GST_TIME_ARGS (demux->segment.start));
1361           continue;
1362         }
1363       }
1364
1365       /* Now see if there's a complete payload queued for this stream */
1366
1367       payload = &g_array_index (stream->payloads, AsfPayload, 0);
1368       if (!gst_asf_payload_is_complete (payload))
1369         continue;
1370
1371       /* ... and whether its timestamp is lower than the current best */
1372       if (best_stream == NULL || best_payload->ts > payload->ts) {
1373         best_stream = stream;
1374         best_payload = payload;
1375       }
1376     }
1377   }
1378
1379   return best_stream;
1380 }
1381
1382 static GstFlowReturn
1383 gst_asf_demux_push_complete_payloads (GstASFDemux * demux, gboolean force)
1384 {
1385   AsfStream *stream;
1386   GstFlowReturn ret = GST_FLOW_OK;
1387
1388   if (G_UNLIKELY (!demux->activated_streams)) {
1389     if (!gst_asf_demux_check_activate_streams (demux, force))
1390       return GST_FLOW_OK;
1391     /* streams are now activated */
1392   }
1393
1394   /* wait until we had a chance to "lock on" some payload's timestamp */
1395   if (G_UNLIKELY (demux->need_newsegment
1396           && !GST_CLOCK_TIME_IS_VALID (demux->segment_ts)))
1397     return GST_FLOW_OK;
1398
1399   while ((stream = gst_asf_demux_find_stream_with_complete_payload (demux))) {
1400     AsfPayload *payload;
1401
1402     payload = &g_array_index (stream->payloads, AsfPayload, 0);
1403
1404     /* do we need to send a newsegment event */
1405     if ((G_UNLIKELY (demux->need_newsegment))) {
1406
1407       /* safe default if insufficient upstream info */
1408       if (!GST_CLOCK_TIME_IS_VALID (demux->in_gap))
1409         demux->in_gap = 0;
1410
1411       if (demux->segment.stop == GST_CLOCK_TIME_NONE &&
1412           demux->segment.duration > 0) {
1413         /* slight HACK; prevent clipping of last bit */
1414         demux->segment.stop = demux->segment.duration + demux->in_gap;
1415       }
1416
1417       /* FIXME : only if ACCURATE ! */
1418       if (G_LIKELY (!demux->accurate
1419               && (GST_CLOCK_TIME_IS_VALID (payload->ts)))) {
1420         GST_DEBUG ("Adjusting newsegment start to %" GST_TIME_FORMAT,
1421             GST_TIME_ARGS (payload->ts));
1422         demux->segment.start = payload->ts;
1423         demux->segment.time = payload->ts;
1424       }
1425
1426       GST_DEBUG_OBJECT (demux, "sending new-segment event %" GST_SEGMENT_FORMAT,
1427           &demux->segment);
1428
1429       /* note: we fix up all timestamps to start from 0, so this should be ok */
1430       gst_asf_demux_send_event_unlocked (demux,
1431           gst_event_new_segment (&demux->segment));
1432
1433       /* now post any global tags we may have found */
1434       if (demux->taglist == NULL)
1435         demux->taglist = gst_tag_list_new_empty ();
1436
1437       gst_tag_list_add (demux->taglist, GST_TAG_MERGE_REPLACE,
1438           GST_TAG_CONTAINER_FORMAT, "ASF", NULL);
1439
1440       GST_DEBUG_OBJECT (demux, "global tags: %" GST_PTR_FORMAT, demux->taglist);
1441       gst_asf_demux_send_event_unlocked (demux,
1442           gst_event_new_tag ("GstDemuxer", demux->taglist));
1443       demux->taglist = NULL;
1444
1445       demux->need_newsegment = FALSE;
1446       demux->segment_running = TRUE;
1447     }
1448
1449     /* Do we have tags pending for this stream? */
1450     if (G_UNLIKELY (stream->pending_tags)) {
1451       GST_LOG_OBJECT (stream->pad, "%" GST_PTR_FORMAT, stream->pending_tags);
1452       gst_pad_push_event (stream->pad,
1453           gst_event_new_tag ("GstDemuxer", stream->pending_tags));
1454       stream->pending_tags = NULL;
1455     }
1456
1457     /* We have the whole packet now so we should push the packet to
1458      * the src pad now. First though we should check if we need to do
1459      * descrambling */
1460     if (G_UNLIKELY (demux->span > 1)) {
1461       gst_asf_demux_descramble_buffer (demux, stream, &payload->buf);
1462     }
1463
1464     payload->buf = gst_buffer_make_writable (payload->buf);
1465
1466     if (G_LIKELY (!payload->keyframe)) {
1467       GST_BUFFER_FLAG_SET (payload->buf, GST_BUFFER_FLAG_DELTA_UNIT);
1468     }
1469
1470     if (G_UNLIKELY (stream->discont)) {
1471       GST_DEBUG_OBJECT (stream->pad, "marking DISCONT on stream");
1472       GST_BUFFER_FLAG_SET (payload->buf, GST_BUFFER_FLAG_DISCONT);
1473       stream->discont = FALSE;
1474     }
1475
1476     if (G_UNLIKELY (stream->is_video && payload->par_x && payload->par_y &&
1477             (payload->par_x != stream->par_x) &&
1478             (payload->par_y != stream->par_y))) {
1479       GST_DEBUG ("Updating PAR (%d/%d => %d/%d)",
1480           stream->par_x, stream->par_y, payload->par_x, payload->par_y);
1481       stream->par_x = payload->par_x;
1482       stream->par_y = payload->par_y;
1483       stream->caps = gst_caps_make_writable (stream->caps);
1484       gst_caps_set_simple (stream->caps, "pixel-aspect-ratio",
1485           GST_TYPE_FRACTION, stream->par_x, stream->par_y, NULL);
1486       gst_pad_set_caps (stream->pad, stream->caps);
1487     }
1488
1489     if (G_UNLIKELY (stream->interlaced != payload->interlaced)) {
1490       GST_DEBUG ("Updating interlaced status (%d => %d)", stream->interlaced,
1491           payload->interlaced);
1492       stream->interlaced = payload->interlaced;
1493       stream->caps = gst_caps_make_writable (stream->caps);
1494       gst_caps_set_simple (stream->caps, "interlace-mode", G_TYPE_BOOLEAN,
1495           (stream->interlaced ? "mixed" : "progressive"), NULL);
1496       gst_pad_set_caps (stream->pad, stream->caps);
1497     }
1498
1499     /* (sort of) interpolate timestamps using upstream "frame of reference",
1500      * typically useful for live src, but might (unavoidably) mess with
1501      * position reporting if a live src is playing not so live content
1502      * (e.g. rtspsrc taking some time to fall back to tcp) */
1503     GST_BUFFER_TIMESTAMP (payload->buf) = payload->ts + demux->in_gap;
1504     if (payload->duration == GST_CLOCK_TIME_NONE
1505         && stream->ext_props.avg_time_per_frame != 0)
1506       GST_BUFFER_DURATION (payload->buf) =
1507           stream->ext_props.avg_time_per_frame * 100;
1508     else
1509       GST_BUFFER_DURATION (payload->buf) = payload->duration;
1510
1511     /* FIXME: we should really set durations on buffers if we can */
1512
1513     GST_LOG_OBJECT (stream->pad, "pushing buffer, ts=%" GST_TIME_FORMAT
1514         ", dur=%" GST_TIME_FORMAT " size=%" G_GSIZE_FORMAT,
1515         GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (payload->buf)),
1516         GST_TIME_ARGS (GST_BUFFER_DURATION (payload->buf)),
1517         gst_buffer_get_size (payload->buf));
1518
1519     if (stream->active) {
1520       ret = gst_pad_push (stream->pad, payload->buf);
1521       ret = gst_asf_demux_aggregate_flow_return (demux, stream, ret);
1522     } else {
1523       ret = GST_FLOW_OK;
1524     }
1525     payload->buf = NULL;
1526     g_array_remove_index (stream->payloads, 0);
1527
1528     /* Break out as soon as we have an issue */
1529     if (G_UNLIKELY (ret != GST_FLOW_OK))
1530       break;
1531   }
1532
1533   return ret;
1534 }
1535
1536 static gboolean
1537 gst_asf_demux_check_buffer_is_header (GstASFDemux * demux, GstBuffer * buf)
1538 {
1539   AsfObject obj;
1540   GstMapInfo map;
1541   g_assert (buf != NULL);
1542
1543   GST_LOG_OBJECT (demux, "Checking if buffer is a header");
1544
1545   gst_buffer_map (buf, &map, GST_MAP_READ);
1546
1547   /* we return false on buffer too small */
1548   if (map.size < ASF_OBJECT_HEADER_SIZE) {
1549     gst_buffer_unmap (buf, &map);
1550     return FALSE;
1551   }
1552
1553   /* check if it is a header */
1554   asf_demux_peek_object (demux, map.data, ASF_OBJECT_HEADER_SIZE, &obj, TRUE);
1555   gst_buffer_unmap (buf, &map);
1556   if (obj.id == ASF_OBJ_HEADER) {
1557     return TRUE;
1558   }
1559   return FALSE;
1560 }
1561
1562 static gboolean
1563 gst_asf_demux_check_chained_asf (GstASFDemux * demux)
1564 {
1565   guint64 off = demux->data_offset + (demux->packet * demux->packet_size);
1566   GstFlowReturn ret = GST_FLOW_OK;
1567   GstBuffer *buf = NULL;
1568   gboolean header = FALSE;
1569
1570   /* TODO maybe we should skip index objects after the data and look
1571    * further for a new header */
1572   if (gst_asf_demux_pull_data (demux, off, ASF_OBJECT_HEADER_SIZE, &buf, &ret)) {
1573     g_assert (buf != NULL);
1574     /* check if it is a header */
1575     if (gst_asf_demux_check_buffer_is_header (demux, buf)) {
1576       GST_DEBUG_OBJECT (demux, "new base offset: %" G_GUINT64_FORMAT, off);
1577       demux->base_offset = off;
1578       header = TRUE;
1579     }
1580
1581     gst_buffer_unref (buf);
1582   }
1583
1584   return header;
1585 }
1586
1587 static void
1588 gst_asf_demux_loop (GstASFDemux * demux)
1589 {
1590   GstFlowReturn flow = GST_FLOW_OK;
1591   GstBuffer *buf = NULL;
1592   guint64 off;
1593   gboolean sent_eos = FALSE;
1594
1595   if (G_UNLIKELY (demux->state == GST_ASF_DEMUX_STATE_HEADER)) {
1596     if (!gst_asf_demux_pull_headers (demux)) {
1597       flow = GST_FLOW_ERROR;
1598       goto pause;
1599     }
1600
1601     gst_asf_demux_pull_indices (demux);
1602   }
1603
1604   g_assert (demux->state == GST_ASF_DEMUX_STATE_DATA);
1605
1606   if (G_UNLIKELY (demux->num_packets != 0
1607           && demux->packet >= demux->num_packets))
1608     goto eos;
1609
1610   GST_LOG_OBJECT (demux, "packet %u/%u", (guint) demux->packet + 1,
1611       (guint) demux->num_packets);
1612
1613   off = demux->data_offset + (demux->packet * demux->packet_size);
1614
1615   if (G_UNLIKELY (!gst_asf_demux_pull_data (demux, off,
1616               demux->packet_size * demux->speed_packets, &buf, &flow))) {
1617     GST_DEBUG_OBJECT (demux, "got flow %s", gst_flow_get_name (flow));
1618     if (flow == GST_FLOW_EOS)
1619       goto eos;
1620     else if (flow == GST_FLOW_FLUSHING) {
1621       GST_DEBUG_OBJECT (demux, "Not fatal");
1622       goto pause;
1623     } else
1624       goto read_failed;
1625   }
1626
1627   if (G_LIKELY (demux->speed_packets == 1)) {
1628     GstAsfDemuxParsePacketError err;
1629     err = gst_asf_demux_parse_packet (demux, buf);
1630     if (G_UNLIKELY (err != GST_ASF_DEMUX_PARSE_PACKET_ERROR_NONE)) {
1631       /* when we don't know when the data object ends, we should check
1632        * for a chained asf */
1633       if (demux->num_packets == 0) {
1634         if (gst_asf_demux_check_buffer_is_header (demux, buf)) {
1635           GST_INFO_OBJECT (demux, "Chained asf found");
1636           demux->base_offset = off;
1637           gst_asf_demux_reset (demux, TRUE);
1638           gst_buffer_unref (buf);
1639           return;
1640         }
1641       }
1642       /* FIXME: We should tally up fatal errors and error out only
1643        * after a few broken packets in a row? */
1644
1645       GST_INFO_OBJECT (demux, "Ignoring recoverable parse error");
1646       gst_buffer_unref (buf);
1647       ++demux->packet;
1648       return;
1649     }
1650
1651     flow = gst_asf_demux_push_complete_payloads (demux, FALSE);
1652
1653     ++demux->packet;
1654
1655   } else {
1656     guint n;
1657     for (n = 0; n < demux->speed_packets; n++) {
1658       GstBuffer *sub;
1659       GstAsfDemuxParsePacketError err;
1660
1661       sub =
1662           gst_buffer_copy_region (buf, GST_BUFFER_COPY_ALL,
1663           n * demux->packet_size, demux->packet_size);
1664       err = gst_asf_demux_parse_packet (demux, sub);
1665       if (G_UNLIKELY (err != GST_ASF_DEMUX_PARSE_PACKET_ERROR_NONE)) {
1666         /* when we don't know when the data object ends, we should check
1667          * for a chained asf */
1668         if (demux->num_packets == 0) {
1669           if (gst_asf_demux_check_buffer_is_header (demux, sub)) {
1670             GST_INFO_OBJECT (demux, "Chained asf found");
1671             demux->base_offset = off + n * demux->packet_size;
1672             gst_asf_demux_reset (demux, TRUE);
1673             gst_buffer_unref (sub);
1674             gst_buffer_unref (buf);
1675             return;
1676           }
1677         }
1678         /* FIXME: We should tally up fatal errors and error out only
1679          * after a few broken packets in a row? */
1680
1681         GST_INFO_OBJECT (demux, "Ignoring recoverable parse error");
1682         flow = GST_FLOW_OK;
1683       }
1684
1685       gst_buffer_unref (sub);
1686
1687       if (err == GST_ASF_DEMUX_PARSE_PACKET_ERROR_NONE)
1688         flow = gst_asf_demux_push_complete_payloads (demux, FALSE);
1689
1690       ++demux->packet;
1691
1692     }
1693
1694     /* reset speed pull */
1695     demux->speed_packets = 1;
1696   }
1697
1698   gst_buffer_unref (buf);
1699
1700   if (G_UNLIKELY (demux->num_packets > 0
1701           && demux->packet >= demux->num_packets)) {
1702     GST_LOG_OBJECT (demux, "reached EOS");
1703     goto eos;
1704   }
1705
1706   if (G_UNLIKELY (flow != GST_FLOW_OK)) {
1707     GST_DEBUG_OBJECT (demux, "pushing complete payloads failed");
1708     goto pause;
1709   }
1710
1711   /* check if we're at the end of the configured segment */
1712   /* FIXME: check if segment end reached etc. */
1713
1714   return;
1715
1716 eos:
1717   {
1718     /* if we haven't activated our streams yet, this might be because we have
1719      * less data queued than required for preroll; force stream activation and
1720      * send any pending payloads before sending EOS */
1721     if (!demux->activated_streams)
1722       gst_asf_demux_push_complete_payloads (demux, TRUE);
1723
1724     /* we want to push an eos or post a segment-done in any case */
1725     if (demux->segment.flags & GST_SEEK_FLAG_SEGMENT) {
1726       gint64 stop;
1727
1728       /* for segment playback we need to post when (in stream time)
1729        * we stopped, this is either stop (when set) or the duration. */
1730       if ((stop = demux->segment.stop) == -1)
1731         stop = demux->segment.duration;
1732
1733       GST_INFO_OBJECT (demux, "Posting segment-done, at end of segment");
1734       gst_element_post_message (GST_ELEMENT_CAST (demux),
1735           gst_message_new_segment_done (GST_OBJECT (demux), GST_FORMAT_TIME,
1736               stop));
1737       gst_asf_demux_send_event_unlocked (demux,
1738           gst_event_new_segment_done (GST_FORMAT_TIME, stop));
1739     } else if (flow != GST_FLOW_EOS) {
1740       /* check if we have a chained asf, in case, we don't eos yet */
1741       if (gst_asf_demux_check_chained_asf (demux)) {
1742         GST_INFO_OBJECT (demux, "Chained ASF starting");
1743         gst_asf_demux_reset (demux, TRUE);
1744         return;
1745       }
1746     }
1747     /* normal playback, send EOS to all linked pads */
1748     GST_INFO_OBJECT (demux, "Sending EOS, at end of stream");
1749     gst_asf_demux_send_event_unlocked (demux, gst_event_new_eos ());
1750     sent_eos = TRUE;
1751     /* ... and fall through to pause */
1752   }
1753 pause:
1754   {
1755     GST_DEBUG_OBJECT (demux, "pausing task, flow return: %s",
1756         gst_flow_get_name (flow));
1757     demux->segment_running = FALSE;
1758     gst_pad_pause_task (demux->sinkpad);
1759
1760     /* For the error cases (not EOS) */
1761     if (!sent_eos) {
1762       if (flow == GST_FLOW_EOS)
1763         gst_asf_demux_send_event_unlocked (demux, gst_event_new_eos ());
1764       else if (flow < GST_FLOW_EOS || flow == GST_FLOW_NOT_LINKED) {
1765         /* Post an error. Hopefully something else already has, but if not... */
1766         GST_ELEMENT_ERROR (demux, STREAM, FAILED,
1767             (_("Internal data stream error.")),
1768             ("streaming stopped, reason %s", gst_flow_get_name (flow)));
1769       }
1770     }
1771     return;
1772   }
1773
1774 /* ERRORS */
1775 read_failed:
1776   {
1777     GST_DEBUG_OBJECT (demux, "Read failed, doh");
1778     gst_asf_demux_send_event_unlocked (demux, gst_event_new_eos ());
1779     flow = GST_FLOW_EOS;
1780     goto pause;
1781   }
1782 #if 0
1783   /* See FIXMEs above */
1784 parse_error:
1785   {
1786     gst_buffer_unref (buf);
1787     GST_ELEMENT_ERROR (demux, STREAM, DEMUX, (NULL),
1788         ("Error parsing ASF packet %u", (guint) demux->packet));
1789     gst_asf_demux_send_event_unlocked (demux, gst_event_new_eos ());
1790     flow = GST_FLOW_ERROR;
1791     goto pause;
1792   }
1793 #endif
1794 }
1795
1796 #define GST_ASF_DEMUX_CHECK_HEADER_YES       0
1797 #define GST_ASF_DEMUX_CHECK_HEADER_NO        1
1798 #define GST_ASF_DEMUX_CHECK_HEADER_NEED_DATA 2
1799
1800 static gint
1801 gst_asf_demux_check_header (GstASFDemux * demux)
1802 {
1803   AsfObject obj;
1804   guint8 *cdata = (guint8 *) gst_adapter_map (demux->adapter,
1805       ASF_OBJECT_HEADER_SIZE);
1806   if (cdata == NULL)            /* need more data */
1807     return GST_ASF_DEMUX_CHECK_HEADER_NEED_DATA;
1808
1809   asf_demux_peek_object (demux, cdata, ASF_OBJECT_HEADER_SIZE, &obj, FALSE);
1810   if (obj.id != ASF_OBJ_HEADER) {
1811     return GST_ASF_DEMUX_CHECK_HEADER_NO;
1812   } else {
1813     return GST_ASF_DEMUX_CHECK_HEADER_YES;
1814   }
1815 }
1816
1817 static GstFlowReturn
1818 gst_asf_demux_chain (GstPad * pad, GstObject * parent, GstBuffer * buf)
1819 {
1820   GstFlowReturn ret = GST_FLOW_OK;
1821   GstASFDemux *demux;
1822
1823   demux = GST_ASF_DEMUX (parent);
1824
1825   GST_LOG_OBJECT (demux,
1826       "buffer: size=%" G_GSIZE_FORMAT ", offset=%" G_GINT64_FORMAT ", time=%"
1827       GST_TIME_FORMAT, gst_buffer_get_size (buf), GST_BUFFER_OFFSET (buf),
1828       GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)));
1829
1830   if (G_UNLIKELY (GST_BUFFER_IS_DISCONT (buf))) {
1831     GST_DEBUG_OBJECT (demux, "received DISCONT");
1832     gst_asf_demux_mark_discont (demux);
1833   }
1834
1835   if (G_UNLIKELY ((!GST_CLOCK_TIME_IS_VALID (demux->in_gap) &&
1836               GST_BUFFER_TIMESTAMP_IS_VALID (buf)))) {
1837     demux->in_gap = GST_BUFFER_TIMESTAMP (buf) - demux->in_segment.start;
1838     GST_DEBUG_OBJECT (demux, "upstream segment start %" GST_TIME_FORMAT
1839         ", interpolation gap: %" GST_TIME_FORMAT,
1840         GST_TIME_ARGS (demux->in_segment.start), GST_TIME_ARGS (demux->in_gap));
1841   }
1842
1843   gst_adapter_push (demux->adapter, buf);
1844
1845   switch (demux->state) {
1846     case GST_ASF_DEMUX_STATE_INDEX:{
1847       gint result = gst_asf_demux_check_header (demux);
1848       if (result == GST_ASF_DEMUX_CHECK_HEADER_NEED_DATA)       /* need more data */
1849         break;
1850
1851       if (result == GST_ASF_DEMUX_CHECK_HEADER_NO) {
1852         /* we don't care about this, probably an index */
1853         /* TODO maybe would be smarter to skip all the indices
1854          * until we got a new header or EOS to decide */
1855         GST_LOG_OBJECT (demux, "Received index object, its EOS");
1856         goto eos;
1857       } else {
1858         GST_INFO_OBJECT (demux, "Chained asf starting");
1859         /* cleanup and get ready for a chained asf */
1860         gst_asf_demux_reset (demux, TRUE);
1861         /* fall through */
1862       }
1863     }
1864     case GST_ASF_DEMUX_STATE_HEADER:{
1865       ret = gst_asf_demux_chain_headers (demux);
1866       if (demux->state != GST_ASF_DEMUX_STATE_DATA)
1867         break;
1868       /* otherwise fall through */
1869     }
1870     case GST_ASF_DEMUX_STATE_DATA:
1871     {
1872       guint64 data_size;
1873
1874       data_size = demux->packet_size;
1875
1876       while (gst_adapter_available (demux->adapter) >= data_size) {
1877         GstBuffer *buf;
1878         GstAsfDemuxParsePacketError err;
1879
1880         /* we don't know the length of the stream
1881          * check for a chained asf everytime */
1882         if (demux->num_packets == 0) {
1883           gint result = gst_asf_demux_check_header (demux);
1884
1885           if (result == GST_ASF_DEMUX_CHECK_HEADER_YES) {
1886             GST_INFO_OBJECT (demux, "Chained asf starting");
1887             /* cleanup and get ready for a chained asf */
1888             gst_asf_demux_reset (demux, TRUE);
1889             break;
1890           }
1891         } else if (G_UNLIKELY (demux->num_packets != 0 && demux->packet >= 0
1892                 && demux->packet >= demux->num_packets)) {
1893           /* do not overshoot data section when streaming */
1894           break;
1895         }
1896
1897         buf = gst_adapter_take_buffer (demux->adapter, data_size);
1898
1899         /* FIXME: We should tally up fatal errors and error out only
1900          * after a few broken packets in a row? */
1901         err = gst_asf_demux_parse_packet (demux, buf);
1902
1903         gst_buffer_unref (buf);
1904
1905         if (G_LIKELY (err == GST_ASF_DEMUX_PARSE_PACKET_ERROR_NONE))
1906           ret = gst_asf_demux_push_complete_payloads (demux, FALSE);
1907         else
1908           GST_WARNING_OBJECT (demux, "Parse error");
1909
1910         if (demux->packet >= 0)
1911           ++demux->packet;
1912       }
1913       if (G_UNLIKELY (demux->num_packets != 0 && demux->packet >= 0
1914               && demux->packet >= demux->num_packets)) {
1915         demux->state = GST_ASF_DEMUX_STATE_INDEX;
1916       }
1917       break;
1918     }
1919     default:
1920       g_assert_not_reached ();
1921   }
1922
1923 done:
1924   if (ret != GST_FLOW_OK)
1925     GST_DEBUG_OBJECT (demux, "flow: %s", gst_flow_get_name (ret));
1926
1927   return ret;
1928
1929 eos:
1930   {
1931     GST_DEBUG_OBJECT (demux, "Handled last packet, setting EOS");
1932     ret = GST_FLOW_EOS;
1933     goto done;
1934   }
1935 }
1936
1937 static inline gboolean
1938 gst_asf_demux_skip_bytes (guint num_bytes, guint8 ** p_data, guint64 * p_size)
1939 {
1940   if (*p_size < num_bytes)
1941     return FALSE;
1942
1943   *p_data += num_bytes;
1944   *p_size -= num_bytes;
1945   return TRUE;
1946 }
1947
1948 static inline guint8
1949 gst_asf_demux_get_uint8 (guint8 ** p_data, guint64 * p_size)
1950 {
1951   guint8 ret;
1952
1953   g_assert (*p_size >= 1);
1954   ret = GST_READ_UINT8 (*p_data);
1955   *p_data += sizeof (guint8);
1956   *p_size -= sizeof (guint8);
1957   return ret;
1958 }
1959
1960 static inline guint16
1961 gst_asf_demux_get_uint16 (guint8 ** p_data, guint64 * p_size)
1962 {
1963   guint16 ret;
1964
1965   g_assert (*p_size >= 2);
1966   ret = GST_READ_UINT16_LE (*p_data);
1967   *p_data += sizeof (guint16);
1968   *p_size -= sizeof (guint16);
1969   return ret;
1970 }
1971
1972 static inline guint32
1973 gst_asf_demux_get_uint32 (guint8 ** p_data, guint64 * p_size)
1974 {
1975   guint32 ret;
1976
1977   g_assert (*p_size >= 4);
1978   ret = GST_READ_UINT32_LE (*p_data);
1979   *p_data += sizeof (guint32);
1980   *p_size -= sizeof (guint32);
1981   return ret;
1982 }
1983
1984 static inline guint64
1985 gst_asf_demux_get_uint64 (guint8 ** p_data, guint64 * p_size)
1986 {
1987   guint64 ret;
1988
1989   g_assert (*p_size >= 8);
1990   ret = GST_READ_UINT64_LE (*p_data);
1991   *p_data += sizeof (guint64);
1992   *p_size -= sizeof (guint64);
1993   return ret;
1994 }
1995
1996 static inline guint32
1997 gst_asf_demux_get_var_length (guint8 type, guint8 ** p_data, guint64 * p_size)
1998 {
1999   switch (type) {
2000     case 0:
2001       return 0;
2002
2003     case 1:
2004       g_assert (*p_size >= 1);
2005       return gst_asf_demux_get_uint8 (p_data, p_size);
2006
2007     case 2:
2008       g_assert (*p_size >= 2);
2009       return gst_asf_demux_get_uint16 (p_data, p_size);
2010
2011     case 3:
2012       g_assert (*p_size >= 4);
2013       return gst_asf_demux_get_uint32 (p_data, p_size);
2014
2015     default:
2016       g_assert_not_reached ();
2017       break;
2018   }
2019   return 0;
2020 }
2021
2022 static gboolean
2023 gst_asf_demux_get_buffer (GstBuffer ** p_buf, guint num_bytes_to_read,
2024     guint8 ** p_data, guint64 * p_size)
2025 {
2026   *p_buf = NULL;
2027
2028   if (*p_size < num_bytes_to_read)
2029     return FALSE;
2030
2031   *p_buf = gst_buffer_new_and_alloc (num_bytes_to_read);
2032   gst_buffer_fill (*p_buf, 0, *p_data, num_bytes_to_read);
2033
2034   *p_data += num_bytes_to_read;
2035   *p_size -= num_bytes_to_read;
2036
2037   return TRUE;
2038 }
2039
2040 static gboolean
2041 gst_asf_demux_get_bytes (guint8 ** p_buf, guint num_bytes_to_read,
2042     guint8 ** p_data, guint64 * p_size)
2043 {
2044   *p_buf = NULL;
2045
2046   if (*p_size < num_bytes_to_read)
2047     return FALSE;
2048
2049   *p_buf = g_memdup (*p_data, num_bytes_to_read);
2050   *p_data += num_bytes_to_read;
2051   *p_size -= num_bytes_to_read;
2052   return TRUE;
2053 }
2054
2055 static gboolean
2056 gst_asf_demux_get_string (gchar ** p_str, guint16 * p_strlen,
2057     guint8 ** p_data, guint64 * p_size)
2058 {
2059   guint16 s_length;
2060   guint8 *s;
2061
2062   *p_str = NULL;
2063
2064   if (*p_size < 2)
2065     return FALSE;
2066
2067   s_length = gst_asf_demux_get_uint16 (p_data, p_size);
2068
2069   if (p_strlen)
2070     *p_strlen = s_length;
2071
2072   if (s_length == 0) {
2073     GST_WARNING ("zero-length string");
2074     *p_str = g_strdup ("");
2075     return TRUE;
2076   }
2077
2078   if (!gst_asf_demux_get_bytes (&s, s_length, p_data, p_size))
2079     return FALSE;
2080
2081   g_assert (s != NULL);
2082
2083   /* just because They don't exist doesn't
2084    * mean They are not out to get you ... */
2085   if (s[s_length - 1] != '\0') {
2086     s = g_realloc (s, s_length + 1);
2087     s[s_length] = '\0';
2088   }
2089
2090   *p_str = (gchar *) s;
2091   return TRUE;
2092 }
2093
2094
2095 static void
2096 gst_asf_demux_get_guid (ASFGuid * guid, guint8 ** p_data, guint64 * p_size)
2097 {
2098   g_assert (*p_size >= 4 * sizeof (guint32));
2099
2100   guid->v1 = gst_asf_demux_get_uint32 (p_data, p_size);
2101   guid->v2 = gst_asf_demux_get_uint32 (p_data, p_size);
2102   guid->v3 = gst_asf_demux_get_uint32 (p_data, p_size);
2103   guid->v4 = gst_asf_demux_get_uint32 (p_data, p_size);
2104 }
2105
2106 static gboolean
2107 gst_asf_demux_get_stream_audio (asf_stream_audio * audio, guint8 ** p_data,
2108     guint64 * p_size)
2109 {
2110   if (*p_size < (2 + 2 + 4 + 4 + 2 + 2 + 2))
2111     return FALSE;
2112
2113   /* WAVEFORMATEX Structure */
2114   audio->codec_tag = gst_asf_demux_get_uint16 (p_data, p_size);
2115   audio->channels = gst_asf_demux_get_uint16 (p_data, p_size);
2116   audio->sample_rate = gst_asf_demux_get_uint32 (p_data, p_size);
2117   audio->byte_rate = gst_asf_demux_get_uint32 (p_data, p_size);
2118   audio->block_align = gst_asf_demux_get_uint16 (p_data, p_size);
2119   audio->word_size = gst_asf_demux_get_uint16 (p_data, p_size);
2120   /* Codec specific data size */
2121   audio->size = gst_asf_demux_get_uint16 (p_data, p_size);
2122   return TRUE;
2123 }
2124
2125 static gboolean
2126 gst_asf_demux_get_stream_video (asf_stream_video * video, guint8 ** p_data,
2127     guint64 * p_size)
2128 {
2129   if (*p_size < (4 + 4 + 1 + 2))
2130     return FALSE;
2131
2132   video->width = gst_asf_demux_get_uint32 (p_data, p_size);
2133   video->height = gst_asf_demux_get_uint32 (p_data, p_size);
2134   video->unknown = gst_asf_demux_get_uint8 (p_data, p_size);
2135   video->size = gst_asf_demux_get_uint16 (p_data, p_size);
2136   return TRUE;
2137 }
2138
2139 static gboolean
2140 gst_asf_demux_get_stream_video_format (asf_stream_video_format * fmt,
2141     guint8 ** p_data, guint64 * p_size)
2142 {
2143   if (*p_size < (4 + 4 + 4 + 2 + 2 + 4 + 4 + 4 + 4 + 4 + 4))
2144     return FALSE;
2145
2146   fmt->size = gst_asf_demux_get_uint32 (p_data, p_size);
2147   fmt->width = gst_asf_demux_get_uint32 (p_data, p_size);
2148   fmt->height = gst_asf_demux_get_uint32 (p_data, p_size);
2149   fmt->planes = gst_asf_demux_get_uint16 (p_data, p_size);
2150   fmt->depth = gst_asf_demux_get_uint16 (p_data, p_size);
2151   fmt->tag = gst_asf_demux_get_uint32 (p_data, p_size);
2152   fmt->image_size = gst_asf_demux_get_uint32 (p_data, p_size);
2153   fmt->xpels_meter = gst_asf_demux_get_uint32 (p_data, p_size);
2154   fmt->ypels_meter = gst_asf_demux_get_uint32 (p_data, p_size);
2155   fmt->num_colors = gst_asf_demux_get_uint32 (p_data, p_size);
2156   fmt->imp_colors = gst_asf_demux_get_uint32 (p_data, p_size);
2157   return TRUE;
2158 }
2159
2160 AsfStream *
2161 gst_asf_demux_get_stream (GstASFDemux * demux, guint16 id)
2162 {
2163   guint i;
2164
2165   for (i = 0; i < demux->num_streams; i++) {
2166     if (demux->stream[i].id == id)
2167       return &demux->stream[i];
2168   }
2169
2170   GST_WARNING ("Segment found for undefined stream: (%d)", id);
2171   return NULL;
2172 }
2173
2174 static void
2175 gst_asf_demux_setup_pad (GstASFDemux * demux, GstPad * src_pad,
2176     GstCaps * caps, guint16 id, gboolean is_video, GstTagList * tags)
2177 {
2178   AsfStream *stream;
2179
2180   gst_pad_use_fixed_caps (src_pad);
2181   gst_pad_set_caps (src_pad, caps);
2182
2183   gst_pad_set_event_function (src_pad,
2184       GST_DEBUG_FUNCPTR (gst_asf_demux_handle_src_event));
2185   gst_pad_set_query_function (src_pad,
2186       GST_DEBUG_FUNCPTR (gst_asf_demux_handle_src_query));
2187
2188   stream = &demux->stream[demux->num_streams];
2189   stream->caps = caps;
2190   stream->pad = src_pad;
2191   stream->id = id;
2192   stream->fps_known = !is_video;        /* bit hacky for audio */
2193   stream->is_video = is_video;
2194   stream->pending_tags = tags;
2195   stream->discont = TRUE;
2196   if (is_video) {
2197     GstStructure *st;
2198     gint par_x, par_y;
2199     st = gst_caps_get_structure (caps, 0);
2200     if (gst_structure_get_fraction (st, "pixel-aspect-ratio", &par_x, &par_y) &&
2201         par_x > 0 && par_y > 0) {
2202       GST_DEBUG ("PAR %d/%d", par_x, par_y);
2203       stream->par_x = par_x;
2204       stream->par_y = par_y;
2205     }
2206   }
2207
2208   stream->payloads = g_array_new (FALSE, FALSE, sizeof (AsfPayload));
2209
2210   GST_INFO ("Created pad %s for stream %u with caps %" GST_PTR_FORMAT,
2211       GST_PAD_NAME (src_pad), demux->num_streams, caps);
2212
2213   ++demux->num_streams;
2214
2215   stream->active = FALSE;
2216 }
2217
2218 static void
2219 gst_asf_demux_add_audio_stream (GstASFDemux * demux,
2220     asf_stream_audio * audio, guint16 id, guint8 ** p_data, guint64 * p_size)
2221 {
2222   GstTagList *tags = NULL;
2223   GstBuffer *extradata = NULL;
2224   GstPad *src_pad;
2225   GstCaps *caps;
2226   guint16 size_left = 0;
2227   gchar *codec_name = NULL;
2228   gchar *name = NULL;
2229
2230   size_left = audio->size;
2231
2232   /* Create the audio pad */
2233   name = g_strdup_printf ("audio_%u", demux->num_audio_streams);
2234
2235   src_pad = gst_pad_new_from_static_template (&audio_src_template, name);
2236   g_free (name);
2237
2238   /* Swallow up any left over data and set up the 
2239    * standard properties from the header info */
2240   if (size_left) {
2241     GST_INFO_OBJECT (demux, "Audio header contains %d bytes of "
2242         "codec specific data", size_left);
2243
2244     g_assert (size_left <= *p_size);
2245     gst_asf_demux_get_buffer (&extradata, size_left, p_data, p_size);
2246   }
2247
2248   /* asf_stream_audio is the same as gst_riff_strf_auds, but with an
2249    * additional two bytes indicating extradata. */
2250   /* FIXME: Handle the channel reorder map here */
2251   caps = gst_riff_create_audio_caps (audio->codec_tag, NULL,
2252       (gst_riff_strf_auds *) audio, extradata, NULL, &codec_name, NULL);
2253
2254   if (caps == NULL) {
2255     caps = gst_caps_new_simple ("audio/x-asf-unknown", "codec_id",
2256         G_TYPE_INT, (gint) audio->codec_tag, NULL);
2257   }
2258
2259   /* Informing about that audio format we just added */
2260   if (codec_name) {
2261     tags = gst_tag_list_new (GST_TAG_AUDIO_CODEC, codec_name, NULL);
2262     g_free (codec_name);
2263   }
2264
2265   if (extradata)
2266     gst_buffer_unref (extradata);
2267
2268   GST_INFO ("Adding audio stream #%u, id %u codec %u (0x%04x), tags=%"
2269       GST_PTR_FORMAT, demux->num_audio_streams, id, audio->codec_tag,
2270       audio->codec_tag, tags);
2271
2272   ++demux->num_audio_streams;
2273
2274   gst_asf_demux_setup_pad (demux, src_pad, caps, id, FALSE, tags);
2275 }
2276
2277 static void
2278 gst_asf_demux_add_video_stream (GstASFDemux * demux,
2279     asf_stream_video_format * video, guint16 id,
2280     guint8 ** p_data, guint64 * p_size)
2281 {
2282   GstTagList *tags = NULL;
2283   GstBuffer *extradata = NULL;
2284   GstPad *src_pad;
2285   GstCaps *caps;
2286   gchar *str;
2287   gchar *name = NULL;
2288   gchar *codec_name = NULL;
2289   gint size_left = video->size - 40;
2290
2291   /* Create the video pad */
2292   name = g_strdup_printf ("video_%u", demux->num_video_streams);
2293   src_pad = gst_pad_new_from_static_template (&video_src_template, name);
2294   g_free (name);
2295
2296   /* Now try some gstreamer formatted MIME types (from gst_avi_demux_strf_vids) */
2297   if (size_left) {
2298     GST_LOG ("Video header has %d bytes of codec specific data", size_left);
2299     g_assert (size_left <= *p_size);
2300     gst_asf_demux_get_buffer (&extradata, size_left, p_data, p_size);
2301   }
2302
2303   GST_DEBUG ("video codec %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (video->tag));
2304
2305   /* yes, asf_stream_video_format and gst_riff_strf_vids are the same */
2306   caps = gst_riff_create_video_caps (video->tag, NULL,
2307       (gst_riff_strf_vids *) video, extradata, NULL, &codec_name);
2308
2309   if (caps == NULL) {
2310     caps = gst_caps_new_simple ("video/x-asf-unknown", "fourcc",
2311         G_TYPE_UINT, video->tag, NULL);
2312   } else {
2313     GstStructure *s;
2314     gint ax, ay;
2315
2316     s = gst_asf_demux_get_metadata_for_stream (demux, id);
2317     if (gst_structure_get_int (s, "AspectRatioX", &ax) &&
2318         gst_structure_get_int (s, "AspectRatioY", &ay) && (ax > 0 && ay > 0)) {
2319       gst_caps_set_simple (caps, "pixel-aspect-ratio", GST_TYPE_FRACTION,
2320           ax, ay, NULL);
2321
2322     } else {
2323       guint ax, ay;
2324       /* retry with the global metadata */
2325       GST_DEBUG ("Retrying with global metadata %" GST_PTR_FORMAT,
2326           demux->global_metadata);
2327       s = demux->global_metadata;
2328       if (gst_structure_get_uint (s, "AspectRatioX", &ax) &&
2329           gst_structure_get_uint (s, "AspectRatioY", &ay)) {
2330         GST_DEBUG ("ax:%d, ay:%d", ax, ay);
2331         if (ax > 0 && ay > 0)
2332           gst_caps_set_simple (caps, "pixel-aspect-ratio", GST_TYPE_FRACTION,
2333               ax, ay, NULL);
2334       }
2335     }
2336     s = gst_caps_get_structure (caps, 0);
2337     gst_structure_remove_field (s, "framerate");
2338   }
2339
2340   /* add fourcc format to caps, some proprietary decoders seem to need it */
2341   str = g_strdup_printf ("%" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (video->tag));
2342   gst_caps_set_simple (caps, "format", G_TYPE_STRING, str, NULL);
2343   g_free (str);
2344
2345   if (codec_name) {
2346     tags = gst_tag_list_new (GST_TAG_VIDEO_CODEC, codec_name, NULL);
2347     g_free (codec_name);
2348   }
2349
2350   if (extradata)
2351     gst_buffer_unref (extradata);
2352
2353   GST_INFO ("Adding video stream #%u, id %u, codec %"
2354       GST_FOURCC_FORMAT " (0x%08x)", demux->num_video_streams, id,
2355       GST_FOURCC_ARGS (video->tag), video->tag);
2356
2357   ++demux->num_video_streams;
2358
2359   gst_asf_demux_setup_pad (demux, src_pad, caps, id, TRUE, tags);
2360 }
2361
2362 static void
2363 gst_asf_demux_activate_stream (GstASFDemux * demux, AsfStream * stream)
2364 {
2365   if (!stream->active) {
2366     GST_INFO_OBJECT (demux, "Activating stream %2u, pad %s, caps %"
2367         GST_PTR_FORMAT, stream->id, GST_PAD_NAME (stream->pad), stream->caps);
2368     gst_pad_set_active (stream->pad, TRUE);
2369     gst_pad_set_caps (stream->pad, stream->caps);
2370     gst_element_add_pad (GST_ELEMENT_CAST (demux), stream->pad);
2371     stream->active = TRUE;
2372   }
2373 }
2374
2375 static AsfStream *
2376 gst_asf_demux_parse_stream_object (GstASFDemux * demux, guint8 * data,
2377     guint64 size)
2378 {
2379   AsfCorrectionType correction_type;
2380   AsfStreamType stream_type;
2381   GstClockTime time_offset;
2382   gboolean is_encrypted G_GNUC_UNUSED;
2383   guint16 stream_id;
2384   guint16 flags;
2385   ASFGuid guid;
2386   guint stream_specific_size;
2387   guint type_specific_size G_GNUC_UNUSED;
2388   guint unknown G_GNUC_UNUSED;
2389
2390   /* Get the rest of the header's header */
2391   if (size < (16 + 16 + 8 + 4 + 4 + 2 + 4))
2392     goto not_enough_data;
2393
2394   gst_asf_demux_get_guid (&guid, &data, &size);
2395   stream_type = gst_asf_demux_identify_guid (asf_stream_guids, &guid);
2396
2397   gst_asf_demux_get_guid (&guid, &data, &size);
2398   correction_type = gst_asf_demux_identify_guid (asf_correction_guids, &guid);
2399
2400   time_offset = gst_asf_demux_get_uint64 (&data, &size) * 100;
2401
2402   type_specific_size = gst_asf_demux_get_uint32 (&data, &size);
2403   stream_specific_size = gst_asf_demux_get_uint32 (&data, &size);
2404
2405   flags = gst_asf_demux_get_uint16 (&data, &size);
2406   stream_id = flags & 0x7f;
2407   is_encrypted = ! !((flags & 0x8000) << 15);
2408   unknown = gst_asf_demux_get_uint32 (&data, &size);
2409
2410   GST_DEBUG_OBJECT (demux, "Found stream %u, time_offset=%" GST_TIME_FORMAT,
2411       stream_id, GST_TIME_ARGS (time_offset));
2412
2413   switch (stream_type) {
2414     case ASF_STREAM_AUDIO:{
2415       asf_stream_audio audio_object;
2416
2417       if (!gst_asf_demux_get_stream_audio (&audio_object, &data, &size))
2418         goto not_enough_data;
2419
2420       GST_INFO ("Object is an audio stream with %u bytes of additional data",
2421           audio_object.size);
2422
2423       gst_asf_demux_add_audio_stream (demux, &audio_object, stream_id,
2424           &data, &size);
2425
2426       switch (correction_type) {
2427         case ASF_CORRECTION_ON:{
2428           guint span, packet_size, chunk_size, data_size, silence_data;
2429
2430           GST_INFO ("Using error correction");
2431
2432           if (size < (1 + 2 + 2 + 2 + 1))
2433             goto not_enough_data;
2434
2435           span = gst_asf_demux_get_uint8 (&data, &size);
2436           packet_size = gst_asf_demux_get_uint16 (&data, &size);
2437           chunk_size = gst_asf_demux_get_uint16 (&data, &size);
2438           data_size = gst_asf_demux_get_uint16 (&data, &size);
2439           silence_data = gst_asf_demux_get_uint8 (&data, &size);
2440
2441           /* FIXME: shouldn't this be per-stream? */
2442           demux->span = span;
2443
2444           GST_DEBUG_OBJECT (demux, "Descrambling ps:%u cs:%u ds:%u s:%u sd:%u",
2445               packet_size, chunk_size, data_size, span, silence_data);
2446
2447           if (demux->span > 1) {
2448             if (chunk_size == 0 || ((packet_size / chunk_size) <= 1)) {
2449               /* Disable descrambling */
2450               demux->span = 0;
2451             } else {
2452               /* FIXME: this else branch was added for
2453                * weird_al_yankovic - the saga begins.asf */
2454               demux->ds_packet_size = packet_size;
2455               demux->ds_chunk_size = chunk_size;
2456             }
2457           } else {
2458             /* Descambling is enabled */
2459             demux->ds_packet_size = packet_size;
2460             demux->ds_chunk_size = chunk_size;
2461           }
2462 #if 0
2463           /* Now skip the rest of the silence data */
2464           if (data_size > 1)
2465             gst_bytestream_flush (demux->bs, data_size - 1);
2466 #else
2467           /* FIXME: CHECKME. And why -1? */
2468           if (data_size > 1) {
2469             if (!gst_asf_demux_skip_bytes (data_size - 1, &data, &size)) {
2470               goto not_enough_data;
2471             }
2472           }
2473 #endif
2474           break;
2475         }
2476         case ASF_CORRECTION_OFF:{
2477           GST_INFO ("Error correction off");
2478           if (!gst_asf_demux_skip_bytes (stream_specific_size, &data, &size))
2479             goto not_enough_data;
2480           break;
2481         }
2482         default:
2483           GST_ELEMENT_ERROR (demux, STREAM, DEMUX, (NULL),
2484               ("Audio stream using unknown error correction"));
2485           return NULL;
2486       }
2487
2488       break;
2489     }
2490
2491     case ASF_STREAM_VIDEO:{
2492       asf_stream_video_format video_format_object;
2493       asf_stream_video video_object;
2494       guint16 vsize;
2495
2496       if (!gst_asf_demux_get_stream_video (&video_object, &data, &size))
2497         goto not_enough_data;
2498
2499       vsize = video_object.size - 40;   /* Byte order gets offset by single byte */
2500
2501       GST_INFO ("object is a video stream with %u bytes of "
2502           "additional data", vsize);
2503
2504       if (!gst_asf_demux_get_stream_video_format (&video_format_object,
2505               &data, &size)) {
2506         goto not_enough_data;
2507       }
2508
2509       gst_asf_demux_add_video_stream (demux, &video_format_object, stream_id,
2510           &data, &size);
2511
2512       break;
2513     }
2514
2515     default:
2516       GST_WARNING_OBJECT (demux, "Unknown stream type for stream %u",
2517           stream_id);
2518       break;
2519   }
2520
2521   return gst_asf_demux_get_stream (demux, stream_id);
2522
2523 not_enough_data:
2524   {
2525     GST_WARNING_OBJECT (demux, "Unexpected end of data parsing stream object");
2526     /* we'll error out later if we found no streams */
2527     return NULL;
2528   }
2529 }
2530
2531 static const gchar *
2532 gst_asf_demux_get_gst_tag_from_tag_name (const gchar * name_utf8)
2533 {
2534   const struct
2535   {
2536     const gchar *asf_name;
2537     const gchar *gst_name;
2538   } tags[] = {
2539     {
2540     "WM/Genre", GST_TAG_GENRE}, {
2541     "WM/AlbumTitle", GST_TAG_ALBUM}, {
2542     "WM/AlbumArtist", GST_TAG_ARTIST}, {
2543     "WM/Picture", GST_TAG_IMAGE}, {
2544     "WM/Track", GST_TAG_TRACK_NUMBER}, {
2545     "WM/TrackNumber", GST_TAG_TRACK_NUMBER}, {
2546     "WM/Year", GST_TAG_DATE}
2547     /* { "WM/Composer", GST_TAG_COMPOSER } */
2548   };
2549   gsize out;
2550   guint i;
2551
2552   if (name_utf8 == NULL) {
2553     GST_WARNING ("Failed to convert name to UTF8, skipping");
2554     return NULL;
2555   }
2556
2557   out = strlen (name_utf8);
2558
2559   for (i = 0; i < G_N_ELEMENTS (tags); ++i) {
2560     if (strncmp (tags[i].asf_name, name_utf8, out) == 0) {
2561       GST_LOG ("map tagname '%s' -> '%s'", name_utf8, tags[i].gst_name);
2562       return tags[i].gst_name;
2563     }
2564   }
2565
2566   return NULL;
2567 }
2568
2569 /* gst_asf_demux_add_global_tags() takes ownership of taglist! */
2570 static void
2571 gst_asf_demux_add_global_tags (GstASFDemux * demux, GstTagList * taglist)
2572 {
2573   GstTagList *t;
2574
2575   GST_DEBUG_OBJECT (demux, "adding global tags: %" GST_PTR_FORMAT, taglist);
2576
2577   if (taglist == NULL)
2578     return;
2579
2580   if (gst_tag_list_is_empty (taglist)) {
2581     gst_tag_list_free (taglist);
2582     return;
2583   }
2584
2585   t = gst_tag_list_merge (demux->taglist, taglist, GST_TAG_MERGE_APPEND);
2586   if (demux->taglist)
2587     gst_tag_list_free (demux->taglist);
2588   gst_tag_list_free (taglist);
2589   demux->taglist = t;
2590   GST_LOG_OBJECT (demux, "global tags now: %" GST_PTR_FORMAT, demux->taglist);
2591 }
2592
2593 #define ASF_DEMUX_DATA_TYPE_UTF16LE_STRING  0
2594 #define ASF_DEMUX_DATA_TYPE_BYTE_ARRAY      1
2595 #define ASF_DEMUX_DATA_TYPE_DWORD           3
2596
2597 static void
2598 asf_demux_parse_picture_tag (GstTagList * tags, const guint8 * tag_data,
2599     guint tag_data_len)
2600 {
2601   GstByteReader r;
2602   const guint8 *img_data = NULL;
2603   guint32 img_data_len = 0;
2604   guint8 pic_type = 0;
2605
2606   gst_byte_reader_init (&r, tag_data, tag_data_len);
2607
2608   /* skip mime type string (we don't trust it and do our own typefinding),
2609    * and also skip the description string, since we don't use it */
2610   if (!gst_byte_reader_get_uint8 (&r, &pic_type) ||
2611       !gst_byte_reader_get_uint32_le (&r, &img_data_len) ||
2612       !gst_byte_reader_skip_string_utf16 (&r) ||
2613       !gst_byte_reader_skip_string_utf16 (&r) ||
2614       !gst_byte_reader_get_data (&r, img_data_len, &img_data)) {
2615     goto not_enough_data;
2616   }
2617
2618
2619   if (!gst_tag_list_add_id3_image (tags, img_data, img_data_len, pic_type))
2620     GST_DEBUG ("failed to add image extracted from WM/Picture tag to taglist");
2621
2622   return;
2623
2624 not_enough_data:
2625   {
2626     GST_DEBUG ("Failed to read WM/Picture tag: not enough data");
2627     GST_MEMDUMP ("WM/Picture data", tag_data, tag_data_len);
2628     return;
2629   }
2630 }
2631
2632 /* Extended Content Description Object */
2633 static GstFlowReturn
2634 gst_asf_demux_process_ext_content_desc (GstASFDemux * demux, guint8 * data,
2635     guint64 size)
2636 {
2637   /* Other known (and unused) 'text/unicode' metadata available :
2638    *
2639    *   WM/Lyrics =
2640    *   WM/MediaPrimaryClassID = {D1607DBC-E323-4BE2-86A1-48A42A28441E}
2641    *   WMFSDKVersion = 9.00.00.2980
2642    *   WMFSDKNeeded = 0.0.0.0000
2643    *   WM/UniqueFileIdentifier = AMGa_id=R    15334;AMGp_id=P     5149;AMGt_id=T  2324984
2644    *   WM/Publisher = 4AD
2645    *   WM/Provider = AMG
2646    *   WM/ProviderRating = 8
2647    *   WM/ProviderStyle = Rock (similar to WM/Genre)
2648    *   WM/GenreID (similar to WM/Genre)
2649    *   WM/TrackNumber (same as WM/Track but as a string)
2650    *
2651    * Other known (and unused) 'non-text' metadata available :
2652    *
2653    *   WM/EncodingTime
2654    *   WM/MCDI
2655    *   IsVBR
2656    *
2657    * We might want to read WM/TrackNumber and use atoi() if we don't have
2658    * WM/Track
2659    */
2660
2661   GstTagList *taglist;
2662   guint16 blockcount, i;
2663
2664   GST_INFO_OBJECT (demux, "object is an extended content description");
2665
2666   taglist = gst_tag_list_new_empty ();
2667
2668   /* Content Descriptor Count */
2669   if (size < 2)
2670     goto not_enough_data;
2671
2672   blockcount = gst_asf_demux_get_uint16 (&data, &size);
2673
2674   for (i = 1; i <= blockcount; ++i) {
2675     const gchar *gst_tag_name;
2676     guint16 datatype;
2677     guint16 value_len;
2678     guint16 name_len;
2679     GValue tag_value = { 0, };
2680     gsize in, out;
2681     gchar *name;
2682     gchar *name_utf8 = NULL;
2683     gchar *value;
2684
2685     /* Descriptor */
2686     if (!gst_asf_demux_get_string (&name, &name_len, &data, &size))
2687       goto not_enough_data;
2688
2689     if (size < 2) {
2690       g_free (name);
2691       goto not_enough_data;
2692     }
2693     /* Descriptor Value Data Type */
2694     datatype = gst_asf_demux_get_uint16 (&data, &size);
2695
2696     /* Descriptor Value (not really a string, but same thing reading-wise) */
2697     if (!gst_asf_demux_get_string (&value, &value_len, &data, &size)) {
2698       g_free (name);
2699       goto not_enough_data;
2700     }
2701
2702     name_utf8 =
2703         g_convert (name, name_len, "UTF-8", "UTF-16LE", &in, &out, NULL);
2704
2705     if (name_utf8 != NULL) {
2706       GST_DEBUG ("Found tag/metadata %s", name_utf8);
2707
2708       gst_tag_name = gst_asf_demux_get_gst_tag_from_tag_name (name_utf8);
2709       GST_DEBUG ("gst_tag_name %s", GST_STR_NULL (gst_tag_name));
2710
2711       switch (datatype) {
2712         case ASF_DEMUX_DATA_TYPE_UTF16LE_STRING:{
2713           gchar *value_utf8;
2714
2715           value_utf8 = g_convert (value, value_len, "UTF-8", "UTF-16LE",
2716               &in, &out, NULL);
2717
2718           /* get rid of tags with empty value */
2719           if (value_utf8 != NULL && *value_utf8 != '\0') {
2720             GST_DEBUG ("string value %s", value_utf8);
2721
2722             value_utf8[out] = '\0';
2723
2724             if (gst_tag_name != NULL) {
2725               if (strcmp (gst_tag_name, GST_TAG_DATE) == 0) {
2726                 guint year = atoi (value_utf8);
2727
2728                 if (year > 0) {
2729                   /* FIXME: really want a GDateTime with just the year field */
2730                   g_value_init (&tag_value, G_TYPE_DATE);
2731                   g_value_take_boxed (&tag_value, g_date_new_dmy (1, 1, year));
2732                 }
2733               } else if (strcmp (gst_tag_name, GST_TAG_GENRE) == 0) {
2734                 guint id3v1_genre_id;
2735                 const gchar *genre_str;
2736
2737                 if (sscanf (value_utf8, "(%u)", &id3v1_genre_id) == 1 &&
2738                     ((genre_str = gst_tag_id3_genre_get (id3v1_genre_id)))) {
2739                   GST_DEBUG ("Genre: %s -> %s", value_utf8, genre_str);
2740                   g_free (value_utf8);
2741                   value_utf8 = g_strdup (genre_str);
2742                 }
2743               } else {
2744                 GType tag_type;
2745
2746                 /* convert tag from string to other type if required */
2747                 tag_type = gst_tag_get_type (gst_tag_name);
2748                 g_value_init (&tag_value, tag_type);
2749                 if (!gst_value_deserialize (&tag_value, value_utf8)) {
2750                   GValue from_val = { 0, };
2751
2752                   g_value_init (&from_val, G_TYPE_STRING);
2753                   g_value_set_string (&from_val, value_utf8);
2754                   if (!g_value_transform (&from_val, &tag_value)) {
2755                     GST_WARNING_OBJECT (demux,
2756                         "Could not transform string tag to " "%s tag type %s",
2757                         gst_tag_name, g_type_name (tag_type));
2758                     g_value_unset (&tag_value);
2759                   }
2760                   g_value_unset (&from_val);
2761                 }
2762               }
2763             } else {
2764               /* metadata ! */
2765               GST_DEBUG ("Setting metadata");
2766               g_value_init (&tag_value, G_TYPE_STRING);
2767               g_value_set_string (&tag_value, value_utf8);
2768             }
2769           } else if (value_utf8 == NULL) {
2770             GST_WARNING ("Failed to convert string value to UTF8, skipping");
2771           } else {
2772             GST_DEBUG ("Skipping empty string value for %s",
2773                 GST_STR_NULL (gst_tag_name));
2774           }
2775           g_free (value_utf8);
2776           break;
2777         }
2778         case ASF_DEMUX_DATA_TYPE_BYTE_ARRAY:{
2779           if (gst_tag_name) {
2780             if (!g_str_equal (gst_tag_name, GST_TAG_IMAGE)) {
2781               GST_FIXME ("Unhandled byte array tag %s",
2782                   GST_STR_NULL (gst_tag_name));
2783               break;
2784             } else {
2785               asf_demux_parse_picture_tag (taglist, (guint8 *) value,
2786                   value_len);
2787             }
2788           }
2789           break;
2790         }
2791         case ASF_DEMUX_DATA_TYPE_DWORD:{
2792           guint uint_val = GST_READ_UINT32_LE (value);
2793
2794           /* this is the track number */
2795           g_value_init (&tag_value, G_TYPE_UINT);
2796
2797           /* WM/Track counts from 0 */
2798           if (!strcmp (name_utf8, "WM/Track"))
2799             ++uint_val;
2800
2801           g_value_set_uint (&tag_value, uint_val);
2802           break;
2803         }
2804         default:{
2805           GST_DEBUG ("Skipping tag %s of type %d", gst_tag_name, datatype);
2806           break;
2807         }
2808       }
2809
2810       if (G_IS_VALUE (&tag_value)) {
2811         if (gst_tag_name) {
2812           GstTagMergeMode merge_mode = GST_TAG_MERGE_APPEND;
2813
2814           /* WM/TrackNumber is more reliable than WM/Track, since the latter
2815            * is supposed to have a 0 base but is often wrongly written to start
2816            * from 1 as well, so prefer WM/TrackNumber when we have it: either
2817            * replace the value added earlier from WM/Track or put it first in
2818            * the list, so that it will get picked up by _get_uint() */
2819           if (strcmp (name_utf8, "WM/TrackNumber") == 0)
2820             merge_mode = GST_TAG_MERGE_REPLACE;
2821
2822           gst_tag_list_add_values (taglist, merge_mode, gst_tag_name,
2823               &tag_value, NULL);
2824         } else {
2825           GST_DEBUG ("Setting global metadata %s", name_utf8);
2826           gst_structure_set_value (demux->global_metadata, name_utf8,
2827               &tag_value);
2828         }
2829
2830         g_value_unset (&tag_value);
2831       }
2832     }
2833
2834     g_free (name);
2835     g_free (value);
2836     g_free (name_utf8);
2837   }
2838
2839   gst_asf_demux_add_global_tags (demux, taglist);
2840
2841   return GST_FLOW_OK;
2842
2843   /* Errors */
2844 not_enough_data:
2845   {
2846     GST_WARNING ("Unexpected end of data parsing ext content desc object");
2847     gst_tag_list_free (taglist);
2848     return GST_FLOW_OK;         /* not really fatal */
2849   }
2850 }
2851
2852 static GstStructure *
2853 gst_asf_demux_get_metadata_for_stream (GstASFDemux * demux, guint stream_num)
2854 {
2855   gchar sname[32];
2856   guint i;
2857
2858   g_snprintf (sname, sizeof (sname), "stream-%u", stream_num);
2859
2860   for (i = 0; i < gst_caps_get_size (demux->metadata); ++i) {
2861     GstStructure *s;
2862
2863     s = gst_caps_get_structure (demux->metadata, i);
2864     if (gst_structure_has_name (s, sname))
2865       return s;
2866   }
2867
2868   gst_caps_append_structure (demux->metadata, gst_structure_new_empty (sname));
2869
2870   /* try lookup again; demux->metadata took ownership of the structure, so we
2871    * can't really make any assumptions about what happened to it, so we can't
2872    * just return it directly after appending it */
2873   return gst_asf_demux_get_metadata_for_stream (demux, stream_num);
2874 }
2875
2876 static GstFlowReturn
2877 gst_asf_demux_process_metadata (GstASFDemux * demux, guint8 * data,
2878     guint64 size)
2879 {
2880   guint16 blockcount, i;
2881
2882   GST_INFO_OBJECT (demux, "object is a metadata object");
2883
2884   /* Content Descriptor Count */
2885   if (size < 2)
2886     goto not_enough_data;
2887
2888   blockcount = gst_asf_demux_get_uint16 (&data, &size);
2889
2890   for (i = 0; i < blockcount; ++i) {
2891     GstStructure *s;
2892     guint16 stream_num, name_len, data_type, lang_idx G_GNUC_UNUSED;
2893     guint32 data_len, ival;
2894     gchar *name_utf8;
2895
2896     if (size < (2 + 2 + 2 + 2 + 4))
2897       goto not_enough_data;
2898
2899     lang_idx = gst_asf_demux_get_uint16 (&data, &size);
2900     stream_num = gst_asf_demux_get_uint16 (&data, &size);
2901     name_len = gst_asf_demux_get_uint16 (&data, &size);
2902     data_type = gst_asf_demux_get_uint16 (&data, &size);
2903     data_len = gst_asf_demux_get_uint32 (&data, &size);
2904
2905     if (size < name_len + data_len)
2906       goto not_enough_data;
2907
2908     /* convert name to UTF-8 */
2909     name_utf8 = g_convert ((gchar *) data, name_len, "UTF-8", "UTF-16LE",
2910         NULL, NULL, NULL);
2911     gst_asf_demux_skip_bytes (name_len, &data, &size);
2912
2913     if (name_utf8 == NULL) {
2914       GST_WARNING ("Failed to convert value name to UTF8, skipping");
2915       gst_asf_demux_skip_bytes (data_len, &data, &size);
2916       continue;
2917     }
2918
2919     if (data_type != ASF_DEMUX_DATA_TYPE_DWORD) {
2920       gst_asf_demux_skip_bytes (data_len, &data, &size);
2921       g_free (name_utf8);
2922       continue;
2923     }
2924
2925     /* read DWORD */
2926     if (size < 4) {
2927       g_free (name_utf8);
2928       goto not_enough_data;
2929     }
2930
2931     ival = gst_asf_demux_get_uint32 (&data, &size);
2932
2933     /* skip anything else there may be, just in case */
2934     gst_asf_demux_skip_bytes (data_len - 4, &data, &size);
2935
2936     s = gst_asf_demux_get_metadata_for_stream (demux, stream_num);
2937     gst_structure_set (s, name_utf8, G_TYPE_INT, ival, NULL);
2938     g_free (name_utf8);
2939   }
2940
2941   GST_INFO_OBJECT (demux, "metadata = %" GST_PTR_FORMAT, demux->metadata);
2942   return GST_FLOW_OK;
2943
2944   /* Errors */
2945 not_enough_data:
2946   {
2947     GST_WARNING ("Unexpected end of data parsing metadata object");
2948     return GST_FLOW_OK;         /* not really fatal */
2949   }
2950 }
2951
2952 static GstFlowReturn
2953 gst_asf_demux_process_header (GstASFDemux * demux, guint8 * data, guint64 size)
2954 {
2955   GstFlowReturn ret = GST_FLOW_OK;
2956   guint32 i, num_objects;
2957   guint8 unknown G_GNUC_UNUSED;
2958
2959   /* Get the rest of the header's header */
2960   if (size < (4 + 1 + 1))
2961     goto not_enough_data;
2962
2963   num_objects = gst_asf_demux_get_uint32 (&data, &size);
2964   unknown = gst_asf_demux_get_uint8 (&data, &size);
2965   unknown = gst_asf_demux_get_uint8 (&data, &size);
2966
2967   GST_INFO_OBJECT (demux, "object is a header with %u parts", num_objects);
2968
2969   /* Loop through the header's objects, processing those */
2970   for (i = 0; i < num_objects; ++i) {
2971     GST_INFO_OBJECT (demux, "reading header part %u", i);
2972     ret = gst_asf_demux_process_object (demux, &data, &size);
2973     if (ret != GST_FLOW_OK) {
2974       GST_WARNING ("process_object returned %s", gst_asf_get_flow_name (ret));
2975       break;
2976     }
2977   }
2978
2979   return ret;
2980
2981 not_enough_data:
2982   {
2983     GST_ELEMENT_ERROR (demux, STREAM, DEMUX, (NULL),
2984         ("short read parsing HEADER object"));
2985     return GST_FLOW_ERROR;
2986   }
2987 }
2988
2989 static GstFlowReturn
2990 gst_asf_demux_process_file (GstASFDemux * demux, guint8 * data, guint64 size)
2991 {
2992   guint64 creation_time G_GNUC_UNUSED;
2993   guint64 file_size G_GNUC_UNUSED;
2994   guint64 send_time G_GNUC_UNUSED;
2995   guint64 packets_count, play_time, preroll;
2996   guint32 flags, min_pktsize, max_pktsize, min_bitrate G_GNUC_UNUSED;
2997
2998   if (size < (16 + 8 + 8 + 8 + 8 + 8 + 8 + 4 + 4 + 4 + 4))
2999     goto not_enough_data;
3000
3001   gst_asf_demux_skip_bytes (16, &data, &size);  /* skip GUID */
3002   file_size = gst_asf_demux_get_uint64 (&data, &size);
3003   creation_time = gst_asf_demux_get_uint64 (&data, &size);
3004   packets_count = gst_asf_demux_get_uint64 (&data, &size);
3005   play_time = gst_asf_demux_get_uint64 (&data, &size);
3006   send_time = gst_asf_demux_get_uint64 (&data, &size);
3007   preroll = gst_asf_demux_get_uint64 (&data, &size);
3008   flags = gst_asf_demux_get_uint32 (&data, &size);
3009   min_pktsize = gst_asf_demux_get_uint32 (&data, &size);
3010   max_pktsize = gst_asf_demux_get_uint32 (&data, &size);
3011   min_bitrate = gst_asf_demux_get_uint32 (&data, &size);
3012
3013   demux->broadcast = ! !(flags & 0x01);
3014   demux->seekable = ! !(flags & 0x02);
3015
3016   GST_DEBUG_OBJECT (demux, "min_pktsize = %u", min_pktsize);
3017   GST_DEBUG_OBJECT (demux, "flags::broadcast = %d", demux->broadcast);
3018   GST_DEBUG_OBJECT (demux, "flags::seekable  = %d", demux->seekable);
3019
3020   if (demux->broadcast) {
3021     /* these fields are invalid if the broadcast flag is set */
3022     play_time = 0;
3023     file_size = 0;
3024   }
3025
3026   if (min_pktsize != max_pktsize)
3027     goto non_fixed_packet_size;
3028
3029   demux->packet_size = max_pktsize;
3030
3031   /* FIXME: do we need send_time as well? what is it? */
3032   if ((play_time * 100) >= (preroll * GST_MSECOND))
3033     demux->play_time = (play_time * 100) - (preroll * GST_MSECOND);
3034   else
3035     demux->play_time = 0;
3036
3037   demux->preroll = preroll * GST_MSECOND;
3038
3039   /* initial latency */
3040   demux->latency = demux->preroll;
3041
3042   if (demux->play_time == 0)
3043     demux->seekable = FALSE;
3044
3045   GST_DEBUG_OBJECT (demux, "play_time %" GST_TIME_FORMAT,
3046       GST_TIME_ARGS (demux->play_time));
3047   GST_DEBUG_OBJECT (demux, "preroll   %" GST_TIME_FORMAT,
3048       GST_TIME_ARGS (demux->preroll));
3049
3050   if (demux->play_time > 0) {
3051     demux->segment.duration = demux->play_time;
3052   }
3053
3054   GST_INFO ("object is a file with %" G_GUINT64_FORMAT " data packets",
3055       packets_count);
3056   GST_INFO ("preroll = %" G_GUINT64_FORMAT, demux->preroll);
3057
3058   return GST_FLOW_OK;
3059
3060 /* ERRORS */
3061 non_fixed_packet_size:
3062   {
3063     GST_ELEMENT_ERROR (demux, STREAM, DEMUX, (NULL),
3064         ("packet size must be fixed"));
3065     return GST_FLOW_ERROR;
3066   }
3067 not_enough_data:
3068   {
3069     GST_ELEMENT_ERROR (demux, STREAM, DEMUX, (NULL),
3070         ("short read parsing FILE object"));
3071     return GST_FLOW_ERROR;
3072   }
3073 }
3074
3075 /* Content Description Object */
3076 static GstFlowReturn
3077 gst_asf_demux_process_comment (GstASFDemux * demux, guint8 * data, guint64 size)
3078 {
3079   struct
3080   {
3081     const gchar *gst_tag;
3082     guint16 val_length;
3083     gchar *val_utf8;
3084   } tags[5] = {
3085     {
3086     GST_TAG_TITLE, 0, NULL}, {
3087     GST_TAG_ARTIST, 0, NULL}, {
3088     GST_TAG_COPYRIGHT, 0, NULL}, {
3089     GST_TAG_DESCRIPTION, 0, NULL}, {
3090     GST_TAG_COMMENT, 0, NULL}
3091   };
3092   GstTagList *taglist;
3093   GValue value = { 0 };
3094   gsize in, out;
3095   gint i = -1;
3096
3097   GST_INFO_OBJECT (demux, "object is a comment");
3098
3099   if (size < (2 + 2 + 2 + 2 + 2))
3100     goto not_enough_data;
3101
3102   tags[0].val_length = gst_asf_demux_get_uint16 (&data, &size);
3103   tags[1].val_length = gst_asf_demux_get_uint16 (&data, &size);
3104   tags[2].val_length = gst_asf_demux_get_uint16 (&data, &size);
3105   tags[3].val_length = gst_asf_demux_get_uint16 (&data, &size);
3106   tags[4].val_length = gst_asf_demux_get_uint16 (&data, &size);
3107
3108   GST_DEBUG_OBJECT (demux, "Comment lengths: title=%d author=%d copyright=%d "
3109       "description=%d rating=%d", tags[0].val_length, tags[1].val_length,
3110       tags[2].val_length, tags[3].val_length, tags[4].val_length);
3111
3112   for (i = 0; i < G_N_ELEMENTS (tags); ++i) {
3113     if (size < tags[i].val_length)
3114       goto not_enough_data;
3115
3116     /* might be just '/0', '/0'... */
3117     if (tags[i].val_length > 2 && tags[i].val_length % 2 == 0) {
3118       /* convert to UTF-8 */
3119       tags[i].val_utf8 = g_convert ((gchar *) data, tags[i].val_length,
3120           "UTF-8", "UTF-16LE", &in, &out, NULL);
3121     }
3122     gst_asf_demux_skip_bytes (tags[i].val_length, &data, &size);
3123   }
3124
3125   /* parse metadata into taglist */
3126   taglist = gst_tag_list_new_empty ();
3127   g_value_init (&value, G_TYPE_STRING);
3128   for (i = 0; i < G_N_ELEMENTS (tags); ++i) {
3129     if (tags[i].val_utf8 && strlen (tags[i].val_utf8) > 0 && tags[i].gst_tag) {
3130       g_value_set_string (&value, tags[i].val_utf8);
3131       gst_tag_list_add_values (taglist, GST_TAG_MERGE_APPEND,
3132           tags[i].gst_tag, &value, NULL);
3133     }
3134   }
3135   g_value_unset (&value);
3136
3137   gst_asf_demux_add_global_tags (demux, taglist);
3138
3139   for (i = 0; i < G_N_ELEMENTS (tags); ++i)
3140     g_free (tags[i].val_utf8);
3141
3142   return GST_FLOW_OK;
3143
3144 not_enough_data:
3145   {
3146     GST_WARNING_OBJECT (demux, "unexpectedly short of data while processing "
3147         "comment tag section %d, skipping comment object", i);
3148     for (i = 0; i < G_N_ELEMENTS (tags); i++)
3149       g_free (tags[i].val_utf8);
3150     return GST_FLOW_OK;         /* not really fatal */
3151   }
3152 }
3153
3154 static GstFlowReturn
3155 gst_asf_demux_process_bitrate_props_object (GstASFDemux * demux, guint8 * data,
3156     guint64 size)
3157 {
3158   guint16 num_streams, i;
3159   AsfStream *stream;
3160
3161   if (size < 2)
3162     goto not_enough_data;
3163
3164   num_streams = gst_asf_demux_get_uint16 (&data, &size);
3165
3166   GST_INFO ("object is a bitrate properties object with %u streams",
3167       num_streams);
3168
3169   if (size < (num_streams * (2 + 4)))
3170     goto not_enough_data;
3171
3172   for (i = 0; i < num_streams; ++i) {
3173     guint32 bitrate;
3174     guint16 stream_id;
3175
3176     stream_id = gst_asf_demux_get_uint16 (&data, &size);
3177     bitrate = gst_asf_demux_get_uint32 (&data, &size);
3178
3179     if (stream_id < GST_ASF_DEMUX_NUM_STREAM_IDS) {
3180       GST_DEBUG_OBJECT (demux, "bitrate of stream %u = %u", stream_id, bitrate);
3181       stream = gst_asf_demux_get_stream (demux, stream_id);
3182       if (stream) {
3183         if (stream->pending_tags == NULL) {
3184           stream->pending_tags =
3185               gst_tag_list_new (GST_TAG_BITRATE, bitrate, NULL);
3186         }
3187       } else {
3188         GST_WARNING_OBJECT (demux, "Stream id %u wasn't found", stream_id);
3189       }
3190     } else {
3191       GST_WARNING ("stream id %u is too large", stream_id);
3192     }
3193   }
3194
3195   return GST_FLOW_OK;
3196
3197 not_enough_data:
3198   {
3199     GST_WARNING_OBJECT (demux, "short read parsing bitrate props object!");
3200     return GST_FLOW_OK;         /* not really fatal */
3201   }
3202 }
3203
3204 static GstFlowReturn
3205 gst_asf_demux_process_header_ext (GstASFDemux * demux, guint8 * data,
3206     guint64 size)
3207 {
3208   GstFlowReturn ret = GST_FLOW_OK;
3209   guint64 hdr_size;
3210
3211   /* Get the rest of the header's header */
3212   if (size < (16 + 2 + 4))
3213     goto not_enough_data;
3214
3215   /* skip GUID and two other bytes */
3216   gst_asf_demux_skip_bytes (16 + 2, &data, &size);
3217   hdr_size = gst_asf_demux_get_uint32 (&data, &size);
3218
3219   GST_INFO ("extended header object with a size of %u bytes", (guint) size);
3220
3221   /* FIXME: does data_size include the rest of the header that we have read? */
3222   if (hdr_size > size)
3223     goto not_enough_data;
3224
3225   while (hdr_size > 0) {
3226     ret = gst_asf_demux_process_object (demux, &data, &hdr_size);
3227     if (ret != GST_FLOW_OK)
3228       break;
3229   }
3230
3231   return ret;
3232
3233 not_enough_data:
3234   {
3235     GST_ELEMENT_ERROR (demux, STREAM, DEMUX, (NULL),
3236         ("short read parsing extended header object"));
3237     return GST_FLOW_ERROR;
3238   }
3239 }
3240
3241 static GstFlowReturn
3242 gst_asf_demux_process_language_list (GstASFDemux * demux, guint8 * data,
3243     guint64 size)
3244 {
3245   guint i;
3246
3247   if (size < 2)
3248     goto not_enough_data;
3249
3250   if (demux->languages) {
3251     GST_WARNING ("More than one LANGUAGE_LIST object in stream");
3252     g_strfreev (demux->languages);
3253     demux->languages = NULL;
3254     demux->num_languages = 0;
3255   }
3256
3257   demux->num_languages = gst_asf_demux_get_uint16 (&data, &size);
3258   GST_LOG ("%u languages:", demux->num_languages);
3259
3260   demux->languages = g_new0 (gchar *, demux->num_languages + 1);
3261   for (i = 0; i < demux->num_languages; ++i) {
3262     guint8 len, *lang_data = NULL;
3263
3264     if (size < 1)
3265       goto not_enough_data;
3266     len = gst_asf_demux_get_uint8 (&data, &size);
3267     if (gst_asf_demux_get_bytes (&lang_data, len, &data, &size)) {
3268       gchar *utf8;
3269
3270       utf8 = g_convert ((gchar *) lang_data, len, "UTF-8", "UTF-16LE", NULL,
3271           NULL, NULL);
3272
3273       /* truncate "en-us" etc. to just "en" */
3274       if (utf8 && strlen (utf8) >= 5 && (utf8[2] == '-' || utf8[2] == '_')) {
3275         utf8[2] = '\0';
3276       }
3277       GST_DEBUG ("[%u] %s", i, GST_STR_NULL (utf8));
3278       demux->languages[i] = utf8;
3279       g_free (lang_data);
3280     } else {
3281       goto not_enough_data;
3282     }
3283   }
3284
3285   return GST_FLOW_OK;
3286
3287 not_enough_data:
3288   {
3289     GST_WARNING_OBJECT (demux, "short read parsing language list object!");
3290     g_free (demux->languages);
3291     demux->languages = NULL;
3292     return GST_FLOW_OK;         /* not fatal */
3293   }
3294 }
3295
3296 static GstFlowReturn
3297 gst_asf_demux_process_simple_index (GstASFDemux * demux, guint8 * data,
3298     guint64 size)
3299 {
3300   GstClockTime interval;
3301   guint32 count, i;
3302
3303   if (size < (16 + 8 + 4 + 4))
3304     goto not_enough_data;
3305
3306   /* skip file id */
3307   gst_asf_demux_skip_bytes (16, &data, &size);
3308   interval = gst_asf_demux_get_uint64 (&data, &size) * (GstClockTime) 100;
3309   gst_asf_demux_skip_bytes (4, &data, &size);
3310   count = gst_asf_demux_get_uint32 (&data, &size);
3311   if (count > 0) {
3312     demux->sidx_interval = interval;
3313     demux->sidx_num_entries = count;
3314     g_free (demux->sidx_entries);
3315     demux->sidx_entries = g_new0 (AsfSimpleIndexEntry, count);
3316
3317     for (i = 0; i < count; ++i) {
3318       if (G_UNLIKELY (size <= 6))
3319         break;
3320       demux->sidx_entries[i].packet = gst_asf_demux_get_uint32 (&data, &size);
3321       demux->sidx_entries[i].count = gst_asf_demux_get_uint16 (&data, &size);
3322       GST_LOG_OBJECT (demux, "%" GST_TIME_FORMAT " = packet %4u  count : %2d",
3323           GST_TIME_ARGS (i * interval), demux->sidx_entries[i].packet,
3324           demux->sidx_entries[i].count);
3325     }
3326   } else {
3327     GST_DEBUG_OBJECT (demux, "simple index object with 0 entries");
3328   }
3329
3330   return GST_FLOW_OK;
3331
3332 not_enough_data:
3333   {
3334     GST_WARNING_OBJECT (demux, "short read parsing simple index object!");
3335     return GST_FLOW_OK;         /* not fatal */
3336   }
3337 }
3338
3339 static GstFlowReturn
3340 gst_asf_demux_process_advanced_mutual_exclusion (GstASFDemux * demux,
3341     guint8 * data, guint64 size)
3342 {
3343   ASFGuid guid;
3344   guint16 num, i;
3345   guint8 *mes;
3346
3347   if (size < 16 + 2 + (2 * 2))
3348     goto not_enough_data;
3349
3350   gst_asf_demux_get_guid (&guid, &data, &size);
3351   num = gst_asf_demux_get_uint16 (&data, &size);
3352
3353   if (num < 2) {
3354     GST_WARNING_OBJECT (demux, "nonsensical mutually exclusive streams count");
3355     return GST_FLOW_OK;
3356   }
3357
3358   if (size < (num * sizeof (guint16)))
3359     goto not_enough_data;
3360
3361   /* read mutually exclusive stream numbers */
3362   mes = g_new (guint8, num + 1);
3363   for (i = 0; i < num; ++i) {
3364     mes[i] = gst_asf_demux_get_uint16 (&data, &size) & 0x7f;
3365     GST_LOG_OBJECT (demux, "mutually exclusive: stream #%d", mes[i]);
3366   }
3367
3368   /* add terminator so we can easily get the count or know when to stop */
3369   mes[i] = (guint8) - 1;
3370
3371   demux->mut_ex_streams = g_slist_append (demux->mut_ex_streams, mes);
3372
3373   return GST_FLOW_OK;
3374
3375   /* Errors */
3376 not_enough_data:
3377   {
3378     GST_WARNING_OBJECT (demux, "short read parsing advanced mutual exclusion");
3379     return GST_FLOW_OK;         /* not absolutely fatal */
3380   }
3381 }
3382
3383 static GstFlowReturn
3384 gst_asf_demux_process_ext_stream_props (GstASFDemux * demux, guint8 * data,
3385     guint64 size)
3386 {
3387   AsfStreamExtProps esp;
3388   AsfStream *stream = NULL;
3389   AsfObject stream_obj;
3390   guint16 stream_name_count;
3391   guint16 num_payload_ext;
3392   guint64 len;
3393   guint8 *stream_obj_data = NULL;
3394   guint8 *data_start;
3395   guint obj_size;
3396   guint i, stream_num;
3397
3398   data_start = data;
3399   obj_size = (guint) size;
3400
3401   if (size < 64)
3402     goto not_enough_data;
3403
3404   esp.valid = TRUE;
3405   esp.start_time = gst_asf_demux_get_uint64 (&data, &size) * GST_MSECOND;
3406   esp.end_time = gst_asf_demux_get_uint64 (&data, &size) * GST_MSECOND;
3407   esp.data_bitrate = gst_asf_demux_get_uint32 (&data, &size);
3408   esp.buffer_size = gst_asf_demux_get_uint32 (&data, &size);
3409   esp.intial_buf_fullness = gst_asf_demux_get_uint32 (&data, &size);
3410   esp.data_bitrate2 = gst_asf_demux_get_uint32 (&data, &size);
3411   esp.buffer_size2 = gst_asf_demux_get_uint32 (&data, &size);
3412   esp.intial_buf_fullness2 = gst_asf_demux_get_uint32 (&data, &size);
3413   esp.max_obj_size = gst_asf_demux_get_uint32 (&data, &size);
3414   esp.flags = gst_asf_demux_get_uint32 (&data, &size);
3415   stream_num = gst_asf_demux_get_uint16 (&data, &size);
3416   esp.lang_idx = gst_asf_demux_get_uint16 (&data, &size);
3417   esp.avg_time_per_frame = gst_asf_demux_get_uint64 (&data, &size);
3418   stream_name_count = gst_asf_demux_get_uint16 (&data, &size);
3419   num_payload_ext = gst_asf_demux_get_uint16 (&data, &size);
3420
3421   GST_INFO ("start_time             = %" GST_TIME_FORMAT,
3422       GST_TIME_ARGS (esp.start_time));
3423   GST_INFO ("end_time               = %" GST_TIME_FORMAT,
3424       GST_TIME_ARGS (esp.end_time));
3425   GST_INFO ("flags                  = %08x", esp.flags);
3426   GST_INFO ("average time per frame = %" GST_TIME_FORMAT,
3427       GST_TIME_ARGS (esp.avg_time_per_frame * 100));
3428   GST_INFO ("stream number          = %u", stream_num);
3429   GST_INFO ("stream language ID idx = %u (%s)", esp.lang_idx,
3430       (esp.lang_idx < demux->num_languages) ?
3431       GST_STR_NULL (demux->languages[esp.lang_idx]) : "??");
3432   GST_INFO ("stream name count      = %u", stream_name_count);
3433
3434   /* read stream names */
3435   for (i = 0; i < stream_name_count; ++i) {
3436     guint16 stream_lang_idx G_GNUC_UNUSED;
3437     gchar *stream_name = NULL;
3438
3439     if (size < 2)
3440       goto not_enough_data;
3441     stream_lang_idx = gst_asf_demux_get_uint16 (&data, &size);
3442     if (!gst_asf_demux_get_string (&stream_name, NULL, &data, &size))
3443       goto not_enough_data;
3444     GST_INFO ("stream name %d: %s", i, GST_STR_NULL (stream_name));
3445     g_free (stream_name);       /* TODO: store names in struct */
3446   }
3447
3448   /* read payload extension systems stuff */
3449   GST_LOG ("payload extension systems count = %u", num_payload_ext);
3450
3451   if (num_payload_ext > 0)
3452     esp.payload_extensions = g_new0 (AsfPayloadExtension, num_payload_ext + 1);
3453   else
3454     esp.payload_extensions = NULL;
3455
3456   for (i = 0; i < num_payload_ext; ++i) {
3457     AsfPayloadExtension ext;
3458     ASFGuid ext_guid;
3459     guint32 sys_info_len;
3460
3461     if (size < 16 + 2 + 4)
3462       goto not_enough_data;
3463
3464     gst_asf_demux_get_guid (&ext_guid, &data, &size);
3465     ext.id = gst_asf_demux_identify_guid (asf_payload_ext_guids, &ext_guid);
3466     ext.len = gst_asf_demux_get_uint16 (&data, &size);
3467
3468     sys_info_len = gst_asf_demux_get_uint32 (&data, &size);
3469     GST_LOG ("payload systems info len = %u", sys_info_len);
3470     if (!gst_asf_demux_skip_bytes (sys_info_len, &data, &size))
3471       goto not_enough_data;
3472
3473     esp.payload_extensions[i] = ext;
3474   }
3475
3476   GST_LOG ("bytes read: %u/%u", (guint) (data - data_start), obj_size);
3477
3478   /* there might be an optional STREAM_INFO object here now; if not, we
3479    * should have parsed the corresponding stream info object already (since
3480    * we are parsing the extended stream properties objects delayed) */
3481   if (size == 0) {
3482     stream = gst_asf_demux_get_stream (demux, stream_num);
3483     goto done;
3484   }
3485
3486   /* get size of the stream object */
3487   if (!asf_demux_peek_object (demux, data, size, &stream_obj, TRUE))
3488     goto not_enough_data;
3489
3490   if (stream_obj.id != ASF_OBJ_STREAM)
3491     goto expected_stream_object;
3492
3493   if (stream_obj.size < ASF_OBJECT_HEADER_SIZE ||
3494       stream_obj.size > (10 * 1024 * 1024))
3495     goto not_enough_data;
3496
3497   gst_asf_demux_skip_bytes (ASF_OBJECT_HEADER_SIZE, &data, &size);
3498
3499   /* process this stream object later after all the other 'normal' ones
3500    * have been processed (since the others are more important/non-hidden) */
3501   len = stream_obj.size - ASF_OBJECT_HEADER_SIZE;
3502   if (!gst_asf_demux_get_bytes (&stream_obj_data, len, &data, &size))
3503     goto not_enough_data;
3504
3505   /* parse stream object */
3506   stream = gst_asf_demux_parse_stream_object (demux, stream_obj_data, len);
3507   g_free (stream_obj_data);
3508
3509 done:
3510
3511   if (stream) {
3512     stream->ext_props = esp;
3513
3514     /* try to set the framerate */
3515     if (stream->is_video && stream->caps) {
3516       GValue framerate = { 0 };
3517       GstStructure *s;
3518       gint num, denom;
3519
3520       g_value_init (&framerate, GST_TYPE_FRACTION);
3521
3522       num = GST_SECOND / 100;
3523       denom = esp.avg_time_per_frame;
3524       if (denom == 0) {
3525         /* avoid division by 0, assume 25/1 framerate */
3526         denom = GST_SECOND / 2500;
3527       }
3528
3529       gst_value_set_fraction (&framerate, num, denom);
3530
3531       stream->caps = gst_caps_make_writable (stream->caps);
3532       s = gst_caps_get_structure (stream->caps, 0);
3533       gst_structure_set_value (s, "framerate", &framerate);
3534       g_value_unset (&framerate);
3535       GST_DEBUG_OBJECT (demux, "setting framerate of %d/%d = %f",
3536           num, denom, ((gdouble) num) / denom);
3537     }
3538
3539     /* add language info now if we have it */
3540     if (stream->ext_props.lang_idx < demux->num_languages) {
3541       if (stream->pending_tags == NULL)
3542         stream->pending_tags = gst_tag_list_new_empty ();
3543       GST_LOG_OBJECT (demux, "stream %u has language '%s'", stream->id,
3544           demux->languages[stream->ext_props.lang_idx]);
3545       gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_APPEND,
3546           GST_TAG_LANGUAGE_CODE, demux->languages[stream->ext_props.lang_idx],
3547           NULL);
3548     }
3549   } else {
3550     GST_WARNING_OBJECT (demux, "Ext. stream properties for unknown stream");
3551   }
3552
3553   return GST_FLOW_OK;
3554
3555   /* Errors */
3556 not_enough_data:
3557   {
3558     GST_WARNING_OBJECT (demux, "short read parsing ext stream props object!");
3559     return GST_FLOW_OK;         /* not absolutely fatal */
3560   }
3561 expected_stream_object:
3562   {
3563     GST_WARNING_OBJECT (demux, "error parsing extended stream properties "
3564         "object: expected embedded stream object, but got %s object instead!",
3565         gst_asf_get_guid_nick (asf_object_guids, stream_obj.id));
3566     return GST_FLOW_OK;         /* not absolutely fatal */
3567   }
3568 }
3569
3570 static const gchar *
3571 gst_asf_demux_push_obj (GstASFDemux * demux, guint32 obj_id)
3572 {
3573   const gchar *nick;
3574
3575   nick = gst_asf_get_guid_nick (asf_object_guids, obj_id);
3576   if (g_str_has_prefix (nick, "ASF_OBJ_"))
3577     nick += strlen ("ASF_OBJ_");
3578
3579   if (demux->objpath == NULL) {
3580     demux->objpath = g_strdup (nick);
3581   } else {
3582     gchar *newpath;
3583
3584     newpath = g_strdup_printf ("%s/%s", demux->objpath, nick);
3585     g_free (demux->objpath);
3586     demux->objpath = newpath;
3587   }
3588
3589   return (const gchar *) demux->objpath;
3590 }
3591
3592 static void
3593 gst_asf_demux_pop_obj (GstASFDemux * demux)
3594 {
3595   gchar *s;
3596
3597   if ((s = g_strrstr (demux->objpath, "/"))) {
3598     *s = '\0';
3599   } else {
3600     g_free (demux->objpath);
3601     demux->objpath = NULL;
3602   }
3603 }
3604
3605 static void
3606 gst_asf_demux_process_queued_extended_stream_objects (GstASFDemux * demux)
3607 {
3608   GSList *l;
3609   guint i;
3610
3611   /* Parse the queued extended stream property objects and add the info
3612    * to the existing streams or add the new embedded streams, but without
3613    * activating them yet */
3614   GST_LOG_OBJECT (demux, "%u queued extended stream properties objects",
3615       g_slist_length (demux->ext_stream_props));
3616
3617   for (l = demux->ext_stream_props, i = 0; l != NULL; l = l->next, ++i) {
3618     GstBuffer *buf = GST_BUFFER (l->data);
3619     GstMapInfo map;
3620
3621     gst_buffer_map (buf, &map, GST_MAP_READ);
3622
3623     GST_LOG_OBJECT (demux, "parsing ext. stream properties object #%u", i);
3624     gst_asf_demux_process_ext_stream_props (demux, map.data, map.size);
3625     gst_buffer_unmap (buf, &map);
3626     gst_buffer_unref (buf);
3627   }
3628   g_slist_free (demux->ext_stream_props);
3629   demux->ext_stream_props = NULL;
3630 }
3631
3632 #if 0
3633 static void
3634 gst_asf_demux_activate_ext_props_streams (GstASFDemux * demux)
3635 {
3636   guint i, j;
3637
3638   for (i = 0; i < demux->num_streams; ++i) {
3639     AsfStream *stream;
3640     gboolean is_hidden;
3641     GSList *x;
3642
3643     stream = &demux->stream[i];
3644
3645     GST_LOG_OBJECT (demux, "checking  stream %2u", stream->id);
3646
3647     if (stream->active) {
3648       GST_LOG_OBJECT (demux, "stream %2u is already activated", stream->id);
3649       continue;
3650     }
3651
3652     is_hidden = FALSE;
3653     for (x = demux->mut_ex_streams; x != NULL; x = x->next) {
3654       guint8 *mes;
3655
3656       /* check for each mutual exclusion whether it affects this stream */
3657       for (mes = (guint8 *) x->data; mes != NULL && *mes != 0xff; ++mes) {
3658         if (*mes == stream->id) {
3659           /* if yes, check if we've already added streams that are mutually
3660            * exclusive with the stream we're about to add */
3661           for (mes = (guint8 *) x->data; mes != NULL && *mes != 0xff; ++mes) {
3662             for (j = 0; j < demux->num_streams; ++j) {
3663               /* if the broadcast flag is set, assume the hidden streams aren't
3664                * actually streamed and hide them (or playbin won't work right),
3665                * otherwise assume their data is available */
3666               if (demux->stream[j].id == *mes && demux->broadcast) {
3667                 is_hidden = TRUE;
3668                 GST_LOG_OBJECT (demux, "broadcast stream ID %d to be added is "
3669                     "mutually exclusive with already existing stream ID %d, "
3670                     "hiding stream", stream->id, demux->stream[j].id);
3671                 goto next;
3672               }
3673             }
3674           }
3675           break;
3676         }
3677       }
3678     }
3679
3680   next:
3681
3682     /* FIXME: we should do stream activation based on preroll data in
3683      * streaming mode too */
3684     if (demux->streaming && !is_hidden)
3685       gst_asf_demux_activate_stream (demux, stream);
3686   }
3687 }
3688 #endif
3689
3690 static GstFlowReturn
3691 gst_asf_demux_process_object (GstASFDemux * demux, guint8 ** p_data,
3692     guint64 * p_size)
3693 {
3694   GstFlowReturn ret = GST_FLOW_OK;
3695   AsfObject obj;
3696   guint64 obj_data_size;
3697
3698   if (*p_size < ASF_OBJECT_HEADER_SIZE)
3699     return ASF_FLOW_NEED_MORE_DATA;
3700
3701   asf_demux_peek_object (demux, *p_data, ASF_OBJECT_HEADER_SIZE, &obj, TRUE);
3702   gst_asf_demux_skip_bytes (ASF_OBJECT_HEADER_SIZE, p_data, p_size);
3703
3704   obj_data_size = obj.size - ASF_OBJECT_HEADER_SIZE;
3705
3706   if (*p_size < obj_data_size)
3707     return ASF_FLOW_NEED_MORE_DATA;
3708
3709   gst_asf_demux_push_obj (demux, obj.id);
3710
3711   GST_INFO ("%s: size %" G_GUINT64_FORMAT, demux->objpath, obj.size);
3712
3713   switch (obj.id) {
3714     case ASF_OBJ_STREAM:
3715       gst_asf_demux_parse_stream_object (demux, *p_data, obj_data_size);
3716       ret = GST_FLOW_OK;
3717       break;
3718     case ASF_OBJ_FILE:
3719       ret = gst_asf_demux_process_file (demux, *p_data, obj_data_size);
3720       break;
3721     case ASF_OBJ_HEADER:
3722       ret = gst_asf_demux_process_header (demux, *p_data, obj_data_size);
3723       break;
3724     case ASF_OBJ_COMMENT:
3725       ret = gst_asf_demux_process_comment (demux, *p_data, obj_data_size);
3726       break;
3727     case ASF_OBJ_HEAD1:
3728       ret = gst_asf_demux_process_header_ext (demux, *p_data, obj_data_size);
3729       break;
3730     case ASF_OBJ_BITRATE_PROPS:
3731       ret =
3732           gst_asf_demux_process_bitrate_props_object (demux, *p_data,
3733           obj_data_size);
3734       break;
3735     case ASF_OBJ_EXT_CONTENT_DESC:
3736       ret =
3737           gst_asf_demux_process_ext_content_desc (demux, *p_data,
3738           obj_data_size);
3739       break;
3740     case ASF_OBJ_METADATA_OBJECT:
3741       ret = gst_asf_demux_process_metadata (demux, *p_data, obj_data_size);
3742       break;
3743     case ASF_OBJ_EXTENDED_STREAM_PROPS:{
3744       GstBuffer *buf;
3745
3746       /* process these later, we might not have parsed the corresponding
3747        * stream object yet */
3748       GST_LOG ("%s: queued for later parsing", demux->objpath);
3749       buf = gst_buffer_new_and_alloc (obj_data_size);
3750       gst_buffer_fill (buf, 0, *p_data, obj_data_size);
3751       demux->ext_stream_props = g_slist_append (demux->ext_stream_props, buf);
3752       ret = GST_FLOW_OK;
3753       break;
3754     }
3755     case ASF_OBJ_LANGUAGE_LIST:
3756       ret = gst_asf_demux_process_language_list (demux, *p_data, obj_data_size);
3757       break;
3758     case ASF_OBJ_ADVANCED_MUTUAL_EXCLUSION:
3759       ret = gst_asf_demux_process_advanced_mutual_exclusion (demux, *p_data,
3760           obj_data_size);
3761       break;
3762     case ASF_OBJ_SIMPLE_INDEX:
3763       ret = gst_asf_demux_process_simple_index (demux, *p_data, obj_data_size);
3764       break;
3765     case ASF_OBJ_CONTENT_ENCRYPTION:
3766     case ASF_OBJ_EXT_CONTENT_ENCRYPTION:
3767     case ASF_OBJ_DIGITAL_SIGNATURE_OBJECT:
3768     case ASF_OBJ_UNKNOWN_ENCRYPTION_OBJECT:
3769       goto error_encrypted;
3770     case ASF_OBJ_CONCEAL_NONE:
3771     case ASF_OBJ_HEAD2:
3772     case ASF_OBJ_UNDEFINED:
3773     case ASF_OBJ_CODEC_COMMENT:
3774     case ASF_OBJ_INDEX:
3775     case ASF_OBJ_PADDING:
3776     case ASF_OBJ_BITRATE_MUTEX:
3777     case ASF_OBJ_COMPATIBILITY:
3778     case ASF_OBJ_INDEX_PLACEHOLDER:
3779     case ASF_OBJ_INDEX_PARAMETERS:
3780     case ASF_OBJ_STREAM_PRIORITIZATION:
3781     case ASF_OBJ_SCRIPT_COMMAND:
3782     default:
3783       /* Unknown/unhandled object, skip it and hope for the best */
3784       GST_INFO ("%s: skipping object", demux->objpath);
3785       ret = GST_FLOW_OK;
3786       break;
3787   }
3788
3789   /* this can't fail, we checked the number of bytes available before */
3790   gst_asf_demux_skip_bytes (obj_data_size, p_data, p_size);
3791
3792   GST_LOG ("%s: ret = %s", demux->objpath, gst_asf_get_flow_name (ret));
3793
3794   gst_asf_demux_pop_obj (demux);
3795
3796   return ret;
3797
3798 /* ERRORS */
3799 error_encrypted:
3800   {
3801     GST_ELEMENT_ERROR (demux, STREAM, DECRYPT, (NULL), (NULL));
3802     return GST_FLOW_ERROR;
3803   }
3804 }
3805
3806 static void
3807 gst_asf_demux_descramble_buffer (GstASFDemux * demux, AsfStream * stream,
3808     GstBuffer ** p_buffer)
3809 {
3810   GstBuffer *descrambled_buffer;
3811   GstBuffer *scrambled_buffer;
3812   GstBuffer *sub_buffer;
3813   guint offset;
3814   guint off;
3815   guint row;
3816   guint col;
3817   guint idx;
3818
3819   /* descrambled_buffer is initialised in the first iteration */
3820   descrambled_buffer = NULL;
3821   scrambled_buffer = *p_buffer;
3822
3823   if (gst_buffer_get_size (scrambled_buffer) <
3824       demux->ds_packet_size * demux->span)
3825     return;
3826
3827   for (offset = 0; offset < gst_buffer_get_size (scrambled_buffer);
3828       offset += demux->ds_chunk_size) {
3829     off = offset / demux->ds_chunk_size;
3830     row = off / demux->span;
3831     col = off % demux->span;
3832     idx = row + col * demux->ds_packet_size / demux->ds_chunk_size;
3833     GST_DEBUG ("idx=%u, row=%u, col=%u, off=%u, ds_chunk_size=%u", idx, row,
3834         col, off, demux->ds_chunk_size);
3835     GST_DEBUG ("scrambled buffer size=%" G_GSIZE_FORMAT
3836         ", span=%u, packet_size=%u", gst_buffer_get_size (scrambled_buffer),
3837         demux->span, demux->ds_packet_size);
3838     GST_DEBUG ("gst_buffer_get_size (scrambled_buffer) = %" G_GSIZE_FORMAT,
3839         gst_buffer_get_size (scrambled_buffer));
3840     sub_buffer =
3841         gst_buffer_copy_region (scrambled_buffer, GST_BUFFER_COPY_NONE,
3842         idx * demux->ds_chunk_size, demux->ds_chunk_size);
3843     if (!offset) {
3844       descrambled_buffer = sub_buffer;
3845     } else {
3846       descrambled_buffer = gst_buffer_append (descrambled_buffer, sub_buffer);
3847     }
3848   }
3849
3850   GST_BUFFER_TIMESTAMP (descrambled_buffer) =
3851       GST_BUFFER_TIMESTAMP (scrambled_buffer);
3852   GST_BUFFER_DURATION (descrambled_buffer) =
3853       GST_BUFFER_DURATION (scrambled_buffer);
3854   GST_BUFFER_OFFSET (descrambled_buffer) = GST_BUFFER_OFFSET (scrambled_buffer);
3855   GST_BUFFER_OFFSET_END (descrambled_buffer) =
3856       GST_BUFFER_OFFSET_END (scrambled_buffer);
3857
3858   /* FIXME/CHECK: do we need to transfer buffer flags here too? */
3859
3860   gst_buffer_unref (scrambled_buffer);
3861   *p_buffer = descrambled_buffer;
3862 }
3863
3864 static gboolean
3865 gst_asf_demux_element_send_event (GstElement * element, GstEvent * event)
3866 {
3867   GstASFDemux *demux = GST_ASF_DEMUX (element);
3868   gint i;
3869
3870   GST_DEBUG ("handling element event of type %s", GST_EVENT_TYPE_NAME (event));
3871
3872   for (i = 0; i < demux->num_streams; ++i) {
3873     gst_event_ref (event);
3874     if (gst_asf_demux_handle_src_event (demux->stream[i].pad,
3875             GST_OBJECT_CAST (element), event)) {
3876       gst_event_unref (event);
3877       return TRUE;
3878     }
3879   }
3880
3881   gst_event_unref (event);
3882   return FALSE;
3883 }
3884
3885 /* takes ownership of the passed event */
3886 static gboolean
3887 gst_asf_demux_send_event_unlocked (GstASFDemux * demux, GstEvent * event)
3888 {
3889   gboolean ret = TRUE;
3890   gint i;
3891
3892   GST_DEBUG_OBJECT (demux, "sending %s event to all source pads",
3893       GST_EVENT_TYPE_NAME (event));
3894
3895   for (i = 0; i < demux->num_streams; ++i) {
3896     gst_event_ref (event);
3897     ret &= gst_pad_push_event (demux->stream[i].pad, event);
3898   }
3899   gst_event_unref (event);
3900   return ret;
3901 }
3902
3903 static gboolean
3904 gst_asf_demux_handle_src_query (GstPad * pad, GstObject * parent,
3905     GstQuery * query)
3906 {
3907   GstASFDemux *demux;
3908   gboolean res = FALSE;
3909
3910   demux = GST_ASF_DEMUX (parent);
3911
3912   GST_DEBUG ("handling %s query",
3913       gst_query_type_get_name (GST_QUERY_TYPE (query)));
3914
3915   switch (GST_QUERY_TYPE (query)) {
3916     case GST_QUERY_DURATION:
3917     {
3918       GstFormat format;
3919
3920       gst_query_parse_duration (query, &format, NULL);
3921
3922       if (format != GST_FORMAT_TIME) {
3923         GST_LOG ("only support duration queries in TIME format");
3924         break;
3925       }
3926
3927       GST_OBJECT_LOCK (demux);
3928
3929       if (demux->segment.duration != GST_CLOCK_TIME_NONE) {
3930         GST_LOG ("returning duration: %" GST_TIME_FORMAT,
3931             GST_TIME_ARGS (demux->segment.duration));
3932
3933         gst_query_set_duration (query, GST_FORMAT_TIME,
3934             demux->segment.duration);
3935
3936         res = TRUE;
3937       } else {
3938         GST_LOG ("duration not known yet");
3939       }
3940
3941       GST_OBJECT_UNLOCK (demux);
3942       break;
3943     }
3944
3945     case GST_QUERY_POSITION:{
3946       GstFormat format;
3947
3948       gst_query_parse_position (query, &format, NULL);
3949
3950       if (format != GST_FORMAT_TIME) {
3951         GST_LOG ("only support position queries in TIME format");
3952         break;
3953       }
3954
3955       GST_OBJECT_LOCK (demux);
3956
3957       if (demux->segment.position != GST_CLOCK_TIME_NONE) {
3958         GST_LOG ("returning position: %" GST_TIME_FORMAT,
3959             GST_TIME_ARGS (demux->segment.position));
3960
3961         gst_query_set_position (query, GST_FORMAT_TIME,
3962             demux->segment.position);
3963
3964         res = TRUE;
3965       } else {
3966         GST_LOG ("position not known yet");
3967       }
3968
3969       GST_OBJECT_UNLOCK (demux);
3970       break;
3971     }
3972
3973     case GST_QUERY_SEEKING:{
3974       GstFormat format;
3975
3976       gst_query_parse_seeking (query, &format, NULL, NULL, NULL);
3977       if (format == GST_FORMAT_TIME) {
3978         gint64 duration;
3979
3980         GST_OBJECT_LOCK (demux);
3981         duration = demux->segment.duration;
3982         GST_OBJECT_UNLOCK (demux);
3983
3984         if (!demux->streaming || !demux->seekable) {
3985           gst_query_set_seeking (query, GST_FORMAT_TIME, demux->seekable, 0,
3986               duration);
3987           res = TRUE;
3988         } else {
3989           GstFormat fmt;
3990           gboolean seekable;
3991
3992           /* try downstream first in TIME */
3993           res = gst_pad_query_default (pad, parent, query);
3994
3995           gst_query_parse_seeking (query, &fmt, &seekable, NULL, NULL);
3996           GST_LOG_OBJECT (demux, "upstream %s seekable %d",
3997               GST_STR_NULL (gst_format_get_name (fmt)), seekable);
3998           /* if no luck, maybe in BYTES */
3999           if (!seekable || fmt != GST_FORMAT_TIME) {
4000             GstQuery *q;
4001
4002             q = gst_query_new_seeking (GST_FORMAT_BYTES);
4003             if ((res = gst_pad_peer_query (demux->sinkpad, q))) {
4004               gst_query_parse_seeking (q, &fmt, &seekable, NULL, NULL);
4005               GST_LOG_OBJECT (demux, "upstream %s seekable %d",
4006                   GST_STR_NULL (gst_format_get_name (fmt)), seekable);
4007               if (fmt != GST_FORMAT_BYTES)
4008                 seekable = FALSE;
4009             }
4010             gst_query_unref (q);
4011             gst_query_set_seeking (query, GST_FORMAT_TIME, seekable, 0,
4012                 duration);
4013             res = TRUE;
4014           }
4015         }
4016       } else
4017         GST_LOG_OBJECT (demux, "only support seeking in TIME format");
4018       break;
4019     }
4020
4021     case GST_QUERY_LATENCY:
4022     {
4023       gboolean live;
4024       GstClockTime min, max;
4025
4026       /* preroll delay does not matter in non-live pipeline,
4027        * but we might end up in a live (rtsp) one ... */
4028
4029       /* first forward */
4030       res = gst_pad_query_default (pad, parent, query);
4031       if (!res)
4032         break;
4033
4034       gst_query_parse_latency (query, &live, &min, &max);
4035
4036       GST_DEBUG_OBJECT (demux, "Peer latency: live %d, min %"
4037           GST_TIME_FORMAT " max %" GST_TIME_FORMAT, live,
4038           GST_TIME_ARGS (min), GST_TIME_ARGS (max));
4039
4040       GST_OBJECT_LOCK (demux);
4041       if (min != -1)
4042         min += demux->latency;
4043       if (max != -1)
4044         max += demux->latency;
4045       GST_OBJECT_UNLOCK (demux);
4046
4047       gst_query_set_latency (query, live, min, max);
4048       break;
4049     }
4050     default:
4051       res = gst_pad_query_default (pad, parent, query);
4052       break;
4053   }
4054
4055   return res;
4056 }
4057
4058 static GstStateChangeReturn
4059 gst_asf_demux_change_state (GstElement * element, GstStateChange transition)
4060 {
4061   GstASFDemux *demux = GST_ASF_DEMUX (element);
4062   GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
4063
4064   switch (transition) {
4065     case GST_STATE_CHANGE_NULL_TO_READY:{
4066       gst_segment_init (&demux->segment, GST_FORMAT_TIME);
4067       demux->need_newsegment = TRUE;
4068       demux->segment_running = FALSE;
4069       demux->accurate = FALSE;
4070       demux->adapter = gst_adapter_new ();
4071       demux->metadata = gst_caps_new_empty ();
4072       demux->global_metadata = gst_structure_new_empty ("metadata");
4073       demux->data_size = 0;
4074       demux->data_offset = 0;
4075       demux->index_offset = 0;
4076       demux->base_offset = 0;
4077       break;
4078     }
4079     default:
4080       break;
4081   }
4082
4083   ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
4084   if (ret == GST_STATE_CHANGE_FAILURE)
4085     return ret;
4086
4087   switch (transition) {
4088     case GST_STATE_CHANGE_PAUSED_TO_READY:
4089     case GST_STATE_CHANGE_READY_TO_NULL:
4090       gst_asf_demux_reset (demux, FALSE);
4091       break;
4092     default:
4093       break;
4094   }
4095
4096   return ret;
4097 }