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