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