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