libasf.c
上传用户:kjfoods
上传日期:2020-07-06
资源大小:29949k
文件大小:52k
源码类别:

midi

开发平台:

Unix_Linux

  1. /*****************************************************************************
  2.  * libasf.c : asf stream demux module for vlc
  3.  *****************************************************************************
  4.  * Copyright (C) 2001-2003 the VideoLAN team
  5.  * $Id: 2b719990dec53415a6e7cbec2d0afa48d79ecf1d $
  6.  *
  7.  * Authors: Laurent Aimar <fenrir@via.ecp.fr>
  8.  *          Gildas Bazin <gbazin@videolan.org>
  9.  *
  10.  * This program is free software; you can redistribute it and/or modify
  11.  * it under the terms of the GNU General Public License as published by
  12.  * the Free Software Foundation; either version 2 of the License, or
  13.  * (at your option) any later version.
  14.  *
  15.  * This program is distributed in the hope that it will be useful,
  16.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  18.  * GNU General Public License for more details.
  19.  *
  20.  * You should have received a copy of the GNU General Public License
  21.  * along with this program; if not, write to the Free Software
  22.  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
  23.  *****************************************************************************/
  24. #ifdef HAVE_CONFIG_H
  25. # include "config.h"
  26. #endif
  27. #include <vlc_common.h>
  28. #include <vlc_demux.h>
  29. #include <vlc_codecs.h>                   /* BITMAPINFOHEADER, WAVEFORMATEX */
  30. #include "libasf.h"
  31. #define ASF_DEBUG 1
  32. #define GUID_FMT "0x%x-0x%x-0x%x-0x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x"
  33. #define GUID_PRINT( guid )  
  34.     (guid).v1,              
  35.     (guid).v2,              
  36.     (guid).v3,              
  37.     (guid).v4[0],(guid).v4[1],(guid).v4[2],(guid).v4[3],    
  38.     (guid).v4[4],(guid).v4[5],(guid).v4[6],(guid).v4[7]
  39. /* Helpers:
  40.  * They ensure that invalid reads will not create problems.
  41.  * They are expansion safe
  42.  * They make the following assumptions:
  43.  *  const uint8_t *p_peek exists and points to the start of a buffer
  44.  *  int i_peek gives the size of the buffer pointed by p_peek
  45.  *  const uint8_t *p_data exits and points to the data inside p_peek to be read.
  46.  */
  47. /* ASF_HAVE(n):
  48.  *  Check that n bytes can be read */
  49. static inline bool AsfObjectHelperHave( const uint8_t *p_peek, int i_peek, const uint8_t *p_current, int i_wanted )
  50. {
  51.     if( i_wanted < 0 || i_wanted > i_peek )
  52.         return false;
  53.     return &p_current[i_wanted] <= &p_peek[i_peek];
  54. }
  55. #define ASF_HAVE(n) AsfObjectHelperHave( p_peek, i_peek, p_data, n )
  56. /* ASF_SKIP(n)
  57.  *  Skip n bytes if possible */
  58. static inline void AsfObjectHelperSkip( const uint8_t *p_peek, int i_peek, uint8_t **pp_data, int i_wanted )
  59. {
  60.     if( AsfObjectHelperHave( p_peek, i_peek, *pp_data, i_wanted ) )
  61.         *pp_data += i_wanted;
  62.     else
  63.         *pp_data = (uint8_t*)&p_peek[i_peek];
  64. }
  65. #define ASF_SKIP(n) AsfObjectHelperSkip( p_peek, i_peek, (uint8_t**)&p_data, n )
  66. /* ASF_READX()
  67.  *  Read X byte if possible, else return 0 */
  68. #define ASF_FUNCTION_READ_X(type, x, cmd ) 
  69. static inline type AsfObjectHelperRead##x( const uint8_t *p_peek, int i_peek, uint8_t **pp_data ) { 
  70.     uint8_t *p_data = *pp_data; 
  71.     type i_ret = 0;  
  72.     if( ASF_HAVE(x) )   
  73.         i_ret = cmd;    
  74.     ASF_SKIP(x);        
  75.     *pp_data = p_data;  
  76.     return i_ret;   }
  77. ASF_FUNCTION_READ_X( uint8_t,  1, *p_data )
  78. ASF_FUNCTION_READ_X( uint16_t, 2, GetWLE(p_data) )
  79. ASF_FUNCTION_READ_X( uint32_t, 4, GetDWLE(p_data) )
  80. ASF_FUNCTION_READ_X( uint64_t, 8, GetQWLE(p_data) )
  81. #define ASF_READ1() AsfObjectHelperRead1( p_peek, i_peek, (uint8_t**)&p_data )
  82. #define ASF_READ2() AsfObjectHelperRead2( p_peek, i_peek, (uint8_t**)&p_data )
  83. #define ASF_READ4() AsfObjectHelperRead4( p_peek, i_peek, (uint8_t**)&p_data )
  84. #define ASF_READ8() AsfObjectHelperRead8( p_peek, i_peek, (uint8_t**)&p_data )
  85. /* ASF_READS(n)
  86.  *  Read a string of n/2 wchar long ie n bytes. Do a stupid conversion (suppose latin1)
  87.  *  Return allocated "" if not possible */
  88. static char *AsfObjectHelperReadString( const uint8_t *p_peek, int i_peek, uint8_t **pp_data, int i_size )
  89. {
  90.     uint8_t *p_data = *pp_data;
  91.     char *psz_string;
  92.     if( ASF_HAVE(i_size) )
  93.     {
  94.         psz_string = calloc( i_size/2 + 1, sizeof( char ) );
  95.         if( psz_string )
  96.         {
  97.             int i;
  98.             for( i = 0; i < i_size/2; i++ )
  99.                 psz_string[i] = GetWLE( &p_data[2*i] );
  100.             psz_string[i_size/2] = ''; 
  101.         }
  102.     }
  103.     else
  104.     {
  105.         psz_string = strdup("");
  106.     }
  107.     ASF_SKIP(i_size);
  108.     *pp_data = p_data;
  109.     return psz_string;
  110. }
  111. #define ASF_READS(n) AsfObjectHelperReadString( p_peek, i_peek, (uint8_t**)&p_data, n )
  112. /****************************************************************************
  113.  *
  114.  ****************************************************************************/
  115. static int ASF_ReadObject( stream_t *, asf_object_t *,  asf_object_t * );
  116. /****************************************************************************
  117.  * GUID functions
  118.  ****************************************************************************/
  119. void ASF_GetGUID( guid_t *p_guid, const uint8_t *p_data )
  120. {
  121.     p_guid->v1 = GetDWLE( p_data );
  122.     p_guid->v2 = GetWLE( p_data + 4);
  123.     p_guid->v3 = GetWLE( p_data + 6);
  124.     memcpy( p_guid->v4, p_data + 8, 8 );
  125. }
  126. bool ASF_CmpGUID( const guid_t *p_guid1, const guid_t *p_guid2 )
  127. {
  128.     if( (p_guid1->v1 != p_guid2->v1 )||
  129.         (p_guid1->v2 != p_guid2->v2 )||
  130.         (p_guid1->v3 != p_guid2->v3 )||
  131.         ( memcmp( p_guid1->v4, p_guid2->v4,8 )) )
  132.     {
  133.         return false;
  134.     }
  135.     return true;
  136. }
  137. /****************************************************************************
  138.  *
  139.  ****************************************************************************/
  140. static int ASF_ReadObjectCommon( stream_t *s, asf_object_t *p_obj )
  141. {
  142.     asf_object_common_t *p_common = &p_obj->common;
  143.     const uint8_t *p_peek;
  144.     if( stream_Peek( s, &p_peek, 24 ) < 24 )
  145.         return VLC_EGENERIC;
  146.     ASF_GetGUID( &p_common->i_object_id, p_peek );
  147.     p_common->i_object_size = GetQWLE( p_peek + 16 );
  148.     p_common->i_object_pos  = stream_Tell( s );
  149.     p_common->p_next = NULL;
  150. #ifdef ASF_DEBUG
  151.     msg_Dbg( s,
  152.              "found object guid: " GUID_FMT " size:%"PRId64,
  153.              GUID_PRINT( p_common->i_object_id ),
  154.              p_common->i_object_size );
  155. #endif
  156.     return VLC_SUCCESS;
  157. }
  158. static int ASF_NextObject( stream_t *s, asf_object_t *p_obj )
  159. {
  160.     asf_object_t obj;
  161.     if( p_obj == NULL )
  162.     {
  163.         if( ASF_ReadObjectCommon( s, &obj ) )
  164.             return VLC_EGENERIC;
  165.         p_obj = &obj;
  166.     }
  167.     if( p_obj->common.i_object_size <= 0 )
  168.         return VLC_EGENERIC;
  169.     if( p_obj->common.p_father &&
  170.         p_obj->common.p_father->common.i_object_size != 0 )
  171.     {
  172.         if( p_obj->common.p_father->common.i_object_pos +
  173.             p_obj->common.p_father->common.i_object_size <
  174.                 p_obj->common.i_object_pos + p_obj->common.i_object_size + 24 )
  175.                                 /* 24 is min size of an object */
  176.         {
  177.             return VLC_EGENERIC;
  178.         }
  179.     }
  180.     return stream_Seek( s, p_obj->common.i_object_pos +
  181.                         p_obj->common.i_object_size );
  182. }
  183. static void ASF_FreeObject_Null( asf_object_t *pp_obj )
  184. {
  185.     VLC_UNUSED(pp_obj);
  186. }
  187. static int  ASF_ReadObject_Header( stream_t *s, asf_object_t *p_obj )
  188. {
  189.     asf_object_header_t *p_hdr = &p_obj->header;
  190.     asf_object_t        *p_subobj;
  191.     int                 i_peek;
  192.     const uint8_t       *p_peek;
  193.     if( ( i_peek = stream_Peek( s, &p_peek, 30 ) ) < 30 )
  194.        return VLC_EGENERIC;
  195.     p_hdr->i_sub_object_count = GetDWLE( p_peek + 24 );
  196.     p_hdr->i_reserved1 = p_peek[28];
  197.     p_hdr->i_reserved2 = p_peek[29];
  198.     p_hdr->p_first = NULL;
  199.     p_hdr->p_last  = NULL;
  200. #ifdef ASF_DEBUG
  201.     msg_Dbg( s,
  202.              "read "header object" subobj:%d, reserved1:%d, reserved2:%d",
  203.              p_hdr->i_sub_object_count,
  204.              p_hdr->i_reserved1,
  205.              p_hdr->i_reserved2 );
  206. #endif
  207.     /* Cannot fail as peek succeed */
  208.     stream_Read( s, NULL, 30 );
  209.     /* Now load sub object */
  210.     for( ; ; )
  211.     {
  212.         p_subobj = malloc( sizeof( asf_object_t ) );
  213.         if( !p_subobj || ASF_ReadObject( s, p_subobj, (asf_object_t*)p_hdr ) )
  214.         {
  215.             free( p_subobj );
  216.             break;
  217.         }
  218.         if( ASF_NextObject( s, p_subobj ) ) /* Go to the next object */
  219.             break;
  220.     }
  221.     return VLC_SUCCESS;
  222. }
  223. static int ASF_ReadObject_Data( stream_t *s, asf_object_t *p_obj )
  224. {
  225.     asf_object_data_t *p_data = &p_obj->data;
  226.     int               i_peek;
  227.     const uint8_t     *p_peek;
  228.     if( ( i_peek = stream_Peek( s, &p_peek, 50 ) ) < 50 )
  229.        return VLC_EGENERIC;
  230.     ASF_GetGUID( &p_data->i_file_id, p_peek + 24 );
  231.     p_data->i_total_data_packets = GetQWLE( p_peek + 40 );
  232.     p_data->i_reserved = GetWLE( p_peek + 48 );
  233. #ifdef ASF_DEBUG
  234.     msg_Dbg( s,
  235.              "read "data object" file_id:" GUID_FMT " total data packet:"
  236.              "%"PRId64" reserved:%d",
  237.              GUID_PRINT( p_data->i_file_id ),
  238.              p_data->i_total_data_packets,
  239.              p_data->i_reserved );
  240. #endif
  241.     return VLC_SUCCESS;
  242. }
  243. static int ASF_ReadObject_Index( stream_t *s, asf_object_t *p_obj )
  244. {
  245.     asf_object_index_t *p_index = &p_obj->index;
  246.     const uint8_t      *p_peek;
  247.     unsigned int       i;
  248.     /* We just ignore error on the index */
  249.     if( stream_Peek( s, &p_peek, p_index->i_object_size ) <
  250.         __MAX( (int64_t)p_index->i_object_size, 56 ) )
  251.         return VLC_SUCCESS;
  252.     ASF_GetGUID( &p_index->i_file_id, p_peek + 24 );
  253.     p_index->i_index_entry_time_interval = GetQWLE( p_peek + 40 );
  254.     p_index->i_max_packet_count = GetDWLE( p_peek + 48 );
  255.     p_index->i_index_entry_count = GetDWLE( p_peek + 52 );
  256.     p_index->index_entry = NULL;
  257. #ifdef ASF_DEBUG
  258.     msg_Dbg( s,
  259.             "read "index object" file_id:" GUID_FMT
  260.             " index_entry_time_interval:%"PRId64" max_packet_count:%d "
  261.             "index_entry_count:%ld",
  262.             GUID_PRINT( p_index->i_file_id ),
  263.             p_index->i_index_entry_time_interval,
  264.             p_index->i_max_packet_count,
  265.             (long int)p_index->i_index_entry_count );
  266. #endif
  267.     /* Sanity checking */
  268.     if( p_index->i_index_entry_count > (p_index->i_object_size - 56) / 6 )
  269.         p_index->i_index_entry_count = (p_index->i_object_size - 56) / 6;
  270.     p_index->index_entry = calloc( p_index->i_index_entry_count,
  271.                                    sizeof(asf_index_entry_t) );
  272.     if( !p_index->index_entry )
  273.         return VLC_ENOMEM;
  274.     for( i = 0, p_peek += 56; i < p_index->i_index_entry_count; i++, p_peek += 6 )
  275.     {
  276.         p_index->index_entry[i].i_packet_number = GetDWLE( p_peek );
  277.         p_index->index_entry[i].i_packet_count = GetDWLE( p_peek + 4 );
  278.     }
  279.     return VLC_SUCCESS;
  280. }
  281. static void ASF_FreeObject_Index( asf_object_t *p_obj )
  282. {
  283.     asf_object_index_t *p_index = &p_obj->index;
  284.     FREENULL( p_index->index_entry );
  285. }
  286. static int ASF_ReadObject_file_properties( stream_t *s, asf_object_t *p_obj )
  287. {
  288.     asf_object_file_properties_t *p_fp = &p_obj->file_properties;
  289.     int           i_peek;
  290.     const uint8_t *p_peek;
  291.     if( ( i_peek = stream_Peek( s, &p_peek,  104 ) ) < 104 )
  292.        return VLC_EGENERIC;
  293.     ASF_GetGUID( &p_fp->i_file_id, p_peek + 24 );
  294.     p_fp->i_file_size = GetQWLE( p_peek + 40 );
  295.     p_fp->i_creation_date = GetQWLE( p_peek + 48 );
  296.     p_fp->i_data_packets_count = GetQWLE( p_peek + 56 );
  297.     p_fp->i_play_duration = GetQWLE( p_peek + 64 );
  298.     p_fp->i_send_duration = GetQWLE( p_peek + 72 );
  299.     p_fp->i_preroll = GetQWLE( p_peek + 80 );
  300.     p_fp->i_flags = GetDWLE( p_peek + 88 );
  301.     p_fp->i_min_data_packet_size = GetDWLE( p_peek + 92 );
  302.     p_fp->i_max_data_packet_size = GetDWLE( p_peek + 96 );
  303.     p_fp->i_max_bitrate = GetDWLE( p_peek + 100 );
  304. #ifdef ASF_DEBUG
  305.     msg_Dbg( s,
  306.             "read "file properties object" file_id:" GUID_FMT
  307.             " file_size:%"PRId64" creation_date:%"PRId64" data_packets_count:"
  308.             "%"PRId64" play_duration:%"PRId64" send_duration:%"PRId64" preroll:%"PRId64
  309.             " flags:%d min_data_packet_size:%d "
  310.             " max_data_packet_size:%d max_bitrate:%d",
  311.             GUID_PRINT( p_fp->i_file_id ), p_fp->i_file_size,
  312.             p_fp->i_creation_date, p_fp->i_data_packets_count,
  313.             p_fp->i_play_duration, p_fp->i_send_duration,
  314.             p_fp->i_preroll, p_fp->i_flags,
  315.             p_fp->i_min_data_packet_size, p_fp->i_max_data_packet_size,
  316.             p_fp->i_max_bitrate );
  317. #endif
  318.     return VLC_SUCCESS;
  319. }
  320. static void ASF_FreeObject_metadata( asf_object_t *p_obj )
  321. {
  322.     asf_object_metadata_t *p_meta = &p_obj->metadata;
  323.     unsigned int i;
  324.     for( i = 0; i < p_meta->i_record_entries_count; i++ )
  325.     {
  326.         free( p_meta->record[i].psz_name );
  327.         free( p_meta->record[i].p_data );
  328.     }
  329.     free( p_meta->record );
  330. }
  331. static int ASF_ReadObject_metadata( stream_t *s, asf_object_t *p_obj )
  332. {
  333.     asf_object_metadata_t *p_meta = &p_obj->metadata;
  334.     int i_peek;
  335.     unsigned int i;
  336.     const uint8_t *p_peek, *p_data;
  337. #ifdef ASF_DEBUG
  338.     unsigned int j;
  339. #endif
  340.     if( ( i_peek = stream_Peek( s, &p_peek, p_meta->i_object_size ) ) <
  341.         __MAX( (int64_t)p_meta->i_object_size, 26 ) )
  342.        return VLC_EGENERIC;
  343.     p_meta->i_record_entries_count = GetWLE( p_peek + 24 );
  344.     p_data = p_peek + 26;
  345.     p_meta->record = calloc( p_meta->i_record_entries_count,
  346.                              sizeof(asf_metadata_record_t) );
  347.     if( !p_meta->record )
  348.         return VLC_ENOMEM;
  349.     for( i = 0; i < p_meta->i_record_entries_count; i++ )
  350.     {
  351.         asf_metadata_record_t *p_record = &p_meta->record[i];
  352.         int i_name;
  353.         int i_data;
  354.         if( !ASF_HAVE( 2+2+2+2+4 ) )
  355.             break;
  356.         if( ASF_READ2() != 0 )
  357.             break;
  358.         p_record->i_stream = ASF_READ2();
  359.         i_name = ASF_READ2();
  360.         p_record->i_type = ASF_READ2();
  361.         i_data = ASF_READ4();
  362.         if( !ASF_HAVE( i_name + i_data ) )
  363.             break;
  364.         /* Read name */
  365.         p_record->psz_name = ASF_READS( i_name );
  366.         /* Read data */
  367.         if( p_record->i_type == ASF_METADATA_TYPE_STRING )
  368.         {
  369.             p_record->p_data = ASF_READS( i_data );
  370.             p_record->i_data = i_data/2; /* FIXME Is that needed ? */
  371.         }
  372.         else if( p_record->i_type == ASF_METADATA_TYPE_BYTE )
  373.         {
  374.             p_record->p_data = malloc( i_data );
  375.             p_record->i_data = i_data;
  376.             if( p_record->p_data && i_data > 0 )
  377.                 memcpy( p_record->p_data, p_data, i_data );
  378.             p_data += i_data;
  379.         }
  380.         else if( p_record->i_type == ASF_METADATA_TYPE_QWORD )
  381.         {
  382.             p_record->i_val = ASF_READ8();
  383.         }
  384.         else if( p_record->i_type == ASF_METADATA_TYPE_DWORD )
  385.         {
  386.             p_record->i_val = ASF_READ4();
  387.         }
  388.         else if( p_record->i_type == ASF_METADATA_TYPE_WORD )
  389.         {
  390.             p_record->i_val = ASF_READ2();
  391.         }
  392.         else if( p_record->i_type == ASF_METADATA_TYPE_BOOL )
  393.         {
  394.             p_record->i_val = ASF_READ2();
  395.         }
  396.         else
  397.         {
  398.             /* Unknown */
  399.             p_data += i_data;
  400.         }
  401.     }
  402.     p_meta->i_record_entries_count = i;
  403. #ifdef ASF_DEBUG
  404.     msg_Dbg( s,
  405.             "read "metadata object" %d entries",
  406.             p_meta->i_record_entries_count );
  407.     for( j = 0; j < p_meta->i_record_entries_count; j++ )
  408.     {
  409.         asf_metadata_record_t *p_rec = &p_meta->record[j];
  410.         if( p_rec->i_type == ASF_METADATA_TYPE_STRING )
  411.             msg_Dbg( s, "  - %s=%s",
  412.                      p_rec->psz_name, p_rec->p_data );
  413.         else if( p_rec->i_type == ASF_METADATA_TYPE_BYTE )
  414.             msg_Dbg( s, "  - %s (%i bytes)",
  415.                      p_rec->psz_name, p_rec->i_data );
  416.         else
  417.             msg_Dbg( s, "  - %s=%"PRId64,
  418.                      p_rec->psz_name, p_rec->i_val );
  419.     }
  420. #endif
  421.     return VLC_SUCCESS;
  422. }
  423. static int ASF_ReadObject_header_extension( stream_t *s, asf_object_t *p_obj )
  424. {
  425.     asf_object_header_extension_t *p_he = &p_obj->header_extension;
  426.     int     i_peek;
  427.     const uint8_t *p_peek;
  428.     if( ( i_peek = stream_Peek( s, &p_peek, p_he->i_object_size ) ) <  46)
  429.     {
  430.        return VLC_EGENERIC;
  431.     }
  432.     ASF_GetGUID( &p_he->i_reserved1, p_peek + 24 );
  433.     p_he->i_reserved2 = GetWLE( p_peek + 40 );
  434.     p_he->i_header_extension_size = GetDWLE( p_peek + 42 );
  435.     if( p_he->i_header_extension_size )
  436.     {
  437.         if( (unsigned int)(i_peek-46) < p_he->i_header_extension_size )
  438.             return VLC_EGENERIC;
  439.         p_he->p_header_extension_data =
  440.             malloc( p_he->i_header_extension_size );
  441.         if( !p_he->p_header_extension_data )
  442.             return VLC_ENOMEM;
  443.         memcpy( p_he->p_header_extension_data, p_peek + 46,
  444.                 p_he->i_header_extension_size );
  445.     }
  446.     else
  447.     {
  448.         p_he->p_header_extension_data = NULL;
  449.     }
  450. #ifdef ASF_DEBUG
  451.     msg_Dbg( s,
  452.             "read "header extension object" reserved1:" GUID_FMT
  453.             " reserved2:%d header_extension_size:%d",
  454.             GUID_PRINT( p_he->i_reserved1 ), p_he->i_reserved2,
  455.             p_he->i_header_extension_size );
  456. #endif
  457.     if( !p_he->i_header_extension_size ) return VLC_SUCCESS;
  458.     /* Read the extension objects */
  459.     stream_Read( s, NULL, 46 );
  460.     for( ; ; )
  461.     {
  462.         asf_object_t *p_obj = malloc( sizeof( asf_object_t ) );
  463.         if( !p_obj || ASF_ReadObject( s, p_obj, (asf_object_t*)p_he ) )
  464.         {
  465.             free( p_obj );
  466.             break;
  467.         }
  468.         if( ASF_NextObject( s, p_obj ) ) /* Go to the next object */
  469.         {
  470.             break;
  471.         }
  472.     }
  473.     return VLC_SUCCESS;
  474. }
  475. static void ASF_FreeObject_header_extension( asf_object_t *p_obj )
  476. {
  477.     asf_object_header_extension_t *p_he = &p_obj->header_extension;
  478.     FREENULL( p_he->p_header_extension_data );
  479. }
  480. static int ASF_ReadObject_stream_properties( stream_t *s, asf_object_t *p_obj )
  481. {
  482.     asf_object_stream_properties_t *p_sp = &p_obj->stream_properties;
  483.     size_t        i_peek;
  484.     const uint8_t *p_peek;
  485.     if( ( i_peek = stream_Peek( s, &p_peek,  p_sp->i_object_size ) ) < 78 )
  486.        return VLC_EGENERIC;
  487.     ASF_GetGUID( &p_sp->i_stream_type, p_peek + 24 );
  488.     ASF_GetGUID( &p_sp->i_error_correction_type, p_peek + 40 );
  489.     p_sp->i_time_offset = GetQWLE( p_peek + 56 );
  490.     p_sp->i_type_specific_data_length = GetDWLE( p_peek + 64 );
  491.     p_sp->i_error_correction_data_length = GetDWLE( p_peek + 68 );
  492.     p_sp->i_flags = GetWLE( p_peek + 72 );
  493.         p_sp->i_stream_number = p_sp->i_flags&0x07f;
  494.     p_sp->i_reserved = GetDWLE( p_peek + 74 );
  495.     i_peek -= 78;
  496.     if( p_sp->i_type_specific_data_length )
  497.     {
  498.         if( i_peek < p_sp->i_type_specific_data_length )
  499.             return VLC_EGENERIC;
  500.         p_sp->p_type_specific_data =
  501.             malloc( p_sp->i_type_specific_data_length );
  502.         if( !p_sp->p_type_specific_data )
  503.             return VLC_ENOMEM;
  504.         memcpy( p_sp->p_type_specific_data, p_peek + 78,
  505.                 p_sp->i_type_specific_data_length );
  506.         i_peek -= p_sp->i_type_specific_data_length;
  507.     }
  508.     if( p_sp->i_error_correction_data_length )
  509.     {
  510.         if( i_peek < p_sp->i_error_correction_data_length )
  511.         {
  512.             free( p_sp->p_type_specific_data );
  513.             return VLC_EGENERIC;
  514.         }
  515.         p_sp->p_error_correction_data =
  516.             malloc( p_sp->i_error_correction_data_length );
  517.         if( !p_sp->p_error_correction_data )
  518.         {
  519.             free( p_sp->p_type_specific_data );
  520.             return VLC_ENOMEM;
  521.         }
  522.         memcpy( p_sp->p_error_correction_data,
  523.                 p_peek + 78 + p_sp->i_type_specific_data_length,
  524.                 p_sp->i_error_correction_data_length );
  525.     }
  526. #ifdef ASF_DEBUG
  527.     msg_Dbg( s,
  528.             "read "stream Properties object" stream_type:" GUID_FMT
  529.             " error_correction_type:" GUID_FMT " time_offset:%"PRId64
  530.             " type_specific_data_length:%d error_correction_data_length:%d"
  531.             " flags:0x%x stream_number:%d",
  532.             GUID_PRINT( p_sp->i_stream_type ),
  533.             GUID_PRINT( p_sp->i_error_correction_type ),
  534.             p_sp->i_time_offset,
  535.             p_sp->i_type_specific_data_length,
  536.             p_sp->i_error_correction_data_length,
  537.             p_sp->i_flags,
  538.             p_sp->i_stream_number );
  539. #endif
  540.     return VLC_SUCCESS;
  541. }
  542. static void ASF_FreeObject_stream_properties( asf_object_t *p_obj )
  543. {
  544.     asf_object_stream_properties_t *p_sp = &p_obj->stream_properties;
  545.     FREENULL( p_sp->p_type_specific_data );
  546.     FREENULL( p_sp->p_error_correction_data );
  547. }
  548. static int ASF_ReadObject_codec_list( stream_t *s, asf_object_t *p_obj )
  549. {
  550.     asf_object_codec_list_t *p_cl = &p_obj->codec_list;
  551.     int     i_peek;
  552.     const uint8_t *p_peek, *p_data;
  553.     unsigned int i_codec;
  554.     if( ( i_peek = stream_Peek( s, &p_peek, p_cl->i_object_size ) ) < 44 )
  555.        return VLC_EGENERIC;
  556.     ASF_GetGUID( &p_cl->i_reserved, p_peek + 24 );
  557.     p_cl->i_codec_entries_count = GetWLE( p_peek + 40 );
  558.     p_data = p_peek + 44;
  559.     if( p_cl->i_codec_entries_count > 0 )
  560.     {
  561.         p_cl->codec = calloc( p_cl->i_codec_entries_count,
  562.                               sizeof( asf_codec_entry_t ) );
  563.         if( !p_cl->codec )
  564.             return VLC_ENOMEM;
  565.         for( i_codec = 0; i_codec < p_cl->i_codec_entries_count; i_codec++ )
  566.         {
  567.             asf_codec_entry_t *p_codec = &p_cl->codec[i_codec];
  568.             if( !ASF_HAVE( 2+2+2 ) )
  569.                 break;
  570.             /* */
  571.             p_codec->i_type = ASF_READ2();
  572.             /* XXX the length here are the number of *unicode* characters and
  573.              * not of bytes like nearly every elsewhere */
  574.             /* codec name */
  575.             p_codec->psz_name = ASF_READS( 2*ASF_READ2() );
  576.             /* description */
  577.             p_codec->psz_description = ASF_READS( 2*ASF_READ2() );
  578.             /* opaque information */
  579.             p_codec->i_information_length = ASF_READ2();
  580.             if( p_codec->i_information_length > 0 && ASF_HAVE( p_codec->i_information_length ) )
  581.             {
  582.                 p_codec->p_information = malloc( p_codec->i_information_length );
  583.                 if( p_codec->p_information )
  584.                     memcpy( p_codec->p_information, p_data, p_codec->i_information_length );
  585.                 else
  586.                     p_codec->i_information_length = 0;
  587.                 p_data += p_codec->i_information_length;
  588.             }
  589.         }
  590.         p_cl->i_codec_entries_count = i_codec;
  591.     }
  592. #ifdef ASF_DEBUG
  593.     msg_Dbg( s, "read "codec list object" reserved_guid:" GUID_FMT
  594.              " codec_entries_count:%d",
  595.             GUID_PRINT( p_cl->i_reserved ), p_cl->i_codec_entries_count );
  596.     for( i_codec = 0; i_codec < p_cl->i_codec_entries_count; i_codec++ )
  597.     {
  598.         const asf_codec_entry_t *p_codec = &p_cl->codec[i_codec];
  599.         msg_Dbg( s, "  - codec[%d] %s name:"%s" "
  600.                  "description:"%s" information_length:%d",
  601.                  i_codec, ( p_codec->i_type == ASF_CODEC_TYPE_VIDEO ) ?
  602.                  "video" : ( ( p_codec->i_type == ASF_CODEC_TYPE_AUDIO ) ?
  603.                  "audio" : "unknown" ),
  604.                  p_codec->psz_name, p_codec->psz_description,
  605.                  p_codec->i_information_length );
  606.     }
  607. #endif
  608.     return VLC_SUCCESS;
  609. }
  610. static void ASF_FreeObject_codec_list( asf_object_t *p_obj )
  611. {
  612.     asf_object_codec_list_t *p_cl = &p_obj->codec_list;
  613.     unsigned int i_codec;
  614.     for( i_codec = 0; i_codec < p_cl->i_codec_entries_count; i_codec++ )
  615.     {
  616.         asf_codec_entry_t *p_codec = &p_cl->codec[i_codec];
  617.         FREENULL( p_codec->psz_name );
  618.         FREENULL( p_codec->psz_description );
  619.         FREENULL( p_codec->p_information );
  620.     }
  621.     FREENULL( p_cl->codec );
  622. }
  623. /* Microsoft should go to hell. This time the length give number of bytes
  624.  * and for the some others object, length give char16 count ... */
  625. static int ASF_ReadObject_content_description(stream_t *s, asf_object_t *p_obj)
  626. {
  627.     asf_object_content_description_t *p_cd = &p_obj->content_description;
  628.     const uint8_t *p_peek, *p_data;
  629.     int i_peek, i_title, i_artist, i_copyright, i_description, i_rating;
  630.     vlc_iconv_t cd = (vlc_iconv_t)-1;
  631.     const char *ib = NULL;
  632.     char *ob = NULL;
  633.     size_t i_ibl, i_obl, i_len;
  634.     if( ( i_peek = stream_Peek( s, &p_peek, p_cd->i_object_size ) ) < 34 )
  635.        return VLC_EGENERIC;
  636.     cd = vlc_iconv_open("UTF-8", "UTF-16LE");
  637.     if( cd == (vlc_iconv_t)-1 )
  638.     {
  639.         msg_Err( s, "vlc_iconv_open failed" );
  640.         return VLC_EGENERIC;
  641.     }
  642. /* FIXME i_size*3 is the worst case. */
  643. #define GETSTRINGW( psz_str, i_size ) do { 
  644.     psz_str = calloc( i_size*3+1, sizeof(char) ); 
  645.     if( psz_str ) { 
  646.         ib = (const char *)p_data; 
  647.         ob = psz_str; 
  648.         i_ibl = i_size; 
  649.         i_obl = i_size*3; 
  650.         i_len = vlc_iconv(cd, &ib, &i_ibl, &ob, &i_obl); 
  651.         p_data += i_size; 
  652.     } } while(0)
  653.     p_data = p_peek + 24;
  654.     
  655.     i_title         = ASF_READ2();
  656.     i_artist        = ASF_READ2();
  657.     i_copyright     = ASF_READ2();
  658.     i_description   = ASF_READ2();
  659.     i_rating        = ASF_READ2();
  660.     if( !ASF_HAVE( i_title+i_artist+i_copyright+i_description+i_rating ) )
  661.     {
  662.         vlc_iconv_close( cd );
  663.         return VLC_EGENERIC;
  664.     }
  665.     GETSTRINGW( p_cd->psz_title, i_title );
  666.     GETSTRINGW( p_cd->psz_artist, i_artist );
  667.     GETSTRINGW( p_cd->psz_copyright, i_copyright );
  668.     GETSTRINGW( p_cd->psz_description, i_description );
  669.     GETSTRINGW( p_cd->psz_rating, i_rating );
  670. #undef  GETSTRINGW
  671. #ifdef ASF_DEBUG
  672.     msg_Dbg( s,
  673.              "read "content description object" title:"%s" artist:"%s" copyright:"%s" description:"%s" rating:"%s"",
  674.              p_cd->psz_title,
  675.              p_cd->psz_artist,
  676.              p_cd->psz_copyright,
  677.              p_cd->psz_description,
  678.              p_cd->psz_rating );
  679. #endif
  680.     vlc_iconv_close(cd);
  681.     return VLC_SUCCESS;
  682. }
  683. static void ASF_FreeObject_content_description( asf_object_t *p_obj)
  684. {
  685.     asf_object_content_description_t *p_cd = &p_obj->content_description;
  686.     FREENULL( p_cd->psz_title );
  687.     FREENULL( p_cd->psz_artist );
  688.     FREENULL( p_cd->psz_copyright );
  689.     FREENULL( p_cd->psz_description );
  690.     FREENULL( p_cd->psz_rating );
  691. }
  692. /* Language list: */
  693. static int ASF_ReadObject_language_list(stream_t *s, asf_object_t *p_obj)
  694. {
  695.     asf_object_language_list_t *p_ll = &p_obj->language_list;
  696.     const uint8_t *p_peek, *p_data;
  697.     int i_peek;
  698.     int i;
  699.     if( ( i_peek = stream_Peek( s, &p_peek, p_ll->i_object_size ) ) < 26 )
  700.        return VLC_EGENERIC;
  701.     p_data = &p_peek[24];
  702.     p_ll->i_language = ASF_READ2();
  703.     if( p_ll->i_language > 0 )
  704.     {
  705.         p_ll->ppsz_language = calloc( p_ll->i_language, sizeof( char *) );
  706.         if( !p_ll->ppsz_language )
  707.             return VLC_ENOMEM;
  708.         for( i = 0; i < p_ll->i_language; i++ )
  709.         {
  710.             if( !ASF_HAVE(1) )
  711.                 break;
  712.             p_ll->ppsz_language[i] = ASF_READS( ASF_READ1() );
  713.         }
  714.         p_ll->i_language = i;
  715.     }
  716. #ifdef ASF_DEBUG
  717.     msg_Dbg( s, "read "language list object" %d entries",
  718.              p_ll->i_language );
  719.     for( i = 0; i < p_ll->i_language; i++ )
  720.         msg_Dbg( s, "  - '%s'",
  721.                  p_ll->ppsz_language[i] );
  722. #endif
  723.     return VLC_SUCCESS;
  724. }
  725. static void ASF_FreeObject_language_list( asf_object_t *p_obj)
  726. {
  727.     asf_object_language_list_t *p_ll = &p_obj->language_list;
  728.     int i;
  729.     for( i = 0; i < p_ll->i_language; i++ )
  730.         FREENULL( p_ll->ppsz_language[i] );
  731.     FREENULL( p_ll->ppsz_language );
  732. }
  733. /* Stream bitrate properties */
  734. static int ASF_ReadObject_stream_bitrate_properties( stream_t *s,
  735.                                                      asf_object_t *p_obj)
  736. {
  737.     asf_object_stream_bitrate_properties_t *p_sb = &p_obj->stream_bitrate;
  738.     const uint8_t *p_peek, *p_data;
  739.     int i_peek;
  740.     int i;
  741.     if( ( i_peek = stream_Peek( s, &p_peek, p_sb->i_object_size ) ) < 26 )
  742.        return VLC_EGENERIC;
  743.     p_data = &p_peek[24];
  744.     p_sb->i_bitrate = ASF_READ2();
  745.     if( p_sb->i_bitrate > 127 )
  746.         p_sb->i_bitrate = 127;  /* Buggy ? */
  747.     for( i = 0; i < p_sb->i_bitrate; i++ )
  748.     {
  749.         if( !ASF_HAVE(2 + 4) )
  750.             break;
  751.         p_sb->bitrate[i].i_stream_number = ASF_READ2()& 0x7f;
  752.         p_sb->bitrate[i].i_avg_bitrate = ASF_READ4();
  753.     }
  754.     p_sb->i_bitrate = i;
  755. #ifdef ASF_DEBUG
  756.     msg_Dbg( s,"read "stream bitrate properties object"" );
  757.     for( i = 0; i < p_sb->i_bitrate; i++ )
  758.     {
  759.         msg_Dbg( s,"  - stream=%d bitrate=%d",
  760.                  p_sb->bitrate[i].i_stream_number,
  761.                  p_sb->bitrate[i].i_avg_bitrate );
  762.     }
  763. #endif
  764.     return VLC_SUCCESS;
  765. }
  766. static void ASF_FreeObject_stream_bitrate_properties( asf_object_t *p_obj)
  767. {
  768.     VLC_UNUSED(p_obj);
  769. }
  770. static int ASF_ReadObject_extended_stream_properties( stream_t *s,
  771.                                                       asf_object_t *p_obj)
  772. {
  773.     asf_object_extended_stream_properties_t *p_esp = &p_obj->ext_stream;
  774.     const uint8_t *p_peek, *p_data;
  775.     int i_peek, i;
  776.     if( ( i_peek = stream_Peek( s, &p_peek, p_esp->i_object_size ) ) < 88 )
  777.        return VLC_EGENERIC;
  778.     p_data = &p_peek[24];
  779.     p_esp->i_start_time = GetQWLE( &p_data[0] );
  780.     p_esp->i_end_time = GetQWLE( &p_data[8] );
  781.     p_esp->i_data_bitrate = GetDWLE( &p_data[16] );
  782.     p_esp->i_buffer_size = GetDWLE( &p_data[20] );
  783.     p_esp->i_initial_buffer_fullness = GetDWLE( &p_data[24] );
  784.     p_esp->i_alternate_data_bitrate = GetDWLE( &p_data[28] );
  785.     p_esp->i_alternate_buffer_size = GetDWLE( &p_data[32] );
  786.     p_esp->i_alternate_initial_buffer_fullness = GetDWLE( &p_data[36] );
  787.     p_esp->i_maximum_object_size = GetDWLE( &p_data[40] );
  788.     p_esp->i_flags = GetDWLE( &p_data[44] );
  789.     p_esp->i_stream_number = GetWLE( &p_data[48] );
  790.     p_esp->i_language_index = GetWLE( &p_data[50] );
  791.     p_esp->i_average_time_per_frame= GetQWLE( &p_data[52] );
  792.     p_esp->i_stream_name_count = GetWLE( &p_data[60] );
  793.     p_esp->i_payload_extension_system_count = GetWLE( &p_data[62] );
  794.     p_data += 64;
  795.     p_esp->pi_stream_name_language = calloc( p_esp->i_stream_name_count,
  796.                                              sizeof(int) );
  797.     p_esp->ppsz_stream_name = calloc( p_esp->i_stream_name_count,
  798.                                       sizeof(char*) );
  799.     if( !p_esp->pi_stream_name_language ||
  800.         !p_esp->ppsz_stream_name )
  801.     {
  802.         free( p_esp->pi_stream_name_language );
  803.         free( p_esp->ppsz_stream_name );
  804.         return VLC_ENOMEM;
  805.     }
  806.     for( i = 0; i < p_esp->i_stream_name_count; i++ )
  807.     {
  808.         if( !ASF_HAVE( 2+2 ) )
  809.             break;
  810.         p_esp->pi_stream_name_language[i] = ASF_READ2();
  811.         p_esp->ppsz_stream_name[i] = ASF_READS( ASF_READ2() );
  812.     }
  813.     p_esp->i_stream_name_count = i;
  814.     for( i = 0; i < p_esp->i_payload_extension_system_count; i++ )
  815.     {
  816.         ASF_SKIP( 16 );   // GUID
  817.         ASF_SKIP( 2 );
  818.         ASF_SKIP( ASF_READ4() );
  819.     }
  820.     p_esp->p_sp = NULL;
  821.     if( p_data < &p_peek[i_peek] )
  822.     {
  823.         asf_object_t *p_sp;
  824.         /* Cannot fail as peek succeed */
  825.         stream_Read( s, NULL, p_data - p_peek );
  826.  
  827.         p_sp = malloc( sizeof( asf_object_t ) );
  828.         if( !p_sp || ASF_ReadObject( s, p_sp, NULL ) )
  829.         {
  830.             free( p_sp );
  831.         }
  832.         else
  833.         {
  834.             /* This p_sp will be inserted by ReadRoot later */
  835.             p_esp->p_sp = (asf_object_stream_properties_t*)p_sp;
  836.         }
  837.     }
  838. #ifdef ASF_DEBUG
  839.     msg_Dbg( s, "read "extended stream properties object":" );
  840.     msg_Dbg( s, "  - start=%"PRId64" end=%"PRId64,
  841.              p_esp->i_start_time, p_esp->i_end_time );
  842.     msg_Dbg( s, "  - data bitrate=%d buffer=%d initial fullness=%d",
  843.              p_esp->i_data_bitrate,
  844.              p_esp->i_buffer_size,
  845.              p_esp->i_initial_buffer_fullness );
  846.     msg_Dbg( s, "  - alternate data bitrate=%d buffer=%d initial fullness=%d",
  847.              p_esp->i_alternate_data_bitrate,
  848.              p_esp->i_alternate_buffer_size,
  849.              p_esp->i_alternate_initial_buffer_fullness );
  850.     msg_Dbg( s, "  - maximum object size=%d", p_esp->i_maximum_object_size );
  851.     msg_Dbg( s, "  - flags=0x%x", p_esp->i_flags );
  852.     msg_Dbg( s, "  - stream number=%d language=%d",
  853.              p_esp->i_stream_number, p_esp->i_language_index );
  854.     msg_Dbg( s, "  - average time per frame=%"PRId64,
  855.              p_esp->i_average_time_per_frame );
  856.     msg_Dbg( s, "  - stream name count=%d", p_esp->i_stream_name_count );
  857.     for( i = 0; i < p_esp->i_stream_name_count; i++ )
  858.         msg_Dbg( s, "     - lang id=%d name=%s",
  859.                  p_esp->pi_stream_name_language[i],
  860.                  p_esp->ppsz_stream_name[i] );
  861.     msg_Dbg( s, "  - payload extension system count=%d",
  862.              p_esp->i_payload_extension_system_count );
  863. #endif
  864.     return VLC_SUCCESS;
  865. }
  866. static void ASF_FreeObject_extended_stream_properties( asf_object_t *p_obj)
  867. {
  868.     asf_object_extended_stream_properties_t *p_esp = &p_obj->ext_stream;
  869.     int i;
  870.     for( i = 0; i < p_esp->i_stream_name_count; i++ )
  871.         FREENULL( p_esp->ppsz_stream_name[i] );
  872.     FREENULL( p_esp->pi_stream_name_language );
  873.     FREENULL( p_esp->ppsz_stream_name );
  874. }
  875. static int ASF_ReadObject_advanced_mutual_exclusion( stream_t *s,
  876.                                                      asf_object_t *p_obj)
  877. {
  878.     asf_object_advanced_mutual_exclusion_t *p_ae = &p_obj->advanced_mutual_exclusion;
  879.     const uint8_t *p_peek, *p_data;
  880.     int i_peek;
  881.     int i;
  882.     if( ( i_peek = stream_Peek( s, &p_peek, p_ae->i_object_size ) ) < 42 )
  883.        return VLC_EGENERIC;
  884.     p_data = &p_peek[24];
  885.     ASF_GetGUID( &p_ae->type, &p_data[0] );
  886.     ASF_SKIP( 16 );
  887.     p_ae->i_stream_number_count = ASF_READ2();
  888.     p_ae->pi_stream_number = calloc( p_ae->i_stream_number_count, sizeof(int) );
  889.     for( i = 0; i < p_ae->i_stream_number_count; i++ )
  890.     {
  891.         if( !ASF_HAVE(2) )
  892.             break;
  893.         p_ae->pi_stream_number[i] = ASF_READ2();
  894.     }
  895.     p_ae->i_stream_number_count = i;
  896.  
  897. #ifdef ASF_DEBUG
  898.     msg_Dbg( s, "read "advanced mutual exclusion object"" );
  899.     for( i = 0; i < p_ae->i_stream_number_count; i++ )
  900.         msg_Dbg( s, "  - stream=%d", p_ae->pi_stream_number[i] );
  901. #endif
  902.     return VLC_SUCCESS;
  903. }
  904. static void ASF_FreeObject_advanced_mutual_exclusion( asf_object_t *p_obj)
  905. {
  906.     asf_object_advanced_mutual_exclusion_t *p_ae = &p_obj->advanced_mutual_exclusion;
  907.     FREENULL( p_ae->pi_stream_number );
  908. }
  909. static int ASF_ReadObject_stream_prioritization( stream_t *s,
  910.                                                  asf_object_t *p_obj)
  911. {
  912.     asf_object_stream_prioritization_t *p_sp = &p_obj->stream_prioritization;
  913.     const uint8_t *p_peek, *p_data;
  914.     int i_peek;
  915.     int i;
  916.     if( ( i_peek = stream_Peek( s, &p_peek, p_sp->i_object_size ) ) < 26 )
  917.        return VLC_EGENERIC;
  918.     p_data = &p_peek[24];
  919.     p_sp->i_priority_count = ASF_READ2();
  920.     p_sp->pi_priority_flag = calloc( p_sp->i_priority_count, sizeof(int) );
  921.     p_sp->pi_priority_stream_number =
  922.                              calloc( p_sp->i_priority_count, sizeof(int) );
  923.     if( !p_sp->pi_priority_flag || !p_sp->pi_priority_stream_number )
  924.     {
  925.         free( p_sp->pi_priority_flag );
  926.         free( p_sp->pi_priority_stream_number );
  927.         return VLC_ENOMEM;
  928.     }
  929.     for( i = 0; i < p_sp->i_priority_count; i++ )
  930.     {
  931.         if( !ASF_HAVE(2+2) )
  932.             break;
  933.         p_sp->pi_priority_stream_number[i] = ASF_READ2();
  934.         p_sp->pi_priority_flag[i] = ASF_READ2();
  935.     }
  936.     p_sp->i_priority_count = i;
  937. #ifdef ASF_DEBUG
  938.     msg_Dbg( s, "read "stream prioritization object"" );
  939.     for( i = 0; i < p_sp->i_priority_count; i++ )
  940.         msg_Dbg( s, "  - Stream:%d flags=0x%x",
  941.                  p_sp->pi_priority_stream_number[i],
  942.                  p_sp->pi_priority_flag[i] );
  943. #endif
  944.     return VLC_SUCCESS;
  945. }
  946. static void ASF_FreeObject_stream_prioritization( asf_object_t *p_obj)
  947. {
  948.     asf_object_stream_prioritization_t *p_sp = &p_obj->stream_prioritization;
  949.     FREENULL( p_sp->pi_priority_stream_number );
  950.     FREENULL( p_sp->pi_priority_flag );
  951. }
  952. static int ASF_ReadObject_extended_content_description( stream_t *s,
  953.                                                         asf_object_t *p_obj)
  954. {
  955.     asf_object_extended_content_description_t *p_ec =
  956.                                         &p_obj->extended_content_description;
  957.     const uint8_t *p_peek, *p_data;
  958.     int i_peek;
  959.     int i;
  960.     if( ( i_peek = stream_Peek( s, &p_peek, p_ec->i_object_size ) ) < 26 )
  961.        return VLC_EGENERIC;
  962.     p_data = &p_peek[24];
  963.     p_ec->i_count = ASF_READ2();
  964.     p_ec->ppsz_name  = calloc( p_ec->i_count, sizeof(char*) );
  965.     p_ec->ppsz_value = calloc( p_ec->i_count, sizeof(char*) );
  966.     if( !p_ec->ppsz_name || !p_ec->ppsz_value )
  967.     {
  968.         free( p_ec->ppsz_name );
  969.         free( p_ec->ppsz_value );
  970.         return VLC_ENOMEM;
  971.     }
  972.     for( i = 0; i < p_ec->i_count; i++ )
  973.     {
  974.         int i_size;
  975.         int i_type;
  976.         if( !ASF_HAVE(2 + 2+2) )
  977.             break;
  978.         p_ec->ppsz_name[i] = ASF_READS( ASF_READ2() );
  979.         /* Grrr */
  980.         i_type = ASF_READ2();
  981.         i_size = ASF_READ2();
  982.         if( i_type == 0 )
  983.         {
  984.             p_ec->ppsz_value[i] = ASF_READS( i_size );
  985.         }
  986.         else if( i_type == 1 )
  987.         {
  988.             /* Byte array */
  989.             static const char hex[16] = "0123456789ABCDEF";
  990.             int j;
  991.             p_ec->ppsz_value[i] = malloc( 2*i_size + 1 );
  992.             if( p_ec->ppsz_value[i] )
  993.             {
  994.                 char *psz_value = p_ec->ppsz_value[i];
  995.                 for( j = 0; j < i_size; j++ )
  996.                 {
  997.                     const uint8_t v = ASF_READ1();
  998.                     psz_value[2*j+0] = hex[v>>4];
  999.                     psz_value[2*j+1] = hex[v&0xf];
  1000.                 }
  1001.                 psz_value[2*i_size] = '';
  1002.             }
  1003.         }
  1004.         else if( i_type == 2 )
  1005.         {
  1006.             /* Bool */
  1007.             p_ec->ppsz_value[i] = strdup( ASF_READ1() ? "true" : "false" );
  1008.             ASF_SKIP(i_size-1);
  1009.         }
  1010.         else if( i_type == 3 )
  1011.         {
  1012.             /* DWord */
  1013.             if( asprintf( &p_ec->ppsz_value[i], "%d", ASF_READ4() ) == -1 )
  1014.                 p_ec->ppsz_value[i] = NULL;
  1015.         }
  1016.         else if( i_type == 4 )
  1017.         {
  1018.             /* QWord */
  1019.             if( asprintf( &p_ec->ppsz_value[i], "%"PRId64, ASF_READ8() ) == -1 )
  1020.                 p_ec->ppsz_value[i] = NULL;
  1021.         }
  1022.         else if( i_type == 5 )
  1023.         {
  1024.             /* Word */
  1025.             if( asprintf( &p_ec->ppsz_value[i], "%d", ASF_READ2() ) == -1 )
  1026.                 p_ec->ppsz_value[i] = NULL;
  1027.         }
  1028.         else
  1029.         {
  1030.             p_ec->ppsz_value[i] = NULL;
  1031.             ASF_SKIP(i_size);
  1032.         }
  1033.     }
  1034.     p_ec->i_count = i;
  1035. #ifdef ASF_DEBUG
  1036.     msg_Dbg( s, "read "extended content description object"" );
  1037.     for( i = 0; i < p_ec->i_count; i++ )
  1038.         msg_Dbg( s, "  - '%s' = '%s'",
  1039.                  p_ec->ppsz_name[i],
  1040.                  p_ec->ppsz_value[i] );
  1041. #endif
  1042.     return VLC_SUCCESS;
  1043. }
  1044. static void ASF_FreeObject_extended_content_description( asf_object_t *p_obj)
  1045. {
  1046.     asf_object_extended_content_description_t *p_ec =
  1047.                                         &p_obj->extended_content_description;
  1048.     int i;
  1049.     for( i = 0; i < p_ec->i_count; i++ )
  1050.     {
  1051.         FREENULL( p_ec->ppsz_name[i] );
  1052.         FREENULL( p_ec->ppsz_value[i] );
  1053.     }
  1054.     FREENULL( p_ec->ppsz_name );
  1055.     FREENULL( p_ec->ppsz_value );
  1056. }
  1057. #if 0
  1058. static int ASF_ReadObject_XXX(stream_t *s, asf_object_t *p_obj)
  1059. {
  1060.     asf_object_XXX_t *p_XX =
  1061.         (asf_object_XXX_t *)p_obj;
  1062.     const uint8_t *p_peek;
  1063.     uint8_t *p_data;
  1064.     int i_peek;
  1065.     if( ( i_peek = stream_Peek( s, &p_peek, p_XX->i_object_size ) ) < XXX )
  1066.        return VLC_EGENERIC;
  1067.     p_data = &p_peek[24];
  1068. #ifdef ASF_DEBUG
  1069.     msg_Dbg( s,
  1070.              "Read "XXX object"" );
  1071. #endif
  1072.     return VLC_SUCCESS;
  1073. }
  1074. static void ASF_FreeObject_XXX( asf_object_t *p_obj)
  1075. {
  1076.     asf_object_XXX_t *p_XX =
  1077.         (asf_object_XXX_t *)p_obj;
  1078. }
  1079. #endif
  1080. /* */
  1081. static const struct
  1082. {
  1083.     const guid_t  *p_id;
  1084.     int     i_type;
  1085.     int     (*ASF_ReadObject_function)( stream_t *, asf_object_t *p_obj );
  1086.     void    (*ASF_FreeObject_function)( asf_object_t *p_obj );
  1087. } ASF_Object_Function [] =
  1088. {
  1089.     { &asf_object_header_guid, ASF_OBJECT_HEADER,
  1090.       ASF_ReadObject_Header, ASF_FreeObject_Null },
  1091.     { &asf_object_data_guid, ASF_OBJECT_DATA,
  1092.       ASF_ReadObject_Data, ASF_FreeObject_Null },
  1093.     { &asf_object_index_guid, ASF_OBJECT_INDEX,
  1094.       ASF_ReadObject_Index, ASF_FreeObject_Index },
  1095.     { &asf_object_file_properties_guid, ASF_OBJECT_FILE_PROPERTIES,
  1096.       ASF_ReadObject_file_properties, ASF_FreeObject_Null },
  1097.     { &asf_object_stream_properties_guid, ASF_OBJECT_STREAM_PROPERTIES,
  1098.       ASF_ReadObject_stream_properties,ASF_FreeObject_stream_properties },
  1099.     { &asf_object_header_extension_guid, ASF_OBJECT_HEADER_EXTENSION,
  1100.       ASF_ReadObject_header_extension, ASF_FreeObject_header_extension},
  1101.     { &asf_object_metadata_guid, ASF_OBJECT_METADATA,
  1102.       ASF_ReadObject_metadata, ASF_FreeObject_metadata},
  1103.     { &asf_object_codec_list_guid, ASF_OBJECT_CODEC_LIST,
  1104.       ASF_ReadObject_codec_list, ASF_FreeObject_codec_list },
  1105.     { &asf_object_marker_guid, ASF_OBJECT_MARKER, NULL, NULL },
  1106.     { &asf_object_padding, ASF_OBJECT_PADDING, NULL, NULL },
  1107.     { &asf_object_content_description_guid, ASF_OBJECT_CONTENT_DESCRIPTION,
  1108.       ASF_ReadObject_content_description, ASF_FreeObject_content_description },
  1109.     { &asf_object_language_list, ASF_OBJECT_OTHER,
  1110.       ASF_ReadObject_language_list, ASF_FreeObject_language_list },
  1111.     { &asf_object_stream_bitrate_properties, ASF_OBJECT_OTHER,
  1112.       ASF_ReadObject_stream_bitrate_properties,
  1113.       ASF_FreeObject_stream_bitrate_properties },
  1114.     { &asf_object_extended_stream_properties, ASF_OBJECT_OTHER,
  1115.       ASF_ReadObject_extended_stream_properties,
  1116.       ASF_FreeObject_extended_stream_properties },
  1117.     { &asf_object_advanced_mutual_exclusion, ASF_OBJECT_OTHER,
  1118.       ASF_ReadObject_advanced_mutual_exclusion,
  1119.       ASF_FreeObject_advanced_mutual_exclusion },
  1120.     { &asf_object_stream_prioritization, ASF_OBJECT_OTHER,
  1121.       ASF_ReadObject_stream_prioritization,
  1122.       ASF_FreeObject_stream_prioritization },
  1123.     { &asf_object_extended_content_description, ASF_OBJECT_OTHER,
  1124.       ASF_ReadObject_extended_content_description,
  1125.       ASF_FreeObject_extended_content_description },
  1126.     { &asf_object_null_guid, 0, NULL, NULL }
  1127. };
  1128. static int ASF_ReadObject( stream_t *s, asf_object_t *p_obj,
  1129.                            asf_object_t *p_father )
  1130. {
  1131.     int i_result;
  1132.     int i_index;
  1133.     if( !p_obj )
  1134.         return 0;
  1135.     memset( p_obj, 0, sizeof( *p_obj ) );
  1136.     if( ASF_ReadObjectCommon( s, p_obj ) )
  1137.     {
  1138.         msg_Warn( s, "cannot read one asf object" );
  1139.         return VLC_EGENERIC;
  1140.     }
  1141.     p_obj->common.p_father = p_father;
  1142.     p_obj->common.p_first = NULL;
  1143.     p_obj->common.p_next = NULL;
  1144.     p_obj->common.p_last = NULL;
  1145.     if( p_obj->common.i_object_size < 24 )
  1146.     {
  1147.         msg_Warn( s, "found a corrupted asf object (size<24)" );
  1148.         return VLC_EGENERIC;
  1149.     }
  1150.     /* find this object */
  1151.     for( i_index = 0; ; i_index++ )
  1152.     {
  1153.         if( ASF_CmpGUID( ASF_Object_Function[i_index].p_id,
  1154.                          &p_obj->common.i_object_id ) ||
  1155.             ASF_CmpGUID( ASF_Object_Function[i_index].p_id,
  1156.                          &asf_object_null_guid ) )
  1157.         {
  1158.             break;
  1159.         }
  1160.     }
  1161.     p_obj->common.i_type = ASF_Object_Function[i_index].i_type;
  1162.     /* Now load this object */
  1163.     if( ASF_Object_Function[i_index].ASF_ReadObject_function == NULL )
  1164.     {
  1165.         msg_Warn( s, "unknown asf object (not loaded)" );
  1166.         i_result = VLC_SUCCESS;
  1167.     }
  1168.     else
  1169.     {
  1170.         /* XXX ASF_ReadObject_function realloc *pp_obj XXX */
  1171.         i_result =
  1172.           (ASF_Object_Function[i_index].ASF_ReadObject_function)( s, p_obj );
  1173.     }
  1174.     /* link this object with father */
  1175.     if( p_father && ! i_result )
  1176.     {
  1177.         if( p_father->common.p_first )
  1178.         {
  1179.             p_father->common.p_last->common.p_next = p_obj;
  1180.         }
  1181.         else
  1182.         {
  1183.             p_father->common.p_first = p_obj;
  1184.         }
  1185.         p_father->common.p_last = p_obj;
  1186.     }
  1187.     return i_result;
  1188. }
  1189. static void ASF_FreeObject( stream_t *s, asf_object_t *p_obj )
  1190. {
  1191.     int i_index;
  1192.     asf_object_t *p_child;
  1193.     if( !p_obj )
  1194.         return;
  1195.     /* Free all child object */
  1196.     p_child = p_obj->common.p_first;
  1197.     while( p_child )
  1198.     {
  1199.         asf_object_t *p_next;
  1200.         p_next = p_child->common.p_next;
  1201.         ASF_FreeObject( s, p_child );
  1202.         p_child = p_next;
  1203.     }
  1204.     /* find this object */
  1205.     for( i_index = 0; ; i_index++ )
  1206.     {
  1207.         if( ASF_CmpGUID( ASF_Object_Function[i_index].p_id,
  1208.                      &p_obj->common.i_object_id )||
  1209.             ASF_CmpGUID( ASF_Object_Function[i_index].p_id,
  1210.                      &asf_object_null_guid ) )
  1211.         {
  1212.             break;
  1213.         }
  1214.     }
  1215.     /* Now free this object */
  1216.     if( ASF_Object_Function[i_index].ASF_FreeObject_function == NULL )
  1217.     {
  1218.         msg_Warn( s,
  1219.                   "unknown asf object " GUID_FMT,
  1220.                   GUID_PRINT( p_obj->common.i_object_id ) );
  1221.     }
  1222.     else
  1223.     {
  1224. #ifdef ASF_DEBUG
  1225.         msg_Dbg( s,
  1226.                   "free asf object " GUID_FMT,
  1227.                   GUID_PRINT( p_obj->common.i_object_id ) );
  1228. #endif
  1229.         (ASF_Object_Function[i_index].ASF_FreeObject_function)( p_obj );
  1230.     }
  1231.     free( p_obj );
  1232. }
  1233. /*****************************************************************************
  1234.  * ASF_ObjectDumpDebug:
  1235.  *****************************************************************************/
  1236. static const struct
  1237. {
  1238.     const guid_t *p_id;
  1239.     const char *psz_name;
  1240. } ASF_ObjectDumpDebugInfo[] =
  1241. {
  1242.     { &asf_object_header_guid, "Header" },
  1243.     { &asf_object_data_guid, "Data" },
  1244.     { &asf_object_index_guid, "Index" },
  1245.     { &asf_object_file_properties_guid, "File Properties" },
  1246.     { &asf_object_stream_properties_guid, "Stream Properties" },
  1247.     { &asf_object_content_description_guid, "Content Description" },
  1248.     { &asf_object_header_extension_guid, "Header Extension" },
  1249.     { &asf_object_metadata_guid, "Metadata" },
  1250.     { &asf_object_codec_list_guid, "Codec List" },
  1251.     { &asf_object_marker_guid, "Marker" },
  1252.     { &asf_object_stream_type_audio, "Stream Type Audio" },
  1253.     { &asf_object_stream_type_video, "Stream Type Video" },
  1254.     { &asf_object_stream_type_command, "Stream Type Command" },
  1255.     { &asf_object_language_list, "Language List" },
  1256.     { &asf_object_stream_bitrate_properties, "Stream Bitrate Properties" },
  1257.     { &asf_object_padding, "Padding" },
  1258.     { &asf_object_extended_stream_properties, "Extended Stream Properties" },
  1259.     { &asf_object_advanced_mutual_exclusion, "Advanced Mutual Exclusion" },
  1260.     { &asf_object_stream_prioritization, "Stream Prioritization" },
  1261.     { &asf_object_extended_content_description, "Extended content description"},
  1262.     { NULL, "Unknown" },
  1263. };
  1264. static void ASF_ObjectDumpDebug( vlc_object_t *p_obj,
  1265.                                  asf_object_common_t *p_node, unsigned i_level )
  1266. {
  1267.     unsigned i;
  1268.     union asf_object_u *p_child;
  1269.     const char *psz_name;
  1270.     /* Find the name */
  1271.     for( i = 0; ASF_ObjectDumpDebugInfo[i].p_id != NULL; i++ )
  1272.     {
  1273.         if( ASF_CmpGUID( ASF_ObjectDumpDebugInfo[i].p_id,
  1274.                           &p_node->i_object_id ) )
  1275.             break;
  1276.     }
  1277.     psz_name = ASF_ObjectDumpDebugInfo[i].psz_name;
  1278.     char str[512];
  1279.     if( i_level * 5 + 1 >= sizeof(str) )
  1280.         return;
  1281.     memset( str, ' ', sizeof( str ) );
  1282.     for( i = 1; i < i_level; i++ )
  1283.     {
  1284.         str[i * 5] = '|';
  1285.     }
  1286.     snprintf( &str[5*i_level], sizeof(str) - 5*i_level,
  1287.              "+ '%s' GUID "GUID_FMT" size:%"PRIu64"pos:%"PRIu64,
  1288.              psz_name,
  1289.              GUID_PRINT( p_node->i_object_id ),
  1290.              p_node->i_object_size, p_node->i_object_pos );
  1291.     msg_Dbg( p_obj, "%s", str );
  1292.     for( p_child = p_node->p_first; p_child != NULL;
  1293.                                              p_child = p_child->common.p_next )
  1294.     {
  1295.         ASF_ObjectDumpDebug( p_obj, &p_child->common, i_level + 1 );
  1296.     }
  1297. }
  1298. /*****************************************************************************
  1299.  * ASF_ReadObjetRoot : parse the entire stream/file
  1300.  *****************************************************************************/
  1301. asf_object_root_t *ASF_ReadObjectRoot( stream_t *s, int b_seekable )
  1302. {
  1303.     asf_object_root_t *p_root = malloc( sizeof( asf_object_root_t ) );
  1304.     asf_object_t *p_obj;
  1305.     if( !p_root )
  1306.         return NULL;
  1307.     p_root->i_type = ASF_OBJECT_ROOT;
  1308.     memcpy( &p_root->i_object_id, &asf_object_null_guid, sizeof( guid_t ) );
  1309.     p_root->i_object_pos = stream_Tell( s );
  1310.     p_root->i_object_size = 0;
  1311.     p_root->p_first = NULL;
  1312.     p_root->p_last  = NULL;
  1313.     p_root->p_next  = NULL;
  1314.     p_root->p_hdr   = NULL;
  1315.     p_root->p_data  = NULL;
  1316.     p_root->p_fp    = NULL;
  1317.     p_root->p_index = NULL;
  1318.     p_root->p_metadata = NULL;
  1319.     for( ; ; )
  1320.     {
  1321.         p_obj = malloc( sizeof( asf_object_t ) );
  1322.         if( !p_obj || ASF_ReadObject( s, p_obj, (asf_object_t*)p_root ) )
  1323.         {
  1324.             free( p_obj );
  1325.             break;
  1326.         }
  1327.         switch( p_obj->common.i_type )
  1328.         {
  1329.             case( ASF_OBJECT_HEADER ):
  1330.                 p_root->p_hdr = (asf_object_header_t*)p_obj;
  1331.                 break;
  1332.             case( ASF_OBJECT_DATA ):
  1333.                 p_root->p_data = (asf_object_data_t*)p_obj;
  1334.                 break;
  1335.             case( ASF_OBJECT_INDEX ):
  1336.                 p_root->p_index = (asf_object_index_t*)p_obj;
  1337.                 break;
  1338.             default:
  1339.                 msg_Warn( s, "unknow object found" );
  1340.                 break;
  1341.         }
  1342.         if( p_obj->common.i_type == ASF_OBJECT_DATA &&
  1343.             p_obj->common.i_object_size <= 50 )
  1344.         {
  1345.             /* probably a dump of broadcasted asf */
  1346.             break;
  1347.         }
  1348.         if( !b_seekable && p_root->p_hdr && p_root->p_data )
  1349.         {
  1350.             /* For unseekable stream it's enough to play */
  1351.             break;
  1352.         }
  1353.         if( ASF_NextObject( s, p_obj ) ) /* Go to the next object */
  1354.             break;
  1355.     }
  1356.     if( p_root->p_hdr != NULL && p_root->p_data != NULL )
  1357.     {
  1358.         p_root->p_fp = ASF_FindObject( p_root->p_hdr,
  1359.                                        &asf_object_file_properties_guid, 0 );
  1360.         if( p_root->p_fp )
  1361.         {
  1362.             asf_object_t *p_hdr_ext =
  1363.                 ASF_FindObject( p_root->p_hdr,
  1364.                                 &asf_object_header_extension_guid, 0 );
  1365.             if( p_hdr_ext )
  1366.             {
  1367.                 int i_ext_stream;
  1368.                 int i;
  1369.                 p_root->p_metadata =
  1370.                     ASF_FindObject( p_hdr_ext,
  1371.                                     &asf_object_metadata_guid, 0 );
  1372.                 /* Special case for broken designed file format :( */
  1373.                 i_ext_stream = ASF_CountObject( p_hdr_ext,
  1374.                                     &asf_object_extended_stream_properties );
  1375.                 for( i = 0; i < i_ext_stream; i++ )
  1376.                 {
  1377.                     asf_object_t *p_esp =
  1378.                         ASF_FindObject( p_hdr_ext,
  1379.                                    &asf_object_extended_stream_properties, i );
  1380.                     if( p_esp->ext_stream.p_sp )
  1381.                     {
  1382.                         asf_object_t *p_sp =
  1383.                                          (asf_object_t*)p_esp->ext_stream.p_sp;
  1384.                         /* Insert this p_sp */
  1385.                         p_root->p_hdr->p_last->common.p_next = p_sp;
  1386.                         p_root->p_hdr->p_last = p_sp;
  1387.                         p_sp->common.p_father = (asf_object_t*)p_root->p_hdr;
  1388.                     }
  1389.                 }
  1390.             }
  1391.             ASF_ObjectDumpDebug( VLC_OBJECT(s),
  1392.                                  (asf_object_common_t*)p_root, 0 );
  1393.             return p_root;
  1394.         }
  1395.         msg_Warn( s, "cannot find file properties object" );
  1396.     }
  1397.     /* Invalid file */
  1398.     ASF_FreeObjectRoot( s, p_root );
  1399.     return NULL;
  1400. }
  1401. void ASF_FreeObjectRoot( stream_t *s, asf_object_root_t *p_root )
  1402. {
  1403.     asf_object_t *p_obj;
  1404.     p_obj = p_root->p_first;
  1405.     while( p_obj )
  1406.     {
  1407.         asf_object_t *p_next;
  1408.         p_next = p_obj->common.p_next;
  1409.         ASF_FreeObject( s, p_obj );
  1410.         p_obj = p_next;
  1411.     }
  1412.     free( p_root );
  1413. }
  1414. int  __ASF_CountObject( asf_object_t *p_obj, const guid_t *p_guid )
  1415. {
  1416.     int i_count;
  1417.     asf_object_t *p_child;
  1418.     if( !p_obj )
  1419.         return 0;
  1420.     i_count = 0;
  1421.     p_child = p_obj->common.p_first;
  1422.     while( p_child )
  1423.     {
  1424.         if( ASF_CmpGUID( &p_child->common.i_object_id, p_guid ) )
  1425.             i_count++;
  1426.         p_child = p_child->common.p_next;
  1427.     }
  1428.     return i_count;
  1429. }
  1430. void *__ASF_FindObject( asf_object_t *p_obj, const guid_t *p_guid,
  1431.                         int i_number )
  1432. {
  1433.     asf_object_t *p_child;
  1434.     p_child = p_obj->common.p_first;
  1435.     while( p_child )
  1436.     {
  1437.         if( ASF_CmpGUID( &p_child->common.i_object_id, p_guid ) )
  1438.         {
  1439.             if( i_number == 0 )
  1440.                 return p_child;
  1441.             i_number--;
  1442.         }
  1443.         p_child = p_child->common.p_next;
  1444.     }
  1445.     return NULL;
  1446. }