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