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