apply cve patch for security weakness
[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->accurate = 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 keyunit_sync, 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   demux->accurate =
667       ((flags & GST_SEEK_FLAG_ACCURATE) == GST_SEEK_FLAG_ACCURATE);
668   keyunit_sync = ((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 && (demux->accurate || (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 (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->accurate) && 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
1599     /* wait until we had a chance to "lock on" some payload's timestamp */
1600     if (G_UNLIKELY (demux->need_newsegment
1601             && !GST_CLOCK_TIME_IS_VALID (demux->segment_ts)))
1602       return GST_FLOW_OK;
1603
1604     payload = &g_array_index (stream->payloads, AsfPayload, 0);
1605
1606     /* do we need to send a newsegment event */
1607     if ((G_UNLIKELY (demux->need_newsegment))) {
1608       GstEvent *segment_event;
1609
1610       /* safe default if insufficient upstream info */
1611       if (!GST_CLOCK_TIME_IS_VALID (demux->in_gap))
1612         demux->in_gap = 0;
1613
1614       if (demux->segment.stop == GST_CLOCK_TIME_NONE &&
1615           demux->segment.duration > 0) {
1616         /* slight HACK; prevent clipping of last bit */
1617         demux->segment.stop = demux->segment.duration + demux->in_gap;
1618       }
1619
1620       /* FIXME : only if ACCURATE ! */
1621       if (G_LIKELY (!demux->accurate
1622               && (GST_CLOCK_TIME_IS_VALID (payload->ts)))) {
1623         GST_DEBUG ("Adjusting newsegment start to %" GST_TIME_FORMAT,
1624             GST_TIME_ARGS (payload->ts));
1625         demux->segment.start = payload->ts;
1626         demux->segment.time = payload->ts;
1627       }
1628
1629       GST_DEBUG_OBJECT (demux, "sending new-segment event %" GST_SEGMENT_FORMAT,
1630           &demux->segment);
1631
1632       /* note: we fix up all timestamps to start from 0, so this should be ok */
1633       segment_event = gst_event_new_segment (&demux->segment);
1634       if (demux->segment_seqnum)
1635         gst_event_set_seqnum (segment_event, demux->segment_seqnum);
1636       gst_asf_demux_send_event_unlocked (demux, segment_event);
1637
1638       /* now post any global tags we may have found */
1639       if (demux->taglist == NULL) {
1640         demux->taglist = gst_tag_list_new_empty ();
1641         gst_tag_list_set_scope (demux->taglist, GST_TAG_SCOPE_GLOBAL);
1642       }
1643
1644       gst_tag_list_add (demux->taglist, GST_TAG_MERGE_REPLACE,
1645           GST_TAG_CONTAINER_FORMAT, "ASF", NULL);
1646
1647       GST_DEBUG_OBJECT (demux, "global tags: %" GST_PTR_FORMAT, demux->taglist);
1648       gst_asf_demux_send_event_unlocked (demux,
1649           gst_event_new_tag (demux->taglist));
1650       demux->taglist = NULL;
1651
1652       demux->need_newsegment = FALSE;
1653       demux->segment_seqnum = 0;
1654       demux->segment_running = TRUE;
1655     }
1656
1657     /* Do we have tags pending for this stream? */
1658     if (G_UNLIKELY (stream->pending_tags)) {
1659       GST_LOG_OBJECT (stream->pad, "%" GST_PTR_FORMAT, stream->pending_tags);
1660       gst_pad_push_event (stream->pad,
1661           gst_event_new_tag (stream->pending_tags));
1662       stream->pending_tags = NULL;
1663     }
1664
1665     /* We have the whole packet now so we should push the packet to
1666      * the src pad now. First though we should check if we need to do
1667      * descrambling */
1668     if (G_UNLIKELY (stream->span > 1)) {
1669       gst_asf_demux_descramble_buffer (demux, stream, &payload->buf);
1670     }
1671
1672     payload->buf = gst_buffer_make_writable (payload->buf);
1673
1674     if (G_LIKELY (!payload->keyframe)) {
1675       GST_BUFFER_FLAG_SET (payload->buf, GST_BUFFER_FLAG_DELTA_UNIT);
1676     }
1677
1678     if (G_UNLIKELY (stream->discont)) {
1679       GST_DEBUG_OBJECT (stream->pad, "marking DISCONT on stream");
1680       GST_BUFFER_FLAG_SET (payload->buf, GST_BUFFER_FLAG_DISCONT);
1681       stream->discont = FALSE;
1682     }
1683
1684     if (G_UNLIKELY (stream->is_video && payload->par_x && payload->par_y &&
1685             (payload->par_x != stream->par_x) &&
1686             (payload->par_y != stream->par_y))) {
1687       GST_DEBUG ("Updating PAR (%d/%d => %d/%d)",
1688           stream->par_x, stream->par_y, payload->par_x, payload->par_y);
1689       stream->par_x = payload->par_x;
1690       stream->par_y = payload->par_y;
1691       stream->caps = gst_caps_make_writable (stream->caps);
1692       gst_caps_set_simple (stream->caps, "pixel-aspect-ratio",
1693           GST_TYPE_FRACTION, stream->par_x, stream->par_y, NULL);
1694       gst_pad_set_caps (stream->pad, stream->caps);
1695     }
1696
1697     if (G_UNLIKELY (stream->interlaced != payload->interlaced)) {
1698       GST_DEBUG ("Updating interlaced status (%d => %d)", stream->interlaced,
1699           payload->interlaced);
1700       stream->interlaced = payload->interlaced;
1701       stream->caps = gst_caps_make_writable (stream->caps);
1702       gst_caps_set_simple (stream->caps, "interlace-mode", G_TYPE_BOOLEAN,
1703           (stream->interlaced ? "mixed" : "progressive"), NULL);
1704       gst_pad_set_caps (stream->pad, stream->caps);
1705     }
1706
1707     /* (sort of) interpolate timestamps using upstream "frame of reference",
1708      * typically useful for live src, but might (unavoidably) mess with
1709      * position reporting if a live src is playing not so live content
1710      * (e.g. rtspsrc taking some time to fall back to tcp) */
1711     GST_BUFFER_PTS (payload->buf) = payload->ts;
1712     if (GST_BUFFER_PTS_IS_VALID (payload->buf)) {
1713       GST_BUFFER_PTS (payload->buf) += demux->in_gap;
1714     }
1715     if (payload->duration == GST_CLOCK_TIME_NONE
1716         && stream->ext_props.avg_time_per_frame != 0)
1717       GST_BUFFER_DURATION (payload->buf) =
1718           stream->ext_props.avg_time_per_frame * 100;
1719     else
1720       GST_BUFFER_DURATION (payload->buf) = payload->duration;
1721
1722     /* FIXME: we should really set durations on buffers if we can */
1723
1724     GST_LOG_OBJECT (stream->pad, "pushing buffer, %" GST_PTR_FORMAT,
1725         payload->buf);
1726
1727     if (stream->active) {
1728       if (G_UNLIKELY (stream->first_buffer)) {
1729         if (stream->streamheader != NULL) {
1730           GST_DEBUG_OBJECT (stream->pad,
1731               "Pushing streamheader before first buffer");
1732           gst_pad_push (stream->pad, gst_buffer_ref (stream->streamheader));
1733         }
1734         stream->first_buffer = FALSE;
1735       }
1736
1737       ret = gst_pad_push (stream->pad, payload->buf);
1738       ret = gst_flow_combiner_update_flow (demux->flowcombiner, ret);
1739     } else {
1740       gst_buffer_unref (payload->buf);
1741       ret = GST_FLOW_OK;
1742     }
1743     payload->buf = NULL;
1744     g_array_remove_index (stream->payloads, 0);
1745
1746     /* Break out as soon as we have an issue */
1747     if (G_UNLIKELY (ret != GST_FLOW_OK))
1748       break;
1749   }
1750
1751   return ret;
1752 }
1753
1754 static gboolean
1755 gst_asf_demux_check_buffer_is_header (GstASFDemux * demux, GstBuffer * buf)
1756 {
1757   AsfObject obj;
1758   GstMapInfo map;
1759   g_assert (buf != NULL);
1760
1761   GST_LOG_OBJECT (demux, "Checking if buffer is a header");
1762
1763   gst_buffer_map (buf, &map, GST_MAP_READ);
1764
1765   /* we return false on buffer too small */
1766   if (map.size < ASF_OBJECT_HEADER_SIZE) {
1767     gst_buffer_unmap (buf, &map);
1768     return FALSE;
1769   }
1770
1771   /* check if it is a header */
1772   asf_demux_peek_object (demux, map.data, ASF_OBJECT_HEADER_SIZE, &obj, TRUE);
1773   gst_buffer_unmap (buf, &map);
1774   if (obj.id == ASF_OBJ_HEADER) {
1775     return TRUE;
1776   }
1777   return FALSE;
1778 }
1779
1780 static gboolean
1781 gst_asf_demux_check_chained_asf (GstASFDemux * demux)
1782 {
1783   guint64 off = demux->data_offset + (demux->packet * demux->packet_size);
1784   GstFlowReturn ret = GST_FLOW_OK;
1785   GstBuffer *buf = NULL;
1786   gboolean header = FALSE;
1787
1788   /* TODO maybe we should skip index objects after the data and look
1789    * further for a new header */
1790   if (gst_asf_demux_pull_data (demux, off, ASF_OBJECT_HEADER_SIZE, &buf, &ret)) {
1791     g_assert (buf != NULL);
1792     /* check if it is a header */
1793     if (gst_asf_demux_check_buffer_is_header (demux, buf)) {
1794       GST_DEBUG_OBJECT (demux, "new base offset: %" G_GUINT64_FORMAT, off);
1795       demux->base_offset = off;
1796       header = TRUE;
1797     }
1798
1799     gst_buffer_unref (buf);
1800   }
1801
1802   return header;
1803 }
1804
1805 static void
1806 gst_asf_demux_loop (GstASFDemux * demux)
1807 {
1808   GstFlowReturn flow = GST_FLOW_OK;
1809   GstBuffer *buf = NULL;
1810   guint64 off;
1811   gboolean sent_eos = FALSE;
1812
1813   if (G_UNLIKELY (demux->state == GST_ASF_DEMUX_STATE_HEADER)) {
1814     if (!gst_asf_demux_pull_headers (demux, &flow)) {
1815       goto pause;
1816     }
1817
1818     gst_asf_demux_pull_indices (demux);
1819   }
1820
1821   g_assert (demux->state == GST_ASF_DEMUX_STATE_DATA);
1822
1823   if (G_UNLIKELY (demux->num_packets != 0
1824           && demux->packet >= demux->num_packets))
1825     goto eos;
1826
1827   GST_LOG_OBJECT (demux, "packet %u/%u", (guint) demux->packet + 1,
1828       (guint) demux->num_packets);
1829
1830   off = demux->data_offset + (demux->packet * demux->packet_size);
1831
1832   if (G_UNLIKELY (!gst_asf_demux_pull_data (demux, off,
1833               demux->packet_size * demux->speed_packets, &buf, &flow))) {
1834     GST_DEBUG_OBJECT (demux, "got flow %s", gst_flow_get_name (flow));
1835     if (flow == GST_FLOW_EOS)
1836       goto eos;
1837     else if (flow == GST_FLOW_FLUSHING) {
1838       GST_DEBUG_OBJECT (demux, "Not fatal");
1839       goto pause;
1840     } else
1841       goto read_failed;
1842   }
1843
1844   if (G_LIKELY (demux->speed_packets == 1)) {
1845     GstAsfDemuxParsePacketError err;
1846     err = gst_asf_demux_parse_packet (demux, buf);
1847     if (G_UNLIKELY (err != GST_ASF_DEMUX_PARSE_PACKET_ERROR_NONE)) {
1848       /* when we don't know when the data object ends, we should check
1849        * for a chained asf */
1850       if (demux->num_packets == 0) {
1851         if (gst_asf_demux_check_buffer_is_header (demux, buf)) {
1852           GST_INFO_OBJECT (demux, "Chained asf found");
1853           demux->base_offset = off;
1854           gst_asf_demux_reset (demux, TRUE);
1855           gst_buffer_unref (buf);
1856           return;
1857         }
1858       }
1859       /* FIXME: We should tally up fatal errors and error out only
1860        * after a few broken packets in a row? */
1861
1862       GST_INFO_OBJECT (demux, "Ignoring recoverable parse error");
1863       gst_buffer_unref (buf);
1864       ++demux->packet;
1865       return;
1866     }
1867
1868     flow = gst_asf_demux_push_complete_payloads (demux, FALSE);
1869
1870     ++demux->packet;
1871
1872   } else {
1873     guint n;
1874     for (n = 0; n < demux->speed_packets; n++) {
1875       GstBuffer *sub;
1876       GstAsfDemuxParsePacketError err;
1877
1878       sub =
1879           gst_buffer_copy_region (buf, GST_BUFFER_COPY_ALL,
1880           n * demux->packet_size, demux->packet_size);
1881       err = gst_asf_demux_parse_packet (demux, sub);
1882       if (G_UNLIKELY (err != GST_ASF_DEMUX_PARSE_PACKET_ERROR_NONE)) {
1883         /* when we don't know when the data object ends, we should check
1884          * for a chained asf */
1885         if (demux->num_packets == 0) {
1886           if (gst_asf_demux_check_buffer_is_header (demux, sub)) {
1887             GST_INFO_OBJECT (demux, "Chained asf found");
1888             demux->base_offset = off + n * demux->packet_size;
1889             gst_asf_demux_reset (demux, TRUE);
1890             gst_buffer_unref (sub);
1891             gst_buffer_unref (buf);
1892             return;
1893           }
1894         }
1895         /* FIXME: We should tally up fatal errors and error out only
1896          * after a few broken packets in a row? */
1897
1898         GST_INFO_OBJECT (demux, "Ignoring recoverable parse error");
1899         flow = GST_FLOW_OK;
1900       }
1901
1902       gst_buffer_unref (sub);
1903
1904       if (err == GST_ASF_DEMUX_PARSE_PACKET_ERROR_NONE)
1905         flow = gst_asf_demux_push_complete_payloads (demux, FALSE);
1906
1907       ++demux->packet;
1908
1909     }
1910
1911     /* reset speed pull */
1912     demux->speed_packets = 1;
1913   }
1914
1915   gst_buffer_unref (buf);
1916
1917   if (G_UNLIKELY (demux->num_packets > 0
1918           && demux->packet >= demux->num_packets)) {
1919     GST_LOG_OBJECT (demux, "reached EOS");
1920     goto eos;
1921   }
1922
1923   if (G_UNLIKELY (flow != GST_FLOW_OK)) {
1924     GST_DEBUG_OBJECT (demux, "pushing complete payloads failed");
1925     goto pause;
1926   }
1927
1928   /* check if we're at the end of the configured segment */
1929   /* FIXME: check if segment end reached etc. */
1930
1931   return;
1932
1933 eos:
1934   {
1935     /* if we haven't activated our streams yet, this might be because we have
1936      * less data queued than required for preroll; force stream activation and
1937      * send any pending payloads before sending EOS */
1938     if (!demux->activated_streams)
1939       gst_asf_demux_push_complete_payloads (demux, TRUE);
1940
1941     /* we want to push an eos or post a segment-done in any case */
1942     if (demux->segment.flags & GST_SEEK_FLAG_SEGMENT) {
1943       gint64 stop;
1944
1945       /* for segment playback we need to post when (in stream time)
1946        * we stopped, this is either stop (when set) or the duration. */
1947       if ((stop = demux->segment.stop) == -1)
1948         stop = demux->segment.duration;
1949
1950       GST_INFO_OBJECT (demux, "Posting segment-done, at end of segment");
1951       gst_element_post_message (GST_ELEMENT_CAST (demux),
1952           gst_message_new_segment_done (GST_OBJECT (demux), GST_FORMAT_TIME,
1953               stop));
1954       gst_asf_demux_send_event_unlocked (demux,
1955           gst_event_new_segment_done (GST_FORMAT_TIME, stop));
1956     } else if (flow != GST_FLOW_EOS) {
1957       /* check if we have a chained asf, in case, we don't eos yet */
1958       if (gst_asf_demux_check_chained_asf (demux)) {
1959         GST_INFO_OBJECT (demux, "Chained ASF starting");
1960         gst_asf_demux_reset (demux, TRUE);
1961         return;
1962       }
1963     }
1964     /* normal playback, send EOS to all linked pads */
1965     GST_INFO_OBJECT (demux, "Sending EOS, at end of stream");
1966     gst_asf_demux_send_event_unlocked (demux, gst_event_new_eos ());
1967     sent_eos = TRUE;
1968     /* ... and fall through to pause */
1969   }
1970 pause:
1971   {
1972     GST_DEBUG_OBJECT (demux, "pausing task, flow return: %s",
1973         gst_flow_get_name (flow));
1974     demux->segment_running = FALSE;
1975     gst_pad_pause_task (demux->sinkpad);
1976
1977     /* For the error cases (not EOS) */
1978     if (!sent_eos) {
1979       if (flow == GST_FLOW_EOS)
1980         gst_asf_demux_send_event_unlocked (demux, gst_event_new_eos ());
1981       else if (flow < GST_FLOW_EOS || flow == GST_FLOW_NOT_LINKED) {
1982         /* Post an error. Hopefully something else already has, but if not... */
1983         GST_ELEMENT_ERROR (demux, STREAM, FAILED,
1984             (_("Internal data stream error.")),
1985             ("streaming stopped, reason %s", gst_flow_get_name (flow)));
1986       }
1987     }
1988     return;
1989   }
1990
1991 /* ERRORS */
1992 read_failed:
1993   {
1994     GST_DEBUG_OBJECT (demux, "Read failed, doh");
1995     gst_asf_demux_send_event_unlocked (demux, gst_event_new_eos ());
1996     flow = GST_FLOW_EOS;
1997     goto pause;
1998   }
1999 #if 0
2000   /* See FIXMEs above */
2001 parse_error:
2002   {
2003     gst_buffer_unref (buf);
2004     GST_ELEMENT_ERROR (demux, STREAM, DEMUX, (NULL),
2005         ("Error parsing ASF packet %u", (guint) demux->packet));
2006     gst_asf_demux_send_event_unlocked (demux, gst_event_new_eos ());
2007     flow = GST_FLOW_ERROR;
2008     goto pause;
2009   }
2010 #endif
2011 }
2012
2013 #define GST_ASF_DEMUX_CHECK_HEADER_YES       0
2014 #define GST_ASF_DEMUX_CHECK_HEADER_NO        1
2015 #define GST_ASF_DEMUX_CHECK_HEADER_NEED_DATA 2
2016
2017 static gint
2018 gst_asf_demux_check_header (GstASFDemux * demux)
2019 {
2020   AsfObject obj;
2021   guint8 *cdata = (guint8 *) gst_adapter_map (demux->adapter,
2022       ASF_OBJECT_HEADER_SIZE);
2023   if (cdata == NULL)            /* need more data */
2024     return GST_ASF_DEMUX_CHECK_HEADER_NEED_DATA;
2025
2026   asf_demux_peek_object (demux, cdata, ASF_OBJECT_HEADER_SIZE, &obj, FALSE);
2027   if (obj.id != ASF_OBJ_HEADER) {
2028     return GST_ASF_DEMUX_CHECK_HEADER_NO;
2029   } else {
2030     return GST_ASF_DEMUX_CHECK_HEADER_YES;
2031   }
2032 }
2033
2034 static GstFlowReturn
2035 gst_asf_demux_chain (GstPad * pad, GstObject * parent, GstBuffer * buf)
2036 {
2037   GstFlowReturn ret = GST_FLOW_OK;
2038   GstASFDemux *demux;
2039
2040   demux = GST_ASF_DEMUX (parent);
2041
2042   GST_LOG_OBJECT (demux,
2043       "buffer: size=%" G_GSIZE_FORMAT ", offset=%" G_GINT64_FORMAT ", time=%"
2044       GST_TIME_FORMAT, gst_buffer_get_size (buf), GST_BUFFER_OFFSET (buf),
2045       GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)));
2046
2047   if (G_UNLIKELY (GST_BUFFER_IS_DISCONT (buf))) {
2048     GST_DEBUG_OBJECT (demux, "received DISCONT");
2049     gst_asf_demux_mark_discont (demux);
2050   }
2051
2052   if (G_UNLIKELY ((!GST_CLOCK_TIME_IS_VALID (demux->in_gap) &&
2053               GST_BUFFER_TIMESTAMP_IS_VALID (buf)))) {
2054     demux->in_gap = GST_BUFFER_TIMESTAMP (buf) - demux->in_segment.start;
2055     GST_DEBUG_OBJECT (demux, "upstream segment start %" GST_TIME_FORMAT
2056         ", interpolation gap: %" GST_TIME_FORMAT,
2057         GST_TIME_ARGS (demux->in_segment.start), GST_TIME_ARGS (demux->in_gap));
2058   }
2059
2060   gst_adapter_push (demux->adapter, buf);
2061
2062   switch (demux->state) {
2063     case GST_ASF_DEMUX_STATE_INDEX:{
2064       gint result = gst_asf_demux_check_header (demux);
2065       if (result == GST_ASF_DEMUX_CHECK_HEADER_NEED_DATA)       /* need more data */
2066         break;
2067
2068       if (result == GST_ASF_DEMUX_CHECK_HEADER_NO) {
2069         /* we don't care about this, probably an index */
2070         /* TODO maybe would be smarter to skip all the indices
2071          * until we got a new header or EOS to decide */
2072         GST_LOG_OBJECT (demux, "Received index object, its EOS");
2073         goto eos;
2074       } else {
2075         GST_INFO_OBJECT (demux, "Chained asf starting");
2076         /* cleanup and get ready for a chained asf */
2077         gst_asf_demux_reset (demux, TRUE);
2078         /* fall through */
2079       }
2080     }
2081     case GST_ASF_DEMUX_STATE_HEADER:{
2082       ret = gst_asf_demux_chain_headers (demux);
2083       if (demux->state != GST_ASF_DEMUX_STATE_DATA)
2084         break;
2085       /* otherwise fall through */
2086     }
2087     case GST_ASF_DEMUX_STATE_DATA:
2088     {
2089       guint64 data_size;
2090
2091       data_size = demux->packet_size;
2092
2093       while (gst_adapter_available (demux->adapter) >= data_size) {
2094         GstBuffer *buf;
2095         GstAsfDemuxParsePacketError err;
2096
2097         /* we don't know the length of the stream
2098          * check for a chained asf everytime */
2099         if (demux->num_packets == 0) {
2100           gint result = gst_asf_demux_check_header (demux);
2101
2102           if (result == GST_ASF_DEMUX_CHECK_HEADER_YES) {
2103             GST_INFO_OBJECT (demux, "Chained asf starting");
2104             /* cleanup and get ready for a chained asf */
2105             gst_asf_demux_reset (demux, TRUE);
2106             break;
2107           }
2108         } else if (G_UNLIKELY (demux->num_packets != 0 && demux->packet >= 0
2109                 && demux->packet >= demux->num_packets)) {
2110           /* do not overshoot data section when streaming */
2111           break;
2112         }
2113
2114         buf = gst_adapter_take_buffer (demux->adapter, data_size);
2115
2116         /* FIXME: We should tally up fatal errors and error out only
2117          * after a few broken packets in a row? */
2118         err = gst_asf_demux_parse_packet (demux, buf);
2119
2120         gst_buffer_unref (buf);
2121
2122         if (G_LIKELY (err == GST_ASF_DEMUX_PARSE_PACKET_ERROR_NONE))
2123           ret = gst_asf_demux_push_complete_payloads (demux, FALSE);
2124         else
2125           GST_WARNING_OBJECT (demux, "Parse error");
2126
2127         if (demux->packet >= 0)
2128           ++demux->packet;
2129       }
2130       if (G_UNLIKELY (demux->num_packets != 0 && demux->packet >= 0
2131               && demux->packet >= demux->num_packets)) {
2132         demux->state = GST_ASF_DEMUX_STATE_INDEX;
2133       }
2134       break;
2135     }
2136     default:
2137       g_assert_not_reached ();
2138   }
2139
2140 done:
2141   if (ret != GST_FLOW_OK)
2142     GST_DEBUG_OBJECT (demux, "flow: %s", gst_flow_get_name (ret));
2143
2144   return ret;
2145
2146 eos:
2147   {
2148     GST_DEBUG_OBJECT (demux, "Handled last packet, setting EOS");
2149     ret = GST_FLOW_EOS;
2150     goto done;
2151   }
2152 }
2153
2154 static inline gboolean
2155 gst_asf_demux_skip_bytes (guint num_bytes, guint8 ** p_data, guint64 * p_size)
2156 {
2157   if (*p_size < num_bytes)
2158     return FALSE;
2159
2160   *p_data += num_bytes;
2161   *p_size -= num_bytes;
2162   return TRUE;
2163 }
2164
2165 static inline guint8
2166 gst_asf_demux_get_uint8 (guint8 ** p_data, guint64 * p_size)
2167 {
2168   guint8 ret;
2169
2170   g_assert (*p_size >= 1);
2171   ret = GST_READ_UINT8 (*p_data);
2172   *p_data += sizeof (guint8);
2173   *p_size -= sizeof (guint8);
2174   return ret;
2175 }
2176
2177 static inline guint16
2178 gst_asf_demux_get_uint16 (guint8 ** p_data, guint64 * p_size)
2179 {
2180   guint16 ret;
2181
2182   g_assert (*p_size >= 2);
2183   ret = GST_READ_UINT16_LE (*p_data);
2184   *p_data += sizeof (guint16);
2185   *p_size -= sizeof (guint16);
2186   return ret;
2187 }
2188
2189 static inline guint32
2190 gst_asf_demux_get_uint32 (guint8 ** p_data, guint64 * p_size)
2191 {
2192   guint32 ret;
2193
2194   g_assert (*p_size >= 4);
2195   ret = GST_READ_UINT32_LE (*p_data);
2196   *p_data += sizeof (guint32);
2197   *p_size -= sizeof (guint32);
2198   return ret;
2199 }
2200
2201 static inline guint64
2202 gst_asf_demux_get_uint64 (guint8 ** p_data, guint64 * p_size)
2203 {
2204   guint64 ret;
2205
2206   g_assert (*p_size >= 8);
2207   ret = GST_READ_UINT64_LE (*p_data);
2208   *p_data += sizeof (guint64);
2209   *p_size -= sizeof (guint64);
2210   return ret;
2211 }
2212
2213 static gboolean
2214 gst_asf_demux_get_buffer (GstBuffer ** p_buf, guint num_bytes_to_read,
2215     guint8 ** p_data, guint64 * p_size)
2216 {
2217   *p_buf = NULL;
2218
2219   if (*p_size < num_bytes_to_read)
2220     return FALSE;
2221
2222   *p_buf = gst_buffer_new_and_alloc (num_bytes_to_read);
2223   gst_buffer_fill (*p_buf, 0, *p_data, num_bytes_to_read);
2224
2225   *p_data += num_bytes_to_read;
2226   *p_size -= num_bytes_to_read;
2227
2228   return TRUE;
2229 }
2230
2231 static gboolean
2232 gst_asf_demux_get_bytes (guint8 ** p_buf, guint num_bytes_to_read,
2233     guint8 ** p_data, guint64 * p_size)
2234 {
2235   *p_buf = NULL;
2236
2237   if (*p_size < num_bytes_to_read)
2238     return FALSE;
2239
2240   *p_buf = g_memdup (*p_data, num_bytes_to_read);
2241   *p_data += num_bytes_to_read;
2242   *p_size -= num_bytes_to_read;
2243   return TRUE;
2244 }
2245
2246 static gboolean
2247 gst_asf_demux_get_string (gchar ** p_str, guint16 * p_strlen,
2248     guint8 ** p_data, guint64 * p_size)
2249 {
2250   guint16 s_length;
2251   guint8 *s;
2252
2253   *p_str = NULL;
2254
2255   if (*p_size < 2)
2256     return FALSE;
2257
2258   s_length = gst_asf_demux_get_uint16 (p_data, p_size);
2259
2260   if (p_strlen)
2261     *p_strlen = s_length;
2262
2263   if (s_length == 0) {
2264     GST_WARNING ("zero-length string");
2265     *p_str = g_strdup ("");
2266     return TRUE;
2267   }
2268
2269   if (!gst_asf_demux_get_bytes (&s, s_length, p_data, p_size))
2270     return FALSE;
2271
2272   g_assert (s != NULL);
2273
2274   /* just because They don't exist doesn't
2275    * mean They are not out to get you ... */
2276   if (s[s_length - 1] != '\0') {
2277     s = g_realloc (s, s_length + 1);
2278     s[s_length] = '\0';
2279   }
2280
2281   *p_str = (gchar *) s;
2282   return TRUE;
2283 }
2284
2285
2286 static void
2287 gst_asf_demux_get_guid (ASFGuid * guid, guint8 ** p_data, guint64 * p_size)
2288 {
2289   g_assert (*p_size >= 4 * sizeof (guint32));
2290
2291   guid->v1 = gst_asf_demux_get_uint32 (p_data, p_size);
2292   guid->v2 = gst_asf_demux_get_uint32 (p_data, p_size);
2293   guid->v3 = gst_asf_demux_get_uint32 (p_data, p_size);
2294   guid->v4 = gst_asf_demux_get_uint32 (p_data, p_size);
2295 }
2296
2297 static gboolean
2298 gst_asf_demux_get_stream_audio (asf_stream_audio * audio, guint8 ** p_data,
2299     guint64 * p_size)
2300 {
2301   if (*p_size < (2 + 2 + 4 + 4 + 2 + 2 + 2))
2302     return FALSE;
2303
2304   /* WAVEFORMATEX Structure */
2305   audio->codec_tag = gst_asf_demux_get_uint16 (p_data, p_size);
2306   audio->channels = gst_asf_demux_get_uint16 (p_data, p_size);
2307   audio->sample_rate = gst_asf_demux_get_uint32 (p_data, p_size);
2308   audio->byte_rate = gst_asf_demux_get_uint32 (p_data, p_size);
2309   audio->block_align = gst_asf_demux_get_uint16 (p_data, p_size);
2310   audio->word_size = gst_asf_demux_get_uint16 (p_data, p_size);
2311   /* Codec specific data size */
2312   audio->size = gst_asf_demux_get_uint16 (p_data, p_size);
2313   return TRUE;
2314 }
2315
2316 static gboolean
2317 gst_asf_demux_get_stream_video (asf_stream_video * video, guint8 ** p_data,
2318     guint64 * p_size)
2319 {
2320   if (*p_size < (4 + 4 + 1 + 2))
2321     return FALSE;
2322
2323   video->width = gst_asf_demux_get_uint32 (p_data, p_size);
2324   video->height = gst_asf_demux_get_uint32 (p_data, p_size);
2325   video->unknown = gst_asf_demux_get_uint8 (p_data, p_size);
2326   video->size = gst_asf_demux_get_uint16 (p_data, p_size);
2327   return TRUE;
2328 }
2329
2330 static gboolean
2331 gst_asf_demux_get_stream_video_format (asf_stream_video_format * fmt,
2332     guint8 ** p_data, guint64 * p_size)
2333 {
2334   if (*p_size < (4 + 4 + 4 + 2 + 2 + 4 + 4 + 4 + 4 + 4 + 4))
2335     return FALSE;
2336
2337   fmt->size = gst_asf_demux_get_uint32 (p_data, p_size);
2338   fmt->width = gst_asf_demux_get_uint32 (p_data, p_size);
2339   fmt->height = gst_asf_demux_get_uint32 (p_data, p_size);
2340   fmt->planes = gst_asf_demux_get_uint16 (p_data, p_size);
2341   fmt->depth = gst_asf_demux_get_uint16 (p_data, p_size);
2342   fmt->tag = gst_asf_demux_get_uint32 (p_data, p_size);
2343   fmt->image_size = gst_asf_demux_get_uint32 (p_data, p_size);
2344   fmt->xpels_meter = gst_asf_demux_get_uint32 (p_data, p_size);
2345   fmt->ypels_meter = gst_asf_demux_get_uint32 (p_data, p_size);
2346   fmt->num_colors = gst_asf_demux_get_uint32 (p_data, p_size);
2347   fmt->imp_colors = gst_asf_demux_get_uint32 (p_data, p_size);
2348   return TRUE;
2349 }
2350
2351 AsfStream *
2352 gst_asf_demux_get_stream (GstASFDemux * demux, guint16 id)
2353 {
2354   guint i;
2355
2356   for (i = 0; i < demux->num_streams; i++) {
2357     if (demux->stream[i].id == id)
2358       return &demux->stream[i];
2359   }
2360
2361   if (gst_asf_demux_is_unknown_stream (demux, id))
2362     GST_WARNING ("Segment found for undefined stream: (%d)", id);
2363   return NULL;
2364 }
2365
2366 static AsfStream *
2367 gst_asf_demux_setup_pad (GstASFDemux * demux, GstPad * src_pad,
2368     GstCaps * caps, guint16 id, gboolean is_video, GstBuffer * streamheader,
2369     GstTagList * tags)
2370 {
2371   AsfStream *stream;
2372
2373   gst_pad_use_fixed_caps (src_pad);
2374   gst_pad_set_caps (src_pad, caps);
2375
2376   gst_pad_set_event_function (src_pad,
2377       GST_DEBUG_FUNCPTR (gst_asf_demux_handle_src_event));
2378   gst_pad_set_query_function (src_pad,
2379       GST_DEBUG_FUNCPTR (gst_asf_demux_handle_src_query));
2380
2381   stream = &demux->stream[demux->num_streams];
2382   stream->caps = caps;
2383   stream->pad = src_pad;
2384   stream->id = id;
2385   stream->fps_known = !is_video;        /* bit hacky for audio */
2386   stream->is_video = is_video;
2387   stream->pending_tags = tags;
2388   stream->discont = TRUE;
2389   stream->first_buffer = TRUE;
2390   stream->streamheader = streamheader;
2391   if (stream->streamheader) {
2392     stream->streamheader = gst_buffer_make_writable (streamheader);
2393     GST_BUFFER_FLAG_SET (stream->streamheader, GST_BUFFER_FLAG_HEADER);
2394   }
2395   if (is_video) {
2396     GstStructure *st;
2397     gint par_x, par_y;
2398     st = gst_caps_get_structure (caps, 0);
2399     if (gst_structure_get_fraction (st, "pixel-aspect-ratio", &par_x, &par_y) &&
2400         par_x > 0 && par_y > 0) {
2401       GST_DEBUG ("PAR %d/%d", par_x, par_y);
2402       stream->par_x = par_x;
2403       stream->par_y = par_y;
2404     }
2405   }
2406
2407   stream->payloads = g_array_new (FALSE, FALSE, sizeof (AsfPayload));
2408
2409   GST_INFO ("Created pad %s for stream %u with caps %" GST_PTR_FORMAT,
2410       GST_PAD_NAME (src_pad), demux->num_streams, caps);
2411
2412   ++demux->num_streams;
2413
2414   stream->active = FALSE;
2415
2416   return stream;
2417 }
2418
2419 static void
2420 gst_asf_demux_add_stream_headers_to_caps (GstASFDemux * demux,
2421     GstBuffer * buffer, GstStructure * structure)
2422 {
2423   GValue arr_val = G_VALUE_INIT;
2424   GValue buf_val = G_VALUE_INIT;
2425
2426   g_value_init (&arr_val, GST_TYPE_ARRAY);
2427   g_value_init (&buf_val, GST_TYPE_BUFFER);
2428
2429   gst_value_set_buffer (&buf_val, buffer);
2430   gst_value_array_append_and_take_value (&arr_val, &buf_val);
2431
2432   gst_structure_take_value (structure, "streamheader", &arr_val);
2433 }
2434
2435 static AsfStream *
2436 gst_asf_demux_add_audio_stream (GstASFDemux * demux,
2437     asf_stream_audio * audio, guint16 id, guint8 ** p_data, guint64 * p_size)
2438 {
2439   GstTagList *tags = NULL;
2440   GstBuffer *extradata = NULL;
2441   GstPad *src_pad;
2442   GstCaps *caps;
2443   guint16 size_left = 0;
2444   gchar *codec_name = NULL;
2445   gchar *name = NULL;
2446
2447   size_left = audio->size;
2448
2449   /* Create the audio pad */
2450   name = g_strdup_printf ("audio_%u", demux->num_audio_streams);
2451
2452   src_pad = gst_pad_new_from_static_template (&audio_src_template, name);
2453   g_free (name);
2454
2455   /* Swallow up any left over data and set up the 
2456    * standard properties from the header info */
2457   if (size_left) {
2458     GST_INFO_OBJECT (demux, "Audio header contains %d bytes of "
2459         "codec specific data", size_left);
2460
2461     g_assert (size_left <= *p_size);
2462     gst_asf_demux_get_buffer (&extradata, size_left, p_data, p_size);
2463   }
2464
2465   /* asf_stream_audio is the same as gst_riff_strf_auds, but with an
2466    * additional two bytes indicating extradata. */
2467   /* FIXME: Handle the channel reorder map here */
2468   caps = gst_riff_create_audio_caps (audio->codec_tag, NULL,
2469       (gst_riff_strf_auds *) audio, extradata, NULL, &codec_name, NULL);
2470
2471   if (caps == NULL) {
2472     caps = gst_caps_new_simple ("audio/x-asf-unknown", "codec_id",
2473         G_TYPE_INT, (gint) audio->codec_tag, NULL);
2474   }
2475
2476   /* Informing about that audio format we just added */
2477   if (codec_name) {
2478     tags = gst_tag_list_new (GST_TAG_AUDIO_CODEC, codec_name, NULL);
2479     g_free (codec_name);
2480   }
2481
2482   if (extradata)
2483     gst_buffer_unref (extradata);
2484
2485   GST_INFO ("Adding audio stream #%u, id %u codec %u (0x%04x), tags=%"
2486       GST_PTR_FORMAT, demux->num_audio_streams, id, audio->codec_tag,
2487       audio->codec_tag, tags);
2488
2489   ++demux->num_audio_streams;
2490
2491   return gst_asf_demux_setup_pad (demux, src_pad, caps, id, FALSE, NULL, tags);
2492 }
2493
2494 static AsfStream *
2495 gst_asf_demux_add_video_stream (GstASFDemux * demux,
2496     asf_stream_video_format * video, guint16 id,
2497     guint8 ** p_data, guint64 * p_size)
2498 {
2499   GstTagList *tags = NULL;
2500   GstStructure *caps_s;
2501   GstBuffer *extradata = NULL;
2502   GstPad *src_pad;
2503   GstCaps *caps;
2504   gchar *str;
2505   gchar *name = NULL;
2506   gchar *codec_name = NULL;
2507   gint size_left = video->size - 40;
2508   GstBuffer *streamheader = NULL;
2509   guint par_w = 1, par_h = 1;
2510
2511   /* Create the video pad */
2512   name = g_strdup_printf ("video_%u", demux->num_video_streams);
2513   src_pad = gst_pad_new_from_static_template (&video_src_template, name);
2514   g_free (name);
2515
2516   /* Now try some gstreamer formatted MIME types (from gst_avi_demux_strf_vids) */
2517   if (size_left) {
2518     GST_LOG ("Video header has %d bytes of codec specific data", size_left);
2519     g_assert (size_left <= *p_size);
2520     gst_asf_demux_get_buffer (&extradata, size_left, p_data, p_size);
2521   }
2522
2523   GST_DEBUG ("video codec %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (video->tag));
2524
2525   /* yes, asf_stream_video_format and gst_riff_strf_vids are the same */
2526   caps = gst_riff_create_video_caps (video->tag, NULL,
2527       (gst_riff_strf_vids *) video, extradata, NULL, &codec_name);
2528
2529   if (caps == NULL) {
2530     caps = gst_caps_new_simple ("video/x-asf-unknown", "fourcc",
2531         G_TYPE_UINT, video->tag, NULL);
2532   } else {
2533     GstStructure *s;
2534     gint ax, ay;
2535
2536     s = gst_asf_demux_get_metadata_for_stream (demux, id);
2537     if (gst_structure_get_int (s, "AspectRatioX", &ax) &&
2538         gst_structure_get_int (s, "AspectRatioY", &ay) && (ax > 0 && ay > 0)) {
2539       par_w = ax;
2540       par_h = ay;
2541       gst_caps_set_simple (caps, "pixel-aspect-ratio", GST_TYPE_FRACTION,
2542           ax, ay, NULL);
2543     } else {
2544       guint ax, ay;
2545       /* retry with the global metadata */
2546       GST_DEBUG ("Retrying with global metadata %" GST_PTR_FORMAT,
2547           demux->global_metadata);
2548       s = demux->global_metadata;
2549       if (gst_structure_get_uint (s, "AspectRatioX", &ax) &&
2550           gst_structure_get_uint (s, "AspectRatioY", &ay)) {
2551         GST_DEBUG ("ax:%d, ay:%d", ax, ay);
2552         if (ax > 0 && ay > 0) {
2553           par_w = ax;
2554           par_h = ay;
2555           gst_caps_set_simple (caps, "pixel-aspect-ratio", GST_TYPE_FRACTION,
2556               ax, ay, NULL);
2557         }
2558       }
2559     }
2560     s = gst_caps_get_structure (caps, 0);
2561     gst_structure_remove_field (s, "framerate");
2562   }
2563
2564   caps_s = gst_caps_get_structure (caps, 0);
2565
2566   /* add format field with fourcc to WMV/VC1 caps to differentiate variants */
2567   if (gst_structure_has_name (caps_s, "video/x-wmv")) {
2568     str = g_strdup_printf ("%" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (video->tag));
2569     gst_caps_set_simple (caps, "format", G_TYPE_STRING, str, NULL);
2570     g_free (str);
2571
2572     /* check if h264 has codec_data (avc) or streamheaders (bytestream) */
2573   } else if (gst_structure_has_name (caps_s, "video/x-h264")) {
2574     const GValue *value = gst_structure_get_value (caps_s, "codec_data");
2575     if (value) {
2576       GstBuffer *buf = gst_value_get_buffer (value);
2577       GstMapInfo mapinfo;
2578
2579       if (gst_buffer_map (buf, &mapinfo, GST_MAP_READ)) {
2580         if (mapinfo.size >= 4 && GST_READ_UINT32_BE (mapinfo.data) == 1) {
2581           /* this looks like a bytestream start */
2582           streamheader = gst_buffer_ref (buf);
2583           gst_asf_demux_add_stream_headers_to_caps (demux, buf, caps_s);
2584           gst_structure_remove_field (caps_s, "codec_data");
2585         }
2586
2587         gst_buffer_unmap (buf, &mapinfo);
2588       }
2589     }
2590   }
2591
2592   /* For a 3D video, set multiview information into the caps based on
2593    * what was detected during object parsing */
2594   if (demux->asf_3D_mode != GST_ASF_3D_NONE) {
2595     GstVideoMultiviewMode mv_mode = GST_VIDEO_MULTIVIEW_MODE_NONE;
2596     GstVideoMultiviewFlags mv_flags = GST_VIDEO_MULTIVIEW_FLAGS_NONE;
2597     const gchar *mview_mode_str;
2598
2599     switch (demux->asf_3D_mode) {
2600       case GST_ASF_3D_SIDE_BY_SIDE_HALF_LR:
2601         mv_mode = GST_VIDEO_MULTIVIEW_MODE_SIDE_BY_SIDE;
2602         break;
2603       case GST_ASF_3D_SIDE_BY_SIDE_HALF_RL:
2604         mv_mode = GST_VIDEO_MULTIVIEW_MODE_SIDE_BY_SIDE;
2605         mv_flags = GST_VIDEO_MULTIVIEW_FLAGS_RIGHT_VIEW_FIRST;
2606         break;
2607       case GST_ASF_3D_TOP_AND_BOTTOM_HALF_LR:
2608         mv_mode = GST_VIDEO_MULTIVIEW_MODE_TOP_BOTTOM;
2609         break;
2610       case GST_ASF_3D_TOP_AND_BOTTOM_HALF_RL:
2611         mv_mode = GST_VIDEO_MULTIVIEW_MODE_TOP_BOTTOM;
2612         mv_flags = GST_VIDEO_MULTIVIEW_FLAGS_RIGHT_VIEW_FIRST;
2613         break;
2614       case GST_ASF_3D_DUAL_STREAM:{
2615         gboolean is_right_view = FALSE;
2616         /* if Advanced_Mutual_Exclusion object exists, use it
2617          * to figure out which is the left view (lower ID) */
2618         if (demux->mut_ex_streams != NULL) {
2619           guint length;
2620           gint i;
2621
2622           length = g_slist_length (demux->mut_ex_streams);
2623
2624           for (i = 0; i < length; i++) {
2625             gpointer v_s_id;
2626
2627             v_s_id = g_slist_nth_data (demux->mut_ex_streams, i);
2628
2629             GST_DEBUG_OBJECT (demux,
2630                 "has Mutual_Exclusion object. stream id in object is %d",
2631                 GPOINTER_TO_INT (v_s_id));
2632
2633             if (id > GPOINTER_TO_INT (v_s_id))
2634               is_right_view = TRUE;
2635           }
2636         } else {
2637           /* if the Advaced_Mutual_Exclusion object doesn't exist, assume the
2638            * first video stream encountered has the lower ID */
2639           if (demux->num_video_streams > 0) {
2640             /* This is not the first video stream, assuming right eye view */
2641             is_right_view = TRUE;
2642           }
2643         }
2644         if (is_right_view)
2645           mv_mode = GST_VIDEO_MULTIVIEW_MODE_RIGHT;
2646         else
2647           mv_mode = GST_VIDEO_MULTIVIEW_MODE_LEFT;
2648         break;
2649       }
2650       default:
2651         break;
2652     }
2653
2654     GST_INFO_OBJECT (demux,
2655         "stream_id %d, has multiview-mode %d flags 0x%x", id, mv_mode,
2656         (guint) mv_flags);
2657
2658     mview_mode_str = gst_video_multiview_mode_to_caps_string (mv_mode);
2659     if (mview_mode_str != NULL) {
2660       if (gst_video_multiview_guess_half_aspect (mv_mode, video->width,
2661               video->height, par_w, par_h))
2662         mv_flags |= GST_VIDEO_MULTIVIEW_FLAGS_HALF_ASPECT;
2663
2664       gst_caps_set_simple (caps,
2665           "multiview-mode", G_TYPE_STRING, mview_mode_str,
2666           "multiview-flags", GST_TYPE_VIDEO_MULTIVIEW_FLAGSET, mv_flags,
2667           GST_FLAG_SET_MASK_EXACT, NULL);
2668     }
2669   }
2670
2671   if (codec_name) {
2672     tags = gst_tag_list_new (GST_TAG_VIDEO_CODEC, codec_name, NULL);
2673     g_free (codec_name);
2674   }
2675
2676   if (extradata)
2677     gst_buffer_unref (extradata);
2678
2679   GST_INFO ("Adding video stream #%u, id %u, codec %"
2680       GST_FOURCC_FORMAT " (0x%08x)", demux->num_video_streams, id,
2681       GST_FOURCC_ARGS (video->tag), video->tag);
2682
2683   ++demux->num_video_streams;
2684
2685   return gst_asf_demux_setup_pad (demux, src_pad, caps, id, TRUE,
2686       streamheader, tags);
2687 }
2688
2689 static void
2690 gst_asf_demux_activate_stream (GstASFDemux * demux, AsfStream * stream)
2691 {
2692   if (!stream->active) {
2693     GstEvent *event;
2694     gchar *stream_id;
2695
2696     GST_INFO_OBJECT (demux, "Activating stream %2u, pad %s, caps %"
2697         GST_PTR_FORMAT, stream->id, GST_PAD_NAME (stream->pad), stream->caps);
2698     gst_pad_set_active (stream->pad, TRUE);
2699
2700     stream_id =
2701         gst_pad_create_stream_id_printf (stream->pad, GST_ELEMENT_CAST (demux),
2702         "%03u", stream->id);
2703
2704     event =
2705         gst_pad_get_sticky_event (demux->sinkpad, GST_EVENT_STREAM_START, 0);
2706     if (event) {
2707       if (gst_event_parse_group_id (event, &demux->group_id))
2708         demux->have_group_id = TRUE;
2709       else
2710         demux->have_group_id = FALSE;
2711       gst_event_unref (event);
2712     } else if (!demux->have_group_id) {
2713       demux->have_group_id = TRUE;
2714       demux->group_id = gst_util_group_id_next ();
2715     }
2716
2717     event = gst_event_new_stream_start (stream_id);
2718     if (demux->have_group_id)
2719       gst_event_set_group_id (event, demux->group_id);
2720
2721     gst_pad_push_event (stream->pad, event);
2722     g_free (stream_id);
2723     gst_pad_set_caps (stream->pad, stream->caps);
2724
2725     gst_element_add_pad (GST_ELEMENT_CAST (demux), stream->pad);
2726     gst_flow_combiner_add_pad (demux->flowcombiner, stream->pad);
2727     stream->active = TRUE;
2728   }
2729 }
2730
2731 static AsfStream *
2732 gst_asf_demux_parse_stream_object (GstASFDemux * demux, guint8 * data,
2733     guint64 size)
2734 {
2735   AsfCorrectionType correction_type;
2736   AsfStreamType stream_type;
2737   GstClockTime time_offset;
2738   gboolean is_encrypted G_GNUC_UNUSED;
2739   guint16 stream_id;
2740   guint16 flags;
2741   ASFGuid guid;
2742   guint stream_specific_size;
2743   guint type_specific_size G_GNUC_UNUSED;
2744   guint unknown G_GNUC_UNUSED;
2745   gboolean inspect_payload = FALSE;
2746   AsfStream *stream = NULL;
2747
2748   /* Get the rest of the header's header */
2749   if (size < (16 + 16 + 8 + 4 + 4 + 2 + 4))
2750     goto not_enough_data;
2751
2752   gst_asf_demux_get_guid (&guid, &data, &size);
2753   stream_type = gst_asf_demux_identify_guid (asf_stream_guids, &guid);
2754
2755   gst_asf_demux_get_guid (&guid, &data, &size);
2756   correction_type = gst_asf_demux_identify_guid (asf_correction_guids, &guid);
2757
2758   time_offset = gst_asf_demux_get_uint64 (&data, &size) * 100;
2759
2760   type_specific_size = gst_asf_demux_get_uint32 (&data, &size);
2761   stream_specific_size = gst_asf_demux_get_uint32 (&data, &size);
2762
2763   flags = gst_asf_demux_get_uint16 (&data, &size);
2764   stream_id = flags & 0x7f;
2765   is_encrypted = ! !((flags & 0x8000) << 15);
2766   unknown = gst_asf_demux_get_uint32 (&data, &size);
2767
2768   GST_DEBUG_OBJECT (demux, "Found stream %u, time_offset=%" GST_TIME_FORMAT,
2769       stream_id, GST_TIME_ARGS (time_offset));
2770
2771   /* dvr-ms has audio stream declared in stream specific data */
2772   if (stream_type == ASF_STREAM_EXT_EMBED_HEADER) {
2773     AsfExtStreamType ext_stream_type;
2774     gst_asf_demux_get_guid (&guid, &data, &size);
2775     ext_stream_type = gst_asf_demux_identify_guid (asf_ext_stream_guids, &guid);
2776
2777     if (ext_stream_type == ASF_EXT_STREAM_AUDIO) {
2778       inspect_payload = TRUE;
2779
2780       gst_asf_demux_get_guid (&guid, &data, &size);
2781       gst_asf_demux_get_uint32 (&data, &size);
2782       gst_asf_demux_get_uint32 (&data, &size);
2783       gst_asf_demux_get_uint32 (&data, &size);
2784       gst_asf_demux_get_guid (&guid, &data, &size);
2785       gst_asf_demux_get_uint32 (&data, &size);
2786       stream_type = ASF_STREAM_AUDIO;
2787     }
2788   }
2789
2790   switch (stream_type) {
2791     case ASF_STREAM_AUDIO:{
2792       asf_stream_audio audio_object;
2793
2794       if (!gst_asf_demux_get_stream_audio (&audio_object, &data, &size))
2795         goto not_enough_data;
2796
2797       GST_INFO ("Object is an audio stream with %u bytes of additional data",
2798           audio_object.size);
2799
2800       stream = gst_asf_demux_add_audio_stream (demux, &audio_object, stream_id,
2801           &data, &size);
2802
2803       switch (correction_type) {
2804         case ASF_CORRECTION_ON:{
2805           guint span, packet_size, chunk_size, data_size, silence_data;
2806
2807           GST_INFO ("Using error correction");
2808
2809           if (size < (1 + 2 + 2 + 2 + 1))
2810             goto not_enough_data;
2811
2812           span = gst_asf_demux_get_uint8 (&data, &size);
2813           packet_size = gst_asf_demux_get_uint16 (&data, &size);
2814           chunk_size = gst_asf_demux_get_uint16 (&data, &size);
2815           data_size = gst_asf_demux_get_uint16 (&data, &size);
2816           silence_data = gst_asf_demux_get_uint8 (&data, &size);
2817
2818           stream->span = span;
2819
2820           GST_DEBUG_OBJECT (demux, "Descrambling ps:%u cs:%u ds:%u s:%u sd:%u",
2821               packet_size, chunk_size, data_size, span, silence_data);
2822
2823           if (stream->span > 1) {
2824             if (chunk_size == 0 || ((packet_size / chunk_size) <= 1)) {
2825               /* Disable descrambling */
2826               stream->span = 0;
2827             } else {
2828               /* FIXME: this else branch was added for
2829                * weird_al_yankovic - the saga begins.asf */
2830               stream->ds_packet_size = packet_size;
2831               stream->ds_chunk_size = chunk_size;
2832             }
2833           } else {
2834             /* Descambling is enabled */
2835             stream->ds_packet_size = packet_size;
2836             stream->ds_chunk_size = chunk_size;
2837           }
2838 #if 0
2839           /* Now skip the rest of the silence data */
2840           if (data_size > 1)
2841             gst_bytestream_flush (demux->bs, data_size - 1);
2842 #else
2843           /* FIXME: CHECKME. And why -1? */
2844           if (data_size > 1) {
2845             if (!gst_asf_demux_skip_bytes (data_size - 1, &data, &size)) {
2846               goto not_enough_data;
2847             }
2848           }
2849 #endif
2850           break;
2851         }
2852         case ASF_CORRECTION_OFF:{
2853           GST_INFO ("Error correction off");
2854           if (!gst_asf_demux_skip_bytes (stream_specific_size, &data, &size))
2855             goto not_enough_data;
2856           break;
2857         }
2858         default:
2859           GST_ELEMENT_ERROR (demux, STREAM, DEMUX, (NULL),
2860               ("Audio stream using unknown error correction"));
2861           return NULL;
2862       }
2863
2864       break;
2865     }
2866
2867     case ASF_STREAM_VIDEO:{
2868       asf_stream_video_format video_format_object;
2869       asf_stream_video video_object;
2870       guint16 vsize;
2871
2872       if (!gst_asf_demux_get_stream_video (&video_object, &data, &size))
2873         goto not_enough_data;
2874
2875       vsize = video_object.size - 40;   /* Byte order gets offset by single byte */
2876
2877       GST_INFO ("object is a video stream with %u bytes of "
2878           "additional data", vsize);
2879
2880       if (!gst_asf_demux_get_stream_video_format (&video_format_object,
2881               &data, &size)) {
2882         goto not_enough_data;
2883       }
2884
2885       stream = gst_asf_demux_add_video_stream (demux, &video_format_object,
2886           stream_id, &data, &size);
2887
2888       break;
2889     }
2890
2891     default:
2892       GST_WARNING_OBJECT (demux, "Unknown stream type for stream %u",
2893           stream_id);
2894       demux->other_streams =
2895           g_slist_append (demux->other_streams, GINT_TO_POINTER (stream_id));
2896       break;
2897   }
2898
2899   if (stream)
2900     stream->inspect_payload = inspect_payload;
2901   return stream;
2902
2903 not_enough_data:
2904   {
2905     GST_WARNING_OBJECT (demux, "Unexpected end of data parsing stream object");
2906     /* we'll error out later if we found no streams */
2907     return NULL;
2908   }
2909 }
2910
2911 static const gchar *
2912 gst_asf_demux_get_gst_tag_from_tag_name (const gchar * name_utf8)
2913 {
2914   const struct
2915   {
2916     const gchar *asf_name;
2917     const gchar *gst_name;
2918   } tags[] = {
2919     {
2920     "WM/Genre", GST_TAG_GENRE}, {
2921     "WM/AlbumTitle", GST_TAG_ALBUM}, {
2922     "WM/AlbumArtist", GST_TAG_ARTIST}, {
2923     "WM/Picture", GST_TAG_IMAGE}, {
2924     "WM/Track", GST_TAG_TRACK_NUMBER}, {
2925     "WM/TrackNumber", GST_TAG_TRACK_NUMBER}, {
2926     "WM/Year", GST_TAG_DATE_TIME}
2927     /* { "WM/Composer", GST_TAG_COMPOSER } */
2928   };
2929   gsize out;
2930   guint i;
2931
2932   if (name_utf8 == NULL) {
2933     GST_WARNING ("Failed to convert name to UTF8, skipping");
2934     return NULL;
2935   }
2936
2937   out = strlen (name_utf8);
2938
2939   for (i = 0; i < G_N_ELEMENTS (tags); ++i) {
2940     if (strncmp (tags[i].asf_name, name_utf8, out) == 0) {
2941       GST_LOG ("map tagname '%s' -> '%s'", name_utf8, tags[i].gst_name);
2942       return tags[i].gst_name;
2943     }
2944   }
2945
2946   return NULL;
2947 }
2948
2949 /* gst_asf_demux_add_global_tags() takes ownership of taglist! */
2950 static void
2951 gst_asf_demux_add_global_tags (GstASFDemux * demux, GstTagList * taglist)
2952 {
2953   GstTagList *t;
2954
2955   GST_DEBUG_OBJECT (demux, "adding global tags: %" GST_PTR_FORMAT, taglist);
2956
2957   if (taglist == NULL)
2958     return;
2959
2960   if (gst_tag_list_is_empty (taglist)) {
2961     gst_tag_list_unref (taglist);
2962     return;
2963   }
2964
2965   t = gst_tag_list_merge (demux->taglist, taglist, GST_TAG_MERGE_APPEND);
2966   gst_tag_list_set_scope (t, GST_TAG_SCOPE_GLOBAL);
2967   if (demux->taglist)
2968     gst_tag_list_unref (demux->taglist);
2969   gst_tag_list_unref (taglist);
2970   demux->taglist = t;
2971   GST_LOG_OBJECT (demux, "global tags now: %" GST_PTR_FORMAT, demux->taglist);
2972 }
2973
2974 #define ASF_DEMUX_DATA_TYPE_UTF16LE_STRING  0
2975 #define ASF_DEMUX_DATA_TYPE_BYTE_ARRAY      1
2976 #define ASF_DEMUX_DATA_TYPE_BOOL                        2
2977 #define ASF_DEMUX_DATA_TYPE_DWORD           3
2978
2979 static void
2980 asf_demux_parse_picture_tag (GstTagList * tags, const guint8 * tag_data,
2981     guint tag_data_len)
2982 {
2983   GstByteReader r;
2984   const guint8 *img_data = NULL;
2985   guint32 img_data_len = 0;
2986   guint8 pic_type = 0;
2987
2988   gst_byte_reader_init (&r, tag_data, tag_data_len);
2989
2990   /* skip mime type string (we don't trust it and do our own typefinding),
2991    * and also skip the description string, since we don't use it */
2992   if (!gst_byte_reader_get_uint8 (&r, &pic_type) ||
2993       !gst_byte_reader_get_uint32_le (&r, &img_data_len) ||
2994       !gst_byte_reader_skip_string_utf16 (&r) ||
2995       !gst_byte_reader_skip_string_utf16 (&r) ||
2996       !gst_byte_reader_get_data (&r, img_data_len, &img_data)) {
2997     goto not_enough_data;
2998   }
2999
3000
3001   if (!gst_tag_list_add_id3_image (tags, img_data, img_data_len, pic_type))
3002     GST_DEBUG ("failed to add image extracted from WM/Picture tag to taglist");
3003
3004   return;
3005
3006 not_enough_data:
3007   {
3008     GST_DEBUG ("Failed to read WM/Picture tag: not enough data");
3009     GST_MEMDUMP ("WM/Picture data", tag_data, tag_data_len);
3010     return;
3011   }
3012 }
3013
3014 /* Extended Content Description Object */
3015 static GstFlowReturn
3016 gst_asf_demux_process_ext_content_desc (GstASFDemux * demux, guint8 * data,
3017     guint64 size)
3018 {
3019   /* Other known (and unused) 'text/unicode' metadata available :
3020    *
3021    *   WM/Lyrics =
3022    *   WM/MediaPrimaryClassID = {D1607DBC-E323-4BE2-86A1-48A42A28441E}
3023    *   WMFSDKVersion = 9.00.00.2980
3024    *   WMFSDKNeeded = 0.0.0.0000
3025    *   WM/UniqueFileIdentifier = AMGa_id=R    15334;AMGp_id=P     5149;AMGt_id=T  2324984
3026    *   WM/Publisher = 4AD
3027    *   WM/Provider = AMG
3028    *   WM/ProviderRating = 8
3029    *   WM/ProviderStyle = Rock (similar to WM/Genre)
3030    *   WM/GenreID (similar to WM/Genre)
3031    *   WM/TrackNumber (same as WM/Track but as a string)
3032    *
3033    * Other known (and unused) 'non-text' metadata available :
3034    *
3035    *   WM/EncodingTime
3036    *   WM/MCDI
3037    *   IsVBR
3038    *
3039    * We might want to read WM/TrackNumber and use atoi() if we don't have
3040    * WM/Track
3041    */
3042
3043   GstTagList *taglist;
3044   guint16 blockcount, i;
3045   gboolean content3D = FALSE;
3046
3047   struct
3048   {
3049     const gchar *interleave_name;
3050     GstASF3DMode interleaving_type;
3051   } stereoscopic_layout_map[] = {
3052     {
3053     "SideBySideRF", GST_ASF_3D_SIDE_BY_SIDE_HALF_RL}, {
3054     "SideBySideLF", GST_ASF_3D_SIDE_BY_SIDE_HALF_LR}, {
3055     "OverUnderRT", GST_ASF_3D_TOP_AND_BOTTOM_HALF_RL}, {
3056     "OverUnderLT", GST_ASF_3D_TOP_AND_BOTTOM_HALF_LR}, {
3057     "DualStream", GST_ASF_3D_DUAL_STREAM}
3058   };
3059   GST_INFO_OBJECT (demux, "object is an extended content description");
3060
3061   taglist = gst_tag_list_new_empty ();
3062
3063   /* Content Descriptor Count */
3064   if (size < 2)
3065     goto not_enough_data;
3066
3067   blockcount = gst_asf_demux_get_uint16 (&data, &size);
3068
3069   for (i = 1; i <= blockcount; ++i) {
3070     const gchar *gst_tag_name;
3071     guint16 datatype;
3072     guint16 value_len;
3073     guint16 name_len;
3074     GValue tag_value = { 0, };
3075     gsize in, out;
3076     gchar *name;
3077     gchar *name_utf8 = NULL;
3078     gchar *value;
3079
3080     /* Descriptor */
3081     if (!gst_asf_demux_get_string (&name, &name_len, &data, &size))
3082       goto not_enough_data;
3083
3084     if (size < 2) {
3085       g_free (name);
3086       goto not_enough_data;
3087     }
3088     /* Descriptor Value Data Type */
3089     datatype = gst_asf_demux_get_uint16 (&data, &size);
3090
3091     /* Descriptor Value (not really a string, but same thing reading-wise) */
3092     if (!gst_asf_demux_get_string (&value, &value_len, &data, &size)) {
3093       g_free (name);
3094       goto not_enough_data;
3095     }
3096
3097     name_utf8 =
3098         g_convert (name, name_len, "UTF-8", "UTF-16LE", &in, &out, NULL);
3099
3100     if (name_utf8 != NULL) {
3101       GST_DEBUG ("Found tag/metadata %s", name_utf8);
3102
3103       gst_tag_name = gst_asf_demux_get_gst_tag_from_tag_name (name_utf8);
3104       GST_DEBUG ("gst_tag_name %s", GST_STR_NULL (gst_tag_name));
3105
3106       switch (datatype) {
3107         case ASF_DEMUX_DATA_TYPE_UTF16LE_STRING:{
3108           gchar *value_utf8;
3109
3110           value_utf8 = g_convert (value, value_len, "UTF-8", "UTF-16LE",
3111               &in, &out, NULL);
3112
3113           /* get rid of tags with empty value */
3114           if (value_utf8 != NULL && *value_utf8 != '\0') {
3115             GST_DEBUG ("string value %s", value_utf8);
3116
3117             value_utf8[out] = '\0';
3118
3119             if (gst_tag_name != NULL) {
3120               if (strcmp (gst_tag_name, GST_TAG_DATE_TIME) == 0) {
3121                 guint year = atoi (value_utf8);
3122
3123                 if (year > 0) {
3124                   g_value_init (&tag_value, GST_TYPE_DATE_TIME);
3125                   g_value_take_boxed (&tag_value, gst_date_time_new_y (year));
3126                 }
3127               } else if (strcmp (gst_tag_name, GST_TAG_GENRE) == 0) {
3128                 guint id3v1_genre_id;
3129                 const gchar *genre_str;
3130
3131                 if (sscanf (value_utf8, "(%u)", &id3v1_genre_id) == 1 &&
3132                     ((genre_str = gst_tag_id3_genre_get (id3v1_genre_id)))) {
3133                   GST_DEBUG ("Genre: %s -> %s", value_utf8, genre_str);
3134                   g_free (value_utf8);
3135                   value_utf8 = g_strdup (genre_str);
3136                 }
3137               } else {
3138                 GType tag_type;
3139
3140                 /* convert tag from string to other type if required */
3141                 tag_type = gst_tag_get_type (gst_tag_name);
3142                 g_value_init (&tag_value, tag_type);
3143                 if (!gst_value_deserialize (&tag_value, value_utf8)) {
3144                   GValue from_val = { 0, };
3145
3146                   g_value_init (&from_val, G_TYPE_STRING);
3147                   g_value_set_string (&from_val, value_utf8);
3148                   if (!g_value_transform (&from_val, &tag_value)) {
3149                     GST_WARNING_OBJECT (demux,
3150                         "Could not transform string tag to " "%s tag type %s",
3151                         gst_tag_name, g_type_name (tag_type));
3152                     g_value_unset (&tag_value);
3153                   }
3154                   g_value_unset (&from_val);
3155                 }
3156               }
3157             } else {
3158               /* metadata ! */
3159               GST_DEBUG ("Setting metadata");
3160               g_value_init (&tag_value, G_TYPE_STRING);
3161               g_value_set_string (&tag_value, value_utf8);
3162               /* If we found a stereoscopic marker, look for StereoscopicLayout
3163                * metadata */
3164               if (content3D) {
3165                 guint i;
3166                 if (strncmp ("StereoscopicLayout", name_utf8,
3167                         strlen (name_utf8)) == 0) {
3168                   for (i = 0; i < G_N_ELEMENTS (stereoscopic_layout_map); i++) {
3169                     if (g_str_equal (stereoscopic_layout_map[i].interleave_name,
3170                             value_utf8)) {
3171                       demux->asf_3D_mode =
3172                           stereoscopic_layout_map[i].interleaving_type;
3173                       GST_INFO ("find interleave type %u", demux->asf_3D_mode);
3174                     }
3175                   }
3176                 }
3177                 GST_INFO_OBJECT (demux, "3d type is %u", demux->asf_3D_mode);
3178               } else {
3179                 demux->asf_3D_mode = GST_ASF_3D_NONE;
3180                 GST_INFO_OBJECT (demux, "None 3d type");
3181               }
3182             }
3183           } else if (value_utf8 == NULL) {
3184             GST_WARNING ("Failed to convert string value to UTF8, skipping");
3185           } else {
3186             GST_DEBUG ("Skipping empty string value for %s",
3187                 GST_STR_NULL (gst_tag_name));
3188           }
3189           g_free (value_utf8);
3190           break;
3191         }
3192         case ASF_DEMUX_DATA_TYPE_BYTE_ARRAY:{
3193           if (gst_tag_name) {
3194             if (!g_str_equal (gst_tag_name, GST_TAG_IMAGE)) {
3195               GST_FIXME ("Unhandled byte array tag %s",
3196                   GST_STR_NULL (gst_tag_name));
3197               break;
3198             } else {
3199               asf_demux_parse_picture_tag (taglist, (guint8 *) value,
3200                   value_len);
3201             }
3202           }
3203           break;
3204         }
3205         case ASF_DEMUX_DATA_TYPE_DWORD:{
3206           guint uint_val;
3207
3208           if (value_len < 4)
3209             break;
3210
3211           uint_val = GST_READ_UINT32_LE (value);
3212
3213           /* this is the track number */
3214           g_value_init (&tag_value, G_TYPE_UINT);
3215
3216           /* WM/Track counts from 0 */
3217           if (!strcmp (name_utf8, "WM/Track"))
3218             ++uint_val;
3219
3220           g_value_set_uint (&tag_value, uint_val);
3221           break;
3222         }
3223           /* Detect 3D */
3224         case ASF_DEMUX_DATA_TYPE_BOOL:{
3225           gboolean bool_val;
3226
3227           if (value_len < 4)
3228             break;
3229
3230           bool_val = GST_READ_UINT32_LE (value);
3231
3232           if (strncmp ("Stereoscopic", name_utf8, strlen (name_utf8)) == 0) {
3233             if (bool_val) {
3234               GST_INFO_OBJECT (demux, "This is 3D contents");
3235               content3D = TRUE;
3236             } else {
3237               GST_INFO_OBJECT (demux, "This is not 3D contenst");
3238               content3D = FALSE;
3239             }
3240           }
3241
3242           break;
3243         }
3244         default:{
3245           GST_DEBUG ("Skipping tag %s of type %d", gst_tag_name, datatype);
3246           break;
3247         }
3248       }
3249
3250       if (G_IS_VALUE (&tag_value)) {
3251         if (gst_tag_name) {
3252           GstTagMergeMode merge_mode = GST_TAG_MERGE_APPEND;
3253
3254           /* WM/TrackNumber is more reliable than WM/Track, since the latter
3255            * is supposed to have a 0 base but is often wrongly written to start
3256            * from 1 as well, so prefer WM/TrackNumber when we have it: either
3257            * replace the value added earlier from WM/Track or put it first in
3258            * the list, so that it will get picked up by _get_uint() */
3259           if (strcmp (name_utf8, "WM/TrackNumber") == 0)
3260             merge_mode = GST_TAG_MERGE_REPLACE;
3261
3262           gst_tag_list_add_values (taglist, merge_mode, gst_tag_name,
3263               &tag_value, NULL);
3264         } else {
3265           GST_DEBUG ("Setting global metadata %s", name_utf8);
3266           gst_structure_set_value (demux->global_metadata, name_utf8,
3267               &tag_value);
3268         }
3269
3270         g_value_unset (&tag_value);
3271       }
3272     }
3273
3274     g_free (name);
3275     g_free (value);
3276     g_free (name_utf8);
3277   }
3278
3279   gst_asf_demux_add_global_tags (demux, taglist);
3280
3281   return GST_FLOW_OK;
3282
3283   /* Errors */
3284 not_enough_data:
3285   {
3286     GST_WARNING ("Unexpected end of data parsing ext content desc object");
3287     gst_tag_list_unref (taglist);
3288     return GST_FLOW_OK;         /* not really fatal */
3289   }
3290 }
3291
3292 static GstStructure *
3293 gst_asf_demux_get_metadata_for_stream (GstASFDemux * demux, guint stream_num)
3294 {
3295   gchar sname[32];
3296   guint i;
3297
3298   g_snprintf (sname, sizeof (sname), "stream-%u", stream_num);
3299
3300   for (i = 0; i < gst_caps_get_size (demux->metadata); ++i) {
3301     GstStructure *s;
3302
3303     s = gst_caps_get_structure (demux->metadata, i);
3304     if (gst_structure_has_name (s, sname))
3305       return s;
3306   }
3307
3308   gst_caps_append_structure (demux->metadata, gst_structure_new_empty (sname));
3309
3310   /* try lookup again; demux->metadata took ownership of the structure, so we
3311    * can't really make any assumptions about what happened to it, so we can't
3312    * just return it directly after appending it */
3313   return gst_asf_demux_get_metadata_for_stream (demux, stream_num);
3314 }
3315
3316 static GstFlowReturn
3317 gst_asf_demux_process_metadata (GstASFDemux * demux, guint8 * data,
3318     guint64 size)
3319 {
3320   guint16 blockcount, i;
3321
3322   GST_INFO_OBJECT (demux, "object is a metadata object");
3323
3324   /* Content Descriptor Count */
3325   if (size < 2)
3326     goto not_enough_data;
3327
3328   blockcount = gst_asf_demux_get_uint16 (&data, &size);
3329
3330   for (i = 0; i < blockcount; ++i) {
3331     GstStructure *s;
3332     guint16 stream_num, name_len, data_type, lang_idx G_GNUC_UNUSED;
3333     guint32 data_len, ival;
3334     gchar *name_utf8;
3335
3336     if (size < (2 + 2 + 2 + 2 + 4))
3337       goto not_enough_data;
3338
3339     lang_idx = gst_asf_demux_get_uint16 (&data, &size);
3340     stream_num = gst_asf_demux_get_uint16 (&data, &size);
3341     name_len = gst_asf_demux_get_uint16 (&data, &size);
3342     data_type = gst_asf_demux_get_uint16 (&data, &size);
3343     data_len = gst_asf_demux_get_uint32 (&data, &size);
3344
3345     if (size < name_len + data_len)
3346       goto not_enough_data;
3347
3348     /* convert name to UTF-8 */
3349     name_utf8 = g_convert ((gchar *) data, name_len, "UTF-8", "UTF-16LE",
3350         NULL, NULL, NULL);
3351     gst_asf_demux_skip_bytes (name_len, &data, &size);
3352
3353     if (name_utf8 == NULL) {
3354       GST_WARNING ("Failed to convert value name to UTF8, skipping");
3355       gst_asf_demux_skip_bytes (data_len, &data, &size);
3356       continue;
3357     }
3358
3359     if (data_type != ASF_DEMUX_DATA_TYPE_DWORD) {
3360       gst_asf_demux_skip_bytes (data_len, &data, &size);
3361       g_free (name_utf8);
3362       continue;
3363     }
3364
3365     /* read DWORD */
3366     if (size < 4) {
3367       g_free (name_utf8);
3368       goto not_enough_data;
3369     }
3370
3371     ival = gst_asf_demux_get_uint32 (&data, &size);
3372
3373     /* skip anything else there may be, just in case */
3374     gst_asf_demux_skip_bytes (data_len - 4, &data, &size);
3375
3376     s = gst_asf_demux_get_metadata_for_stream (demux, stream_num);
3377     gst_structure_set (s, name_utf8, G_TYPE_INT, ival, NULL);
3378     g_free (name_utf8);
3379   }
3380
3381   GST_INFO_OBJECT (demux, "metadata = %" GST_PTR_FORMAT, demux->metadata);
3382   return GST_FLOW_OK;
3383
3384   /* Errors */
3385 not_enough_data:
3386   {
3387     GST_WARNING ("Unexpected end of data parsing metadata object");
3388     return GST_FLOW_OK;         /* not really fatal */
3389   }
3390 }
3391
3392 static GstFlowReturn
3393 gst_asf_demux_process_header (GstASFDemux * demux, guint8 * data, guint64 size)
3394 {
3395   GstFlowReturn ret = GST_FLOW_OK;
3396   guint32 i, num_objects;
3397   guint8 unknown G_GNUC_UNUSED;
3398
3399   /* Get the rest of the header's header */
3400   if (size < (4 + 1 + 1))
3401     goto not_enough_data;
3402
3403   num_objects = gst_asf_demux_get_uint32 (&data, &size);
3404   unknown = gst_asf_demux_get_uint8 (&data, &size);
3405   unknown = gst_asf_demux_get_uint8 (&data, &size);
3406
3407   GST_INFO_OBJECT (demux, "object is a header with %u parts", num_objects);
3408
3409   /* Loop through the header's objects, processing those */
3410   for (i = 0; i < num_objects; ++i) {
3411     GST_INFO_OBJECT (demux, "reading header part %u", i);
3412     ret = gst_asf_demux_process_object (demux, &data, &size);
3413     if (ret != GST_FLOW_OK) {
3414       GST_WARNING ("process_object returned %s", gst_asf_get_flow_name (ret));
3415       break;
3416     }
3417   }
3418
3419   return ret;
3420
3421 not_enough_data:
3422   {
3423     GST_ELEMENT_ERROR (demux, STREAM, DEMUX, (NULL),
3424         ("short read parsing HEADER object"));
3425     return GST_FLOW_ERROR;
3426   }
3427 }
3428
3429 static GstFlowReturn
3430 gst_asf_demux_process_file (GstASFDemux * demux, guint8 * data, guint64 size)
3431 {
3432   guint64 creation_time G_GNUC_UNUSED;
3433   guint64 file_size G_GNUC_UNUSED;
3434   guint64 send_time G_GNUC_UNUSED;
3435   guint64 packets_count, play_time, preroll;
3436   guint32 flags, min_pktsize, max_pktsize, min_bitrate G_GNUC_UNUSED;
3437
3438   if (size < (16 + 8 + 8 + 8 + 8 + 8 + 8 + 4 + 4 + 4 + 4))
3439     goto not_enough_data;
3440
3441   gst_asf_demux_skip_bytes (16, &data, &size);  /* skip GUID */
3442   file_size = gst_asf_demux_get_uint64 (&data, &size);
3443   creation_time = gst_asf_demux_get_uint64 (&data, &size);
3444   packets_count = gst_asf_demux_get_uint64 (&data, &size);
3445   play_time = gst_asf_demux_get_uint64 (&data, &size);
3446   send_time = gst_asf_demux_get_uint64 (&data, &size);
3447   preroll = gst_asf_demux_get_uint64 (&data, &size);
3448   flags = gst_asf_demux_get_uint32 (&data, &size);
3449   min_pktsize = gst_asf_demux_get_uint32 (&data, &size);
3450   max_pktsize = gst_asf_demux_get_uint32 (&data, &size);
3451   min_bitrate = gst_asf_demux_get_uint32 (&data, &size);
3452
3453   demux->broadcast = ! !(flags & 0x01);
3454   demux->seekable = ! !(flags & 0x02);
3455
3456   GST_DEBUG_OBJECT (demux, "min_pktsize = %u", min_pktsize);
3457   GST_DEBUG_OBJECT (demux, "flags::broadcast = %d", demux->broadcast);
3458   GST_DEBUG_OBJECT (demux, "flags::seekable  = %d", demux->seekable);
3459
3460   if (demux->broadcast) {
3461     /* these fields are invalid if the broadcast flag is set */
3462     play_time = 0;
3463     file_size = 0;
3464   }
3465
3466   if (min_pktsize != max_pktsize)
3467     goto non_fixed_packet_size;
3468
3469   demux->packet_size = max_pktsize;
3470
3471   /* FIXME: do we need send_time as well? what is it? */
3472   if ((play_time * 100) >= (preroll * GST_MSECOND))
3473     demux->play_time = (play_time * 100) - (preroll * GST_MSECOND);
3474   else
3475     demux->play_time = 0;
3476
3477   demux->preroll = preroll * GST_MSECOND;
3478
3479   /* initial latency */
3480   demux->latency = demux->preroll;
3481
3482   if (demux->play_time == 0)
3483     demux->seekable = FALSE;
3484
3485   GST_DEBUG_OBJECT (demux, "play_time %" GST_TIME_FORMAT,
3486       GST_TIME_ARGS (demux->play_time));
3487   GST_DEBUG_OBJECT (demux, "preroll   %" GST_TIME_FORMAT,
3488       GST_TIME_ARGS (demux->preroll));
3489
3490   if (demux->play_time > 0) {
3491     demux->segment.duration = demux->play_time;
3492   }
3493
3494   GST_INFO ("object is a file with %" G_GUINT64_FORMAT " data packets",
3495       packets_count);
3496   GST_INFO ("preroll = %" G_GUINT64_FORMAT, demux->preroll);
3497
3498   return GST_FLOW_OK;
3499
3500 /* ERRORS */
3501 non_fixed_packet_size:
3502   {
3503     GST_ELEMENT_ERROR (demux, STREAM, DEMUX, (NULL),
3504         ("packet size must be fixed"));
3505     return GST_FLOW_ERROR;
3506   }
3507 not_enough_data:
3508   {
3509     GST_ELEMENT_ERROR (demux, STREAM, DEMUX, (NULL),
3510         ("short read parsing FILE object"));
3511     return GST_FLOW_ERROR;
3512   }
3513 }
3514
3515 /* Content Description Object */
3516 static GstFlowReturn
3517 gst_asf_demux_process_comment (GstASFDemux * demux, guint8 * data, guint64 size)
3518 {
3519   struct
3520   {
3521     const gchar *gst_tag;
3522     guint16 val_length;
3523     gchar *val_utf8;
3524   } tags[5] = {
3525     {
3526     GST_TAG_TITLE, 0, NULL}, {
3527     GST_TAG_ARTIST, 0, NULL}, {
3528     GST_TAG_COPYRIGHT, 0, NULL}, {
3529     GST_TAG_DESCRIPTION, 0, NULL}, {
3530     GST_TAG_COMMENT, 0, NULL}
3531   };
3532   GstTagList *taglist;
3533   GValue value = { 0 };
3534   gsize in, out;
3535   gint i = -1;
3536
3537   GST_INFO_OBJECT (demux, "object is a comment");
3538
3539   if (size < (2 + 2 + 2 + 2 + 2))
3540     goto not_enough_data;
3541
3542   tags[0].val_length = gst_asf_demux_get_uint16 (&data, &size);
3543   tags[1].val_length = gst_asf_demux_get_uint16 (&data, &size);
3544   tags[2].val_length = gst_asf_demux_get_uint16 (&data, &size);
3545   tags[3].val_length = gst_asf_demux_get_uint16 (&data, &size);
3546   tags[4].val_length = gst_asf_demux_get_uint16 (&data, &size);
3547
3548   GST_DEBUG_OBJECT (demux, "Comment lengths: title=%d author=%d copyright=%d "
3549       "description=%d rating=%d", tags[0].val_length, tags[1].val_length,
3550       tags[2].val_length, tags[3].val_length, tags[4].val_length);
3551
3552   for (i = 0; i < G_N_ELEMENTS (tags); ++i) {
3553     if (size < tags[i].val_length)
3554       goto not_enough_data;
3555
3556     /* might be just '/0', '/0'... */
3557     if (tags[i].val_length > 2 && tags[i].val_length % 2 == 0) {
3558       /* convert to UTF-8 */
3559       tags[i].val_utf8 = g_convert ((gchar *) data, tags[i].val_length,
3560           "UTF-8", "UTF-16LE", &in, &out, NULL);
3561     }
3562     gst_asf_demux_skip_bytes (tags[i].val_length, &data, &size);
3563   }
3564
3565   /* parse metadata into taglist */
3566   taglist = gst_tag_list_new_empty ();
3567   g_value_init (&value, G_TYPE_STRING);
3568   for (i = 0; i < G_N_ELEMENTS (tags); ++i) {
3569     if (tags[i].val_utf8 && strlen (tags[i].val_utf8) > 0 && tags[i].gst_tag) {
3570       g_value_set_string (&value, tags[i].val_utf8);
3571       gst_tag_list_add_values (taglist, GST_TAG_MERGE_APPEND,
3572           tags[i].gst_tag, &value, NULL);
3573     }
3574   }
3575   g_value_unset (&value);
3576
3577   gst_asf_demux_add_global_tags (demux, taglist);
3578
3579   for (i = 0; i < G_N_ELEMENTS (tags); ++i)
3580     g_free (tags[i].val_utf8);
3581
3582   return GST_FLOW_OK;
3583
3584 not_enough_data:
3585   {
3586     GST_WARNING_OBJECT (demux, "unexpectedly short of data while processing "
3587         "comment tag section %d, skipping comment object", i);
3588     for (i = 0; i < G_N_ELEMENTS (tags); i++)
3589       g_free (tags[i].val_utf8);
3590     return GST_FLOW_OK;         /* not really fatal */
3591   }
3592 }
3593
3594 static GstFlowReturn
3595 gst_asf_demux_process_bitrate_props_object (GstASFDemux * demux, guint8 * data,
3596     guint64 size)
3597 {
3598   guint16 num_streams, i;
3599   AsfStream *stream;
3600
3601   if (size < 2)
3602     goto not_enough_data;
3603
3604   num_streams = gst_asf_demux_get_uint16 (&data, &size);
3605
3606   GST_INFO ("object is a bitrate properties object with %u streams",
3607       num_streams);
3608
3609   if (size < (num_streams * (2 + 4)))
3610     goto not_enough_data;
3611
3612   for (i = 0; i < num_streams; ++i) {
3613     guint32 bitrate;
3614     guint16 stream_id;
3615
3616     stream_id = gst_asf_demux_get_uint16 (&data, &size);
3617     bitrate = gst_asf_demux_get_uint32 (&data, &size);
3618
3619     if (stream_id < GST_ASF_DEMUX_NUM_STREAM_IDS) {
3620       GST_DEBUG_OBJECT (demux, "bitrate of stream %u = %u", stream_id, bitrate);
3621       stream = gst_asf_demux_get_stream (demux, stream_id);
3622       if (stream) {
3623         if (stream->pending_tags == NULL) {
3624           stream->pending_tags =
3625               gst_tag_list_new (GST_TAG_BITRATE, bitrate, NULL);
3626         }
3627       } else {
3628         GST_WARNING_OBJECT (demux, "Stream id %u wasn't found", stream_id);
3629       }
3630     } else {
3631       GST_WARNING ("stream id %u is too large", stream_id);
3632     }
3633   }
3634
3635   return GST_FLOW_OK;
3636
3637 not_enough_data:
3638   {
3639     GST_WARNING_OBJECT (demux, "short read parsing bitrate props object!");
3640     return GST_FLOW_OK;         /* not really fatal */
3641   }
3642 }
3643
3644 static GstFlowReturn
3645 gst_asf_demux_process_header_ext (GstASFDemux * demux, guint8 * data,
3646     guint64 size)
3647 {
3648   GstFlowReturn ret = GST_FLOW_OK;
3649   guint64 hdr_size;
3650
3651   /* Get the rest of the header's header */
3652   if (size < (16 + 2 + 4))
3653     goto not_enough_data;
3654
3655   /* skip GUID and two other bytes */
3656   gst_asf_demux_skip_bytes (16 + 2, &data, &size);
3657   hdr_size = gst_asf_demux_get_uint32 (&data, &size);
3658
3659   GST_INFO ("extended header object with a size of %u bytes", (guint) size);
3660
3661   /* FIXME: does data_size include the rest of the header that we have read? */
3662   if (hdr_size > size)
3663     goto not_enough_data;
3664
3665   while (hdr_size > 0) {
3666     ret = gst_asf_demux_process_object (demux, &data, &hdr_size);
3667     if (ret != GST_FLOW_OK)
3668       break;
3669   }
3670
3671   return ret;
3672
3673 not_enough_data:
3674   {
3675     GST_ELEMENT_ERROR (demux, STREAM, DEMUX, (NULL),
3676         ("short read parsing extended header object"));
3677     return GST_FLOW_ERROR;
3678   }
3679 }
3680
3681 static GstFlowReturn
3682 gst_asf_demux_process_language_list (GstASFDemux * demux, guint8 * data,
3683     guint64 size)
3684 {
3685   guint i;
3686
3687   if (size < 2)
3688     goto not_enough_data;
3689
3690   if (demux->languages) {
3691     GST_WARNING ("More than one LANGUAGE_LIST object in stream");
3692     g_strfreev (demux->languages);
3693     demux->languages = NULL;
3694     demux->num_languages = 0;
3695   }
3696
3697   demux->num_languages = gst_asf_demux_get_uint16 (&data, &size);
3698   GST_LOG ("%u languages:", demux->num_languages);
3699
3700   demux->languages = g_new0 (gchar *, demux->num_languages + 1);
3701   for (i = 0; i < demux->num_languages; ++i) {
3702     guint8 len, *lang_data = NULL;
3703
3704     if (size < 1)
3705       goto not_enough_data;
3706     len = gst_asf_demux_get_uint8 (&data, &size);
3707     if (gst_asf_demux_get_bytes (&lang_data, len, &data, &size)) {
3708       gchar *utf8;
3709
3710       utf8 = g_convert ((gchar *) lang_data, len, "UTF-8", "UTF-16LE", NULL,
3711           NULL, NULL);
3712
3713       /* truncate "en-us" etc. to just "en" */
3714       if (utf8 && strlen (utf8) >= 5 && (utf8[2] == '-' || utf8[2] == '_')) {
3715         utf8[2] = '\0';
3716       }
3717       GST_DEBUG ("[%u] %s", i, GST_STR_NULL (utf8));
3718       demux->languages[i] = utf8;
3719       g_free (lang_data);
3720     } else {
3721       goto not_enough_data;
3722     }
3723   }
3724
3725   return GST_FLOW_OK;
3726
3727 not_enough_data:
3728   {
3729     GST_WARNING_OBJECT (demux, "short read parsing language list object!");
3730     g_free (demux->languages);
3731     demux->languages = NULL;
3732     return GST_FLOW_OK;         /* not fatal */
3733   }
3734 }
3735
3736 static GstFlowReturn
3737 gst_asf_demux_process_simple_index (GstASFDemux * demux, guint8 * data,
3738     guint64 size)
3739 {
3740   GstClockTime interval;
3741   guint32 count, i;
3742
3743   if (size < (16 + 8 + 4 + 4))
3744     goto not_enough_data;
3745
3746   /* skip file id */
3747   gst_asf_demux_skip_bytes (16, &data, &size);
3748   interval = gst_asf_demux_get_uint64 (&data, &size) * (GstClockTime) 100;
3749   gst_asf_demux_skip_bytes (4, &data, &size);
3750   count = gst_asf_demux_get_uint32 (&data, &size);
3751   if (count > 0) {
3752     demux->sidx_interval = interval;
3753     demux->sidx_num_entries = count;
3754     g_free (demux->sidx_entries);
3755     demux->sidx_entries = g_new0 (AsfSimpleIndexEntry, count);
3756
3757     for (i = 0; i < count; ++i) {
3758       if (G_UNLIKELY (size < 6)) {
3759         /* adjust for broken files, to avoid having entries at the end
3760          * of the parsed index that point to time=0. Resulting in seeking to
3761          * the end of the file leading back to the beginning */
3762         demux->sidx_num_entries -= (count - i);
3763         break;
3764       }
3765       demux->sidx_entries[i].packet = gst_asf_demux_get_uint32 (&data, &size);
3766       demux->sidx_entries[i].count = gst_asf_demux_get_uint16 (&data, &size);
3767       GST_LOG_OBJECT (demux, "%" GST_TIME_FORMAT " = packet %4u  count : %2d",
3768           GST_TIME_ARGS (i * interval), demux->sidx_entries[i].packet,
3769           demux->sidx_entries[i].count);
3770     }
3771   } else {
3772     GST_DEBUG_OBJECT (demux, "simple index object with 0 entries");
3773   }
3774
3775   return GST_FLOW_OK;
3776
3777 not_enough_data:
3778   {
3779     GST_WARNING_OBJECT (demux, "short read parsing simple index object!");
3780     return GST_FLOW_OK;         /* not fatal */
3781   }
3782 }
3783
3784 static GstFlowReturn
3785 gst_asf_demux_process_advanced_mutual_exclusion (GstASFDemux * demux,
3786     guint8 * data, guint64 size)
3787 {
3788   ASFGuid guid;
3789   guint16 num, i;
3790
3791   if (size < 16 + 2 + (2 * 2))
3792     goto not_enough_data;
3793
3794   gst_asf_demux_get_guid (&guid, &data, &size);
3795   num = gst_asf_demux_get_uint16 (&data, &size);
3796
3797   if (num < 2) {
3798     GST_WARNING_OBJECT (demux, "nonsensical mutually exclusive streams count");
3799     return GST_FLOW_OK;
3800   }
3801
3802   if (size < (num * sizeof (guint16)))
3803     goto not_enough_data;
3804
3805   /* read mutually exclusive stream numbers */
3806   for (i = 0; i < num; ++i) {
3807     guint8 mes;
3808     mes = gst_asf_demux_get_uint16 (&data, &size) & 0x7f;
3809     GST_LOG_OBJECT (demux, "mutually exclusive: stream %d", mes);
3810
3811     demux->mut_ex_streams =
3812         g_slist_append (demux->mut_ex_streams, GINT_TO_POINTER (mes));
3813   }
3814
3815
3816   return GST_FLOW_OK;
3817
3818   /* Errors */
3819 not_enough_data:
3820   {
3821     GST_WARNING_OBJECT (demux, "short read parsing advanced mutual exclusion");
3822     return GST_FLOW_OK;         /* not absolutely fatal */
3823   }
3824 }
3825
3826 gboolean
3827 gst_asf_demux_is_unknown_stream (GstASFDemux * demux, guint stream_num)
3828 {
3829   return g_slist_find (demux->other_streams,
3830       GINT_TO_POINTER (stream_num)) == NULL;
3831 }
3832
3833 static GstFlowReturn
3834 gst_asf_demux_process_ext_stream_props (GstASFDemux * demux, guint8 * data,
3835     guint64 size)
3836 {
3837   AsfStreamExtProps esp;
3838   AsfStream *stream = NULL;
3839   AsfObject stream_obj;
3840   guint16 stream_name_count;
3841   guint16 num_payload_ext;
3842   guint64 len;
3843   guint8 *stream_obj_data = NULL;
3844   guint8 *data_start;
3845   guint obj_size;
3846   guint i, stream_num;
3847
3848   data_start = data;
3849   obj_size = (guint) size;
3850
3851   if (size < 64)
3852     goto not_enough_data;
3853
3854   esp.valid = TRUE;
3855   esp.start_time = gst_asf_demux_get_uint64 (&data, &size) * GST_MSECOND;
3856   esp.end_time = gst_asf_demux_get_uint64 (&data, &size) * GST_MSECOND;
3857   esp.data_bitrate = gst_asf_demux_get_uint32 (&data, &size);
3858   esp.buffer_size = gst_asf_demux_get_uint32 (&data, &size);
3859   esp.intial_buf_fullness = gst_asf_demux_get_uint32 (&data, &size);
3860   esp.data_bitrate2 = gst_asf_demux_get_uint32 (&data, &size);
3861   esp.buffer_size2 = gst_asf_demux_get_uint32 (&data, &size);
3862   esp.intial_buf_fullness2 = gst_asf_demux_get_uint32 (&data, &size);
3863   esp.max_obj_size = gst_asf_demux_get_uint32 (&data, &size);
3864   esp.flags = gst_asf_demux_get_uint32 (&data, &size);
3865   stream_num = gst_asf_demux_get_uint16 (&data, &size);
3866   esp.lang_idx = gst_asf_demux_get_uint16 (&data, &size);
3867   esp.avg_time_per_frame = gst_asf_demux_get_uint64 (&data, &size);
3868   stream_name_count = gst_asf_demux_get_uint16 (&data, &size);
3869   num_payload_ext = gst_asf_demux_get_uint16 (&data, &size);
3870
3871   GST_INFO ("start_time             = %" GST_TIME_FORMAT,
3872       GST_TIME_ARGS (esp.start_time));
3873   GST_INFO ("end_time               = %" GST_TIME_FORMAT,
3874       GST_TIME_ARGS (esp.end_time));
3875   GST_INFO ("flags                  = %08x", esp.flags);
3876   GST_INFO ("average time per frame = %" GST_TIME_FORMAT,
3877       GST_TIME_ARGS (esp.avg_time_per_frame * 100));
3878   GST_INFO ("stream number          = %u", stream_num);
3879   GST_INFO ("stream language ID idx = %u (%s)", esp.lang_idx,
3880       (esp.lang_idx < demux->num_languages) ?
3881       GST_STR_NULL (demux->languages[esp.lang_idx]) : "??");
3882   GST_INFO ("stream name count      = %u", stream_name_count);
3883
3884   /* read stream names */
3885   for (i = 0; i < stream_name_count; ++i) {
3886     guint16 stream_lang_idx G_GNUC_UNUSED;
3887     gchar *stream_name = NULL;
3888
3889     if (size < 2)
3890       goto not_enough_data;
3891     stream_lang_idx = gst_asf_demux_get_uint16 (&data, &size);
3892     if (!gst_asf_demux_get_string (&stream_name, NULL, &data, &size))
3893       goto not_enough_data;
3894     GST_INFO ("stream name %d: %s", i, GST_STR_NULL (stream_name));
3895     g_free (stream_name);       /* TODO: store names in struct */
3896   }
3897
3898   /* read payload extension systems stuff */
3899   GST_LOG ("payload extension systems count = %u", num_payload_ext);
3900
3901   if (num_payload_ext > 0)
3902     esp.payload_extensions = g_new0 (AsfPayloadExtension, num_payload_ext + 1);
3903   else
3904     esp.payload_extensions = NULL;
3905
3906   for (i = 0; i < num_payload_ext; ++i) {
3907     AsfPayloadExtension ext;
3908     ASFGuid ext_guid;
3909     guint32 sys_info_len;
3910
3911     if (size < 16 + 2 + 4)
3912       goto not_enough_data;
3913
3914     gst_asf_demux_get_guid (&ext_guid, &data, &size);
3915     ext.id = gst_asf_demux_identify_guid (asf_payload_ext_guids, &ext_guid);
3916     ext.len = gst_asf_demux_get_uint16 (&data, &size);
3917
3918     sys_info_len = gst_asf_demux_get_uint32 (&data, &size);
3919     GST_LOG ("payload systems info len = %u", sys_info_len);
3920     if (!gst_asf_demux_skip_bytes (sys_info_len, &data, &size))
3921       goto not_enough_data;
3922
3923     esp.payload_extensions[i] = ext;
3924   }
3925
3926   GST_LOG ("bytes read: %u/%u", (guint) (data - data_start), obj_size);
3927
3928   /* there might be an optional STREAM_INFO object here now; if not, we
3929    * should have parsed the corresponding stream info object already (since
3930    * we are parsing the extended stream properties objects delayed) */
3931   if (size == 0) {
3932     stream = gst_asf_demux_get_stream (demux, stream_num);
3933     goto done;
3934   }
3935
3936   /* get size of the stream object */
3937   if (!asf_demux_peek_object (demux, data, size, &stream_obj, TRUE))
3938     goto not_enough_data;
3939
3940   if (stream_obj.id != ASF_OBJ_STREAM)
3941     goto expected_stream_object;
3942
3943   if (stream_obj.size < ASF_OBJECT_HEADER_SIZE ||
3944       stream_obj.size > (10 * 1024 * 1024))
3945     goto not_enough_data;
3946
3947   gst_asf_demux_skip_bytes (ASF_OBJECT_HEADER_SIZE, &data, &size);
3948
3949   /* process this stream object later after all the other 'normal' ones
3950    * have been processed (since the others are more important/non-hidden) */
3951   len = stream_obj.size - ASF_OBJECT_HEADER_SIZE;
3952   if (!gst_asf_demux_get_bytes (&stream_obj_data, len, &data, &size))
3953     goto not_enough_data;
3954
3955   /* parse stream object */
3956   stream = gst_asf_demux_parse_stream_object (demux, stream_obj_data, len);
3957   g_free (stream_obj_data);
3958
3959 done:
3960
3961   if (stream) {
3962     stream->ext_props = esp;
3963
3964     /* try to set the framerate */
3965     if (stream->is_video && stream->caps) {
3966       GValue framerate = { 0 };
3967       GstStructure *s;
3968       gint num, denom;
3969
3970       g_value_init (&framerate, GST_TYPE_FRACTION);
3971
3972       num = GST_SECOND / 100;
3973       denom = esp.avg_time_per_frame;
3974       if (denom == 0) {
3975         /* avoid division by 0, assume 25/1 framerate */
3976         denom = GST_SECOND / 2500;
3977       }
3978
3979       gst_value_set_fraction (&framerate, num, denom);
3980
3981       stream->caps = gst_caps_make_writable (stream->caps);
3982       s = gst_caps_get_structure (stream->caps, 0);
3983       gst_structure_set_value (s, "framerate", &framerate);
3984       g_value_unset (&framerate);
3985       GST_DEBUG_OBJECT (demux, "setting framerate of %d/%d = %f",
3986           num, denom, ((gdouble) num) / denom);
3987     }
3988
3989     /* add language info now if we have it */
3990     if (stream->ext_props.lang_idx < demux->num_languages) {
3991       if (stream->pending_tags == NULL)
3992         stream->pending_tags = gst_tag_list_new_empty ();
3993       GST_LOG_OBJECT (demux, "stream %u has language '%s'", stream->id,
3994           demux->languages[stream->ext_props.lang_idx]);
3995       gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_APPEND,
3996           GST_TAG_LANGUAGE_CODE, demux->languages[stream->ext_props.lang_idx],
3997           NULL);
3998     }
3999   } else if (gst_asf_demux_is_unknown_stream (demux, stream_num)) {
4000     GST_WARNING_OBJECT (demux, "Ext. stream properties for unknown stream");
4001   }
4002
4003   return GST_FLOW_OK;
4004
4005   /* Errors */
4006 not_enough_data:
4007   {
4008     GST_WARNING_OBJECT (demux, "short read parsing ext stream props object!");
4009     return GST_FLOW_OK;         /* not absolutely fatal */
4010   }
4011 expected_stream_object:
4012   {
4013     GST_WARNING_OBJECT (demux, "error parsing extended stream properties "
4014         "object: expected embedded stream object, but got %s object instead!",
4015         gst_asf_get_guid_nick (asf_object_guids, stream_obj.id));
4016     return GST_FLOW_OK;         /* not absolutely fatal */
4017   }
4018 }
4019
4020 static const gchar *
4021 gst_asf_demux_push_obj (GstASFDemux * demux, guint32 obj_id)
4022 {
4023   const gchar *nick;
4024
4025   nick = gst_asf_get_guid_nick (asf_object_guids, obj_id);
4026   if (g_str_has_prefix (nick, "ASF_OBJ_"))
4027     nick += strlen ("ASF_OBJ_");
4028
4029   if (demux->objpath == NULL) {
4030     demux->objpath = g_strdup (nick);
4031   } else {
4032     gchar *newpath;
4033
4034     newpath = g_strdup_printf ("%s/%s", demux->objpath, nick);
4035     g_free (demux->objpath);
4036     demux->objpath = newpath;
4037   }
4038
4039   return (const gchar *) demux->objpath;
4040 }
4041
4042 static void
4043 gst_asf_demux_pop_obj (GstASFDemux * demux)
4044 {
4045   gchar *s;
4046
4047   if ((s = g_strrstr (demux->objpath, "/"))) {
4048     *s = '\0';
4049   } else {
4050     g_free (demux->objpath);
4051     demux->objpath = NULL;
4052   }
4053 }
4054
4055 static void
4056 gst_asf_demux_process_queued_extended_stream_objects (GstASFDemux * demux)
4057 {
4058   GSList *l;
4059   guint i;
4060
4061   /* Parse the queued extended stream property objects and add the info
4062    * to the existing streams or add the new embedded streams, but without
4063    * activating them yet */
4064   GST_LOG_OBJECT (demux, "%u queued extended stream properties objects",
4065       g_slist_length (demux->ext_stream_props));
4066
4067   for (l = demux->ext_stream_props, i = 0; l != NULL; l = l->next, ++i) {
4068     GstBuffer *buf = GST_BUFFER (l->data);
4069     GstMapInfo map;
4070
4071     gst_buffer_map (buf, &map, GST_MAP_READ);
4072
4073     GST_LOG_OBJECT (demux, "parsing ext. stream properties object #%u", i);
4074     gst_asf_demux_process_ext_stream_props (demux, map.data, map.size);
4075     gst_buffer_unmap (buf, &map);
4076     gst_buffer_unref (buf);
4077   }
4078   g_slist_free (demux->ext_stream_props);
4079   demux->ext_stream_props = NULL;
4080 }
4081
4082 #if 0
4083 static void
4084 gst_asf_demux_activate_ext_props_streams (GstASFDemux * demux)
4085 {
4086   guint i, j;
4087
4088   for (i = 0; i < demux->num_streams; ++i) {
4089     AsfStream *stream;
4090     gboolean is_hidden;
4091     GSList *x;
4092
4093     stream = &demux->stream[i];
4094
4095     GST_LOG_OBJECT (demux, "checking  stream %2u", stream->id);
4096
4097     if (stream->active) {
4098       GST_LOG_OBJECT (demux, "stream %2u is already activated", stream->id);
4099       continue;
4100     }
4101
4102     is_hidden = FALSE;
4103     for (x = demux->mut_ex_streams; x != NULL; x = x->next) {
4104       guint8 *mes;
4105
4106       /* check for each mutual exclusion whether it affects this stream */
4107       for (mes = (guint8 *) x->data; mes != NULL && *mes != 0xff; ++mes) {
4108         if (*mes == stream->id) {
4109           /* if yes, check if we've already added streams that are mutually
4110            * exclusive with the stream we're about to add */
4111           for (mes = (guint8 *) x->data; mes != NULL && *mes != 0xff; ++mes) {
4112             for (j = 0; j < demux->num_streams; ++j) {
4113               /* if the broadcast flag is set, assume the hidden streams aren't
4114                * actually streamed and hide them (or playbin won't work right),
4115                * otherwise assume their data is available */
4116               if (demux->stream[j].id == *mes && demux->broadcast) {
4117                 is_hidden = TRUE;
4118                 GST_LOG_OBJECT (demux, "broadcast stream ID %d to be added is "
4119                     "mutually exclusive with already existing stream ID %d, "
4120                     "hiding stream", stream->id, demux->stream[j].id);
4121                 goto next;
4122               }
4123             }
4124           }
4125           break;
4126         }
4127       }
4128     }
4129
4130   next:
4131
4132     /* FIXME: we should do stream activation based on preroll data in
4133      * streaming mode too */
4134     if (demux->streaming && !is_hidden)
4135       gst_asf_demux_activate_stream (demux, stream);
4136   }
4137 }
4138 #endif
4139
4140 static GstFlowReturn
4141 gst_asf_demux_process_object (GstASFDemux * demux, guint8 ** p_data,
4142     guint64 * p_size)
4143 {
4144   GstFlowReturn ret = GST_FLOW_OK;
4145   AsfObject obj;
4146   guint64 obj_data_size;
4147
4148   if (*p_size < ASF_OBJECT_HEADER_SIZE)
4149     return ASF_FLOW_NEED_MORE_DATA;
4150
4151   asf_demux_peek_object (demux, *p_data, ASF_OBJECT_HEADER_SIZE, &obj, TRUE);
4152   gst_asf_demux_skip_bytes (ASF_OBJECT_HEADER_SIZE, p_data, p_size);
4153
4154   obj_data_size = obj.size - ASF_OBJECT_HEADER_SIZE;
4155
4156   if (*p_size < obj_data_size)
4157     return ASF_FLOW_NEED_MORE_DATA;
4158
4159   gst_asf_demux_push_obj (demux, obj.id);
4160
4161   GST_INFO ("%s: size %" G_GUINT64_FORMAT, demux->objpath, obj.size);
4162
4163   switch (obj.id) {
4164     case ASF_OBJ_STREAM:
4165       gst_asf_demux_parse_stream_object (demux, *p_data, obj_data_size);
4166       ret = GST_FLOW_OK;
4167       break;
4168     case ASF_OBJ_FILE:
4169       ret = gst_asf_demux_process_file (demux, *p_data, obj_data_size);
4170       break;
4171     case ASF_OBJ_HEADER:
4172       ret = gst_asf_demux_process_header (demux, *p_data, obj_data_size);
4173       break;
4174     case ASF_OBJ_COMMENT:
4175       ret = gst_asf_demux_process_comment (demux, *p_data, obj_data_size);
4176       break;
4177     case ASF_OBJ_HEAD1:
4178       ret = gst_asf_demux_process_header_ext (demux, *p_data, obj_data_size);
4179       break;
4180     case ASF_OBJ_BITRATE_PROPS:
4181       ret =
4182           gst_asf_demux_process_bitrate_props_object (demux, *p_data,
4183           obj_data_size);
4184       break;
4185     case ASF_OBJ_EXT_CONTENT_DESC:
4186       ret =
4187           gst_asf_demux_process_ext_content_desc (demux, *p_data,
4188           obj_data_size);
4189       break;
4190     case ASF_OBJ_METADATA_OBJECT:
4191       ret = gst_asf_demux_process_metadata (demux, *p_data, obj_data_size);
4192       break;
4193     case ASF_OBJ_EXTENDED_STREAM_PROPS:{
4194       GstBuffer *buf;
4195
4196       /* process these later, we might not have parsed the corresponding
4197        * stream object yet */
4198       GST_LOG ("%s: queued for later parsing", demux->objpath);
4199       buf = gst_buffer_new_and_alloc (obj_data_size);
4200       gst_buffer_fill (buf, 0, *p_data, obj_data_size);
4201       demux->ext_stream_props = g_slist_append (demux->ext_stream_props, buf);
4202       ret = GST_FLOW_OK;
4203       break;
4204     }
4205     case ASF_OBJ_LANGUAGE_LIST:
4206       ret = gst_asf_demux_process_language_list (demux, *p_data, obj_data_size);
4207       break;
4208     case ASF_OBJ_ADVANCED_MUTUAL_EXCLUSION:
4209       ret = gst_asf_demux_process_advanced_mutual_exclusion (demux, *p_data,
4210           obj_data_size);
4211       break;
4212     case ASF_OBJ_SIMPLE_INDEX:
4213       ret = gst_asf_demux_process_simple_index (demux, *p_data, obj_data_size);
4214       break;
4215     case ASF_OBJ_CONTENT_ENCRYPTION:
4216     case ASF_OBJ_EXT_CONTENT_ENCRYPTION:
4217     case ASF_OBJ_DIGITAL_SIGNATURE_OBJECT:
4218     case ASF_OBJ_UNKNOWN_ENCRYPTION_OBJECT:
4219       goto error_encrypted;
4220     case ASF_OBJ_CONCEAL_NONE:
4221     case ASF_OBJ_HEAD2:
4222     case ASF_OBJ_UNDEFINED:
4223     case ASF_OBJ_CODEC_COMMENT:
4224     case ASF_OBJ_INDEX:
4225     case ASF_OBJ_PADDING:
4226     case ASF_OBJ_BITRATE_MUTEX:
4227     case ASF_OBJ_COMPATIBILITY:
4228     case ASF_OBJ_INDEX_PLACEHOLDER:
4229     case ASF_OBJ_INDEX_PARAMETERS:
4230     case ASF_OBJ_STREAM_PRIORITIZATION:
4231     case ASF_OBJ_SCRIPT_COMMAND:
4232     case ASF_OBJ_METADATA_LIBRARY_OBJECT:
4233     default:
4234       /* Unknown/unhandled object, skip it and hope for the best */
4235       GST_INFO ("%s: skipping object", demux->objpath);
4236       ret = GST_FLOW_OK;
4237       break;
4238   }
4239
4240   /* this can't fail, we checked the number of bytes available before */
4241   gst_asf_demux_skip_bytes (obj_data_size, p_data, p_size);
4242
4243   GST_LOG ("%s: ret = %s", demux->objpath, gst_asf_get_flow_name (ret));
4244
4245   gst_asf_demux_pop_obj (demux);
4246
4247   return ret;
4248
4249 /* ERRORS */
4250 error_encrypted:
4251   {
4252     GST_ELEMENT_ERROR (demux, STREAM, DECRYPT, (NULL), (NULL));
4253     return GST_FLOW_ERROR;
4254   }
4255 }
4256
4257 static void
4258 gst_asf_demux_descramble_buffer (GstASFDemux * demux, AsfStream * stream,
4259     GstBuffer ** p_buffer)
4260 {
4261   GstBuffer *descrambled_buffer;
4262   GstBuffer *scrambled_buffer;
4263   GstBuffer *sub_buffer;
4264   guint offset;
4265   guint off;
4266   guint row;
4267   guint col;
4268   guint idx;
4269
4270   /* descrambled_buffer is initialised in the first iteration */
4271   descrambled_buffer = NULL;
4272   scrambled_buffer = *p_buffer;
4273
4274   if (gst_buffer_get_size (scrambled_buffer) <
4275       stream->ds_packet_size * stream->span)
4276     return;
4277
4278   for (offset = 0; offset < gst_buffer_get_size (scrambled_buffer);
4279       offset += stream->ds_chunk_size) {
4280     off = offset / stream->ds_chunk_size;
4281     row = off / stream->span;
4282     col = off % stream->span;
4283     idx = row + col * stream->ds_packet_size / stream->ds_chunk_size;
4284     GST_DEBUG ("idx=%u, row=%u, col=%u, off=%u, ds_chunk_size=%u", idx, row,
4285         col, off, stream->ds_chunk_size);
4286     GST_DEBUG ("scrambled buffer size=%" G_GSIZE_FORMAT
4287         ", span=%u, packet_size=%u", gst_buffer_get_size (scrambled_buffer),
4288         stream->span, stream->ds_packet_size);
4289     GST_DEBUG ("gst_buffer_get_size (scrambled_buffer) = %" G_GSIZE_FORMAT,
4290         gst_buffer_get_size (scrambled_buffer));
4291     sub_buffer =
4292         gst_buffer_copy_region (scrambled_buffer, GST_BUFFER_COPY_MEMORY,
4293         idx * stream->ds_chunk_size, stream->ds_chunk_size);
4294     if (!offset) {
4295       descrambled_buffer = sub_buffer;
4296     } else {
4297       descrambled_buffer = gst_buffer_append (descrambled_buffer, sub_buffer);
4298     }
4299   }
4300
4301   GST_BUFFER_TIMESTAMP (descrambled_buffer) =
4302       GST_BUFFER_TIMESTAMP (scrambled_buffer);
4303   GST_BUFFER_DURATION (descrambled_buffer) =
4304       GST_BUFFER_DURATION (scrambled_buffer);
4305   GST_BUFFER_OFFSET (descrambled_buffer) = GST_BUFFER_OFFSET (scrambled_buffer);
4306   GST_BUFFER_OFFSET_END (descrambled_buffer) =
4307       GST_BUFFER_OFFSET_END (scrambled_buffer);
4308
4309   /* FIXME/CHECK: do we need to transfer buffer flags here too? */
4310
4311   gst_buffer_unref (scrambled_buffer);
4312   *p_buffer = descrambled_buffer;
4313 }
4314
4315 static gboolean
4316 gst_asf_demux_element_send_event (GstElement * element, GstEvent * event)
4317 {
4318   GstASFDemux *demux = GST_ASF_DEMUX (element);
4319   gint i;
4320
4321   GST_DEBUG ("handling element event of type %s", GST_EVENT_TYPE_NAME (event));
4322
4323   for (i = 0; i < demux->num_streams; ++i) {
4324     gst_event_ref (event);
4325     if (gst_asf_demux_handle_src_event (demux->stream[i].pad,
4326             GST_OBJECT_CAST (element), event)) {
4327       gst_event_unref (event);
4328       return TRUE;
4329     }
4330   }
4331
4332   gst_event_unref (event);
4333   return FALSE;
4334 }
4335
4336 /* takes ownership of the passed event */
4337 static gboolean
4338 gst_asf_demux_send_event_unlocked (GstASFDemux * demux, GstEvent * event)
4339 {
4340   gboolean ret = TRUE;
4341   gint i;
4342
4343   GST_DEBUG_OBJECT (demux, "sending %s event to all source pads",
4344       GST_EVENT_TYPE_NAME (event));
4345
4346   for (i = 0; i < demux->num_streams; ++i) {
4347     gst_event_ref (event);
4348     ret &= gst_pad_push_event (demux->stream[i].pad, event);
4349   }
4350   gst_event_unref (event);
4351   return ret;
4352 }
4353
4354 static gboolean
4355 gst_asf_demux_handle_src_query (GstPad * pad, GstObject * parent,
4356     GstQuery * query)
4357 {
4358   GstASFDemux *demux;
4359   gboolean res = FALSE;
4360
4361   demux = GST_ASF_DEMUX (parent);
4362
4363   GST_DEBUG ("handling %s query",
4364       gst_query_type_get_name (GST_QUERY_TYPE (query)));
4365
4366   switch (GST_QUERY_TYPE (query)) {
4367     case GST_QUERY_DURATION:
4368     {
4369       GstFormat format;
4370
4371       gst_query_parse_duration (query, &format, NULL);
4372
4373       if (format != GST_FORMAT_TIME) {
4374         GST_LOG ("only support duration queries in TIME format");
4375         break;
4376       }
4377
4378       res = gst_pad_query_default (pad, parent, query);
4379       if (!res) {
4380         GST_OBJECT_LOCK (demux);
4381
4382         if (demux->segment.duration != GST_CLOCK_TIME_NONE) {
4383           GST_LOG ("returning duration: %" GST_TIME_FORMAT,
4384               GST_TIME_ARGS (demux->segment.duration));
4385
4386           gst_query_set_duration (query, GST_FORMAT_TIME,
4387               demux->segment.duration);
4388
4389           res = TRUE;
4390         } else {
4391           GST_LOG ("duration not known yet");
4392         }
4393
4394         GST_OBJECT_UNLOCK (demux);
4395       }
4396       break;
4397     }
4398
4399     case GST_QUERY_POSITION:{
4400       GstFormat format;
4401
4402       gst_query_parse_position (query, &format, NULL);
4403
4404       if (format != GST_FORMAT_TIME) {
4405         GST_LOG ("only support position queries in TIME format");
4406         break;
4407       }
4408
4409       GST_OBJECT_LOCK (demux);
4410
4411       if (demux->segment.position != GST_CLOCK_TIME_NONE) {
4412         GST_LOG ("returning position: %" GST_TIME_FORMAT,
4413             GST_TIME_ARGS (demux->segment.position));
4414
4415         gst_query_set_position (query, GST_FORMAT_TIME,
4416             demux->segment.position);
4417
4418         res = TRUE;
4419       } else {
4420         GST_LOG ("position not known yet");
4421       }
4422
4423       GST_OBJECT_UNLOCK (demux);
4424       break;
4425     }
4426
4427     case GST_QUERY_SEEKING:{
4428       GstFormat format;
4429
4430       gst_query_parse_seeking (query, &format, NULL, NULL, NULL);
4431       if (format == GST_FORMAT_TIME) {
4432         gint64 duration;
4433
4434         GST_OBJECT_LOCK (demux);
4435         duration = demux->segment.duration;
4436         GST_OBJECT_UNLOCK (demux);
4437
4438         if (!demux->streaming || !demux->seekable) {
4439           gst_query_set_seeking (query, GST_FORMAT_TIME, demux->seekable, 0,
4440               duration);
4441           res = TRUE;
4442         } else {
4443           GstFormat fmt;
4444           gboolean seekable;
4445
4446           /* try upstream first in TIME */
4447           res = gst_pad_query_default (pad, parent, query);
4448
4449           gst_query_parse_seeking (query, &fmt, &seekable, NULL, NULL);
4450           GST_LOG_OBJECT (demux, "upstream %s seekable %d",
4451               GST_STR_NULL (gst_format_get_name (fmt)), seekable);
4452           /* if no luck, maybe in BYTES */
4453           if (!seekable || fmt != GST_FORMAT_TIME) {
4454             GstQuery *q;
4455
4456             q = gst_query_new_seeking (GST_FORMAT_BYTES);
4457             if ((res = gst_pad_peer_query (demux->sinkpad, q))) {
4458               gst_query_parse_seeking (q, &fmt, &seekable, NULL, NULL);
4459               GST_LOG_OBJECT (demux, "upstream %s seekable %d",
4460                   GST_STR_NULL (gst_format_get_name (fmt)), seekable);
4461               if (fmt != GST_FORMAT_BYTES)
4462                 seekable = FALSE;
4463             }
4464             gst_query_unref (q);
4465             gst_query_set_seeking (query, GST_FORMAT_TIME, seekable, 0,
4466                 duration);
4467             res = TRUE;
4468           }
4469         }
4470       } else
4471         GST_LOG_OBJECT (demux, "only support seeking in TIME format");
4472       break;
4473     }
4474
4475     case GST_QUERY_LATENCY:
4476     {
4477       gboolean live;
4478       GstClockTime min, max;
4479
4480       /* preroll delay does not matter in non-live pipeline,
4481        * but we might end up in a live (rtsp) one ... */
4482
4483       /* first forward */
4484       res = gst_pad_query_default (pad, parent, query);
4485       if (!res)
4486         break;
4487
4488       gst_query_parse_latency (query, &live, &min, &max);
4489
4490       GST_DEBUG_OBJECT (demux, "Peer latency: live %d, min %"
4491           GST_TIME_FORMAT " max %" GST_TIME_FORMAT, live,
4492           GST_TIME_ARGS (min), GST_TIME_ARGS (max));
4493
4494       GST_OBJECT_LOCK (demux);
4495       min += demux->latency;
4496       if (max != -1)
4497         max += demux->latency;
4498       GST_OBJECT_UNLOCK (demux);
4499
4500       gst_query_set_latency (query, live, min, max);
4501       break;
4502     }
4503     case GST_QUERY_SEGMENT:
4504     {
4505       GstFormat format;
4506       gint64 start, stop;
4507
4508       format = demux->segment.format;
4509
4510       start =
4511           gst_segment_to_stream_time (&demux->segment, format,
4512           demux->segment.start);
4513       if ((stop = demux->segment.stop) == -1)
4514         stop = demux->segment.duration;
4515       else
4516         stop = gst_segment_to_stream_time (&demux->segment, format, stop);
4517
4518       gst_query_set_segment (query, demux->segment.rate, format, start, stop);
4519       res = TRUE;
4520       break;
4521     }
4522     default:
4523       res = gst_pad_query_default (pad, parent, query);
4524       break;
4525   }
4526
4527   return res;
4528 }
4529
4530 static GstStateChangeReturn
4531 gst_asf_demux_change_state (GstElement * element, GstStateChange transition)
4532 {
4533   GstASFDemux *demux = GST_ASF_DEMUX (element);
4534   GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
4535
4536   switch (transition) {
4537     case GST_STATE_CHANGE_NULL_TO_READY:{
4538       gst_segment_init (&demux->segment, GST_FORMAT_TIME);
4539       demux->need_newsegment = TRUE;
4540       demux->segment_running = FALSE;
4541       demux->accurate = FALSE;
4542       demux->adapter = gst_adapter_new ();
4543       demux->metadata = gst_caps_new_empty ();
4544       demux->global_metadata = gst_structure_new_empty ("metadata");
4545       demux->data_size = 0;
4546       demux->data_offset = 0;
4547       demux->index_offset = 0;
4548       demux->base_offset = 0;
4549       demux->flowcombiner = gst_flow_combiner_new ();
4550       break;
4551     }
4552     default:
4553       break;
4554   }
4555
4556   ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
4557   if (ret == GST_STATE_CHANGE_FAILURE)
4558     return ret;
4559
4560   switch (transition) {
4561     case GST_STATE_CHANGE_PAUSED_TO_READY:
4562       gst_asf_demux_reset (demux, FALSE);
4563       break;
4564
4565     case GST_STATE_CHANGE_READY_TO_NULL:
4566       gst_asf_demux_reset (demux, FALSE);
4567       gst_flow_combiner_free (demux->flowcombiner);
4568       demux->flowcombiner = NULL;
4569       break;
4570     default:
4571       break;
4572   }
4573
4574   return ret;
4575 }