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