asfdemux: remove unread value
[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     GstBuffer *buf = gst_value_get_buffer (value);
2576     GstMapInfo mapinfo;
2577
2578     if (gst_buffer_map (buf, &mapinfo, GST_MAP_READ)) {
2579       if (mapinfo.size >= 4 && GST_READ_UINT32_BE (mapinfo.data) == 1) {
2580         /* this looks like a bytestream start */
2581         streamheader = gst_buffer_ref (buf);
2582         gst_asf_demux_add_stream_headers_to_caps (demux, buf, caps_s);
2583         gst_structure_remove_field (caps_s, "codec_data");
2584       }
2585
2586       gst_buffer_unmap (buf, &mapinfo);
2587     }
2588   }
2589
2590   /* For a 3D video, set multiview information into the caps based on
2591    * what was detected during object parsing */
2592   if (demux->asf_3D_mode != GST_ASF_3D_NONE) {
2593     GstVideoMultiviewMode mv_mode = GST_VIDEO_MULTIVIEW_MODE_NONE;
2594     GstVideoMultiviewFlags mv_flags = GST_VIDEO_MULTIVIEW_FLAGS_NONE;
2595     const gchar *mview_mode_str;
2596
2597     switch (demux->asf_3D_mode) {
2598       case GST_ASF_3D_SIDE_BY_SIDE_HALF_LR:
2599         mv_mode = GST_VIDEO_MULTIVIEW_MODE_SIDE_BY_SIDE;
2600         break;
2601       case GST_ASF_3D_SIDE_BY_SIDE_HALF_RL:
2602         mv_mode = GST_VIDEO_MULTIVIEW_MODE_SIDE_BY_SIDE;
2603         mv_flags = GST_VIDEO_MULTIVIEW_FLAGS_RIGHT_VIEW_FIRST;
2604         break;
2605       case GST_ASF_3D_TOP_AND_BOTTOM_HALF_LR:
2606         mv_mode = GST_VIDEO_MULTIVIEW_MODE_TOP_BOTTOM;
2607         break;
2608       case GST_ASF_3D_TOP_AND_BOTTOM_HALF_RL:
2609         mv_mode = GST_VIDEO_MULTIVIEW_MODE_TOP_BOTTOM;
2610         mv_flags = GST_VIDEO_MULTIVIEW_FLAGS_RIGHT_VIEW_FIRST;
2611         break;
2612       case GST_ASF_3D_DUAL_STREAM:{
2613         gboolean is_right_view = FALSE;
2614         /* if Advanced_Mutual_Exclusion object exists, use it
2615          * to figure out which is the left view (lower ID) */
2616         if (demux->mut_ex_streams != NULL) {
2617           guint length;
2618           gint i;
2619
2620           length = g_slist_length (demux->mut_ex_streams);
2621
2622           for (i = 0; i < length; i++) {
2623             gpointer v_s_id;
2624
2625             v_s_id = g_slist_nth_data (demux->mut_ex_streams, i);
2626
2627             GST_DEBUG_OBJECT (demux,
2628                 "has Mutual_Exclusion object. stream id in object is %d",
2629                 GPOINTER_TO_INT (v_s_id));
2630
2631             if (id > GPOINTER_TO_INT (v_s_id))
2632               is_right_view = TRUE;
2633           }
2634         } else {
2635           /* if the Advaced_Mutual_Exclusion object doesn't exist, assume the
2636            * first video stream encountered has the lower ID */
2637           if (demux->num_video_streams > 0) {
2638             /* This is not the first video stream, assuming right eye view */
2639             is_right_view = TRUE;
2640           }
2641         }
2642         if (is_right_view)
2643           mv_mode = GST_VIDEO_MULTIVIEW_MODE_RIGHT;
2644         else
2645           mv_mode = GST_VIDEO_MULTIVIEW_MODE_LEFT;
2646         break;
2647       }
2648       default:
2649         break;
2650     }
2651
2652     GST_INFO_OBJECT (demux,
2653         "stream_id %d, has multiview-mode %d flags 0x%x", id, mv_mode,
2654         (guint) mv_flags);
2655
2656     mview_mode_str = gst_video_multiview_mode_to_caps_string (mv_mode);
2657     if (mview_mode_str != NULL) {
2658       if (gst_video_multiview_guess_half_aspect (mv_mode, video->width,
2659               video->height, par_w, par_h))
2660         mv_flags |= GST_VIDEO_MULTIVIEW_FLAGS_HALF_ASPECT;
2661
2662       gst_caps_set_simple (caps,
2663           "multiview-mode", G_TYPE_STRING, mview_mode_str,
2664           "multiview-flags", GST_TYPE_VIDEO_MULTIVIEW_FLAGSET, mv_flags,
2665           GST_FLAG_SET_MASK_EXACT, NULL);
2666     }
2667   }
2668
2669   if (codec_name) {
2670     tags = gst_tag_list_new (GST_TAG_VIDEO_CODEC, codec_name, NULL);
2671     g_free (codec_name);
2672   }
2673
2674   if (extradata)
2675     gst_buffer_unref (extradata);
2676
2677   GST_INFO ("Adding video stream #%u, id %u, codec %"
2678       GST_FOURCC_FORMAT " (0x%08x)", demux->num_video_streams, id,
2679       GST_FOURCC_ARGS (video->tag), video->tag);
2680
2681   ++demux->num_video_streams;
2682
2683   return gst_asf_demux_setup_pad (demux, src_pad, caps, id, TRUE,
2684       streamheader, tags);
2685 }
2686
2687 static void
2688 gst_asf_demux_activate_stream (GstASFDemux * demux, AsfStream * stream)
2689 {
2690   if (!stream->active) {
2691     GstEvent *event;
2692     gchar *stream_id;
2693
2694     GST_INFO_OBJECT (demux, "Activating stream %2u, pad %s, caps %"
2695         GST_PTR_FORMAT, stream->id, GST_PAD_NAME (stream->pad), stream->caps);
2696     gst_pad_set_active (stream->pad, TRUE);
2697
2698     stream_id =
2699         gst_pad_create_stream_id_printf (stream->pad, GST_ELEMENT_CAST (demux),
2700         "%03u", stream->id);
2701
2702     event =
2703         gst_pad_get_sticky_event (demux->sinkpad, GST_EVENT_STREAM_START, 0);
2704     if (event) {
2705       if (gst_event_parse_group_id (event, &demux->group_id))
2706         demux->have_group_id = TRUE;
2707       else
2708         demux->have_group_id = FALSE;
2709       gst_event_unref (event);
2710     } else if (!demux->have_group_id) {
2711       demux->have_group_id = TRUE;
2712       demux->group_id = gst_util_group_id_next ();
2713     }
2714
2715     event = gst_event_new_stream_start (stream_id);
2716     if (demux->have_group_id)
2717       gst_event_set_group_id (event, demux->group_id);
2718
2719     gst_pad_push_event (stream->pad, event);
2720     g_free (stream_id);
2721     gst_pad_set_caps (stream->pad, stream->caps);
2722
2723     gst_element_add_pad (GST_ELEMENT_CAST (demux), stream->pad);
2724     gst_flow_combiner_add_pad (demux->flowcombiner, stream->pad);
2725     stream->active = TRUE;
2726   }
2727 }
2728
2729 static AsfStream *
2730 gst_asf_demux_parse_stream_object (GstASFDemux * demux, guint8 * data,
2731     guint64 size)
2732 {
2733   AsfCorrectionType correction_type;
2734   AsfStreamType stream_type;
2735   GstClockTime time_offset;
2736   gboolean is_encrypted G_GNUC_UNUSED;
2737   guint16 stream_id;
2738   guint16 flags;
2739   ASFGuid guid;
2740   guint stream_specific_size;
2741   guint type_specific_size G_GNUC_UNUSED;
2742   guint unknown G_GNUC_UNUSED;
2743   gboolean inspect_payload = FALSE;
2744   AsfStream *stream = NULL;
2745
2746   /* Get the rest of the header's header */
2747   if (size < (16 + 16 + 8 + 4 + 4 + 2 + 4))
2748     goto not_enough_data;
2749
2750   gst_asf_demux_get_guid (&guid, &data, &size);
2751   stream_type = gst_asf_demux_identify_guid (asf_stream_guids, &guid);
2752
2753   gst_asf_demux_get_guid (&guid, &data, &size);
2754   correction_type = gst_asf_demux_identify_guid (asf_correction_guids, &guid);
2755
2756   time_offset = gst_asf_demux_get_uint64 (&data, &size) * 100;
2757
2758   type_specific_size = gst_asf_demux_get_uint32 (&data, &size);
2759   stream_specific_size = gst_asf_demux_get_uint32 (&data, &size);
2760
2761   flags = gst_asf_demux_get_uint16 (&data, &size);
2762   stream_id = flags & 0x7f;
2763   is_encrypted = ! !((flags & 0x8000) << 15);
2764   unknown = gst_asf_demux_get_uint32 (&data, &size);
2765
2766   GST_DEBUG_OBJECT (demux, "Found stream %u, time_offset=%" GST_TIME_FORMAT,
2767       stream_id, GST_TIME_ARGS (time_offset));
2768
2769   /* dvr-ms has audio stream declared in stream specific data */
2770   if (stream_type == ASF_STREAM_EXT_EMBED_HEADER) {
2771     AsfExtStreamType ext_stream_type;
2772     gst_asf_demux_get_guid (&guid, &data, &size);
2773     ext_stream_type = gst_asf_demux_identify_guid (asf_ext_stream_guids, &guid);
2774
2775     if (ext_stream_type == ASF_EXT_STREAM_AUDIO) {
2776       inspect_payload = TRUE;
2777
2778       gst_asf_demux_get_guid (&guid, &data, &size);
2779       gst_asf_demux_get_uint32 (&data, &size);
2780       gst_asf_demux_get_uint32 (&data, &size);
2781       gst_asf_demux_get_uint32 (&data, &size);
2782       gst_asf_demux_get_guid (&guid, &data, &size);
2783       gst_asf_demux_get_uint32 (&data, &size);
2784       stream_type = ASF_STREAM_AUDIO;
2785     }
2786   }
2787
2788   switch (stream_type) {
2789     case ASF_STREAM_AUDIO:{
2790       asf_stream_audio audio_object;
2791
2792       if (!gst_asf_demux_get_stream_audio (&audio_object, &data, &size))
2793         goto not_enough_data;
2794
2795       GST_INFO ("Object is an audio stream with %u bytes of additional data",
2796           audio_object.size);
2797
2798       stream = gst_asf_demux_add_audio_stream (demux, &audio_object, stream_id,
2799           &data, &size);
2800
2801       switch (correction_type) {
2802         case ASF_CORRECTION_ON:{
2803           guint span, packet_size, chunk_size, data_size, silence_data;
2804
2805           GST_INFO ("Using error correction");
2806
2807           if (size < (1 + 2 + 2 + 2 + 1))
2808             goto not_enough_data;
2809
2810           span = gst_asf_demux_get_uint8 (&data, &size);
2811           packet_size = gst_asf_demux_get_uint16 (&data, &size);
2812           chunk_size = gst_asf_demux_get_uint16 (&data, &size);
2813           data_size = gst_asf_demux_get_uint16 (&data, &size);
2814           silence_data = gst_asf_demux_get_uint8 (&data, &size);
2815
2816           stream->span = span;
2817
2818           GST_DEBUG_OBJECT (demux, "Descrambling ps:%u cs:%u ds:%u s:%u sd:%u",
2819               packet_size, chunk_size, data_size, span, silence_data);
2820
2821           if (stream->span > 1) {
2822             if (chunk_size == 0 || ((packet_size / chunk_size) <= 1)) {
2823               /* Disable descrambling */
2824               stream->span = 0;
2825             } else {
2826               /* FIXME: this else branch was added for
2827                * weird_al_yankovic - the saga begins.asf */
2828               stream->ds_packet_size = packet_size;
2829               stream->ds_chunk_size = chunk_size;
2830             }
2831           } else {
2832             /* Descambling is enabled */
2833             stream->ds_packet_size = packet_size;
2834             stream->ds_chunk_size = chunk_size;
2835           }
2836 #if 0
2837           /* Now skip the rest of the silence data */
2838           if (data_size > 1)
2839             gst_bytestream_flush (demux->bs, data_size - 1);
2840 #else
2841           /* FIXME: CHECKME. And why -1? */
2842           if (data_size > 1) {
2843             if (!gst_asf_demux_skip_bytes (data_size - 1, &data, &size)) {
2844               goto not_enough_data;
2845             }
2846           }
2847 #endif
2848           break;
2849         }
2850         case ASF_CORRECTION_OFF:{
2851           GST_INFO ("Error correction off");
2852           if (!gst_asf_demux_skip_bytes (stream_specific_size, &data, &size))
2853             goto not_enough_data;
2854           break;
2855         }
2856         default:
2857           GST_ELEMENT_ERROR (demux, STREAM, DEMUX, (NULL),
2858               ("Audio stream using unknown error correction"));
2859           return NULL;
2860       }
2861
2862       break;
2863     }
2864
2865     case ASF_STREAM_VIDEO:{
2866       asf_stream_video_format video_format_object;
2867       asf_stream_video video_object;
2868       guint16 vsize;
2869
2870       if (!gst_asf_demux_get_stream_video (&video_object, &data, &size))
2871         goto not_enough_data;
2872
2873       vsize = video_object.size - 40;   /* Byte order gets offset by single byte */
2874
2875       GST_INFO ("object is a video stream with %u bytes of "
2876           "additional data", vsize);
2877
2878       if (!gst_asf_demux_get_stream_video_format (&video_format_object,
2879               &data, &size)) {
2880         goto not_enough_data;
2881       }
2882
2883       stream = gst_asf_demux_add_video_stream (demux, &video_format_object,
2884           stream_id, &data, &size);
2885
2886       break;
2887     }
2888
2889     default:
2890       GST_WARNING_OBJECT (demux, "Unknown stream type for stream %u",
2891           stream_id);
2892       demux->other_streams =
2893           g_slist_append (demux->other_streams, GINT_TO_POINTER (stream_id));
2894       break;
2895   }
2896
2897   if (stream)
2898     stream->inspect_payload = inspect_payload;
2899   return stream;
2900
2901 not_enough_data:
2902   {
2903     GST_WARNING_OBJECT (demux, "Unexpected end of data parsing stream object");
2904     /* we'll error out later if we found no streams */
2905     return NULL;
2906   }
2907 }
2908
2909 static const gchar *
2910 gst_asf_demux_get_gst_tag_from_tag_name (const gchar * name_utf8)
2911 {
2912   const struct
2913   {
2914     const gchar *asf_name;
2915     const gchar *gst_name;
2916   } tags[] = {
2917     {
2918     "WM/Genre", GST_TAG_GENRE}, {
2919     "WM/AlbumTitle", GST_TAG_ALBUM}, {
2920     "WM/AlbumArtist", GST_TAG_ARTIST}, {
2921     "WM/Picture", GST_TAG_IMAGE}, {
2922     "WM/Track", GST_TAG_TRACK_NUMBER}, {
2923     "WM/TrackNumber", GST_TAG_TRACK_NUMBER}, {
2924     "WM/Year", GST_TAG_DATE_TIME}
2925     /* { "WM/Composer", GST_TAG_COMPOSER } */
2926   };
2927   gsize out;
2928   guint i;
2929
2930   if (name_utf8 == NULL) {
2931     GST_WARNING ("Failed to convert name to UTF8, skipping");
2932     return NULL;
2933   }
2934
2935   out = strlen (name_utf8);
2936
2937   for (i = 0; i < G_N_ELEMENTS (tags); ++i) {
2938     if (strncmp (tags[i].asf_name, name_utf8, out) == 0) {
2939       GST_LOG ("map tagname '%s' -> '%s'", name_utf8, tags[i].gst_name);
2940       return tags[i].gst_name;
2941     }
2942   }
2943
2944   return NULL;
2945 }
2946
2947 /* gst_asf_demux_add_global_tags() takes ownership of taglist! */
2948 static void
2949 gst_asf_demux_add_global_tags (GstASFDemux * demux, GstTagList * taglist)
2950 {
2951   GstTagList *t;
2952
2953   GST_DEBUG_OBJECT (demux, "adding global tags: %" GST_PTR_FORMAT, taglist);
2954
2955   if (taglist == NULL)
2956     return;
2957
2958   if (gst_tag_list_is_empty (taglist)) {
2959     gst_tag_list_unref (taglist);
2960     return;
2961   }
2962
2963   t = gst_tag_list_merge (demux->taglist, taglist, GST_TAG_MERGE_APPEND);
2964   gst_tag_list_set_scope (t, GST_TAG_SCOPE_GLOBAL);
2965   if (demux->taglist)
2966     gst_tag_list_unref (demux->taglist);
2967   gst_tag_list_unref (taglist);
2968   demux->taglist = t;
2969   GST_LOG_OBJECT (demux, "global tags now: %" GST_PTR_FORMAT, demux->taglist);
2970 }
2971
2972 #define ASF_DEMUX_DATA_TYPE_UTF16LE_STRING  0
2973 #define ASF_DEMUX_DATA_TYPE_BYTE_ARRAY      1
2974 #define ASF_DEMUX_DATA_TYPE_BOOL                        2
2975 #define ASF_DEMUX_DATA_TYPE_DWORD           3
2976
2977 static void
2978 asf_demux_parse_picture_tag (GstTagList * tags, const guint8 * tag_data,
2979     guint tag_data_len)
2980 {
2981   GstByteReader r;
2982   const guint8 *img_data = NULL;
2983   guint32 img_data_len = 0;
2984   guint8 pic_type = 0;
2985
2986   gst_byte_reader_init (&r, tag_data, tag_data_len);
2987
2988   /* skip mime type string (we don't trust it and do our own typefinding),
2989    * and also skip the description string, since we don't use it */
2990   if (!gst_byte_reader_get_uint8 (&r, &pic_type) ||
2991       !gst_byte_reader_get_uint32_le (&r, &img_data_len) ||
2992       !gst_byte_reader_skip_string_utf16 (&r) ||
2993       !gst_byte_reader_skip_string_utf16 (&r) ||
2994       !gst_byte_reader_get_data (&r, img_data_len, &img_data)) {
2995     goto not_enough_data;
2996   }
2997
2998
2999   if (!gst_tag_list_add_id3_image (tags, img_data, img_data_len, pic_type))
3000     GST_DEBUG ("failed to add image extracted from WM/Picture tag to taglist");
3001
3002   return;
3003
3004 not_enough_data:
3005   {
3006     GST_DEBUG ("Failed to read WM/Picture tag: not enough data");
3007     GST_MEMDUMP ("WM/Picture data", tag_data, tag_data_len);
3008     return;
3009   }
3010 }
3011
3012 /* Extended Content Description Object */
3013 static GstFlowReturn
3014 gst_asf_demux_process_ext_content_desc (GstASFDemux * demux, guint8 * data,
3015     guint64 size)
3016 {
3017   /* Other known (and unused) 'text/unicode' metadata available :
3018    *
3019    *   WM/Lyrics =
3020    *   WM/MediaPrimaryClassID = {D1607DBC-E323-4BE2-86A1-48A42A28441E}
3021    *   WMFSDKVersion = 9.00.00.2980
3022    *   WMFSDKNeeded = 0.0.0.0000
3023    *   WM/UniqueFileIdentifier = AMGa_id=R    15334;AMGp_id=P     5149;AMGt_id=T  2324984
3024    *   WM/Publisher = 4AD
3025    *   WM/Provider = AMG
3026    *   WM/ProviderRating = 8
3027    *   WM/ProviderStyle = Rock (similar to WM/Genre)
3028    *   WM/GenreID (similar to WM/Genre)
3029    *   WM/TrackNumber (same as WM/Track but as a string)
3030    *
3031    * Other known (and unused) 'non-text' metadata available :
3032    *
3033    *   WM/EncodingTime
3034    *   WM/MCDI
3035    *   IsVBR
3036    *
3037    * We might want to read WM/TrackNumber and use atoi() if we don't have
3038    * WM/Track
3039    */
3040
3041   GstTagList *taglist;
3042   guint16 blockcount, i;
3043   gboolean content3D = FALSE;
3044
3045   struct
3046   {
3047     const gchar *interleave_name;
3048     GstASF3DMode interleaving_type;
3049   } stereoscopic_layout_map[] = {
3050     {
3051     "SideBySideRF", GST_ASF_3D_SIDE_BY_SIDE_HALF_RL}, {
3052     "SideBySideLF", GST_ASF_3D_SIDE_BY_SIDE_HALF_LR}, {
3053     "OverUnderRT", GST_ASF_3D_TOP_AND_BOTTOM_HALF_RL}, {
3054     "OverUnderLT", GST_ASF_3D_TOP_AND_BOTTOM_HALF_LR}, {
3055     "DualStream", GST_ASF_3D_DUAL_STREAM}
3056   };
3057   GST_INFO_OBJECT (demux, "object is an extended content description");
3058
3059   taglist = gst_tag_list_new_empty ();
3060
3061   /* Content Descriptor Count */
3062   if (size < 2)
3063     goto not_enough_data;
3064
3065   blockcount = gst_asf_demux_get_uint16 (&data, &size);
3066
3067   for (i = 1; i <= blockcount; ++i) {
3068     const gchar *gst_tag_name;
3069     guint16 datatype;
3070     guint16 value_len;
3071     guint16 name_len;
3072     GValue tag_value = { 0, };
3073     gsize in, out;
3074     gchar *name;
3075     gchar *name_utf8 = NULL;
3076     gchar *value;
3077
3078     /* Descriptor */
3079     if (!gst_asf_demux_get_string (&name, &name_len, &data, &size))
3080       goto not_enough_data;
3081
3082     if (size < 2) {
3083       g_free (name);
3084       goto not_enough_data;
3085     }
3086     /* Descriptor Value Data Type */
3087     datatype = gst_asf_demux_get_uint16 (&data, &size);
3088
3089     /* Descriptor Value (not really a string, but same thing reading-wise) */
3090     if (!gst_asf_demux_get_string (&value, &value_len, &data, &size)) {
3091       g_free (name);
3092       goto not_enough_data;
3093     }
3094
3095     name_utf8 =
3096         g_convert (name, name_len, "UTF-8", "UTF-16LE", &in, &out, NULL);
3097
3098     if (name_utf8 != NULL) {
3099       GST_DEBUG ("Found tag/metadata %s", name_utf8);
3100
3101       gst_tag_name = gst_asf_demux_get_gst_tag_from_tag_name (name_utf8);
3102       GST_DEBUG ("gst_tag_name %s", GST_STR_NULL (gst_tag_name));
3103
3104       switch (datatype) {
3105         case ASF_DEMUX_DATA_TYPE_UTF16LE_STRING:{
3106           gchar *value_utf8;
3107
3108           value_utf8 = g_convert (value, value_len, "UTF-8", "UTF-16LE",
3109               &in, &out, NULL);
3110
3111           /* get rid of tags with empty value */
3112           if (value_utf8 != NULL && *value_utf8 != '\0') {
3113             GST_DEBUG ("string value %s", value_utf8);
3114
3115             value_utf8[out] = '\0';
3116
3117             if (gst_tag_name != NULL) {
3118               if (strcmp (gst_tag_name, GST_TAG_DATE_TIME) == 0) {
3119                 guint year = atoi (value_utf8);
3120
3121                 if (year > 0) {
3122                   g_value_init (&tag_value, GST_TYPE_DATE_TIME);
3123                   g_value_take_boxed (&tag_value, gst_date_time_new_y (year));
3124                 }
3125               } else if (strcmp (gst_tag_name, GST_TAG_GENRE) == 0) {
3126                 guint id3v1_genre_id;
3127                 const gchar *genre_str;
3128
3129                 if (sscanf (value_utf8, "(%u)", &id3v1_genre_id) == 1 &&
3130                     ((genre_str = gst_tag_id3_genre_get (id3v1_genre_id)))) {
3131                   GST_DEBUG ("Genre: %s -> %s", value_utf8, genre_str);
3132                   g_free (value_utf8);
3133                   value_utf8 = g_strdup (genre_str);
3134                 }
3135               } else {
3136                 GType tag_type;
3137
3138                 /* convert tag from string to other type if required */
3139                 tag_type = gst_tag_get_type (gst_tag_name);
3140                 g_value_init (&tag_value, tag_type);
3141                 if (!gst_value_deserialize (&tag_value, value_utf8)) {
3142                   GValue from_val = { 0, };
3143
3144                   g_value_init (&from_val, G_TYPE_STRING);
3145                   g_value_set_string (&from_val, value_utf8);
3146                   if (!g_value_transform (&from_val, &tag_value)) {
3147                     GST_WARNING_OBJECT (demux,
3148                         "Could not transform string tag to " "%s tag type %s",
3149                         gst_tag_name, g_type_name (tag_type));
3150                     g_value_unset (&tag_value);
3151                   }
3152                   g_value_unset (&from_val);
3153                 }
3154               }
3155             } else {
3156               /* metadata ! */
3157               GST_DEBUG ("Setting metadata");
3158               g_value_init (&tag_value, G_TYPE_STRING);
3159               g_value_set_string (&tag_value, value_utf8);
3160               /* If we found a stereoscopic marker, look for StereoscopicLayout
3161                * metadata */
3162               if (content3D) {
3163                 guint i;
3164                 if (strncmp ("StereoscopicLayout", name_utf8,
3165                         strlen (name_utf8)) == 0) {
3166                   for (i = 0; i < G_N_ELEMENTS (stereoscopic_layout_map); i++) {
3167                     if (g_str_equal (stereoscopic_layout_map[i].interleave_name,
3168                             value_utf8)) {
3169                       demux->asf_3D_mode =
3170                           stereoscopic_layout_map[i].interleaving_type;
3171                       GST_INFO ("find interleave type %u", demux->asf_3D_mode);
3172                     }
3173                   }
3174                 }
3175                 GST_INFO_OBJECT (demux, "3d type is %u", demux->asf_3D_mode);
3176               } else {
3177                 demux->asf_3D_mode = GST_ASF_3D_NONE;
3178                 GST_INFO_OBJECT (demux, "None 3d type");
3179               }
3180             }
3181           } else if (value_utf8 == NULL) {
3182             GST_WARNING ("Failed to convert string value to UTF8, skipping");
3183           } else {
3184             GST_DEBUG ("Skipping empty string value for %s",
3185                 GST_STR_NULL (gst_tag_name));
3186           }
3187           g_free (value_utf8);
3188           break;
3189         }
3190         case ASF_DEMUX_DATA_TYPE_BYTE_ARRAY:{
3191           if (gst_tag_name) {
3192             if (!g_str_equal (gst_tag_name, GST_TAG_IMAGE)) {
3193               GST_FIXME ("Unhandled byte array tag %s",
3194                   GST_STR_NULL (gst_tag_name));
3195               break;
3196             } else {
3197               asf_demux_parse_picture_tag (taglist, (guint8 *) value,
3198                   value_len);
3199             }
3200           }
3201           break;
3202         }
3203         case ASF_DEMUX_DATA_TYPE_DWORD:{
3204           guint uint_val = GST_READ_UINT32_LE (value);
3205
3206           /* this is the track number */
3207           g_value_init (&tag_value, G_TYPE_UINT);
3208
3209           /* WM/Track counts from 0 */
3210           if (!strcmp (name_utf8, "WM/Track"))
3211             ++uint_val;
3212
3213           g_value_set_uint (&tag_value, uint_val);
3214           break;
3215         }
3216           /* Detect 3D */
3217         case ASF_DEMUX_DATA_TYPE_BOOL:{
3218           gboolean bool_val = GST_READ_UINT32_LE (value);
3219
3220           if (strncmp ("Stereoscopic", name_utf8, strlen (name_utf8)) == 0) {
3221             if (bool_val) {
3222               GST_INFO_OBJECT (demux, "This is 3D contents");
3223               content3D = TRUE;
3224             } else {
3225               GST_INFO_OBJECT (demux, "This is not 3D contenst");
3226               content3D = FALSE;
3227             }
3228           }
3229
3230           break;
3231         }
3232         default:{
3233           GST_DEBUG ("Skipping tag %s of type %d", gst_tag_name, datatype);
3234           break;
3235         }
3236       }
3237
3238       if (G_IS_VALUE (&tag_value)) {
3239         if (gst_tag_name) {
3240           GstTagMergeMode merge_mode = GST_TAG_MERGE_APPEND;
3241
3242           /* WM/TrackNumber is more reliable than WM/Track, since the latter
3243            * is supposed to have a 0 base but is often wrongly written to start
3244            * from 1 as well, so prefer WM/TrackNumber when we have it: either
3245            * replace the value added earlier from WM/Track or put it first in
3246            * the list, so that it will get picked up by _get_uint() */
3247           if (strcmp (name_utf8, "WM/TrackNumber") == 0)
3248             merge_mode = GST_TAG_MERGE_REPLACE;
3249
3250           gst_tag_list_add_values (taglist, merge_mode, gst_tag_name,
3251               &tag_value, NULL);
3252         } else {
3253           GST_DEBUG ("Setting global metadata %s", name_utf8);
3254           gst_structure_set_value (demux->global_metadata, name_utf8,
3255               &tag_value);
3256         }
3257
3258         g_value_unset (&tag_value);
3259       }
3260     }
3261
3262     g_free (name);
3263     g_free (value);
3264     g_free (name_utf8);
3265   }
3266
3267   gst_asf_demux_add_global_tags (demux, taglist);
3268
3269   return GST_FLOW_OK;
3270
3271   /* Errors */
3272 not_enough_data:
3273   {
3274     GST_WARNING ("Unexpected end of data parsing ext content desc object");
3275     gst_tag_list_unref (taglist);
3276     return GST_FLOW_OK;         /* not really fatal */
3277   }
3278 }
3279
3280 static GstStructure *
3281 gst_asf_demux_get_metadata_for_stream (GstASFDemux * demux, guint stream_num)
3282 {
3283   gchar sname[32];
3284   guint i;
3285
3286   g_snprintf (sname, sizeof (sname), "stream-%u", stream_num);
3287
3288   for (i = 0; i < gst_caps_get_size (demux->metadata); ++i) {
3289     GstStructure *s;
3290
3291     s = gst_caps_get_structure (demux->metadata, i);
3292     if (gst_structure_has_name (s, sname))
3293       return s;
3294   }
3295
3296   gst_caps_append_structure (demux->metadata, gst_structure_new_empty (sname));
3297
3298   /* try lookup again; demux->metadata took ownership of the structure, so we
3299    * can't really make any assumptions about what happened to it, so we can't
3300    * just return it directly after appending it */
3301   return gst_asf_demux_get_metadata_for_stream (demux, stream_num);
3302 }
3303
3304 static GstFlowReturn
3305 gst_asf_demux_process_metadata (GstASFDemux * demux, guint8 * data,
3306     guint64 size)
3307 {
3308   guint16 blockcount, i;
3309
3310   GST_INFO_OBJECT (demux, "object is a metadata object");
3311
3312   /* Content Descriptor Count */
3313   if (size < 2)
3314     goto not_enough_data;
3315
3316   blockcount = gst_asf_demux_get_uint16 (&data, &size);
3317
3318   for (i = 0; i < blockcount; ++i) {
3319     GstStructure *s;
3320     guint16 stream_num, name_len, data_type, lang_idx G_GNUC_UNUSED;
3321     guint32 data_len, ival;
3322     gchar *name_utf8;
3323
3324     if (size < (2 + 2 + 2 + 2 + 4))
3325       goto not_enough_data;
3326
3327     lang_idx = gst_asf_demux_get_uint16 (&data, &size);
3328     stream_num = gst_asf_demux_get_uint16 (&data, &size);
3329     name_len = gst_asf_demux_get_uint16 (&data, &size);
3330     data_type = gst_asf_demux_get_uint16 (&data, &size);
3331     data_len = gst_asf_demux_get_uint32 (&data, &size);
3332
3333     if (size < name_len + data_len)
3334       goto not_enough_data;
3335
3336     /* convert name to UTF-8 */
3337     name_utf8 = g_convert ((gchar *) data, name_len, "UTF-8", "UTF-16LE",
3338         NULL, NULL, NULL);
3339     gst_asf_demux_skip_bytes (name_len, &data, &size);
3340
3341     if (name_utf8 == NULL) {
3342       GST_WARNING ("Failed to convert value name to UTF8, skipping");
3343       gst_asf_demux_skip_bytes (data_len, &data, &size);
3344       continue;
3345     }
3346
3347     if (data_type != ASF_DEMUX_DATA_TYPE_DWORD) {
3348       gst_asf_demux_skip_bytes (data_len, &data, &size);
3349       g_free (name_utf8);
3350       continue;
3351     }
3352
3353     /* read DWORD */
3354     if (size < 4) {
3355       g_free (name_utf8);
3356       goto not_enough_data;
3357     }
3358
3359     ival = gst_asf_demux_get_uint32 (&data, &size);
3360
3361     /* skip anything else there may be, just in case */
3362     gst_asf_demux_skip_bytes (data_len - 4, &data, &size);
3363
3364     s = gst_asf_demux_get_metadata_for_stream (demux, stream_num);
3365     gst_structure_set (s, name_utf8, G_TYPE_INT, ival, NULL);
3366     g_free (name_utf8);
3367   }
3368
3369   GST_INFO_OBJECT (demux, "metadata = %" GST_PTR_FORMAT, demux->metadata);
3370   return GST_FLOW_OK;
3371
3372   /* Errors */
3373 not_enough_data:
3374   {
3375     GST_WARNING ("Unexpected end of data parsing metadata object");
3376     return GST_FLOW_OK;         /* not really fatal */
3377   }
3378 }
3379
3380 static GstFlowReturn
3381 gst_asf_demux_process_header (GstASFDemux * demux, guint8 * data, guint64 size)
3382 {
3383   GstFlowReturn ret = GST_FLOW_OK;
3384   guint32 i, num_objects;
3385   guint8 unknown G_GNUC_UNUSED;
3386
3387   /* Get the rest of the header's header */
3388   if (size < (4 + 1 + 1))
3389     goto not_enough_data;
3390
3391   num_objects = gst_asf_demux_get_uint32 (&data, &size);
3392   unknown = gst_asf_demux_get_uint8 (&data, &size);
3393   unknown = gst_asf_demux_get_uint8 (&data, &size);
3394
3395   GST_INFO_OBJECT (demux, "object is a header with %u parts", num_objects);
3396
3397   /* Loop through the header's objects, processing those */
3398   for (i = 0; i < num_objects; ++i) {
3399     GST_INFO_OBJECT (demux, "reading header part %u", i);
3400     ret = gst_asf_demux_process_object (demux, &data, &size);
3401     if (ret != GST_FLOW_OK) {
3402       GST_WARNING ("process_object returned %s", gst_asf_get_flow_name (ret));
3403       break;
3404     }
3405   }
3406
3407   return ret;
3408
3409 not_enough_data:
3410   {
3411     GST_ELEMENT_ERROR (demux, STREAM, DEMUX, (NULL),
3412         ("short read parsing HEADER object"));
3413     return GST_FLOW_ERROR;
3414   }
3415 }
3416
3417 static GstFlowReturn
3418 gst_asf_demux_process_file (GstASFDemux * demux, guint8 * data, guint64 size)
3419 {
3420   guint64 creation_time G_GNUC_UNUSED;
3421   guint64 file_size G_GNUC_UNUSED;
3422   guint64 send_time G_GNUC_UNUSED;
3423   guint64 packets_count, play_time, preroll;
3424   guint32 flags, min_pktsize, max_pktsize, min_bitrate G_GNUC_UNUSED;
3425
3426   if (size < (16 + 8 + 8 + 8 + 8 + 8 + 8 + 4 + 4 + 4 + 4))
3427     goto not_enough_data;
3428
3429   gst_asf_demux_skip_bytes (16, &data, &size);  /* skip GUID */
3430   file_size = gst_asf_demux_get_uint64 (&data, &size);
3431   creation_time = gst_asf_demux_get_uint64 (&data, &size);
3432   packets_count = gst_asf_demux_get_uint64 (&data, &size);
3433   play_time = gst_asf_demux_get_uint64 (&data, &size);
3434   send_time = gst_asf_demux_get_uint64 (&data, &size);
3435   preroll = gst_asf_demux_get_uint64 (&data, &size);
3436   flags = gst_asf_demux_get_uint32 (&data, &size);
3437   min_pktsize = gst_asf_demux_get_uint32 (&data, &size);
3438   max_pktsize = gst_asf_demux_get_uint32 (&data, &size);
3439   min_bitrate = gst_asf_demux_get_uint32 (&data, &size);
3440
3441   demux->broadcast = ! !(flags & 0x01);
3442   demux->seekable = ! !(flags & 0x02);
3443
3444   GST_DEBUG_OBJECT (demux, "min_pktsize = %u", min_pktsize);
3445   GST_DEBUG_OBJECT (demux, "flags::broadcast = %d", demux->broadcast);
3446   GST_DEBUG_OBJECT (demux, "flags::seekable  = %d", demux->seekable);
3447
3448   if (demux->broadcast) {
3449     /* these fields are invalid if the broadcast flag is set */
3450     play_time = 0;
3451     file_size = 0;
3452   }
3453
3454   if (min_pktsize != max_pktsize)
3455     goto non_fixed_packet_size;
3456
3457   demux->packet_size = max_pktsize;
3458
3459   /* FIXME: do we need send_time as well? what is it? */
3460   if ((play_time * 100) >= (preroll * GST_MSECOND))
3461     demux->play_time = (play_time * 100) - (preroll * GST_MSECOND);
3462   else
3463     demux->play_time = 0;
3464
3465   demux->preroll = preroll * GST_MSECOND;
3466
3467   /* initial latency */
3468   demux->latency = demux->preroll;
3469
3470   if (demux->play_time == 0)
3471     demux->seekable = FALSE;
3472
3473   GST_DEBUG_OBJECT (demux, "play_time %" GST_TIME_FORMAT,
3474       GST_TIME_ARGS (demux->play_time));
3475   GST_DEBUG_OBJECT (demux, "preroll   %" GST_TIME_FORMAT,
3476       GST_TIME_ARGS (demux->preroll));
3477
3478   if (demux->play_time > 0) {
3479     demux->segment.duration = demux->play_time;
3480   }
3481
3482   GST_INFO ("object is a file with %" G_GUINT64_FORMAT " data packets",
3483       packets_count);
3484   GST_INFO ("preroll = %" G_GUINT64_FORMAT, demux->preroll);
3485
3486   return GST_FLOW_OK;
3487
3488 /* ERRORS */
3489 non_fixed_packet_size:
3490   {
3491     GST_ELEMENT_ERROR (demux, STREAM, DEMUX, (NULL),
3492         ("packet size must be fixed"));
3493     return GST_FLOW_ERROR;
3494   }
3495 not_enough_data:
3496   {
3497     GST_ELEMENT_ERROR (demux, STREAM, DEMUX, (NULL),
3498         ("short read parsing FILE object"));
3499     return GST_FLOW_ERROR;
3500   }
3501 }
3502
3503 /* Content Description Object */
3504 static GstFlowReturn
3505 gst_asf_demux_process_comment (GstASFDemux * demux, guint8 * data, guint64 size)
3506 {
3507   struct
3508   {
3509     const gchar *gst_tag;
3510     guint16 val_length;
3511     gchar *val_utf8;
3512   } tags[5] = {
3513     {
3514     GST_TAG_TITLE, 0, NULL}, {
3515     GST_TAG_ARTIST, 0, NULL}, {
3516     GST_TAG_COPYRIGHT, 0, NULL}, {
3517     GST_TAG_DESCRIPTION, 0, NULL}, {
3518     GST_TAG_COMMENT, 0, NULL}
3519   };
3520   GstTagList *taglist;
3521   GValue value = { 0 };
3522   gsize in, out;
3523   gint i = -1;
3524
3525   GST_INFO_OBJECT (demux, "object is a comment");
3526
3527   if (size < (2 + 2 + 2 + 2 + 2))
3528     goto not_enough_data;
3529
3530   tags[0].val_length = gst_asf_demux_get_uint16 (&data, &size);
3531   tags[1].val_length = gst_asf_demux_get_uint16 (&data, &size);
3532   tags[2].val_length = gst_asf_demux_get_uint16 (&data, &size);
3533   tags[3].val_length = gst_asf_demux_get_uint16 (&data, &size);
3534   tags[4].val_length = gst_asf_demux_get_uint16 (&data, &size);
3535
3536   GST_DEBUG_OBJECT (demux, "Comment lengths: title=%d author=%d copyright=%d "
3537       "description=%d rating=%d", tags[0].val_length, tags[1].val_length,
3538       tags[2].val_length, tags[3].val_length, tags[4].val_length);
3539
3540   for (i = 0; i < G_N_ELEMENTS (tags); ++i) {
3541     if (size < tags[i].val_length)
3542       goto not_enough_data;
3543
3544     /* might be just '/0', '/0'... */
3545     if (tags[i].val_length > 2 && tags[i].val_length % 2 == 0) {
3546       /* convert to UTF-8 */
3547       tags[i].val_utf8 = g_convert ((gchar *) data, tags[i].val_length,
3548           "UTF-8", "UTF-16LE", &in, &out, NULL);
3549     }
3550     gst_asf_demux_skip_bytes (tags[i].val_length, &data, &size);
3551   }
3552
3553   /* parse metadata into taglist */
3554   taglist = gst_tag_list_new_empty ();
3555   g_value_init (&value, G_TYPE_STRING);
3556   for (i = 0; i < G_N_ELEMENTS (tags); ++i) {
3557     if (tags[i].val_utf8 && strlen (tags[i].val_utf8) > 0 && tags[i].gst_tag) {
3558       g_value_set_string (&value, tags[i].val_utf8);
3559       gst_tag_list_add_values (taglist, GST_TAG_MERGE_APPEND,
3560           tags[i].gst_tag, &value, NULL);
3561     }
3562   }
3563   g_value_unset (&value);
3564
3565   gst_asf_demux_add_global_tags (demux, taglist);
3566
3567   for (i = 0; i < G_N_ELEMENTS (tags); ++i)
3568     g_free (tags[i].val_utf8);
3569
3570   return GST_FLOW_OK;
3571
3572 not_enough_data:
3573   {
3574     GST_WARNING_OBJECT (demux, "unexpectedly short of data while processing "
3575         "comment tag section %d, skipping comment object", i);
3576     for (i = 0; i < G_N_ELEMENTS (tags); i++)
3577       g_free (tags[i].val_utf8);
3578     return GST_FLOW_OK;         /* not really fatal */
3579   }
3580 }
3581
3582 static GstFlowReturn
3583 gst_asf_demux_process_bitrate_props_object (GstASFDemux * demux, guint8 * data,
3584     guint64 size)
3585 {
3586   guint16 num_streams, i;
3587   AsfStream *stream;
3588
3589   if (size < 2)
3590     goto not_enough_data;
3591
3592   num_streams = gst_asf_demux_get_uint16 (&data, &size);
3593
3594   GST_INFO ("object is a bitrate properties object with %u streams",
3595       num_streams);
3596
3597   if (size < (num_streams * (2 + 4)))
3598     goto not_enough_data;
3599
3600   for (i = 0; i < num_streams; ++i) {
3601     guint32 bitrate;
3602     guint16 stream_id;
3603
3604     stream_id = gst_asf_demux_get_uint16 (&data, &size);
3605     bitrate = gst_asf_demux_get_uint32 (&data, &size);
3606
3607     if (stream_id < GST_ASF_DEMUX_NUM_STREAM_IDS) {
3608       GST_DEBUG_OBJECT (demux, "bitrate of stream %u = %u", stream_id, bitrate);
3609       stream = gst_asf_demux_get_stream (demux, stream_id);
3610       if (stream) {
3611         if (stream->pending_tags == NULL) {
3612           stream->pending_tags =
3613               gst_tag_list_new (GST_TAG_BITRATE, bitrate, NULL);
3614         }
3615       } else {
3616         GST_WARNING_OBJECT (demux, "Stream id %u wasn't found", stream_id);
3617       }
3618     } else {
3619       GST_WARNING ("stream id %u is too large", stream_id);
3620     }
3621   }
3622
3623   return GST_FLOW_OK;
3624
3625 not_enough_data:
3626   {
3627     GST_WARNING_OBJECT (demux, "short read parsing bitrate props object!");
3628     return GST_FLOW_OK;         /* not really fatal */
3629   }
3630 }
3631
3632 static GstFlowReturn
3633 gst_asf_demux_process_header_ext (GstASFDemux * demux, guint8 * data,
3634     guint64 size)
3635 {
3636   GstFlowReturn ret = GST_FLOW_OK;
3637   guint64 hdr_size;
3638
3639   /* Get the rest of the header's header */
3640   if (size < (16 + 2 + 4))
3641     goto not_enough_data;
3642
3643   /* skip GUID and two other bytes */
3644   gst_asf_demux_skip_bytes (16 + 2, &data, &size);
3645   hdr_size = gst_asf_demux_get_uint32 (&data, &size);
3646
3647   GST_INFO ("extended header object with a size of %u bytes", (guint) size);
3648
3649   /* FIXME: does data_size include the rest of the header that we have read? */
3650   if (hdr_size > size)
3651     goto not_enough_data;
3652
3653   while (hdr_size > 0) {
3654     ret = gst_asf_demux_process_object (demux, &data, &hdr_size);
3655     if (ret != GST_FLOW_OK)
3656       break;
3657   }
3658
3659   return ret;
3660
3661 not_enough_data:
3662   {
3663     GST_ELEMENT_ERROR (demux, STREAM, DEMUX, (NULL),
3664         ("short read parsing extended header object"));
3665     return GST_FLOW_ERROR;
3666   }
3667 }
3668
3669 static GstFlowReturn
3670 gst_asf_demux_process_language_list (GstASFDemux * demux, guint8 * data,
3671     guint64 size)
3672 {
3673   guint i;
3674
3675   if (size < 2)
3676     goto not_enough_data;
3677
3678   if (demux->languages) {
3679     GST_WARNING ("More than one LANGUAGE_LIST object in stream");
3680     g_strfreev (demux->languages);
3681     demux->languages = NULL;
3682     demux->num_languages = 0;
3683   }
3684
3685   demux->num_languages = gst_asf_demux_get_uint16 (&data, &size);
3686   GST_LOG ("%u languages:", demux->num_languages);
3687
3688   demux->languages = g_new0 (gchar *, demux->num_languages + 1);
3689   for (i = 0; i < demux->num_languages; ++i) {
3690     guint8 len, *lang_data = NULL;
3691
3692     if (size < 1)
3693       goto not_enough_data;
3694     len = gst_asf_demux_get_uint8 (&data, &size);
3695     if (gst_asf_demux_get_bytes (&lang_data, len, &data, &size)) {
3696       gchar *utf8;
3697
3698       utf8 = g_convert ((gchar *) lang_data, len, "UTF-8", "UTF-16LE", NULL,
3699           NULL, NULL);
3700
3701       /* truncate "en-us" etc. to just "en" */
3702       if (utf8 && strlen (utf8) >= 5 && (utf8[2] == '-' || utf8[2] == '_')) {
3703         utf8[2] = '\0';
3704       }
3705       GST_DEBUG ("[%u] %s", i, GST_STR_NULL (utf8));
3706       demux->languages[i] = utf8;
3707       g_free (lang_data);
3708     } else {
3709       goto not_enough_data;
3710     }
3711   }
3712
3713   return GST_FLOW_OK;
3714
3715 not_enough_data:
3716   {
3717     GST_WARNING_OBJECT (demux, "short read parsing language list object!");
3718     g_free (demux->languages);
3719     demux->languages = NULL;
3720     return GST_FLOW_OK;         /* not fatal */
3721   }
3722 }
3723
3724 static GstFlowReturn
3725 gst_asf_demux_process_simple_index (GstASFDemux * demux, guint8 * data,
3726     guint64 size)
3727 {
3728   GstClockTime interval;
3729   guint32 count, i;
3730
3731   if (size < (16 + 8 + 4 + 4))
3732     goto not_enough_data;
3733
3734   /* skip file id */
3735   gst_asf_demux_skip_bytes (16, &data, &size);
3736   interval = gst_asf_demux_get_uint64 (&data, &size) * (GstClockTime) 100;
3737   gst_asf_demux_skip_bytes (4, &data, &size);
3738   count = gst_asf_demux_get_uint32 (&data, &size);
3739   if (count > 0) {
3740     demux->sidx_interval = interval;
3741     demux->sidx_num_entries = count;
3742     g_free (demux->sidx_entries);
3743     demux->sidx_entries = g_new0 (AsfSimpleIndexEntry, count);
3744
3745     for (i = 0; i < count; ++i) {
3746       if (G_UNLIKELY (size < 6)) {
3747         /* adjust for broken files, to avoid having entries at the end
3748          * of the parsed index that point to time=0. Resulting in seeking to
3749          * the end of the file leading back to the beginning */
3750         demux->sidx_num_entries -= (count - i);
3751         break;
3752       }
3753       demux->sidx_entries[i].packet = gst_asf_demux_get_uint32 (&data, &size);
3754       demux->sidx_entries[i].count = gst_asf_demux_get_uint16 (&data, &size);
3755       GST_LOG_OBJECT (demux, "%" GST_TIME_FORMAT " = packet %4u  count : %2d",
3756           GST_TIME_ARGS (i * interval), demux->sidx_entries[i].packet,
3757           demux->sidx_entries[i].count);
3758     }
3759   } else {
3760     GST_DEBUG_OBJECT (demux, "simple index object with 0 entries");
3761   }
3762
3763   return GST_FLOW_OK;
3764
3765 not_enough_data:
3766   {
3767     GST_WARNING_OBJECT (demux, "short read parsing simple index object!");
3768     return GST_FLOW_OK;         /* not fatal */
3769   }
3770 }
3771
3772 static GstFlowReturn
3773 gst_asf_demux_process_advanced_mutual_exclusion (GstASFDemux * demux,
3774     guint8 * data, guint64 size)
3775 {
3776   ASFGuid guid;
3777   guint16 num, i;
3778
3779   if (size < 16 + 2 + (2 * 2))
3780     goto not_enough_data;
3781
3782   gst_asf_demux_get_guid (&guid, &data, &size);
3783   num = gst_asf_demux_get_uint16 (&data, &size);
3784
3785   if (num < 2) {
3786     GST_WARNING_OBJECT (demux, "nonsensical mutually exclusive streams count");
3787     return GST_FLOW_OK;
3788   }
3789
3790   if (size < (num * sizeof (guint16)))
3791     goto not_enough_data;
3792
3793   /* read mutually exclusive stream numbers */
3794   for (i = 0; i < num; ++i) {
3795     guint8 mes;
3796     mes = gst_asf_demux_get_uint16 (&data, &size) & 0x7f;
3797     GST_LOG_OBJECT (demux, "mutually exclusive: stream %d", mes);
3798
3799     demux->mut_ex_streams =
3800         g_slist_append (demux->mut_ex_streams, GINT_TO_POINTER (mes));
3801   }
3802
3803
3804   return GST_FLOW_OK;
3805
3806   /* Errors */
3807 not_enough_data:
3808   {
3809     GST_WARNING_OBJECT (demux, "short read parsing advanced mutual exclusion");
3810     return GST_FLOW_OK;         /* not absolutely fatal */
3811   }
3812 }
3813
3814 gboolean
3815 gst_asf_demux_is_unknown_stream (GstASFDemux * demux, guint stream_num)
3816 {
3817   return g_slist_find (demux->other_streams,
3818       GINT_TO_POINTER (stream_num)) == NULL;
3819 }
3820
3821 static GstFlowReturn
3822 gst_asf_demux_process_ext_stream_props (GstASFDemux * demux, guint8 * data,
3823     guint64 size)
3824 {
3825   AsfStreamExtProps esp;
3826   AsfStream *stream = NULL;
3827   AsfObject stream_obj;
3828   guint16 stream_name_count;
3829   guint16 num_payload_ext;
3830   guint64 len;
3831   guint8 *stream_obj_data = NULL;
3832   guint8 *data_start;
3833   guint obj_size;
3834   guint i, stream_num;
3835
3836   data_start = data;
3837   obj_size = (guint) size;
3838
3839   if (size < 64)
3840     goto not_enough_data;
3841
3842   esp.valid = TRUE;
3843   esp.start_time = gst_asf_demux_get_uint64 (&data, &size) * GST_MSECOND;
3844   esp.end_time = gst_asf_demux_get_uint64 (&data, &size) * GST_MSECOND;
3845   esp.data_bitrate = gst_asf_demux_get_uint32 (&data, &size);
3846   esp.buffer_size = gst_asf_demux_get_uint32 (&data, &size);
3847   esp.intial_buf_fullness = gst_asf_demux_get_uint32 (&data, &size);
3848   esp.data_bitrate2 = gst_asf_demux_get_uint32 (&data, &size);
3849   esp.buffer_size2 = gst_asf_demux_get_uint32 (&data, &size);
3850   esp.intial_buf_fullness2 = gst_asf_demux_get_uint32 (&data, &size);
3851   esp.max_obj_size = gst_asf_demux_get_uint32 (&data, &size);
3852   esp.flags = gst_asf_demux_get_uint32 (&data, &size);
3853   stream_num = gst_asf_demux_get_uint16 (&data, &size);
3854   esp.lang_idx = gst_asf_demux_get_uint16 (&data, &size);
3855   esp.avg_time_per_frame = gst_asf_demux_get_uint64 (&data, &size);
3856   stream_name_count = gst_asf_demux_get_uint16 (&data, &size);
3857   num_payload_ext = gst_asf_demux_get_uint16 (&data, &size);
3858
3859   GST_INFO ("start_time             = %" GST_TIME_FORMAT,
3860       GST_TIME_ARGS (esp.start_time));
3861   GST_INFO ("end_time               = %" GST_TIME_FORMAT,
3862       GST_TIME_ARGS (esp.end_time));
3863   GST_INFO ("flags                  = %08x", esp.flags);
3864   GST_INFO ("average time per frame = %" GST_TIME_FORMAT,
3865       GST_TIME_ARGS (esp.avg_time_per_frame * 100));
3866   GST_INFO ("stream number          = %u", stream_num);
3867   GST_INFO ("stream language ID idx = %u (%s)", esp.lang_idx,
3868       (esp.lang_idx < demux->num_languages) ?
3869       GST_STR_NULL (demux->languages[esp.lang_idx]) : "??");
3870   GST_INFO ("stream name count      = %u", stream_name_count);
3871
3872   /* read stream names */
3873   for (i = 0; i < stream_name_count; ++i) {
3874     guint16 stream_lang_idx G_GNUC_UNUSED;
3875     gchar *stream_name = NULL;
3876
3877     if (size < 2)
3878       goto not_enough_data;
3879     stream_lang_idx = gst_asf_demux_get_uint16 (&data, &size);
3880     if (!gst_asf_demux_get_string (&stream_name, NULL, &data, &size))
3881       goto not_enough_data;
3882     GST_INFO ("stream name %d: %s", i, GST_STR_NULL (stream_name));
3883     g_free (stream_name);       /* TODO: store names in struct */
3884   }
3885
3886   /* read payload extension systems stuff */
3887   GST_LOG ("payload extension systems count = %u", num_payload_ext);
3888
3889   if (num_payload_ext > 0)
3890     esp.payload_extensions = g_new0 (AsfPayloadExtension, num_payload_ext + 1);
3891   else
3892     esp.payload_extensions = NULL;
3893
3894   for (i = 0; i < num_payload_ext; ++i) {
3895     AsfPayloadExtension ext;
3896     ASFGuid ext_guid;
3897     guint32 sys_info_len;
3898
3899     if (size < 16 + 2 + 4)
3900       goto not_enough_data;
3901
3902     gst_asf_demux_get_guid (&ext_guid, &data, &size);
3903     ext.id = gst_asf_demux_identify_guid (asf_payload_ext_guids, &ext_guid);
3904     ext.len = gst_asf_demux_get_uint16 (&data, &size);
3905
3906     sys_info_len = gst_asf_demux_get_uint32 (&data, &size);
3907     GST_LOG ("payload systems info len = %u", sys_info_len);
3908     if (!gst_asf_demux_skip_bytes (sys_info_len, &data, &size))
3909       goto not_enough_data;
3910
3911     esp.payload_extensions[i] = ext;
3912   }
3913
3914   GST_LOG ("bytes read: %u/%u", (guint) (data - data_start), obj_size);
3915
3916   /* there might be an optional STREAM_INFO object here now; if not, we
3917    * should have parsed the corresponding stream info object already (since
3918    * we are parsing the extended stream properties objects delayed) */
3919   if (size == 0) {
3920     stream = gst_asf_demux_get_stream (demux, stream_num);
3921     goto done;
3922   }
3923
3924   /* get size of the stream object */
3925   if (!asf_demux_peek_object (demux, data, size, &stream_obj, TRUE))
3926     goto not_enough_data;
3927
3928   if (stream_obj.id != ASF_OBJ_STREAM)
3929     goto expected_stream_object;
3930
3931   if (stream_obj.size < ASF_OBJECT_HEADER_SIZE ||
3932       stream_obj.size > (10 * 1024 * 1024))
3933     goto not_enough_data;
3934
3935   gst_asf_demux_skip_bytes (ASF_OBJECT_HEADER_SIZE, &data, &size);
3936
3937   /* process this stream object later after all the other 'normal' ones
3938    * have been processed (since the others are more important/non-hidden) */
3939   len = stream_obj.size - ASF_OBJECT_HEADER_SIZE;
3940   if (!gst_asf_demux_get_bytes (&stream_obj_data, len, &data, &size))
3941     goto not_enough_data;
3942
3943   /* parse stream object */
3944   stream = gst_asf_demux_parse_stream_object (demux, stream_obj_data, len);
3945   g_free (stream_obj_data);
3946
3947 done:
3948
3949   if (stream) {
3950     stream->ext_props = esp;
3951
3952     /* try to set the framerate */
3953     if (stream->is_video && stream->caps) {
3954       GValue framerate = { 0 };
3955       GstStructure *s;
3956       gint num, denom;
3957
3958       g_value_init (&framerate, GST_TYPE_FRACTION);
3959
3960       num = GST_SECOND / 100;
3961       denom = esp.avg_time_per_frame;
3962       if (denom == 0) {
3963         /* avoid division by 0, assume 25/1 framerate */
3964         denom = GST_SECOND / 2500;
3965       }
3966
3967       gst_value_set_fraction (&framerate, num, denom);
3968
3969       stream->caps = gst_caps_make_writable (stream->caps);
3970       s = gst_caps_get_structure (stream->caps, 0);
3971       gst_structure_set_value (s, "framerate", &framerate);
3972       g_value_unset (&framerate);
3973       GST_DEBUG_OBJECT (demux, "setting framerate of %d/%d = %f",
3974           num, denom, ((gdouble) num) / denom);
3975     }
3976
3977     /* add language info now if we have it */
3978     if (stream->ext_props.lang_idx < demux->num_languages) {
3979       if (stream->pending_tags == NULL)
3980         stream->pending_tags = gst_tag_list_new_empty ();
3981       GST_LOG_OBJECT (demux, "stream %u has language '%s'", stream->id,
3982           demux->languages[stream->ext_props.lang_idx]);
3983       gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_APPEND,
3984           GST_TAG_LANGUAGE_CODE, demux->languages[stream->ext_props.lang_idx],
3985           NULL);
3986     }
3987   } else if (gst_asf_demux_is_unknown_stream (demux, stream_num)) {
3988     GST_WARNING_OBJECT (demux, "Ext. stream properties for unknown stream");
3989   }
3990
3991   return GST_FLOW_OK;
3992
3993   /* Errors */
3994 not_enough_data:
3995   {
3996     GST_WARNING_OBJECT (demux, "short read parsing ext stream props object!");
3997     return GST_FLOW_OK;         /* not absolutely fatal */
3998   }
3999 expected_stream_object:
4000   {
4001     GST_WARNING_OBJECT (demux, "error parsing extended stream properties "
4002         "object: expected embedded stream object, but got %s object instead!",
4003         gst_asf_get_guid_nick (asf_object_guids, stream_obj.id));
4004     return GST_FLOW_OK;         /* not absolutely fatal */
4005   }
4006 }
4007
4008 static const gchar *
4009 gst_asf_demux_push_obj (GstASFDemux * demux, guint32 obj_id)
4010 {
4011   const gchar *nick;
4012
4013   nick = gst_asf_get_guid_nick (asf_object_guids, obj_id);
4014   if (g_str_has_prefix (nick, "ASF_OBJ_"))
4015     nick += strlen ("ASF_OBJ_");
4016
4017   if (demux->objpath == NULL) {
4018     demux->objpath = g_strdup (nick);
4019   } else {
4020     gchar *newpath;
4021
4022     newpath = g_strdup_printf ("%s/%s", demux->objpath, nick);
4023     g_free (demux->objpath);
4024     demux->objpath = newpath;
4025   }
4026
4027   return (const gchar *) demux->objpath;
4028 }
4029
4030 static void
4031 gst_asf_demux_pop_obj (GstASFDemux * demux)
4032 {
4033   gchar *s;
4034
4035   if ((s = g_strrstr (demux->objpath, "/"))) {
4036     *s = '\0';
4037   } else {
4038     g_free (demux->objpath);
4039     demux->objpath = NULL;
4040   }
4041 }
4042
4043 static void
4044 gst_asf_demux_process_queued_extended_stream_objects (GstASFDemux * demux)
4045 {
4046   GSList *l;
4047   guint i;
4048
4049   /* Parse the queued extended stream property objects and add the info
4050    * to the existing streams or add the new embedded streams, but without
4051    * activating them yet */
4052   GST_LOG_OBJECT (demux, "%u queued extended stream properties objects",
4053       g_slist_length (demux->ext_stream_props));
4054
4055   for (l = demux->ext_stream_props, i = 0; l != NULL; l = l->next, ++i) {
4056     GstBuffer *buf = GST_BUFFER (l->data);
4057     GstMapInfo map;
4058
4059     gst_buffer_map (buf, &map, GST_MAP_READ);
4060
4061     GST_LOG_OBJECT (demux, "parsing ext. stream properties object #%u", i);
4062     gst_asf_demux_process_ext_stream_props (demux, map.data, map.size);
4063     gst_buffer_unmap (buf, &map);
4064     gst_buffer_unref (buf);
4065   }
4066   g_slist_free (demux->ext_stream_props);
4067   demux->ext_stream_props = NULL;
4068 }
4069
4070 #if 0
4071 static void
4072 gst_asf_demux_activate_ext_props_streams (GstASFDemux * demux)
4073 {
4074   guint i, j;
4075
4076   for (i = 0; i < demux->num_streams; ++i) {
4077     AsfStream *stream;
4078     gboolean is_hidden;
4079     GSList *x;
4080
4081     stream = &demux->stream[i];
4082
4083     GST_LOG_OBJECT (demux, "checking  stream %2u", stream->id);
4084
4085     if (stream->active) {
4086       GST_LOG_OBJECT (demux, "stream %2u is already activated", stream->id);
4087       continue;
4088     }
4089
4090     is_hidden = FALSE;
4091     for (x = demux->mut_ex_streams; x != NULL; x = x->next) {
4092       guint8 *mes;
4093
4094       /* check for each mutual exclusion whether it affects this stream */
4095       for (mes = (guint8 *) x->data; mes != NULL && *mes != 0xff; ++mes) {
4096         if (*mes == stream->id) {
4097           /* if yes, check if we've already added streams that are mutually
4098            * exclusive with the stream we're about to add */
4099           for (mes = (guint8 *) x->data; mes != NULL && *mes != 0xff; ++mes) {
4100             for (j = 0; j < demux->num_streams; ++j) {
4101               /* if the broadcast flag is set, assume the hidden streams aren't
4102                * actually streamed and hide them (or playbin won't work right),
4103                * otherwise assume their data is available */
4104               if (demux->stream[j].id == *mes && demux->broadcast) {
4105                 is_hidden = TRUE;
4106                 GST_LOG_OBJECT (demux, "broadcast stream ID %d to be added is "
4107                     "mutually exclusive with already existing stream ID %d, "
4108                     "hiding stream", stream->id, demux->stream[j].id);
4109                 goto next;
4110               }
4111             }
4112           }
4113           break;
4114         }
4115       }
4116     }
4117
4118   next:
4119
4120     /* FIXME: we should do stream activation based on preroll data in
4121      * streaming mode too */
4122     if (demux->streaming && !is_hidden)
4123       gst_asf_demux_activate_stream (demux, stream);
4124   }
4125 }
4126 #endif
4127
4128 static GstFlowReturn
4129 gst_asf_demux_process_object (GstASFDemux * demux, guint8 ** p_data,
4130     guint64 * p_size)
4131 {
4132   GstFlowReturn ret = GST_FLOW_OK;
4133   AsfObject obj;
4134   guint64 obj_data_size;
4135
4136   if (*p_size < ASF_OBJECT_HEADER_SIZE)
4137     return ASF_FLOW_NEED_MORE_DATA;
4138
4139   asf_demux_peek_object (demux, *p_data, ASF_OBJECT_HEADER_SIZE, &obj, TRUE);
4140   gst_asf_demux_skip_bytes (ASF_OBJECT_HEADER_SIZE, p_data, p_size);
4141
4142   obj_data_size = obj.size - ASF_OBJECT_HEADER_SIZE;
4143
4144   if (*p_size < obj_data_size)
4145     return ASF_FLOW_NEED_MORE_DATA;
4146
4147   gst_asf_demux_push_obj (demux, obj.id);
4148
4149   GST_INFO ("%s: size %" G_GUINT64_FORMAT, demux->objpath, obj.size);
4150
4151   switch (obj.id) {
4152     case ASF_OBJ_STREAM:
4153       gst_asf_demux_parse_stream_object (demux, *p_data, obj_data_size);
4154       ret = GST_FLOW_OK;
4155       break;
4156     case ASF_OBJ_FILE:
4157       ret = gst_asf_demux_process_file (demux, *p_data, obj_data_size);
4158       break;
4159     case ASF_OBJ_HEADER:
4160       ret = gst_asf_demux_process_header (demux, *p_data, obj_data_size);
4161       break;
4162     case ASF_OBJ_COMMENT:
4163       ret = gst_asf_demux_process_comment (demux, *p_data, obj_data_size);
4164       break;
4165     case ASF_OBJ_HEAD1:
4166       ret = gst_asf_demux_process_header_ext (demux, *p_data, obj_data_size);
4167       break;
4168     case ASF_OBJ_BITRATE_PROPS:
4169       ret =
4170           gst_asf_demux_process_bitrate_props_object (demux, *p_data,
4171           obj_data_size);
4172       break;
4173     case ASF_OBJ_EXT_CONTENT_DESC:
4174       ret =
4175           gst_asf_demux_process_ext_content_desc (demux, *p_data,
4176           obj_data_size);
4177       break;
4178     case ASF_OBJ_METADATA_OBJECT:
4179       ret = gst_asf_demux_process_metadata (demux, *p_data, obj_data_size);
4180       break;
4181     case ASF_OBJ_EXTENDED_STREAM_PROPS:{
4182       GstBuffer *buf;
4183
4184       /* process these later, we might not have parsed the corresponding
4185        * stream object yet */
4186       GST_LOG ("%s: queued for later parsing", demux->objpath);
4187       buf = gst_buffer_new_and_alloc (obj_data_size);
4188       gst_buffer_fill (buf, 0, *p_data, obj_data_size);
4189       demux->ext_stream_props = g_slist_append (demux->ext_stream_props, buf);
4190       ret = GST_FLOW_OK;
4191       break;
4192     }
4193     case ASF_OBJ_LANGUAGE_LIST:
4194       ret = gst_asf_demux_process_language_list (demux, *p_data, obj_data_size);
4195       break;
4196     case ASF_OBJ_ADVANCED_MUTUAL_EXCLUSION:
4197       ret = gst_asf_demux_process_advanced_mutual_exclusion (demux, *p_data,
4198           obj_data_size);
4199       break;
4200     case ASF_OBJ_SIMPLE_INDEX:
4201       ret = gst_asf_demux_process_simple_index (demux, *p_data, obj_data_size);
4202       break;
4203     case ASF_OBJ_CONTENT_ENCRYPTION:
4204     case ASF_OBJ_EXT_CONTENT_ENCRYPTION:
4205     case ASF_OBJ_DIGITAL_SIGNATURE_OBJECT:
4206     case ASF_OBJ_UNKNOWN_ENCRYPTION_OBJECT:
4207       goto error_encrypted;
4208     case ASF_OBJ_CONCEAL_NONE:
4209     case ASF_OBJ_HEAD2:
4210     case ASF_OBJ_UNDEFINED:
4211     case ASF_OBJ_CODEC_COMMENT:
4212     case ASF_OBJ_INDEX:
4213     case ASF_OBJ_PADDING:
4214     case ASF_OBJ_BITRATE_MUTEX:
4215     case ASF_OBJ_COMPATIBILITY:
4216     case ASF_OBJ_INDEX_PLACEHOLDER:
4217     case ASF_OBJ_INDEX_PARAMETERS:
4218     case ASF_OBJ_STREAM_PRIORITIZATION:
4219     case ASF_OBJ_SCRIPT_COMMAND:
4220     case ASF_OBJ_METADATA_LIBRARY_OBJECT:
4221     default:
4222       /* Unknown/unhandled object, skip it and hope for the best */
4223       GST_INFO ("%s: skipping object", demux->objpath);
4224       ret = GST_FLOW_OK;
4225       break;
4226   }
4227
4228   /* this can't fail, we checked the number of bytes available before */
4229   gst_asf_demux_skip_bytes (obj_data_size, p_data, p_size);
4230
4231   GST_LOG ("%s: ret = %s", demux->objpath, gst_asf_get_flow_name (ret));
4232
4233   gst_asf_demux_pop_obj (demux);
4234
4235   return ret;
4236
4237 /* ERRORS */
4238 error_encrypted:
4239   {
4240     GST_ELEMENT_ERROR (demux, STREAM, DECRYPT, (NULL), (NULL));
4241     return GST_FLOW_ERROR;
4242   }
4243 }
4244
4245 static void
4246 gst_asf_demux_descramble_buffer (GstASFDemux * demux, AsfStream * stream,
4247     GstBuffer ** p_buffer)
4248 {
4249   GstBuffer *descrambled_buffer;
4250   GstBuffer *scrambled_buffer;
4251   GstBuffer *sub_buffer;
4252   guint offset;
4253   guint off;
4254   guint row;
4255   guint col;
4256   guint idx;
4257
4258   /* descrambled_buffer is initialised in the first iteration */
4259   descrambled_buffer = NULL;
4260   scrambled_buffer = *p_buffer;
4261
4262   if (gst_buffer_get_size (scrambled_buffer) <
4263       stream->ds_packet_size * stream->span)
4264     return;
4265
4266   for (offset = 0; offset < gst_buffer_get_size (scrambled_buffer);
4267       offset += stream->ds_chunk_size) {
4268     off = offset / stream->ds_chunk_size;
4269     row = off / stream->span;
4270     col = off % stream->span;
4271     idx = row + col * stream->ds_packet_size / stream->ds_chunk_size;
4272     GST_DEBUG ("idx=%u, row=%u, col=%u, off=%u, ds_chunk_size=%u", idx, row,
4273         col, off, stream->ds_chunk_size);
4274     GST_DEBUG ("scrambled buffer size=%" G_GSIZE_FORMAT
4275         ", span=%u, packet_size=%u", gst_buffer_get_size (scrambled_buffer),
4276         stream->span, stream->ds_packet_size);
4277     GST_DEBUG ("gst_buffer_get_size (scrambled_buffer) = %" G_GSIZE_FORMAT,
4278         gst_buffer_get_size (scrambled_buffer));
4279     sub_buffer =
4280         gst_buffer_copy_region (scrambled_buffer, GST_BUFFER_COPY_MEMORY,
4281         idx * stream->ds_chunk_size, stream->ds_chunk_size);
4282     if (!offset) {
4283       descrambled_buffer = sub_buffer;
4284     } else {
4285       descrambled_buffer = gst_buffer_append (descrambled_buffer, sub_buffer);
4286     }
4287   }
4288
4289   GST_BUFFER_TIMESTAMP (descrambled_buffer) =
4290       GST_BUFFER_TIMESTAMP (scrambled_buffer);
4291   GST_BUFFER_DURATION (descrambled_buffer) =
4292       GST_BUFFER_DURATION (scrambled_buffer);
4293   GST_BUFFER_OFFSET (descrambled_buffer) = GST_BUFFER_OFFSET (scrambled_buffer);
4294   GST_BUFFER_OFFSET_END (descrambled_buffer) =
4295       GST_BUFFER_OFFSET_END (scrambled_buffer);
4296
4297   /* FIXME/CHECK: do we need to transfer buffer flags here too? */
4298
4299   gst_buffer_unref (scrambled_buffer);
4300   *p_buffer = descrambled_buffer;
4301 }
4302
4303 static gboolean
4304 gst_asf_demux_element_send_event (GstElement * element, GstEvent * event)
4305 {
4306   GstASFDemux *demux = GST_ASF_DEMUX (element);
4307   gint i;
4308
4309   GST_DEBUG ("handling element event of type %s", GST_EVENT_TYPE_NAME (event));
4310
4311   for (i = 0; i < demux->num_streams; ++i) {
4312     gst_event_ref (event);
4313     if (gst_asf_demux_handle_src_event (demux->stream[i].pad,
4314             GST_OBJECT_CAST (element), event)) {
4315       gst_event_unref (event);
4316       return TRUE;
4317     }
4318   }
4319
4320   gst_event_unref (event);
4321   return FALSE;
4322 }
4323
4324 /* takes ownership of the passed event */
4325 static gboolean
4326 gst_asf_demux_send_event_unlocked (GstASFDemux * demux, GstEvent * event)
4327 {
4328   gboolean ret = TRUE;
4329   gint i;
4330
4331   GST_DEBUG_OBJECT (demux, "sending %s event to all source pads",
4332       GST_EVENT_TYPE_NAME (event));
4333
4334   for (i = 0; i < demux->num_streams; ++i) {
4335     gst_event_ref (event);
4336     ret &= gst_pad_push_event (demux->stream[i].pad, event);
4337   }
4338   gst_event_unref (event);
4339   return ret;
4340 }
4341
4342 static gboolean
4343 gst_asf_demux_handle_src_query (GstPad * pad, GstObject * parent,
4344     GstQuery * query)
4345 {
4346   GstASFDemux *demux;
4347   gboolean res = FALSE;
4348
4349   demux = GST_ASF_DEMUX (parent);
4350
4351   GST_DEBUG ("handling %s query",
4352       gst_query_type_get_name (GST_QUERY_TYPE (query)));
4353
4354   switch (GST_QUERY_TYPE (query)) {
4355     case GST_QUERY_DURATION:
4356     {
4357       GstFormat format;
4358
4359       gst_query_parse_duration (query, &format, NULL);
4360
4361       if (format != GST_FORMAT_TIME) {
4362         GST_LOG ("only support duration queries in TIME format");
4363         break;
4364       }
4365
4366       res = gst_pad_query_default (pad, parent, query);
4367       if (!res) {
4368         GST_OBJECT_LOCK (demux);
4369
4370         if (demux->segment.duration != GST_CLOCK_TIME_NONE) {
4371           GST_LOG ("returning duration: %" GST_TIME_FORMAT,
4372               GST_TIME_ARGS (demux->segment.duration));
4373
4374           gst_query_set_duration (query, GST_FORMAT_TIME,
4375               demux->segment.duration);
4376
4377           res = TRUE;
4378         } else {
4379           GST_LOG ("duration not known yet");
4380         }
4381
4382         GST_OBJECT_UNLOCK (demux);
4383       }
4384       break;
4385     }
4386
4387     case GST_QUERY_POSITION:{
4388       GstFormat format;
4389
4390       gst_query_parse_position (query, &format, NULL);
4391
4392       if (format != GST_FORMAT_TIME) {
4393         GST_LOG ("only support position queries in TIME format");
4394         break;
4395       }
4396
4397       GST_OBJECT_LOCK (demux);
4398
4399       if (demux->segment.position != GST_CLOCK_TIME_NONE) {
4400         GST_LOG ("returning position: %" GST_TIME_FORMAT,
4401             GST_TIME_ARGS (demux->segment.position));
4402
4403         gst_query_set_position (query, GST_FORMAT_TIME,
4404             demux->segment.position);
4405
4406         res = TRUE;
4407       } else {
4408         GST_LOG ("position not known yet");
4409       }
4410
4411       GST_OBJECT_UNLOCK (demux);
4412       break;
4413     }
4414
4415     case GST_QUERY_SEEKING:{
4416       GstFormat format;
4417
4418       gst_query_parse_seeking (query, &format, NULL, NULL, NULL);
4419       if (format == GST_FORMAT_TIME) {
4420         gint64 duration;
4421
4422         GST_OBJECT_LOCK (demux);
4423         duration = demux->segment.duration;
4424         GST_OBJECT_UNLOCK (demux);
4425
4426         if (!demux->streaming || !demux->seekable) {
4427           gst_query_set_seeking (query, GST_FORMAT_TIME, demux->seekable, 0,
4428               duration);
4429           res = TRUE;
4430         } else {
4431           GstFormat fmt;
4432           gboolean seekable;
4433
4434           /* try upstream first in TIME */
4435           res = gst_pad_query_default (pad, parent, query);
4436
4437           gst_query_parse_seeking (query, &fmt, &seekable, NULL, NULL);
4438           GST_LOG_OBJECT (demux, "upstream %s seekable %d",
4439               GST_STR_NULL (gst_format_get_name (fmt)), seekable);
4440           /* if no luck, maybe in BYTES */
4441           if (!seekable || fmt != GST_FORMAT_TIME) {
4442             GstQuery *q;
4443
4444             q = gst_query_new_seeking (GST_FORMAT_BYTES);
4445             if ((res = gst_pad_peer_query (demux->sinkpad, q))) {
4446               gst_query_parse_seeking (q, &fmt, &seekable, NULL, NULL);
4447               GST_LOG_OBJECT (demux, "upstream %s seekable %d",
4448                   GST_STR_NULL (gst_format_get_name (fmt)), seekable);
4449               if (fmt != GST_FORMAT_BYTES)
4450                 seekable = FALSE;
4451             }
4452             gst_query_unref (q);
4453             gst_query_set_seeking (query, GST_FORMAT_TIME, seekable, 0,
4454                 duration);
4455             res = TRUE;
4456           }
4457         }
4458       } else
4459         GST_LOG_OBJECT (demux, "only support seeking in TIME format");
4460       break;
4461     }
4462
4463     case GST_QUERY_LATENCY:
4464     {
4465       gboolean live;
4466       GstClockTime min, max;
4467
4468       /* preroll delay does not matter in non-live pipeline,
4469        * but we might end up in a live (rtsp) one ... */
4470
4471       /* first forward */
4472       res = gst_pad_query_default (pad, parent, query);
4473       if (!res)
4474         break;
4475
4476       gst_query_parse_latency (query, &live, &min, &max);
4477
4478       GST_DEBUG_OBJECT (demux, "Peer latency: live %d, min %"
4479           GST_TIME_FORMAT " max %" GST_TIME_FORMAT, live,
4480           GST_TIME_ARGS (min), GST_TIME_ARGS (max));
4481
4482       GST_OBJECT_LOCK (demux);
4483       min += demux->latency;
4484       if (max != -1)
4485         max += demux->latency;
4486       GST_OBJECT_UNLOCK (demux);
4487
4488       gst_query_set_latency (query, live, min, max);
4489       break;
4490     }
4491     case GST_QUERY_SEGMENT:
4492     {
4493       GstFormat format;
4494       gint64 start, stop;
4495
4496       format = demux->segment.format;
4497
4498       start =
4499           gst_segment_to_stream_time (&demux->segment, format,
4500           demux->segment.start);
4501       if ((stop = demux->segment.stop) == -1)
4502         stop = demux->segment.duration;
4503       else
4504         stop = gst_segment_to_stream_time (&demux->segment, format, stop);
4505
4506       gst_query_set_segment (query, demux->segment.rate, format, start, stop);
4507       res = TRUE;
4508       break;
4509     }
4510     default:
4511       res = gst_pad_query_default (pad, parent, query);
4512       break;
4513   }
4514
4515   return res;
4516 }
4517
4518 static GstStateChangeReturn
4519 gst_asf_demux_change_state (GstElement * element, GstStateChange transition)
4520 {
4521   GstASFDemux *demux = GST_ASF_DEMUX (element);
4522   GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
4523
4524   switch (transition) {
4525     case GST_STATE_CHANGE_NULL_TO_READY:{
4526       gst_segment_init (&demux->segment, GST_FORMAT_TIME);
4527       demux->need_newsegment = TRUE;
4528       demux->segment_running = FALSE;
4529       demux->accurate = FALSE;
4530       demux->adapter = gst_adapter_new ();
4531       demux->metadata = gst_caps_new_empty ();
4532       demux->global_metadata = gst_structure_new_empty ("metadata");
4533       demux->data_size = 0;
4534       demux->data_offset = 0;
4535       demux->index_offset = 0;
4536       demux->base_offset = 0;
4537       demux->flowcombiner = gst_flow_combiner_new ();
4538       break;
4539     }
4540     default:
4541       break;
4542   }
4543
4544   ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
4545   if (ret == GST_STATE_CHANGE_FAILURE)
4546     return ret;
4547
4548   switch (transition) {
4549     case GST_STATE_CHANGE_PAUSED_TO_READY:
4550       gst_asf_demux_reset (demux, FALSE);
4551       break;
4552
4553     case GST_STATE_CHANGE_READY_TO_NULL:
4554       gst_asf_demux_reset (demux, FALSE);
4555       gst_flow_combiner_free (demux->flowcombiner);
4556       demux->flowcombiner = NULL;
4557       break;
4558     default:
4559       break;
4560   }
4561
4562   return ret;
4563 }