asfdemux: Use gst_video_multiview_guess_half_aspect() function
[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   guint par_w = 1, par_h = 1;
2505
2506   /* Create the video pad */
2507   name = g_strdup_printf ("video_%u", demux->num_video_streams);
2508   src_pad = gst_pad_new_from_static_template (&video_src_template, name);
2509   g_free (name);
2510
2511   /* Now try some gstreamer formatted MIME types (from gst_avi_demux_strf_vids) */
2512   if (size_left) {
2513     GST_LOG ("Video header has %d bytes of codec specific data", size_left);
2514     g_assert (size_left <= *p_size);
2515     gst_asf_demux_get_buffer (&extradata, size_left, p_data, p_size);
2516   }
2517
2518   GST_DEBUG ("video codec %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (video->tag));
2519
2520   /* yes, asf_stream_video_format and gst_riff_strf_vids are the same */
2521   caps = gst_riff_create_video_caps (video->tag, NULL,
2522       (gst_riff_strf_vids *) video, extradata, NULL, &codec_name);
2523
2524   if (caps == NULL) {
2525     caps = gst_caps_new_simple ("video/x-asf-unknown", "fourcc",
2526         G_TYPE_UINT, video->tag, NULL);
2527   } else {
2528     GstStructure *s;
2529     gint ax, ay;
2530
2531     s = gst_asf_demux_get_metadata_for_stream (demux, id);
2532     if (gst_structure_get_int (s, "AspectRatioX", &ax) &&
2533         gst_structure_get_int (s, "AspectRatioY", &ay) && (ax > 0 && ay > 0)) {
2534       par_w = ax;
2535       par_h = ay;
2536       gst_caps_set_simple (caps, "pixel-aspect-ratio", GST_TYPE_FRACTION,
2537           ax, ay, NULL);
2538     } else {
2539       guint ax, ay;
2540       /* retry with the global metadata */
2541       GST_DEBUG ("Retrying with global metadata %" GST_PTR_FORMAT,
2542           demux->global_metadata);
2543       s = demux->global_metadata;
2544       if (gst_structure_get_uint (s, "AspectRatioX", &ax) &&
2545           gst_structure_get_uint (s, "AspectRatioY", &ay)) {
2546         GST_DEBUG ("ax:%d, ay:%d", ax, ay);
2547         if (ax > 0 && ay > 0) {
2548           par_w = ax;
2549           par_h = ay;
2550           gst_caps_set_simple (caps, "pixel-aspect-ratio", GST_TYPE_FRACTION,
2551               ax, ay, NULL);
2552         }
2553       }
2554     }
2555     s = gst_caps_get_structure (caps, 0);
2556     gst_structure_remove_field (s, "framerate");
2557   }
2558
2559   caps_s = gst_caps_get_structure (caps, 0);
2560
2561   /* add format field with fourcc to WMV/VC1 caps to differentiate variants */
2562   if (gst_structure_has_name (caps_s, "video/x-wmv")) {
2563     str = g_strdup_printf ("%" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (video->tag));
2564     gst_caps_set_simple (caps, "format", G_TYPE_STRING, str, NULL);
2565     g_free (str);
2566
2567     /* check if h264 has codec_data (avc) or streamheaders (bytestream) */
2568   } else if (gst_structure_has_name (caps_s, "video/x-h264")) {
2569     const GValue *value = gst_structure_get_value (caps_s, "codec_data");
2570     GstBuffer *buf = gst_value_get_buffer (value);
2571     GstMapInfo mapinfo;
2572
2573     if (gst_buffer_map (buf, &mapinfo, GST_MAP_READ)) {
2574       if (mapinfo.size >= 4 && GST_READ_UINT32_BE (mapinfo.data) == 1) {
2575         /* this looks like a bytestream start */
2576         streamheader = gst_buffer_ref (buf);
2577         gst_asf_demux_add_stream_headers_to_caps (demux, buf, caps_s);
2578         gst_structure_remove_field (caps_s, "codec_data");
2579       }
2580
2581       gst_buffer_unmap (buf, &mapinfo);
2582     }
2583   }
2584
2585   /* For a 3D video, set multiview information into the caps based on
2586    * what was detected during object parsing */
2587   if (demux->asf_3D_mode != GST_ASF_3D_NONE) {
2588     GstVideoMultiviewMode mv_mode = GST_VIDEO_MULTIVIEW_MODE_NONE;
2589     GstVideoMultiviewFlags mv_flags = GST_VIDEO_MULTIVIEW_FLAGS_NONE;
2590     const gchar *mview_mode_str;
2591
2592     switch (demux->asf_3D_mode) {
2593       case GST_ASF_3D_SIDE_BY_SIDE_HALF_LR:
2594         mv_mode = GST_VIDEO_MULTIVIEW_MODE_SIDE_BY_SIDE;
2595         break;
2596       case GST_ASF_3D_SIDE_BY_SIDE_HALF_RL:
2597         mv_mode = GST_VIDEO_MULTIVIEW_MODE_SIDE_BY_SIDE;
2598         mv_flags = GST_VIDEO_MULTIVIEW_FLAGS_RIGHT_VIEW_FIRST;
2599         break;
2600       case GST_ASF_3D_TOP_AND_BOTTOM_HALF_LR:
2601         mv_mode = GST_VIDEO_MULTIVIEW_MODE_TOP_BOTTOM;
2602         break;
2603       case GST_ASF_3D_TOP_AND_BOTTOM_HALF_RL:
2604         mv_mode = GST_VIDEO_MULTIVIEW_MODE_TOP_BOTTOM;
2605         mv_flags = GST_VIDEO_MULTIVIEW_FLAGS_RIGHT_VIEW_FIRST;
2606         break;
2607       case GST_ASF_3D_DUAL_STREAM:{
2608         gboolean is_right_view = FALSE;
2609         /* if Advanced_Mutual_Exclusion object exists, use it
2610          * to figure out which is the left view (lower ID) */
2611         if (demux->mut_ex_streams != NULL) {
2612           guint length;
2613           gint i;
2614
2615           length = g_slist_length (demux->mut_ex_streams);
2616
2617           for (i = 0; i < length; i++) {
2618             gpointer v_s_id;
2619
2620             v_s_id = g_slist_nth_data (demux->mut_ex_streams, i);
2621
2622             GST_DEBUG_OBJECT (demux,
2623                 "has Mutual_Exclusion object. stream id in object is %d",
2624                 GPOINTER_TO_INT (v_s_id));
2625
2626             if (id > GPOINTER_TO_INT (v_s_id))
2627               is_right_view = TRUE;
2628           }
2629         } else {
2630           /* if the Advaced_Mutual_Exclusion object doesn't exist, assume the
2631            * first video stream encountered has the lower ID */
2632           if (demux->num_video_streams > 0) {
2633             /* This is not the first video stream, assuming right eye view */
2634             is_right_view = TRUE;
2635           }
2636         }
2637         if (is_right_view)
2638           mv_mode = GST_VIDEO_MULTIVIEW_MODE_RIGHT;
2639         else
2640           mv_mode = GST_VIDEO_MULTIVIEW_MODE_LEFT;
2641         break;
2642       }
2643       default:
2644         break;
2645     }
2646
2647     GST_INFO_OBJECT (demux,
2648         "stream_id %d, has multiview-mode %d flags 0x%x", id, mv_mode,
2649         (guint) mv_flags);
2650
2651     mview_mode_str = gst_video_multiview_mode_to_caps_string (mv_mode);
2652     if (mview_mode_str != NULL) {
2653       if (gst_video_multiview_guess_half_aspect (mv_mode, video->width,
2654               video->height, par_w, par_h))
2655         mv_flags |= GST_VIDEO_MULTIVIEW_FLAGS_HALF_ASPECT;
2656
2657       gst_caps_set_simple (caps,
2658           "multiview-mode", G_TYPE_STRING, mview_mode_str,
2659           "multiview-flags", GST_TYPE_VIDEO_MULTIVIEW_FLAGSET, mv_flags,
2660           GST_FLAG_SET_MASK_EXACT, NULL);
2661     }
2662   }
2663
2664   if (codec_name) {
2665     tags = gst_tag_list_new (GST_TAG_VIDEO_CODEC, codec_name, NULL);
2666     g_free (codec_name);
2667   }
2668
2669   if (extradata)
2670     gst_buffer_unref (extradata);
2671
2672   GST_INFO ("Adding video stream #%u, id %u, codec %"
2673       GST_FOURCC_FORMAT " (0x%08x)", demux->num_video_streams, id,
2674       GST_FOURCC_ARGS (video->tag), video->tag);
2675
2676   ++demux->num_video_streams;
2677
2678   return gst_asf_demux_setup_pad (demux, src_pad, caps, id, TRUE,
2679       streamheader, tags);
2680 }
2681
2682 static void
2683 gst_asf_demux_activate_stream (GstASFDemux * demux, AsfStream * stream)
2684 {
2685   if (!stream->active) {
2686     GstEvent *event;
2687     gchar *stream_id;
2688
2689     GST_INFO_OBJECT (demux, "Activating stream %2u, pad %s, caps %"
2690         GST_PTR_FORMAT, stream->id, GST_PAD_NAME (stream->pad), stream->caps);
2691     gst_pad_set_active (stream->pad, TRUE);
2692
2693     stream_id =
2694         gst_pad_create_stream_id_printf (stream->pad, GST_ELEMENT_CAST (demux),
2695         "%03u", stream->id);
2696
2697     event =
2698         gst_pad_get_sticky_event (demux->sinkpad, GST_EVENT_STREAM_START, 0);
2699     if (event) {
2700       if (gst_event_parse_group_id (event, &demux->group_id))
2701         demux->have_group_id = TRUE;
2702       else
2703         demux->have_group_id = FALSE;
2704       gst_event_unref (event);
2705     } else if (!demux->have_group_id) {
2706       demux->have_group_id = TRUE;
2707       demux->group_id = gst_util_group_id_next ();
2708     }
2709
2710     event = gst_event_new_stream_start (stream_id);
2711     if (demux->have_group_id)
2712       gst_event_set_group_id (event, demux->group_id);
2713
2714     gst_pad_push_event (stream->pad, event);
2715     g_free (stream_id);
2716     gst_pad_set_caps (stream->pad, stream->caps);
2717
2718     gst_element_add_pad (GST_ELEMENT_CAST (demux), stream->pad);
2719     gst_flow_combiner_add_pad (demux->flowcombiner, stream->pad);
2720     stream->active = TRUE;
2721   }
2722 }
2723
2724 static AsfStream *
2725 gst_asf_demux_parse_stream_object (GstASFDemux * demux, guint8 * data,
2726     guint64 size)
2727 {
2728   AsfCorrectionType correction_type;
2729   AsfStreamType stream_type;
2730   GstClockTime time_offset;
2731   gboolean is_encrypted G_GNUC_UNUSED;
2732   guint16 stream_id;
2733   guint16 flags;
2734   ASFGuid guid;
2735   guint stream_specific_size;
2736   guint type_specific_size G_GNUC_UNUSED;
2737   guint unknown G_GNUC_UNUSED;
2738   gboolean inspect_payload = FALSE;
2739   AsfStream *stream = NULL;
2740
2741   /* Get the rest of the header's header */
2742   if (size < (16 + 16 + 8 + 4 + 4 + 2 + 4))
2743     goto not_enough_data;
2744
2745   gst_asf_demux_get_guid (&guid, &data, &size);
2746   stream_type = gst_asf_demux_identify_guid (asf_stream_guids, &guid);
2747
2748   gst_asf_demux_get_guid (&guid, &data, &size);
2749   correction_type = gst_asf_demux_identify_guid (asf_correction_guids, &guid);
2750
2751   time_offset = gst_asf_demux_get_uint64 (&data, &size) * 100;
2752
2753   type_specific_size = gst_asf_demux_get_uint32 (&data, &size);
2754   stream_specific_size = gst_asf_demux_get_uint32 (&data, &size);
2755
2756   flags = gst_asf_demux_get_uint16 (&data, &size);
2757   stream_id = flags & 0x7f;
2758   is_encrypted = ! !((flags & 0x8000) << 15);
2759   unknown = gst_asf_demux_get_uint32 (&data, &size);
2760
2761   GST_DEBUG_OBJECT (demux, "Found stream %u, time_offset=%" GST_TIME_FORMAT,
2762       stream_id, GST_TIME_ARGS (time_offset));
2763
2764   /* dvr-ms has audio stream declared in stream specific data */
2765   if (stream_type == ASF_STREAM_EXT_EMBED_HEADER) {
2766     AsfExtStreamType ext_stream_type;
2767     gst_asf_demux_get_guid (&guid, &data, &size);
2768     ext_stream_type = gst_asf_demux_identify_guid (asf_ext_stream_guids, &guid);
2769
2770     if (ext_stream_type == ASF_EXT_STREAM_AUDIO) {
2771       inspect_payload = TRUE;
2772
2773       gst_asf_demux_get_guid (&guid, &data, &size);
2774       gst_asf_demux_get_uint32 (&data, &size);
2775       gst_asf_demux_get_uint32 (&data, &size);
2776       gst_asf_demux_get_uint32 (&data, &size);
2777       gst_asf_demux_get_guid (&guid, &data, &size);
2778       gst_asf_demux_get_uint32 (&data, &size);
2779       stream_type = ASF_STREAM_AUDIO;
2780     }
2781   }
2782
2783   switch (stream_type) {
2784     case ASF_STREAM_AUDIO:{
2785       asf_stream_audio audio_object;
2786
2787       if (!gst_asf_demux_get_stream_audio (&audio_object, &data, &size))
2788         goto not_enough_data;
2789
2790       GST_INFO ("Object is an audio stream with %u bytes of additional data",
2791           audio_object.size);
2792
2793       stream = gst_asf_demux_add_audio_stream (demux, &audio_object, stream_id,
2794           &data, &size);
2795
2796       switch (correction_type) {
2797         case ASF_CORRECTION_ON:{
2798           guint span, packet_size, chunk_size, data_size, silence_data;
2799
2800           GST_INFO ("Using error correction");
2801
2802           if (size < (1 + 2 + 2 + 2 + 1))
2803             goto not_enough_data;
2804
2805           span = gst_asf_demux_get_uint8 (&data, &size);
2806           packet_size = gst_asf_demux_get_uint16 (&data, &size);
2807           chunk_size = gst_asf_demux_get_uint16 (&data, &size);
2808           data_size = gst_asf_demux_get_uint16 (&data, &size);
2809           silence_data = gst_asf_demux_get_uint8 (&data, &size);
2810
2811           stream->span = span;
2812
2813           GST_DEBUG_OBJECT (demux, "Descrambling ps:%u cs:%u ds:%u s:%u sd:%u",
2814               packet_size, chunk_size, data_size, span, silence_data);
2815
2816           if (stream->span > 1) {
2817             if (chunk_size == 0 || ((packet_size / chunk_size) <= 1)) {
2818               /* Disable descrambling */
2819               stream->span = 0;
2820             } else {
2821               /* FIXME: this else branch was added for
2822                * weird_al_yankovic - the saga begins.asf */
2823               stream->ds_packet_size = packet_size;
2824               stream->ds_chunk_size = chunk_size;
2825             }
2826           } else {
2827             /* Descambling is enabled */
2828             stream->ds_packet_size = packet_size;
2829             stream->ds_chunk_size = chunk_size;
2830           }
2831 #if 0
2832           /* Now skip the rest of the silence data */
2833           if (data_size > 1)
2834             gst_bytestream_flush (demux->bs, data_size - 1);
2835 #else
2836           /* FIXME: CHECKME. And why -1? */
2837           if (data_size > 1) {
2838             if (!gst_asf_demux_skip_bytes (data_size - 1, &data, &size)) {
2839               goto not_enough_data;
2840             }
2841           }
2842 #endif
2843           break;
2844         }
2845         case ASF_CORRECTION_OFF:{
2846           GST_INFO ("Error correction off");
2847           if (!gst_asf_demux_skip_bytes (stream_specific_size, &data, &size))
2848             goto not_enough_data;
2849           break;
2850         }
2851         default:
2852           GST_ELEMENT_ERROR (demux, STREAM, DEMUX, (NULL),
2853               ("Audio stream using unknown error correction"));
2854           return NULL;
2855       }
2856
2857       break;
2858     }
2859
2860     case ASF_STREAM_VIDEO:{
2861       asf_stream_video_format video_format_object;
2862       asf_stream_video video_object;
2863       guint16 vsize;
2864
2865       if (!gst_asf_demux_get_stream_video (&video_object, &data, &size))
2866         goto not_enough_data;
2867
2868       vsize = video_object.size - 40;   /* Byte order gets offset by single byte */
2869
2870       GST_INFO ("object is a video stream with %u bytes of "
2871           "additional data", vsize);
2872
2873       if (!gst_asf_demux_get_stream_video_format (&video_format_object,
2874               &data, &size)) {
2875         goto not_enough_data;
2876       }
2877
2878       stream = gst_asf_demux_add_video_stream (demux, &video_format_object,
2879           stream_id, &data, &size);
2880
2881       break;
2882     }
2883
2884     default:
2885       GST_WARNING_OBJECT (demux, "Unknown stream type for stream %u",
2886           stream_id);
2887       demux->other_streams =
2888           g_slist_append (demux->other_streams, GINT_TO_POINTER (stream_id));
2889       break;
2890   }
2891
2892   if (stream)
2893     stream->inspect_payload = inspect_payload;
2894   return stream;
2895
2896 not_enough_data:
2897   {
2898     GST_WARNING_OBJECT (demux, "Unexpected end of data parsing stream object");
2899     /* we'll error out later if we found no streams */
2900     return NULL;
2901   }
2902 }
2903
2904 static const gchar *
2905 gst_asf_demux_get_gst_tag_from_tag_name (const gchar * name_utf8)
2906 {
2907   const struct
2908   {
2909     const gchar *asf_name;
2910     const gchar *gst_name;
2911   } tags[] = {
2912     {
2913     "WM/Genre", GST_TAG_GENRE}, {
2914     "WM/AlbumTitle", GST_TAG_ALBUM}, {
2915     "WM/AlbumArtist", GST_TAG_ARTIST}, {
2916     "WM/Picture", GST_TAG_IMAGE}, {
2917     "WM/Track", GST_TAG_TRACK_NUMBER}, {
2918     "WM/TrackNumber", GST_TAG_TRACK_NUMBER}, {
2919     "WM/Year", GST_TAG_DATE_TIME}
2920     /* { "WM/Composer", GST_TAG_COMPOSER } */
2921   };
2922   gsize out;
2923   guint i;
2924
2925   if (name_utf8 == NULL) {
2926     GST_WARNING ("Failed to convert name to UTF8, skipping");
2927     return NULL;
2928   }
2929
2930   out = strlen (name_utf8);
2931
2932   for (i = 0; i < G_N_ELEMENTS (tags); ++i) {
2933     if (strncmp (tags[i].asf_name, name_utf8, out) == 0) {
2934       GST_LOG ("map tagname '%s' -> '%s'", name_utf8, tags[i].gst_name);
2935       return tags[i].gst_name;
2936     }
2937   }
2938
2939   return NULL;
2940 }
2941
2942 /* gst_asf_demux_add_global_tags() takes ownership of taglist! */
2943 static void
2944 gst_asf_demux_add_global_tags (GstASFDemux * demux, GstTagList * taglist)
2945 {
2946   GstTagList *t;
2947
2948   GST_DEBUG_OBJECT (demux, "adding global tags: %" GST_PTR_FORMAT, taglist);
2949
2950   if (taglist == NULL)
2951     return;
2952
2953   if (gst_tag_list_is_empty (taglist)) {
2954     gst_tag_list_unref (taglist);
2955     return;
2956   }
2957
2958   t = gst_tag_list_merge (demux->taglist, taglist, GST_TAG_MERGE_APPEND);
2959   gst_tag_list_set_scope (t, GST_TAG_SCOPE_GLOBAL);
2960   if (demux->taglist)
2961     gst_tag_list_unref (demux->taglist);
2962   gst_tag_list_unref (taglist);
2963   demux->taglist = t;
2964   GST_LOG_OBJECT (demux, "global tags now: %" GST_PTR_FORMAT, demux->taglist);
2965 }
2966
2967 #define ASF_DEMUX_DATA_TYPE_UTF16LE_STRING  0
2968 #define ASF_DEMUX_DATA_TYPE_BYTE_ARRAY      1
2969 #define ASF_DEMUX_DATA_TYPE_BOOL                        2
2970 #define ASF_DEMUX_DATA_TYPE_DWORD           3
2971
2972 static void
2973 asf_demux_parse_picture_tag (GstTagList * tags, const guint8 * tag_data,
2974     guint tag_data_len)
2975 {
2976   GstByteReader r;
2977   const guint8 *img_data = NULL;
2978   guint32 img_data_len = 0;
2979   guint8 pic_type = 0;
2980
2981   gst_byte_reader_init (&r, tag_data, tag_data_len);
2982
2983   /* skip mime type string (we don't trust it and do our own typefinding),
2984    * and also skip the description string, since we don't use it */
2985   if (!gst_byte_reader_get_uint8 (&r, &pic_type) ||
2986       !gst_byte_reader_get_uint32_le (&r, &img_data_len) ||
2987       !gst_byte_reader_skip_string_utf16 (&r) ||
2988       !gst_byte_reader_skip_string_utf16 (&r) ||
2989       !gst_byte_reader_get_data (&r, img_data_len, &img_data)) {
2990     goto not_enough_data;
2991   }
2992
2993
2994   if (!gst_tag_list_add_id3_image (tags, img_data, img_data_len, pic_type))
2995     GST_DEBUG ("failed to add image extracted from WM/Picture tag to taglist");
2996
2997   return;
2998
2999 not_enough_data:
3000   {
3001     GST_DEBUG ("Failed to read WM/Picture tag: not enough data");
3002     GST_MEMDUMP ("WM/Picture data", tag_data, tag_data_len);
3003     return;
3004   }
3005 }
3006
3007 /* Extended Content Description Object */
3008 static GstFlowReturn
3009 gst_asf_demux_process_ext_content_desc (GstASFDemux * demux, guint8 * data,
3010     guint64 size)
3011 {
3012   /* Other known (and unused) 'text/unicode' metadata available :
3013    *
3014    *   WM/Lyrics =
3015    *   WM/MediaPrimaryClassID = {D1607DBC-E323-4BE2-86A1-48A42A28441E}
3016    *   WMFSDKVersion = 9.00.00.2980
3017    *   WMFSDKNeeded = 0.0.0.0000
3018    *   WM/UniqueFileIdentifier = AMGa_id=R    15334;AMGp_id=P     5149;AMGt_id=T  2324984
3019    *   WM/Publisher = 4AD
3020    *   WM/Provider = AMG
3021    *   WM/ProviderRating = 8
3022    *   WM/ProviderStyle = Rock (similar to WM/Genre)
3023    *   WM/GenreID (similar to WM/Genre)
3024    *   WM/TrackNumber (same as WM/Track but as a string)
3025    *
3026    * Other known (and unused) 'non-text' metadata available :
3027    *
3028    *   WM/EncodingTime
3029    *   WM/MCDI
3030    *   IsVBR
3031    *
3032    * We might want to read WM/TrackNumber and use atoi() if we don't have
3033    * WM/Track
3034    */
3035
3036   GstTagList *taglist;
3037   guint16 blockcount, i;
3038   gboolean content3D = FALSE;
3039
3040   struct
3041   {
3042     const gchar *interleave_name;
3043     GstASF3DMode interleaving_type;
3044   } stereoscopic_layout_map[] = {
3045     {
3046     "SideBySideRF", GST_ASF_3D_SIDE_BY_SIDE_HALF_RL}, {
3047     "SideBySideLF", GST_ASF_3D_SIDE_BY_SIDE_HALF_LR}, {
3048     "OverUnderRT", GST_ASF_3D_TOP_AND_BOTTOM_HALF_RL}, {
3049     "OverUnderLT", GST_ASF_3D_TOP_AND_BOTTOM_HALF_LR}, {
3050     "DualStream", GST_ASF_3D_DUAL_STREAM}
3051   };
3052   GST_INFO_OBJECT (demux, "object is an extended content description");
3053
3054   taglist = gst_tag_list_new_empty ();
3055
3056   /* Content Descriptor Count */
3057   if (size < 2)
3058     goto not_enough_data;
3059
3060   blockcount = gst_asf_demux_get_uint16 (&data, &size);
3061
3062   for (i = 1; i <= blockcount; ++i) {
3063     const gchar *gst_tag_name;
3064     guint16 datatype;
3065     guint16 value_len;
3066     guint16 name_len;
3067     GValue tag_value = { 0, };
3068     gsize in, out;
3069     gchar *name;
3070     gchar *name_utf8 = NULL;
3071     gchar *value;
3072
3073     /* Descriptor */
3074     if (!gst_asf_demux_get_string (&name, &name_len, &data, &size))
3075       goto not_enough_data;
3076
3077     if (size < 2) {
3078       g_free (name);
3079       goto not_enough_data;
3080     }
3081     /* Descriptor Value Data Type */
3082     datatype = gst_asf_demux_get_uint16 (&data, &size);
3083
3084     /* Descriptor Value (not really a string, but same thing reading-wise) */
3085     if (!gst_asf_demux_get_string (&value, &value_len, &data, &size)) {
3086       g_free (name);
3087       goto not_enough_data;
3088     }
3089
3090     name_utf8 =
3091         g_convert (name, name_len, "UTF-8", "UTF-16LE", &in, &out, NULL);
3092
3093     if (name_utf8 != NULL) {
3094       GST_DEBUG ("Found tag/metadata %s", name_utf8);
3095
3096       gst_tag_name = gst_asf_demux_get_gst_tag_from_tag_name (name_utf8);
3097       GST_DEBUG ("gst_tag_name %s", GST_STR_NULL (gst_tag_name));
3098
3099       switch (datatype) {
3100         case ASF_DEMUX_DATA_TYPE_UTF16LE_STRING:{
3101           gchar *value_utf8;
3102
3103           value_utf8 = g_convert (value, value_len, "UTF-8", "UTF-16LE",
3104               &in, &out, NULL);
3105
3106           /* get rid of tags with empty value */
3107           if (value_utf8 != NULL && *value_utf8 != '\0') {
3108             GST_DEBUG ("string value %s", value_utf8);
3109
3110             value_utf8[out] = '\0';
3111
3112             if (gst_tag_name != NULL) {
3113               if (strcmp (gst_tag_name, GST_TAG_DATE_TIME) == 0) {
3114                 guint year = atoi (value_utf8);
3115
3116                 if (year > 0) {
3117                   g_value_init (&tag_value, GST_TYPE_DATE_TIME);
3118                   g_value_take_boxed (&tag_value, gst_date_time_new_y (year));
3119                 }
3120               } else if (strcmp (gst_tag_name, GST_TAG_GENRE) == 0) {
3121                 guint id3v1_genre_id;
3122                 const gchar *genre_str;
3123
3124                 if (sscanf (value_utf8, "(%u)", &id3v1_genre_id) == 1 &&
3125                     ((genre_str = gst_tag_id3_genre_get (id3v1_genre_id)))) {
3126                   GST_DEBUG ("Genre: %s -> %s", value_utf8, genre_str);
3127                   g_free (value_utf8);
3128                   value_utf8 = g_strdup (genre_str);
3129                 }
3130               } else {
3131                 GType tag_type;
3132
3133                 /* convert tag from string to other type if required */
3134                 tag_type = gst_tag_get_type (gst_tag_name);
3135                 g_value_init (&tag_value, tag_type);
3136                 if (!gst_value_deserialize (&tag_value, value_utf8)) {
3137                   GValue from_val = { 0, };
3138
3139                   g_value_init (&from_val, G_TYPE_STRING);
3140                   g_value_set_string (&from_val, value_utf8);
3141                   if (!g_value_transform (&from_val, &tag_value)) {
3142                     GST_WARNING_OBJECT (demux,
3143                         "Could not transform string tag to " "%s tag type %s",
3144                         gst_tag_name, g_type_name (tag_type));
3145                     g_value_unset (&tag_value);
3146                   }
3147                   g_value_unset (&from_val);
3148                 }
3149               }
3150             } else {
3151               /* metadata ! */
3152               GST_DEBUG ("Setting metadata");
3153               g_value_init (&tag_value, G_TYPE_STRING);
3154               g_value_set_string (&tag_value, value_utf8);
3155               /* If we found a stereoscopic marker, look for StereoscopicLayout
3156                * metadata */
3157               if (content3D) {
3158                 guint i;
3159                 if (strncmp ("StereoscopicLayout", name_utf8,
3160                         strlen (name_utf8)) == 0) {
3161                   for (i = 0; i < G_N_ELEMENTS (stereoscopic_layout_map); i++) {
3162                     if (g_str_equal (stereoscopic_layout_map[i].interleave_name,
3163                             value_utf8)) {
3164                       demux->asf_3D_mode =
3165                           stereoscopic_layout_map[i].interleaving_type;
3166                       GST_INFO ("find interleave type %u", demux->asf_3D_mode);
3167                     }
3168                   }
3169                 }
3170                 GST_INFO_OBJECT (demux, "3d type is %u", demux->asf_3D_mode);
3171               } else {
3172                 demux->asf_3D_mode = GST_ASF_3D_NONE;
3173                 GST_INFO_OBJECT (demux, "None 3d type");
3174               }
3175             }
3176           } else if (value_utf8 == NULL) {
3177             GST_WARNING ("Failed to convert string value to UTF8, skipping");
3178           } else {
3179             GST_DEBUG ("Skipping empty string value for %s",
3180                 GST_STR_NULL (gst_tag_name));
3181           }
3182           g_free (value_utf8);
3183           break;
3184         }
3185         case ASF_DEMUX_DATA_TYPE_BYTE_ARRAY:{
3186           if (gst_tag_name) {
3187             if (!g_str_equal (gst_tag_name, GST_TAG_IMAGE)) {
3188               GST_FIXME ("Unhandled byte array tag %s",
3189                   GST_STR_NULL (gst_tag_name));
3190               break;
3191             } else {
3192               asf_demux_parse_picture_tag (taglist, (guint8 *) value,
3193                   value_len);
3194             }
3195           }
3196           break;
3197         }
3198         case ASF_DEMUX_DATA_TYPE_DWORD:{
3199           guint uint_val = GST_READ_UINT32_LE (value);
3200
3201           /* this is the track number */
3202           g_value_init (&tag_value, G_TYPE_UINT);
3203
3204           /* WM/Track counts from 0 */
3205           if (!strcmp (name_utf8, "WM/Track"))
3206             ++uint_val;
3207
3208           g_value_set_uint (&tag_value, uint_val);
3209           break;
3210         }
3211           /* Detect 3D */
3212         case ASF_DEMUX_DATA_TYPE_BOOL:{
3213           gboolean bool_val = GST_READ_UINT32_LE (value);
3214
3215           if (strncmp ("Stereoscopic", name_utf8, strlen (name_utf8)) == 0) {
3216             if (bool_val) {
3217               GST_INFO_OBJECT (demux, "This is 3D contents");
3218               content3D = TRUE;
3219             } else {
3220               GST_INFO_OBJECT (demux, "This is not 3D contenst");
3221               content3D = FALSE;
3222             }
3223           }
3224
3225           break;
3226         }
3227         default:{
3228           GST_DEBUG ("Skipping tag %s of type %d", gst_tag_name, datatype);
3229           break;
3230         }
3231       }
3232
3233       if (G_IS_VALUE (&tag_value)) {
3234         if (gst_tag_name) {
3235           GstTagMergeMode merge_mode = GST_TAG_MERGE_APPEND;
3236
3237           /* WM/TrackNumber is more reliable than WM/Track, since the latter
3238            * is supposed to have a 0 base but is often wrongly written to start
3239            * from 1 as well, so prefer WM/TrackNumber when we have it: either
3240            * replace the value added earlier from WM/Track or put it first in
3241            * the list, so that it will get picked up by _get_uint() */
3242           if (strcmp (name_utf8, "WM/TrackNumber") == 0)
3243             merge_mode = GST_TAG_MERGE_REPLACE;
3244
3245           gst_tag_list_add_values (taglist, merge_mode, gst_tag_name,
3246               &tag_value, NULL);
3247         } else {
3248           GST_DEBUG ("Setting global metadata %s", name_utf8);
3249           gst_structure_set_value (demux->global_metadata, name_utf8,
3250               &tag_value);
3251         }
3252
3253         g_value_unset (&tag_value);
3254       }
3255     }
3256
3257     g_free (name);
3258     g_free (value);
3259     g_free (name_utf8);
3260   }
3261
3262   gst_asf_demux_add_global_tags (demux, taglist);
3263
3264   return GST_FLOW_OK;
3265
3266   /* Errors */
3267 not_enough_data:
3268   {
3269     GST_WARNING ("Unexpected end of data parsing ext content desc object");
3270     gst_tag_list_unref (taglist);
3271     return GST_FLOW_OK;         /* not really fatal */
3272   }
3273 }
3274
3275 static GstStructure *
3276 gst_asf_demux_get_metadata_for_stream (GstASFDemux * demux, guint stream_num)
3277 {
3278   gchar sname[32];
3279   guint i;
3280
3281   g_snprintf (sname, sizeof (sname), "stream-%u", stream_num);
3282
3283   for (i = 0; i < gst_caps_get_size (demux->metadata); ++i) {
3284     GstStructure *s;
3285
3286     s = gst_caps_get_structure (demux->metadata, i);
3287     if (gst_structure_has_name (s, sname))
3288       return s;
3289   }
3290
3291   gst_caps_append_structure (demux->metadata, gst_structure_new_empty (sname));
3292
3293   /* try lookup again; demux->metadata took ownership of the structure, so we
3294    * can't really make any assumptions about what happened to it, so we can't
3295    * just return it directly after appending it */
3296   return gst_asf_demux_get_metadata_for_stream (demux, stream_num);
3297 }
3298
3299 static GstFlowReturn
3300 gst_asf_demux_process_metadata (GstASFDemux * demux, guint8 * data,
3301     guint64 size)
3302 {
3303   guint16 blockcount, i;
3304
3305   GST_INFO_OBJECT (demux, "object is a metadata object");
3306
3307   /* Content Descriptor Count */
3308   if (size < 2)
3309     goto not_enough_data;
3310
3311   blockcount = gst_asf_demux_get_uint16 (&data, &size);
3312
3313   for (i = 0; i < blockcount; ++i) {
3314     GstStructure *s;
3315     guint16 stream_num, name_len, data_type, lang_idx G_GNUC_UNUSED;
3316     guint32 data_len, ival;
3317     gchar *name_utf8;
3318
3319     if (size < (2 + 2 + 2 + 2 + 4))
3320       goto not_enough_data;
3321
3322     lang_idx = gst_asf_demux_get_uint16 (&data, &size);
3323     stream_num = gst_asf_demux_get_uint16 (&data, &size);
3324     name_len = gst_asf_demux_get_uint16 (&data, &size);
3325     data_type = gst_asf_demux_get_uint16 (&data, &size);
3326     data_len = gst_asf_demux_get_uint32 (&data, &size);
3327
3328     if (size < name_len + data_len)
3329       goto not_enough_data;
3330
3331     /* convert name to UTF-8 */
3332     name_utf8 = g_convert ((gchar *) data, name_len, "UTF-8", "UTF-16LE",
3333         NULL, NULL, NULL);
3334     gst_asf_demux_skip_bytes (name_len, &data, &size);
3335
3336     if (name_utf8 == NULL) {
3337       GST_WARNING ("Failed to convert value name to UTF8, skipping");
3338       gst_asf_demux_skip_bytes (data_len, &data, &size);
3339       continue;
3340     }
3341
3342     if (data_type != ASF_DEMUX_DATA_TYPE_DWORD) {
3343       gst_asf_demux_skip_bytes (data_len, &data, &size);
3344       g_free (name_utf8);
3345       continue;
3346     }
3347
3348     /* read DWORD */
3349     if (size < 4) {
3350       g_free (name_utf8);
3351       goto not_enough_data;
3352     }
3353
3354     ival = gst_asf_demux_get_uint32 (&data, &size);
3355
3356     /* skip anything else there may be, just in case */
3357     gst_asf_demux_skip_bytes (data_len - 4, &data, &size);
3358
3359     s = gst_asf_demux_get_metadata_for_stream (demux, stream_num);
3360     gst_structure_set (s, name_utf8, G_TYPE_INT, ival, NULL);
3361     g_free (name_utf8);
3362   }
3363
3364   GST_INFO_OBJECT (demux, "metadata = %" GST_PTR_FORMAT, demux->metadata);
3365   return GST_FLOW_OK;
3366
3367   /* Errors */
3368 not_enough_data:
3369   {
3370     GST_WARNING ("Unexpected end of data parsing metadata object");
3371     return GST_FLOW_OK;         /* not really fatal */
3372   }
3373 }
3374
3375 static GstFlowReturn
3376 gst_asf_demux_process_header (GstASFDemux * demux, guint8 * data, guint64 size)
3377 {
3378   GstFlowReturn ret = GST_FLOW_OK;
3379   guint32 i, num_objects;
3380   guint8 unknown G_GNUC_UNUSED;
3381
3382   /* Get the rest of the header's header */
3383   if (size < (4 + 1 + 1))
3384     goto not_enough_data;
3385
3386   num_objects = gst_asf_demux_get_uint32 (&data, &size);
3387   unknown = gst_asf_demux_get_uint8 (&data, &size);
3388   unknown = gst_asf_demux_get_uint8 (&data, &size);
3389
3390   GST_INFO_OBJECT (demux, "object is a header with %u parts", num_objects);
3391
3392   /* Loop through the header's objects, processing those */
3393   for (i = 0; i < num_objects; ++i) {
3394     GST_INFO_OBJECT (demux, "reading header part %u", i);
3395     ret = gst_asf_demux_process_object (demux, &data, &size);
3396     if (ret != GST_FLOW_OK) {
3397       GST_WARNING ("process_object returned %s", gst_asf_get_flow_name (ret));
3398       break;
3399     }
3400   }
3401
3402   return ret;
3403
3404 not_enough_data:
3405   {
3406     GST_ELEMENT_ERROR (demux, STREAM, DEMUX, (NULL),
3407         ("short read parsing HEADER object"));
3408     return GST_FLOW_ERROR;
3409   }
3410 }
3411
3412 static GstFlowReturn
3413 gst_asf_demux_process_file (GstASFDemux * demux, guint8 * data, guint64 size)
3414 {
3415   guint64 creation_time G_GNUC_UNUSED;
3416   guint64 file_size G_GNUC_UNUSED;
3417   guint64 send_time G_GNUC_UNUSED;
3418   guint64 packets_count, play_time, preroll;
3419   guint32 flags, min_pktsize, max_pktsize, min_bitrate G_GNUC_UNUSED;
3420
3421   if (size < (16 + 8 + 8 + 8 + 8 + 8 + 8 + 4 + 4 + 4 + 4))
3422     goto not_enough_data;
3423
3424   gst_asf_demux_skip_bytes (16, &data, &size);  /* skip GUID */
3425   file_size = gst_asf_demux_get_uint64 (&data, &size);
3426   creation_time = gst_asf_demux_get_uint64 (&data, &size);
3427   packets_count = gst_asf_demux_get_uint64 (&data, &size);
3428   play_time = gst_asf_demux_get_uint64 (&data, &size);
3429   send_time = gst_asf_demux_get_uint64 (&data, &size);
3430   preroll = gst_asf_demux_get_uint64 (&data, &size);
3431   flags = gst_asf_demux_get_uint32 (&data, &size);
3432   min_pktsize = gst_asf_demux_get_uint32 (&data, &size);
3433   max_pktsize = gst_asf_demux_get_uint32 (&data, &size);
3434   min_bitrate = gst_asf_demux_get_uint32 (&data, &size);
3435
3436   demux->broadcast = ! !(flags & 0x01);
3437   demux->seekable = ! !(flags & 0x02);
3438
3439   GST_DEBUG_OBJECT (demux, "min_pktsize = %u", min_pktsize);
3440   GST_DEBUG_OBJECT (demux, "flags::broadcast = %d", demux->broadcast);
3441   GST_DEBUG_OBJECT (demux, "flags::seekable  = %d", demux->seekable);
3442
3443   if (demux->broadcast) {
3444     /* these fields are invalid if the broadcast flag is set */
3445     play_time = 0;
3446     file_size = 0;
3447   }
3448
3449   if (min_pktsize != max_pktsize)
3450     goto non_fixed_packet_size;
3451
3452   demux->packet_size = max_pktsize;
3453
3454   /* FIXME: do we need send_time as well? what is it? */
3455   if ((play_time * 100) >= (preroll * GST_MSECOND))
3456     demux->play_time = (play_time * 100) - (preroll * GST_MSECOND);
3457   else
3458     demux->play_time = 0;
3459
3460   demux->preroll = preroll * GST_MSECOND;
3461
3462   /* initial latency */
3463   demux->latency = demux->preroll;
3464
3465   if (demux->play_time == 0)
3466     demux->seekable = FALSE;
3467
3468   GST_DEBUG_OBJECT (demux, "play_time %" GST_TIME_FORMAT,
3469       GST_TIME_ARGS (demux->play_time));
3470   GST_DEBUG_OBJECT (demux, "preroll   %" GST_TIME_FORMAT,
3471       GST_TIME_ARGS (demux->preroll));
3472
3473   if (demux->play_time > 0) {
3474     demux->segment.duration = demux->play_time;
3475   }
3476
3477   GST_INFO ("object is a file with %" G_GUINT64_FORMAT " data packets",
3478       packets_count);
3479   GST_INFO ("preroll = %" G_GUINT64_FORMAT, demux->preroll);
3480
3481   return GST_FLOW_OK;
3482
3483 /* ERRORS */
3484 non_fixed_packet_size:
3485   {
3486     GST_ELEMENT_ERROR (demux, STREAM, DEMUX, (NULL),
3487         ("packet size must be fixed"));
3488     return GST_FLOW_ERROR;
3489   }
3490 not_enough_data:
3491   {
3492     GST_ELEMENT_ERROR (demux, STREAM, DEMUX, (NULL),
3493         ("short read parsing FILE object"));
3494     return GST_FLOW_ERROR;
3495   }
3496 }
3497
3498 /* Content Description Object */
3499 static GstFlowReturn
3500 gst_asf_demux_process_comment (GstASFDemux * demux, guint8 * data, guint64 size)
3501 {
3502   struct
3503   {
3504     const gchar *gst_tag;
3505     guint16 val_length;
3506     gchar *val_utf8;
3507   } tags[5] = {
3508     {
3509     GST_TAG_TITLE, 0, NULL}, {
3510     GST_TAG_ARTIST, 0, NULL}, {
3511     GST_TAG_COPYRIGHT, 0, NULL}, {
3512     GST_TAG_DESCRIPTION, 0, NULL}, {
3513     GST_TAG_COMMENT, 0, NULL}
3514   };
3515   GstTagList *taglist;
3516   GValue value = { 0 };
3517   gsize in, out;
3518   gint i = -1;
3519
3520   GST_INFO_OBJECT (demux, "object is a comment");
3521
3522   if (size < (2 + 2 + 2 + 2 + 2))
3523     goto not_enough_data;
3524
3525   tags[0].val_length = gst_asf_demux_get_uint16 (&data, &size);
3526   tags[1].val_length = gst_asf_demux_get_uint16 (&data, &size);
3527   tags[2].val_length = gst_asf_demux_get_uint16 (&data, &size);
3528   tags[3].val_length = gst_asf_demux_get_uint16 (&data, &size);
3529   tags[4].val_length = gst_asf_demux_get_uint16 (&data, &size);
3530
3531   GST_DEBUG_OBJECT (demux, "Comment lengths: title=%d author=%d copyright=%d "
3532       "description=%d rating=%d", tags[0].val_length, tags[1].val_length,
3533       tags[2].val_length, tags[3].val_length, tags[4].val_length);
3534
3535   for (i = 0; i < G_N_ELEMENTS (tags); ++i) {
3536     if (size < tags[i].val_length)
3537       goto not_enough_data;
3538
3539     /* might be just '/0', '/0'... */
3540     if (tags[i].val_length > 2 && tags[i].val_length % 2 == 0) {
3541       /* convert to UTF-8 */
3542       tags[i].val_utf8 = g_convert ((gchar *) data, tags[i].val_length,
3543           "UTF-8", "UTF-16LE", &in, &out, NULL);
3544     }
3545     gst_asf_demux_skip_bytes (tags[i].val_length, &data, &size);
3546   }
3547
3548   /* parse metadata into taglist */
3549   taglist = gst_tag_list_new_empty ();
3550   g_value_init (&value, G_TYPE_STRING);
3551   for (i = 0; i < G_N_ELEMENTS (tags); ++i) {
3552     if (tags[i].val_utf8 && strlen (tags[i].val_utf8) > 0 && tags[i].gst_tag) {
3553       g_value_set_string (&value, tags[i].val_utf8);
3554       gst_tag_list_add_values (taglist, GST_TAG_MERGE_APPEND,
3555           tags[i].gst_tag, &value, NULL);
3556     }
3557   }
3558   g_value_unset (&value);
3559
3560   gst_asf_demux_add_global_tags (demux, taglist);
3561
3562   for (i = 0; i < G_N_ELEMENTS (tags); ++i)
3563     g_free (tags[i].val_utf8);
3564
3565   return GST_FLOW_OK;
3566
3567 not_enough_data:
3568   {
3569     GST_WARNING_OBJECT (demux, "unexpectedly short of data while processing "
3570         "comment tag section %d, skipping comment object", i);
3571     for (i = 0; i < G_N_ELEMENTS (tags); i++)
3572       g_free (tags[i].val_utf8);
3573     return GST_FLOW_OK;         /* not really fatal */
3574   }
3575 }
3576
3577 static GstFlowReturn
3578 gst_asf_demux_process_bitrate_props_object (GstASFDemux * demux, guint8 * data,
3579     guint64 size)
3580 {
3581   guint16 num_streams, i;
3582   AsfStream *stream;
3583
3584   if (size < 2)
3585     goto not_enough_data;
3586
3587   num_streams = gst_asf_demux_get_uint16 (&data, &size);
3588
3589   GST_INFO ("object is a bitrate properties object with %u streams",
3590       num_streams);
3591
3592   if (size < (num_streams * (2 + 4)))
3593     goto not_enough_data;
3594
3595   for (i = 0; i < num_streams; ++i) {
3596     guint32 bitrate;
3597     guint16 stream_id;
3598
3599     stream_id = gst_asf_demux_get_uint16 (&data, &size);
3600     bitrate = gst_asf_demux_get_uint32 (&data, &size);
3601
3602     if (stream_id < GST_ASF_DEMUX_NUM_STREAM_IDS) {
3603       GST_DEBUG_OBJECT (demux, "bitrate of stream %u = %u", stream_id, bitrate);
3604       stream = gst_asf_demux_get_stream (demux, stream_id);
3605       if (stream) {
3606         if (stream->pending_tags == NULL) {
3607           stream->pending_tags =
3608               gst_tag_list_new (GST_TAG_BITRATE, bitrate, NULL);
3609         }
3610       } else {
3611         GST_WARNING_OBJECT (demux, "Stream id %u wasn't found", stream_id);
3612       }
3613     } else {
3614       GST_WARNING ("stream id %u is too large", stream_id);
3615     }
3616   }
3617
3618   return GST_FLOW_OK;
3619
3620 not_enough_data:
3621   {
3622     GST_WARNING_OBJECT (demux, "short read parsing bitrate props object!");
3623     return GST_FLOW_OK;         /* not really fatal */
3624   }
3625 }
3626
3627 static GstFlowReturn
3628 gst_asf_demux_process_header_ext (GstASFDemux * demux, guint8 * data,
3629     guint64 size)
3630 {
3631   GstFlowReturn ret = GST_FLOW_OK;
3632   guint64 hdr_size;
3633
3634   /* Get the rest of the header's header */
3635   if (size < (16 + 2 + 4))
3636     goto not_enough_data;
3637
3638   /* skip GUID and two other bytes */
3639   gst_asf_demux_skip_bytes (16 + 2, &data, &size);
3640   hdr_size = gst_asf_demux_get_uint32 (&data, &size);
3641
3642   GST_INFO ("extended header object with a size of %u bytes", (guint) size);
3643
3644   /* FIXME: does data_size include the rest of the header that we have read? */
3645   if (hdr_size > size)
3646     goto not_enough_data;
3647
3648   while (hdr_size > 0) {
3649     ret = gst_asf_demux_process_object (demux, &data, &hdr_size);
3650     if (ret != GST_FLOW_OK)
3651       break;
3652   }
3653
3654   return ret;
3655
3656 not_enough_data:
3657   {
3658     GST_ELEMENT_ERROR (demux, STREAM, DEMUX, (NULL),
3659         ("short read parsing extended header object"));
3660     return GST_FLOW_ERROR;
3661   }
3662 }
3663
3664 static GstFlowReturn
3665 gst_asf_demux_process_language_list (GstASFDemux * demux, guint8 * data,
3666     guint64 size)
3667 {
3668   guint i;
3669
3670   if (size < 2)
3671     goto not_enough_data;
3672
3673   if (demux->languages) {
3674     GST_WARNING ("More than one LANGUAGE_LIST object in stream");
3675     g_strfreev (demux->languages);
3676     demux->languages = NULL;
3677     demux->num_languages = 0;
3678   }
3679
3680   demux->num_languages = gst_asf_demux_get_uint16 (&data, &size);
3681   GST_LOG ("%u languages:", demux->num_languages);
3682
3683   demux->languages = g_new0 (gchar *, demux->num_languages + 1);
3684   for (i = 0; i < demux->num_languages; ++i) {
3685     guint8 len, *lang_data = NULL;
3686
3687     if (size < 1)
3688       goto not_enough_data;
3689     len = gst_asf_demux_get_uint8 (&data, &size);
3690     if (gst_asf_demux_get_bytes (&lang_data, len, &data, &size)) {
3691       gchar *utf8;
3692
3693       utf8 = g_convert ((gchar *) lang_data, len, "UTF-8", "UTF-16LE", NULL,
3694           NULL, NULL);
3695
3696       /* truncate "en-us" etc. to just "en" */
3697       if (utf8 && strlen (utf8) >= 5 && (utf8[2] == '-' || utf8[2] == '_')) {
3698         utf8[2] = '\0';
3699       }
3700       GST_DEBUG ("[%u] %s", i, GST_STR_NULL (utf8));
3701       demux->languages[i] = utf8;
3702       g_free (lang_data);
3703     } else {
3704       goto not_enough_data;
3705     }
3706   }
3707
3708   return GST_FLOW_OK;
3709
3710 not_enough_data:
3711   {
3712     GST_WARNING_OBJECT (demux, "short read parsing language list object!");
3713     g_free (demux->languages);
3714     demux->languages = NULL;
3715     return GST_FLOW_OK;         /* not fatal */
3716   }
3717 }
3718
3719 static GstFlowReturn
3720 gst_asf_demux_process_simple_index (GstASFDemux * demux, guint8 * data,
3721     guint64 size)
3722 {
3723   GstClockTime interval;
3724   guint32 count, i;
3725
3726   if (size < (16 + 8 + 4 + 4))
3727     goto not_enough_data;
3728
3729   /* skip file id */
3730   gst_asf_demux_skip_bytes (16, &data, &size);
3731   interval = gst_asf_demux_get_uint64 (&data, &size) * (GstClockTime) 100;
3732   gst_asf_demux_skip_bytes (4, &data, &size);
3733   count = gst_asf_demux_get_uint32 (&data, &size);
3734   if (count > 0) {
3735     demux->sidx_interval = interval;
3736     demux->sidx_num_entries = count;
3737     g_free (demux->sidx_entries);
3738     demux->sidx_entries = g_new0 (AsfSimpleIndexEntry, count);
3739
3740     for (i = 0; i < count; ++i) {
3741       if (G_UNLIKELY (size < 6)) {
3742         /* adjust for broken files, to avoid having entries at the end
3743          * of the parsed index that point to time=0. Resulting in seeking to
3744          * the end of the file leading back to the beginning */
3745         demux->sidx_num_entries -= (count - i);
3746         break;
3747       }
3748       demux->sidx_entries[i].packet = gst_asf_demux_get_uint32 (&data, &size);
3749       demux->sidx_entries[i].count = gst_asf_demux_get_uint16 (&data, &size);
3750       GST_LOG_OBJECT (demux, "%" GST_TIME_FORMAT " = packet %4u  count : %2d",
3751           GST_TIME_ARGS (i * interval), demux->sidx_entries[i].packet,
3752           demux->sidx_entries[i].count);
3753     }
3754   } else {
3755     GST_DEBUG_OBJECT (demux, "simple index object with 0 entries");
3756   }
3757
3758   return GST_FLOW_OK;
3759
3760 not_enough_data:
3761   {
3762     GST_WARNING_OBJECT (demux, "short read parsing simple index object!");
3763     return GST_FLOW_OK;         /* not fatal */
3764   }
3765 }
3766
3767 static GstFlowReturn
3768 gst_asf_demux_process_advanced_mutual_exclusion (GstASFDemux * demux,
3769     guint8 * data, guint64 size)
3770 {
3771   ASFGuid guid;
3772   guint16 num, i;
3773
3774   if (size < 16 + 2 + (2 * 2))
3775     goto not_enough_data;
3776
3777   gst_asf_demux_get_guid (&guid, &data, &size);
3778   num = gst_asf_demux_get_uint16 (&data, &size);
3779
3780   if (num < 2) {
3781     GST_WARNING_OBJECT (demux, "nonsensical mutually exclusive streams count");
3782     return GST_FLOW_OK;
3783   }
3784
3785   if (size < (num * sizeof (guint16)))
3786     goto not_enough_data;
3787
3788   /* read mutually exclusive stream numbers */
3789   for (i = 0; i < num; ++i) {
3790     guint8 mes;
3791     mes = gst_asf_demux_get_uint16 (&data, &size) & 0x7f;
3792     GST_LOG_OBJECT (demux, "mutually exclusive: stream %d", mes);
3793
3794     demux->mut_ex_streams =
3795         g_slist_append (demux->mut_ex_streams, GINT_TO_POINTER (mes));
3796   }
3797
3798
3799   return GST_FLOW_OK;
3800
3801   /* Errors */
3802 not_enough_data:
3803   {
3804     GST_WARNING_OBJECT (demux, "short read parsing advanced mutual exclusion");
3805     return GST_FLOW_OK;         /* not absolutely fatal */
3806   }
3807 }
3808
3809 gboolean
3810 gst_asf_demux_is_unknown_stream (GstASFDemux * demux, guint stream_num)
3811 {
3812   return g_slist_find (demux->other_streams,
3813       GINT_TO_POINTER (stream_num)) == NULL;
3814 }
3815
3816 static GstFlowReturn
3817 gst_asf_demux_process_ext_stream_props (GstASFDemux * demux, guint8 * data,
3818     guint64 size)
3819 {
3820   AsfStreamExtProps esp;
3821   AsfStream *stream = NULL;
3822   AsfObject stream_obj;
3823   guint16 stream_name_count;
3824   guint16 num_payload_ext;
3825   guint64 len;
3826   guint8 *stream_obj_data = NULL;
3827   guint8 *data_start;
3828   guint obj_size;
3829   guint i, stream_num;
3830
3831   data_start = data;
3832   obj_size = (guint) size;
3833
3834   if (size < 64)
3835     goto not_enough_data;
3836
3837   esp.valid = TRUE;
3838   esp.start_time = gst_asf_demux_get_uint64 (&data, &size) * GST_MSECOND;
3839   esp.end_time = gst_asf_demux_get_uint64 (&data, &size) * GST_MSECOND;
3840   esp.data_bitrate = gst_asf_demux_get_uint32 (&data, &size);
3841   esp.buffer_size = gst_asf_demux_get_uint32 (&data, &size);
3842   esp.intial_buf_fullness = gst_asf_demux_get_uint32 (&data, &size);
3843   esp.data_bitrate2 = gst_asf_demux_get_uint32 (&data, &size);
3844   esp.buffer_size2 = gst_asf_demux_get_uint32 (&data, &size);
3845   esp.intial_buf_fullness2 = gst_asf_demux_get_uint32 (&data, &size);
3846   esp.max_obj_size = gst_asf_demux_get_uint32 (&data, &size);
3847   esp.flags = gst_asf_demux_get_uint32 (&data, &size);
3848   stream_num = gst_asf_demux_get_uint16 (&data, &size);
3849   esp.lang_idx = gst_asf_demux_get_uint16 (&data, &size);
3850   esp.avg_time_per_frame = gst_asf_demux_get_uint64 (&data, &size);
3851   stream_name_count = gst_asf_demux_get_uint16 (&data, &size);
3852   num_payload_ext = gst_asf_demux_get_uint16 (&data, &size);
3853
3854   GST_INFO ("start_time             = %" GST_TIME_FORMAT,
3855       GST_TIME_ARGS (esp.start_time));
3856   GST_INFO ("end_time               = %" GST_TIME_FORMAT,
3857       GST_TIME_ARGS (esp.end_time));
3858   GST_INFO ("flags                  = %08x", esp.flags);
3859   GST_INFO ("average time per frame = %" GST_TIME_FORMAT,
3860       GST_TIME_ARGS (esp.avg_time_per_frame * 100));
3861   GST_INFO ("stream number          = %u", stream_num);
3862   GST_INFO ("stream language ID idx = %u (%s)", esp.lang_idx,
3863       (esp.lang_idx < demux->num_languages) ?
3864       GST_STR_NULL (demux->languages[esp.lang_idx]) : "??");
3865   GST_INFO ("stream name count      = %u", stream_name_count);
3866
3867   /* read stream names */
3868   for (i = 0; i < stream_name_count; ++i) {
3869     guint16 stream_lang_idx G_GNUC_UNUSED;
3870     gchar *stream_name = NULL;
3871
3872     if (size < 2)
3873       goto not_enough_data;
3874     stream_lang_idx = gst_asf_demux_get_uint16 (&data, &size);
3875     if (!gst_asf_demux_get_string (&stream_name, NULL, &data, &size))
3876       goto not_enough_data;
3877     GST_INFO ("stream name %d: %s", i, GST_STR_NULL (stream_name));
3878     g_free (stream_name);       /* TODO: store names in struct */
3879   }
3880
3881   /* read payload extension systems stuff */
3882   GST_LOG ("payload extension systems count = %u", num_payload_ext);
3883
3884   if (num_payload_ext > 0)
3885     esp.payload_extensions = g_new0 (AsfPayloadExtension, num_payload_ext + 1);
3886   else
3887     esp.payload_extensions = NULL;
3888
3889   for (i = 0; i < num_payload_ext; ++i) {
3890     AsfPayloadExtension ext;
3891     ASFGuid ext_guid;
3892     guint32 sys_info_len;
3893
3894     if (size < 16 + 2 + 4)
3895       goto not_enough_data;
3896
3897     gst_asf_demux_get_guid (&ext_guid, &data, &size);
3898     ext.id = gst_asf_demux_identify_guid (asf_payload_ext_guids, &ext_guid);
3899     ext.len = gst_asf_demux_get_uint16 (&data, &size);
3900
3901     sys_info_len = gst_asf_demux_get_uint32 (&data, &size);
3902     GST_LOG ("payload systems info len = %u", sys_info_len);
3903     if (!gst_asf_demux_skip_bytes (sys_info_len, &data, &size))
3904       goto not_enough_data;
3905
3906     esp.payload_extensions[i] = ext;
3907   }
3908
3909   GST_LOG ("bytes read: %u/%u", (guint) (data - data_start), obj_size);
3910
3911   /* there might be an optional STREAM_INFO object here now; if not, we
3912    * should have parsed the corresponding stream info object already (since
3913    * we are parsing the extended stream properties objects delayed) */
3914   if (size == 0) {
3915     stream = gst_asf_demux_get_stream (demux, stream_num);
3916     goto done;
3917   }
3918
3919   /* get size of the stream object */
3920   if (!asf_demux_peek_object (demux, data, size, &stream_obj, TRUE))
3921     goto not_enough_data;
3922
3923   if (stream_obj.id != ASF_OBJ_STREAM)
3924     goto expected_stream_object;
3925
3926   if (stream_obj.size < ASF_OBJECT_HEADER_SIZE ||
3927       stream_obj.size > (10 * 1024 * 1024))
3928     goto not_enough_data;
3929
3930   gst_asf_demux_skip_bytes (ASF_OBJECT_HEADER_SIZE, &data, &size);
3931
3932   /* process this stream object later after all the other 'normal' ones
3933    * have been processed (since the others are more important/non-hidden) */
3934   len = stream_obj.size - ASF_OBJECT_HEADER_SIZE;
3935   if (!gst_asf_demux_get_bytes (&stream_obj_data, len, &data, &size))
3936     goto not_enough_data;
3937
3938   /* parse stream object */
3939   stream = gst_asf_demux_parse_stream_object (demux, stream_obj_data, len);
3940   g_free (stream_obj_data);
3941
3942 done:
3943
3944   if (stream) {
3945     stream->ext_props = esp;
3946
3947     /* try to set the framerate */
3948     if (stream->is_video && stream->caps) {
3949       GValue framerate = { 0 };
3950       GstStructure *s;
3951       gint num, denom;
3952
3953       g_value_init (&framerate, GST_TYPE_FRACTION);
3954
3955       num = GST_SECOND / 100;
3956       denom = esp.avg_time_per_frame;
3957       if (denom == 0) {
3958         /* avoid division by 0, assume 25/1 framerate */
3959         denom = GST_SECOND / 2500;
3960       }
3961
3962       gst_value_set_fraction (&framerate, num, denom);
3963
3964       stream->caps = gst_caps_make_writable (stream->caps);
3965       s = gst_caps_get_structure (stream->caps, 0);
3966       gst_structure_set_value (s, "framerate", &framerate);
3967       g_value_unset (&framerate);
3968       GST_DEBUG_OBJECT (demux, "setting framerate of %d/%d = %f",
3969           num, denom, ((gdouble) num) / denom);
3970     }
3971
3972     /* add language info now if we have it */
3973     if (stream->ext_props.lang_idx < demux->num_languages) {
3974       if (stream->pending_tags == NULL)
3975         stream->pending_tags = gst_tag_list_new_empty ();
3976       GST_LOG_OBJECT (demux, "stream %u has language '%s'", stream->id,
3977           demux->languages[stream->ext_props.lang_idx]);
3978       gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_APPEND,
3979           GST_TAG_LANGUAGE_CODE, demux->languages[stream->ext_props.lang_idx],
3980           NULL);
3981     }
3982   } else if (gst_asf_demux_is_unknown_stream (demux, stream_num)) {
3983     GST_WARNING_OBJECT (demux, "Ext. stream properties for unknown stream");
3984   }
3985
3986   return GST_FLOW_OK;
3987
3988   /* Errors */
3989 not_enough_data:
3990   {
3991     GST_WARNING_OBJECT (demux, "short read parsing ext stream props object!");
3992     return GST_FLOW_OK;         /* not absolutely fatal */
3993   }
3994 expected_stream_object:
3995   {
3996     GST_WARNING_OBJECT (demux, "error parsing extended stream properties "
3997         "object: expected embedded stream object, but got %s object instead!",
3998         gst_asf_get_guid_nick (asf_object_guids, stream_obj.id));
3999     return GST_FLOW_OK;         /* not absolutely fatal */
4000   }
4001 }
4002
4003 static const gchar *
4004 gst_asf_demux_push_obj (GstASFDemux * demux, guint32 obj_id)
4005 {
4006   const gchar *nick;
4007
4008   nick = gst_asf_get_guid_nick (asf_object_guids, obj_id);
4009   if (g_str_has_prefix (nick, "ASF_OBJ_"))
4010     nick += strlen ("ASF_OBJ_");
4011
4012   if (demux->objpath == NULL) {
4013     demux->objpath = g_strdup (nick);
4014   } else {
4015     gchar *newpath;
4016
4017     newpath = g_strdup_printf ("%s/%s", demux->objpath, nick);
4018     g_free (demux->objpath);
4019     demux->objpath = newpath;
4020   }
4021
4022   return (const gchar *) demux->objpath;
4023 }
4024
4025 static void
4026 gst_asf_demux_pop_obj (GstASFDemux * demux)
4027 {
4028   gchar *s;
4029
4030   if ((s = g_strrstr (demux->objpath, "/"))) {
4031     *s = '\0';
4032   } else {
4033     g_free (demux->objpath);
4034     demux->objpath = NULL;
4035   }
4036 }
4037
4038 static void
4039 gst_asf_demux_process_queued_extended_stream_objects (GstASFDemux * demux)
4040 {
4041   GSList *l;
4042   guint i;
4043
4044   /* Parse the queued extended stream property objects and add the info
4045    * to the existing streams or add the new embedded streams, but without
4046    * activating them yet */
4047   GST_LOG_OBJECT (demux, "%u queued extended stream properties objects",
4048       g_slist_length (demux->ext_stream_props));
4049
4050   for (l = demux->ext_stream_props, i = 0; l != NULL; l = l->next, ++i) {
4051     GstBuffer *buf = GST_BUFFER (l->data);
4052     GstMapInfo map;
4053
4054     gst_buffer_map (buf, &map, GST_MAP_READ);
4055
4056     GST_LOG_OBJECT (demux, "parsing ext. stream properties object #%u", i);
4057     gst_asf_demux_process_ext_stream_props (demux, map.data, map.size);
4058     gst_buffer_unmap (buf, &map);
4059     gst_buffer_unref (buf);
4060   }
4061   g_slist_free (demux->ext_stream_props);
4062   demux->ext_stream_props = NULL;
4063 }
4064
4065 #if 0
4066 static void
4067 gst_asf_demux_activate_ext_props_streams (GstASFDemux * demux)
4068 {
4069   guint i, j;
4070
4071   for (i = 0; i < demux->num_streams; ++i) {
4072     AsfStream *stream;
4073     gboolean is_hidden;
4074     GSList *x;
4075
4076     stream = &demux->stream[i];
4077
4078     GST_LOG_OBJECT (demux, "checking  stream %2u", stream->id);
4079
4080     if (stream->active) {
4081       GST_LOG_OBJECT (demux, "stream %2u is already activated", stream->id);
4082       continue;
4083     }
4084
4085     is_hidden = FALSE;
4086     for (x = demux->mut_ex_streams; x != NULL; x = x->next) {
4087       guint8 *mes;
4088
4089       /* check for each mutual exclusion whether it affects this stream */
4090       for (mes = (guint8 *) x->data; mes != NULL && *mes != 0xff; ++mes) {
4091         if (*mes == stream->id) {
4092           /* if yes, check if we've already added streams that are mutually
4093            * exclusive with the stream we're about to add */
4094           for (mes = (guint8 *) x->data; mes != NULL && *mes != 0xff; ++mes) {
4095             for (j = 0; j < demux->num_streams; ++j) {
4096               /* if the broadcast flag is set, assume the hidden streams aren't
4097                * actually streamed and hide them (or playbin won't work right),
4098                * otherwise assume their data is available */
4099               if (demux->stream[j].id == *mes && demux->broadcast) {
4100                 is_hidden = TRUE;
4101                 GST_LOG_OBJECT (demux, "broadcast stream ID %d to be added is "
4102                     "mutually exclusive with already existing stream ID %d, "
4103                     "hiding stream", stream->id, demux->stream[j].id);
4104                 goto next;
4105               }
4106             }
4107           }
4108           break;
4109         }
4110       }
4111     }
4112
4113   next:
4114
4115     /* FIXME: we should do stream activation based on preroll data in
4116      * streaming mode too */
4117     if (demux->streaming && !is_hidden)
4118       gst_asf_demux_activate_stream (demux, stream);
4119   }
4120 }
4121 #endif
4122
4123 static GstFlowReturn
4124 gst_asf_demux_process_object (GstASFDemux * demux, guint8 ** p_data,
4125     guint64 * p_size)
4126 {
4127   GstFlowReturn ret = GST_FLOW_OK;
4128   AsfObject obj;
4129   guint64 obj_data_size;
4130
4131   if (*p_size < ASF_OBJECT_HEADER_SIZE)
4132     return ASF_FLOW_NEED_MORE_DATA;
4133
4134   asf_demux_peek_object (demux, *p_data, ASF_OBJECT_HEADER_SIZE, &obj, TRUE);
4135   gst_asf_demux_skip_bytes (ASF_OBJECT_HEADER_SIZE, p_data, p_size);
4136
4137   obj_data_size = obj.size - ASF_OBJECT_HEADER_SIZE;
4138
4139   if (*p_size < obj_data_size)
4140     return ASF_FLOW_NEED_MORE_DATA;
4141
4142   gst_asf_demux_push_obj (demux, obj.id);
4143
4144   GST_INFO ("%s: size %" G_GUINT64_FORMAT, demux->objpath, obj.size);
4145
4146   switch (obj.id) {
4147     case ASF_OBJ_STREAM:
4148       gst_asf_demux_parse_stream_object (demux, *p_data, obj_data_size);
4149       ret = GST_FLOW_OK;
4150       break;
4151     case ASF_OBJ_FILE:
4152       ret = gst_asf_demux_process_file (demux, *p_data, obj_data_size);
4153       break;
4154     case ASF_OBJ_HEADER:
4155       ret = gst_asf_demux_process_header (demux, *p_data, obj_data_size);
4156       break;
4157     case ASF_OBJ_COMMENT:
4158       ret = gst_asf_demux_process_comment (demux, *p_data, obj_data_size);
4159       break;
4160     case ASF_OBJ_HEAD1:
4161       ret = gst_asf_demux_process_header_ext (demux, *p_data, obj_data_size);
4162       break;
4163     case ASF_OBJ_BITRATE_PROPS:
4164       ret =
4165           gst_asf_demux_process_bitrate_props_object (demux, *p_data,
4166           obj_data_size);
4167       break;
4168     case ASF_OBJ_EXT_CONTENT_DESC:
4169       ret =
4170           gst_asf_demux_process_ext_content_desc (demux, *p_data,
4171           obj_data_size);
4172       break;
4173     case ASF_OBJ_METADATA_OBJECT:
4174       ret = gst_asf_demux_process_metadata (demux, *p_data, obj_data_size);
4175       break;
4176     case ASF_OBJ_EXTENDED_STREAM_PROPS:{
4177       GstBuffer *buf;
4178
4179       /* process these later, we might not have parsed the corresponding
4180        * stream object yet */
4181       GST_LOG ("%s: queued for later parsing", demux->objpath);
4182       buf = gst_buffer_new_and_alloc (obj_data_size);
4183       gst_buffer_fill (buf, 0, *p_data, obj_data_size);
4184       demux->ext_stream_props = g_slist_append (demux->ext_stream_props, buf);
4185       ret = GST_FLOW_OK;
4186       break;
4187     }
4188     case ASF_OBJ_LANGUAGE_LIST:
4189       ret = gst_asf_demux_process_language_list (demux, *p_data, obj_data_size);
4190       break;
4191     case ASF_OBJ_ADVANCED_MUTUAL_EXCLUSION:
4192       ret = gst_asf_demux_process_advanced_mutual_exclusion (demux, *p_data,
4193           obj_data_size);
4194       break;
4195     case ASF_OBJ_SIMPLE_INDEX:
4196       ret = gst_asf_demux_process_simple_index (demux, *p_data, obj_data_size);
4197       break;
4198     case ASF_OBJ_CONTENT_ENCRYPTION:
4199     case ASF_OBJ_EXT_CONTENT_ENCRYPTION:
4200     case ASF_OBJ_DIGITAL_SIGNATURE_OBJECT:
4201     case ASF_OBJ_UNKNOWN_ENCRYPTION_OBJECT:
4202       goto error_encrypted;
4203     case ASF_OBJ_CONCEAL_NONE:
4204     case ASF_OBJ_HEAD2:
4205     case ASF_OBJ_UNDEFINED:
4206     case ASF_OBJ_CODEC_COMMENT:
4207     case ASF_OBJ_INDEX:
4208     case ASF_OBJ_PADDING:
4209     case ASF_OBJ_BITRATE_MUTEX:
4210     case ASF_OBJ_COMPATIBILITY:
4211     case ASF_OBJ_INDEX_PLACEHOLDER:
4212     case ASF_OBJ_INDEX_PARAMETERS:
4213     case ASF_OBJ_STREAM_PRIORITIZATION:
4214     case ASF_OBJ_SCRIPT_COMMAND:
4215     case ASF_OBJ_METADATA_LIBRARY_OBJECT:
4216     default:
4217       /* Unknown/unhandled object, skip it and hope for the best */
4218       GST_INFO ("%s: skipping object", demux->objpath);
4219       ret = GST_FLOW_OK;
4220       break;
4221   }
4222
4223   /* this can't fail, we checked the number of bytes available before */
4224   gst_asf_demux_skip_bytes (obj_data_size, p_data, p_size);
4225
4226   GST_LOG ("%s: ret = %s", demux->objpath, gst_asf_get_flow_name (ret));
4227
4228   gst_asf_demux_pop_obj (demux);
4229
4230   return ret;
4231
4232 /* ERRORS */
4233 error_encrypted:
4234   {
4235     GST_ELEMENT_ERROR (demux, STREAM, DECRYPT, (NULL), (NULL));
4236     return GST_FLOW_ERROR;
4237   }
4238 }
4239
4240 static void
4241 gst_asf_demux_descramble_buffer (GstASFDemux * demux, AsfStream * stream,
4242     GstBuffer ** p_buffer)
4243 {
4244   GstBuffer *descrambled_buffer;
4245   GstBuffer *scrambled_buffer;
4246   GstBuffer *sub_buffer;
4247   guint offset;
4248   guint off;
4249   guint row;
4250   guint col;
4251   guint idx;
4252
4253   /* descrambled_buffer is initialised in the first iteration */
4254   descrambled_buffer = NULL;
4255   scrambled_buffer = *p_buffer;
4256
4257   if (gst_buffer_get_size (scrambled_buffer) <
4258       stream->ds_packet_size * stream->span)
4259     return;
4260
4261   for (offset = 0; offset < gst_buffer_get_size (scrambled_buffer);
4262       offset += stream->ds_chunk_size) {
4263     off = offset / stream->ds_chunk_size;
4264     row = off / stream->span;
4265     col = off % stream->span;
4266     idx = row + col * stream->ds_packet_size / stream->ds_chunk_size;
4267     GST_DEBUG ("idx=%u, row=%u, col=%u, off=%u, ds_chunk_size=%u", idx, row,
4268         col, off, stream->ds_chunk_size);
4269     GST_DEBUG ("scrambled buffer size=%" G_GSIZE_FORMAT
4270         ", span=%u, packet_size=%u", gst_buffer_get_size (scrambled_buffer),
4271         stream->span, stream->ds_packet_size);
4272     GST_DEBUG ("gst_buffer_get_size (scrambled_buffer) = %" G_GSIZE_FORMAT,
4273         gst_buffer_get_size (scrambled_buffer));
4274     sub_buffer =
4275         gst_buffer_copy_region (scrambled_buffer, GST_BUFFER_COPY_MEMORY,
4276         idx * stream->ds_chunk_size, stream->ds_chunk_size);
4277     if (!offset) {
4278       descrambled_buffer = sub_buffer;
4279     } else {
4280       descrambled_buffer = gst_buffer_append (descrambled_buffer, sub_buffer);
4281     }
4282   }
4283
4284   GST_BUFFER_TIMESTAMP (descrambled_buffer) =
4285       GST_BUFFER_TIMESTAMP (scrambled_buffer);
4286   GST_BUFFER_DURATION (descrambled_buffer) =
4287       GST_BUFFER_DURATION (scrambled_buffer);
4288   GST_BUFFER_OFFSET (descrambled_buffer) = GST_BUFFER_OFFSET (scrambled_buffer);
4289   GST_BUFFER_OFFSET_END (descrambled_buffer) =
4290       GST_BUFFER_OFFSET_END (scrambled_buffer);
4291
4292   /* FIXME/CHECK: do we need to transfer buffer flags here too? */
4293
4294   gst_buffer_unref (scrambled_buffer);
4295   *p_buffer = descrambled_buffer;
4296 }
4297
4298 static gboolean
4299 gst_asf_demux_element_send_event (GstElement * element, GstEvent * event)
4300 {
4301   GstASFDemux *demux = GST_ASF_DEMUX (element);
4302   gint i;
4303
4304   GST_DEBUG ("handling element event of type %s", GST_EVENT_TYPE_NAME (event));
4305
4306   for (i = 0; i < demux->num_streams; ++i) {
4307     gst_event_ref (event);
4308     if (gst_asf_demux_handle_src_event (demux->stream[i].pad,
4309             GST_OBJECT_CAST (element), event)) {
4310       gst_event_unref (event);
4311       return TRUE;
4312     }
4313   }
4314
4315   gst_event_unref (event);
4316   return FALSE;
4317 }
4318
4319 /* takes ownership of the passed event */
4320 static gboolean
4321 gst_asf_demux_send_event_unlocked (GstASFDemux * demux, GstEvent * event)
4322 {
4323   gboolean ret = TRUE;
4324   gint i;
4325
4326   GST_DEBUG_OBJECT (demux, "sending %s event to all source pads",
4327       GST_EVENT_TYPE_NAME (event));
4328
4329   for (i = 0; i < demux->num_streams; ++i) {
4330     gst_event_ref (event);
4331     ret &= gst_pad_push_event (demux->stream[i].pad, event);
4332   }
4333   gst_event_unref (event);
4334   return ret;
4335 }
4336
4337 static gboolean
4338 gst_asf_demux_handle_src_query (GstPad * pad, GstObject * parent,
4339     GstQuery * query)
4340 {
4341   GstASFDemux *demux;
4342   gboolean res = FALSE;
4343
4344   demux = GST_ASF_DEMUX (parent);
4345
4346   GST_DEBUG ("handling %s query",
4347       gst_query_type_get_name (GST_QUERY_TYPE (query)));
4348
4349   switch (GST_QUERY_TYPE (query)) {
4350     case GST_QUERY_DURATION:
4351     {
4352       GstFormat format;
4353
4354       gst_query_parse_duration (query, &format, NULL);
4355
4356       if (format != GST_FORMAT_TIME) {
4357         GST_LOG ("only support duration queries in TIME format");
4358         break;
4359       }
4360
4361       res = gst_pad_query_default (pad, parent, query);
4362       if (!res) {
4363         GST_OBJECT_LOCK (demux);
4364
4365         if (demux->segment.duration != GST_CLOCK_TIME_NONE) {
4366           GST_LOG ("returning duration: %" GST_TIME_FORMAT,
4367               GST_TIME_ARGS (demux->segment.duration));
4368
4369           gst_query_set_duration (query, GST_FORMAT_TIME,
4370               demux->segment.duration);
4371
4372           res = TRUE;
4373         } else {
4374           GST_LOG ("duration not known yet");
4375         }
4376
4377         GST_OBJECT_UNLOCK (demux);
4378       }
4379       break;
4380     }
4381
4382     case GST_QUERY_POSITION:{
4383       GstFormat format;
4384
4385       gst_query_parse_position (query, &format, NULL);
4386
4387       if (format != GST_FORMAT_TIME) {
4388         GST_LOG ("only support position queries in TIME format");
4389         break;
4390       }
4391
4392       GST_OBJECT_LOCK (demux);
4393
4394       if (demux->segment.position != GST_CLOCK_TIME_NONE) {
4395         GST_LOG ("returning position: %" GST_TIME_FORMAT,
4396             GST_TIME_ARGS (demux->segment.position));
4397
4398         gst_query_set_position (query, GST_FORMAT_TIME,
4399             demux->segment.position);
4400
4401         res = TRUE;
4402       } else {
4403         GST_LOG ("position not known yet");
4404       }
4405
4406       GST_OBJECT_UNLOCK (demux);
4407       break;
4408     }
4409
4410     case GST_QUERY_SEEKING:{
4411       GstFormat format;
4412
4413       gst_query_parse_seeking (query, &format, NULL, NULL, NULL);
4414       if (format == GST_FORMAT_TIME) {
4415         gint64 duration;
4416
4417         GST_OBJECT_LOCK (demux);
4418         duration = demux->segment.duration;
4419         GST_OBJECT_UNLOCK (demux);
4420
4421         if (!demux->streaming || !demux->seekable) {
4422           gst_query_set_seeking (query, GST_FORMAT_TIME, demux->seekable, 0,
4423               duration);
4424           res = TRUE;
4425         } else {
4426           GstFormat fmt;
4427           gboolean seekable;
4428
4429           /* try upstream first in TIME */
4430           res = gst_pad_query_default (pad, parent, query);
4431
4432           gst_query_parse_seeking (query, &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 no luck, maybe in BYTES */
4436           if (!seekable || fmt != GST_FORMAT_TIME) {
4437             GstQuery *q;
4438
4439             q = gst_query_new_seeking (GST_FORMAT_BYTES);
4440             if ((res = gst_pad_peer_query (demux->sinkpad, q))) {
4441               gst_query_parse_seeking (q, &fmt, &seekable, NULL, NULL);
4442               GST_LOG_OBJECT (demux, "upstream %s seekable %d",
4443                   GST_STR_NULL (gst_format_get_name (fmt)), seekable);
4444               if (fmt != GST_FORMAT_BYTES)
4445                 seekable = FALSE;
4446             }
4447             gst_query_unref (q);
4448             gst_query_set_seeking (query, GST_FORMAT_TIME, seekable, 0,
4449                 duration);
4450             res = TRUE;
4451           }
4452         }
4453       } else
4454         GST_LOG_OBJECT (demux, "only support seeking in TIME format");
4455       break;
4456     }
4457
4458     case GST_QUERY_LATENCY:
4459     {
4460       gboolean live;
4461       GstClockTime min, max;
4462
4463       /* preroll delay does not matter in non-live pipeline,
4464        * but we might end up in a live (rtsp) one ... */
4465
4466       /* first forward */
4467       res = gst_pad_query_default (pad, parent, query);
4468       if (!res)
4469         break;
4470
4471       gst_query_parse_latency (query, &live, &min, &max);
4472
4473       GST_DEBUG_OBJECT (demux, "Peer latency: live %d, min %"
4474           GST_TIME_FORMAT " max %" GST_TIME_FORMAT, live,
4475           GST_TIME_ARGS (min), GST_TIME_ARGS (max));
4476
4477       GST_OBJECT_LOCK (demux);
4478       min += demux->latency;
4479       if (max != -1)
4480         max += demux->latency;
4481       GST_OBJECT_UNLOCK (demux);
4482
4483       gst_query_set_latency (query, live, min, max);
4484       break;
4485     }
4486     case GST_QUERY_SEGMENT:
4487     {
4488       GstFormat format;
4489       gint64 start, stop;
4490
4491       format = demux->segment.format;
4492
4493       start =
4494           gst_segment_to_stream_time (&demux->segment, format,
4495           demux->segment.start);
4496       if ((stop = demux->segment.stop) == -1)
4497         stop = demux->segment.duration;
4498       else
4499         stop = gst_segment_to_stream_time (&demux->segment, format, stop);
4500
4501       gst_query_set_segment (query, demux->segment.rate, format, start, stop);
4502       res = TRUE;
4503       break;
4504     }
4505     default:
4506       res = gst_pad_query_default (pad, parent, query);
4507       break;
4508   }
4509
4510   return res;
4511 }
4512
4513 static GstStateChangeReturn
4514 gst_asf_demux_change_state (GstElement * element, GstStateChange transition)
4515 {
4516   GstASFDemux *demux = GST_ASF_DEMUX (element);
4517   GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
4518
4519   switch (transition) {
4520     case GST_STATE_CHANGE_NULL_TO_READY:{
4521       gst_segment_init (&demux->segment, GST_FORMAT_TIME);
4522       demux->need_newsegment = TRUE;
4523       demux->segment_running = FALSE;
4524       demux->accurate = FALSE;
4525       demux->adapter = gst_adapter_new ();
4526       demux->metadata = gst_caps_new_empty ();
4527       demux->global_metadata = gst_structure_new_empty ("metadata");
4528       demux->data_size = 0;
4529       demux->data_offset = 0;
4530       demux->index_offset = 0;
4531       demux->base_offset = 0;
4532       demux->flowcombiner = gst_flow_combiner_new ();
4533       break;
4534     }
4535     default:
4536       break;
4537   }
4538
4539   ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
4540   if (ret == GST_STATE_CHANGE_FAILURE)
4541     return ret;
4542
4543   switch (transition) {
4544     case GST_STATE_CHANGE_PAUSED_TO_READY:
4545       gst_asf_demux_reset (demux, FALSE);
4546       break;
4547
4548     case GST_STATE_CHANGE_READY_TO_NULL:
4549       gst_asf_demux_reset (demux, FALSE);
4550       gst_flow_combiner_free (demux->flowcombiner);
4551       demux->flowcombiner = NULL;
4552       break;
4553     default:
4554       break;
4555   }
4556
4557   return ret;
4558 }