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