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