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