]> git.sesse.net Git - vlc/blob - modules/demux/asf/asf.c
Merge author/artist
[vlc] / modules / demux / asf / asf.c
1 /*****************************************************************************
2  * asf.c : ASF demux module
3  *****************************************************************************
4  * Copyright (C) 2002-2003 the VideoLAN team
5  * $Id$
6  *
7  * Authors: Laurent Aimar <fenrir@via.ecp.fr>
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22  *****************************************************************************/
23
24 /*****************************************************************************
25  * Preamble
26  *****************************************************************************/
27 #include <stdlib.h>                                      /* malloc(), free() */
28
29 #include <vlc/vlc.h>
30 #include <vlc/input.h>
31 #include <vlc_interaction.h>
32
33 #include "vlc_meta.h"
34
35 #include "codecs.h"                        /* BITMAPINFOHEADER, WAVEFORMATEX */
36 #include "libasf.h"
37
38 /* TODO
39  *  - add support for the newly added object: language, bitrate,
40  *                                            extended stream properties.
41  */
42
43 /*****************************************************************************
44  * Module descriptor
45  *****************************************************************************/
46 static int  Open  ( vlc_object_t * );
47 static void Close ( vlc_object_t * );
48
49 vlc_module_begin();
50     set_category( CAT_INPUT );
51     set_subcategory( SUBCAT_INPUT_DEMUX );
52     set_description( _("ASF v1.0 demuxer") );
53     set_capability( "demux2", 200 );
54     set_callbacks( Open, Close );
55     add_shortcut( "asf" );
56 vlc_module_end();
57
58
59 /*****************************************************************************
60  * Local prototypes
61  *****************************************************************************/
62 static int Demux  ( demux_t * );
63 static int Control( demux_t *, int i_query, va_list args );
64
65 typedef struct
66 {
67     int i_cat;
68
69     es_out_id_t     *p_es;
70
71     asf_object_stream_properties_t *p_sp;
72
73     mtime_t i_time;
74
75     block_t         *p_frame; /* use to gather complete frame */
76
77 } asf_track_t;
78
79 struct demux_sys_t
80 {
81     mtime_t             i_time;     /* s */
82     mtime_t             i_length;   /* length of file file */
83     int64_t             i_bitrate;  /* global file bitrate */
84
85     asf_object_root_t            *p_root;
86     asf_object_file_properties_t *p_fp;
87
88     unsigned int        i_track;
89     asf_track_t         *track[128];
90
91     int64_t             i_data_begin;
92     int64_t             i_data_end;
93
94     vlc_meta_t          *meta;
95 };
96
97 static mtime_t  GetMoviePTS( demux_sys_t * );
98 static int      DemuxInit( demux_t * );
99 static void     DemuxEnd( demux_t * );
100 static int      DemuxPacket( demux_t * );
101
102 /*****************************************************************************
103  * Open: check file and initializes ASF structures
104  *****************************************************************************/
105 static int Open( vlc_object_t * p_this )
106 {
107     demux_t     *p_demux = (demux_t *)p_this;
108     demux_sys_t *p_sys;
109     guid_t      guid;
110     uint8_t     *p_peek;
111
112     /* A little test to see if it could be a asf stream */
113     if( stream_Peek( p_demux->s, &p_peek, 16 ) < 16 ) return VLC_EGENERIC;
114
115     ASF_GetGUID( &guid, p_peek );
116     if( !ASF_CmpGUID( &guid, &asf_object_header_guid ) ) return VLC_EGENERIC;
117
118     /* Set p_demux fields */
119     p_demux->pf_demux = Demux;
120     p_demux->pf_control = Control;
121     p_demux->p_sys = p_sys = malloc( sizeof( demux_sys_t ) );
122     memset( p_sys, 0, sizeof( demux_sys_t ) );
123
124     /* Load the headers */
125     if( DemuxInit( p_demux ) )
126     {
127         return VLC_EGENERIC;
128     }
129     return VLC_SUCCESS;
130 }
131
132
133 /*****************************************************************************
134  * Demux: read packet and send them to decoders
135  *****************************************************************************/
136 static int Demux( demux_t *p_demux )
137 {
138     demux_sys_t *p_sys = p_demux->p_sys;
139
140     for( ;; )
141     {
142         uint8_t *p_peek;
143         mtime_t i_length;
144         mtime_t i_time_begin = GetMoviePTS( p_sys );
145         int i_result;
146
147         if( p_demux->b_die )
148         {
149             break;
150         }
151
152         /* Check if we have concatenated files */
153         if( stream_Peek( p_demux->s, &p_peek, 16 ) == 16 )
154         {
155             guid_t guid;
156
157             ASF_GetGUID( &guid, p_peek );
158             if( ASF_CmpGUID( &guid, &asf_object_header_guid ) )
159             {
160                 msg_Warn( p_demux, "found a new ASF header" );
161                 /* We end this stream */
162                 DemuxEnd( p_demux );
163
164                 /* And we prepare to read the next one */
165                 if( DemuxInit( p_demux ) )
166                 {
167                     msg_Err( p_demux, "failed to load the new header" );
168                     intf_UserFatal( p_demux, VLC_FALSE, _("Could not demux ASF stream"), 
169                                     _("VLC failed to load the ASF header.") );
170                     return 0;
171                 }
172                 continue;
173             }
174         }
175
176         /* Read and demux a packet */
177         if( ( i_result = DemuxPacket( p_demux ) ) <= 0 )
178         {
179             return i_result;
180         }
181         if( i_time_begin == -1 )
182         {
183             i_time_begin = GetMoviePTS( p_sys );
184         }
185         else
186         {
187             i_length = GetMoviePTS( p_sys ) - i_time_begin;
188             if( i_length < 0 || i_length >= 40 * 1000 )
189             {
190                 break;
191             }
192         }
193     }
194
195     /* Set the PCR */
196     p_sys->i_time = GetMoviePTS( p_sys );
197     if( p_sys->i_time >= 0 )
198     {
199         es_out_Control( p_demux->out, ES_OUT_SET_PCR, p_sys->i_time );
200     }
201
202     return 1;
203 }
204
205 /*****************************************************************************
206  * Close: frees unused data
207  *****************************************************************************/
208 static void Close( vlc_object_t * p_this )
209 {
210     demux_t     *p_demux = (demux_t *)p_this;
211
212     DemuxEnd( p_demux );
213
214     free( p_demux->p_sys );
215 }
216
217 /*****************************************************************************
218  * Control:
219  *****************************************************************************/
220 static int Control( demux_t *p_demux, int i_query, va_list args )
221 {
222     demux_sys_t *p_sys = p_demux->p_sys;
223     int64_t     *pi64;
224     int         i;
225     vlc_meta_t *p_meta;
226
227     switch( i_query )
228     {
229         case DEMUX_SET_TIME:
230             return VLC_EGENERIC;
231
232         case DEMUX_GET_LENGTH:
233             pi64 = (int64_t*)va_arg( args, int64_t * );
234             *pi64 = p_sys->i_length;
235             return VLC_SUCCESS;
236
237         case DEMUX_GET_META:
238             p_meta = (vlc_meta_t*)va_arg( args, vlc_meta_t* );
239             vlc_meta_Merge( p_meta, p_sys->meta );
240             return VLC_SUCCESS;
241
242         case DEMUX_SET_POSITION:
243             p_sys->i_time = -1;
244             for( i = 0; i < 128 ; i++ )
245             {
246                 asf_track_t *tk = p_sys->track[i];
247                 if( tk ) tk->i_time = -1;
248             }
249
250         default:
251             return demux2_vaControlHelper( p_demux->s,
252                                            p_sys->i_data_begin, p_sys->i_data_end,
253                                            p_sys->i_bitrate, p_sys->p_fp->i_min_data_packet_size,
254                                            i_query, args );
255     }
256 }
257
258 /*****************************************************************************
259  *
260  *****************************************************************************/
261 static mtime_t GetMoviePTS( demux_sys_t *p_sys )
262 {
263     mtime_t i_time;
264     int     i;
265
266     i_time = -1;
267     for( i = 0; i < 128 ; i++ )
268     {
269         asf_track_t *tk = p_sys->track[i];
270
271         if( tk && tk->p_es && tk->i_time > 0)
272         {
273             if( i_time < 0 )
274             {
275                 i_time = tk->i_time;
276             }
277             else
278             {
279                 i_time = __MIN( i_time, tk->i_time );
280             }
281         }
282     }
283
284     return i_time;
285 }
286
287 #define GETVALUE2b( bits, var, def ) \
288     switch( (bits)&0x03 ) \
289     { \
290         case 1: var = p_peek[i_skip]; i_skip++; break; \
291         case 2: var = GetWLE( p_peek + i_skip );  i_skip+= 2; break; \
292         case 3: var = GetDWLE( p_peek + i_skip ); i_skip+= 4; break; \
293         case 0: \
294         default: var = def; break;\
295     }
296
297 static int DemuxPacket( demux_t *p_demux )
298 {
299     demux_sys_t *p_sys = p_demux->p_sys;
300     int         i_data_packet_min = p_sys->p_fp->i_min_data_packet_size;
301     uint8_t     *p_peek;
302     int         i_skip;
303
304     int         i_packet_size_left;
305     int         i_packet_flags;
306     int         i_packet_property;
307
308     int         b_packet_multiple_payload;
309     int         i_packet_length;
310     int         i_packet_sequence;
311     int         i_packet_padding_length;
312
313     uint32_t    i_packet_send_time;
314     uint16_t    i_packet_duration;
315     int         i_payload;
316     int         i_payload_count;
317     int         i_payload_length_type;
318
319
320     if( stream_Peek( p_demux->s, &p_peek,i_data_packet_min)<i_data_packet_min )
321     {
322         msg_Warn( p_demux, "cannot peek while getting new packet, EOF ?" );
323         return 0;
324     }
325     i_skip = 0;
326
327     /* *** parse error correction if present *** */
328     if( p_peek[0]&0x80 )
329     {
330         unsigned int i_error_correction_length_type;
331         unsigned int i_error_correction_data_length;
332         unsigned int i_opaque_data_present;
333
334         i_error_correction_data_length = p_peek[0] & 0x0f;  // 4bits
335         i_opaque_data_present = ( p_peek[0] >> 4 )& 0x01;    // 1bit
336         i_error_correction_length_type = ( p_peek[0] >> 5 ) & 0x03; // 2bits
337         i_skip += 1; // skip error correction flags
338
339         if( i_error_correction_length_type != 0x00 ||
340             i_opaque_data_present != 0 ||
341             i_error_correction_data_length != 0x02 )
342         {
343             goto loop_error_recovery;
344         }
345
346         i_skip += i_error_correction_data_length;
347     }
348     else
349     {
350         msg_Warn( p_demux, "p_peek[0]&0x80 != 0x80" );
351     }
352
353     /* sanity check */
354     if( i_skip + 2 >= i_data_packet_min )
355     {
356         goto loop_error_recovery;
357     }
358
359     i_packet_flags = p_peek[i_skip]; i_skip++;
360     i_packet_property = p_peek[i_skip]; i_skip++;
361
362     b_packet_multiple_payload = i_packet_flags&0x01;
363
364     /* read some value */
365     GETVALUE2b( i_packet_flags >> 5, i_packet_length, i_data_packet_min );
366     GETVALUE2b( i_packet_flags >> 1, i_packet_sequence, 0 );
367     GETVALUE2b( i_packet_flags >> 3, i_packet_padding_length, 0 );
368
369     i_packet_send_time = GetDWLE( p_peek + i_skip ); i_skip += 4;
370     i_packet_duration  = GetWLE( p_peek + i_skip ); i_skip += 2;
371
372 //        i_packet_size_left = i_packet_length;   // XXX data really read 
373     /* FIXME I have to do that for some file, I don't known why */
374     i_packet_size_left = i_data_packet_min;
375
376     if( b_packet_multiple_payload )
377     {
378         i_payload_count = p_peek[i_skip] & 0x3f;
379         i_payload_length_type = ( p_peek[i_skip] >> 6 )&0x03;
380         i_skip++;
381     }
382     else
383     {
384         i_payload_count = 1;
385         i_payload_length_type = 0x02; // unused
386     }
387
388     for( i_payload = 0; i_payload < i_payload_count ; i_payload++ )
389     {
390         asf_track_t   *tk;
391
392         int i_stream_number;
393         int i_media_object_number;
394         int i_media_object_offset;
395         int i_replicated_data_length;
396         int i_payload_data_length;
397         int i_payload_data_pos;
398         int i_sub_payload_data_length;
399         int i_tmp;
400
401         mtime_t i_pts;
402         mtime_t i_pts_delta;
403
404         if( i_skip >= i_packet_size_left )
405         {
406             /* prevent some segfault with invalid file */
407             break;
408         }
409
410         i_stream_number = p_peek[i_skip] & 0x7f;
411         i_skip++;
412
413         GETVALUE2b( i_packet_property >> 4, i_media_object_number, 0 );
414         GETVALUE2b( i_packet_property >> 2, i_tmp, 0 );
415         GETVALUE2b( i_packet_property, i_replicated_data_length, 0 );
416
417         if( i_replicated_data_length > 1 ) // should be at least 8 bytes
418         {
419             i_pts = (mtime_t)GetDWLE( p_peek + i_skip + 4 ) * 1000;
420             i_skip += i_replicated_data_length;
421             i_pts_delta = 0;
422
423             i_media_object_offset = i_tmp;
424
425             if( i_skip >= i_packet_size_left )
426             {
427                 break;
428             }
429         }
430         else if( i_replicated_data_length == 1 )
431         {
432             /* msg_Dbg( p_demux, "found compressed payload" ); */
433
434             i_pts = (mtime_t)i_tmp * 1000;
435             i_pts_delta = (mtime_t)p_peek[i_skip] * 1000; i_skip++;
436
437             i_media_object_offset = 0;
438         }
439         else
440         {
441             i_pts = (mtime_t)i_packet_send_time * 1000;
442             i_pts_delta = 0;
443
444             i_media_object_offset = i_tmp;
445         }
446
447         i_pts = __MAX( i_pts - p_sys->p_fp->i_preroll * 1000, 0 );
448         if( b_packet_multiple_payload )
449         {
450             GETVALUE2b( i_payload_length_type, i_payload_data_length, 0 );
451         }
452         else
453         {
454             i_payload_data_length = i_packet_length -
455                                         i_packet_padding_length - i_skip;
456         }
457
458         if( i_payload_data_length < 0 || i_skip + i_payload_data_length > i_packet_size_left )
459         {
460             break;
461         }
462 #if 0
463          msg_Dbg( p_demux,
464                   "payload(%d/%d) stream_number:%d media_object_number:%d media_object_offset:%d replicated_data_length:%d payload_data_length %d",
465                   i_payload + 1, i_payload_count, i_stream_number, i_media_object_number,
466                   i_media_object_offset, i_replicated_data_length, i_payload_data_length );
467 #endif
468
469         if( ( tk = p_sys->track[i_stream_number] ) == NULL )
470         {
471             msg_Warn( p_demux,
472                       "undeclared stream[Id 0x%x]", i_stream_number );
473             i_skip += i_payload_data_length;
474             continue;   // over payload
475         }
476
477         if( !tk->p_es )
478         {
479             i_skip += i_payload_data_length;
480             continue;
481         }
482
483
484         for( i_payload_data_pos = 0;
485              i_payload_data_pos < i_payload_data_length &&
486                     i_packet_size_left > 0;
487              i_payload_data_pos += i_sub_payload_data_length )
488         {
489             block_t *p_frag;
490             int i_read;
491
492             // read sub payload length
493             if( i_replicated_data_length == 1 )
494             {
495                 i_sub_payload_data_length = p_peek[i_skip]; i_skip++;
496                 i_payload_data_pos++;
497             }
498             else
499             {
500                 i_sub_payload_data_length = i_payload_data_length;
501             }
502
503             /* FIXME I don't use i_media_object_number, sould I ? */
504             if( tk->p_frame && i_media_object_offset == 0 )
505             {
506                 /* send complete packet to decoder */
507                 block_t *p_gather = block_ChainGather( tk->p_frame );
508
509                 es_out_Send( p_demux->out, tk->p_es, p_gather );
510
511                 tk->p_frame = NULL;
512             }
513
514             i_read = i_sub_payload_data_length + i_skip;
515             if( ( p_frag = stream_Block( p_demux->s, i_read ) ) == NULL )
516             {
517                 msg_Warn( p_demux, "cannot read data" );
518                 return 0;
519             }
520             i_packet_size_left -= i_read;
521
522             p_frag->p_buffer += i_skip;
523             p_frag->i_buffer -= i_skip;
524
525             if( tk->p_frame == NULL )
526             {
527                 tk->i_time =
528                     ( (mtime_t)i_pts + i_payload * (mtime_t)i_pts_delta );
529
530                 p_frag->i_pts = tk->i_time;
531
532                 if( tk->i_cat != VIDEO_ES )
533                     p_frag->i_dts = p_frag->i_pts;
534                 else
535                 {
536                     p_frag->i_dts = p_frag->i_pts;
537                     p_frag->i_pts = 0;
538                 }
539             }
540
541             block_ChainAppend( &tk->p_frame, p_frag );
542
543             i_skip = 0;
544             if( i_packet_size_left > 0 )
545             {
546                 if( stream_Peek( p_demux->s, &p_peek, i_packet_size_left )
547                                                          < i_packet_size_left )
548                 {
549                     msg_Warn( p_demux, "cannot peek, EOF ?" );
550                     return 0;
551                 }
552             }
553         }
554     }
555
556     if( i_packet_size_left > 0 )
557     {
558         if( stream_Read( p_demux->s, NULL, i_packet_size_left )
559                                                          < i_packet_size_left )
560         {
561             msg_Warn( p_demux, "cannot skip data, EOF ?" );
562             return 0;
563         }
564     }
565
566     return 1;
567
568 loop_error_recovery:
569     msg_Warn( p_demux, "unsupported packet header" );
570     if( p_sys->p_fp->i_min_data_packet_size != p_sys->p_fp->i_max_data_packet_size )
571     {
572         msg_Err( p_demux, "unsupported packet header, fatal error" );
573         return -1;
574     }
575     stream_Read( p_demux->s, NULL, i_data_packet_min );
576
577     return 1;
578 }
579
580 /*****************************************************************************
581  *
582  *****************************************************************************/
583 static int DemuxInit( demux_t *p_demux )
584 {
585     demux_sys_t *p_sys = p_demux->p_sys;
586     vlc_bool_t  b_seekable;
587     int         i;
588
589     unsigned int    i_stream;
590     asf_object_content_description_t *p_cd;
591
592     /* init context */
593     p_sys->i_time   = -1;
594     p_sys->i_length = 0;
595     p_sys->i_bitrate = 0;
596     p_sys->p_root   = NULL;
597     p_sys->p_fp     = NULL;
598     p_sys->i_track  = 0;
599     for( i = 0; i < 128; i++ )
600     {
601         p_sys->track[i] = NULL;
602     }
603     p_sys->i_data_begin = -1;
604     p_sys->i_data_end   = -1;
605     p_sys->meta         = NULL;
606
607     /* Now load all object ( except raw data ) */
608     stream_Control( p_demux->s, STREAM_CAN_FASTSEEK, &b_seekable );
609     if( (p_sys->p_root = ASF_ReadObjectRoot( p_demux->s, b_seekable )) == NULL )
610     {
611         msg_Warn( p_demux, "ASF plugin discarded (not a valid file)" );
612         return VLC_EGENERIC;
613     }
614     p_sys->p_fp = p_sys->p_root->p_fp;
615
616     if( p_sys->p_fp->i_min_data_packet_size != p_sys->p_fp->i_max_data_packet_size )
617     {
618         msg_Warn( p_demux, "ASF plugin discarded (invalid file_properties object)" );
619         goto error;
620     }
621
622     p_sys->i_track = ASF_CountObject( p_sys->p_root->p_hdr,
623                                       &asf_object_stream_properties_guid );
624     if( p_sys->i_track <= 0 )
625     {
626         msg_Warn( p_demux, "ASF plugin discarded (cannot find any stream!)" );
627         goto error;
628     }
629
630     msg_Dbg( p_demux, "found %d streams", p_sys->i_track );
631
632     for( i_stream = 0; i_stream < p_sys->i_track; i_stream ++ )
633     {
634         asf_track_t    *tk;
635         asf_object_stream_properties_t *p_sp;
636         vlc_bool_t b_access_selected;
637
638         p_sp = ASF_FindObject( p_sys->p_root->p_hdr,
639                                &asf_object_stream_properties_guid,
640                                i_stream );
641
642         tk = p_sys->track[p_sp->i_stream_number] = malloc( sizeof( asf_track_t ) );
643         memset( tk, 0, sizeof( asf_track_t ) );
644
645         tk->i_time = -1;
646         tk->p_sp = p_sp;
647         tk->p_es = NULL;
648         tk->p_frame = NULL;
649
650         /* Check (in case of mms) if this track is selected (ie will receive data) */
651         if( !stream_Control( p_demux->s, STREAM_CONTROL_ACCESS, ACCESS_GET_PRIVATE_ID_STATE,
652                              p_sp->i_stream_number, &b_access_selected ) &&
653             !b_access_selected )
654         {
655             tk->i_cat = UNKNOWN_ES;
656             msg_Dbg( p_demux, "ignoring not selected stream(ID:%d) (by access)",
657                      p_sp->i_stream_number );
658             continue;
659         }
660
661         if( ASF_CmpGUID( &p_sp->i_stream_type, &asf_object_stream_type_audio ) &&
662             p_sp->i_type_specific_data_length >= sizeof( WAVEFORMATEX ) - 2 )
663         {
664             es_format_t fmt;
665             uint8_t *p_data = p_sp->p_type_specific_data;
666             int i_format;
667
668             es_format_Init( &fmt, AUDIO_ES, 0 );
669             i_format = GetWLE( &p_data[0] );
670             wf_tag_to_fourcc( i_format, &fmt.i_codec, NULL );
671             fmt.audio.i_channels        = GetWLE(  &p_data[2] );
672             fmt.audio.i_rate      = GetDWLE( &p_data[4] );
673             fmt.i_bitrate         = GetDWLE( &p_data[8] ) * 8;
674             fmt.audio.i_blockalign      = GetWLE(  &p_data[12] );
675             fmt.audio.i_bitspersample   = GetWLE(  &p_data[14] );
676
677             if( p_sp->i_type_specific_data_length > sizeof( WAVEFORMATEX ) &&
678                 i_format != WAVE_FORMAT_MPEGLAYER3 &&
679                 i_format != WAVE_FORMAT_MPEG )
680             {
681                 fmt.i_extra = __MIN( GetWLE( &p_data[16] ),
682                                      p_sp->i_type_specific_data_length -
683                                      sizeof( WAVEFORMATEX ) );
684                 fmt.p_extra = malloc( fmt.i_extra );
685                 memcpy( fmt.p_extra, &p_data[sizeof( WAVEFORMATEX )],
686                         fmt.i_extra );
687             }
688
689             tk->i_cat = AUDIO_ES;
690             tk->p_es = es_out_Add( p_demux->out, &fmt );
691             es_format_Clean( &fmt );
692
693             msg_Dbg( p_demux, "added new audio stream(codec:0x%x,ID:%d)",
694                     GetWLE( p_data ), p_sp->i_stream_number );
695         }
696         else if( ASF_CmpGUID( &p_sp->i_stream_type,
697                               &asf_object_stream_type_video ) &&
698                  p_sp->i_type_specific_data_length >= 11 +
699                  sizeof( BITMAPINFOHEADER ) )
700         {
701             es_format_t  fmt;
702             uint8_t      *p_data = &p_sp->p_type_specific_data[11];
703
704             es_format_Init( &fmt, VIDEO_ES,
705                             VLC_FOURCC( p_data[16], p_data[17],
706                                         p_data[18], p_data[19] ) );
707             fmt.video.i_width = GetDWLE( p_data + 4 );
708             fmt.video.i_height= GetDWLE( p_data + 8 );
709
710             if( p_sp->i_type_specific_data_length > 11 +
711                 sizeof( BITMAPINFOHEADER ) )
712             {
713                 fmt.i_extra = __MIN( GetDWLE( p_data ),
714                                      p_sp->i_type_specific_data_length - 11 -
715                                      sizeof( BITMAPINFOHEADER ) );
716                 fmt.p_extra = malloc( fmt.i_extra );
717                 memcpy( fmt.p_extra, &p_data[sizeof( BITMAPINFOHEADER )],
718                         fmt.i_extra );
719             }
720
721             /* Look for an aspect ratio */
722             if( p_sys->p_root->p_metadata )
723             {
724                 asf_object_metadata_t *p_meta = p_sys->p_root->p_metadata;
725                 int i_aspect_x = 0, i_aspect_y = 0;
726                 unsigned int i;
727
728                 for( i = 0; i < p_meta->i_record_entries_count; i++ )
729                 {
730                     if( !strcmp( p_meta->record[i].psz_name, "AspectRatioX" ) )
731                     {
732                         if( (!i_aspect_x && !p_meta->record[i].i_stream) ||
733                             p_meta->record[i].i_stream ==
734                             p_sp->i_stream_number )
735                             i_aspect_x = p_meta->record[i].i_val;
736                     }
737                     if( !strcmp( p_meta->record[i].psz_name, "AspectRatioY" ) )
738                     {
739                         if( (!i_aspect_y && !p_meta->record[i].i_stream) ||
740                             p_meta->record[i].i_stream ==
741                             p_sp->i_stream_number )
742                             i_aspect_y = p_meta->record[i].i_val;
743                     }
744                 }
745
746                 if( i_aspect_x && i_aspect_y )
747                 {
748                     fmt.video.i_aspect = i_aspect_x *
749                         (int64_t)fmt.video.i_width * VOUT_ASPECT_FACTOR /
750                         fmt.video.i_height / i_aspect_y;
751                 }
752             }
753
754             tk->i_cat = VIDEO_ES;
755             tk->p_es = es_out_Add( p_demux->out, &fmt );
756             es_format_Clean( &fmt );
757
758             msg_Dbg( p_demux, "added new video stream(ID:%d)",
759                      p_sp->i_stream_number );
760         }
761         else
762         {
763             tk->i_cat = UNKNOWN_ES;
764             msg_Dbg( p_demux, "ignoring unknown stream(ID:%d)",
765                      p_sp->i_stream_number );
766         }
767     }
768
769     p_sys->i_data_begin = p_sys->p_root->p_data->i_object_pos + 50;
770     if( p_sys->p_root->p_data->i_object_size != 0 )
771     { /* local file */
772         p_sys->i_data_end = p_sys->p_root->p_data->i_object_pos +
773                                     p_sys->p_root->p_data->i_object_size;
774     }
775     else
776     { /* live/broacast */
777         p_sys->i_data_end = -1;
778     }
779
780
781     /* go to first packet */
782     stream_Seek( p_demux->s, p_sys->i_data_begin );
783
784     /* try to calculate movie time */
785     if( p_sys->p_fp->i_data_packets_count > 0 )
786     {
787         int64_t i_count;
788         int64_t i_size = stream_Size( p_demux->s );
789
790         if( p_sys->i_data_end > 0 && i_size > p_sys->i_data_end )
791         {
792             i_size = p_sys->i_data_end;
793         }
794
795         /* real number of packets */
796         i_count = ( i_size - p_sys->i_data_begin ) /
797                   p_sys->p_fp->i_min_data_packet_size;
798
799         /* calculate the time duration in micro-s */
800         p_sys->i_length = (mtime_t)p_sys->p_fp->i_play_duration / 10 *
801                    (mtime_t)i_count /
802                    (mtime_t)p_sys->p_fp->i_data_packets_count;
803
804         if( p_sys->i_length > 0 )
805         {
806             p_sys->i_bitrate = 8 * i_size * (int64_t)1000000 / p_sys->i_length;
807         }
808     }
809
810     /* Create meta information */
811     p_sys->meta = vlc_meta_New();
812
813     if( ( p_cd = ASF_FindObject( p_sys->p_root->p_hdr,
814                                  &asf_object_content_description_guid, 0 ) ) )
815     {
816         if( p_cd->psz_title && *p_cd->psz_title )
817         {
818             vlc_meta_SetTitle( p_sys->meta, p_cd->psz_title );
819         }
820         if( p_cd->psz_artist && *p_cd->psz_artist )
821         {
822              vlc_meta_SetArtist( p_sys->meta, p_cd->psz_artist );
823         }
824         if( p_cd->psz_copyright && *p_cd->psz_copyright )
825         {
826             vlc_meta_SetCopyright( p_sys->meta, p_cd->psz_copyright );
827         }
828         if( p_cd->psz_description && *p_cd->psz_description )
829         {
830             vlc_meta_SetDescription( p_sys->meta, p_cd->psz_description );
831         }
832         if( p_cd->psz_rating && *p_cd->psz_rating )
833         {
834             vlc_meta_SetRating( p_sys->meta, p_cd->psz_rating );
835         }
836     }
837     /// \tood Fix Child meta for ASF tracks
838 #if 0
839     for( i_stream = 0, i = 0; i < 128; i++ )
840     {
841         asf_object_codec_list_t *p_cl = ASF_FindObject( p_sys->p_root->p_hdr,
842                                                         &asf_object_codec_list_guid, 0 );
843
844         if( p_sys->track[i] )
845         {
846             vlc_meta_t *tk = vlc_meta_New();
847             TAB_APPEND( p_sys->meta->i_track, p_sys->meta->track, tk );
848
849             if( p_cl && i_stream < p_cl->i_codec_entries_count )
850             {
851                 if( p_cl->codec[i_stream].psz_name &&
852                     *p_cl->codec[i_stream].psz_name )
853                 {
854                     vlc_meta_Add( tk, VLC_META_CODEC_NAME,
855                                   p_cl->codec[i_stream].psz_name );
856                 }
857                 if( p_cl->codec[i_stream].psz_description &&
858                     *p_cl->codec[i_stream].psz_description )
859                 {
860                     vlc_meta_Add( tk, VLC_META_CODEC_DESCRIPTION,
861                                   p_cl->codec[i_stream].psz_description );
862                 }
863             }
864             i_stream++;
865         }
866     }
867 #endif
868
869     es_out_Control( p_demux->out, ES_OUT_RESET_PCR );
870     return VLC_SUCCESS;
871
872 error:
873     ASF_FreeObjectRoot( p_demux->s, p_sys->p_root );
874     return VLC_EGENERIC;
875 }
876 /*****************************************************************************
877  *
878  *****************************************************************************/
879 static void DemuxEnd( demux_t *p_demux )
880 {
881     demux_sys_t *p_sys = p_demux->p_sys;
882     int         i;
883
884     if( p_sys->p_root )
885     {
886         ASF_FreeObjectRoot( p_demux->s, p_sys->p_root );
887         p_sys->p_root = NULL;
888     }
889     if( p_sys->meta )
890     {
891         vlc_meta_Delete( p_sys->meta );
892         p_sys->meta = NULL;
893     }
894
895     for( i = 0; i < 128; i++ )
896     {
897         asf_track_t *tk = p_sys->track[i];
898
899         if( tk )
900         {
901             if( tk->p_frame )
902             {
903                 block_ChainRelease( tk->p_frame );
904             }
905             if( tk->p_es )
906             {
907                 es_out_Del( p_demux->out, tk->p_es );
908             }
909             free( tk );
910         }
911         p_sys->track[i] = 0;
912     }
913 }
914