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