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