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