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