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