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