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