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