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