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