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