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