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