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