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