fix interlace-mode
[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     /* FIXME: maybe we should just skip broken packets and error out only
1625      * after a few broken packets in a row? */
1626     if (G_UNLIKELY (!gst_asf_demux_parse_packet (demux, buf))) {
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       goto parse_error;
1639     }
1640
1641     flow = gst_asf_demux_push_complete_payloads (demux, FALSE);
1642
1643     ++demux->packet;
1644
1645   } else {
1646     guint n;
1647     for (n = 0; n < demux->speed_packets; n++) {
1648       GstBuffer *sub;
1649
1650       sub =
1651           gst_buffer_copy_region (buf, GST_BUFFER_COPY_NONE,
1652           n * demux->packet_size, demux->packet_size);
1653       /* FIXME: maybe we should just skip broken packets and error out only
1654        * after a few broken packets in a row? */
1655       if (G_UNLIKELY (!gst_asf_demux_parse_packet (demux, sub))) {
1656         /* when we don't know when the data object ends, we should check
1657          * for a chained asf */
1658         if (demux->num_packets == 0) {
1659           if (gst_asf_demux_check_buffer_is_header (demux, sub)) {
1660             GST_INFO_OBJECT (demux, "Chained asf found");
1661             demux->base_offset = off + n * demux->packet_size;
1662             gst_asf_demux_reset (demux, TRUE);
1663             gst_buffer_unref (sub);
1664             gst_buffer_unref (buf);
1665             return;
1666           }
1667         }
1668         goto parse_error;
1669       }
1670
1671       gst_buffer_unref (sub);
1672
1673       flow = gst_asf_demux_push_complete_payloads (demux, FALSE);
1674
1675       ++demux->packet;
1676
1677     }
1678
1679     /* reset speed pull */
1680     demux->speed_packets = 1;
1681   }
1682
1683   gst_buffer_unref (buf);
1684
1685   if (G_UNLIKELY (demux->num_packets > 0
1686           && demux->packet >= demux->num_packets)) {
1687     GST_LOG_OBJECT (demux, "reached EOS");
1688     goto eos;
1689   }
1690
1691   if (G_UNLIKELY (flow != GST_FLOW_OK)) {
1692     GST_DEBUG_OBJECT (demux, "pushing complete payloads failed");
1693     goto pause;
1694   }
1695
1696   /* check if we're at the end of the configured segment */
1697   /* FIXME: check if segment end reached etc. */
1698
1699   return;
1700
1701 eos:
1702   {
1703     /* if we haven't activated our streams yet, this might be because we have
1704      * less data queued than required for preroll; force stream activation and
1705      * send any pending payloads before sending EOS */
1706     if (!demux->activated_streams)
1707       gst_asf_demux_push_complete_payloads (demux, TRUE);
1708
1709     /* we want to push an eos or post a segment-done in any case */
1710     if (demux->segment.flags & GST_SEEK_FLAG_SEGMENT) {
1711       gint64 stop;
1712
1713       /* for segment playback we need to post when (in stream time)
1714        * we stopped, this is either stop (when set) or the duration. */
1715       if ((stop = demux->segment.stop) == -1)
1716         stop = demux->segment.duration;
1717
1718       GST_INFO_OBJECT (demux, "Posting segment-done, at end of segment");
1719       gst_element_post_message (GST_ELEMENT_CAST (demux),
1720           gst_message_new_segment_done (GST_OBJECT (demux), GST_FORMAT_TIME,
1721               stop));
1722     } else if (flow != GST_FLOW_EOS) {
1723       /* check if we have a chained asf, in case, we don't eos yet */
1724       if (gst_asf_demux_check_chained_asf (demux)) {
1725         GST_INFO_OBJECT (demux, "Chained ASF starting");
1726         gst_asf_demux_reset (demux, TRUE);
1727         return;
1728       }
1729     }
1730     /* normal playback, send EOS to all linked pads */
1731     GST_INFO_OBJECT (demux, "Sending EOS, at end of stream");
1732     gst_asf_demux_send_event_unlocked (demux, gst_event_new_eos ());
1733     sent_eos = TRUE;
1734     /* ... and fall through to pause */
1735   }
1736 pause:
1737   {
1738     GST_DEBUG_OBJECT (demux, "pausing task, flow return: %s",
1739         gst_flow_get_name (flow));
1740     demux->segment_running = FALSE;
1741     gst_pad_pause_task (demux->sinkpad);
1742
1743     /* For the error cases (not EOS) */
1744     if (!sent_eos) {
1745       if (flow == GST_FLOW_EOS)
1746         gst_asf_demux_send_event_unlocked (demux, gst_event_new_eos ());
1747       else if (flow < GST_FLOW_EOS || flow == GST_FLOW_NOT_LINKED) {
1748         /* Post an error. Hopefully something else already has, but if not... */
1749         GST_ELEMENT_ERROR (demux, STREAM, FAILED,
1750             (_("Internal data stream error.")),
1751             ("streaming stopped, reason %s", gst_flow_get_name (flow)));
1752       }
1753     }
1754     return;
1755   }
1756
1757 /* ERRORS */
1758 read_failed:
1759   {
1760     GST_DEBUG_OBJECT (demux, "Read failed, doh");
1761     gst_asf_demux_send_event_unlocked (demux, gst_event_new_eos ());
1762     flow = GST_FLOW_EOS;
1763     goto pause;
1764   }
1765 parse_error:
1766   {
1767     gst_buffer_unref (buf);
1768     GST_ELEMENT_ERROR (demux, STREAM, DEMUX, (NULL),
1769         ("Error parsing ASF packet %u", (guint) demux->packet));
1770     gst_asf_demux_send_event_unlocked (demux, gst_event_new_eos ());
1771     flow = GST_FLOW_ERROR;
1772     goto pause;
1773   }
1774 }
1775
1776 #define GST_ASF_DEMUX_CHECK_HEADER_YES       0
1777 #define GST_ASF_DEMUX_CHECK_HEADER_NO        1
1778 #define GST_ASF_DEMUX_CHECK_HEADER_NEED_DATA 2
1779
1780 static gint
1781 gst_asf_demux_check_header (GstASFDemux * demux)
1782 {
1783   AsfObject obj;
1784   guint8 *cdata = (guint8 *) gst_adapter_map (demux->adapter,
1785       ASF_OBJECT_HEADER_SIZE);
1786   if (cdata == NULL)            /* need more data */
1787     return GST_ASF_DEMUX_CHECK_HEADER_NEED_DATA;
1788
1789   asf_demux_peek_object (demux, cdata, ASF_OBJECT_HEADER_SIZE, &obj, FALSE);
1790   if (obj.id != ASF_OBJ_HEADER) {
1791     return GST_ASF_DEMUX_CHECK_HEADER_NO;
1792   } else {
1793     return GST_ASF_DEMUX_CHECK_HEADER_YES;
1794   }
1795 }
1796
1797 static GstFlowReturn
1798 gst_asf_demux_chain (GstPad * pad, GstObject * parent, GstBuffer * buf)
1799 {
1800   GstFlowReturn ret = GST_FLOW_OK;
1801   GstASFDemux *demux;
1802
1803   demux = GST_ASF_DEMUX (parent);
1804
1805   GST_LOG_OBJECT (demux,
1806       "buffer: size=%" G_GSIZE_FORMAT ", offset=%" G_GINT64_FORMAT ", time=%"
1807       GST_TIME_FORMAT, gst_buffer_get_size (buf), GST_BUFFER_OFFSET (buf),
1808       GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)));
1809
1810   if (G_UNLIKELY (GST_BUFFER_IS_DISCONT (buf))) {
1811     GST_DEBUG_OBJECT (demux, "received DISCONT");
1812     gst_asf_demux_mark_discont (demux);
1813   }
1814
1815   if (G_UNLIKELY ((!GST_CLOCK_TIME_IS_VALID (demux->in_gap) &&
1816               GST_BUFFER_TIMESTAMP_IS_VALID (buf)))) {
1817     demux->in_gap = GST_BUFFER_TIMESTAMP (buf) - demux->in_segment.start;
1818     GST_DEBUG_OBJECT (demux, "upstream segment start %" GST_TIME_FORMAT
1819         ", interpolation gap: %" GST_TIME_FORMAT,
1820         GST_TIME_ARGS (demux->in_segment.start), GST_TIME_ARGS (demux->in_gap));
1821   }
1822
1823   gst_adapter_push (demux->adapter, buf);
1824
1825   switch (demux->state) {
1826     case GST_ASF_DEMUX_STATE_INDEX:{
1827       gint result = gst_asf_demux_check_header (demux);
1828       if (result == GST_ASF_DEMUX_CHECK_HEADER_NEED_DATA)       /* need more data */
1829         break;
1830
1831       if (result == GST_ASF_DEMUX_CHECK_HEADER_NO) {
1832         /* we don't care about this, probably an index */
1833         /* TODO maybe would be smarter to skip all the indices
1834          * until we got a new header or EOS to decide */
1835         GST_LOG_OBJECT (demux, "Received index object, its EOS");
1836         goto eos;
1837       } else {
1838         GST_INFO_OBJECT (demux, "Chained asf starting");
1839         /* cleanup and get ready for a chained asf */
1840         gst_asf_demux_reset (demux, TRUE);
1841         /* fall through */
1842       }
1843     }
1844     case GST_ASF_DEMUX_STATE_HEADER:{
1845       ret = gst_asf_demux_chain_headers (demux);
1846       if (demux->state != GST_ASF_DEMUX_STATE_DATA)
1847         break;
1848       /* otherwise fall through */
1849     }
1850     case GST_ASF_DEMUX_STATE_DATA:
1851     {
1852       guint64 data_size;
1853
1854       data_size = demux->packet_size;
1855
1856       while (gst_adapter_available (demux->adapter) >= data_size) {
1857         GstBuffer *buf;
1858
1859         /* we don't know the length of the stream
1860          * check for a chained asf everytime */
1861         if (demux->num_packets == 0) {
1862           gint result = gst_asf_demux_check_header (demux);
1863
1864           if (result == GST_ASF_DEMUX_CHECK_HEADER_YES) {
1865             GST_INFO_OBJECT (demux, "Chained asf starting");
1866             /* cleanup and get ready for a chained asf */
1867             gst_asf_demux_reset (demux, TRUE);
1868             break;
1869           }
1870         } else if (G_UNLIKELY (demux->num_packets != 0 && demux->packet >= 0
1871                 && demux->packet >= demux->num_packets)) {
1872           /* do not overshoot data section when streaming */
1873           break;
1874         }
1875
1876         buf = gst_adapter_take_buffer (demux->adapter, data_size);
1877
1878         /* FIXME: maybe we should just skip broken packets and error out only
1879          * after a few broken packets in a row? */
1880         if (G_UNLIKELY (!gst_asf_demux_parse_packet (demux, buf))) {
1881           GST_WARNING_OBJECT (demux, "Parse error");
1882         }
1883
1884         gst_buffer_unref (buf);
1885
1886         ret = gst_asf_demux_push_complete_payloads (demux, FALSE);
1887
1888         if (demux->packet >= 0)
1889           ++demux->packet;
1890       }
1891       if (G_UNLIKELY (demux->num_packets != 0 && demux->packet >= 0
1892               && demux->packet >= demux->num_packets)) {
1893         demux->state = GST_ASF_DEMUX_STATE_INDEX;
1894       }
1895       break;
1896     }
1897     default:
1898       g_assert_not_reached ();
1899   }
1900
1901 done:
1902   if (ret != GST_FLOW_OK)
1903     GST_DEBUG_OBJECT (demux, "flow: %s", gst_flow_get_name (ret));
1904
1905   return ret;
1906
1907 eos:
1908   {
1909     GST_DEBUG_OBJECT (demux, "Handled last packet, setting EOS");
1910     ret = GST_FLOW_EOS;
1911     goto done;
1912   }
1913 }
1914
1915 static inline gboolean
1916 gst_asf_demux_skip_bytes (guint num_bytes, guint8 ** p_data, guint64 * p_size)
1917 {
1918   if (*p_size < num_bytes)
1919     return FALSE;
1920
1921   *p_data += num_bytes;
1922   *p_size -= num_bytes;
1923   return TRUE;
1924 }
1925
1926 static inline guint8
1927 gst_asf_demux_get_uint8 (guint8 ** p_data, guint64 * p_size)
1928 {
1929   guint8 ret;
1930
1931   g_assert (*p_size >= 1);
1932   ret = GST_READ_UINT8 (*p_data);
1933   *p_data += sizeof (guint8);
1934   *p_size -= sizeof (guint8);
1935   return ret;
1936 }
1937
1938 static inline guint16
1939 gst_asf_demux_get_uint16 (guint8 ** p_data, guint64 * p_size)
1940 {
1941   guint16 ret;
1942
1943   g_assert (*p_size >= 2);
1944   ret = GST_READ_UINT16_LE (*p_data);
1945   *p_data += sizeof (guint16);
1946   *p_size -= sizeof (guint16);
1947   return ret;
1948 }
1949
1950 static inline guint32
1951 gst_asf_demux_get_uint32 (guint8 ** p_data, guint64 * p_size)
1952 {
1953   guint32 ret;
1954
1955   g_assert (*p_size >= 4);
1956   ret = GST_READ_UINT32_LE (*p_data);
1957   *p_data += sizeof (guint32);
1958   *p_size -= sizeof (guint32);
1959   return ret;
1960 }
1961
1962 static inline guint64
1963 gst_asf_demux_get_uint64 (guint8 ** p_data, guint64 * p_size)
1964 {
1965   guint64 ret;
1966
1967   g_assert (*p_size >= 8);
1968   ret = GST_READ_UINT64_LE (*p_data);
1969   *p_data += sizeof (guint64);
1970   *p_size -= sizeof (guint64);
1971   return ret;
1972 }
1973
1974 static inline guint32
1975 gst_asf_demux_get_var_length (guint8 type, guint8 ** p_data, guint64 * p_size)
1976 {
1977   switch (type) {
1978     case 0:
1979       return 0;
1980
1981     case 1:
1982       g_assert (*p_size >= 1);
1983       return gst_asf_demux_get_uint8 (p_data, p_size);
1984
1985     case 2:
1986       g_assert (*p_size >= 2);
1987       return gst_asf_demux_get_uint16 (p_data, p_size);
1988
1989     case 3:
1990       g_assert (*p_size >= 4);
1991       return gst_asf_demux_get_uint32 (p_data, p_size);
1992
1993     default:
1994       g_assert_not_reached ();
1995       break;
1996   }
1997   return 0;
1998 }
1999
2000 static gboolean
2001 gst_asf_demux_get_buffer (GstBuffer ** p_buf, guint num_bytes_to_read,
2002     guint8 ** p_data, guint64 * p_size)
2003 {
2004   *p_buf = NULL;
2005
2006   if (*p_size < num_bytes_to_read)
2007     return FALSE;
2008
2009   *p_buf = gst_buffer_new_and_alloc (num_bytes_to_read);
2010   gst_buffer_fill (*p_buf, 0, *p_data, num_bytes_to_read);
2011
2012   *p_data += num_bytes_to_read;
2013   *p_size -= num_bytes_to_read;
2014
2015   return TRUE;
2016 }
2017
2018 static gboolean
2019 gst_asf_demux_get_bytes (guint8 ** 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 = g_memdup (*p_data, num_bytes_to_read);
2028   *p_data += num_bytes_to_read;
2029   *p_size -= num_bytes_to_read;
2030   return TRUE;
2031 }
2032
2033 static gboolean
2034 gst_asf_demux_get_string (gchar ** p_str, guint16 * p_strlen,
2035     guint8 ** p_data, guint64 * p_size)
2036 {
2037   guint16 s_length;
2038   guint8 *s;
2039
2040   *p_str = NULL;
2041
2042   if (*p_size < 2)
2043     return FALSE;
2044
2045   s_length = gst_asf_demux_get_uint16 (p_data, p_size);
2046
2047   if (p_strlen)
2048     *p_strlen = s_length;
2049
2050   if (s_length == 0) {
2051     GST_WARNING ("zero-length string");
2052     *p_str = g_strdup ("");
2053     return TRUE;
2054   }
2055
2056   if (!gst_asf_demux_get_bytes (&s, s_length, p_data, p_size))
2057     return FALSE;
2058
2059   g_assert (s != NULL);
2060
2061   /* just because They don't exist doesn't
2062    * mean They are not out to get you ... */
2063   if (s[s_length - 1] != '\0') {
2064     s = g_realloc (s, s_length + 1);
2065     s[s_length] = '\0';
2066   }
2067
2068   *p_str = (gchar *) s;
2069   return TRUE;
2070 }
2071
2072
2073 static void
2074 gst_asf_demux_get_guid (ASFGuid * guid, guint8 ** p_data, guint64 * p_size)
2075 {
2076   g_assert (*p_size >= 4 * sizeof (guint32));
2077
2078   guid->v1 = gst_asf_demux_get_uint32 (p_data, p_size);
2079   guid->v2 = gst_asf_demux_get_uint32 (p_data, p_size);
2080   guid->v3 = gst_asf_demux_get_uint32 (p_data, p_size);
2081   guid->v4 = gst_asf_demux_get_uint32 (p_data, p_size);
2082 }
2083
2084 static gboolean
2085 gst_asf_demux_get_stream_audio (asf_stream_audio * audio, guint8 ** p_data,
2086     guint64 * p_size)
2087 {
2088   if (*p_size < (2 + 2 + 4 + 4 + 2 + 2 + 2))
2089     return FALSE;
2090
2091   /* WAVEFORMATEX Structure */
2092   audio->codec_tag = gst_asf_demux_get_uint16 (p_data, p_size);
2093   audio->channels = gst_asf_demux_get_uint16 (p_data, p_size);
2094   audio->sample_rate = gst_asf_demux_get_uint32 (p_data, p_size);
2095   audio->byte_rate = gst_asf_demux_get_uint32 (p_data, p_size);
2096   audio->block_align = gst_asf_demux_get_uint16 (p_data, p_size);
2097   audio->word_size = gst_asf_demux_get_uint16 (p_data, p_size);
2098   /* Codec specific data size */
2099   audio->size = gst_asf_demux_get_uint16 (p_data, p_size);
2100   return TRUE;
2101 }
2102
2103 static gboolean
2104 gst_asf_demux_get_stream_video (asf_stream_video * video, guint8 ** p_data,
2105     guint64 * p_size)
2106 {
2107   if (*p_size < (4 + 4 + 1 + 2))
2108     return FALSE;
2109
2110   video->width = gst_asf_demux_get_uint32 (p_data, p_size);
2111   video->height = gst_asf_demux_get_uint32 (p_data, p_size);
2112   video->unknown = gst_asf_demux_get_uint8 (p_data, p_size);
2113   video->size = gst_asf_demux_get_uint16 (p_data, p_size);
2114   return TRUE;
2115 }
2116
2117 static gboolean
2118 gst_asf_demux_get_stream_video_format (asf_stream_video_format * fmt,
2119     guint8 ** p_data, guint64 * p_size)
2120 {
2121   if (*p_size < (4 + 4 + 4 + 2 + 2 + 4 + 4 + 4 + 4 + 4 + 4))
2122     return FALSE;
2123
2124   fmt->size = gst_asf_demux_get_uint32 (p_data, p_size);
2125   fmt->width = gst_asf_demux_get_uint32 (p_data, p_size);
2126   fmt->height = gst_asf_demux_get_uint32 (p_data, p_size);
2127   fmt->planes = gst_asf_demux_get_uint16 (p_data, p_size);
2128   fmt->depth = gst_asf_demux_get_uint16 (p_data, p_size);
2129   fmt->tag = gst_asf_demux_get_uint32 (p_data, p_size);
2130   fmt->image_size = gst_asf_demux_get_uint32 (p_data, p_size);
2131   fmt->xpels_meter = gst_asf_demux_get_uint32 (p_data, p_size);
2132   fmt->ypels_meter = gst_asf_demux_get_uint32 (p_data, p_size);
2133   fmt->num_colors = gst_asf_demux_get_uint32 (p_data, p_size);
2134   fmt->imp_colors = gst_asf_demux_get_uint32 (p_data, p_size);
2135   return TRUE;
2136 }
2137
2138 AsfStream *
2139 gst_asf_demux_get_stream (GstASFDemux * demux, guint16 id)
2140 {
2141   guint i;
2142
2143   for (i = 0; i < demux->num_streams; i++) {
2144     if (demux->stream[i].id == id)
2145       return &demux->stream[i];
2146   }
2147
2148   GST_WARNING ("Segment found for undefined stream: (%d)", id);
2149   return NULL;
2150 }
2151
2152 static void
2153 gst_asf_demux_setup_pad (GstASFDemux * demux, GstPad * src_pad,
2154     GstCaps * caps, guint16 id, gboolean is_video, GstTagList * tags)
2155 {
2156   AsfStream *stream;
2157
2158   gst_pad_use_fixed_caps (src_pad);
2159   gst_pad_set_caps (src_pad, caps);
2160
2161   gst_pad_set_event_function (src_pad,
2162       GST_DEBUG_FUNCPTR (gst_asf_demux_handle_src_event));
2163   gst_pad_set_query_function (src_pad,
2164       GST_DEBUG_FUNCPTR (gst_asf_demux_handle_src_query));
2165
2166   stream = &demux->stream[demux->num_streams];
2167   stream->caps = caps;
2168   stream->pad = src_pad;
2169   stream->id = id;
2170   stream->fps_known = !is_video;        /* bit hacky for audio */
2171   stream->is_video = is_video;
2172   stream->pending_tags = tags;
2173   stream->discont = TRUE;
2174   if (is_video) {
2175     GstStructure *st;
2176     gint par_x, par_y;
2177     st = gst_caps_get_structure (caps, 0);
2178     if (gst_structure_get_fraction (st, "pixel-aspect-ratio", &par_x, &par_y) &&
2179         par_x > 0 && par_y > 0) {
2180       GST_DEBUG ("PAR %d/%d", par_x, par_y);
2181       stream->par_x = par_x;
2182       stream->par_y = par_y;
2183     }
2184   }
2185
2186   stream->payloads = g_array_new (FALSE, FALSE, sizeof (AsfPayload));
2187
2188   GST_INFO ("Created pad %s for stream %u with caps %" GST_PTR_FORMAT,
2189       GST_PAD_NAME (src_pad), demux->num_streams, caps);
2190
2191   ++demux->num_streams;
2192
2193   stream->active = FALSE;
2194 }
2195
2196 static void
2197 gst_asf_demux_add_audio_stream (GstASFDemux * demux,
2198     asf_stream_audio * audio, guint16 id, guint8 ** p_data, guint64 * p_size)
2199 {
2200   GstTagList *tags = NULL;
2201   GstBuffer *extradata = NULL;
2202   GstPad *src_pad;
2203   GstCaps *caps;
2204   guint16 size_left = 0;
2205   gchar *codec_name = NULL;
2206   gchar *name = NULL;
2207
2208   size_left = audio->size;
2209
2210   /* Create the audio pad */
2211   name = g_strdup_printf ("audio_%u", demux->num_audio_streams);
2212
2213   src_pad = gst_pad_new_from_static_template (&audio_src_template, name);
2214   g_free (name);
2215
2216   /* Swallow up any left over data and set up the 
2217    * standard properties from the header info */
2218   if (size_left) {
2219     GST_INFO_OBJECT (demux, "Audio header contains %d bytes of "
2220         "codec specific data", size_left);
2221
2222     g_assert (size_left <= *p_size);
2223     gst_asf_demux_get_buffer (&extradata, size_left, p_data, p_size);
2224   }
2225
2226   /* asf_stream_audio is the same as gst_riff_strf_auds, but with an
2227    * additional two bytes indicating extradata. */
2228   /* FIXME: Handle the channel reorder map here */
2229   caps = gst_riff_create_audio_caps (audio->codec_tag, NULL,
2230       (gst_riff_strf_auds *) audio, extradata, NULL, &codec_name, NULL);
2231
2232   if (caps == NULL) {
2233     caps = gst_caps_new_simple ("audio/x-asf-unknown", "codec_id",
2234         G_TYPE_INT, (gint) audio->codec_tag, NULL);
2235   }
2236
2237   /* Informing about that audio format we just added */
2238   if (codec_name) {
2239     tags = gst_tag_list_new (GST_TAG_AUDIO_CODEC, codec_name, NULL);
2240     g_free (codec_name);
2241   }
2242
2243   if (extradata)
2244     gst_buffer_unref (extradata);
2245
2246   GST_INFO ("Adding audio stream #%u, id %u codec %u (0x%04x), tags=%"
2247       GST_PTR_FORMAT, demux->num_audio_streams, id, audio->codec_tag,
2248       audio->codec_tag, tags);
2249
2250   ++demux->num_audio_streams;
2251
2252   gst_asf_demux_setup_pad (demux, src_pad, caps, id, FALSE, tags);
2253 }
2254
2255 static void
2256 gst_asf_demux_add_video_stream (GstASFDemux * demux,
2257     asf_stream_video_format * video, guint16 id,
2258     guint8 ** p_data, guint64 * p_size)
2259 {
2260   GstTagList *tags = NULL;
2261   GstBuffer *extradata = NULL;
2262   GstPad *src_pad;
2263   GstCaps *caps;
2264   gchar *name = NULL;
2265   gchar *codec_name = NULL;
2266   gint size_left = video->size - 40;
2267
2268   /* Create the video pad */
2269   name = g_strdup_printf ("video_%u", demux->num_video_streams);
2270   src_pad = gst_pad_new_from_static_template (&video_src_template, name);
2271   g_free (name);
2272
2273   /* Now try some gstreamer formatted MIME types (from gst_avi_demux_strf_vids) */
2274   if (size_left) {
2275     GST_LOG ("Video header has %d bytes of codec specific data", size_left);
2276     g_assert (size_left <= *p_size);
2277     gst_asf_demux_get_buffer (&extradata, size_left, p_data, p_size);
2278   }
2279
2280   GST_DEBUG ("video codec %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (video->tag));
2281
2282   /* yes, asf_stream_video_format and gst_riff_strf_vids are the same */
2283   caps = gst_riff_create_video_caps (video->tag, NULL,
2284       (gst_riff_strf_vids *) video, extradata, NULL, &codec_name);
2285
2286   if (caps == NULL) {
2287     caps = gst_caps_new_simple ("video/x-asf-unknown", "fourcc",
2288         G_TYPE_UINT, video->tag, NULL);
2289   } else {
2290     GstStructure *s;
2291     gint ax, ay;
2292
2293     s = gst_asf_demux_get_metadata_for_stream (demux, id);
2294     if (gst_structure_get_int (s, "AspectRatioX", &ax) &&
2295         gst_structure_get_int (s, "AspectRatioY", &ay) && (ax > 0 && ay > 0)) {
2296       gst_caps_set_simple (caps, "pixel-aspect-ratio", GST_TYPE_FRACTION,
2297           ax, ay, NULL);
2298
2299     } else {
2300       guint ax, ay;
2301       /* retry with the global metadata */
2302       GST_DEBUG ("Retrying with global metadata %" GST_PTR_FORMAT,
2303           demux->global_metadata);
2304       s = demux->global_metadata;
2305       if (gst_structure_get_uint (s, "AspectRatioX", &ax) &&
2306           gst_structure_get_uint (s, "AspectRatioY", &ay)) {
2307         GST_DEBUG ("ax:%d, ay:%d", ax, ay);
2308         if (ax > 0 && ay > 0)
2309           gst_caps_set_simple (caps, "pixel-aspect-ratio", GST_TYPE_FRACTION,
2310               ax, ay, NULL);
2311       }
2312     }
2313     s = gst_caps_get_structure (caps, 0);
2314     gst_structure_remove_field (s, "framerate");
2315   }
2316
2317   /* add fourcc format to caps, some proprietary decoders seem to need it */
2318   gst_caps_set_simple (caps, "format", G_TYPE_UINT, video->tag, NULL);
2319
2320   if (codec_name) {
2321     tags = gst_tag_list_new (GST_TAG_VIDEO_CODEC, codec_name, NULL);
2322     g_free (codec_name);
2323   }
2324
2325   if (extradata)
2326     gst_buffer_unref (extradata);
2327
2328   GST_INFO ("Adding video stream #%u, id %u, codec %"
2329       GST_FOURCC_FORMAT " (0x%08x)", demux->num_video_streams, id,
2330       GST_FOURCC_ARGS (video->tag), video->tag);
2331
2332   ++demux->num_video_streams;
2333
2334   gst_asf_demux_setup_pad (demux, src_pad, caps, id, TRUE, tags);
2335 }
2336
2337 static void
2338 gst_asf_demux_activate_stream (GstASFDemux * demux, AsfStream * stream)
2339 {
2340   if (!stream->active) {
2341     GST_INFO_OBJECT (demux, "Activating stream %2u, pad %s, caps %"
2342         GST_PTR_FORMAT, stream->id, GST_PAD_NAME (stream->pad), stream->caps);
2343     gst_pad_set_active (stream->pad, TRUE);
2344     gst_pad_set_caps (stream->pad, stream->caps);
2345     gst_element_add_pad (GST_ELEMENT_CAST (demux), stream->pad);
2346     stream->active = TRUE;
2347   }
2348 }
2349
2350 static AsfStream *
2351 gst_asf_demux_parse_stream_object (GstASFDemux * demux, guint8 * data,
2352     guint64 size)
2353 {
2354   AsfCorrectionType correction_type;
2355   AsfStreamType stream_type;
2356   GstClockTime time_offset;
2357   gboolean is_encrypted G_GNUC_UNUSED;
2358   guint16 stream_id;
2359   guint16 flags;
2360   ASFGuid guid;
2361   guint stream_specific_size;
2362   guint type_specific_size G_GNUC_UNUSED;
2363   guint unknown G_GNUC_UNUSED;
2364
2365   /* Get the rest of the header's header */
2366   if (size < (16 + 16 + 8 + 4 + 4 + 2 + 4))
2367     goto not_enough_data;
2368
2369   gst_asf_demux_get_guid (&guid, &data, &size);
2370   stream_type = gst_asf_demux_identify_guid (asf_stream_guids, &guid);
2371
2372   gst_asf_demux_get_guid (&guid, &data, &size);
2373   correction_type = gst_asf_demux_identify_guid (asf_correction_guids, &guid);
2374
2375   time_offset = gst_asf_demux_get_uint64 (&data, &size) * 100;
2376
2377   type_specific_size = gst_asf_demux_get_uint32 (&data, &size);
2378   stream_specific_size = gst_asf_demux_get_uint32 (&data, &size);
2379
2380   flags = gst_asf_demux_get_uint16 (&data, &size);
2381   stream_id = flags & 0x7f;
2382   is_encrypted = ! !((flags & 0x8000) << 15);
2383   unknown = gst_asf_demux_get_uint32 (&data, &size);
2384
2385   GST_DEBUG_OBJECT (demux, "Found stream %u, time_offset=%" GST_TIME_FORMAT,
2386       stream_id, GST_TIME_ARGS (time_offset));
2387
2388   switch (stream_type) {
2389     case ASF_STREAM_AUDIO:{
2390       asf_stream_audio audio_object;
2391
2392       if (!gst_asf_demux_get_stream_audio (&audio_object, &data, &size))
2393         goto not_enough_data;
2394
2395       GST_INFO ("Object is an audio stream with %u bytes of additional data",
2396           audio_object.size);
2397
2398       gst_asf_demux_add_audio_stream (demux, &audio_object, stream_id,
2399           &data, &size);
2400
2401       switch (correction_type) {
2402         case ASF_CORRECTION_ON:{
2403           guint span, packet_size, chunk_size, data_size, silence_data;
2404
2405           GST_INFO ("Using error correction");
2406
2407           if (size < (1 + 2 + 2 + 2 + 1))
2408             goto not_enough_data;
2409
2410           span = gst_asf_demux_get_uint8 (&data, &size);
2411           packet_size = gst_asf_demux_get_uint16 (&data, &size);
2412           chunk_size = gst_asf_demux_get_uint16 (&data, &size);
2413           data_size = gst_asf_demux_get_uint16 (&data, &size);
2414           silence_data = gst_asf_demux_get_uint8 (&data, &size);
2415
2416           /* FIXME: shouldn't this be per-stream? */
2417           demux->span = span;
2418
2419           GST_DEBUG_OBJECT (demux, "Descrambling ps:%u cs:%u ds:%u s:%u sd:%u",
2420               packet_size, chunk_size, data_size, span, silence_data);
2421
2422           if (demux->span > 1) {
2423             if (chunk_size == 0 || ((packet_size / chunk_size) <= 1)) {
2424               /* Disable descrambling */
2425               demux->span = 0;
2426             } else {
2427               /* FIXME: this else branch was added for
2428                * weird_al_yankovic - the saga begins.asf */
2429               demux->ds_packet_size = packet_size;
2430               demux->ds_chunk_size = chunk_size;
2431             }
2432           } else {
2433             /* Descambling is enabled */
2434             demux->ds_packet_size = packet_size;
2435             demux->ds_chunk_size = chunk_size;
2436           }
2437 #if 0
2438           /* Now skip the rest of the silence data */
2439           if (data_size > 1)
2440             gst_bytestream_flush (demux->bs, data_size - 1);
2441 #else
2442           /* FIXME: CHECKME. And why -1? */
2443           if (data_size > 1) {
2444             if (!gst_asf_demux_skip_bytes (data_size - 1, &data, &size)) {
2445               goto not_enough_data;
2446             }
2447           }
2448 #endif
2449           break;
2450         }
2451         case ASF_CORRECTION_OFF:{
2452           GST_INFO ("Error correction off");
2453           if (!gst_asf_demux_skip_bytes (stream_specific_size, &data, &size))
2454             goto not_enough_data;
2455           break;
2456         }
2457         default:
2458           GST_ELEMENT_ERROR (demux, STREAM, DEMUX, (NULL),
2459               ("Audio stream using unknown error correction"));
2460           return NULL;
2461       }
2462
2463       break;
2464     }
2465
2466     case ASF_STREAM_VIDEO:{
2467       asf_stream_video_format video_format_object;
2468       asf_stream_video video_object;
2469       guint16 vsize;
2470
2471       if (!gst_asf_demux_get_stream_video (&video_object, &data, &size))
2472         goto not_enough_data;
2473
2474       vsize = video_object.size - 40;   /* Byte order gets offset by single byte */
2475
2476       GST_INFO ("object is a video stream with %u bytes of "
2477           "additional data", vsize);
2478
2479       if (!gst_asf_demux_get_stream_video_format (&video_format_object,
2480               &data, &size)) {
2481         goto not_enough_data;
2482       }
2483
2484       gst_asf_demux_add_video_stream (demux, &video_format_object, stream_id,
2485           &data, &size);
2486
2487       break;
2488     }
2489
2490     default:
2491       GST_WARNING_OBJECT (demux, "Unknown stream type for stream %u",
2492           stream_id);
2493       break;
2494   }
2495
2496   return gst_asf_demux_get_stream (demux, stream_id);
2497
2498 not_enough_data:
2499   {
2500     GST_WARNING_OBJECT (demux, "Unexpected end of data parsing stream object");
2501     /* we'll error out later if we found no streams */
2502     return NULL;
2503   }
2504 }
2505
2506 static const gchar *
2507 gst_asf_demux_get_gst_tag_from_tag_name (const gchar * name_utf8)
2508 {
2509   const struct
2510   {
2511     const gchar *asf_name;
2512     const gchar *gst_name;
2513   } tags[] = {
2514     {
2515     "WM/Genre", GST_TAG_GENRE}, {
2516     "WM/AlbumTitle", GST_TAG_ALBUM}, {
2517     "WM/AlbumArtist", GST_TAG_ARTIST}, {
2518     "WM/Picture", GST_TAG_IMAGE}, {
2519     "WM/Track", GST_TAG_TRACK_NUMBER}, {
2520     "WM/TrackNumber", GST_TAG_TRACK_NUMBER}, {
2521     "WM/Year", GST_TAG_DATE}
2522     /* { "WM/Composer", GST_TAG_COMPOSER } */
2523   };
2524   gsize out;
2525   guint i;
2526
2527   if (name_utf8 == NULL) {
2528     GST_WARNING ("Failed to convert name to UTF8, skipping");
2529     return NULL;
2530   }
2531
2532   out = strlen (name_utf8);
2533
2534   for (i = 0; i < G_N_ELEMENTS (tags); ++i) {
2535     if (strncmp (tags[i].asf_name, name_utf8, out) == 0) {
2536       GST_LOG ("map tagname '%s' -> '%s'", name_utf8, tags[i].gst_name);
2537       return tags[i].gst_name;
2538     }
2539   }
2540
2541   return NULL;
2542 }
2543
2544 /* gst_asf_demux_add_global_tags() takes ownership of taglist! */
2545 static void
2546 gst_asf_demux_add_global_tags (GstASFDemux * demux, GstTagList * taglist)
2547 {
2548   GstTagList *t;
2549
2550   GST_DEBUG_OBJECT (demux, "adding global tags: %" GST_PTR_FORMAT, taglist);
2551
2552   if (taglist == NULL)
2553     return;
2554
2555   if (gst_tag_list_is_empty (taglist)) {
2556     gst_tag_list_free (taglist);
2557     return;
2558   }
2559
2560   t = gst_tag_list_merge (demux->taglist, taglist, GST_TAG_MERGE_APPEND);
2561   if (demux->taglist)
2562     gst_tag_list_free (demux->taglist);
2563   gst_tag_list_free (taglist);
2564   demux->taglist = t;
2565   GST_LOG_OBJECT (demux, "global tags now: %" GST_PTR_FORMAT, demux->taglist);
2566 }
2567
2568 #define ASF_DEMUX_DATA_TYPE_UTF16LE_STRING  0
2569 #define ASF_DEMUX_DATA_TYPE_BYTE_ARRAY      1
2570 #define ASF_DEMUX_DATA_TYPE_DWORD           3
2571
2572 static void
2573 asf_demux_parse_picture_tag (GstTagList * tags, const guint8 * tag_data,
2574     guint tag_data_len)
2575 {
2576   GstByteReader r;
2577   const guint8 *img_data = NULL;
2578   guint32 img_data_len = 0;
2579   guint8 pic_type = 0;
2580
2581   gst_byte_reader_init (&r, tag_data, tag_data_len);
2582
2583   /* skip mime type string (we don't trust it and do our own typefinding),
2584    * and also skip the description string, since we don't use it */
2585   if (!gst_byte_reader_get_uint8 (&r, &pic_type) ||
2586       !gst_byte_reader_get_uint32_le (&r, &img_data_len) ||
2587       !gst_byte_reader_skip_string_utf16 (&r) ||
2588       !gst_byte_reader_skip_string_utf16 (&r) ||
2589       !gst_byte_reader_get_data (&r, img_data_len, &img_data)) {
2590     goto not_enough_data;
2591   }
2592
2593
2594   if (!gst_tag_list_add_id3_image (tags, img_data, img_data_len, pic_type))
2595     GST_DEBUG ("failed to add image extracted from WM/Picture tag to taglist");
2596
2597   return;
2598
2599 not_enough_data:
2600   {
2601     GST_DEBUG ("Failed to read WM/Picture tag: not enough data");
2602     GST_MEMDUMP ("WM/Picture data", tag_data, tag_data_len);
2603     return;
2604   }
2605 }
2606
2607 /* Extended Content Description Object */
2608 static GstFlowReturn
2609 gst_asf_demux_process_ext_content_desc (GstASFDemux * demux, guint8 * data,
2610     guint64 size)
2611 {
2612   /* Other known (and unused) 'text/unicode' metadata available :
2613    *
2614    *   WM/Lyrics =
2615    *   WM/MediaPrimaryClassID = {D1607DBC-E323-4BE2-86A1-48A42A28441E}
2616    *   WMFSDKVersion = 9.00.00.2980
2617    *   WMFSDKNeeded = 0.0.0.0000
2618    *   WM/UniqueFileIdentifier = AMGa_id=R    15334;AMGp_id=P     5149;AMGt_id=T  2324984
2619    *   WM/Publisher = 4AD
2620    *   WM/Provider = AMG
2621    *   WM/ProviderRating = 8
2622    *   WM/ProviderStyle = Rock (similar to WM/Genre)
2623    *   WM/GenreID (similar to WM/Genre)
2624    *   WM/TrackNumber (same as WM/Track but as a string)
2625    *
2626    * Other known (and unused) 'non-text' metadata available :
2627    *
2628    *   WM/EncodingTime
2629    *   WM/MCDI
2630    *   IsVBR
2631    *
2632    * We might want to read WM/TrackNumber and use atoi() if we don't have
2633    * WM/Track
2634    */
2635
2636   GstTagList *taglist;
2637   guint16 blockcount, i;
2638
2639   GST_INFO_OBJECT (demux, "object is an extended content description");
2640
2641   taglist = gst_tag_list_new_empty ();
2642
2643   /* Content Descriptor Count */
2644   if (size < 2)
2645     goto not_enough_data;
2646
2647   blockcount = gst_asf_demux_get_uint16 (&data, &size);
2648
2649   for (i = 1; i <= blockcount; ++i) {
2650     const gchar *gst_tag_name;
2651     guint16 datatype;
2652     guint16 value_len;
2653     guint16 name_len;
2654     GValue tag_value = { 0, };
2655     gsize in, out;
2656     gchar *name;
2657     gchar *name_utf8 = NULL;
2658     gchar *value;
2659
2660     /* Descriptor */
2661     if (!gst_asf_demux_get_string (&name, &name_len, &data, &size))
2662       goto not_enough_data;
2663
2664     if (size < 2) {
2665       g_free (name);
2666       goto not_enough_data;
2667     }
2668     /* Descriptor Value Data Type */
2669     datatype = gst_asf_demux_get_uint16 (&data, &size);
2670
2671     /* Descriptor Value (not really a string, but same thing reading-wise) */
2672     if (!gst_asf_demux_get_string (&value, &value_len, &data, &size)) {
2673       g_free (name);
2674       goto not_enough_data;
2675     }
2676
2677     name_utf8 =
2678         g_convert (name, name_len, "UTF-8", "UTF-16LE", &in, &out, NULL);
2679
2680     if (name_utf8 != NULL) {
2681       GST_DEBUG ("Found tag/metadata %s", name_utf8);
2682
2683       gst_tag_name = gst_asf_demux_get_gst_tag_from_tag_name (name_utf8);
2684       GST_DEBUG ("gst_tag_name %s", GST_STR_NULL (gst_tag_name));
2685
2686       switch (datatype) {
2687         case ASF_DEMUX_DATA_TYPE_UTF16LE_STRING:{
2688           gchar *value_utf8;
2689
2690           value_utf8 = g_convert (value, value_len, "UTF-8", "UTF-16LE",
2691               &in, &out, NULL);
2692
2693           /* get rid of tags with empty value */
2694           if (value_utf8 != NULL && *value_utf8 != '\0') {
2695             GST_DEBUG ("string value %s", value_utf8);
2696
2697             value_utf8[out] = '\0';
2698
2699             if (gst_tag_name != NULL) {
2700               if (strcmp (gst_tag_name, GST_TAG_DATE) == 0) {
2701                 guint year = atoi (value_utf8);
2702
2703                 if (year > 0) {
2704                   /* FIXME: really want a GDateTime with just the year field */
2705                   g_value_init (&tag_value, G_TYPE_DATE);
2706                   g_value_take_boxed (&tag_value, g_date_new_dmy (1, 1, year));
2707                 }
2708               } else if (strcmp (gst_tag_name, GST_TAG_GENRE) == 0) {
2709                 guint id3v1_genre_id;
2710                 const gchar *genre_str;
2711
2712                 if (sscanf (value_utf8, "(%u)", &id3v1_genre_id) == 1 &&
2713                     ((genre_str = gst_tag_id3_genre_get (id3v1_genre_id)))) {
2714                   GST_DEBUG ("Genre: %s -> %s", value_utf8, genre_str);
2715                   g_free (value_utf8);
2716                   value_utf8 = g_strdup (genre_str);
2717                 }
2718               } else {
2719                 GType tag_type;
2720
2721                 /* convert tag from string to other type if required */
2722                 tag_type = gst_tag_get_type (gst_tag_name);
2723                 g_value_init (&tag_value, tag_type);
2724                 if (!gst_value_deserialize (&tag_value, value_utf8)) {
2725                   GValue from_val = { 0, };
2726
2727                   g_value_init (&from_val, G_TYPE_STRING);
2728                   g_value_set_string (&from_val, value_utf8);
2729                   if (!g_value_transform (&from_val, &tag_value)) {
2730                     GST_WARNING_OBJECT (demux,
2731                         "Could not transform string tag to " "%s tag type %s",
2732                         gst_tag_name, g_type_name (tag_type));
2733                     g_value_unset (&tag_value);
2734                   }
2735                   g_value_unset (&from_val);
2736                 }
2737               }
2738             } else {
2739               /* metadata ! */
2740               GST_DEBUG ("Setting metadata");
2741               g_value_init (&tag_value, G_TYPE_STRING);
2742               g_value_set_string (&tag_value, value_utf8);
2743             }
2744           } else if (value_utf8 == NULL) {
2745             GST_WARNING ("Failed to convert string value to UTF8, skipping");
2746           } else {
2747             GST_DEBUG ("Skipping empty string value for %s",
2748                 GST_STR_NULL (gst_tag_name));
2749           }
2750           g_free (value_utf8);
2751           break;
2752         }
2753         case ASF_DEMUX_DATA_TYPE_BYTE_ARRAY:{
2754           if (gst_tag_name) {
2755             if (!g_str_equal (gst_tag_name, GST_TAG_IMAGE)) {
2756               GST_FIXME ("Unhandled byte array tag %s",
2757                   GST_STR_NULL (gst_tag_name));
2758               break;
2759             } else {
2760               asf_demux_parse_picture_tag (taglist, (guint8 *) value,
2761                   value_len);
2762             }
2763           }
2764           break;
2765         }
2766         case ASF_DEMUX_DATA_TYPE_DWORD:{
2767           guint uint_val = GST_READ_UINT32_LE (value);
2768
2769           /* this is the track number */
2770           g_value_init (&tag_value, G_TYPE_UINT);
2771
2772           /* WM/Track counts from 0 */
2773           if (!strcmp (name_utf8, "WM/Track"))
2774             ++uint_val;
2775
2776           g_value_set_uint (&tag_value, uint_val);
2777           break;
2778         }
2779         default:{
2780           GST_DEBUG ("Skipping tag %s of type %d", gst_tag_name, datatype);
2781           break;
2782         }
2783       }
2784
2785       if (G_IS_VALUE (&tag_value)) {
2786         if (gst_tag_name) {
2787           GstTagMergeMode merge_mode = GST_TAG_MERGE_APPEND;
2788
2789           /* WM/TrackNumber is more reliable than WM/Track, since the latter
2790            * is supposed to have a 0 base but is often wrongly written to start
2791            * from 1 as well, so prefer WM/TrackNumber when we have it: either
2792            * replace the value added earlier from WM/Track or put it first in
2793            * the list, so that it will get picked up by _get_uint() */
2794           if (strcmp (name_utf8, "WM/TrackNumber") == 0)
2795             merge_mode = GST_TAG_MERGE_REPLACE;
2796
2797           gst_tag_list_add_values (taglist, merge_mode, gst_tag_name,
2798               &tag_value, NULL);
2799         } else {
2800           GST_DEBUG ("Setting global metadata %s", name_utf8);
2801           gst_structure_set_value (demux->global_metadata, name_utf8,
2802               &tag_value);
2803         }
2804
2805         g_value_unset (&tag_value);
2806       }
2807     }
2808
2809     g_free (name);
2810     g_free (value);
2811     g_free (name_utf8);
2812   }
2813
2814   gst_asf_demux_add_global_tags (demux, taglist);
2815
2816   return GST_FLOW_OK;
2817
2818   /* Errors */
2819 not_enough_data:
2820   {
2821     GST_WARNING ("Unexpected end of data parsing ext content desc object");
2822     gst_tag_list_free (taglist);
2823     return GST_FLOW_OK;         /* not really fatal */
2824   }
2825 }
2826
2827 static GstStructure *
2828 gst_asf_demux_get_metadata_for_stream (GstASFDemux * demux, guint stream_num)
2829 {
2830   gchar sname[32];
2831   guint i;
2832
2833   g_snprintf (sname, sizeof (sname), "stream-%u", stream_num);
2834
2835   for (i = 0; i < gst_caps_get_size (demux->metadata); ++i) {
2836     GstStructure *s;
2837
2838     s = gst_caps_get_structure (demux->metadata, i);
2839     if (gst_structure_has_name (s, sname))
2840       return s;
2841   }
2842
2843   gst_caps_append_structure (demux->metadata, gst_structure_new_empty (sname));
2844
2845   /* try lookup again; demux->metadata took ownership of the structure, so we
2846    * can't really make any assumptions about what happened to it, so we can't
2847    * just return it directly after appending it */
2848   return gst_asf_demux_get_metadata_for_stream (demux, stream_num);
2849 }
2850
2851 static GstFlowReturn
2852 gst_asf_demux_process_metadata (GstASFDemux * demux, guint8 * data,
2853     guint64 size)
2854 {
2855   guint16 blockcount, i;
2856
2857   GST_INFO_OBJECT (demux, "object is a metadata object");
2858
2859   /* Content Descriptor Count */
2860   if (size < 2)
2861     goto not_enough_data;
2862
2863   blockcount = gst_asf_demux_get_uint16 (&data, &size);
2864
2865   for (i = 0; i < blockcount; ++i) {
2866     GstStructure *s;
2867     guint16 stream_num, name_len, data_type, lang_idx G_GNUC_UNUSED;
2868     guint32 data_len, ival;
2869     gchar *name_utf8;
2870
2871     if (size < (2 + 2 + 2 + 2 + 4))
2872       goto not_enough_data;
2873
2874     lang_idx = gst_asf_demux_get_uint16 (&data, &size);
2875     stream_num = gst_asf_demux_get_uint16 (&data, &size);
2876     name_len = gst_asf_demux_get_uint16 (&data, &size);
2877     data_type = gst_asf_demux_get_uint16 (&data, &size);
2878     data_len = gst_asf_demux_get_uint32 (&data, &size);
2879
2880     if (size < name_len + data_len)
2881       goto not_enough_data;
2882
2883     /* convert name to UTF-8 */
2884     name_utf8 = g_convert ((gchar *) data, name_len, "UTF-8", "UTF-16LE",
2885         NULL, NULL, NULL);
2886     gst_asf_demux_skip_bytes (name_len, &data, &size);
2887
2888     if (name_utf8 == NULL) {
2889       GST_WARNING ("Failed to convert value name to UTF8, skipping");
2890       gst_asf_demux_skip_bytes (data_len, &data, &size);
2891       continue;
2892     }
2893
2894     if (data_type != ASF_DEMUX_DATA_TYPE_DWORD) {
2895       gst_asf_demux_skip_bytes (data_len, &data, &size);
2896       g_free (name_utf8);
2897       continue;
2898     }
2899
2900     /* read DWORD */
2901     if (size < 4) {
2902       g_free (name_utf8);
2903       goto not_enough_data;
2904     }
2905
2906     ival = gst_asf_demux_get_uint32 (&data, &size);
2907
2908     /* skip anything else there may be, just in case */
2909     gst_asf_demux_skip_bytes (data_len - 4, &data, &size);
2910
2911     s = gst_asf_demux_get_metadata_for_stream (demux, stream_num);
2912     gst_structure_set (s, name_utf8, G_TYPE_INT, ival, NULL);
2913     g_free (name_utf8);
2914   }
2915
2916   GST_INFO_OBJECT (demux, "metadata = %" GST_PTR_FORMAT, demux->metadata);
2917   return GST_FLOW_OK;
2918
2919   /* Errors */
2920 not_enough_data:
2921   {
2922     GST_WARNING ("Unexpected end of data parsing metadata object");
2923     return GST_FLOW_OK;         /* not really fatal */
2924   }
2925 }
2926
2927 static GstFlowReturn
2928 gst_asf_demux_process_header (GstASFDemux * demux, guint8 * data, guint64 size)
2929 {
2930   GstFlowReturn ret = GST_FLOW_OK;
2931   guint32 i, num_objects;
2932   guint8 unknown G_GNUC_UNUSED;
2933
2934   /* Get the rest of the header's header */
2935   if (size < (4 + 1 + 1))
2936     goto not_enough_data;
2937
2938   num_objects = gst_asf_demux_get_uint32 (&data, &size);
2939   unknown = gst_asf_demux_get_uint8 (&data, &size);
2940   unknown = gst_asf_demux_get_uint8 (&data, &size);
2941
2942   GST_INFO_OBJECT (demux, "object is a header with %u parts", num_objects);
2943
2944   /* Loop through the header's objects, processing those */
2945   for (i = 0; i < num_objects; ++i) {
2946     GST_INFO_OBJECT (demux, "reading header part %u", i);
2947     ret = gst_asf_demux_process_object (demux, &data, &size);
2948     if (ret != GST_FLOW_OK) {
2949       GST_WARNING ("process_object returned %s", gst_asf_get_flow_name (ret));
2950       break;
2951     }
2952   }
2953
2954   return ret;
2955
2956 not_enough_data:
2957   {
2958     GST_ELEMENT_ERROR (demux, STREAM, DEMUX, (NULL),
2959         ("short read parsing HEADER object"));
2960     return GST_FLOW_ERROR;
2961   }
2962 }
2963
2964 static GstFlowReturn
2965 gst_asf_demux_process_file (GstASFDemux * demux, guint8 * data, guint64 size)
2966 {
2967   guint64 creation_time G_GNUC_UNUSED;
2968   guint64 file_size G_GNUC_UNUSED;
2969   guint64 send_time G_GNUC_UNUSED;
2970   guint64 packets_count, play_time, preroll;
2971   guint32 flags, min_pktsize, max_pktsize, min_bitrate G_GNUC_UNUSED;
2972
2973   if (size < (16 + 8 + 8 + 8 + 8 + 8 + 8 + 4 + 4 + 4 + 4))
2974     goto not_enough_data;
2975
2976   gst_asf_demux_skip_bytes (16, &data, &size);  /* skip GUID */
2977   file_size = gst_asf_demux_get_uint64 (&data, &size);
2978   creation_time = gst_asf_demux_get_uint64 (&data, &size);
2979   packets_count = gst_asf_demux_get_uint64 (&data, &size);
2980   play_time = gst_asf_demux_get_uint64 (&data, &size);
2981   send_time = gst_asf_demux_get_uint64 (&data, &size);
2982   preroll = gst_asf_demux_get_uint64 (&data, &size);
2983   flags = gst_asf_demux_get_uint32 (&data, &size);
2984   min_pktsize = gst_asf_demux_get_uint32 (&data, &size);
2985   max_pktsize = gst_asf_demux_get_uint32 (&data, &size);
2986   min_bitrate = gst_asf_demux_get_uint32 (&data, &size);
2987
2988   demux->broadcast = ! !(flags & 0x01);
2989   demux->seekable = ! !(flags & 0x02);
2990
2991   GST_DEBUG_OBJECT (demux, "min_pktsize = %u", min_pktsize);
2992   GST_DEBUG_OBJECT (demux, "flags::broadcast = %d", demux->broadcast);
2993   GST_DEBUG_OBJECT (demux, "flags::seekable  = %d", demux->seekable);
2994
2995   if (demux->broadcast) {
2996     /* these fields are invalid if the broadcast flag is set */
2997     play_time = 0;
2998     file_size = 0;
2999   }
3000
3001   if (min_pktsize != max_pktsize)
3002     goto non_fixed_packet_size;
3003
3004   demux->packet_size = max_pktsize;
3005
3006   /* FIXME: do we need send_time as well? what is it? */
3007   if ((play_time * 100) >= (preroll * GST_MSECOND))
3008     demux->play_time = (play_time * 100) - (preroll * GST_MSECOND);
3009   else
3010     demux->play_time = 0;
3011
3012   demux->preroll = preroll * GST_MSECOND;
3013
3014   /* initial latency */
3015   demux->latency = demux->preroll;
3016
3017   if (demux->play_time == 0)
3018     demux->seekable = FALSE;
3019
3020   GST_DEBUG_OBJECT (demux, "play_time %" GST_TIME_FORMAT,
3021       GST_TIME_ARGS (demux->play_time));
3022   GST_DEBUG_OBJECT (demux, "preroll   %" GST_TIME_FORMAT,
3023       GST_TIME_ARGS (demux->preroll));
3024
3025   if (demux->play_time > 0) {
3026     demux->segment.duration = demux->play_time;
3027   }
3028
3029   GST_INFO ("object is a file with %" G_GUINT64_FORMAT " data packets",
3030       packets_count);
3031   GST_INFO ("preroll = %" G_GUINT64_FORMAT, demux->preroll);
3032
3033   return GST_FLOW_OK;
3034
3035 /* ERRORS */
3036 non_fixed_packet_size:
3037   {
3038     GST_ELEMENT_ERROR (demux, STREAM, DEMUX, (NULL),
3039         ("packet size must be fixed"));
3040     return GST_FLOW_ERROR;
3041   }
3042 not_enough_data:
3043   {
3044     GST_ELEMENT_ERROR (demux, STREAM, DEMUX, (NULL),
3045         ("short read parsing FILE object"));
3046     return GST_FLOW_ERROR;
3047   }
3048 }
3049
3050 /* Content Description Object */
3051 static GstFlowReturn
3052 gst_asf_demux_process_comment (GstASFDemux * demux, guint8 * data, guint64 size)
3053 {
3054   struct
3055   {
3056     const gchar *gst_tag;
3057     guint16 val_length;
3058     gchar *val_utf8;
3059   } tags[5] = {
3060     {
3061     GST_TAG_TITLE, 0, NULL}, {
3062     GST_TAG_ARTIST, 0, NULL}, {
3063     GST_TAG_COPYRIGHT, 0, NULL}, {
3064     GST_TAG_DESCRIPTION, 0, NULL}, {
3065     GST_TAG_COMMENT, 0, NULL}
3066   };
3067   GstTagList *taglist;
3068   GValue value = { 0 };
3069   gsize in, out;
3070   gint i = -1;
3071
3072   GST_INFO_OBJECT (demux, "object is a comment");
3073
3074   if (size < (2 + 2 + 2 + 2 + 2))
3075     goto not_enough_data;
3076
3077   tags[0].val_length = gst_asf_demux_get_uint16 (&data, &size);
3078   tags[1].val_length = gst_asf_demux_get_uint16 (&data, &size);
3079   tags[2].val_length = gst_asf_demux_get_uint16 (&data, &size);
3080   tags[3].val_length = gst_asf_demux_get_uint16 (&data, &size);
3081   tags[4].val_length = gst_asf_demux_get_uint16 (&data, &size);
3082
3083   GST_DEBUG_OBJECT (demux, "Comment lengths: title=%d author=%d copyright=%d "
3084       "description=%d rating=%d", tags[0].val_length, tags[1].val_length,
3085       tags[2].val_length, tags[3].val_length, tags[4].val_length);
3086
3087   for (i = 0; i < G_N_ELEMENTS (tags); ++i) {
3088     if (size < tags[i].val_length)
3089       goto not_enough_data;
3090
3091     /* might be just '/0', '/0'... */
3092     if (tags[i].val_length > 2 && tags[i].val_length % 2 == 0) {
3093       /* convert to UTF-8 */
3094       tags[i].val_utf8 = g_convert ((gchar *) data, tags[i].val_length,
3095           "UTF-8", "UTF-16LE", &in, &out, NULL);
3096     }
3097     gst_asf_demux_skip_bytes (tags[i].val_length, &data, &size);
3098   }
3099
3100   /* parse metadata into taglist */
3101   taglist = gst_tag_list_new_empty ();
3102   g_value_init (&value, G_TYPE_STRING);
3103   for (i = 0; i < G_N_ELEMENTS (tags); ++i) {
3104     if (tags[i].val_utf8 && strlen (tags[i].val_utf8) > 0 && tags[i].gst_tag) {
3105       g_value_set_string (&value, tags[i].val_utf8);
3106       gst_tag_list_add_values (taglist, GST_TAG_MERGE_APPEND,
3107           tags[i].gst_tag, &value, NULL);
3108     }
3109   }
3110   g_value_unset (&value);
3111
3112   gst_asf_demux_add_global_tags (demux, taglist);
3113
3114   for (i = 0; i < G_N_ELEMENTS (tags); ++i)
3115     g_free (tags[i].val_utf8);
3116
3117   return GST_FLOW_OK;
3118
3119 not_enough_data:
3120   {
3121     GST_WARNING_OBJECT (demux, "unexpectedly short of data while processing "
3122         "comment tag section %d, skipping comment object", i);
3123     for (i = 0; i < G_N_ELEMENTS (tags); i++)
3124       g_free (tags[i].val_utf8);
3125     return GST_FLOW_OK;         /* not really fatal */
3126   }
3127 }
3128
3129 static GstFlowReturn
3130 gst_asf_demux_process_bitrate_props_object (GstASFDemux * demux, guint8 * data,
3131     guint64 size)
3132 {
3133   guint16 num_streams, i;
3134   AsfStream *stream;
3135
3136   if (size < 2)
3137     goto not_enough_data;
3138
3139   num_streams = gst_asf_demux_get_uint16 (&data, &size);
3140
3141   GST_INFO ("object is a bitrate properties object with %u streams",
3142       num_streams);
3143
3144   if (size < (num_streams * (2 + 4)))
3145     goto not_enough_data;
3146
3147   for (i = 0; i < num_streams; ++i) {
3148     guint32 bitrate;
3149     guint16 stream_id;
3150
3151     stream_id = gst_asf_demux_get_uint16 (&data, &size);
3152     bitrate = gst_asf_demux_get_uint32 (&data, &size);
3153
3154     if (stream_id < GST_ASF_DEMUX_NUM_STREAM_IDS) {
3155       GST_DEBUG_OBJECT (demux, "bitrate of stream %u = %u", stream_id, bitrate);
3156       stream = gst_asf_demux_get_stream (demux, stream_id);
3157       if (stream) {
3158         if (stream->pending_tags == NULL) {
3159           stream->pending_tags =
3160               gst_tag_list_new (GST_TAG_BITRATE, bitrate, NULL);
3161         }
3162       } else {
3163         GST_WARNING_OBJECT (demux, "Stream id %u wasn't found", stream_id);
3164       }
3165     } else {
3166       GST_WARNING ("stream id %u is too large", stream_id);
3167     }
3168   }
3169
3170   return GST_FLOW_OK;
3171
3172 not_enough_data:
3173   {
3174     GST_WARNING_OBJECT (demux, "short read parsing bitrate props object!");
3175     return GST_FLOW_OK;         /* not really fatal */
3176   }
3177 }
3178
3179 static GstFlowReturn
3180 gst_asf_demux_process_header_ext (GstASFDemux * demux, guint8 * data,
3181     guint64 size)
3182 {
3183   GstFlowReturn ret = GST_FLOW_OK;
3184   guint64 hdr_size;
3185
3186   /* Get the rest of the header's header */
3187   if (size < (16 + 2 + 4))
3188     goto not_enough_data;
3189
3190   /* skip GUID and two other bytes */
3191   gst_asf_demux_skip_bytes (16 + 2, &data, &size);
3192   hdr_size = gst_asf_demux_get_uint32 (&data, &size);
3193
3194   GST_INFO ("extended header object with a size of %u bytes", (guint) size);
3195
3196   /* FIXME: does data_size include the rest of the header that we have read? */
3197   if (hdr_size > size)
3198     goto not_enough_data;
3199
3200   while (hdr_size > 0) {
3201     ret = gst_asf_demux_process_object (demux, &data, &hdr_size);
3202     if (ret != GST_FLOW_OK)
3203       break;
3204   }
3205
3206   return ret;
3207
3208 not_enough_data:
3209   {
3210     GST_ELEMENT_ERROR (demux, STREAM, DEMUX, (NULL),
3211         ("short read parsing extended header object"));
3212     return GST_FLOW_ERROR;
3213   }
3214 }
3215
3216 static GstFlowReturn
3217 gst_asf_demux_process_language_list (GstASFDemux * demux, guint8 * data,
3218     guint64 size)
3219 {
3220   guint i;
3221
3222   if (size < 2)
3223     goto not_enough_data;
3224
3225   if (demux->languages) {
3226     GST_WARNING ("More than one LANGUAGE_LIST object in stream");
3227     g_strfreev (demux->languages);
3228     demux->languages = NULL;
3229     demux->num_languages = 0;
3230   }
3231
3232   demux->num_languages = gst_asf_demux_get_uint16 (&data, &size);
3233   GST_LOG ("%u languages:", demux->num_languages);
3234
3235   demux->languages = g_new0 (gchar *, demux->num_languages + 1);
3236   for (i = 0; i < demux->num_languages; ++i) {
3237     guint8 len, *lang_data = NULL;
3238
3239     if (size < 1)
3240       goto not_enough_data;
3241     len = gst_asf_demux_get_uint8 (&data, &size);
3242     if (gst_asf_demux_get_bytes (&lang_data, len, &data, &size)) {
3243       gchar *utf8;
3244
3245       utf8 = g_convert ((gchar *) lang_data, len, "UTF-8", "UTF-16LE", NULL,
3246           NULL, NULL);
3247
3248       /* truncate "en-us" etc. to just "en" */
3249       if (utf8 && strlen (utf8) >= 5 && (utf8[2] == '-' || utf8[2] == '_')) {
3250         utf8[2] = '\0';
3251       }
3252       GST_DEBUG ("[%u] %s", i, GST_STR_NULL (utf8));
3253       demux->languages[i] = utf8;
3254       g_free (lang_data);
3255     } else {
3256       goto not_enough_data;
3257     }
3258   }
3259
3260   return GST_FLOW_OK;
3261
3262 not_enough_data:
3263   {
3264     GST_WARNING_OBJECT (demux, "short read parsing language list object!");
3265     g_free (demux->languages);
3266     demux->languages = NULL;
3267     return GST_FLOW_OK;         /* not fatal */
3268   }
3269 }
3270
3271 static GstFlowReturn
3272 gst_asf_demux_process_simple_index (GstASFDemux * demux, guint8 * data,
3273     guint64 size)
3274 {
3275   GstClockTime interval;
3276   guint32 count, i;
3277
3278   if (size < (16 + 8 + 4 + 4))
3279     goto not_enough_data;
3280
3281   /* skip file id */
3282   gst_asf_demux_skip_bytes (16, &data, &size);
3283   interval = gst_asf_demux_get_uint64 (&data, &size) * (GstClockTime) 100;
3284   gst_asf_demux_skip_bytes (4, &data, &size);
3285   count = gst_asf_demux_get_uint32 (&data, &size);
3286   if (count > 0) {
3287     demux->sidx_interval = interval;
3288     demux->sidx_num_entries = count;
3289     g_free (demux->sidx_entries);
3290     demux->sidx_entries = g_new0 (AsfSimpleIndexEntry, count);
3291
3292     for (i = 0; i < count; ++i) {
3293       if (G_UNLIKELY (size <= 6))
3294         break;
3295       demux->sidx_entries[i].packet = gst_asf_demux_get_uint32 (&data, &size);
3296       demux->sidx_entries[i].count = gst_asf_demux_get_uint16 (&data, &size);
3297       GST_LOG_OBJECT (demux, "%" GST_TIME_FORMAT " = packet %4u  count : %2d",
3298           GST_TIME_ARGS (i * interval), demux->sidx_entries[i].packet,
3299           demux->sidx_entries[i].count);
3300     }
3301   } else {
3302     GST_DEBUG_OBJECT (demux, "simple index object with 0 entries");
3303   }
3304
3305   return GST_FLOW_OK;
3306
3307 not_enough_data:
3308   {
3309     GST_WARNING_OBJECT (demux, "short read parsing simple index object!");
3310     return GST_FLOW_OK;         /* not fatal */
3311   }
3312 }
3313
3314 static GstFlowReturn
3315 gst_asf_demux_process_advanced_mutual_exclusion (GstASFDemux * demux,
3316     guint8 * data, guint64 size)
3317 {
3318   ASFGuid guid;
3319   guint16 num, i;
3320   guint8 *mes;
3321
3322   if (size < 16 + 2 + (2 * 2))
3323     goto not_enough_data;
3324
3325   gst_asf_demux_get_guid (&guid, &data, &size);
3326   num = gst_asf_demux_get_uint16 (&data, &size);
3327
3328   if (num < 2) {
3329     GST_WARNING_OBJECT (demux, "nonsensical mutually exclusive streams count");
3330     return GST_FLOW_OK;
3331   }
3332
3333   if (size < (num * sizeof (guint16)))
3334     goto not_enough_data;
3335
3336   /* read mutually exclusive stream numbers */
3337   mes = g_new (guint8, num + 1);
3338   for (i = 0; i < num; ++i) {
3339     mes[i] = gst_asf_demux_get_uint16 (&data, &size) & 0x7f;
3340     GST_LOG_OBJECT (demux, "mutually exclusive: stream #%d", mes[i]);
3341   }
3342
3343   /* add terminator so we can easily get the count or know when to stop */
3344   mes[i] = (guint8) - 1;
3345
3346   demux->mut_ex_streams = g_slist_append (demux->mut_ex_streams, mes);
3347
3348   return GST_FLOW_OK;
3349
3350   /* Errors */
3351 not_enough_data:
3352   {
3353     GST_WARNING_OBJECT (demux, "short read parsing advanced mutual exclusion");
3354     return GST_FLOW_OK;         /* not absolutely fatal */
3355   }
3356 }
3357
3358 static GstFlowReturn
3359 gst_asf_demux_process_ext_stream_props (GstASFDemux * demux, guint8 * data,
3360     guint64 size)
3361 {
3362   AsfStreamExtProps esp;
3363   AsfStream *stream = NULL;
3364   AsfObject stream_obj;
3365   guint16 stream_name_count;
3366   guint16 num_payload_ext;
3367   guint64 len;
3368   guint8 *stream_obj_data = NULL;
3369   guint8 *data_start;
3370   guint obj_size;
3371   guint i, stream_num;
3372
3373   data_start = data;
3374   obj_size = (guint) size;
3375
3376   if (size < 64)
3377     goto not_enough_data;
3378
3379   esp.valid = TRUE;
3380   esp.start_time = gst_asf_demux_get_uint64 (&data, &size) * GST_MSECOND;
3381   esp.end_time = gst_asf_demux_get_uint64 (&data, &size) * GST_MSECOND;
3382   esp.data_bitrate = gst_asf_demux_get_uint32 (&data, &size);
3383   esp.buffer_size = gst_asf_demux_get_uint32 (&data, &size);
3384   esp.intial_buf_fullness = gst_asf_demux_get_uint32 (&data, &size);
3385   esp.data_bitrate2 = gst_asf_demux_get_uint32 (&data, &size);
3386   esp.buffer_size2 = gst_asf_demux_get_uint32 (&data, &size);
3387   esp.intial_buf_fullness2 = gst_asf_demux_get_uint32 (&data, &size);
3388   esp.max_obj_size = gst_asf_demux_get_uint32 (&data, &size);
3389   esp.flags = gst_asf_demux_get_uint32 (&data, &size);
3390   stream_num = gst_asf_demux_get_uint16 (&data, &size);
3391   esp.lang_idx = gst_asf_demux_get_uint16 (&data, &size);
3392   esp.avg_time_per_frame = gst_asf_demux_get_uint64 (&data, &size);
3393   stream_name_count = gst_asf_demux_get_uint16 (&data, &size);
3394   num_payload_ext = gst_asf_demux_get_uint16 (&data, &size);
3395
3396   GST_INFO ("start_time             = %" GST_TIME_FORMAT,
3397       GST_TIME_ARGS (esp.start_time));
3398   GST_INFO ("end_time               = %" GST_TIME_FORMAT,
3399       GST_TIME_ARGS (esp.end_time));
3400   GST_INFO ("flags                  = %08x", esp.flags);
3401   GST_INFO ("average time per frame = %" GST_TIME_FORMAT,
3402       GST_TIME_ARGS (esp.avg_time_per_frame * 100));
3403   GST_INFO ("stream number          = %u", stream_num);
3404   GST_INFO ("stream language ID idx = %u (%s)", esp.lang_idx,
3405       (esp.lang_idx < demux->num_languages) ?
3406       GST_STR_NULL (demux->languages[esp.lang_idx]) : "??");
3407   GST_INFO ("stream name count      = %u", stream_name_count);
3408
3409   /* read stream names */
3410   for (i = 0; i < stream_name_count; ++i) {
3411     guint16 stream_lang_idx G_GNUC_UNUSED;
3412     gchar *stream_name = NULL;
3413
3414     if (size < 2)
3415       goto not_enough_data;
3416     stream_lang_idx = gst_asf_demux_get_uint16 (&data, &size);
3417     if (!gst_asf_demux_get_string (&stream_name, NULL, &data, &size))
3418       goto not_enough_data;
3419     GST_INFO ("stream name %d: %s", i, GST_STR_NULL (stream_name));
3420     g_free (stream_name);       /* TODO: store names in struct */
3421   }
3422
3423   /* read payload extension systems stuff */
3424   GST_LOG ("payload extension systems count = %u", num_payload_ext);
3425
3426   if (num_payload_ext > 0)
3427     esp.payload_extensions = g_new0 (AsfPayloadExtension, num_payload_ext + 1);
3428   else
3429     esp.payload_extensions = NULL;
3430
3431   for (i = 0; i < num_payload_ext; ++i) {
3432     AsfPayloadExtension ext;
3433     ASFGuid ext_guid;
3434     guint32 sys_info_len;
3435
3436     if (size < 16 + 2 + 4)
3437       goto not_enough_data;
3438
3439     gst_asf_demux_get_guid (&ext_guid, &data, &size);
3440     ext.id = gst_asf_demux_identify_guid (asf_payload_ext_guids, &ext_guid);
3441     ext.len = gst_asf_demux_get_uint16 (&data, &size);
3442
3443     sys_info_len = gst_asf_demux_get_uint32 (&data, &size);
3444     GST_LOG ("payload systems info len = %u", sys_info_len);
3445     if (!gst_asf_demux_skip_bytes (sys_info_len, &data, &size))
3446       goto not_enough_data;
3447
3448     esp.payload_extensions[i] = ext;
3449   }
3450
3451   GST_LOG ("bytes read: %u/%u", (guint) (data - data_start), obj_size);
3452
3453   /* there might be an optional STREAM_INFO object here now; if not, we
3454    * should have parsed the corresponding stream info object already (since
3455    * we are parsing the extended stream properties objects delayed) */
3456   if (size == 0) {
3457     stream = gst_asf_demux_get_stream (demux, stream_num);
3458     goto done;
3459   }
3460
3461   /* get size of the stream object */
3462   if (!asf_demux_peek_object (demux, data, size, &stream_obj, TRUE))
3463     goto not_enough_data;
3464
3465   if (stream_obj.id != ASF_OBJ_STREAM)
3466     goto expected_stream_object;
3467
3468   if (stream_obj.size < ASF_OBJECT_HEADER_SIZE ||
3469       stream_obj.size > (10 * 1024 * 1024))
3470     goto not_enough_data;
3471
3472   gst_asf_demux_skip_bytes (ASF_OBJECT_HEADER_SIZE, &data, &size);
3473
3474   /* process this stream object later after all the other 'normal' ones
3475    * have been processed (since the others are more important/non-hidden) */
3476   len = stream_obj.size - ASF_OBJECT_HEADER_SIZE;
3477   if (!gst_asf_demux_get_bytes (&stream_obj_data, len, &data, &size))
3478     goto not_enough_data;
3479
3480   /* parse stream object */
3481   stream = gst_asf_demux_parse_stream_object (demux, stream_obj_data, len);
3482   g_free (stream_obj_data);
3483
3484 done:
3485
3486   if (stream) {
3487     stream->ext_props = esp;
3488
3489     /* try to set the framerate */
3490     if (stream->is_video && stream->caps) {
3491       GValue framerate = { 0 };
3492       GstStructure *s;
3493       gint num, denom;
3494
3495       g_value_init (&framerate, GST_TYPE_FRACTION);
3496
3497       num = GST_SECOND / 100;
3498       denom = esp.avg_time_per_frame;
3499       if (denom == 0) {
3500         /* avoid division by 0, assume 25/1 framerate */
3501         denom = GST_SECOND / 2500;
3502       }
3503
3504       gst_value_set_fraction (&framerate, num, denom);
3505
3506       stream->caps = gst_caps_make_writable (stream->caps);
3507       s = gst_caps_get_structure (stream->caps, 0);
3508       gst_structure_set_value (s, "framerate", &framerate);
3509       g_value_unset (&framerate);
3510       GST_DEBUG_OBJECT (demux, "setting framerate of %d/%d = %f",
3511           num, denom, ((gdouble) num) / denom);
3512     }
3513
3514     /* add language info now if we have it */
3515     if (stream->ext_props.lang_idx < demux->num_languages) {
3516       if (stream->pending_tags == NULL)
3517         stream->pending_tags = gst_tag_list_new_empty ();
3518       GST_LOG_OBJECT (demux, "stream %u has language '%s'", stream->id,
3519           demux->languages[stream->ext_props.lang_idx]);
3520       gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_APPEND,
3521           GST_TAG_LANGUAGE_CODE, demux->languages[stream->ext_props.lang_idx],
3522           NULL);
3523     }
3524   } else {
3525     GST_WARNING_OBJECT (demux, "Ext. stream properties for unknown stream");
3526   }
3527
3528   return GST_FLOW_OK;
3529
3530   /* Errors */
3531 not_enough_data:
3532   {
3533     GST_WARNING_OBJECT (demux, "short read parsing ext stream props object!");
3534     return GST_FLOW_OK;         /* not absolutely fatal */
3535   }
3536 expected_stream_object:
3537   {
3538     GST_WARNING_OBJECT (demux, "error parsing extended stream properties "
3539         "object: expected embedded stream object, but got %s object instead!",
3540         gst_asf_get_guid_nick (asf_object_guids, stream_obj.id));
3541     return GST_FLOW_OK;         /* not absolutely fatal */
3542   }
3543 }
3544
3545 static const gchar *
3546 gst_asf_demux_push_obj (GstASFDemux * demux, guint32 obj_id)
3547 {
3548   const gchar *nick;
3549
3550   nick = gst_asf_get_guid_nick (asf_object_guids, obj_id);
3551   if (g_str_has_prefix (nick, "ASF_OBJ_"))
3552     nick += strlen ("ASF_OBJ_");
3553
3554   if (demux->objpath == NULL) {
3555     demux->objpath = g_strdup (nick);
3556   } else {
3557     gchar *newpath;
3558
3559     newpath = g_strdup_printf ("%s/%s", demux->objpath, nick);
3560     g_free (demux->objpath);
3561     demux->objpath = newpath;
3562   }
3563
3564   return (const gchar *) demux->objpath;
3565 }
3566
3567 static void
3568 gst_asf_demux_pop_obj (GstASFDemux * demux)
3569 {
3570   gchar *s;
3571
3572   if ((s = g_strrstr (demux->objpath, "/"))) {
3573     *s = '\0';
3574   } else {
3575     g_free (demux->objpath);
3576     demux->objpath = NULL;
3577   }
3578 }
3579
3580 static void
3581 gst_asf_demux_process_queued_extended_stream_objects (GstASFDemux * demux)
3582 {
3583   GSList *l;
3584   guint i;
3585
3586   /* Parse the queued extended stream property objects and add the info
3587    * to the existing streams or add the new embedded streams, but without
3588    * activating them yet */
3589   GST_LOG_OBJECT (demux, "%u queued extended stream properties objects",
3590       g_slist_length (demux->ext_stream_props));
3591
3592   for (l = demux->ext_stream_props, i = 0; l != NULL; l = l->next, ++i) {
3593     GstBuffer *buf = GST_BUFFER (l->data);
3594     GstMapInfo map;
3595
3596     gst_buffer_map (buf, &map, GST_MAP_READ);
3597
3598     GST_LOG_OBJECT (demux, "parsing ext. stream properties object #%u", i);
3599     gst_asf_demux_process_ext_stream_props (demux, map.data, map.size);
3600     gst_buffer_unmap (buf, &map);
3601     gst_buffer_unref (buf);
3602   }
3603   g_slist_free (demux->ext_stream_props);
3604   demux->ext_stream_props = NULL;
3605 }
3606
3607 #if 0
3608 static void
3609 gst_asf_demux_activate_ext_props_streams (GstASFDemux * demux)
3610 {
3611   guint i, j;
3612
3613   for (i = 0; i < demux->num_streams; ++i) {
3614     AsfStream *stream;
3615     gboolean is_hidden;
3616     GSList *x;
3617
3618     stream = &demux->stream[i];
3619
3620     GST_LOG_OBJECT (demux, "checking  stream %2u", stream->id);
3621
3622     if (stream->active) {
3623       GST_LOG_OBJECT (demux, "stream %2u is already activated", stream->id);
3624       continue;
3625     }
3626
3627     is_hidden = FALSE;
3628     for (x = demux->mut_ex_streams; x != NULL; x = x->next) {
3629       guint8 *mes;
3630
3631       /* check for each mutual exclusion whether it affects this stream */
3632       for (mes = (guint8 *) x->data; mes != NULL && *mes != 0xff; ++mes) {
3633         if (*mes == stream->id) {
3634           /* if yes, check if we've already added streams that are mutually
3635            * exclusive with the stream we're about to add */
3636           for (mes = (guint8 *) x->data; mes != NULL && *mes != 0xff; ++mes) {
3637             for (j = 0; j < demux->num_streams; ++j) {
3638               /* if the broadcast flag is set, assume the hidden streams aren't
3639                * actually streamed and hide them (or playbin won't work right),
3640                * otherwise assume their data is available */
3641               if (demux->stream[j].id == *mes && demux->broadcast) {
3642                 is_hidden = TRUE;
3643                 GST_LOG_OBJECT (demux, "broadcast stream ID %d to be added is "
3644                     "mutually exclusive with already existing stream ID %d, "
3645                     "hiding stream", stream->id, demux->stream[j].id);
3646                 goto next;
3647               }
3648             }
3649           }
3650           break;
3651         }
3652       }
3653     }
3654
3655   next:
3656
3657     /* FIXME: we should do stream activation based on preroll data in
3658      * streaming mode too */
3659     if (demux->streaming && !is_hidden)
3660       gst_asf_demux_activate_stream (demux, stream);
3661   }
3662 }
3663 #endif
3664
3665 static GstFlowReturn
3666 gst_asf_demux_process_object (GstASFDemux * demux, guint8 ** p_data,
3667     guint64 * p_size)
3668 {
3669   GstFlowReturn ret = GST_FLOW_OK;
3670   AsfObject obj;
3671   guint64 obj_data_size;
3672
3673   if (*p_size < ASF_OBJECT_HEADER_SIZE)
3674     return ASF_FLOW_NEED_MORE_DATA;
3675
3676   asf_demux_peek_object (demux, *p_data, ASF_OBJECT_HEADER_SIZE, &obj, TRUE);
3677   gst_asf_demux_skip_bytes (ASF_OBJECT_HEADER_SIZE, p_data, p_size);
3678
3679   obj_data_size = obj.size - ASF_OBJECT_HEADER_SIZE;
3680
3681   if (*p_size < obj_data_size)
3682     return ASF_FLOW_NEED_MORE_DATA;
3683
3684   gst_asf_demux_push_obj (demux, obj.id);
3685
3686   GST_INFO ("%s: size %" G_GUINT64_FORMAT, demux->objpath, obj.size);
3687
3688   switch (obj.id) {
3689     case ASF_OBJ_STREAM:
3690       gst_asf_demux_parse_stream_object (demux, *p_data, obj_data_size);
3691       ret = GST_FLOW_OK;
3692       break;
3693     case ASF_OBJ_FILE:
3694       ret = gst_asf_demux_process_file (demux, *p_data, obj_data_size);
3695       break;
3696     case ASF_OBJ_HEADER:
3697       ret = gst_asf_demux_process_header (demux, *p_data, obj_data_size);
3698       break;
3699     case ASF_OBJ_COMMENT:
3700       ret = gst_asf_demux_process_comment (demux, *p_data, obj_data_size);
3701       break;
3702     case ASF_OBJ_HEAD1:
3703       ret = gst_asf_demux_process_header_ext (demux, *p_data, obj_data_size);
3704       break;
3705     case ASF_OBJ_BITRATE_PROPS:
3706       ret =
3707           gst_asf_demux_process_bitrate_props_object (demux, *p_data,
3708           obj_data_size);
3709       break;
3710     case ASF_OBJ_EXT_CONTENT_DESC:
3711       ret =
3712           gst_asf_demux_process_ext_content_desc (demux, *p_data,
3713           obj_data_size);
3714       break;
3715     case ASF_OBJ_METADATA_OBJECT:
3716       ret = gst_asf_demux_process_metadata (demux, *p_data, obj_data_size);
3717       break;
3718     case ASF_OBJ_EXTENDED_STREAM_PROPS:{
3719       GstBuffer *buf;
3720
3721       /* process these later, we might not have parsed the corresponding
3722        * stream object yet */
3723       GST_LOG ("%s: queued for later parsing", demux->objpath);
3724       buf = gst_buffer_new_and_alloc (obj_data_size);
3725       gst_buffer_fill (buf, 0, *p_data, obj_data_size);
3726       demux->ext_stream_props = g_slist_append (demux->ext_stream_props, buf);
3727       ret = GST_FLOW_OK;
3728       break;
3729     }
3730     case ASF_OBJ_LANGUAGE_LIST:
3731       ret = gst_asf_demux_process_language_list (demux, *p_data, obj_data_size);
3732       break;
3733     case ASF_OBJ_ADVANCED_MUTUAL_EXCLUSION:
3734       ret = gst_asf_demux_process_advanced_mutual_exclusion (demux, *p_data,
3735           obj_data_size);
3736       break;
3737     case ASF_OBJ_SIMPLE_INDEX:
3738       ret = gst_asf_demux_process_simple_index (demux, *p_data, obj_data_size);
3739       break;
3740     case ASF_OBJ_CONTENT_ENCRYPTION:
3741     case ASF_OBJ_EXT_CONTENT_ENCRYPTION:
3742     case ASF_OBJ_DIGITAL_SIGNATURE_OBJECT:
3743     case ASF_OBJ_UNKNOWN_ENCRYPTION_OBJECT:
3744       goto error_encrypted;
3745     case ASF_OBJ_CONCEAL_NONE:
3746     case ASF_OBJ_HEAD2:
3747     case ASF_OBJ_UNDEFINED:
3748     case ASF_OBJ_CODEC_COMMENT:
3749     case ASF_OBJ_INDEX:
3750     case ASF_OBJ_PADDING:
3751     case ASF_OBJ_BITRATE_MUTEX:
3752     case ASF_OBJ_COMPATIBILITY:
3753     case ASF_OBJ_INDEX_PLACEHOLDER:
3754     case ASF_OBJ_INDEX_PARAMETERS:
3755     case ASF_OBJ_STREAM_PRIORITIZATION:
3756     case ASF_OBJ_SCRIPT_COMMAND:
3757     default:
3758       /* Unknown/unhandled object, skip it and hope for the best */
3759       GST_INFO ("%s: skipping object", demux->objpath);
3760       ret = GST_FLOW_OK;
3761       break;
3762   }
3763
3764   /* this can't fail, we checked the number of bytes available before */
3765   gst_asf_demux_skip_bytes (obj_data_size, p_data, p_size);
3766
3767   GST_LOG ("%s: ret = %s", demux->objpath, gst_asf_get_flow_name (ret));
3768
3769   gst_asf_demux_pop_obj (demux);
3770
3771   return ret;
3772
3773 /* ERRORS */
3774 error_encrypted:
3775   {
3776     GST_ELEMENT_ERROR (demux, STREAM, DECRYPT, (NULL), (NULL));
3777     return GST_FLOW_ERROR;
3778   }
3779 }
3780
3781 static void
3782 gst_asf_demux_descramble_buffer (GstASFDemux * demux, AsfStream * stream,
3783     GstBuffer ** p_buffer)
3784 {
3785   GstBuffer *descrambled_buffer;
3786   GstBuffer *scrambled_buffer;
3787   GstBuffer *sub_buffer;
3788   guint offset;
3789   guint off;
3790   guint row;
3791   guint col;
3792   guint idx;
3793
3794   /* descrambled_buffer is initialised in the first iteration */
3795   descrambled_buffer = NULL;
3796   scrambled_buffer = *p_buffer;
3797
3798   if (gst_buffer_get_size (scrambled_buffer) <
3799       demux->ds_packet_size * demux->span)
3800     return;
3801
3802   for (offset = 0; offset < gst_buffer_get_size (scrambled_buffer);
3803       offset += demux->ds_chunk_size) {
3804     off = offset / demux->ds_chunk_size;
3805     row = off / demux->span;
3806     col = off % demux->span;
3807     idx = row + col * demux->ds_packet_size / demux->ds_chunk_size;
3808     GST_DEBUG ("idx=%u, row=%u, col=%u, off=%u, ds_chunk_size=%u", idx, row,
3809         col, off, demux->ds_chunk_size);
3810     GST_DEBUG ("scrambled buffer size=%" G_GSIZE_FORMAT
3811         ", span=%u, packet_size=%u", gst_buffer_get_size (scrambled_buffer),
3812         demux->span, demux->ds_packet_size);
3813     GST_DEBUG ("gst_buffer_get_size (scrambled_buffer) = %" G_GSIZE_FORMAT,
3814         gst_buffer_get_size (scrambled_buffer));
3815     sub_buffer =
3816         gst_buffer_copy_region (scrambled_buffer, GST_BUFFER_COPY_NONE,
3817         idx * demux->ds_chunk_size, demux->ds_chunk_size);
3818     if (!offset) {
3819       descrambled_buffer = sub_buffer;
3820     } else {
3821       descrambled_buffer = gst_buffer_append (descrambled_buffer, sub_buffer);
3822     }
3823   }
3824
3825   GST_BUFFER_TIMESTAMP (descrambled_buffer) =
3826       GST_BUFFER_TIMESTAMP (scrambled_buffer);
3827   GST_BUFFER_DURATION (descrambled_buffer) =
3828       GST_BUFFER_DURATION (scrambled_buffer);
3829   GST_BUFFER_OFFSET (descrambled_buffer) = GST_BUFFER_OFFSET (scrambled_buffer);
3830   GST_BUFFER_OFFSET_END (descrambled_buffer) =
3831       GST_BUFFER_OFFSET_END (scrambled_buffer);
3832
3833   /* FIXME/CHECK: do we need to transfer buffer flags here too? */
3834
3835   gst_buffer_unref (scrambled_buffer);
3836   *p_buffer = descrambled_buffer;
3837 }
3838
3839 static gboolean
3840 gst_asf_demux_element_send_event (GstElement * element, GstEvent * event)
3841 {
3842   GstASFDemux *demux = GST_ASF_DEMUX (element);
3843   gint i;
3844
3845   GST_DEBUG ("handling element event of type %s", GST_EVENT_TYPE_NAME (event));
3846
3847   for (i = 0; i < demux->num_streams; ++i) {
3848     gst_event_ref (event);
3849     if (gst_asf_demux_handle_src_event (demux->stream[i].pad,
3850             GST_OBJECT_CAST (element), event)) {
3851       gst_event_unref (event);
3852       return TRUE;
3853     }
3854   }
3855
3856   gst_event_unref (event);
3857   return FALSE;
3858 }
3859
3860 /* takes ownership of the passed event */
3861 static gboolean
3862 gst_asf_demux_send_event_unlocked (GstASFDemux * demux, GstEvent * event)
3863 {
3864   gboolean ret = TRUE;
3865   gint i;
3866
3867   GST_DEBUG_OBJECT (demux, "sending %s event to all source pads",
3868       GST_EVENT_TYPE_NAME (event));
3869
3870   for (i = 0; i < demux->num_streams; ++i) {
3871     gst_event_ref (event);
3872     ret &= gst_pad_push_event (demux->stream[i].pad, event);
3873   }
3874   gst_event_unref (event);
3875   return ret;
3876 }
3877
3878 static gboolean
3879 gst_asf_demux_handle_src_query (GstPad * pad, GstObject * parent,
3880     GstQuery * query)
3881 {
3882   GstASFDemux *demux;
3883   gboolean res = FALSE;
3884
3885   demux = GST_ASF_DEMUX (parent);
3886
3887   GST_DEBUG ("handling %s query",
3888       gst_query_type_get_name (GST_QUERY_TYPE (query)));
3889
3890   switch (GST_QUERY_TYPE (query)) {
3891     case GST_QUERY_DURATION:
3892     {
3893       GstFormat format;
3894
3895       gst_query_parse_duration (query, &format, NULL);
3896
3897       if (format != GST_FORMAT_TIME) {
3898         GST_LOG ("only support duration queries in TIME format");
3899         break;
3900       }
3901
3902       GST_OBJECT_LOCK (demux);
3903
3904       if (demux->segment.duration != GST_CLOCK_TIME_NONE) {
3905         GST_LOG ("returning duration: %" GST_TIME_FORMAT,
3906             GST_TIME_ARGS (demux->segment.duration));
3907
3908         gst_query_set_duration (query, GST_FORMAT_TIME,
3909             demux->segment.duration);
3910
3911         res = TRUE;
3912       } else {
3913         GST_LOG ("duration not known yet");
3914       }
3915
3916       GST_OBJECT_UNLOCK (demux);
3917       break;
3918     }
3919
3920     case GST_QUERY_POSITION:{
3921       GstFormat format;
3922
3923       gst_query_parse_position (query, &format, NULL);
3924
3925       if (format != GST_FORMAT_TIME) {
3926         GST_LOG ("only support position queries in TIME format");
3927         break;
3928       }
3929
3930       GST_OBJECT_LOCK (demux);
3931
3932       if (demux->segment.position != GST_CLOCK_TIME_NONE) {
3933         GST_LOG ("returning position: %" GST_TIME_FORMAT,
3934             GST_TIME_ARGS (demux->segment.position));
3935
3936         gst_query_set_position (query, GST_FORMAT_TIME,
3937             demux->segment.position);
3938
3939         res = TRUE;
3940       } else {
3941         GST_LOG ("position not known yet");
3942       }
3943
3944       GST_OBJECT_UNLOCK (demux);
3945       break;
3946     }
3947
3948     case GST_QUERY_SEEKING:{
3949       GstFormat format;
3950
3951       gst_query_parse_seeking (query, &format, NULL, NULL, NULL);
3952       if (format == GST_FORMAT_TIME) {
3953         gint64 duration;
3954
3955         GST_OBJECT_LOCK (demux);
3956         duration = demux->segment.duration;
3957         GST_OBJECT_UNLOCK (demux);
3958
3959         if (!demux->streaming || !demux->seekable) {
3960           gst_query_set_seeking (query, GST_FORMAT_TIME, demux->seekable, 0,
3961               duration);
3962           res = TRUE;
3963         } else {
3964           GstFormat fmt;
3965           gboolean seekable;
3966
3967           /* try downstream first in TIME */
3968           res = gst_pad_query_default (pad, parent, query);
3969
3970           gst_query_parse_seeking (query, &fmt, &seekable, NULL, NULL);
3971           GST_LOG_OBJECT (demux, "upstream %s seekable %d",
3972               GST_STR_NULL (gst_format_get_name (fmt)), seekable);
3973           /* if no luck, maybe in BYTES */
3974           if (!seekable || fmt != GST_FORMAT_TIME) {
3975             GstQuery *q;
3976
3977             q = gst_query_new_seeking (GST_FORMAT_BYTES);
3978             if ((res = gst_pad_peer_query (demux->sinkpad, q))) {
3979               gst_query_parse_seeking (q, &fmt, &seekable, NULL, NULL);
3980               GST_LOG_OBJECT (demux, "upstream %s seekable %d",
3981                   GST_STR_NULL (gst_format_get_name (fmt)), seekable);
3982               if (fmt != GST_FORMAT_BYTES)
3983                 seekable = FALSE;
3984             }
3985             gst_query_unref (q);
3986             gst_query_set_seeking (query, GST_FORMAT_TIME, seekable, 0,
3987                 duration);
3988             res = TRUE;
3989           }
3990         }
3991       } else
3992         GST_LOG_OBJECT (demux, "only support seeking in TIME format");
3993       break;
3994     }
3995
3996     case GST_QUERY_LATENCY:
3997     {
3998       gboolean live;
3999       GstClockTime min, max;
4000
4001       /* preroll delay does not matter in non-live pipeline,
4002        * but we might end up in a live (rtsp) one ... */
4003
4004       /* first forward */
4005       res = gst_pad_query_default (pad, parent, query);
4006       if (!res)
4007         break;
4008
4009       gst_query_parse_latency (query, &live, &min, &max);
4010
4011       GST_DEBUG_OBJECT (demux, "Peer latency: live %d, min %"
4012           GST_TIME_FORMAT " max %" GST_TIME_FORMAT, live,
4013           GST_TIME_ARGS (min), GST_TIME_ARGS (max));
4014
4015       GST_OBJECT_LOCK (demux);
4016       if (min != -1)
4017         min += demux->latency;
4018       if (max != -1)
4019         max += demux->latency;
4020       GST_OBJECT_UNLOCK (demux);
4021
4022       gst_query_set_latency (query, live, min, max);
4023       break;
4024     }
4025     default:
4026       res = gst_pad_query_default (pad, parent, query);
4027       break;
4028   }
4029
4030   return res;
4031 }
4032
4033 static GstStateChangeReturn
4034 gst_asf_demux_change_state (GstElement * element, GstStateChange transition)
4035 {
4036   GstASFDemux *demux = GST_ASF_DEMUX (element);
4037   GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
4038
4039   switch (transition) {
4040     case GST_STATE_CHANGE_NULL_TO_READY:{
4041       gst_segment_init (&demux->segment, GST_FORMAT_TIME);
4042       demux->need_newsegment = TRUE;
4043       demux->segment_running = FALSE;
4044       demux->accurate = FALSE;
4045       demux->adapter = gst_adapter_new ();
4046       demux->metadata = gst_caps_new_empty ();
4047       demux->global_metadata = gst_structure_new_empty ("metadata");
4048       demux->data_size = 0;
4049       demux->data_offset = 0;
4050       demux->index_offset = 0;
4051       demux->base_offset = 0;
4052       break;
4053     }
4054     default:
4055       break;
4056   }
4057
4058   ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
4059   if (ret == GST_STATE_CHANGE_FAILURE)
4060     return ret;
4061
4062   switch (transition) {
4063     case GST_STATE_CHANGE_PAUSED_TO_READY:
4064     case GST_STATE_CHANGE_READY_TO_NULL:
4065       gst_asf_demux_reset (demux, FALSE);
4066       break;
4067     default:
4068       break;
4069   }
4070
4071   return ret;
4072 }