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