asf.c
上传用户:riyaled888
上传日期:2009-03-27
资源大小:7338k
文件大小:28k
源码类别:

多媒体

开发平台:

MultiPlatform

  1. /*****************************************************************************
  2.  * asf.c : ASF demux module
  3.  *****************************************************************************
  4.  * Copyright (C) 2002-2003 VideoLAN
  5.  * $Id: asf.c 9063 2004-10-27 10:42:48Z gbazin $
  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., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
  22.  *****************************************************************************/
  23. /*****************************************************************************
  24.  * Preamble
  25.  *****************************************************************************/
  26. #include <stdlib.h>                                      /* malloc(), free() */
  27. #include <vlc/vlc.h>
  28. #include <vlc/input.h>
  29. #include "vlc_meta.h"
  30. #include "codecs.h"                        /* BITMAPINFOHEADER, WAVEFORMATEX */
  31. #include "libasf.h"
  32. /*****************************************************************************
  33.  * Module descriptor
  34.  *****************************************************************************/
  35. static int  Open  ( vlc_object_t * );
  36. static void Close ( vlc_object_t * );
  37. vlc_module_begin();
  38.     set_description( _("ASF v1.0 demuxer") );
  39.     set_capability( "demux2", 200 );
  40.     set_callbacks( Open, Close );
  41.     add_shortcut( "asf" );
  42. vlc_module_end();
  43. /*****************************************************************************
  44.  * Local prototypes
  45.  *****************************************************************************/
  46. static int Demux  ( demux_t * );
  47. static int Control( demux_t *, int i_query, va_list args );
  48. typedef struct
  49. {
  50.     int i_cat;
  51.     es_out_id_t     *p_es;
  52.     asf_object_stream_properties_t *p_sp;
  53.     mtime_t i_time;
  54.     block_t         *p_frame; /* use to gather complete frame */
  55. } asf_track_t;
  56. struct demux_sys_t
  57. {
  58.     mtime_t             i_time;     /* 祍 */
  59.     mtime_t             i_length;   /* length of file file */
  60.     int64_t             i_bitrate;  /* global file bitrate */
  61.     asf_object_root_t            *p_root;
  62.     asf_object_file_properties_t *p_fp;
  63.     unsigned int        i_track;
  64.     asf_track_t         *track[128];
  65.     int64_t             i_data_begin;
  66.     int64_t             i_data_end;
  67.     vlc_meta_t          *meta;
  68. };
  69. static mtime_t  GetMoviePTS( demux_sys_t * );
  70. static int      DemuxInit( demux_t * );
  71. static void     DemuxEnd( demux_t * );
  72. static int      DemuxPacket( demux_t * );
  73. /*****************************************************************************
  74.  * Open: check file and initializes ASF structures
  75.  *****************************************************************************/
  76. static int Open( vlc_object_t * p_this )
  77. {
  78.     demux_t     *p_demux = (demux_t *)p_this;
  79.     demux_sys_t *p_sys;
  80.     guid_t      guid;
  81.     uint8_t     *p_peek;
  82.     /* a little test to see if it could be a asf stream */
  83.     if( stream_Peek( p_demux->s, &p_peek, 16 ) < 16 )
  84.     {
  85.         msg_Warn( p_demux, "ASF plugin discarded (cannot peek)" );
  86.         return VLC_EGENERIC;
  87.     }
  88.     ASF_GetGUID( &guid, p_peek );
  89.     if( !ASF_CmpGUID( &guid, &asf_object_header_guid ) )
  90.     {
  91.         msg_Warn( p_demux, "ASF plugin discarded (not a valid file)" );
  92.         return VLC_EGENERIC;
  93.     }
  94.     /* Set p_demux fields */
  95.     p_demux->pf_demux = Demux;
  96.     p_demux->pf_control = Control;
  97.     p_demux->p_sys = p_sys = malloc( sizeof( demux_sys_t ) );
  98.     memset( p_sys, 0, sizeof( demux_sys_t ) );
  99.     /* Load the headers */
  100.     if( DemuxInit( p_demux ) )
  101.     {
  102.         return VLC_EGENERIC;
  103.     }
  104.     return VLC_SUCCESS;
  105. }
  106. /*****************************************************************************
  107.  * Demux: read packet and send them to decoders
  108.  *****************************************************************************/
  109. static int Demux( demux_t *p_demux )
  110. {
  111.     demux_sys_t *p_sys = p_demux->p_sys;
  112.     for( ;; )
  113.     {
  114.         uint8_t *p_peek;
  115.         mtime_t i_length;
  116.         mtime_t i_time_begin = GetMoviePTS( p_sys );
  117.         int i_result;
  118.         if( p_demux->b_die )
  119.         {
  120.             break;
  121.         }
  122.         /* Check if we have concatenated files */
  123.         if( stream_Peek( p_demux->s, &p_peek, 16 ) == 16 )
  124.         {
  125.             guid_t guid;
  126.             ASF_GetGUID( &guid, p_peek );
  127.             if( ASF_CmpGUID( &guid, &asf_object_header_guid ) )
  128.             {
  129.                 msg_Warn( p_demux, "Found a new ASF header" );
  130.                 /* We end this stream */
  131.                 DemuxEnd( p_demux );
  132.                 /* And we prepare to read the next one */
  133.                 if( DemuxInit( p_demux ) )
  134.                 {
  135.                     msg_Err( p_demux, "failed to load the new header" );
  136.                     return 0;
  137.                 }
  138.                 continue;
  139.             }
  140.         }
  141.         /* Read and demux a packet */
  142.         if( ( i_result = DemuxPacket( p_demux ) ) <= 0 )
  143.         {
  144.             return i_result;
  145.         }
  146.         if( i_time_begin == -1 )
  147.         {
  148.             i_time_begin = GetMoviePTS( p_sys );
  149.         }
  150.         else
  151.         {
  152.             i_length = GetMoviePTS( p_sys ) - i_time_begin;
  153.             if( i_length < 0 || i_length >= 40 * 1000 )
  154.             {
  155.                 break;
  156.             }
  157.         }
  158.     }
  159.     /* Set the PCR */
  160.     p_sys->i_time = GetMoviePTS( p_sys );
  161.     if( p_sys->i_time >= 0 )
  162.     {
  163.         es_out_Control( p_demux->out, ES_OUT_SET_PCR, p_sys->i_time );
  164.     }
  165.     return 1;
  166. }
  167. /*****************************************************************************
  168.  * Close: frees unused data
  169.  *****************************************************************************/
  170. static void Close( vlc_object_t * p_this )
  171. {
  172.     demux_t     *p_demux = (demux_t *)p_this;
  173.     DemuxEnd( p_demux );
  174.     free( p_demux->p_sys );
  175. }
  176. /*****************************************************************************
  177.  * Control:
  178.  *****************************************************************************/
  179. static int Control( demux_t *p_demux, int i_query, va_list args )
  180. {
  181.     demux_sys_t *p_sys = p_demux->p_sys;
  182.     int64_t     *pi64;
  183.     int         i;
  184.     vlc_meta_t **pp_meta;
  185.     switch( i_query )
  186.     {
  187.         case DEMUX_SET_TIME:
  188.             return VLC_EGENERIC;
  189.         case DEMUX_GET_LENGTH:
  190.             pi64 = (int64_t*)va_arg( args, int64_t * );
  191.             *pi64 = p_sys->i_length;
  192.             return VLC_SUCCESS;
  193.         case DEMUX_GET_META:
  194.             pp_meta = (vlc_meta_t**)va_arg( args, vlc_meta_t** );
  195.             *pp_meta = vlc_meta_Duplicate( p_sys->meta );
  196.             return VLC_SUCCESS;
  197.         case DEMUX_SET_POSITION:
  198.             p_sys->i_time = -1;
  199.             for( i = 0; i < 128 ; i++ )
  200.             {
  201.                 asf_track_t *tk = p_sys->track[i];
  202.                 if( tk ) tk->i_time = -1;
  203.             }
  204.         default:
  205.             return demux2_vaControlHelper( p_demux->s,
  206.                                            p_sys->i_data_begin, p_sys->i_data_end,
  207.                                            p_sys->i_bitrate, p_sys->p_fp->i_min_data_packet_size,
  208.                                            i_query, args );
  209.     }
  210. }
  211. /*****************************************************************************
  212.  *
  213.  *****************************************************************************/
  214. static mtime_t GetMoviePTS( demux_sys_t *p_sys )
  215. {
  216.     mtime_t i_time;
  217.     int     i;
  218.     i_time = -1;
  219.     for( i = 0; i < 128 ; i++ )
  220.     {
  221.         asf_track_t *tk = p_sys->track[i];
  222.         if( tk && tk->p_es && tk->i_time > 0)
  223.         {
  224.             if( i_time < 0 )
  225.             {
  226.                 i_time = tk->i_time;
  227.             }
  228.             else
  229.             {
  230.                 i_time = __MIN( i_time, tk->i_time );
  231.             }
  232.         }
  233.     }
  234.     return i_time;
  235. }
  236. #define GETVALUE2b( bits, var, def ) 
  237.     switch( (bits)&0x03 ) 
  238.     { 
  239.         case 1: var = p_peek[i_skip]; i_skip++; break; 
  240.         case 2: var = GetWLE( p_peek + i_skip );  i_skip+= 2; break; 
  241.         case 3: var = GetDWLE( p_peek + i_skip ); i_skip+= 4; break; 
  242.         case 0: 
  243.         default: var = def; break;
  244.     }
  245. static int DemuxPacket( demux_t *p_demux )
  246. {
  247.     demux_sys_t *p_sys = p_demux->p_sys;
  248.     int         i_data_packet_min = p_sys->p_fp->i_min_data_packet_size;
  249.     uint8_t     *p_peek;
  250.     int         i_skip;
  251.     int         i_packet_size_left;
  252.     int         i_packet_flags;
  253.     int         i_packet_property;
  254.     int         b_packet_multiple_payload;
  255.     int         i_packet_length;
  256.     int         i_packet_sequence;
  257.     int         i_packet_padding_length;
  258.     uint32_t    i_packet_send_time;
  259.     uint16_t    i_packet_duration;
  260.     int         i_payload;
  261.     int         i_payload_count;
  262.     int         i_payload_length_type;
  263.     if( stream_Peek( p_demux->s, &p_peek,i_data_packet_min)<i_data_packet_min )
  264.     {
  265.         msg_Warn( p_demux, "cannot peek while getting new packet, EOF ?" );
  266.         return 0;
  267.     }
  268.     i_skip = 0;
  269.     /* *** parse error correction if present *** */
  270.     if( p_peek[0]&0x80 )
  271.     {
  272.         unsigned int i_error_correction_length_type;
  273.         unsigned int i_error_correction_data_length;
  274.         unsigned int i_opaque_data_present;
  275.         i_error_correction_data_length = p_peek[0] & 0x0f;  // 4bits
  276.         i_opaque_data_present = ( p_peek[0] >> 4 )& 0x01;    // 1bit
  277.         i_error_correction_length_type = ( p_peek[0] >> 5 ) & 0x03; // 2bits
  278.         i_skip += 1; // skip error correction flags
  279.         if( i_error_correction_length_type != 0x00 ||
  280.             i_opaque_data_present != 0 ||
  281.             i_error_correction_data_length != 0x02 )
  282.         {
  283.             goto loop_error_recovery;
  284.         }
  285.         i_skip += i_error_correction_data_length;
  286.     }
  287.     else
  288.     {
  289.         msg_Warn( p_demux, "p_peek[0]&0x80 != 0x80" );
  290.     }
  291.     /* sanity check */
  292.     if( i_skip + 2 >= i_data_packet_min )
  293.     {
  294.         goto loop_error_recovery;
  295.     }
  296.     i_packet_flags = p_peek[i_skip]; i_skip++;
  297.     i_packet_property = p_peek[i_skip]; i_skip++;
  298.     b_packet_multiple_payload = i_packet_flags&0x01;
  299.     /* read some value */
  300.     GETVALUE2b( i_packet_flags >> 5, i_packet_length, i_data_packet_min );
  301.     GETVALUE2b( i_packet_flags >> 1, i_packet_sequence, 0 );
  302.     GETVALUE2b( i_packet_flags >> 3, i_packet_padding_length, 0 );
  303.     i_packet_send_time = GetDWLE( p_peek + i_skip ); i_skip += 4;
  304.     i_packet_duration  = GetWLE( p_peek + i_skip ); i_skip += 2;
  305. //        i_packet_size_left = i_packet_length;   // XXX donn閑s reellement lu
  306.     /* FIXME I have to do that for some file, I don't known why */
  307.     i_packet_size_left = i_data_packet_min;
  308.     if( b_packet_multiple_payload )
  309.     {
  310.         i_payload_count = p_peek[i_skip] & 0x3f;
  311.         i_payload_length_type = ( p_peek[i_skip] >> 6 )&0x03;
  312.         i_skip++;
  313.     }
  314.     else
  315.     {
  316.         i_payload_count = 1;
  317.         i_payload_length_type = 0x02; // unused
  318.     }
  319.     for( i_payload = 0; i_payload < i_payload_count ; i_payload++ )
  320.     {
  321.         asf_track_t   *tk;
  322.         int i_stream_number;
  323.         int i_media_object_number;
  324.         int i_media_object_offset;
  325.         int i_replicated_data_length;
  326.         int i_payload_data_length;
  327.         int i_payload_data_pos;
  328.         int i_sub_payload_data_length;
  329.         int i_tmp;
  330.         mtime_t i_pts;
  331.         mtime_t i_pts_delta;
  332.         if( i_skip >= i_packet_size_left )
  333.         {
  334.             /* prevent some segfault with invalid file */
  335.             break;
  336.         }
  337.         i_stream_number = p_peek[i_skip] & 0x7f;
  338.         i_skip++;
  339.         GETVALUE2b( i_packet_property >> 4, i_media_object_number, 0 );
  340.         GETVALUE2b( i_packet_property >> 2, i_tmp, 0 );
  341.         GETVALUE2b( i_packet_property, i_replicated_data_length, 0 );
  342.         if( i_replicated_data_length > 1 ) // should be at least 8 bytes
  343.         {
  344.             i_pts = (mtime_t)GetDWLE( p_peek + i_skip + 4 ) * 1000;
  345.             i_skip += i_replicated_data_length;
  346.             i_pts_delta = 0;
  347.             i_media_object_offset = i_tmp;
  348.             if( i_skip >= i_packet_size_left )
  349.             {
  350.                 break;
  351.             }
  352.         }
  353.         else if( i_replicated_data_length == 1 )
  354.         {
  355.             /* msg_Dbg( p_demux, "found compressed payload" ); */
  356.             i_pts = (mtime_t)i_tmp * 1000;
  357.             i_pts_delta = (mtime_t)p_peek[i_skip] * 1000; i_skip++;
  358.             i_media_object_offset = 0;
  359.         }
  360.         else
  361.         {
  362.             i_pts = (mtime_t)i_packet_send_time * 1000;
  363.             i_pts_delta = 0;
  364.             i_media_object_offset = i_tmp;
  365.         }
  366.         i_pts = __MAX( i_pts - p_sys->p_fp->i_preroll * 1000, 0 );
  367.         if( b_packet_multiple_payload )
  368.         {
  369.             GETVALUE2b( i_payload_length_type, i_payload_data_length, 0 );
  370.         }
  371.         else
  372.         {
  373.             i_payload_data_length = i_packet_length -
  374.                                         i_packet_padding_length - i_skip;
  375.         }
  376.         if( i_payload_data_length < 0 || i_skip + i_payload_data_length > i_packet_size_left )
  377.         {
  378.             break;
  379.         }
  380. #if 0
  381.          msg_Dbg( p_demux,
  382.                   "payload(%d/%d) stream_number:%d media_object_number:%d media_object_offset:%d replicated_data_length:%d payload_data_length %d",
  383.                   i_payload + 1, i_payload_count, i_stream_number, i_media_object_number,
  384.                   i_media_object_offset, i_replicated_data_length, i_payload_data_length );
  385. #endif
  386.         if( ( tk = p_sys->track[i_stream_number] ) == NULL )
  387.         {
  388.             msg_Warn( p_demux,
  389.                       "undeclared stream[Id 0x%x]", i_stream_number );
  390.             i_skip += i_payload_data_length;
  391.             continue;   // over payload
  392.         }
  393.         if( !tk->p_es )
  394.         {
  395.             i_skip += i_payload_data_length;
  396.             continue;
  397.         }
  398.         for( i_payload_data_pos = 0;
  399.              i_payload_data_pos < i_payload_data_length &&
  400.                     i_packet_size_left > 0;
  401.              i_payload_data_pos += i_sub_payload_data_length )
  402.         {
  403.             block_t *p_frag;
  404.             int i_read;
  405.             // read sub payload length
  406.             if( i_replicated_data_length == 1 )
  407.             {
  408.                 i_sub_payload_data_length = p_peek[i_skip]; i_skip++;
  409.                 i_payload_data_pos++;
  410.             }
  411.             else
  412.             {
  413.                 i_sub_payload_data_length = i_payload_data_length;
  414.             }
  415.             /* FIXME I don't use i_media_object_number, sould I ? */
  416.             if( tk->p_frame && i_media_object_offset == 0 )
  417.             {
  418.                 /* send complete packet to decoder */
  419.                 block_t *p_gather = block_ChainGather( tk->p_frame );
  420.                 es_out_Send( p_demux->out, tk->p_es, p_gather );
  421.                 tk->p_frame = NULL;
  422.             }
  423.             i_read = i_sub_payload_data_length + i_skip;
  424.             if( ( p_frag = stream_Block( p_demux->s, i_read ) ) == NULL )
  425.             {
  426.                 msg_Warn( p_demux, "cannot read data" );
  427.                 return 0;
  428.             }
  429.             i_packet_size_left -= i_read;
  430.             p_frag->p_buffer += i_skip;
  431.             p_frag->i_buffer -= i_skip;
  432.             if( tk->p_frame == NULL )
  433.             {
  434.                 tk->i_time =
  435.                     ( (mtime_t)i_pts + i_payload * (mtime_t)i_pts_delta );
  436.                 p_frag->i_pts = tk->i_time;
  437.                 if( tk->i_cat != VIDEO_ES )
  438.                     p_frag->i_dts = p_frag->i_pts;
  439.                 else
  440.                 {
  441.                     p_frag->i_dts = p_frag->i_pts;
  442.                     p_frag->i_pts = 0;
  443.                 }
  444.             }
  445.             block_ChainAppend( &tk->p_frame, p_frag );
  446.             i_skip = 0;
  447.             if( i_packet_size_left > 0 )
  448.             {
  449.                 if( stream_Peek( p_demux->s, &p_peek, i_packet_size_left )
  450.                                                          < i_packet_size_left )
  451.                 {
  452.                     msg_Warn( p_demux, "cannot peek, EOF ?" );
  453.                     return 0;
  454.                 }
  455.             }
  456.         }
  457.     }
  458.     if( i_packet_size_left > 0 )
  459.     {
  460.         if( stream_Read( p_demux->s, NULL, i_packet_size_left )
  461.                                                          < i_packet_size_left )
  462.         {
  463.             msg_Warn( p_demux, "cannot skip data, EOF ?" );
  464.             return 0;
  465.         }
  466.     }
  467.     return 1;
  468. loop_error_recovery:
  469.     msg_Warn( p_demux, "unsupported packet header" );
  470.     if( p_sys->p_fp->i_min_data_packet_size != p_sys->p_fp->i_max_data_packet_size )
  471.     {
  472.         msg_Err( p_demux, "unsupported packet header, fatal error" );
  473.         return -1;
  474.     }
  475.     stream_Read( p_demux->s, NULL, i_data_packet_min );
  476.     return 1;
  477. }
  478. /*****************************************************************************
  479.  *
  480.  *****************************************************************************/
  481. static int DemuxInit( demux_t *p_demux )
  482. {
  483.     demux_sys_t *p_sys = p_demux->p_sys;
  484.     vlc_bool_t  b_seekable;
  485.     int         i;
  486.     unsigned int    i_stream;
  487.     asf_object_content_description_t *p_cd;
  488.     /* init context */
  489.     p_sys->i_time   = -1;
  490.     p_sys->i_length = 0;
  491.     p_sys->i_bitrate = 0;
  492.     p_sys->p_root   = NULL;
  493.     p_sys->p_fp     = NULL;
  494.     p_sys->i_track  = 0;
  495.     for( i = 0; i < 128; i++ )
  496.     {
  497.         p_sys->track[i] = NULL;
  498.     }
  499.     p_sys->i_data_begin = -1;
  500.     p_sys->i_data_end   = -1;
  501.     p_sys->meta         = NULL;
  502.     /* Now load all object ( except raw data ) */
  503.     stream_Control( p_demux->s, STREAM_CAN_FASTSEEK, &b_seekable );
  504.     if( (p_sys->p_root = ASF_ReadObjectRoot( p_demux->s, b_seekable )) == NULL )
  505.     {
  506.         msg_Warn( p_demux, "ASF plugin discarded (not a valid file)" );
  507.         return VLC_EGENERIC;
  508.     }
  509.     p_sys->p_fp = p_sys->p_root->p_fp;
  510.     if( p_sys->p_fp->i_min_data_packet_size != p_sys->p_fp->i_max_data_packet_size )
  511.     {
  512.         msg_Warn( p_demux, "ASF plugin discarded (invalid file_properties object)" );
  513.         goto error;
  514.     }
  515.     p_sys->i_track = ASF_CountObject( p_sys->p_root->p_hdr,
  516.                                       &asf_object_stream_properties_guid );
  517.     if( p_sys->i_track <= 0 )
  518.     {
  519.         msg_Warn( p_demux, "ASF plugin discarded (cannot find any stream!)" );
  520.         goto error;
  521.     }
  522.     msg_Dbg( p_demux, "found %d streams", p_sys->i_track );
  523.     for( i_stream = 0; i_stream < p_sys->i_track; i_stream ++ )
  524.     {
  525.         asf_track_t    *tk;
  526.         asf_object_stream_properties_t *p_sp;
  527.         p_sp = ASF_FindObject( p_sys->p_root->p_hdr,
  528.                                &asf_object_stream_properties_guid,
  529.                                i_stream );
  530.         tk = p_sys->track[p_sp->i_stream_number] = malloc( sizeof( asf_track_t ) );
  531.         memset( tk, 0, sizeof( asf_track_t ) );
  532.         tk->i_time = -1;
  533.         tk->p_sp = p_sp;
  534.         tk->p_es = NULL;
  535.         tk->p_frame = NULL;
  536.         if( ASF_CmpGUID( &p_sp->i_stream_type, &asf_object_stream_type_audio ) &&
  537.             p_sp->i_type_specific_data_length >= sizeof( WAVEFORMATEX ) - 2 )
  538.         {
  539.             es_format_t fmt;
  540.             uint8_t *p_data = p_sp->p_type_specific_data;
  541.             int i_format;
  542.             es_format_Init( &fmt, AUDIO_ES, 0 );
  543.             i_format = GetWLE( &p_data[0] );
  544.             wf_tag_to_fourcc( i_format, &fmt.i_codec, NULL );
  545.             fmt.audio.i_channels        = GetWLE(  &p_data[2] );
  546.             fmt.audio.i_rate      = GetDWLE( &p_data[4] );
  547.             fmt.i_bitrate         = GetDWLE( &p_data[8] ) * 8;
  548.             fmt.audio.i_blockalign      = GetWLE(  &p_data[12] );
  549.             fmt.audio.i_bitspersample   = GetWLE(  &p_data[14] );
  550.             if( p_sp->i_type_specific_data_length > sizeof( WAVEFORMATEX ) &&
  551.                 i_format != WAVE_FORMAT_MPEGLAYER3 &&
  552.                 i_format != WAVE_FORMAT_MPEG )
  553.             {
  554.                 fmt.i_extra = __MIN( GetWLE( &p_data[16] ),
  555.                                      p_sp->i_type_specific_data_length -
  556.                                      sizeof( WAVEFORMATEX ) );
  557.                 fmt.p_extra = malloc( fmt.i_extra );
  558.                 memcpy( fmt.p_extra, &p_data[sizeof( WAVEFORMATEX )],
  559.                         fmt.i_extra );
  560.             }
  561.             tk->i_cat = AUDIO_ES;
  562.             tk->p_es = es_out_Add( p_demux->out, &fmt );
  563.             es_format_Clean( &fmt );
  564.             msg_Dbg( p_demux, "added new audio stream(codec:0x%x,ID:%d)",
  565.                     GetWLE( p_data ), p_sp->i_stream_number );
  566.         }
  567.         else if( ASF_CmpGUID( &p_sp->i_stream_type,
  568.                               &asf_object_stream_type_video ) &&
  569.                  p_sp->i_type_specific_data_length >= 11 +
  570.                  sizeof( BITMAPINFOHEADER ) )
  571.         {
  572.             es_format_t  fmt;
  573.             uint8_t      *p_data = &p_sp->p_type_specific_data[11];
  574.             es_format_Init( &fmt, VIDEO_ES,
  575.                             VLC_FOURCC( p_data[16], p_data[17],
  576.                                         p_data[18], p_data[19] ) );
  577.             fmt.video.i_width = GetDWLE( p_data + 4 );
  578.             fmt.video.i_height= GetDWLE( p_data + 8 );
  579.             if( p_sp->i_type_specific_data_length > 11 +
  580.                 sizeof( BITMAPINFOHEADER ) )
  581.             {
  582.                 fmt.i_extra = __MIN( GetDWLE( p_data ),
  583.                                      p_sp->i_type_specific_data_length - 11 -
  584.                                      sizeof( BITMAPINFOHEADER ) );
  585.                 fmt.p_extra = malloc( fmt.i_extra );
  586.                 memcpy( fmt.p_extra, &p_data[sizeof( BITMAPINFOHEADER )],
  587.                         fmt.i_extra );
  588.             }
  589.             /* Look for an aspect ratio */
  590.             if( p_sys->p_root->p_metadata )
  591.             {
  592.                 asf_object_metadata_t *p_meta = p_sys->p_root->p_metadata;
  593.                 int i, i_aspect_x = 0, i_aspect_y = 0;
  594.                 for( i = 0; i < p_meta->i_record_entries_count; i++ )
  595.                 {
  596.                     if( !strcmp( p_meta->record[i].psz_name, "AspectRatioX" ) )
  597.                     {
  598.                         if( (!i_aspect_x && !p_meta->record[i].i_stream) ||
  599.                             p_meta->record[i].i_stream ==
  600.                             p_sp->i_stream_number )
  601.                             i_aspect_x = p_meta->record[i].i_val;
  602.                     }
  603.                     if( !strcmp( p_meta->record[i].psz_name, "AspectRatioY" ) )
  604.                     {
  605.                         if( (!i_aspect_y && !p_meta->record[i].i_stream) ||
  606.                             p_meta->record[i].i_stream ==
  607.                             p_sp->i_stream_number )
  608.                             i_aspect_y = p_meta->record[i].i_val;
  609.                     }
  610.                 }
  611.                 if( i_aspect_x && i_aspect_y )
  612.                 {
  613.                     fmt.video.i_aspect = i_aspect_x *
  614.                         (int64_t)fmt.video.i_width * VOUT_ASPECT_FACTOR /
  615.                         fmt.video.i_height / i_aspect_y;
  616.                 }
  617.     }
  618.             tk->i_cat = VIDEO_ES;
  619.             tk->p_es = es_out_Add( p_demux->out, &fmt );
  620.             es_format_Clean( &fmt );
  621.             msg_Dbg( p_demux, "added new video stream(ID:%d)",
  622.                      p_sp->i_stream_number );
  623.         }
  624.         else
  625.         {
  626.             tk->i_cat = UNKNOWN_ES;
  627.             msg_Dbg( p_demux, "ignoring unknown stream(ID:%d)",
  628.                      p_sp->i_stream_number );
  629.         }
  630.     }
  631.     p_sys->i_data_begin = p_sys->p_root->p_data->i_object_pos + 50;
  632.     if( p_sys->p_root->p_data->i_object_size != 0 )
  633.     { /* local file */
  634.         p_sys->i_data_end = p_sys->p_root->p_data->i_object_pos +
  635.                                     p_sys->p_root->p_data->i_object_size;
  636.     }
  637.     else
  638.     { /* live/broacast */
  639.         p_sys->i_data_end = -1;
  640.     }
  641.     /* go to first packet */
  642.     stream_Seek( p_demux->s, p_sys->i_data_begin );
  643.     /* try to calculate movie time */
  644.     if( p_sys->p_fp->i_data_packets_count > 0 )
  645.     {
  646.         int64_t i_count;
  647.         int64_t i_size = stream_Size( p_demux->s );
  648.         if( p_sys->i_data_end > 0 && i_size > p_sys->i_data_end )
  649.         {
  650.             i_size = p_sys->i_data_end;
  651.         }
  652.         /* real number of packets */
  653.         i_count = ( i_size - p_sys->i_data_begin ) /
  654.                   p_sys->p_fp->i_min_data_packet_size;
  655.         /* calculate the time duration in micro-s */
  656.         p_sys->i_length = (mtime_t)p_sys->p_fp->i_play_duration / 10 *
  657.                    (mtime_t)i_count /
  658.                    (mtime_t)p_sys->p_fp->i_data_packets_count;
  659.         if( p_sys->i_length > 0 )
  660.         {
  661.             p_sys->i_bitrate = 8 * i_size * (int64_t)1000000 / p_sys->i_length;
  662.         }
  663.     }
  664.     /* Create meta information */
  665.     p_sys->meta = vlc_meta_New();
  666.     if( ( p_cd = ASF_FindObject( p_sys->p_root->p_hdr,
  667.                                  &asf_object_content_description_guid, 0 ) ) )
  668.     {
  669.         if( p_cd->psz_title && *p_cd->psz_title )
  670.         {
  671.             vlc_meta_Add( p_sys->meta, VLC_META_TITLE, p_cd->psz_title );
  672.         }
  673.         if( p_cd->psz_author && *p_cd->psz_author )
  674.         {
  675.              vlc_meta_Add( p_sys->meta, VLC_META_AUTHOR, p_cd->psz_author );
  676.         }
  677.         if( p_cd->psz_copyright && *p_cd->psz_copyright )
  678.         {
  679.             vlc_meta_Add( p_sys->meta, VLC_META_COPYRIGHT, p_cd->psz_copyright );
  680.         }
  681.         if( p_cd->psz_description && *p_cd->psz_description )
  682.         {
  683.             vlc_meta_Add( p_sys->meta, VLC_META_DESCRIPTION, p_cd->psz_description );
  684.         }
  685.         if( p_cd->psz_rating && *p_cd->psz_rating )
  686.         {
  687.             vlc_meta_Add( p_sys->meta, VLC_META_RATING, p_cd->psz_rating );
  688.         }
  689.     }
  690.     for( i_stream = 0, i = 0; i < 128; i++ )
  691.     {
  692.         asf_object_codec_list_t *p_cl = ASF_FindObject( p_sys->p_root->p_hdr,
  693.                                                         &asf_object_codec_list_guid, 0 );
  694.         if( p_sys->track[i] )
  695.         {
  696.             vlc_meta_t *tk = vlc_meta_New();
  697.             TAB_APPEND( p_sys->meta->i_track, p_sys->meta->track, tk );
  698.             if( p_cl && i_stream < p_cl->i_codec_entries_count )
  699.             {
  700.                 if( p_cl->codec[i_stream].psz_name &&
  701.                     *p_cl->codec[i_stream].psz_name )
  702.                 {
  703.                     vlc_meta_Add( tk, VLC_META_CODEC_NAME,
  704.                                   p_cl->codec[i_stream].psz_name );
  705.                 }
  706.                 if( p_cl->codec[i_stream].psz_description &&
  707.                     *p_cl->codec[i_stream].psz_description )
  708.                 {
  709.                     vlc_meta_Add( tk, VLC_META_CODEC_DESCRIPTION,
  710.                                   p_cl->codec[i_stream].psz_description );
  711.                 }
  712.             }
  713.             i_stream++;
  714.         }
  715.     }
  716.     es_out_Control( p_demux->out, ES_OUT_RESET_PCR );
  717.     return VLC_SUCCESS;
  718. error:
  719.     ASF_FreeObjectRoot( p_demux->s, p_sys->p_root );
  720.     return VLC_EGENERIC;
  721. }
  722. /*****************************************************************************
  723.  *
  724.  *****************************************************************************/
  725. static void DemuxEnd( demux_t *p_demux )
  726. {
  727.     demux_sys_t *p_sys = p_demux->p_sys;
  728.     int         i;
  729.     if( p_sys->p_root )
  730.     {
  731.         ASF_FreeObjectRoot( p_demux->s, p_sys->p_root );
  732.         p_sys->p_root = NULL;
  733.     }
  734.     if( p_sys->meta )
  735.     {
  736.         vlc_meta_Delete( p_sys->meta );
  737.         p_sys->meta = NULL;
  738.     }
  739.     for( i = 0; i < 128; i++ )
  740.     {
  741.         asf_track_t *tk = p_sys->track[i];
  742.         if( tk )
  743.         {
  744.             if( tk->p_frame )
  745.             {
  746.                 block_ChainRelease( tk->p_frame );
  747.             }
  748.             if( tk->p_es )
  749.             {
  750.                 es_out_Del( p_demux->out, tk->p_es );
  751.             }
  752.             free( tk );
  753.         }
  754.         p_sys->track[i] = 0;
  755.     }
  756. }