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