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