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