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