Merge remote-tracking branch 'remotes/origin/upstream/1.6' into tizen
[platform/upstream/gst-plugins-ugly.git] / gst / asfdemux / gstasfdemux.c
1 /* GStreamer ASF/WMV/WMA demuxer
2  * Copyright (C) 1999 Erik Walthinsen <omega@cse.ogi.edu>
3  * Copyright (C) 2006-2009 Tim-Philipp Müller <tim centricular net>
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Library General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Library General Public License for more details.
14  *
15  * You should have received a copy of the GNU Library General Public
16  * License along with this library; if not, write to the
17  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
18  * Boston, MA 02110-1301, USA.
19  */
20
21 /* TODO:
22  *
23  * - _loop():
24  *   stop if at end of segment if != end of file, ie. demux->segment.stop
25  *
26  * - fix packet parsing:
27  *   there's something wrong with timestamps for packets with keyframes,
28  *   and durations too.
29  */
30
31 #ifdef HAVE_CONFIG_H
32 #include "config.h"
33 #endif
34
35 #include <gst/gstutils.h>
36 #include <gst/base/gstbytereader.h>
37 #include <gst/base/gsttypefindhelper.h>
38 #include <gst/riff/riff-media.h>
39 #include <gst/tag/tag.h>
40 #include <gst/gst-i18n-plugin.h>
41 #include <gst/video/video.h>
42 #include <stdio.h>
43 #include <stdlib.h>
44 #include <string.h>
45
46 #include "gstasfdemux.h"
47 #include "asfheaders.h"
48 #include "asfpacket.h"
49
50 static GstStaticPadTemplate gst_asf_demux_sink_template =
51 GST_STATIC_PAD_TEMPLATE ("sink",
52     GST_PAD_SINK,
53     GST_PAD_ALWAYS,
54     GST_STATIC_CAPS ("video/x-ms-asf")
55     );
56
57 static GstStaticPadTemplate audio_src_template =
58 GST_STATIC_PAD_TEMPLATE ("audio_%u",
59     GST_PAD_SRC,
60     GST_PAD_SOMETIMES,
61     GST_STATIC_CAPS_ANY);
62
63 static GstStaticPadTemplate video_src_template =
64 GST_STATIC_PAD_TEMPLATE ("video_%u",
65     GST_PAD_SRC,
66     GST_PAD_SOMETIMES,
67     GST_STATIC_CAPS_ANY);
68
69 /* size of an ASF object header, ie. GUID (16 bytes) + object size (8 bytes) */
70 #define ASF_OBJECT_HEADER_SIZE  (16+8)
71
72 /* FIXME: get rid of this */
73 /* abuse this GstFlowReturn enum for internal usage */
74 #define ASF_FLOW_NEED_MORE_DATA  99
75
76 #define gst_asf_get_flow_name(flow)    \
77   (flow == ASF_FLOW_NEED_MORE_DATA) ?  \
78   "need-more-data" : gst_flow_get_name (flow)
79
80 GST_DEBUG_CATEGORY (asfdemux_dbg);
81
82 static GstStateChangeReturn gst_asf_demux_change_state (GstElement * element,
83     GstStateChange transition);
84 static gboolean gst_asf_demux_element_send_event (GstElement * element,
85     GstEvent * event);
86 static gboolean gst_asf_demux_send_event_unlocked (GstASFDemux * demux,
87     GstEvent * event);
88 static gboolean gst_asf_demux_handle_src_query (GstPad * pad,
89     GstObject * parent, GstQuery * query);
90 static GstFlowReturn gst_asf_demux_chain (GstPad * pad, GstObject * parent,
91     GstBuffer * buf);
92 static gboolean gst_asf_demux_sink_event (GstPad * pad, GstObject * parent,
93     GstEvent * event);
94 static GstFlowReturn gst_asf_demux_process_object (GstASFDemux * demux,
95     guint8 ** p_data, guint64 * p_size);
96 static gboolean gst_asf_demux_activate (GstPad * sinkpad, GstObject * parent);
97 static gboolean gst_asf_demux_activate_mode (GstPad * sinkpad,
98     GstObject * parent, GstPadMode mode, gboolean active);
99 static void gst_asf_demux_loop (GstASFDemux * demux);
100 static void
101 gst_asf_demux_process_queued_extended_stream_objects (GstASFDemux * demux);
102 static gboolean gst_asf_demux_pull_headers (GstASFDemux * demux,
103     GstFlowReturn * pflow);
104 static 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 = GST_READ_UINT32_LE (value);
3207
3208           /* this is the track number */
3209           g_value_init (&tag_value, G_TYPE_UINT);
3210
3211           /* WM/Track counts from 0 */
3212           if (!strcmp (name_utf8, "WM/Track"))
3213             ++uint_val;
3214
3215           g_value_set_uint (&tag_value, uint_val);
3216           break;
3217         }
3218           /* Detect 3D */
3219         case ASF_DEMUX_DATA_TYPE_BOOL:{
3220           gboolean bool_val = GST_READ_UINT32_LE (value);
3221
3222           if (strncmp ("Stereoscopic", name_utf8, strlen (name_utf8)) == 0) {
3223             if (bool_val) {
3224               GST_INFO_OBJECT (demux, "This is 3D contents");
3225               content3D = TRUE;
3226             } else {
3227               GST_INFO_OBJECT (demux, "This is not 3D contenst");
3228               content3D = FALSE;
3229             }
3230           }
3231
3232           break;
3233         }
3234         default:{
3235           GST_DEBUG ("Skipping tag %s of type %d", gst_tag_name, datatype);
3236           break;
3237         }
3238       }
3239
3240       if (G_IS_VALUE (&tag_value)) {
3241         if (gst_tag_name) {
3242           GstTagMergeMode merge_mode = GST_TAG_MERGE_APPEND;
3243
3244           /* WM/TrackNumber is more reliable than WM/Track, since the latter
3245            * is supposed to have a 0 base but is often wrongly written to start
3246            * from 1 as well, so prefer WM/TrackNumber when we have it: either
3247            * replace the value added earlier from WM/Track or put it first in
3248            * the list, so that it will get picked up by _get_uint() */
3249           if (strcmp (name_utf8, "WM/TrackNumber") == 0)
3250             merge_mode = GST_TAG_MERGE_REPLACE;
3251
3252           gst_tag_list_add_values (taglist, merge_mode, gst_tag_name,
3253               &tag_value, NULL);
3254         } else {
3255           GST_DEBUG ("Setting global metadata %s", name_utf8);
3256           gst_structure_set_value (demux->global_metadata, name_utf8,
3257               &tag_value);
3258         }
3259
3260         g_value_unset (&tag_value);
3261       }
3262     }
3263
3264     g_free (name);
3265     g_free (value);
3266     g_free (name_utf8);
3267   }
3268
3269   gst_asf_demux_add_global_tags (demux, taglist);
3270
3271   return GST_FLOW_OK;
3272
3273   /* Errors */
3274 not_enough_data:
3275   {
3276     GST_WARNING ("Unexpected end of data parsing ext content desc object");
3277     gst_tag_list_unref (taglist);
3278     return GST_FLOW_OK;         /* not really fatal */
3279   }
3280 }
3281
3282 static GstStructure *
3283 gst_asf_demux_get_metadata_for_stream (GstASFDemux * demux, guint stream_num)
3284 {
3285   gchar sname[32];
3286   guint i;
3287
3288   g_snprintf (sname, sizeof (sname), "stream-%u", stream_num);
3289
3290   for (i = 0; i < gst_caps_get_size (demux->metadata); ++i) {
3291     GstStructure *s;
3292
3293     s = gst_caps_get_structure (demux->metadata, i);
3294     if (gst_structure_has_name (s, sname))
3295       return s;
3296   }
3297
3298   gst_caps_append_structure (demux->metadata, gst_structure_new_empty (sname));
3299
3300   /* try lookup again; demux->metadata took ownership of the structure, so we
3301    * can't really make any assumptions about what happened to it, so we can't
3302    * just return it directly after appending it */
3303   return gst_asf_demux_get_metadata_for_stream (demux, stream_num);
3304 }
3305
3306 static GstFlowReturn
3307 gst_asf_demux_process_metadata (GstASFDemux * demux, guint8 * data,
3308     guint64 size)
3309 {
3310   guint16 blockcount, i;
3311
3312   GST_INFO_OBJECT (demux, "object is a metadata object");
3313
3314   /* Content Descriptor Count */
3315   if (size < 2)
3316     goto not_enough_data;
3317
3318   blockcount = gst_asf_demux_get_uint16 (&data, &size);
3319
3320   for (i = 0; i < blockcount; ++i) {
3321     GstStructure *s;
3322     guint16 stream_num, name_len, data_type, lang_idx G_GNUC_UNUSED;
3323     guint32 data_len, ival;
3324     gchar *name_utf8;
3325
3326     if (size < (2 + 2 + 2 + 2 + 4))
3327       goto not_enough_data;
3328
3329     lang_idx = gst_asf_demux_get_uint16 (&data, &size);
3330     stream_num = gst_asf_demux_get_uint16 (&data, &size);
3331     name_len = gst_asf_demux_get_uint16 (&data, &size);
3332     data_type = gst_asf_demux_get_uint16 (&data, &size);
3333     data_len = gst_asf_demux_get_uint32 (&data, &size);
3334
3335     if (size < name_len + data_len)
3336       goto not_enough_data;
3337
3338     /* convert name to UTF-8 */
3339     name_utf8 = g_convert ((gchar *) data, name_len, "UTF-8", "UTF-16LE",
3340         NULL, NULL, NULL);
3341     gst_asf_demux_skip_bytes (name_len, &data, &size);
3342
3343     if (name_utf8 == NULL) {
3344       GST_WARNING ("Failed to convert value name to UTF8, skipping");
3345       gst_asf_demux_skip_bytes (data_len, &data, &size);
3346       continue;
3347     }
3348
3349     if (data_type != ASF_DEMUX_DATA_TYPE_DWORD) {
3350       gst_asf_demux_skip_bytes (data_len, &data, &size);
3351       g_free (name_utf8);
3352       continue;
3353     }
3354
3355     /* read DWORD */
3356     if (size < 4) {
3357       g_free (name_utf8);
3358       goto not_enough_data;
3359     }
3360
3361     ival = gst_asf_demux_get_uint32 (&data, &size);
3362
3363     /* skip anything else there may be, just in case */
3364     gst_asf_demux_skip_bytes (data_len - 4, &data, &size);
3365
3366     s = gst_asf_demux_get_metadata_for_stream (demux, stream_num);
3367     gst_structure_set (s, name_utf8, G_TYPE_INT, ival, NULL);
3368     g_free (name_utf8);
3369   }
3370
3371   GST_INFO_OBJECT (demux, "metadata = %" GST_PTR_FORMAT, demux->metadata);
3372   return GST_FLOW_OK;
3373
3374   /* Errors */
3375 not_enough_data:
3376   {
3377     GST_WARNING ("Unexpected end of data parsing metadata object");
3378     return GST_FLOW_OK;         /* not really fatal */
3379   }
3380 }
3381
3382 static GstFlowReturn
3383 gst_asf_demux_process_header (GstASFDemux * demux, guint8 * data, guint64 size)
3384 {
3385   GstFlowReturn ret = GST_FLOW_OK;
3386   guint32 i, num_objects;
3387   guint8 unknown G_GNUC_UNUSED;
3388
3389   /* Get the rest of the header's header */
3390   if (size < (4 + 1 + 1))
3391     goto not_enough_data;
3392
3393   num_objects = gst_asf_demux_get_uint32 (&data, &size);
3394   unknown = gst_asf_demux_get_uint8 (&data, &size);
3395   unknown = gst_asf_demux_get_uint8 (&data, &size);
3396
3397   GST_INFO_OBJECT (demux, "object is a header with %u parts", num_objects);
3398
3399   /* Loop through the header's objects, processing those */
3400   for (i = 0; i < num_objects; ++i) {
3401     GST_INFO_OBJECT (demux, "reading header part %u", i);
3402     ret = gst_asf_demux_process_object (demux, &data, &size);
3403     if (ret != GST_FLOW_OK) {
3404       GST_WARNING ("process_object returned %s", gst_asf_get_flow_name (ret));
3405       break;
3406     }
3407   }
3408
3409   return ret;
3410
3411 not_enough_data:
3412   {
3413     GST_ELEMENT_ERROR (demux, STREAM, DEMUX, (NULL),
3414         ("short read parsing HEADER object"));
3415     return GST_FLOW_ERROR;
3416   }
3417 }
3418
3419 static GstFlowReturn
3420 gst_asf_demux_process_file (GstASFDemux * demux, guint8 * data, guint64 size)
3421 {
3422   guint64 creation_time G_GNUC_UNUSED;
3423   guint64 file_size G_GNUC_UNUSED;
3424   guint64 send_time G_GNUC_UNUSED;
3425   guint64 packets_count, play_time, preroll;
3426   guint32 flags, min_pktsize, max_pktsize, min_bitrate G_GNUC_UNUSED;
3427
3428   if (size < (16 + 8 + 8 + 8 + 8 + 8 + 8 + 4 + 4 + 4 + 4))
3429     goto not_enough_data;
3430
3431   gst_asf_demux_skip_bytes (16, &data, &size);  /* skip GUID */
3432   file_size = gst_asf_demux_get_uint64 (&data, &size);
3433   creation_time = gst_asf_demux_get_uint64 (&data, &size);
3434   packets_count = gst_asf_demux_get_uint64 (&data, &size);
3435   play_time = gst_asf_demux_get_uint64 (&data, &size);
3436   send_time = gst_asf_demux_get_uint64 (&data, &size);
3437   preroll = gst_asf_demux_get_uint64 (&data, &size);
3438   flags = gst_asf_demux_get_uint32 (&data, &size);
3439   min_pktsize = gst_asf_demux_get_uint32 (&data, &size);
3440   max_pktsize = gst_asf_demux_get_uint32 (&data, &size);
3441   min_bitrate = gst_asf_demux_get_uint32 (&data, &size);
3442
3443   demux->broadcast = ! !(flags & 0x01);
3444   demux->seekable = ! !(flags & 0x02);
3445
3446   GST_DEBUG_OBJECT (demux, "min_pktsize = %u", min_pktsize);
3447   GST_DEBUG_OBJECT (demux, "flags::broadcast = %d", demux->broadcast);
3448   GST_DEBUG_OBJECT (demux, "flags::seekable  = %d", demux->seekable);
3449
3450   if (demux->broadcast) {
3451     /* these fields are invalid if the broadcast flag is set */
3452     play_time = 0;
3453     file_size = 0;
3454   }
3455
3456   if (min_pktsize != max_pktsize)
3457     goto non_fixed_packet_size;
3458
3459   demux->packet_size = max_pktsize;
3460
3461   /* FIXME: do we need send_time as well? what is it? */
3462   if ((play_time * 100) >= (preroll * GST_MSECOND))
3463     demux->play_time = (play_time * 100) - (preroll * GST_MSECOND);
3464   else
3465     demux->play_time = 0;
3466
3467   demux->preroll = preroll * GST_MSECOND;
3468
3469   /* initial latency */
3470   demux->latency = demux->preroll;
3471
3472   if (demux->play_time == 0)
3473     demux->seekable = FALSE;
3474
3475   GST_DEBUG_OBJECT (demux, "play_time %" GST_TIME_FORMAT,
3476       GST_TIME_ARGS (demux->play_time));
3477   GST_DEBUG_OBJECT (demux, "preroll   %" GST_TIME_FORMAT,
3478       GST_TIME_ARGS (demux->preroll));
3479
3480   if (demux->play_time > 0) {
3481     demux->segment.duration = demux->play_time;
3482   }
3483
3484   GST_INFO ("object is a file with %" G_GUINT64_FORMAT " data packets",
3485       packets_count);
3486   GST_INFO ("preroll = %" G_GUINT64_FORMAT, demux->preroll);
3487
3488   return GST_FLOW_OK;
3489
3490 /* ERRORS */
3491 non_fixed_packet_size:
3492   {
3493     GST_ELEMENT_ERROR (demux, STREAM, DEMUX, (NULL),
3494         ("packet size must be fixed"));
3495     return GST_FLOW_ERROR;
3496   }
3497 not_enough_data:
3498   {
3499     GST_ELEMENT_ERROR (demux, STREAM, DEMUX, (NULL),
3500         ("short read parsing FILE object"));
3501     return GST_FLOW_ERROR;
3502   }
3503 }
3504
3505 /* Content Description Object */
3506 static GstFlowReturn
3507 gst_asf_demux_process_comment (GstASFDemux * demux, guint8 * data, guint64 size)
3508 {
3509   struct
3510   {
3511     const gchar *gst_tag;
3512     guint16 val_length;
3513     gchar *val_utf8;
3514   } tags[5] = {
3515     {
3516     GST_TAG_TITLE, 0, NULL}, {
3517     GST_TAG_ARTIST, 0, NULL}, {
3518     GST_TAG_COPYRIGHT, 0, NULL}, {
3519     GST_TAG_DESCRIPTION, 0, NULL}, {
3520     GST_TAG_COMMENT, 0, NULL}
3521   };
3522   GstTagList *taglist;
3523   GValue value = { 0 };
3524   gsize in, out;
3525   gint i = -1;
3526
3527   GST_INFO_OBJECT (demux, "object is a comment");
3528
3529   if (size < (2 + 2 + 2 + 2 + 2))
3530     goto not_enough_data;
3531
3532   tags[0].val_length = gst_asf_demux_get_uint16 (&data, &size);
3533   tags[1].val_length = gst_asf_demux_get_uint16 (&data, &size);
3534   tags[2].val_length = gst_asf_demux_get_uint16 (&data, &size);
3535   tags[3].val_length = gst_asf_demux_get_uint16 (&data, &size);
3536   tags[4].val_length = gst_asf_demux_get_uint16 (&data, &size);
3537
3538   GST_DEBUG_OBJECT (demux, "Comment lengths: title=%d author=%d copyright=%d "
3539       "description=%d rating=%d", tags[0].val_length, tags[1].val_length,
3540       tags[2].val_length, tags[3].val_length, tags[4].val_length);
3541
3542   for (i = 0; i < G_N_ELEMENTS (tags); ++i) {
3543     if (size < tags[i].val_length)
3544       goto not_enough_data;
3545
3546     /* might be just '/0', '/0'... */
3547     if (tags[i].val_length > 2 && tags[i].val_length % 2 == 0) {
3548       /* convert to UTF-8 */
3549       tags[i].val_utf8 = g_convert ((gchar *) data, tags[i].val_length,
3550           "UTF-8", "UTF-16LE", &in, &out, NULL);
3551     }
3552     gst_asf_demux_skip_bytes (tags[i].val_length, &data, &size);
3553   }
3554
3555   /* parse metadata into taglist */
3556   taglist = gst_tag_list_new_empty ();
3557   g_value_init (&value, G_TYPE_STRING);
3558   for (i = 0; i < G_N_ELEMENTS (tags); ++i) {
3559     if (tags[i].val_utf8 && strlen (tags[i].val_utf8) > 0 && tags[i].gst_tag) {
3560       g_value_set_string (&value, tags[i].val_utf8);
3561       gst_tag_list_add_values (taglist, GST_TAG_MERGE_APPEND,
3562           tags[i].gst_tag, &value, NULL);
3563     }
3564   }
3565   g_value_unset (&value);
3566
3567   gst_asf_demux_add_global_tags (demux, taglist);
3568
3569   for (i = 0; i < G_N_ELEMENTS (tags); ++i)
3570     g_free (tags[i].val_utf8);
3571
3572   return GST_FLOW_OK;
3573
3574 not_enough_data:
3575   {
3576     GST_WARNING_OBJECT (demux, "unexpectedly short of data while processing "
3577         "comment tag section %d, skipping comment object", i);
3578     for (i = 0; i < G_N_ELEMENTS (tags); i++)
3579       g_free (tags[i].val_utf8);
3580     return GST_FLOW_OK;         /* not really fatal */
3581   }
3582 }
3583
3584 static GstFlowReturn
3585 gst_asf_demux_process_bitrate_props_object (GstASFDemux * demux, guint8 * data,
3586     guint64 size)
3587 {
3588   guint16 num_streams, i;
3589   AsfStream *stream;
3590
3591   if (size < 2)
3592     goto not_enough_data;
3593
3594   num_streams = gst_asf_demux_get_uint16 (&data, &size);
3595
3596   GST_INFO ("object is a bitrate properties object with %u streams",
3597       num_streams);
3598
3599   if (size < (num_streams * (2 + 4)))
3600     goto not_enough_data;
3601
3602   for (i = 0; i < num_streams; ++i) {
3603     guint32 bitrate;
3604     guint16 stream_id;
3605
3606     stream_id = gst_asf_demux_get_uint16 (&data, &size);
3607     bitrate = gst_asf_demux_get_uint32 (&data, &size);
3608
3609     if (stream_id < GST_ASF_DEMUX_NUM_STREAM_IDS) {
3610       GST_DEBUG_OBJECT (demux, "bitrate of stream %u = %u", stream_id, bitrate);
3611       stream = gst_asf_demux_get_stream (demux, stream_id);
3612       if (stream) {
3613         if (stream->pending_tags == NULL) {
3614           stream->pending_tags =
3615               gst_tag_list_new (GST_TAG_BITRATE, bitrate, NULL);
3616         }
3617       } else {
3618         GST_WARNING_OBJECT (demux, "Stream id %u wasn't found", stream_id);
3619       }
3620     } else {
3621       GST_WARNING ("stream id %u is too large", stream_id);
3622     }
3623   }
3624
3625   return GST_FLOW_OK;
3626
3627 not_enough_data:
3628   {
3629     GST_WARNING_OBJECT (demux, "short read parsing bitrate props object!");
3630     return GST_FLOW_OK;         /* not really fatal */
3631   }
3632 }
3633
3634 static GstFlowReturn
3635 gst_asf_demux_process_header_ext (GstASFDemux * demux, guint8 * data,
3636     guint64 size)
3637 {
3638   GstFlowReturn ret = GST_FLOW_OK;
3639   guint64 hdr_size;
3640
3641   /* Get the rest of the header's header */
3642   if (size < (16 + 2 + 4))
3643     goto not_enough_data;
3644
3645   /* skip GUID and two other bytes */
3646   gst_asf_demux_skip_bytes (16 + 2, &data, &size);
3647   hdr_size = gst_asf_demux_get_uint32 (&data, &size);
3648
3649   GST_INFO ("extended header object with a size of %u bytes", (guint) size);
3650
3651   /* FIXME: does data_size include the rest of the header that we have read? */
3652   if (hdr_size > size)
3653     goto not_enough_data;
3654
3655   while (hdr_size > 0) {
3656     ret = gst_asf_demux_process_object (demux, &data, &hdr_size);
3657     if (ret != GST_FLOW_OK)
3658       break;
3659   }
3660
3661   return ret;
3662
3663 not_enough_data:
3664   {
3665     GST_ELEMENT_ERROR (demux, STREAM, DEMUX, (NULL),
3666         ("short read parsing extended header object"));
3667     return GST_FLOW_ERROR;
3668   }
3669 }
3670
3671 static GstFlowReturn
3672 gst_asf_demux_process_language_list (GstASFDemux * demux, guint8 * data,
3673     guint64 size)
3674 {
3675   guint i;
3676
3677   if (size < 2)
3678     goto not_enough_data;
3679
3680   if (demux->languages) {
3681     GST_WARNING ("More than one LANGUAGE_LIST object in stream");
3682     g_strfreev (demux->languages);
3683     demux->languages = NULL;
3684     demux->num_languages = 0;
3685   }
3686
3687   demux->num_languages = gst_asf_demux_get_uint16 (&data, &size);
3688   GST_LOG ("%u languages:", demux->num_languages);
3689
3690   demux->languages = g_new0 (gchar *, demux->num_languages + 1);
3691   for (i = 0; i < demux->num_languages; ++i) {
3692     guint8 len, *lang_data = NULL;
3693
3694     if (size < 1)
3695       goto not_enough_data;
3696     len = gst_asf_demux_get_uint8 (&data, &size);
3697     if (gst_asf_demux_get_bytes (&lang_data, len, &data, &size)) {
3698       gchar *utf8;
3699
3700       utf8 = g_convert ((gchar *) lang_data, len, "UTF-8", "UTF-16LE", NULL,
3701           NULL, NULL);
3702
3703       /* truncate "en-us" etc. to just "en" */
3704       if (utf8 && strlen (utf8) >= 5 && (utf8[2] == '-' || utf8[2] == '_')) {
3705         utf8[2] = '\0';
3706       }
3707       GST_DEBUG ("[%u] %s", i, GST_STR_NULL (utf8));
3708       demux->languages[i] = utf8;
3709       g_free (lang_data);
3710     } else {
3711       goto not_enough_data;
3712     }
3713   }
3714
3715   return GST_FLOW_OK;
3716
3717 not_enough_data:
3718   {
3719     GST_WARNING_OBJECT (demux, "short read parsing language list object!");
3720     g_free (demux->languages);
3721     demux->languages = NULL;
3722     return GST_FLOW_OK;         /* not fatal */
3723   }
3724 }
3725
3726 static GstFlowReturn
3727 gst_asf_demux_process_simple_index (GstASFDemux * demux, guint8 * data,
3728     guint64 size)
3729 {
3730   GstClockTime interval;
3731   guint32 count, i;
3732
3733   if (size < (16 + 8 + 4 + 4))
3734     goto not_enough_data;
3735
3736   /* skip file id */
3737   gst_asf_demux_skip_bytes (16, &data, &size);
3738   interval = gst_asf_demux_get_uint64 (&data, &size) * (GstClockTime) 100;
3739   gst_asf_demux_skip_bytes (4, &data, &size);
3740   count = gst_asf_demux_get_uint32 (&data, &size);
3741   if (count > 0) {
3742     demux->sidx_interval = interval;
3743     demux->sidx_num_entries = count;
3744     g_free (demux->sidx_entries);
3745     demux->sidx_entries = g_new0 (AsfSimpleIndexEntry, count);
3746
3747     for (i = 0; i < count; ++i) {
3748       if (G_UNLIKELY (size < 6)) {
3749         /* adjust for broken files, to avoid having entries at the end
3750          * of the parsed index that point to time=0. Resulting in seeking to
3751          * the end of the file leading back to the beginning */
3752         demux->sidx_num_entries -= (count - i);
3753         break;
3754       }
3755       demux->sidx_entries[i].packet = gst_asf_demux_get_uint32 (&data, &size);
3756       demux->sidx_entries[i].count = gst_asf_demux_get_uint16 (&data, &size);
3757       GST_LOG_OBJECT (demux, "%" GST_TIME_FORMAT " = packet %4u  count : %2d",
3758           GST_TIME_ARGS (i * interval), demux->sidx_entries[i].packet,
3759           demux->sidx_entries[i].count);
3760     }
3761   } else {
3762     GST_DEBUG_OBJECT (demux, "simple index object with 0 entries");
3763   }
3764
3765   return GST_FLOW_OK;
3766
3767 not_enough_data:
3768   {
3769     GST_WARNING_OBJECT (demux, "short read parsing simple index object!");
3770     return GST_FLOW_OK;         /* not fatal */
3771   }
3772 }
3773
3774 static GstFlowReturn
3775 gst_asf_demux_process_advanced_mutual_exclusion (GstASFDemux * demux,
3776     guint8 * data, guint64 size)
3777 {
3778   ASFGuid guid;
3779   guint16 num, i;
3780
3781   if (size < 16 + 2 + (2 * 2))
3782     goto not_enough_data;
3783
3784   gst_asf_demux_get_guid (&guid, &data, &size);
3785   num = gst_asf_demux_get_uint16 (&data, &size);
3786
3787   if (num < 2) {
3788     GST_WARNING_OBJECT (demux, "nonsensical mutually exclusive streams count");
3789     return GST_FLOW_OK;
3790   }
3791
3792   if (size < (num * sizeof (guint16)))
3793     goto not_enough_data;
3794
3795   /* read mutually exclusive stream numbers */
3796   for (i = 0; i < num; ++i) {
3797     guint8 mes;
3798     mes = gst_asf_demux_get_uint16 (&data, &size) & 0x7f;
3799     GST_LOG_OBJECT (demux, "mutually exclusive: stream %d", mes);
3800
3801     demux->mut_ex_streams =
3802         g_slist_append (demux->mut_ex_streams, GINT_TO_POINTER (mes));
3803   }
3804
3805
3806   return GST_FLOW_OK;
3807
3808   /* Errors */
3809 not_enough_data:
3810   {
3811     GST_WARNING_OBJECT (demux, "short read parsing advanced mutual exclusion");
3812     return GST_FLOW_OK;         /* not absolutely fatal */
3813   }
3814 }
3815
3816 gboolean
3817 gst_asf_demux_is_unknown_stream (GstASFDemux * demux, guint stream_num)
3818 {
3819   return g_slist_find (demux->other_streams,
3820       GINT_TO_POINTER (stream_num)) == NULL;
3821 }
3822
3823 static GstFlowReturn
3824 gst_asf_demux_process_ext_stream_props (GstASFDemux * demux, guint8 * data,
3825     guint64 size)
3826 {
3827   AsfStreamExtProps esp;
3828   AsfStream *stream = NULL;
3829   AsfObject stream_obj;
3830   guint16 stream_name_count;
3831   guint16 num_payload_ext;
3832   guint64 len;
3833   guint8 *stream_obj_data = NULL;
3834   guint8 *data_start;
3835   guint obj_size;
3836   guint i, stream_num;
3837
3838   data_start = data;
3839   obj_size = (guint) size;
3840
3841   if (size < 64)
3842     goto not_enough_data;
3843
3844   esp.valid = TRUE;
3845   esp.start_time = gst_asf_demux_get_uint64 (&data, &size) * GST_MSECOND;
3846   esp.end_time = gst_asf_demux_get_uint64 (&data, &size) * GST_MSECOND;
3847   esp.data_bitrate = gst_asf_demux_get_uint32 (&data, &size);
3848   esp.buffer_size = gst_asf_demux_get_uint32 (&data, &size);
3849   esp.intial_buf_fullness = gst_asf_demux_get_uint32 (&data, &size);
3850   esp.data_bitrate2 = gst_asf_demux_get_uint32 (&data, &size);
3851   esp.buffer_size2 = gst_asf_demux_get_uint32 (&data, &size);
3852   esp.intial_buf_fullness2 = gst_asf_demux_get_uint32 (&data, &size);
3853   esp.max_obj_size = gst_asf_demux_get_uint32 (&data, &size);
3854   esp.flags = gst_asf_demux_get_uint32 (&data, &size);
3855   stream_num = gst_asf_demux_get_uint16 (&data, &size);
3856   esp.lang_idx = gst_asf_demux_get_uint16 (&data, &size);
3857   esp.avg_time_per_frame = gst_asf_demux_get_uint64 (&data, &size);
3858   stream_name_count = gst_asf_demux_get_uint16 (&data, &size);
3859   num_payload_ext = gst_asf_demux_get_uint16 (&data, &size);
3860
3861   GST_INFO ("start_time             = %" GST_TIME_FORMAT,
3862       GST_TIME_ARGS (esp.start_time));
3863   GST_INFO ("end_time               = %" GST_TIME_FORMAT,
3864       GST_TIME_ARGS (esp.end_time));
3865   GST_INFO ("flags                  = %08x", esp.flags);
3866   GST_INFO ("average time per frame = %" GST_TIME_FORMAT,
3867       GST_TIME_ARGS (esp.avg_time_per_frame * 100));
3868   GST_INFO ("stream number          = %u", stream_num);
3869   GST_INFO ("stream language ID idx = %u (%s)", esp.lang_idx,
3870       (esp.lang_idx < demux->num_languages) ?
3871       GST_STR_NULL (demux->languages[esp.lang_idx]) : "??");
3872   GST_INFO ("stream name count      = %u", stream_name_count);
3873
3874   /* read stream names */
3875   for (i = 0; i < stream_name_count; ++i) {
3876     guint16 stream_lang_idx G_GNUC_UNUSED;
3877     gchar *stream_name = NULL;
3878
3879     if (size < 2)
3880       goto not_enough_data;
3881     stream_lang_idx = gst_asf_demux_get_uint16 (&data, &size);
3882     if (!gst_asf_demux_get_string (&stream_name, NULL, &data, &size))
3883       goto not_enough_data;
3884     GST_INFO ("stream name %d: %s", i, GST_STR_NULL (stream_name));
3885     g_free (stream_name);       /* TODO: store names in struct */
3886   }
3887
3888   /* read payload extension systems stuff */
3889   GST_LOG ("payload extension systems count = %u", num_payload_ext);
3890
3891   if (num_payload_ext > 0)
3892     esp.payload_extensions = g_new0 (AsfPayloadExtension, num_payload_ext + 1);
3893   else
3894     esp.payload_extensions = NULL;
3895
3896   for (i = 0; i < num_payload_ext; ++i) {
3897     AsfPayloadExtension ext;
3898     ASFGuid ext_guid;
3899     guint32 sys_info_len;
3900
3901     if (size < 16 + 2 + 4)
3902       goto not_enough_data;
3903
3904     gst_asf_demux_get_guid (&ext_guid, &data, &size);
3905     ext.id = gst_asf_demux_identify_guid (asf_payload_ext_guids, &ext_guid);
3906     ext.len = gst_asf_demux_get_uint16 (&data, &size);
3907
3908     sys_info_len = gst_asf_demux_get_uint32 (&data, &size);
3909     GST_LOG ("payload systems info len = %u", sys_info_len);
3910     if (!gst_asf_demux_skip_bytes (sys_info_len, &data, &size))
3911       goto not_enough_data;
3912
3913     esp.payload_extensions[i] = ext;
3914   }
3915
3916   GST_LOG ("bytes read: %u/%u", (guint) (data - data_start), obj_size);
3917
3918   /* there might be an optional STREAM_INFO object here now; if not, we
3919    * should have parsed the corresponding stream info object already (since
3920    * we are parsing the extended stream properties objects delayed) */
3921   if (size == 0) {
3922     stream = gst_asf_demux_get_stream (demux, stream_num);
3923     goto done;
3924   }
3925
3926   /* get size of the stream object */
3927   if (!asf_demux_peek_object (demux, data, size, &stream_obj, TRUE))
3928     goto not_enough_data;
3929
3930   if (stream_obj.id != ASF_OBJ_STREAM)
3931     goto expected_stream_object;
3932
3933   if (stream_obj.size < ASF_OBJECT_HEADER_SIZE ||
3934       stream_obj.size > (10 * 1024 * 1024))
3935     goto not_enough_data;
3936
3937   gst_asf_demux_skip_bytes (ASF_OBJECT_HEADER_SIZE, &data, &size);
3938
3939   /* process this stream object later after all the other 'normal' ones
3940    * have been processed (since the others are more important/non-hidden) */
3941   len = stream_obj.size - ASF_OBJECT_HEADER_SIZE;
3942   if (!gst_asf_demux_get_bytes (&stream_obj_data, len, &data, &size))
3943     goto not_enough_data;
3944
3945   /* parse stream object */
3946   stream = gst_asf_demux_parse_stream_object (demux, stream_obj_data, len);
3947   g_free (stream_obj_data);
3948
3949 done:
3950
3951   if (stream) {
3952     stream->ext_props = esp;
3953
3954     /* try to set the framerate */
3955     if (stream->is_video && stream->caps) {
3956       GValue framerate = { 0 };
3957       GstStructure *s;
3958       gint num, denom;
3959
3960       g_value_init (&framerate, GST_TYPE_FRACTION);
3961
3962       num = GST_SECOND / 100;
3963       denom = esp.avg_time_per_frame;
3964       if (denom == 0) {
3965         /* avoid division by 0, assume 25/1 framerate */
3966         denom = GST_SECOND / 2500;
3967       }
3968
3969       gst_value_set_fraction (&framerate, num, denom);
3970
3971       stream->caps = gst_caps_make_writable (stream->caps);
3972       s = gst_caps_get_structure (stream->caps, 0);
3973       gst_structure_set_value (s, "framerate", &framerate);
3974       g_value_unset (&framerate);
3975       GST_DEBUG_OBJECT (demux, "setting framerate of %d/%d = %f",
3976           num, denom, ((gdouble) num) / denom);
3977     }
3978
3979     /* add language info now if we have it */
3980     if (stream->ext_props.lang_idx < demux->num_languages) {
3981       if (stream->pending_tags == NULL)
3982         stream->pending_tags = gst_tag_list_new_empty ();
3983       GST_LOG_OBJECT (demux, "stream %u has language '%s'", stream->id,
3984           demux->languages[stream->ext_props.lang_idx]);
3985       gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_APPEND,
3986           GST_TAG_LANGUAGE_CODE, demux->languages[stream->ext_props.lang_idx],
3987           NULL);
3988     }
3989   } else if (gst_asf_demux_is_unknown_stream (demux, stream_num)) {
3990     GST_WARNING_OBJECT (demux, "Ext. stream properties for unknown stream");
3991   }
3992
3993   return GST_FLOW_OK;
3994
3995   /* Errors */
3996 not_enough_data:
3997   {
3998     GST_WARNING_OBJECT (demux, "short read parsing ext stream props object!");
3999     return GST_FLOW_OK;         /* not absolutely fatal */
4000   }
4001 expected_stream_object:
4002   {
4003     GST_WARNING_OBJECT (demux, "error parsing extended stream properties "
4004         "object: expected embedded stream object, but got %s object instead!",
4005         gst_asf_get_guid_nick (asf_object_guids, stream_obj.id));
4006     return GST_FLOW_OK;         /* not absolutely fatal */
4007   }
4008 }
4009
4010 static const gchar *
4011 gst_asf_demux_push_obj (GstASFDemux * demux, guint32 obj_id)
4012 {
4013   const gchar *nick;
4014
4015   nick = gst_asf_get_guid_nick (asf_object_guids, obj_id);
4016   if (g_str_has_prefix (nick, "ASF_OBJ_"))
4017     nick += strlen ("ASF_OBJ_");
4018
4019   if (demux->objpath == NULL) {
4020     demux->objpath = g_strdup (nick);
4021   } else {
4022     gchar *newpath;
4023
4024     newpath = g_strdup_printf ("%s/%s", demux->objpath, nick);
4025     g_free (demux->objpath);
4026     demux->objpath = newpath;
4027   }
4028
4029   return (const gchar *) demux->objpath;
4030 }
4031
4032 static void
4033 gst_asf_demux_pop_obj (GstASFDemux * demux)
4034 {
4035   gchar *s;
4036
4037   if ((s = g_strrstr (demux->objpath, "/"))) {
4038     *s = '\0';
4039   } else {
4040     g_free (demux->objpath);
4041     demux->objpath = NULL;
4042   }
4043 }
4044
4045 static void
4046 gst_asf_demux_process_queued_extended_stream_objects (GstASFDemux * demux)
4047 {
4048   GSList *l;
4049   guint i;
4050
4051   /* Parse the queued extended stream property objects and add the info
4052    * to the existing streams or add the new embedded streams, but without
4053    * activating them yet */
4054   GST_LOG_OBJECT (demux, "%u queued extended stream properties objects",
4055       g_slist_length (demux->ext_stream_props));
4056
4057   for (l = demux->ext_stream_props, i = 0; l != NULL; l = l->next, ++i) {
4058     GstBuffer *buf = GST_BUFFER (l->data);
4059     GstMapInfo map;
4060
4061     gst_buffer_map (buf, &map, GST_MAP_READ);
4062
4063     GST_LOG_OBJECT (demux, "parsing ext. stream properties object #%u", i);
4064     gst_asf_demux_process_ext_stream_props (demux, map.data, map.size);
4065     gst_buffer_unmap (buf, &map);
4066     gst_buffer_unref (buf);
4067   }
4068   g_slist_free (demux->ext_stream_props);
4069   demux->ext_stream_props = NULL;
4070 }
4071
4072 #if 0
4073 static void
4074 gst_asf_demux_activate_ext_props_streams (GstASFDemux * demux)
4075 {
4076   guint i, j;
4077
4078   for (i = 0; i < demux->num_streams; ++i) {
4079     AsfStream *stream;
4080     gboolean is_hidden;
4081     GSList *x;
4082
4083     stream = &demux->stream[i];
4084
4085     GST_LOG_OBJECT (demux, "checking  stream %2u", stream->id);
4086
4087     if (stream->active) {
4088       GST_LOG_OBJECT (demux, "stream %2u is already activated", stream->id);
4089       continue;
4090     }
4091
4092     is_hidden = FALSE;
4093     for (x = demux->mut_ex_streams; x != NULL; x = x->next) {
4094       guint8 *mes;
4095
4096       /* check for each mutual exclusion whether it affects this stream */
4097       for (mes = (guint8 *) x->data; mes != NULL && *mes != 0xff; ++mes) {
4098         if (*mes == stream->id) {
4099           /* if yes, check if we've already added streams that are mutually
4100            * exclusive with the stream we're about to add */
4101           for (mes = (guint8 *) x->data; mes != NULL && *mes != 0xff; ++mes) {
4102             for (j = 0; j < demux->num_streams; ++j) {
4103               /* if the broadcast flag is set, assume the hidden streams aren't
4104                * actually streamed and hide them (or playbin won't work right),
4105                * otherwise assume their data is available */
4106               if (demux->stream[j].id == *mes && demux->broadcast) {
4107                 is_hidden = TRUE;
4108                 GST_LOG_OBJECT (demux, "broadcast stream ID %d to be added is "
4109                     "mutually exclusive with already existing stream ID %d, "
4110                     "hiding stream", stream->id, demux->stream[j].id);
4111                 goto next;
4112               }
4113             }
4114           }
4115           break;
4116         }
4117       }
4118     }
4119
4120   next:
4121
4122     /* FIXME: we should do stream activation based on preroll data in
4123      * streaming mode too */
4124     if (demux->streaming && !is_hidden)
4125       gst_asf_demux_activate_stream (demux, stream);
4126   }
4127 }
4128 #endif
4129
4130 static GstFlowReturn
4131 gst_asf_demux_process_object (GstASFDemux * demux, guint8 ** p_data,
4132     guint64 * p_size)
4133 {
4134   GstFlowReturn ret = GST_FLOW_OK;
4135   AsfObject obj;
4136   guint64 obj_data_size;
4137
4138   if (*p_size < ASF_OBJECT_HEADER_SIZE)
4139     return ASF_FLOW_NEED_MORE_DATA;
4140
4141   asf_demux_peek_object (demux, *p_data, ASF_OBJECT_HEADER_SIZE, &obj, TRUE);
4142   gst_asf_demux_skip_bytes (ASF_OBJECT_HEADER_SIZE, p_data, p_size);
4143
4144   obj_data_size = obj.size - ASF_OBJECT_HEADER_SIZE;
4145
4146   if (*p_size < obj_data_size)
4147     return ASF_FLOW_NEED_MORE_DATA;
4148
4149   gst_asf_demux_push_obj (demux, obj.id);
4150
4151   GST_INFO ("%s: size %" G_GUINT64_FORMAT, demux->objpath, obj.size);
4152
4153   switch (obj.id) {
4154     case ASF_OBJ_STREAM:
4155       gst_asf_demux_parse_stream_object (demux, *p_data, obj_data_size);
4156       ret = GST_FLOW_OK;
4157       break;
4158     case ASF_OBJ_FILE:
4159       ret = gst_asf_demux_process_file (demux, *p_data, obj_data_size);
4160       break;
4161     case ASF_OBJ_HEADER:
4162       ret = gst_asf_demux_process_header (demux, *p_data, obj_data_size);
4163       break;
4164     case ASF_OBJ_COMMENT:
4165       ret = gst_asf_demux_process_comment (demux, *p_data, obj_data_size);
4166       break;
4167     case ASF_OBJ_HEAD1:
4168       ret = gst_asf_demux_process_header_ext (demux, *p_data, obj_data_size);
4169       break;
4170     case ASF_OBJ_BITRATE_PROPS:
4171       ret =
4172           gst_asf_demux_process_bitrate_props_object (demux, *p_data,
4173           obj_data_size);
4174       break;
4175     case ASF_OBJ_EXT_CONTENT_DESC:
4176       ret =
4177           gst_asf_demux_process_ext_content_desc (demux, *p_data,
4178           obj_data_size);
4179       break;
4180     case ASF_OBJ_METADATA_OBJECT:
4181       ret = gst_asf_demux_process_metadata (demux, *p_data, obj_data_size);
4182       break;
4183     case ASF_OBJ_EXTENDED_STREAM_PROPS:{
4184       GstBuffer *buf;
4185
4186       /* process these later, we might not have parsed the corresponding
4187        * stream object yet */
4188       GST_LOG ("%s: queued for later parsing", demux->objpath);
4189       buf = gst_buffer_new_and_alloc (obj_data_size);
4190       gst_buffer_fill (buf, 0, *p_data, obj_data_size);
4191       demux->ext_stream_props = g_slist_append (demux->ext_stream_props, buf);
4192       ret = GST_FLOW_OK;
4193       break;
4194     }
4195     case ASF_OBJ_LANGUAGE_LIST:
4196       ret = gst_asf_demux_process_language_list (demux, *p_data, obj_data_size);
4197       break;
4198     case ASF_OBJ_ADVANCED_MUTUAL_EXCLUSION:
4199       ret = gst_asf_demux_process_advanced_mutual_exclusion (demux, *p_data,
4200           obj_data_size);
4201       break;
4202     case ASF_OBJ_SIMPLE_INDEX:
4203       ret = gst_asf_demux_process_simple_index (demux, *p_data, obj_data_size);
4204       break;
4205     case ASF_OBJ_CONTENT_ENCRYPTION:
4206     case ASF_OBJ_EXT_CONTENT_ENCRYPTION:
4207     case ASF_OBJ_DIGITAL_SIGNATURE_OBJECT:
4208     case ASF_OBJ_UNKNOWN_ENCRYPTION_OBJECT:
4209       goto error_encrypted;
4210     case ASF_OBJ_CONCEAL_NONE:
4211     case ASF_OBJ_HEAD2:
4212     case ASF_OBJ_UNDEFINED:
4213     case ASF_OBJ_CODEC_COMMENT:
4214     case ASF_OBJ_INDEX:
4215     case ASF_OBJ_PADDING:
4216     case ASF_OBJ_BITRATE_MUTEX:
4217     case ASF_OBJ_COMPATIBILITY:
4218     case ASF_OBJ_INDEX_PLACEHOLDER:
4219     case ASF_OBJ_INDEX_PARAMETERS:
4220     case ASF_OBJ_STREAM_PRIORITIZATION:
4221     case ASF_OBJ_SCRIPT_COMMAND:
4222     case ASF_OBJ_METADATA_LIBRARY_OBJECT:
4223     default:
4224       /* Unknown/unhandled object, skip it and hope for the best */
4225       GST_INFO ("%s: skipping object", demux->objpath);
4226       ret = GST_FLOW_OK;
4227       break;
4228   }
4229
4230   /* this can't fail, we checked the number of bytes available before */
4231   gst_asf_demux_skip_bytes (obj_data_size, p_data, p_size);
4232
4233   GST_LOG ("%s: ret = %s", demux->objpath, gst_asf_get_flow_name (ret));
4234
4235   gst_asf_demux_pop_obj (demux);
4236
4237   return ret;
4238
4239 /* ERRORS */
4240 error_encrypted:
4241   {
4242     GST_ELEMENT_ERROR (demux, STREAM, DECRYPT, (NULL), (NULL));
4243     return GST_FLOW_ERROR;
4244   }
4245 }
4246
4247 static void
4248 gst_asf_demux_descramble_buffer (GstASFDemux * demux, AsfStream * stream,
4249     GstBuffer ** p_buffer)
4250 {
4251   GstBuffer *descrambled_buffer;
4252   GstBuffer *scrambled_buffer;
4253   GstBuffer *sub_buffer;
4254   guint offset;
4255   guint off;
4256   guint row;
4257   guint col;
4258   guint idx;
4259
4260   /* descrambled_buffer is initialised in the first iteration */
4261   descrambled_buffer = NULL;
4262   scrambled_buffer = *p_buffer;
4263
4264   if (gst_buffer_get_size (scrambled_buffer) <
4265       stream->ds_packet_size * stream->span)
4266     return;
4267
4268   for (offset = 0; offset < gst_buffer_get_size (scrambled_buffer);
4269       offset += stream->ds_chunk_size) {
4270     off = offset / stream->ds_chunk_size;
4271     row = off / stream->span;
4272     col = off % stream->span;
4273     idx = row + col * stream->ds_packet_size / stream->ds_chunk_size;
4274     GST_DEBUG ("idx=%u, row=%u, col=%u, off=%u, ds_chunk_size=%u", idx, row,
4275         col, off, stream->ds_chunk_size);
4276     GST_DEBUG ("scrambled buffer size=%" G_GSIZE_FORMAT
4277         ", span=%u, packet_size=%u", gst_buffer_get_size (scrambled_buffer),
4278         stream->span, stream->ds_packet_size);
4279     GST_DEBUG ("gst_buffer_get_size (scrambled_buffer) = %" G_GSIZE_FORMAT,
4280         gst_buffer_get_size (scrambled_buffer));
4281     sub_buffer =
4282         gst_buffer_copy_region (scrambled_buffer, GST_BUFFER_COPY_MEMORY,
4283         idx * stream->ds_chunk_size, stream->ds_chunk_size);
4284     if (!offset) {
4285       descrambled_buffer = sub_buffer;
4286     } else {
4287       descrambled_buffer = gst_buffer_append (descrambled_buffer, sub_buffer);
4288     }
4289   }
4290
4291   GST_BUFFER_TIMESTAMP (descrambled_buffer) =
4292       GST_BUFFER_TIMESTAMP (scrambled_buffer);
4293   GST_BUFFER_DURATION (descrambled_buffer) =
4294       GST_BUFFER_DURATION (scrambled_buffer);
4295   GST_BUFFER_OFFSET (descrambled_buffer) = GST_BUFFER_OFFSET (scrambled_buffer);
4296   GST_BUFFER_OFFSET_END (descrambled_buffer) =
4297       GST_BUFFER_OFFSET_END (scrambled_buffer);
4298
4299   /* FIXME/CHECK: do we need to transfer buffer flags here too? */
4300
4301   gst_buffer_unref (scrambled_buffer);
4302   *p_buffer = descrambled_buffer;
4303 }
4304
4305 static gboolean
4306 gst_asf_demux_element_send_event (GstElement * element, GstEvent * event)
4307 {
4308   GstASFDemux *demux = GST_ASF_DEMUX (element);
4309   gint i;
4310
4311   GST_DEBUG ("handling element event of type %s", GST_EVENT_TYPE_NAME (event));
4312
4313   for (i = 0; i < demux->num_streams; ++i) {
4314     gst_event_ref (event);
4315     if (gst_asf_demux_handle_src_event (demux->stream[i].pad,
4316             GST_OBJECT_CAST (element), event)) {
4317       gst_event_unref (event);
4318       return TRUE;
4319     }
4320   }
4321
4322   gst_event_unref (event);
4323   return FALSE;
4324 }
4325
4326 /* takes ownership of the passed event */
4327 static gboolean
4328 gst_asf_demux_send_event_unlocked (GstASFDemux * demux, GstEvent * event)
4329 {
4330   gboolean ret = TRUE;
4331   gint i;
4332
4333   GST_DEBUG_OBJECT (demux, "sending %s event to all source pads",
4334       GST_EVENT_TYPE_NAME (event));
4335
4336   for (i = 0; i < demux->num_streams; ++i) {
4337     gst_event_ref (event);
4338     ret &= gst_pad_push_event (demux->stream[i].pad, event);
4339   }
4340   gst_event_unref (event);
4341   return ret;
4342 }
4343
4344 static gboolean
4345 gst_asf_demux_handle_src_query (GstPad * pad, GstObject * parent,
4346     GstQuery * query)
4347 {
4348   GstASFDemux *demux;
4349   gboolean res = FALSE;
4350
4351   demux = GST_ASF_DEMUX (parent);
4352
4353   GST_DEBUG ("handling %s query",
4354       gst_query_type_get_name (GST_QUERY_TYPE (query)));
4355
4356   switch (GST_QUERY_TYPE (query)) {
4357     case GST_QUERY_DURATION:
4358     {
4359       GstFormat format;
4360
4361       gst_query_parse_duration (query, &format, NULL);
4362
4363       if (format != GST_FORMAT_TIME) {
4364         GST_LOG ("only support duration queries in TIME format");
4365         break;
4366       }
4367
4368       res = gst_pad_query_default (pad, parent, query);
4369       if (!res) {
4370         GST_OBJECT_LOCK (demux);
4371
4372         if (demux->segment.duration != GST_CLOCK_TIME_NONE) {
4373           GST_LOG ("returning duration: %" GST_TIME_FORMAT,
4374               GST_TIME_ARGS (demux->segment.duration));
4375
4376           gst_query_set_duration (query, GST_FORMAT_TIME,
4377               demux->segment.duration);
4378
4379           res = TRUE;
4380         } else {
4381           GST_LOG ("duration not known yet");
4382         }
4383
4384         GST_OBJECT_UNLOCK (demux);
4385       }
4386       break;
4387     }
4388
4389     case GST_QUERY_POSITION:{
4390       GstFormat format;
4391
4392       gst_query_parse_position (query, &format, NULL);
4393
4394       if (format != GST_FORMAT_TIME) {
4395         GST_LOG ("only support position queries in TIME format");
4396         break;
4397       }
4398
4399       GST_OBJECT_LOCK (demux);
4400
4401       if (demux->segment.position != GST_CLOCK_TIME_NONE) {
4402         GST_LOG ("returning position: %" GST_TIME_FORMAT,
4403             GST_TIME_ARGS (demux->segment.position));
4404
4405         gst_query_set_position (query, GST_FORMAT_TIME,
4406             demux->segment.position);
4407
4408         res = TRUE;
4409       } else {
4410         GST_LOG ("position not known yet");
4411       }
4412
4413       GST_OBJECT_UNLOCK (demux);
4414       break;
4415     }
4416
4417     case GST_QUERY_SEEKING:{
4418       GstFormat format;
4419
4420       gst_query_parse_seeking (query, &format, NULL, NULL, NULL);
4421       if (format == GST_FORMAT_TIME) {
4422         gint64 duration;
4423
4424         GST_OBJECT_LOCK (demux);
4425         duration = demux->segment.duration;
4426         GST_OBJECT_UNLOCK (demux);
4427
4428         if (!demux->streaming || !demux->seekable) {
4429           gst_query_set_seeking (query, GST_FORMAT_TIME, demux->seekable, 0,
4430               duration);
4431           res = TRUE;
4432         } else {
4433           GstFormat fmt;
4434           gboolean seekable;
4435
4436           /* try upstream first in TIME */
4437           res = gst_pad_query_default (pad, parent, query);
4438
4439           gst_query_parse_seeking (query, &fmt, &seekable, NULL, NULL);
4440           GST_LOG_OBJECT (demux, "upstream %s seekable %d",
4441               GST_STR_NULL (gst_format_get_name (fmt)), seekable);
4442           /* if no luck, maybe in BYTES */
4443           if (!seekable || fmt != GST_FORMAT_TIME) {
4444             GstQuery *q;
4445
4446             q = gst_query_new_seeking (GST_FORMAT_BYTES);
4447             if ((res = gst_pad_peer_query (demux->sinkpad, q))) {
4448               gst_query_parse_seeking (q, &fmt, &seekable, NULL, NULL);
4449               GST_LOG_OBJECT (demux, "upstream %s seekable %d",
4450                   GST_STR_NULL (gst_format_get_name (fmt)), seekable);
4451               if (fmt != GST_FORMAT_BYTES)
4452                 seekable = FALSE;
4453             }
4454             gst_query_unref (q);
4455             gst_query_set_seeking (query, GST_FORMAT_TIME, seekable, 0,
4456                 duration);
4457             res = TRUE;
4458           }
4459         }
4460       } else
4461         GST_LOG_OBJECT (demux, "only support seeking in TIME format");
4462       break;
4463     }
4464
4465     case GST_QUERY_LATENCY:
4466     {
4467       gboolean live;
4468       GstClockTime min, max;
4469
4470       /* preroll delay does not matter in non-live pipeline,
4471        * but we might end up in a live (rtsp) one ... */
4472
4473       /* first forward */
4474       res = gst_pad_query_default (pad, parent, query);
4475       if (!res)
4476         break;
4477
4478       gst_query_parse_latency (query, &live, &min, &max);
4479
4480       GST_DEBUG_OBJECT (demux, "Peer latency: live %d, min %"
4481           GST_TIME_FORMAT " max %" GST_TIME_FORMAT, live,
4482           GST_TIME_ARGS (min), GST_TIME_ARGS (max));
4483
4484       GST_OBJECT_LOCK (demux);
4485       min += demux->latency;
4486       if (max != -1)
4487         max += demux->latency;
4488       GST_OBJECT_UNLOCK (demux);
4489
4490       gst_query_set_latency (query, live, min, max);
4491       break;
4492     }
4493     case GST_QUERY_SEGMENT:
4494     {
4495       GstFormat format;
4496       gint64 start, stop;
4497
4498       format = demux->segment.format;
4499
4500       start =
4501           gst_segment_to_stream_time (&demux->segment, format,
4502           demux->segment.start);
4503       if ((stop = demux->segment.stop) == -1)
4504         stop = demux->segment.duration;
4505       else
4506         stop = gst_segment_to_stream_time (&demux->segment, format, stop);
4507
4508       gst_query_set_segment (query, demux->segment.rate, format, start, stop);
4509       res = TRUE;
4510       break;
4511     }
4512     default:
4513       res = gst_pad_query_default (pad, parent, query);
4514       break;
4515   }
4516
4517   return res;
4518 }
4519
4520 static GstStateChangeReturn
4521 gst_asf_demux_change_state (GstElement * element, GstStateChange transition)
4522 {
4523   GstASFDemux *demux = GST_ASF_DEMUX (element);
4524   GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
4525
4526   switch (transition) {
4527     case GST_STATE_CHANGE_NULL_TO_READY:{
4528       gst_segment_init (&demux->segment, GST_FORMAT_TIME);
4529       demux->need_newsegment = TRUE;
4530       demux->segment_running = FALSE;
4531       demux->accurate = FALSE;
4532       demux->adapter = gst_adapter_new ();
4533       demux->metadata = gst_caps_new_empty ();
4534       demux->global_metadata = gst_structure_new_empty ("metadata");
4535       demux->data_size = 0;
4536       demux->data_offset = 0;
4537       demux->index_offset = 0;
4538       demux->base_offset = 0;
4539       demux->flowcombiner = gst_flow_combiner_new ();
4540       break;
4541     }
4542     default:
4543       break;
4544   }
4545
4546   ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
4547   if (ret == GST_STATE_CHANGE_FAILURE)
4548     return ret;
4549
4550   switch (transition) {
4551     case GST_STATE_CHANGE_PAUSED_TO_READY:
4552       gst_asf_demux_reset (demux, FALSE);
4553       break;
4554
4555     case GST_STATE_CHANGE_READY_TO_NULL:
4556       gst_asf_demux_reset (demux, FALSE);
4557       gst_flow_combiner_free (demux->flowcombiner);
4558       demux->flowcombiner = NULL;
4559       break;
4560     default:
4561       break;
4562   }
4563
4564   return ret;
4565 }