asfdemux: slightly relax supported seek requirements
[platform/upstream/gst-plugins-ugly.git] / gst / asfdemux / gstasfdemux.c
1 /* GStreamer ASF/WMV/WMA demuxer
2  * Copyright (C) 1999 Erik Walthinsen <omega@cse.ogi.edu>
3  * Copyright (C) 2006-2009 Tim-Philipp Müller <tim centricular net>
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Library General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Library General Public License for more details.
14  *
15  * You should have received a copy of the GNU Library General Public
16  * License along with this library; if not, write to the
17  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18  * Boston, MA 02111-1307, USA.
19  */
20
21 /* TODO:
22  *
23  * - _loop():
24  *   stop if at end of segment if != end of file, ie. demux->segment.stop
25  *
26  * - fix packet parsing:
27  *   there's something wrong with timestamps for packets with keyframes,
28  *   and durations too.
29  */
30
31 #ifdef HAVE_CONFIG_H
32 #include "config.h"
33 #endif
34
35 #include <gst/gstutils.h>
36 #include <gst/base/gstbytereader.h>
37 #include <gst/riff/riff-media.h>
38 #include <gst/tag/tag.h>
39 #include <gst/gst-i18n-plugin.h>
40 #include <stdio.h>
41 #include <stdlib.h>
42 #include <string.h>
43
44 #include "gstasfdemux.h"
45 #include "asfheaders.h"
46 #include "asfpacket.h"
47
48 static GstStaticPadTemplate gst_asf_demux_sink_template =
49 GST_STATIC_PAD_TEMPLATE ("sink",
50     GST_PAD_SINK,
51     GST_PAD_ALWAYS,
52     GST_STATIC_CAPS ("video/x-ms-asf")
53     );
54
55 static GstStaticPadTemplate audio_src_template =
56 GST_STATIC_PAD_TEMPLATE ("audio_%u",
57     GST_PAD_SRC,
58     GST_PAD_SOMETIMES,
59     GST_STATIC_CAPS_ANY);
60
61 static GstStaticPadTemplate video_src_template =
62 GST_STATIC_PAD_TEMPLATE ("video_%u",
63     GST_PAD_SRC,
64     GST_PAD_SOMETIMES,
65     GST_STATIC_CAPS_ANY);
66
67 /* size of an ASF object header, ie. GUID (16 bytes) + object size (8 bytes) */
68 #define ASF_OBJECT_HEADER_SIZE  (16+8)
69
70 /* FIXME: get rid of this */
71 /* abuse this GstFlowReturn enum for internal usage */
72 #define ASF_FLOW_NEED_MORE_DATA  99
73
74 #define gst_asf_get_flow_name(flow)    \
75   (flow == ASF_FLOW_NEED_MORE_DATA) ?  \
76   "need-more-data" : gst_flow_get_name (flow)
77
78 GST_DEBUG_CATEGORY (asfdemux_dbg);
79
80 static GstStateChangeReturn gst_asf_demux_change_state (GstElement * element,
81     GstStateChange transition);
82 static gboolean gst_asf_demux_element_send_event (GstElement * element,
83     GstEvent * event);
84 static gboolean gst_asf_demux_send_event_unlocked (GstASFDemux * demux,
85     GstEvent * event);
86 static gboolean gst_asf_demux_handle_src_query (GstPad * pad,
87     GstObject * parent, GstQuery * query);
88 static GstFlowReturn gst_asf_demux_chain (GstPad * pad, GstObject * parent,
89     GstBuffer * buf);
90 static gboolean gst_asf_demux_sink_event (GstPad * pad, GstObject * parent,
91     GstEvent * event);
92 static GstFlowReturn gst_asf_demux_process_object (GstASFDemux * demux,
93     guint8 ** p_data, guint64 * p_size);
94 static gboolean gst_asf_demux_activate (GstPad * sinkpad, GstObject * parent);
95 static gboolean gst_asf_demux_activate_mode (GstPad * sinkpad,
96     GstObject * parent, GstPadMode mode, gboolean active);
97 static void gst_asf_demux_loop (GstASFDemux * demux);
98 static void
99 gst_asf_demux_process_queued_extended_stream_objects (GstASFDemux * demux);
100 static gboolean gst_asf_demux_pull_headers (GstASFDemux * demux);
101 static void gst_asf_demux_pull_indices (GstASFDemux * demux);
102 static void gst_asf_demux_reset_stream_state_after_discont (GstASFDemux * asf);
103 static gboolean
104 gst_asf_demux_parse_data_object_start (GstASFDemux * demux, guint8 * data);
105 static void gst_asf_demux_descramble_buffer (GstASFDemux * demux,
106     AsfStream * stream, GstBuffer ** p_buffer);
107 static void gst_asf_demux_activate_stream (GstASFDemux * demux,
108     AsfStream * stream);
109 static GstStructure *gst_asf_demux_get_metadata_for_stream (GstASFDemux * d,
110     guint stream_num);
111 static GstFlowReturn gst_asf_demux_push_complete_payloads (GstASFDemux * demux,
112     gboolean force);
113
114 #define gst_asf_demux_parent_class parent_class
115 G_DEFINE_TYPE (GstASFDemux, gst_asf_demux, GST_TYPE_ELEMENT);
116
117 static void
118 gst_asf_demux_class_init (GstASFDemuxClass * klass)
119 {
120   GstElementClass *gstelement_class;
121
122   gstelement_class = (GstElementClass *) klass;
123
124   gst_element_class_set_static_metadata (gstelement_class, "ASF Demuxer",
125       "Codec/Demuxer",
126       "Demultiplexes ASF Streams", "Owen Fraser-Green <owen@discobabe.net>");
127
128   gst_element_class_add_pad_template (gstelement_class,
129       gst_static_pad_template_get (&audio_src_template));
130   gst_element_class_add_pad_template (gstelement_class,
131       gst_static_pad_template_get (&video_src_template));
132   gst_element_class_add_pad_template (gstelement_class,
133       gst_static_pad_template_get (&gst_asf_demux_sink_template));
134
135   gstelement_class->change_state =
136       GST_DEBUG_FUNCPTR (gst_asf_demux_change_state);
137   gstelement_class->send_event =
138       GST_DEBUG_FUNCPTR (gst_asf_demux_element_send_event);
139 }
140
141 static void
142 gst_asf_demux_free_stream (GstASFDemux * demux, AsfStream * stream)
143 {
144   gst_caps_replace (&stream->caps, NULL);
145   if (stream->pending_tags) {
146     gst_tag_list_free (stream->pending_tags);
147     stream->pending_tags = NULL;
148   }
149   if (stream->pad) {
150     if (stream->active)
151       gst_element_remove_pad (GST_ELEMENT_CAST (demux), stream->pad);
152     else
153       gst_object_unref (stream->pad);
154     stream->pad = NULL;
155   }
156
157   while (stream->payloads->len > 0) {
158     AsfPayload *payload;
159     guint last;
160
161     last = stream->payloads->len - 1;
162     payload = &g_array_index (stream->payloads, AsfPayload, last);
163     gst_buffer_replace (&payload->buf, NULL);
164     g_array_remove_index (stream->payloads, last);
165   }
166   if (stream->payloads) {
167     g_array_free (stream->payloads, TRUE);
168     stream->payloads = NULL;
169   }
170   if (stream->ext_props.valid) {
171     g_free (stream->ext_props.payload_extensions);
172     stream->ext_props.payload_extensions = NULL;
173   }
174 }
175
176 static void
177 gst_asf_demux_reset (GstASFDemux * demux, gboolean chain_reset)
178 {
179   GST_LOG_OBJECT (demux, "resetting");
180
181   gst_segment_init (&demux->segment, GST_FORMAT_UNDEFINED);
182   demux->segment_running = FALSE;
183   if (demux->adapter && !chain_reset) {
184     gst_adapter_clear (demux->adapter);
185     g_object_unref (demux->adapter);
186     demux->adapter = NULL;
187   }
188   if (demux->taglist) {
189     gst_tag_list_free (demux->taglist);
190     demux->taglist = NULL;
191   }
192   if (demux->metadata) {
193     gst_caps_unref (demux->metadata);
194     demux->metadata = NULL;
195   }
196   if (demux->global_metadata) {
197     gst_structure_free (demux->global_metadata);
198     demux->global_metadata = NULL;
199   }
200
201   demux->state = GST_ASF_DEMUX_STATE_HEADER;
202   g_free (demux->objpath);
203   demux->objpath = NULL;
204   g_strfreev (demux->languages);
205   demux->languages = NULL;
206   demux->num_languages = 0;
207   g_slist_foreach (demux->ext_stream_props, (GFunc) gst_mini_object_unref,
208       NULL);
209   g_slist_free (demux->ext_stream_props);
210   demux->ext_stream_props = NULL;
211
212   while (demux->old_num_streams > 0) {
213     gst_asf_demux_free_stream (demux,
214         &demux->old_stream[demux->old_num_streams - 1]);
215     --demux->old_num_streams;
216   }
217   memset (demux->old_stream, 0, sizeof (demux->old_stream));
218   demux->old_num_streams = 0;
219
220   /* when resetting for a new chained asf, we don't want to remove the pads
221    * before adding the new ones */
222   if (chain_reset) {
223     memcpy (demux->old_stream, demux->stream, sizeof (demux->stream));
224     demux->old_num_streams = demux->num_streams;
225     demux->num_streams = 0;
226   }
227
228   while (demux->num_streams > 0) {
229     gst_asf_demux_free_stream (demux, &demux->stream[demux->num_streams - 1]);
230     --demux->num_streams;
231   }
232   memset (demux->stream, 0, sizeof (demux->stream));
233   if (!chain_reset) {
234     /* do not remove those for not adding pads with same name */
235     demux->num_audio_streams = 0;
236     demux->num_video_streams = 0;
237   }
238   demux->num_streams = 0;
239   demux->activated_streams = FALSE;
240   demux->first_ts = GST_CLOCK_TIME_NONE;
241   demux->segment_ts = GST_CLOCK_TIME_NONE;
242   demux->in_gap = 0;
243   if (!chain_reset)
244     gst_segment_init (&demux->in_segment, GST_FORMAT_UNDEFINED);
245   demux->state = GST_ASF_DEMUX_STATE_HEADER;
246   demux->seekable = FALSE;
247   demux->broadcast = FALSE;
248   demux->sidx_interval = 0;
249   demux->sidx_num_entries = 0;
250   g_free (demux->sidx_entries);
251   demux->sidx_entries = NULL;
252
253   demux->speed_packets = 1;
254
255   if (chain_reset) {
256     GST_LOG_OBJECT (demux, "Restarting");
257     gst_segment_init (&demux->segment, GST_FORMAT_TIME);
258     demux->need_newsegment = TRUE;
259     demux->segment_running = FALSE;
260     demux->accurate = FALSE;
261     demux->metadata = gst_caps_new_empty ();
262     demux->global_metadata = gst_structure_new_empty ("metadata");
263     demux->data_size = 0;
264     demux->data_offset = 0;
265     demux->index_offset = 0;
266   } else {
267     demux->base_offset = 0;
268   }
269 }
270
271 static void
272 gst_asf_demux_init (GstASFDemux * demux)
273 {
274   demux->sinkpad =
275       gst_pad_new_from_static_template (&gst_asf_demux_sink_template, "sink");
276   gst_pad_set_chain_function (demux->sinkpad,
277       GST_DEBUG_FUNCPTR (gst_asf_demux_chain));
278   gst_pad_set_event_function (demux->sinkpad,
279       GST_DEBUG_FUNCPTR (gst_asf_demux_sink_event));
280   gst_pad_set_activate_function (demux->sinkpad,
281       GST_DEBUG_FUNCPTR (gst_asf_demux_activate));
282   gst_pad_set_activatemode_function (demux->sinkpad,
283       GST_DEBUG_FUNCPTR (gst_asf_demux_activate_mode));
284   gst_element_add_pad (GST_ELEMENT (demux), demux->sinkpad);
285
286   /* set initial state */
287   gst_asf_demux_reset (demux, FALSE);
288 }
289
290 static gboolean
291 gst_asf_demux_activate (GstPad * sinkpad, GstObject * parent)
292 {
293   GstQuery *query;
294   gboolean pull_mode;
295
296   query = gst_query_new_scheduling ();
297
298   if (!gst_pad_peer_query (sinkpad, query)) {
299     gst_query_unref (query);
300     goto activate_push;
301   }
302
303   pull_mode = gst_query_has_scheduling_mode (query, GST_PAD_MODE_PULL);
304   gst_query_unref (query);
305
306   if (!pull_mode)
307     goto activate_push;
308
309   GST_DEBUG_OBJECT (sinkpad, "activating pull");
310   return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PULL, TRUE);
311
312 activate_push:
313   {
314     GST_DEBUG_OBJECT (sinkpad, "activating push");
315     return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PUSH, TRUE);
316   }
317 }
318
319 static gboolean
320 gst_asf_demux_activate_mode (GstPad * sinkpad, GstObject * parent,
321     GstPadMode mode, gboolean active)
322 {
323   gboolean res;
324   GstASFDemux *demux;
325
326   demux = GST_ASF_DEMUX (parent);
327
328   switch (mode) {
329     case GST_PAD_MODE_PUSH:
330       demux->state = GST_ASF_DEMUX_STATE_HEADER;
331       demux->streaming = TRUE;
332       res = TRUE;
333       break;
334     case GST_PAD_MODE_PULL:
335       if (active) {
336         demux->state = GST_ASF_DEMUX_STATE_HEADER;
337         demux->streaming = FALSE;
338
339         res = gst_pad_start_task (sinkpad, (GstTaskFunction) gst_asf_demux_loop,
340             demux, NULL);
341       } else {
342         res = gst_pad_stop_task (sinkpad);
343       }
344       break;
345     default:
346       res = FALSE;
347       break;
348   }
349   return res;
350 }
351
352 static gboolean
353 gst_asf_demux_sink_event (GstPad * pad, GstObject * parent, GstEvent * event)
354 {
355   GstASFDemux *demux;
356   gboolean ret = TRUE;
357
358   demux = GST_ASF_DEMUX (parent);
359
360   GST_LOG_OBJECT (demux, "handling %s event", GST_EVENT_TYPE_NAME (event));
361   switch (GST_EVENT_TYPE (event)) {
362     case GST_EVENT_SEGMENT:{
363       const GstSegment *segment;
364
365       gst_event_parse_segment (event, &segment);
366
367       if (segment->format == GST_FORMAT_BYTES) {
368         if (demux->packet_size && segment->start > demux->data_offset)
369           demux->packet = (segment->start - demux->data_offset) /
370               demux->packet_size;
371         else
372           demux->packet = 0;
373       } else if (segment->format == GST_FORMAT_TIME) {
374         /* do not know packet position, not really a problem */
375         demux->packet = -1;
376       } else {
377         GST_WARNING_OBJECT (demux, "unsupported newsegment format, ignoring");
378         gst_event_unref (event);
379         break;
380       }
381
382       /* record upstream segment for interpolation */
383       if (segment->format != demux->in_segment.format)
384         gst_segment_init (&demux->in_segment, GST_FORMAT_UNDEFINED);
385       gst_segment_copy_into (segment, &demux->in_segment);
386
387       /* in either case, clear some state and generate newsegment later on */
388       GST_OBJECT_LOCK (demux);
389       demux->segment_ts = GST_CLOCK_TIME_NONE;
390       demux->in_gap = GST_CLOCK_TIME_NONE;
391       demux->need_newsegment = TRUE;
392       gst_asf_demux_reset_stream_state_after_discont (demux);
393       GST_OBJECT_UNLOCK (demux);
394
395       gst_event_unref (event);
396       break;
397     }
398     case GST_EVENT_EOS:{
399       GstFlowReturn flow;
400
401       if (demux->state == GST_ASF_DEMUX_STATE_HEADER) {
402         GST_ELEMENT_ERROR (demux, STREAM, DEMUX,
403             (_("This stream contains no data.")),
404             ("got eos and didn't receive a complete header object"));
405         break;
406       }
407       flow = gst_asf_demux_push_complete_payloads (demux, TRUE);
408       if (flow < GST_FLOW_EOS || flow == GST_FLOW_NOT_LINKED) {
409         GST_ELEMENT_ERROR (demux, STREAM, FAILED,
410             (_("Internal data stream error.")),
411             ("streaming stopped, reason %s", gst_flow_get_name (flow)));
412         break;
413       }
414
415       GST_OBJECT_LOCK (demux);
416       gst_adapter_clear (demux->adapter);
417       GST_OBJECT_UNLOCK (demux);
418       gst_asf_demux_send_event_unlocked (demux, event);
419       break;
420     }
421
422     case GST_EVENT_FLUSH_STOP:
423       GST_OBJECT_LOCK (demux);
424       gst_asf_demux_reset_stream_state_after_discont (demux);
425       GST_OBJECT_UNLOCK (demux);
426       gst_asf_demux_send_event_unlocked (demux, event);
427       /* upon activation, latency is no longer introduced, e.g. after seek */
428       if (demux->activated_streams)
429         demux->latency = 0;
430       break;
431
432     default:
433       ret = gst_pad_event_default (pad, parent, event);
434       break;
435   }
436
437   return ret;
438 }
439
440 static gboolean
441 gst_asf_demux_seek_index_lookup (GstASFDemux * demux, guint * packet,
442     GstClockTime seek_time, GstClockTime * p_idx_time, guint * speed,
443     gboolean next, gboolean * eos)
444 {
445   GstClockTime idx_time;
446   guint idx;
447
448   if (eos)
449     *eos = FALSE;
450
451   if (G_UNLIKELY (demux->sidx_num_entries == 0 || demux->sidx_interval == 0))
452     return FALSE;
453
454   idx = (guint) ((seek_time + demux->preroll) / demux->sidx_interval);
455
456   if (next) {
457     /* if we want the next keyframe, we have to go forward till we find
458        a different packet number */
459     guint idx2 = idx;
460     if (idx >= demux->sidx_num_entries - 1) {
461       /* If we get here, we're asking for next keyframe after the last one. There isn't one. */
462       if (eos)
463         *eos = TRUE;
464       return FALSE;
465     }
466     for (idx2 = idx + 1; idx2 < demux->sidx_num_entries; ++idx2) {
467       if (demux->sidx_entries[idx].packet != demux->sidx_entries[idx2].packet) {
468         idx = idx2;
469         break;
470       }
471     }
472   }
473
474   if (G_UNLIKELY (idx >= demux->sidx_num_entries)) {
475     if (eos)
476       *eos = TRUE;
477     return FALSE;
478   }
479
480   *packet = demux->sidx_entries[idx].packet;
481   if (speed)
482     *speed = demux->sidx_entries[idx].count;
483
484   /* so we get closer to the actual time of the packet ... actually, let's not
485    * do this, since we throw away superfluous payloads before the seek position
486    * anyway; this way, our key unit seek 'snap resolution' is a bit better
487    * (ie. same as index resolution) */
488   /*
489      while (idx > 0 && demux->sidx_entries[idx-1] == demux->sidx_entries[idx])
490      --idx;
491    */
492
493   idx_time = demux->sidx_interval * idx;
494   if (G_LIKELY (idx_time >= demux->preroll))
495     idx_time -= demux->preroll;
496
497   GST_DEBUG_OBJECT (demux, "%" GST_TIME_FORMAT " => packet %u at %"
498       GST_TIME_FORMAT, GST_TIME_ARGS (seek_time), *packet,
499       GST_TIME_ARGS (idx_time));
500
501   if (G_LIKELY (p_idx_time))
502     *p_idx_time = idx_time;
503
504   return TRUE;
505 }
506
507 static void
508 gst_asf_demux_reset_stream_state_after_discont (GstASFDemux * demux)
509 {
510   guint n;
511
512   gst_adapter_clear (demux->adapter);
513
514   GST_DEBUG_OBJECT (demux, "reset stream state");
515
516   for (n = 0; n < demux->num_streams; n++) {
517     demux->stream[n].discont = TRUE;
518     demux->stream[n].last_flow = GST_FLOW_OK;
519
520     while (demux->stream[n].payloads->len > 0) {
521       AsfPayload *payload;
522       guint last;
523
524       last = demux->stream[n].payloads->len - 1;
525       payload = &g_array_index (demux->stream[n].payloads, AsfPayload, last);
526       gst_buffer_replace (&payload->buf, NULL);
527       g_array_remove_index (demux->stream[n].payloads, last);
528     }
529   }
530 }
531
532 static void
533 gst_asf_demux_mark_discont (GstASFDemux * demux)
534 {
535   guint n;
536
537   GST_DEBUG_OBJECT (demux, "Mark stream discont");
538
539   for (n = 0; n < demux->num_streams; n++)
540     demux->stream[n].discont = TRUE;
541 }
542
543 /* do a seek in push based mode */
544 static gboolean
545 gst_asf_demux_handle_seek_push (GstASFDemux * demux, GstEvent * event)
546 {
547   gdouble rate;
548   GstFormat format;
549   GstSeekFlags flags;
550   GstSeekType cur_type, stop_type;
551   gint64 cur, stop;
552   guint packet;
553   gboolean res;
554
555   gst_event_parse_seek (event, &rate, &format, &flags, &cur_type, &cur,
556       &stop_type, &stop);
557
558   stop_type = GST_SEEK_TYPE_NONE;
559   stop = -1;
560
561   GST_DEBUG_OBJECT (demux, "seeking to %" GST_TIME_FORMAT, GST_TIME_ARGS (cur));
562
563   /* determine packet, by index or by estimation */
564   if (!gst_asf_demux_seek_index_lookup (demux, &packet, cur, NULL, NULL, FALSE,
565           NULL)) {
566     packet =
567         (guint) gst_util_uint64_scale (demux->num_packets, cur,
568         demux->play_time);
569   }
570
571   if (packet > demux->num_packets) {
572     GST_DEBUG_OBJECT (demux, "could not determine packet to seek to, "
573         "seek aborted.");
574     return FALSE;
575   }
576
577   GST_DEBUG_OBJECT (demux, "seeking to packet %d", packet);
578
579   cur = demux->data_offset + (packet * demux->packet_size);
580
581   GST_DEBUG_OBJECT (demux, "Pushing BYTE seek rate %g, "
582       "start %" G_GINT64_FORMAT ", stop %" G_GINT64_FORMAT, rate, cur, stop);
583   /* BYTE seek event */
584   event = gst_event_new_seek (rate, GST_FORMAT_BYTES, flags, cur_type, cur,
585       stop_type, stop);
586   res = gst_pad_push_event (demux->sinkpad, event);
587
588   return res;
589 }
590
591 static gboolean
592 gst_asf_demux_handle_seek_event (GstASFDemux * demux, GstEvent * event)
593 {
594   GstClockTime idx_time;
595   GstSegment segment;
596   GstSeekFlags flags;
597   GstSeekType cur_type, stop_type;
598   GstFormat format;
599   gboolean only_need_update;
600   gboolean keyunit_sync, after, before, next;
601   gboolean flush;
602   gdouble rate;
603   gint64 cur, stop;
604   gint64 seek_time;
605   guint packet, speed_count = 1;
606   gboolean eos;
607
608   if (G_UNLIKELY (demux->seekable == FALSE || demux->packet_size == 0 ||
609           demux->num_packets == 0 || demux->play_time == 0)) {
610     GST_LOG_OBJECT (demux, "stream is not seekable");
611     return FALSE;
612   }
613
614   if (G_UNLIKELY (!demux->activated_streams)) {
615     GST_LOG_OBJECT (demux, "streams not yet activated, ignoring seek");
616     return FALSE;
617   }
618
619   gst_event_parse_seek (event, &rate, &format, &flags, &cur_type, &cur,
620       &stop_type, &stop);
621
622   if (G_UNLIKELY (format != GST_FORMAT_TIME)) {
623     GST_LOG_OBJECT (demux, "seeking is only supported in TIME format");
624     return FALSE;
625   }
626
627   if (G_UNLIKELY (rate <= 0.0)) {
628     GST_LOG_OBJECT (demux, "backward playback is not supported yet");
629     return FALSE;
630   }
631
632   flush = ((flags & GST_SEEK_FLAG_FLUSH) == GST_SEEK_FLAG_FLUSH);
633   demux->accurate =
634       ((flags & GST_SEEK_FLAG_ACCURATE) == GST_SEEK_FLAG_ACCURATE);
635   keyunit_sync = ((flags & GST_SEEK_FLAG_KEY_UNIT) == GST_SEEK_FLAG_KEY_UNIT);
636   after = ((flags & GST_SEEK_FLAG_SNAP_AFTER) == GST_SEEK_FLAG_SNAP_AFTER);
637   before = ((flags & GST_SEEK_FLAG_SNAP_BEFORE) == GST_SEEK_FLAG_SNAP_BEFORE);
638   next = after && !before;
639
640   if (G_UNLIKELY (demux->streaming)) {
641     /* support it safely needs more segment handling, e.g. closing etc */
642     if (!flush) {
643       GST_LOG_OBJECT (demux, "streaming; non-flushing seek not supported");
644       return FALSE;
645     }
646     /* we can (re)construct the start later on, but not the end */
647     if (stop_type != GST_SEEK_TYPE_NONE &&
648         (stop_type != GST_SEEK_TYPE_SET || GST_CLOCK_TIME_IS_VALID (stop))) {
649       GST_LOG_OBJECT (demux, "streaming; end position must be NONE");
650       return FALSE;
651     }
652     gst_event_ref (event);
653     /* upstream might handle TIME seek, e.g. mms or rtsp,
654      * or not, e.g. http, then we give it a hand */
655     if (!gst_pad_push_event (demux->sinkpad, event))
656       return gst_asf_demux_handle_seek_push (demux, event);
657     else
658       return TRUE;
659   }
660
661   /* unlock the streaming thread */
662   if (G_LIKELY (flush)) {
663     gst_pad_push_event (demux->sinkpad, gst_event_new_flush_start ());
664     gst_asf_demux_send_event_unlocked (demux, gst_event_new_flush_start ());
665   } else {
666     gst_pad_pause_task (demux->sinkpad);
667   }
668
669   /* grab the stream lock so that streaming cannot continue, for
670    * non flushing seeks when the element is in PAUSED this could block
671    * forever */
672   GST_PAD_STREAM_LOCK (demux->sinkpad);
673
674   /* we now can stop flushing, since we have the stream lock now */
675   gst_pad_push_event (demux->sinkpad, gst_event_new_flush_stop (TRUE));
676
677   if (G_LIKELY (flush))
678     gst_asf_demux_send_event_unlocked (demux, gst_event_new_flush_stop (TRUE));
679
680   /* operating on copy of segment until we know the seek worked */
681   segment = demux->segment;
682
683   if (G_UNLIKELY (demux->segment_running && !flush)) {
684     GstSegment newsegment;
685     GstEvent *newseg;
686
687     /* create the segment event to close the current segment */
688     gst_segment_copy_into (&segment, &newsegment);
689     newseg = gst_event_new_segment (&newsegment);
690
691     gst_asf_demux_send_event_unlocked (demux, newseg);
692   }
693
694   gst_segment_do_seek (&segment, rate, format, flags, cur_type,
695       cur, stop_type, stop, &only_need_update);
696
697   GST_DEBUG_OBJECT (demux, "seeking to time %" GST_TIME_FORMAT ", segment: "
698       "%" GST_SEGMENT_FORMAT, GST_TIME_ARGS (segment.start), &segment);
699
700   seek_time = segment.start;
701
702   /* FIXME: should check the KEY_UNIT flag; need to adjust position to
703    * real start of data and segment_start to indexed time for key unit seek*/
704   if (G_UNLIKELY (!gst_asf_demux_seek_index_lookup (demux, &packet, seek_time,
705               &idx_time, &speed_count, next, &eos))) {
706     gint64 offset;
707
708     if (eos) {
709       demux->packet = demux->num_packets;
710       goto skip;
711     }
712
713     /* First try to query our source to see if it can convert for us. This is
714        the case when our source is an mms stream, notice that in this case
715        gstmms will do a time based seek to get the byte offset, this is not a
716        problem as the seek to this offset needs to happen anway. */
717     if (gst_pad_peer_query_convert (demux->sinkpad, GST_FORMAT_TIME, seek_time,
718             GST_FORMAT_BYTES, &offset)) {
719       packet = (offset - demux->data_offset) / demux->packet_size;
720       GST_LOG_OBJECT (demux, "convert %" GST_TIME_FORMAT
721           " to bytes query result: %" G_GINT64_FORMAT ", data_ofset: %"
722           G_GINT64_FORMAT ", packet_size: %u," " resulting packet: %u\n",
723           GST_TIME_ARGS (seek_time), offset, demux->data_offset,
724           demux->packet_size, packet);
725     } else {
726       /* FIXME: For streams containing video, seek to an earlier position in
727        * the hope of hitting a keyframe and let the sinks throw away the stuff
728        * before the segment start. For audio-only this is unnecessary as every
729        * frame is 'key'. */
730       if (flush && (demux->accurate || (keyunit_sync && !next))
731           && demux->num_video_streams > 0) {
732         seek_time -= 5 * GST_SECOND;
733         if (seek_time < 0)
734           seek_time = 0;
735       }
736
737       packet = (guint) gst_util_uint64_scale (demux->num_packets,
738           seek_time, demux->play_time);
739
740       if (packet > demux->num_packets)
741         packet = demux->num_packets;
742     }
743   } else {
744     if (G_LIKELY (keyunit_sync)) {
745       GST_DEBUG_OBJECT (demux, "key unit seek, adjust seek_time = %"
746           GST_TIME_FORMAT " to index_time = %" GST_TIME_FORMAT,
747           GST_TIME_ARGS (seek_time), GST_TIME_ARGS (idx_time));
748       segment.start = idx_time;
749       segment.position = idx_time;
750       segment.time = idx_time;
751     }
752   }
753
754   GST_DEBUG_OBJECT (demux, "seeking to packet %u (%d)", packet, speed_count);
755
756   GST_OBJECT_LOCK (demux);
757   demux->segment = segment;
758   demux->packet = packet;
759   demux->need_newsegment = TRUE;
760   demux->speed_packets = speed_count;
761   gst_asf_demux_reset_stream_state_after_discont (demux);
762   GST_OBJECT_UNLOCK (demux);
763
764 skip:
765   /* restart our task since it might have been stopped when we did the flush */
766   gst_pad_start_task (demux->sinkpad, (GstTaskFunction) gst_asf_demux_loop,
767       demux, NULL);
768
769   /* streaming can continue now */
770   GST_PAD_STREAM_UNLOCK (demux->sinkpad);
771
772   return TRUE;
773 }
774
775 static gboolean
776 gst_asf_demux_handle_src_event (GstPad * pad, GstObject * parent,
777     GstEvent * event)
778 {
779   GstASFDemux *demux;
780   gboolean ret;
781
782   demux = GST_ASF_DEMUX (parent);
783
784   switch (GST_EVENT_TYPE (event)) {
785     case GST_EVENT_SEEK:
786       GST_LOG_OBJECT (pad, "seek event");
787       ret = gst_asf_demux_handle_seek_event (demux, event);
788       gst_event_unref (event);
789       break;
790     case GST_EVENT_QOS:
791     case GST_EVENT_NAVIGATION:
792       /* just drop these two silently */
793       gst_event_unref (event);
794       ret = FALSE;
795       break;
796     default:
797       GST_LOG_OBJECT (pad, "%s event", GST_EVENT_TYPE_NAME (event));
798       ret = gst_pad_event_default (pad, parent, event);
799       break;
800   }
801
802   return ret;
803 }
804
805 static inline guint32
806 gst_asf_demux_identify_guid (const ASFGuidHash * guids, ASFGuid * guid)
807 {
808   guint32 ret;
809
810   ret = gst_asf_identify_guid (guids, guid);
811
812   GST_LOG ("%s  0x%08x-0x%08x-0x%08x-0x%08x",
813       gst_asf_get_guid_nick (guids, ret),
814       guid->v1, guid->v2, guid->v3, guid->v4);
815
816   return ret;
817 }
818
819 typedef struct
820 {
821   AsfObjectID id;
822   guint64 size;
823 } AsfObject;
824
825
826 /* expect is true when the user is expeting an object,
827  * when false, it will give no warnings if the object
828  * is not identified
829  */
830 static gboolean
831 asf_demux_peek_object (GstASFDemux * demux, const guint8 * data,
832     guint data_len, AsfObject * object, gboolean expect)
833 {
834   ASFGuid guid;
835
836   if (data_len < ASF_OBJECT_HEADER_SIZE)
837     return FALSE;
838
839   guid.v1 = GST_READ_UINT32_LE (data + 0);
840   guid.v2 = GST_READ_UINT32_LE (data + 4);
841   guid.v3 = GST_READ_UINT32_LE (data + 8);
842   guid.v4 = GST_READ_UINT32_LE (data + 12);
843
844   object->size = GST_READ_UINT64_LE (data + 16);
845
846   /* FIXME: make asf_demux_identify_object_guid() */
847   object->id = gst_asf_demux_identify_guid (asf_object_guids, &guid);
848   if (object->id == ASF_OBJ_UNDEFINED && expect) {
849     GST_WARNING_OBJECT (demux, "Unknown object %08x-%08x-%08x-%08x",
850         guid.v1, guid.v2, guid.v3, guid.v4);
851   }
852
853   return TRUE;
854 }
855
856 static void
857 gst_asf_demux_release_old_pads (GstASFDemux * demux)
858 {
859   GST_DEBUG_OBJECT (demux, "Releasing old pads");
860
861   while (demux->old_num_streams > 0) {
862     gst_pad_push_event (demux->old_stream[demux->old_num_streams - 1].pad,
863         gst_event_new_eos ());
864     gst_asf_demux_free_stream (demux,
865         &demux->old_stream[demux->old_num_streams - 1]);
866     --demux->old_num_streams;
867   }
868   memset (demux->old_stream, 0, sizeof (demux->old_stream));
869   demux->old_num_streams = 0;
870 }
871
872 static GstFlowReturn
873 gst_asf_demux_chain_headers (GstASFDemux * demux)
874 {
875   GstFlowReturn flow;
876   AsfObject obj;
877   guint8 *header_data, *data = NULL;
878   const guint8 *cdata = NULL;
879   guint64 header_size;
880
881   cdata = (guint8 *) gst_adapter_map (demux->adapter, ASF_OBJECT_HEADER_SIZE);
882   if (cdata == NULL)
883     goto need_more_data;
884
885   asf_demux_peek_object (demux, cdata, ASF_OBJECT_HEADER_SIZE, &obj, TRUE);
886   if (obj.id != ASF_OBJ_HEADER)
887     goto wrong_type;
888
889   GST_LOG_OBJECT (demux, "header size = %u", (guint) obj.size);
890
891   /* + 50 for non-packet data at beginning of ASF_OBJ_DATA */
892   if (gst_adapter_available (demux->adapter) < obj.size + 50)
893     goto need_more_data;
894
895   data = gst_adapter_take (demux->adapter, obj.size + 50);
896
897   header_data = data;
898   header_size = obj.size;
899   flow = gst_asf_demux_process_object (demux, &header_data, &header_size);
900   if (flow != GST_FLOW_OK)
901     goto parse_failed;
902
903   /* calculate where the packet data starts */
904   demux->data_offset = obj.size + 50;
905
906   /* now parse the beginning of the ASF_OBJ_DATA object */
907   if (!gst_asf_demux_parse_data_object_start (demux, data + obj.size))
908     goto wrong_type;
909
910   if (demux->num_streams == 0)
911     goto no_streams;
912
913   g_free (data);
914   return GST_FLOW_OK;
915
916 /* NON-FATAL */
917 need_more_data:
918   {
919     GST_LOG_OBJECT (demux, "not enough data in adapter yet");
920     return GST_FLOW_OK;
921   }
922
923 /* ERRORS */
924 wrong_type:
925   {
926     GST_ELEMENT_ERROR (demux, STREAM, WRONG_TYPE, (NULL),
927         ("This doesn't seem to be an ASF file"));
928     g_free (data);
929     return GST_FLOW_ERROR;
930   }
931 no_streams:
932 parse_failed:
933   {
934     GST_ELEMENT_ERROR (demux, STREAM, DEMUX, (NULL),
935         ("header parsing failed, or no streams found, flow = %s",
936             gst_flow_get_name (flow)));
937     g_free (data);
938     return GST_FLOW_ERROR;
939   }
940 }
941
942 static GstFlowReturn
943 gst_asf_demux_aggregate_flow_return (GstASFDemux * demux, AsfStream * stream,
944     GstFlowReturn flow)
945 {
946   int i;
947
948   GST_DEBUG_OBJECT (demux, "Aggregating");
949
950   /* Store the value */
951   stream->last_flow = flow;
952
953   /* any other error that is not not-linked can be returned right away */
954   if (flow != GST_FLOW_NOT_LINKED)
955     goto done;
956
957   for (i = 0; i < demux->num_streams; i++) {
958     if (demux->stream[i].active) {
959       flow = demux->stream[i].last_flow;
960       GST_DEBUG_OBJECT (demux, "Aggregating: flow %i return %s", i,
961           gst_flow_get_name (flow));
962       if (flow != GST_FLOW_NOT_LINKED)
963         goto done;
964     }
965   }
966
967   /* If we got here, then all our active streams are not linked */
968 done:
969   return flow;
970 }
971
972 static gboolean
973 gst_asf_demux_pull_data (GstASFDemux * demux, guint64 offset, guint size,
974     GstBuffer ** p_buf, GstFlowReturn * p_flow)
975 {
976   gsize buffer_size;
977   GstFlowReturn flow;
978
979   GST_LOG_OBJECT (demux, "pulling buffer at %" G_GUINT64_FORMAT "+%u",
980       offset, size);
981
982   flow = gst_pad_pull_range (demux->sinkpad, offset, size, p_buf);
983
984   if (G_LIKELY (p_flow))
985     *p_flow = flow;
986
987   if (G_UNLIKELY (flow != GST_FLOW_OK)) {
988     GST_DEBUG_OBJECT (demux, "flow %s pulling buffer at %" G_GUINT64_FORMAT
989         "+%u", gst_flow_get_name (flow), offset, size);
990     *p_buf = NULL;
991     return FALSE;
992   }
993
994   g_assert (*p_buf != NULL);
995
996   buffer_size = gst_buffer_get_size (*p_buf);
997   if (G_UNLIKELY (buffer_size < size)) {
998     GST_DEBUG_OBJECT (demux, "short read pulling buffer at %" G_GUINT64_FORMAT
999         "+%u (got only %" G_GSIZE_FORMAT " bytes)", offset, size, buffer_size);
1000     gst_buffer_unref (*p_buf);
1001     if (G_LIKELY (p_flow))
1002       *p_flow = GST_FLOW_EOS;
1003     *p_buf = NULL;
1004     return FALSE;
1005   }
1006
1007   return TRUE;
1008 }
1009
1010 static void
1011 gst_asf_demux_pull_indices (GstASFDemux * demux)
1012 {
1013   GstBuffer *buf = NULL;
1014   guint64 offset;
1015   guint num_read = 0;
1016
1017   offset = demux->index_offset;
1018
1019   if (G_UNLIKELY (offset == 0)) {
1020     GST_DEBUG_OBJECT (demux, "can't read indices, don't know index offset");
1021     return;
1022   }
1023
1024   while (gst_asf_demux_pull_data (demux, offset, 16 + 8, &buf, NULL)) {
1025     GstFlowReturn flow;
1026     AsfObject obj;
1027     GstMapInfo map;
1028     guint8 *bufdata;
1029
1030     gst_buffer_map (buf, &map, GST_MAP_READ);
1031     g_assert (map.size >= 16 + 8);
1032     asf_demux_peek_object (demux, map.data, 16 + 8, &obj, TRUE);
1033     gst_buffer_unmap (buf, &map);
1034     gst_buffer_replace (&buf, NULL);
1035
1036     /* check for sanity */
1037     if (G_UNLIKELY (obj.size > (5 * 1024 * 1024))) {
1038       GST_DEBUG_OBJECT (demux, "implausible index object size, bailing out");
1039       break;
1040     }
1041
1042     if (G_UNLIKELY (!gst_asf_demux_pull_data (demux, offset, obj.size, &buf,
1043                 NULL)))
1044       break;
1045
1046     GST_LOG_OBJECT (demux, "index object at offset 0x%" G_GINT64_MODIFIER "X"
1047         ", size %u", offset, (guint) obj.size);
1048
1049     offset += obj.size;         /* increase before _process_object changes it */
1050
1051     gst_buffer_map (buf, &map, GST_MAP_READ);
1052     g_assert (map.size >= obj.size);
1053     bufdata = (guint8 *) map.data;
1054     flow = gst_asf_demux_process_object (demux, &bufdata, &obj.size);
1055     gst_buffer_unmap (buf, &map);
1056     gst_buffer_replace (&buf, NULL);
1057
1058     if (G_UNLIKELY (flow != GST_FLOW_OK))
1059       break;
1060
1061     ++num_read;
1062   }
1063   GST_DEBUG_OBJECT (demux, "read %u index objects", num_read);
1064 }
1065
1066 static gboolean
1067 gst_asf_demux_parse_data_object_start (GstASFDemux * demux, guint8 * data)
1068 {
1069   AsfObject obj;
1070
1071   asf_demux_peek_object (demux, data, 50, &obj, TRUE);
1072   if (obj.id != ASF_OBJ_DATA) {
1073     GST_WARNING_OBJECT (demux, "headers not followed by a DATA object");
1074     return FALSE;
1075   }
1076
1077   demux->state = GST_ASF_DEMUX_STATE_DATA;
1078
1079   if (!demux->broadcast && obj.size > 50) {
1080     demux->data_size = obj.size - 50;
1081     /* CHECKME: for at least one file this is off by +158 bytes?! */
1082     demux->index_offset = demux->data_offset + demux->data_size;
1083   } else {
1084     demux->data_size = 0;
1085     demux->index_offset = 0;
1086   }
1087
1088   demux->packet = 0;
1089
1090   if (!demux->broadcast) {
1091     /* skip object header (24 bytes) and file GUID (16 bytes) */
1092     demux->num_packets = GST_READ_UINT64_LE (data + (16 + 8) + 16);
1093   } else {
1094     demux->num_packets = 0;
1095   }
1096
1097   if (demux->num_packets == 0)
1098     demux->seekable = FALSE;
1099
1100   /* fallback in the unlikely case that headers are inconsistent, can't hurt */
1101   if (demux->data_size == 0 && demux->num_packets > 0) {
1102     demux->data_size = demux->num_packets * demux->packet_size;
1103     demux->index_offset = demux->data_offset + demux->data_size;
1104   }
1105
1106   /* process pending stream objects and create pads for those */
1107   gst_asf_demux_process_queued_extended_stream_objects (demux);
1108
1109   GST_INFO_OBJECT (demux, "Stream has %" G_GUINT64_FORMAT " packets, "
1110       "data_offset=%" G_GINT64_FORMAT ", data_size=%" G_GINT64_FORMAT
1111       ", index_offset=%" G_GUINT64_FORMAT, demux->num_packets,
1112       demux->data_offset, demux->data_size, demux->index_offset);
1113
1114   return TRUE;
1115 }
1116
1117 static gboolean
1118 gst_asf_demux_pull_headers (GstASFDemux * demux)
1119 {
1120   GstFlowReturn flow;
1121   AsfObject obj;
1122   GstBuffer *buf = NULL;
1123   guint64 size;
1124   GstMapInfo map;
1125   guint8 *bufdata;
1126
1127   GST_LOG_OBJECT (demux, "reading headers");
1128
1129   /* pull HEADER object header, so we know its size */
1130   if (!gst_asf_demux_pull_data (demux, demux->base_offset, 16 + 8, &buf, NULL))
1131     goto read_failed;
1132
1133   gst_buffer_map (buf, &map, GST_MAP_READ);
1134   g_assert (map.size >= 16 + 8);
1135   asf_demux_peek_object (demux, map.data, 16 + 8, &obj, TRUE);
1136   gst_buffer_unmap (buf, &map);
1137   gst_buffer_replace (&buf, NULL);
1138
1139   if (obj.id != ASF_OBJ_HEADER)
1140     goto wrong_type;
1141
1142   GST_LOG_OBJECT (demux, "header size = %u", (guint) obj.size);
1143
1144   /* pull HEADER object */
1145   if (!gst_asf_demux_pull_data (demux, demux->base_offset, obj.size, &buf,
1146           NULL))
1147     goto read_failed;
1148
1149   size = obj.size;              /* don't want obj.size changed */
1150   gst_buffer_map (buf, &map, GST_MAP_READ);
1151   g_assert (map.size >= size);
1152   bufdata = (guint8 *) map.data;
1153   flow = gst_asf_demux_process_object (demux, &bufdata, &size);
1154   gst_buffer_unmap (buf, &map);
1155   gst_buffer_replace (&buf, NULL);
1156
1157   if (flow != GST_FLOW_OK) {
1158     GST_WARNING_OBJECT (demux, "process_object: %s", gst_flow_get_name (flow));
1159     goto parse_failed;
1160   }
1161
1162   /* calculate where the packet data starts */
1163   demux->data_offset = demux->base_offset + obj.size + 50;
1164
1165   /* now pull beginning of DATA object before packet data */
1166   if (!gst_asf_demux_pull_data (demux, demux->base_offset + obj.size, 50, &buf,
1167           NULL))
1168     goto read_failed;
1169
1170   gst_buffer_map (buf, &map, GST_MAP_READ);
1171   g_assert (map.size >= size);
1172   bufdata = (guint8 *) map.data;
1173   if (!gst_asf_demux_parse_data_object_start (demux, bufdata))
1174     goto wrong_type;
1175
1176   if (demux->num_streams == 0)
1177     goto no_streams;
1178
1179   gst_buffer_unmap (buf, &map);
1180   gst_buffer_replace (&buf, NULL);
1181
1182   return TRUE;
1183
1184 /* ERRORS */
1185 wrong_type:
1186   {
1187     if (buf != NULL) {
1188       gst_buffer_unmap (buf, &map);
1189       gst_buffer_replace (&buf, NULL);
1190     }
1191     GST_ELEMENT_ERROR (demux, STREAM, WRONG_TYPE, (NULL),
1192         ("This doesn't seem to be an ASF file"));
1193     return FALSE;
1194   }
1195
1196 no_streams:
1197 read_failed:
1198 parse_failed:
1199   {
1200     if (buf)
1201       gst_buffer_unmap (buf, &map);
1202     gst_buffer_replace (&buf, NULL);
1203     GST_ELEMENT_ERROR (demux, STREAM, DEMUX, (NULL), (NULL));
1204     return FALSE;
1205   }
1206 }
1207
1208 static gboolean
1209 all_streams_prerolled (GstASFDemux * demux)
1210 {
1211   GstClockTime preroll_time;
1212   guint i, num_no_data = 0;
1213
1214   /* Allow at least 500ms of preroll_time  */
1215   preroll_time = MAX (demux->preroll, 500 * GST_MSECOND);
1216
1217   /* returns TRUE as long as there isn't a stream which (a) has data queued
1218    * and (b) the timestamp of last piece of data queued is < demux->preroll
1219    * AND there is at least one other stream with data queued */
1220   for (i = 0; i < demux->num_streams; ++i) {
1221     AsfPayload *last_payload;
1222     AsfStream *stream;
1223     guint last_idx;
1224
1225     stream = &demux->stream[i];
1226     if (G_UNLIKELY (stream->payloads->len == 0)) {
1227       ++num_no_data;
1228       GST_LOG_OBJECT (stream->pad, "no data queued");
1229       continue;
1230     }
1231
1232     last_idx = stream->payloads->len - 1;
1233     last_payload = &g_array_index (stream->payloads, AsfPayload, last_idx);
1234
1235     GST_LOG_OBJECT (stream->pad, "checking if %" GST_TIME_FORMAT " > %"
1236         GST_TIME_FORMAT, GST_TIME_ARGS (last_payload->ts),
1237         GST_TIME_ARGS (preroll_time));
1238     if (G_UNLIKELY (last_payload->ts <= preroll_time)) {
1239       GST_LOG_OBJECT (stream->pad, "not beyond preroll point yet");
1240       return FALSE;
1241     }
1242   }
1243
1244   if (G_UNLIKELY (num_no_data == demux->num_streams))
1245     return FALSE;
1246
1247   return TRUE;
1248 }
1249
1250 #if 0
1251 static gboolean
1252 gst_asf_demux_have_mutually_exclusive_active_stream (GstASFDemux * demux,
1253     AsfStream * stream)
1254 {
1255   GSList *l;
1256
1257   for (l = demux->mut_ex_streams; l != NULL; l = l->next) {
1258     guint8 *mes;
1259
1260     /* check for each mutual exclusion group whether it affects this stream */
1261     for (mes = (guint8 *) l->data; mes != NULL && *mes != 0xff; ++mes) {
1262       if (*mes == stream->id) {
1263         /* we are in this group; let's check if we've already activated streams
1264          * that are in the same group (and hence mutually exclusive to this
1265          * one) */
1266         for (mes = (guint8 *) l->data; mes != NULL && *mes != 0xff; ++mes) {
1267           guint i;
1268
1269           for (i = 0; i < demux->num_streams; ++i) {
1270             if (demux->stream[i].id == *mes && demux->stream[i].active) {
1271               GST_LOG_OBJECT (demux, "stream with ID %d is mutually exclusive "
1272                   "to already active stream with ID %d", stream->id,
1273                   demux->stream[i].id);
1274               return TRUE;
1275             }
1276           }
1277         }
1278         /* we can only be in this group once, let's break out and move on to
1279          * the next mutual exclusion group */
1280         break;
1281       }
1282     }
1283   }
1284
1285   return FALSE;
1286 }
1287 #endif
1288
1289 static gboolean
1290 gst_asf_demux_check_activate_streams (GstASFDemux * demux, gboolean force)
1291 {
1292   guint i;
1293
1294   if (demux->activated_streams)
1295     return TRUE;
1296
1297   if (!all_streams_prerolled (demux) && !force) {
1298     GST_DEBUG_OBJECT (demux, "not all streams with data beyond preroll yet");
1299     return FALSE;
1300   }
1301
1302   for (i = 0; i < demux->num_streams; ++i) {
1303     AsfStream *stream = &demux->stream[i];
1304
1305     if (stream->payloads->len > 0) {
1306       /* we don't check mutual exclusion stuff here; either we have data for
1307        * a stream, then we active it, or we don't, then we'll ignore it */
1308       GST_LOG_OBJECT (stream->pad, "is prerolled - activate!");
1309       gst_asf_demux_activate_stream (demux, stream);
1310     } else {
1311       GST_LOG_OBJECT (stream->pad, "no data, ignoring stream");
1312     }
1313   }
1314
1315   gst_asf_demux_release_old_pads (demux);
1316
1317   demux->activated_streams = TRUE;
1318   GST_LOG_OBJECT (demux, "signalling no more pads");
1319   gst_element_no_more_pads (GST_ELEMENT (demux));
1320   return TRUE;
1321 }
1322
1323 /* returns the stream that has a complete payload with the lowest timestamp
1324  * queued, or NULL (we push things by timestamp because during the internal
1325  * prerolling we might accumulate more data then the external queues can take,
1326  * so we'd lock up if we pushed all accumulated data for stream N in one go) */
1327 static AsfStream *
1328 gst_asf_demux_find_stream_with_complete_payload (GstASFDemux * demux)
1329 {
1330   AsfPayload *best_payload = NULL;
1331   AsfStream *best_stream = NULL;
1332   guint i;
1333
1334   for (i = 0; i < demux->num_streams; ++i) {
1335     AsfStream *stream;
1336
1337     stream = &demux->stream[i];
1338
1339     /* Don't push any data until we have at least one payload that falls within
1340      * the current segment. This way we can remove out-of-segment payloads that
1341      * don't need to be decoded after a seek, sending only data from the
1342      * keyframe directly before our segment start */
1343     if (stream->payloads->len > 0) {
1344       AsfPayload *payload;
1345       guint last_idx;
1346
1347       last_idx = stream->payloads->len - 1;
1348       payload = &g_array_index (stream->payloads, AsfPayload, last_idx);
1349       if (G_UNLIKELY (GST_CLOCK_TIME_IS_VALID (payload->ts) &&
1350               (payload->ts < demux->segment.start))) {
1351         if (G_UNLIKELY ((!demux->accurate) && payload->keyframe)) {
1352           GST_DEBUG_OBJECT (stream->pad,
1353               "Found keyframe, updating segment start to %" GST_TIME_FORMAT,
1354               GST_TIME_ARGS (payload->ts));
1355           demux->segment.start = payload->ts;
1356           demux->segment.time = payload->ts;
1357         } else {
1358           GST_DEBUG_OBJECT (stream->pad, "Last queued payload has timestamp %"
1359               GST_TIME_FORMAT " which is before our segment start %"
1360               GST_TIME_FORMAT ", not pushing yet", GST_TIME_ARGS (payload->ts),
1361               GST_TIME_ARGS (demux->segment.start));
1362           continue;
1363         }
1364       }
1365
1366       /* Now see if there's a complete payload queued for this stream */
1367
1368       payload = &g_array_index (stream->payloads, AsfPayload, 0);
1369       if (!gst_asf_payload_is_complete (payload))
1370         continue;
1371
1372       /* ... and whether its timestamp is lower than the current best */
1373       if (best_stream == NULL || best_payload->ts > payload->ts) {
1374         best_stream = stream;
1375         best_payload = payload;
1376       }
1377     }
1378   }
1379
1380   return best_stream;
1381 }
1382
1383 static GstFlowReturn
1384 gst_asf_demux_push_complete_payloads (GstASFDemux * demux, gboolean force)
1385 {
1386   AsfStream *stream;
1387   GstFlowReturn ret = GST_FLOW_OK;
1388
1389   if (G_UNLIKELY (!demux->activated_streams)) {
1390     if (!gst_asf_demux_check_activate_streams (demux, force))
1391       return GST_FLOW_OK;
1392     /* streams are now activated */
1393   }
1394
1395   /* wait until we had a chance to "lock on" some payload's timestamp */
1396   if (G_UNLIKELY (demux->need_newsegment
1397           && !GST_CLOCK_TIME_IS_VALID (demux->segment_ts)))
1398     return GST_FLOW_OK;
1399
1400   while ((stream = gst_asf_demux_find_stream_with_complete_payload (demux))) {
1401     AsfPayload *payload;
1402
1403     payload = &g_array_index (stream->payloads, AsfPayload, 0);
1404
1405     /* do we need to send a newsegment event */
1406     if ((G_UNLIKELY (demux->need_newsegment))) {
1407
1408       /* safe default if insufficient upstream info */
1409       if (!GST_CLOCK_TIME_IS_VALID (demux->in_gap))
1410         demux->in_gap = 0;
1411
1412       if (demux->segment.stop == GST_CLOCK_TIME_NONE &&
1413           demux->segment.duration > 0) {
1414         /* slight HACK; prevent clipping of last bit */
1415         demux->segment.stop = demux->segment.duration + demux->in_gap;
1416       }
1417
1418       /* FIXME : only if ACCURATE ! */
1419       if (G_LIKELY (!demux->accurate
1420               && (GST_CLOCK_TIME_IS_VALID (payload->ts)))) {
1421         GST_DEBUG ("Adjusting newsegment start to %" GST_TIME_FORMAT,
1422             GST_TIME_ARGS (payload->ts));
1423         demux->segment.start = payload->ts;
1424         demux->segment.time = payload->ts;
1425       }
1426
1427       GST_DEBUG_OBJECT (demux, "sending new-segment event %" GST_SEGMENT_FORMAT,
1428           &demux->segment);
1429
1430       /* note: we fix up all timestamps to start from 0, so this should be ok */
1431       gst_asf_demux_send_event_unlocked (demux,
1432           gst_event_new_segment (&demux->segment));
1433
1434       /* now post any global tags we may have found */
1435       if (demux->taglist == NULL)
1436         demux->taglist = gst_tag_list_new_empty ();
1437
1438       gst_tag_list_add (demux->taglist, GST_TAG_MERGE_REPLACE,
1439           GST_TAG_CONTAINER_FORMAT, "ASF", NULL);
1440
1441       GST_DEBUG_OBJECT (demux, "global tags: %" GST_PTR_FORMAT, demux->taglist);
1442       gst_asf_demux_send_event_unlocked (demux,
1443           gst_event_new_tag ("GstDemuxer", demux->taglist));
1444       demux->taglist = NULL;
1445
1446       demux->need_newsegment = FALSE;
1447       demux->segment_running = TRUE;
1448     }
1449
1450     /* Do we have tags pending for this stream? */
1451     if (G_UNLIKELY (stream->pending_tags)) {
1452       GST_LOG_OBJECT (stream->pad, "%" GST_PTR_FORMAT, stream->pending_tags);
1453       gst_pad_push_event (stream->pad,
1454           gst_event_new_tag ("GstDemuxer", stream->pending_tags));
1455       stream->pending_tags = NULL;
1456     }
1457
1458     /* We have the whole packet now so we should push the packet to
1459      * the src pad now. First though we should check if we need to do
1460      * descrambling */
1461     if (G_UNLIKELY (demux->span > 1)) {
1462       gst_asf_demux_descramble_buffer (demux, stream, &payload->buf);
1463     }
1464
1465     payload->buf = gst_buffer_make_writable (payload->buf);
1466
1467     if (G_LIKELY (!payload->keyframe)) {
1468       GST_BUFFER_FLAG_SET (payload->buf, GST_BUFFER_FLAG_DELTA_UNIT);
1469     }
1470
1471     if (G_UNLIKELY (stream->discont)) {
1472       GST_DEBUG_OBJECT (stream->pad, "marking DISCONT on stream");
1473       GST_BUFFER_FLAG_SET (payload->buf, GST_BUFFER_FLAG_DISCONT);
1474       stream->discont = FALSE;
1475     }
1476
1477     if (G_UNLIKELY (stream->is_video && payload->par_x && payload->par_y &&
1478             (payload->par_x != stream->par_x) &&
1479             (payload->par_y != stream->par_y))) {
1480       GST_DEBUG ("Updating PAR (%d/%d => %d/%d)",
1481           stream->par_x, stream->par_y, payload->par_x, payload->par_y);
1482       stream->par_x = payload->par_x;
1483       stream->par_y = payload->par_y;
1484       stream->caps = gst_caps_make_writable (stream->caps);
1485       gst_caps_set_simple (stream->caps, "pixel-aspect-ratio",
1486           GST_TYPE_FRACTION, stream->par_x, stream->par_y, NULL);
1487       gst_pad_set_caps (stream->pad, stream->caps);
1488     }
1489
1490     if (G_UNLIKELY (stream->interlaced != payload->interlaced)) {
1491       GST_DEBUG ("Updating interlaced status (%d => %d)", stream->interlaced,
1492           payload->interlaced);
1493       stream->interlaced = payload->interlaced;
1494       stream->caps = gst_caps_make_writable (stream->caps);
1495       gst_caps_set_simple (stream->caps, "interlace-mode", G_TYPE_BOOLEAN,
1496           (stream->interlaced ? "mixed" : "progressive"), NULL);
1497       gst_pad_set_caps (stream->pad, stream->caps);
1498     }
1499
1500     /* (sort of) interpolate timestamps using upstream "frame of reference",
1501      * typically useful for live src, but might (unavoidably) mess with
1502      * position reporting if a live src is playing not so live content
1503      * (e.g. rtspsrc taking some time to fall back to tcp) */
1504     GST_BUFFER_TIMESTAMP (payload->buf) = payload->ts + demux->in_gap;
1505     if (payload->duration == GST_CLOCK_TIME_NONE
1506         && stream->ext_props.avg_time_per_frame != 0)
1507       GST_BUFFER_DURATION (payload->buf) =
1508           stream->ext_props.avg_time_per_frame * 100;
1509     else
1510       GST_BUFFER_DURATION (payload->buf) = payload->duration;
1511
1512     /* FIXME: we should really set durations on buffers if we can */
1513
1514     GST_LOG_OBJECT (stream->pad, "pushing buffer, ts=%" GST_TIME_FORMAT
1515         ", dur=%" GST_TIME_FORMAT " size=%" G_GSIZE_FORMAT,
1516         GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (payload->buf)),
1517         GST_TIME_ARGS (GST_BUFFER_DURATION (payload->buf)),
1518         gst_buffer_get_size (payload->buf));
1519
1520     if (stream->active) {
1521       ret = gst_pad_push (stream->pad, payload->buf);
1522       ret = gst_asf_demux_aggregate_flow_return (demux, stream, ret);
1523     } else {
1524       gst_buffer_unref (payload->buf);
1525       ret = GST_FLOW_OK;
1526     }
1527     payload->buf = NULL;
1528     g_array_remove_index (stream->payloads, 0);
1529
1530     /* Break out as soon as we have an issue */
1531     if (G_UNLIKELY (ret != GST_FLOW_OK))
1532       break;
1533   }
1534
1535   return ret;
1536 }
1537
1538 static gboolean
1539 gst_asf_demux_check_buffer_is_header (GstASFDemux * demux, GstBuffer * buf)
1540 {
1541   AsfObject obj;
1542   GstMapInfo map;
1543   g_assert (buf != NULL);
1544
1545   GST_LOG_OBJECT (demux, "Checking if buffer is a header");
1546
1547   gst_buffer_map (buf, &map, GST_MAP_READ);
1548
1549   /* we return false on buffer too small */
1550   if (map.size < ASF_OBJECT_HEADER_SIZE) {
1551     gst_buffer_unmap (buf, &map);
1552     return FALSE;
1553   }
1554
1555   /* check if it is a header */
1556   asf_demux_peek_object (demux, map.data, ASF_OBJECT_HEADER_SIZE, &obj, TRUE);
1557   gst_buffer_unmap (buf, &map);
1558   if (obj.id == ASF_OBJ_HEADER) {
1559     return TRUE;
1560   }
1561   return FALSE;
1562 }
1563
1564 static gboolean
1565 gst_asf_demux_check_chained_asf (GstASFDemux * demux)
1566 {
1567   guint64 off = demux->data_offset + (demux->packet * demux->packet_size);
1568   GstFlowReturn ret = GST_FLOW_OK;
1569   GstBuffer *buf = NULL;
1570   gboolean header = FALSE;
1571
1572   /* TODO maybe we should skip index objects after the data and look
1573    * further for a new header */
1574   if (gst_asf_demux_pull_data (demux, off, ASF_OBJECT_HEADER_SIZE, &buf, &ret)) {
1575     g_assert (buf != NULL);
1576     /* check if it is a header */
1577     if (gst_asf_demux_check_buffer_is_header (demux, buf)) {
1578       GST_DEBUG_OBJECT (demux, "new base offset: %" G_GUINT64_FORMAT, off);
1579       demux->base_offset = off;
1580       header = TRUE;
1581     }
1582
1583     gst_buffer_unref (buf);
1584   }
1585
1586   return header;
1587 }
1588
1589 static void
1590 gst_asf_demux_loop (GstASFDemux * demux)
1591 {
1592   GstFlowReturn flow = GST_FLOW_OK;
1593   GstBuffer *buf = NULL;
1594   guint64 off;
1595   gboolean sent_eos = FALSE;
1596
1597   if (G_UNLIKELY (demux->state == GST_ASF_DEMUX_STATE_HEADER)) {
1598     if (!gst_asf_demux_pull_headers (demux)) {
1599       flow = GST_FLOW_ERROR;
1600       goto pause;
1601     }
1602
1603     gst_asf_demux_pull_indices (demux);
1604   }
1605
1606   g_assert (demux->state == GST_ASF_DEMUX_STATE_DATA);
1607
1608   if (G_UNLIKELY (demux->num_packets != 0
1609           && demux->packet >= demux->num_packets))
1610     goto eos;
1611
1612   GST_LOG_OBJECT (demux, "packet %u/%u", (guint) demux->packet + 1,
1613       (guint) demux->num_packets);
1614
1615   off = demux->data_offset + (demux->packet * demux->packet_size);
1616
1617   if (G_UNLIKELY (!gst_asf_demux_pull_data (demux, off,
1618               demux->packet_size * demux->speed_packets, &buf, &flow))) {
1619     GST_DEBUG_OBJECT (demux, "got flow %s", gst_flow_get_name (flow));
1620     if (flow == GST_FLOW_EOS)
1621       goto eos;
1622     else if (flow == GST_FLOW_FLUSHING) {
1623       GST_DEBUG_OBJECT (demux, "Not fatal");
1624       goto pause;
1625     } else
1626       goto read_failed;
1627   }
1628
1629   if (G_LIKELY (demux->speed_packets == 1)) {
1630     GstAsfDemuxParsePacketError err;
1631     err = gst_asf_demux_parse_packet (demux, buf);
1632     if (G_UNLIKELY (err != GST_ASF_DEMUX_PARSE_PACKET_ERROR_NONE)) {
1633       /* when we don't know when the data object ends, we should check
1634        * for a chained asf */
1635       if (demux->num_packets == 0) {
1636         if (gst_asf_demux_check_buffer_is_header (demux, buf)) {
1637           GST_INFO_OBJECT (demux, "Chained asf found");
1638           demux->base_offset = off;
1639           gst_asf_demux_reset (demux, TRUE);
1640           gst_buffer_unref (buf);
1641           return;
1642         }
1643       }
1644       /* FIXME: We should tally up fatal errors and error out only
1645        * after a few broken packets in a row? */
1646
1647       GST_INFO_OBJECT (demux, "Ignoring recoverable parse error");
1648       gst_buffer_unref (buf);
1649       ++demux->packet;
1650       return;
1651     }
1652
1653     flow = gst_asf_demux_push_complete_payloads (demux, FALSE);
1654
1655     ++demux->packet;
1656
1657   } else {
1658     guint n;
1659     for (n = 0; n < demux->speed_packets; n++) {
1660       GstBuffer *sub;
1661       GstAsfDemuxParsePacketError err;
1662
1663       sub =
1664           gst_buffer_copy_region (buf, GST_BUFFER_COPY_ALL,
1665           n * demux->packet_size, demux->packet_size);
1666       err = gst_asf_demux_parse_packet (demux, sub);
1667       if (G_UNLIKELY (err != GST_ASF_DEMUX_PARSE_PACKET_ERROR_NONE)) {
1668         /* when we don't know when the data object ends, we should check
1669          * for a chained asf */
1670         if (demux->num_packets == 0) {
1671           if (gst_asf_demux_check_buffer_is_header (demux, sub)) {
1672             GST_INFO_OBJECT (demux, "Chained asf found");
1673             demux->base_offset = off + n * demux->packet_size;
1674             gst_asf_demux_reset (demux, TRUE);
1675             gst_buffer_unref (sub);
1676             gst_buffer_unref (buf);
1677             return;
1678           }
1679         }
1680         /* FIXME: We should tally up fatal errors and error out only
1681          * after a few broken packets in a row? */
1682
1683         GST_INFO_OBJECT (demux, "Ignoring recoverable parse error");
1684         flow = GST_FLOW_OK;
1685       }
1686
1687       gst_buffer_unref (sub);
1688
1689       if (err == GST_ASF_DEMUX_PARSE_PACKET_ERROR_NONE)
1690         flow = gst_asf_demux_push_complete_payloads (demux, FALSE);
1691
1692       ++demux->packet;
1693
1694     }
1695
1696     /* reset speed pull */
1697     demux->speed_packets = 1;
1698   }
1699
1700   gst_buffer_unref (buf);
1701
1702   if (G_UNLIKELY (demux->num_packets > 0
1703           && demux->packet >= demux->num_packets)) {
1704     GST_LOG_OBJECT (demux, "reached EOS");
1705     goto eos;
1706   }
1707
1708   if (G_UNLIKELY (flow != GST_FLOW_OK)) {
1709     GST_DEBUG_OBJECT (demux, "pushing complete payloads failed");
1710     goto pause;
1711   }
1712
1713   /* check if we're at the end of the configured segment */
1714   /* FIXME: check if segment end reached etc. */
1715
1716   return;
1717
1718 eos:
1719   {
1720     /* if we haven't activated our streams yet, this might be because we have
1721      * less data queued than required for preroll; force stream activation and
1722      * send any pending payloads before sending EOS */
1723     if (!demux->activated_streams)
1724       gst_asf_demux_push_complete_payloads (demux, TRUE);
1725
1726     /* we want to push an eos or post a segment-done in any case */
1727     if (demux->segment.flags & GST_SEEK_FLAG_SEGMENT) {
1728       gint64 stop;
1729
1730       /* for segment playback we need to post when (in stream time)
1731        * we stopped, this is either stop (when set) or the duration. */
1732       if ((stop = demux->segment.stop) == -1)
1733         stop = demux->segment.duration;
1734
1735       GST_INFO_OBJECT (demux, "Posting segment-done, at end of segment");
1736       gst_element_post_message (GST_ELEMENT_CAST (demux),
1737           gst_message_new_segment_done (GST_OBJECT (demux), GST_FORMAT_TIME,
1738               stop));
1739       gst_asf_demux_send_event_unlocked (demux,
1740           gst_event_new_segment_done (GST_FORMAT_TIME, stop));
1741     } else if (flow != GST_FLOW_EOS) {
1742       /* check if we have a chained asf, in case, we don't eos yet */
1743       if (gst_asf_demux_check_chained_asf (demux)) {
1744         GST_INFO_OBJECT (demux, "Chained ASF starting");
1745         gst_asf_demux_reset (demux, TRUE);
1746         return;
1747       }
1748     }
1749     /* normal playback, send EOS to all linked pads */
1750     GST_INFO_OBJECT (demux, "Sending EOS, at end of stream");
1751     gst_asf_demux_send_event_unlocked (demux, gst_event_new_eos ());
1752     sent_eos = TRUE;
1753     /* ... and fall through to pause */
1754   }
1755 pause:
1756   {
1757     GST_DEBUG_OBJECT (demux, "pausing task, flow return: %s",
1758         gst_flow_get_name (flow));
1759     demux->segment_running = FALSE;
1760     gst_pad_pause_task (demux->sinkpad);
1761
1762     /* For the error cases (not EOS) */
1763     if (!sent_eos) {
1764       if (flow == GST_FLOW_EOS)
1765         gst_asf_demux_send_event_unlocked (demux, gst_event_new_eos ());
1766       else if (flow < GST_FLOW_EOS || flow == GST_FLOW_NOT_LINKED) {
1767         /* Post an error. Hopefully something else already has, but if not... */
1768         GST_ELEMENT_ERROR (demux, STREAM, FAILED,
1769             (_("Internal data stream error.")),
1770             ("streaming stopped, reason %s", gst_flow_get_name (flow)));
1771       }
1772     }
1773     return;
1774   }
1775
1776 /* ERRORS */
1777 read_failed:
1778   {
1779     GST_DEBUG_OBJECT (demux, "Read failed, doh");
1780     gst_asf_demux_send_event_unlocked (demux, gst_event_new_eos ());
1781     flow = GST_FLOW_EOS;
1782     goto pause;
1783   }
1784 #if 0
1785   /* See FIXMEs above */
1786 parse_error:
1787   {
1788     gst_buffer_unref (buf);
1789     GST_ELEMENT_ERROR (demux, STREAM, DEMUX, (NULL),
1790         ("Error parsing ASF packet %u", (guint) demux->packet));
1791     gst_asf_demux_send_event_unlocked (demux, gst_event_new_eos ());
1792     flow = GST_FLOW_ERROR;
1793     goto pause;
1794   }
1795 #endif
1796 }
1797
1798 #define GST_ASF_DEMUX_CHECK_HEADER_YES       0
1799 #define GST_ASF_DEMUX_CHECK_HEADER_NO        1
1800 #define GST_ASF_DEMUX_CHECK_HEADER_NEED_DATA 2
1801
1802 static gint
1803 gst_asf_demux_check_header (GstASFDemux * demux)
1804 {
1805   AsfObject obj;
1806   guint8 *cdata = (guint8 *) gst_adapter_map (demux->adapter,
1807       ASF_OBJECT_HEADER_SIZE);
1808   if (cdata == NULL)            /* need more data */
1809     return GST_ASF_DEMUX_CHECK_HEADER_NEED_DATA;
1810
1811   asf_demux_peek_object (demux, cdata, ASF_OBJECT_HEADER_SIZE, &obj, FALSE);
1812   if (obj.id != ASF_OBJ_HEADER) {
1813     return GST_ASF_DEMUX_CHECK_HEADER_NO;
1814   } else {
1815     return GST_ASF_DEMUX_CHECK_HEADER_YES;
1816   }
1817 }
1818
1819 static GstFlowReturn
1820 gst_asf_demux_chain (GstPad * pad, GstObject * parent, GstBuffer * buf)
1821 {
1822   GstFlowReturn ret = GST_FLOW_OK;
1823   GstASFDemux *demux;
1824
1825   demux = GST_ASF_DEMUX (parent);
1826
1827   GST_LOG_OBJECT (demux,
1828       "buffer: size=%" G_GSIZE_FORMAT ", offset=%" G_GINT64_FORMAT ", time=%"
1829       GST_TIME_FORMAT, gst_buffer_get_size (buf), GST_BUFFER_OFFSET (buf),
1830       GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)));
1831
1832   if (G_UNLIKELY (GST_BUFFER_IS_DISCONT (buf))) {
1833     GST_DEBUG_OBJECT (demux, "received DISCONT");
1834     gst_asf_demux_mark_discont (demux);
1835   }
1836
1837   if (G_UNLIKELY ((!GST_CLOCK_TIME_IS_VALID (demux->in_gap) &&
1838               GST_BUFFER_TIMESTAMP_IS_VALID (buf)))) {
1839     demux->in_gap = GST_BUFFER_TIMESTAMP (buf) - demux->in_segment.start;
1840     GST_DEBUG_OBJECT (demux, "upstream segment start %" GST_TIME_FORMAT
1841         ", interpolation gap: %" GST_TIME_FORMAT,
1842         GST_TIME_ARGS (demux->in_segment.start), GST_TIME_ARGS (demux->in_gap));
1843   }
1844
1845   gst_adapter_push (demux->adapter, buf);
1846
1847   switch (demux->state) {
1848     case GST_ASF_DEMUX_STATE_INDEX:{
1849       gint result = gst_asf_demux_check_header (demux);
1850       if (result == GST_ASF_DEMUX_CHECK_HEADER_NEED_DATA)       /* need more data */
1851         break;
1852
1853       if (result == GST_ASF_DEMUX_CHECK_HEADER_NO) {
1854         /* we don't care about this, probably an index */
1855         /* TODO maybe would be smarter to skip all the indices
1856          * until we got a new header or EOS to decide */
1857         GST_LOG_OBJECT (demux, "Received index object, its EOS");
1858         goto eos;
1859       } else {
1860         GST_INFO_OBJECT (demux, "Chained asf starting");
1861         /* cleanup and get ready for a chained asf */
1862         gst_asf_demux_reset (demux, TRUE);
1863         /* fall through */
1864       }
1865     }
1866     case GST_ASF_DEMUX_STATE_HEADER:{
1867       ret = gst_asf_demux_chain_headers (demux);
1868       if (demux->state != GST_ASF_DEMUX_STATE_DATA)
1869         break;
1870       /* otherwise fall through */
1871     }
1872     case GST_ASF_DEMUX_STATE_DATA:
1873     {
1874       guint64 data_size;
1875
1876       data_size = demux->packet_size;
1877
1878       while (gst_adapter_available (demux->adapter) >= data_size) {
1879         GstBuffer *buf;
1880         GstAsfDemuxParsePacketError err;
1881
1882         /* we don't know the length of the stream
1883          * check for a chained asf everytime */
1884         if (demux->num_packets == 0) {
1885           gint result = gst_asf_demux_check_header (demux);
1886
1887           if (result == GST_ASF_DEMUX_CHECK_HEADER_YES) {
1888             GST_INFO_OBJECT (demux, "Chained asf starting");
1889             /* cleanup and get ready for a chained asf */
1890             gst_asf_demux_reset (demux, TRUE);
1891             break;
1892           }
1893         } else if (G_UNLIKELY (demux->num_packets != 0 && demux->packet >= 0
1894                 && demux->packet >= demux->num_packets)) {
1895           /* do not overshoot data section when streaming */
1896           break;
1897         }
1898
1899         buf = gst_adapter_take_buffer (demux->adapter, data_size);
1900
1901         /* FIXME: We should tally up fatal errors and error out only
1902          * after a few broken packets in a row? */
1903         err = gst_asf_demux_parse_packet (demux, buf);
1904
1905         gst_buffer_unref (buf);
1906
1907         if (G_LIKELY (err == GST_ASF_DEMUX_PARSE_PACKET_ERROR_NONE))
1908           ret = gst_asf_demux_push_complete_payloads (demux, FALSE);
1909         else
1910           GST_WARNING_OBJECT (demux, "Parse error");
1911
1912         if (demux->packet >= 0)
1913           ++demux->packet;
1914       }
1915       if (G_UNLIKELY (demux->num_packets != 0 && demux->packet >= 0
1916               && demux->packet >= demux->num_packets)) {
1917         demux->state = GST_ASF_DEMUX_STATE_INDEX;
1918       }
1919       break;
1920     }
1921     default:
1922       g_assert_not_reached ();
1923   }
1924
1925 done:
1926   if (ret != GST_FLOW_OK)
1927     GST_DEBUG_OBJECT (demux, "flow: %s", gst_flow_get_name (ret));
1928
1929   return ret;
1930
1931 eos:
1932   {
1933     GST_DEBUG_OBJECT (demux, "Handled last packet, setting EOS");
1934     ret = GST_FLOW_EOS;
1935     goto done;
1936   }
1937 }
1938
1939 static inline gboolean
1940 gst_asf_demux_skip_bytes (guint num_bytes, guint8 ** p_data, guint64 * p_size)
1941 {
1942   if (*p_size < num_bytes)
1943     return FALSE;
1944
1945   *p_data += num_bytes;
1946   *p_size -= num_bytes;
1947   return TRUE;
1948 }
1949
1950 static inline guint8
1951 gst_asf_demux_get_uint8 (guint8 ** p_data, guint64 * p_size)
1952 {
1953   guint8 ret;
1954
1955   g_assert (*p_size >= 1);
1956   ret = GST_READ_UINT8 (*p_data);
1957   *p_data += sizeof (guint8);
1958   *p_size -= sizeof (guint8);
1959   return ret;
1960 }
1961
1962 static inline guint16
1963 gst_asf_demux_get_uint16 (guint8 ** p_data, guint64 * p_size)
1964 {
1965   guint16 ret;
1966
1967   g_assert (*p_size >= 2);
1968   ret = GST_READ_UINT16_LE (*p_data);
1969   *p_data += sizeof (guint16);
1970   *p_size -= sizeof (guint16);
1971   return ret;
1972 }
1973
1974 static inline guint32
1975 gst_asf_demux_get_uint32 (guint8 ** p_data, guint64 * p_size)
1976 {
1977   guint32 ret;
1978
1979   g_assert (*p_size >= 4);
1980   ret = GST_READ_UINT32_LE (*p_data);
1981   *p_data += sizeof (guint32);
1982   *p_size -= sizeof (guint32);
1983   return ret;
1984 }
1985
1986 static inline guint64
1987 gst_asf_demux_get_uint64 (guint8 ** p_data, guint64 * p_size)
1988 {
1989   guint64 ret;
1990
1991   g_assert (*p_size >= 8);
1992   ret = GST_READ_UINT64_LE (*p_data);
1993   *p_data += sizeof (guint64);
1994   *p_size -= sizeof (guint64);
1995   return ret;
1996 }
1997
1998 static inline guint32
1999 gst_asf_demux_get_var_length (guint8 type, guint8 ** p_data, guint64 * p_size)
2000 {
2001   switch (type) {
2002     case 0:
2003       return 0;
2004
2005     case 1:
2006       g_assert (*p_size >= 1);
2007       return gst_asf_demux_get_uint8 (p_data, p_size);
2008
2009     case 2:
2010       g_assert (*p_size >= 2);
2011       return gst_asf_demux_get_uint16 (p_data, p_size);
2012
2013     case 3:
2014       g_assert (*p_size >= 4);
2015       return gst_asf_demux_get_uint32 (p_data, p_size);
2016
2017     default:
2018       g_assert_not_reached ();
2019       break;
2020   }
2021   return 0;
2022 }
2023
2024 static gboolean
2025 gst_asf_demux_get_buffer (GstBuffer ** p_buf, guint num_bytes_to_read,
2026     guint8 ** p_data, guint64 * p_size)
2027 {
2028   *p_buf = NULL;
2029
2030   if (*p_size < num_bytes_to_read)
2031     return FALSE;
2032
2033   *p_buf = gst_buffer_new_and_alloc (num_bytes_to_read);
2034   gst_buffer_fill (*p_buf, 0, *p_data, num_bytes_to_read);
2035
2036   *p_data += num_bytes_to_read;
2037   *p_size -= num_bytes_to_read;
2038
2039   return TRUE;
2040 }
2041
2042 static gboolean
2043 gst_asf_demux_get_bytes (guint8 ** p_buf, guint num_bytes_to_read,
2044     guint8 ** p_data, guint64 * p_size)
2045 {
2046   *p_buf = NULL;
2047
2048   if (*p_size < num_bytes_to_read)
2049     return FALSE;
2050
2051   *p_buf = g_memdup (*p_data, num_bytes_to_read);
2052   *p_data += num_bytes_to_read;
2053   *p_size -= num_bytes_to_read;
2054   return TRUE;
2055 }
2056
2057 static gboolean
2058 gst_asf_demux_get_string (gchar ** p_str, guint16 * p_strlen,
2059     guint8 ** p_data, guint64 * p_size)
2060 {
2061   guint16 s_length;
2062   guint8 *s;
2063
2064   *p_str = NULL;
2065
2066   if (*p_size < 2)
2067     return FALSE;
2068
2069   s_length = gst_asf_demux_get_uint16 (p_data, p_size);
2070
2071   if (p_strlen)
2072     *p_strlen = s_length;
2073
2074   if (s_length == 0) {
2075     GST_WARNING ("zero-length string");
2076     *p_str = g_strdup ("");
2077     return TRUE;
2078   }
2079
2080   if (!gst_asf_demux_get_bytes (&s, s_length, p_data, p_size))
2081     return FALSE;
2082
2083   g_assert (s != NULL);
2084
2085   /* just because They don't exist doesn't
2086    * mean They are not out to get you ... */
2087   if (s[s_length - 1] != '\0') {
2088     s = g_realloc (s, s_length + 1);
2089     s[s_length] = '\0';
2090   }
2091
2092   *p_str = (gchar *) s;
2093   return TRUE;
2094 }
2095
2096
2097 static void
2098 gst_asf_demux_get_guid (ASFGuid * guid, guint8 ** p_data, guint64 * p_size)
2099 {
2100   g_assert (*p_size >= 4 * sizeof (guint32));
2101
2102   guid->v1 = gst_asf_demux_get_uint32 (p_data, p_size);
2103   guid->v2 = gst_asf_demux_get_uint32 (p_data, p_size);
2104   guid->v3 = gst_asf_demux_get_uint32 (p_data, p_size);
2105   guid->v4 = gst_asf_demux_get_uint32 (p_data, p_size);
2106 }
2107
2108 static gboolean
2109 gst_asf_demux_get_stream_audio (asf_stream_audio * audio, guint8 ** p_data,
2110     guint64 * p_size)
2111 {
2112   if (*p_size < (2 + 2 + 4 + 4 + 2 + 2 + 2))
2113     return FALSE;
2114
2115   /* WAVEFORMATEX Structure */
2116   audio->codec_tag = gst_asf_demux_get_uint16 (p_data, p_size);
2117   audio->channels = gst_asf_demux_get_uint16 (p_data, p_size);
2118   audio->sample_rate = gst_asf_demux_get_uint32 (p_data, p_size);
2119   audio->byte_rate = gst_asf_demux_get_uint32 (p_data, p_size);
2120   audio->block_align = gst_asf_demux_get_uint16 (p_data, p_size);
2121   audio->word_size = gst_asf_demux_get_uint16 (p_data, p_size);
2122   /* Codec specific data size */
2123   audio->size = gst_asf_demux_get_uint16 (p_data, p_size);
2124   return TRUE;
2125 }
2126
2127 static gboolean
2128 gst_asf_demux_get_stream_video (asf_stream_video * video, guint8 ** p_data,
2129     guint64 * p_size)
2130 {
2131   if (*p_size < (4 + 4 + 1 + 2))
2132     return FALSE;
2133
2134   video->width = gst_asf_demux_get_uint32 (p_data, p_size);
2135   video->height = gst_asf_demux_get_uint32 (p_data, p_size);
2136   video->unknown = gst_asf_demux_get_uint8 (p_data, p_size);
2137   video->size = gst_asf_demux_get_uint16 (p_data, p_size);
2138   return TRUE;
2139 }
2140
2141 static gboolean
2142 gst_asf_demux_get_stream_video_format (asf_stream_video_format * fmt,
2143     guint8 ** p_data, guint64 * p_size)
2144 {
2145   if (*p_size < (4 + 4 + 4 + 2 + 2 + 4 + 4 + 4 + 4 + 4 + 4))
2146     return FALSE;
2147
2148   fmt->size = gst_asf_demux_get_uint32 (p_data, p_size);
2149   fmt->width = gst_asf_demux_get_uint32 (p_data, p_size);
2150   fmt->height = gst_asf_demux_get_uint32 (p_data, p_size);
2151   fmt->planes = gst_asf_demux_get_uint16 (p_data, p_size);
2152   fmt->depth = gst_asf_demux_get_uint16 (p_data, p_size);
2153   fmt->tag = gst_asf_demux_get_uint32 (p_data, p_size);
2154   fmt->image_size = gst_asf_demux_get_uint32 (p_data, p_size);
2155   fmt->xpels_meter = gst_asf_demux_get_uint32 (p_data, p_size);
2156   fmt->ypels_meter = gst_asf_demux_get_uint32 (p_data, p_size);
2157   fmt->num_colors = gst_asf_demux_get_uint32 (p_data, p_size);
2158   fmt->imp_colors = gst_asf_demux_get_uint32 (p_data, p_size);
2159   return TRUE;
2160 }
2161
2162 AsfStream *
2163 gst_asf_demux_get_stream (GstASFDemux * demux, guint16 id)
2164 {
2165   guint i;
2166
2167   for (i = 0; i < demux->num_streams; i++) {
2168     if (demux->stream[i].id == id)
2169       return &demux->stream[i];
2170   }
2171
2172   GST_WARNING ("Segment found for undefined stream: (%d)", id);
2173   return NULL;
2174 }
2175
2176 static void
2177 gst_asf_demux_setup_pad (GstASFDemux * demux, GstPad * src_pad,
2178     GstCaps * caps, guint16 id, gboolean is_video, GstTagList * tags)
2179 {
2180   AsfStream *stream;
2181
2182   gst_pad_use_fixed_caps (src_pad);
2183   gst_pad_set_caps (src_pad, caps);
2184
2185   gst_pad_set_event_function (src_pad,
2186       GST_DEBUG_FUNCPTR (gst_asf_demux_handle_src_event));
2187   gst_pad_set_query_function (src_pad,
2188       GST_DEBUG_FUNCPTR (gst_asf_demux_handle_src_query));
2189
2190   stream = &demux->stream[demux->num_streams];
2191   stream->caps = caps;
2192   stream->pad = src_pad;
2193   stream->id = id;
2194   stream->fps_known = !is_video;        /* bit hacky for audio */
2195   stream->is_video = is_video;
2196   stream->pending_tags = tags;
2197   stream->discont = TRUE;
2198   if (is_video) {
2199     GstStructure *st;
2200     gint par_x, par_y;
2201     st = gst_caps_get_structure (caps, 0);
2202     if (gst_structure_get_fraction (st, "pixel-aspect-ratio", &par_x, &par_y) &&
2203         par_x > 0 && par_y > 0) {
2204       GST_DEBUG ("PAR %d/%d", par_x, par_y);
2205       stream->par_x = par_x;
2206       stream->par_y = par_y;
2207     }
2208   }
2209
2210   stream->payloads = g_array_new (FALSE, FALSE, sizeof (AsfPayload));
2211
2212   GST_INFO ("Created pad %s for stream %u with caps %" GST_PTR_FORMAT,
2213       GST_PAD_NAME (src_pad), demux->num_streams, caps);
2214
2215   ++demux->num_streams;
2216
2217   stream->active = FALSE;
2218 }
2219
2220 static void
2221 gst_asf_demux_add_audio_stream (GstASFDemux * demux,
2222     asf_stream_audio * audio, guint16 id, guint8 ** p_data, guint64 * p_size)
2223 {
2224   GstTagList *tags = NULL;
2225   GstBuffer *extradata = NULL;
2226   GstPad *src_pad;
2227   GstCaps *caps;
2228   guint16 size_left = 0;
2229   gchar *codec_name = NULL;
2230   gchar *name = NULL;
2231
2232   size_left = audio->size;
2233
2234   /* Create the audio pad */
2235   name = g_strdup_printf ("audio_%u", demux->num_audio_streams);
2236
2237   src_pad = gst_pad_new_from_static_template (&audio_src_template, name);
2238   g_free (name);
2239
2240   /* Swallow up any left over data and set up the 
2241    * standard properties from the header info */
2242   if (size_left) {
2243     GST_INFO_OBJECT (demux, "Audio header contains %d bytes of "
2244         "codec specific data", size_left);
2245
2246     g_assert (size_left <= *p_size);
2247     gst_asf_demux_get_buffer (&extradata, size_left, p_data, p_size);
2248   }
2249
2250   /* asf_stream_audio is the same as gst_riff_strf_auds, but with an
2251    * additional two bytes indicating extradata. */
2252   /* FIXME: Handle the channel reorder map here */
2253   caps = gst_riff_create_audio_caps (audio->codec_tag, NULL,
2254       (gst_riff_strf_auds *) audio, extradata, NULL, &codec_name, NULL);
2255
2256   if (caps == NULL) {
2257     caps = gst_caps_new_simple ("audio/x-asf-unknown", "codec_id",
2258         G_TYPE_INT, (gint) audio->codec_tag, NULL);
2259   }
2260
2261   /* Informing about that audio format we just added */
2262   if (codec_name) {
2263     tags = gst_tag_list_new (GST_TAG_AUDIO_CODEC, codec_name, NULL);
2264     g_free (codec_name);
2265   }
2266
2267   if (extradata)
2268     gst_buffer_unref (extradata);
2269
2270   GST_INFO ("Adding audio stream #%u, id %u codec %u (0x%04x), tags=%"
2271       GST_PTR_FORMAT, demux->num_audio_streams, id, audio->codec_tag,
2272       audio->codec_tag, tags);
2273
2274   ++demux->num_audio_streams;
2275
2276   gst_asf_demux_setup_pad (demux, src_pad, caps, id, FALSE, tags);
2277 }
2278
2279 static void
2280 gst_asf_demux_add_video_stream (GstASFDemux * demux,
2281     asf_stream_video_format * video, guint16 id,
2282     guint8 ** p_data, guint64 * p_size)
2283 {
2284   GstTagList *tags = NULL;
2285   GstBuffer *extradata = NULL;
2286   GstPad *src_pad;
2287   GstCaps *caps;
2288   gchar *str;
2289   gchar *name = NULL;
2290   gchar *codec_name = NULL;
2291   gint size_left = video->size - 40;
2292
2293   /* Create the video pad */
2294   name = g_strdup_printf ("video_%u", demux->num_video_streams);
2295   src_pad = gst_pad_new_from_static_template (&video_src_template, name);
2296   g_free (name);
2297
2298   /* Now try some gstreamer formatted MIME types (from gst_avi_demux_strf_vids) */
2299   if (size_left) {
2300     GST_LOG ("Video header has %d bytes of codec specific data", size_left);
2301     g_assert (size_left <= *p_size);
2302     gst_asf_demux_get_buffer (&extradata, size_left, p_data, p_size);
2303   }
2304
2305   GST_DEBUG ("video codec %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (video->tag));
2306
2307   /* yes, asf_stream_video_format and gst_riff_strf_vids are the same */
2308   caps = gst_riff_create_video_caps (video->tag, NULL,
2309       (gst_riff_strf_vids *) video, extradata, NULL, &codec_name);
2310
2311   if (caps == NULL) {
2312     caps = gst_caps_new_simple ("video/x-asf-unknown", "fourcc",
2313         G_TYPE_UINT, video->tag, NULL);
2314   } else {
2315     GstStructure *s;
2316     gint ax, ay;
2317
2318     s = gst_asf_demux_get_metadata_for_stream (demux, id);
2319     if (gst_structure_get_int (s, "AspectRatioX", &ax) &&
2320         gst_structure_get_int (s, "AspectRatioY", &ay) && (ax > 0 && ay > 0)) {
2321       gst_caps_set_simple (caps, "pixel-aspect-ratio", GST_TYPE_FRACTION,
2322           ax, ay, NULL);
2323
2324     } else {
2325       guint ax, ay;
2326       /* retry with the global metadata */
2327       GST_DEBUG ("Retrying with global metadata %" GST_PTR_FORMAT,
2328           demux->global_metadata);
2329       s = demux->global_metadata;
2330       if (gst_structure_get_uint (s, "AspectRatioX", &ax) &&
2331           gst_structure_get_uint (s, "AspectRatioY", &ay)) {
2332         GST_DEBUG ("ax:%d, ay:%d", ax, ay);
2333         if (ax > 0 && ay > 0)
2334           gst_caps_set_simple (caps, "pixel-aspect-ratio", GST_TYPE_FRACTION,
2335               ax, ay, NULL);
2336       }
2337     }
2338     s = gst_caps_get_structure (caps, 0);
2339     gst_structure_remove_field (s, "framerate");
2340   }
2341
2342   /* add fourcc format to caps, some proprietary decoders seem to need it */
2343   str = g_strdup_printf ("%" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (video->tag));
2344   gst_caps_set_simple (caps, "format", G_TYPE_STRING, str, NULL);
2345   g_free (str);
2346
2347   if (codec_name) {
2348     tags = gst_tag_list_new (GST_TAG_VIDEO_CODEC, codec_name, NULL);
2349     g_free (codec_name);
2350   }
2351
2352   if (extradata)
2353     gst_buffer_unref (extradata);
2354
2355   GST_INFO ("Adding video stream #%u, id %u, codec %"
2356       GST_FOURCC_FORMAT " (0x%08x)", demux->num_video_streams, id,
2357       GST_FOURCC_ARGS (video->tag), video->tag);
2358
2359   ++demux->num_video_streams;
2360
2361   gst_asf_demux_setup_pad (demux, src_pad, caps, id, TRUE, tags);
2362 }
2363
2364 static void
2365 gst_asf_demux_activate_stream (GstASFDemux * demux, AsfStream * stream)
2366 {
2367   if (!stream->active) {
2368     GST_INFO_OBJECT (demux, "Activating stream %2u, pad %s, caps %"
2369         GST_PTR_FORMAT, stream->id, GST_PAD_NAME (stream->pad), stream->caps);
2370     gst_pad_set_active (stream->pad, TRUE);
2371     gst_pad_set_caps (stream->pad, stream->caps);
2372     gst_element_add_pad (GST_ELEMENT_CAST (demux), stream->pad);
2373     gst_pad_push_event (stream->pad, gst_event_new_stream_start ());
2374     stream->active = TRUE;
2375   }
2376 }
2377
2378 static AsfStream *
2379 gst_asf_demux_parse_stream_object (GstASFDemux * demux, guint8 * data,
2380     guint64 size)
2381 {
2382   AsfCorrectionType correction_type;
2383   AsfStreamType stream_type;
2384   GstClockTime time_offset;
2385   gboolean is_encrypted G_GNUC_UNUSED;
2386   guint16 stream_id;
2387   guint16 flags;
2388   ASFGuid guid;
2389   guint stream_specific_size;
2390   guint type_specific_size G_GNUC_UNUSED;
2391   guint unknown G_GNUC_UNUSED;
2392
2393   /* Get the rest of the header's header */
2394   if (size < (16 + 16 + 8 + 4 + 4 + 2 + 4))
2395     goto not_enough_data;
2396
2397   gst_asf_demux_get_guid (&guid, &data, &size);
2398   stream_type = gst_asf_demux_identify_guid (asf_stream_guids, &guid);
2399
2400   gst_asf_demux_get_guid (&guid, &data, &size);
2401   correction_type = gst_asf_demux_identify_guid (asf_correction_guids, &guid);
2402
2403   time_offset = gst_asf_demux_get_uint64 (&data, &size) * 100;
2404
2405   type_specific_size = gst_asf_demux_get_uint32 (&data, &size);
2406   stream_specific_size = gst_asf_demux_get_uint32 (&data, &size);
2407
2408   flags = gst_asf_demux_get_uint16 (&data, &size);
2409   stream_id = flags & 0x7f;
2410   is_encrypted = ! !((flags & 0x8000) << 15);
2411   unknown = gst_asf_demux_get_uint32 (&data, &size);
2412
2413   GST_DEBUG_OBJECT (demux, "Found stream %u, time_offset=%" GST_TIME_FORMAT,
2414       stream_id, GST_TIME_ARGS (time_offset));
2415
2416   switch (stream_type) {
2417     case ASF_STREAM_AUDIO:{
2418       asf_stream_audio audio_object;
2419
2420       if (!gst_asf_demux_get_stream_audio (&audio_object, &data, &size))
2421         goto not_enough_data;
2422
2423       GST_INFO ("Object is an audio stream with %u bytes of additional data",
2424           audio_object.size);
2425
2426       gst_asf_demux_add_audio_stream (demux, &audio_object, stream_id,
2427           &data, &size);
2428
2429       switch (correction_type) {
2430         case ASF_CORRECTION_ON:{
2431           guint span, packet_size, chunk_size, data_size, silence_data;
2432
2433           GST_INFO ("Using error correction");
2434
2435           if (size < (1 + 2 + 2 + 2 + 1))
2436             goto not_enough_data;
2437
2438           span = gst_asf_demux_get_uint8 (&data, &size);
2439           packet_size = gst_asf_demux_get_uint16 (&data, &size);
2440           chunk_size = gst_asf_demux_get_uint16 (&data, &size);
2441           data_size = gst_asf_demux_get_uint16 (&data, &size);
2442           silence_data = gst_asf_demux_get_uint8 (&data, &size);
2443
2444           /* FIXME: shouldn't this be per-stream? */
2445           demux->span = span;
2446
2447           GST_DEBUG_OBJECT (demux, "Descrambling ps:%u cs:%u ds:%u s:%u sd:%u",
2448               packet_size, chunk_size, data_size, span, silence_data);
2449
2450           if (demux->span > 1) {
2451             if (chunk_size == 0 || ((packet_size / chunk_size) <= 1)) {
2452               /* Disable descrambling */
2453               demux->span = 0;
2454             } else {
2455               /* FIXME: this else branch was added for
2456                * weird_al_yankovic - the saga begins.asf */
2457               demux->ds_packet_size = packet_size;
2458               demux->ds_chunk_size = chunk_size;
2459             }
2460           } else {
2461             /* Descambling is enabled */
2462             demux->ds_packet_size = packet_size;
2463             demux->ds_chunk_size = chunk_size;
2464           }
2465 #if 0
2466           /* Now skip the rest of the silence data */
2467           if (data_size > 1)
2468             gst_bytestream_flush (demux->bs, data_size - 1);
2469 #else
2470           /* FIXME: CHECKME. And why -1? */
2471           if (data_size > 1) {
2472             if (!gst_asf_demux_skip_bytes (data_size - 1, &data, &size)) {
2473               goto not_enough_data;
2474             }
2475           }
2476 #endif
2477           break;
2478         }
2479         case ASF_CORRECTION_OFF:{
2480           GST_INFO ("Error correction off");
2481           if (!gst_asf_demux_skip_bytes (stream_specific_size, &data, &size))
2482             goto not_enough_data;
2483           break;
2484         }
2485         default:
2486           GST_ELEMENT_ERROR (demux, STREAM, DEMUX, (NULL),
2487               ("Audio stream using unknown error correction"));
2488           return NULL;
2489       }
2490
2491       break;
2492     }
2493
2494     case ASF_STREAM_VIDEO:{
2495       asf_stream_video_format video_format_object;
2496       asf_stream_video video_object;
2497       guint16 vsize;
2498
2499       if (!gst_asf_demux_get_stream_video (&video_object, &data, &size))
2500         goto not_enough_data;
2501
2502       vsize = video_object.size - 40;   /* Byte order gets offset by single byte */
2503
2504       GST_INFO ("object is a video stream with %u bytes of "
2505           "additional data", vsize);
2506
2507       if (!gst_asf_demux_get_stream_video_format (&video_format_object,
2508               &data, &size)) {
2509         goto not_enough_data;
2510       }
2511
2512       gst_asf_demux_add_video_stream (demux, &video_format_object, stream_id,
2513           &data, &size);
2514
2515       break;
2516     }
2517
2518     default:
2519       GST_WARNING_OBJECT (demux, "Unknown stream type for stream %u",
2520           stream_id);
2521       break;
2522   }
2523
2524   return gst_asf_demux_get_stream (demux, stream_id);
2525
2526 not_enough_data:
2527   {
2528     GST_WARNING_OBJECT (demux, "Unexpected end of data parsing stream object");
2529     /* we'll error out later if we found no streams */
2530     return NULL;
2531   }
2532 }
2533
2534 static const gchar *
2535 gst_asf_demux_get_gst_tag_from_tag_name (const gchar * name_utf8)
2536 {
2537   const struct
2538   {
2539     const gchar *asf_name;
2540     const gchar *gst_name;
2541   } tags[] = {
2542     {
2543     "WM/Genre", GST_TAG_GENRE}, {
2544     "WM/AlbumTitle", GST_TAG_ALBUM}, {
2545     "WM/AlbumArtist", GST_TAG_ARTIST}, {
2546     "WM/Picture", GST_TAG_IMAGE}, {
2547     "WM/Track", GST_TAG_TRACK_NUMBER}, {
2548     "WM/TrackNumber", GST_TAG_TRACK_NUMBER}, {
2549     "WM/Year", GST_TAG_DATE_TIME}
2550     /* { "WM/Composer", GST_TAG_COMPOSER } */
2551   };
2552   gsize out;
2553   guint i;
2554
2555   if (name_utf8 == NULL) {
2556     GST_WARNING ("Failed to convert name to UTF8, skipping");
2557     return NULL;
2558   }
2559
2560   out = strlen (name_utf8);
2561
2562   for (i = 0; i < G_N_ELEMENTS (tags); ++i) {
2563     if (strncmp (tags[i].asf_name, name_utf8, out) == 0) {
2564       GST_LOG ("map tagname '%s' -> '%s'", name_utf8, tags[i].gst_name);
2565       return tags[i].gst_name;
2566     }
2567   }
2568
2569   return NULL;
2570 }
2571
2572 /* gst_asf_demux_add_global_tags() takes ownership of taglist! */
2573 static void
2574 gst_asf_demux_add_global_tags (GstASFDemux * demux, GstTagList * taglist)
2575 {
2576   GstTagList *t;
2577
2578   GST_DEBUG_OBJECT (demux, "adding global tags: %" GST_PTR_FORMAT, taglist);
2579
2580   if (taglist == NULL)
2581     return;
2582
2583   if (gst_tag_list_is_empty (taglist)) {
2584     gst_tag_list_free (taglist);
2585     return;
2586   }
2587
2588   t = gst_tag_list_merge (demux->taglist, taglist, GST_TAG_MERGE_APPEND);
2589   if (demux->taglist)
2590     gst_tag_list_free (demux->taglist);
2591   gst_tag_list_free (taglist);
2592   demux->taglist = t;
2593   GST_LOG_OBJECT (demux, "global tags now: %" GST_PTR_FORMAT, demux->taglist);
2594 }
2595
2596 #define ASF_DEMUX_DATA_TYPE_UTF16LE_STRING  0
2597 #define ASF_DEMUX_DATA_TYPE_BYTE_ARRAY      1
2598 #define ASF_DEMUX_DATA_TYPE_DWORD           3
2599
2600 static void
2601 asf_demux_parse_picture_tag (GstTagList * tags, const guint8 * tag_data,
2602     guint tag_data_len)
2603 {
2604   GstByteReader r;
2605   const guint8 *img_data = NULL;
2606   guint32 img_data_len = 0;
2607   guint8 pic_type = 0;
2608
2609   gst_byte_reader_init (&r, tag_data, tag_data_len);
2610
2611   /* skip mime type string (we don't trust it and do our own typefinding),
2612    * and also skip the description string, since we don't use it */
2613   if (!gst_byte_reader_get_uint8 (&r, &pic_type) ||
2614       !gst_byte_reader_get_uint32_le (&r, &img_data_len) ||
2615       !gst_byte_reader_skip_string_utf16 (&r) ||
2616       !gst_byte_reader_skip_string_utf16 (&r) ||
2617       !gst_byte_reader_get_data (&r, img_data_len, &img_data)) {
2618     goto not_enough_data;
2619   }
2620
2621
2622   if (!gst_tag_list_add_id3_image (tags, img_data, img_data_len, pic_type))
2623     GST_DEBUG ("failed to add image extracted from WM/Picture tag to taglist");
2624
2625   return;
2626
2627 not_enough_data:
2628   {
2629     GST_DEBUG ("Failed to read WM/Picture tag: not enough data");
2630     GST_MEMDUMP ("WM/Picture data", tag_data, tag_data_len);
2631     return;
2632   }
2633 }
2634
2635 /* Extended Content Description Object */
2636 static GstFlowReturn
2637 gst_asf_demux_process_ext_content_desc (GstASFDemux * demux, guint8 * data,
2638     guint64 size)
2639 {
2640   /* Other known (and unused) 'text/unicode' metadata available :
2641    *
2642    *   WM/Lyrics =
2643    *   WM/MediaPrimaryClassID = {D1607DBC-E323-4BE2-86A1-48A42A28441E}
2644    *   WMFSDKVersion = 9.00.00.2980
2645    *   WMFSDKNeeded = 0.0.0.0000
2646    *   WM/UniqueFileIdentifier = AMGa_id=R    15334;AMGp_id=P     5149;AMGt_id=T  2324984
2647    *   WM/Publisher = 4AD
2648    *   WM/Provider = AMG
2649    *   WM/ProviderRating = 8
2650    *   WM/ProviderStyle = Rock (similar to WM/Genre)
2651    *   WM/GenreID (similar to WM/Genre)
2652    *   WM/TrackNumber (same as WM/Track but as a string)
2653    *
2654    * Other known (and unused) 'non-text' metadata available :
2655    *
2656    *   WM/EncodingTime
2657    *   WM/MCDI
2658    *   IsVBR
2659    *
2660    * We might want to read WM/TrackNumber and use atoi() if we don't have
2661    * WM/Track
2662    */
2663
2664   GstTagList *taglist;
2665   guint16 blockcount, i;
2666
2667   GST_INFO_OBJECT (demux, "object is an extended content description");
2668
2669   taglist = gst_tag_list_new_empty ();
2670
2671   /* Content Descriptor Count */
2672   if (size < 2)
2673     goto not_enough_data;
2674
2675   blockcount = gst_asf_demux_get_uint16 (&data, &size);
2676
2677   for (i = 1; i <= blockcount; ++i) {
2678     const gchar *gst_tag_name;
2679     guint16 datatype;
2680     guint16 value_len;
2681     guint16 name_len;
2682     GValue tag_value = { 0, };
2683     gsize in, out;
2684     gchar *name;
2685     gchar *name_utf8 = NULL;
2686     gchar *value;
2687
2688     /* Descriptor */
2689     if (!gst_asf_demux_get_string (&name, &name_len, &data, &size))
2690       goto not_enough_data;
2691
2692     if (size < 2) {
2693       g_free (name);
2694       goto not_enough_data;
2695     }
2696     /* Descriptor Value Data Type */
2697     datatype = gst_asf_demux_get_uint16 (&data, &size);
2698
2699     /* Descriptor Value (not really a string, but same thing reading-wise) */
2700     if (!gst_asf_demux_get_string (&value, &value_len, &data, &size)) {
2701       g_free (name);
2702       goto not_enough_data;
2703     }
2704
2705     name_utf8 =
2706         g_convert (name, name_len, "UTF-8", "UTF-16LE", &in, &out, NULL);
2707
2708     if (name_utf8 != NULL) {
2709       GST_DEBUG ("Found tag/metadata %s", name_utf8);
2710
2711       gst_tag_name = gst_asf_demux_get_gst_tag_from_tag_name (name_utf8);
2712       GST_DEBUG ("gst_tag_name %s", GST_STR_NULL (gst_tag_name));
2713
2714       switch (datatype) {
2715         case ASF_DEMUX_DATA_TYPE_UTF16LE_STRING:{
2716           gchar *value_utf8;
2717
2718           value_utf8 = g_convert (value, value_len, "UTF-8", "UTF-16LE",
2719               &in, &out, NULL);
2720
2721           /* get rid of tags with empty value */
2722           if (value_utf8 != NULL && *value_utf8 != '\0') {
2723             GST_DEBUG ("string value %s", value_utf8);
2724
2725             value_utf8[out] = '\0';
2726
2727             if (gst_tag_name != NULL) {
2728               if (strcmp (gst_tag_name, GST_TAG_DATE_TIME) == 0) {
2729                 guint year = atoi (value_utf8);
2730
2731                 if (year > 0) {
2732                   g_value_init (&tag_value, GST_TYPE_DATE_TIME);
2733                   g_value_take_boxed (&tag_value, gst_date_time_new_y (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 }