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