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