Main Page | Modules | Class Hierarchy | Class List | Directories | File List | Class Members | File Members | Related Pages

libasf.c

00001 /*****************************************************************************
00002  * libasf.c : asf stream demux module for vlc
00003  *****************************************************************************
00004  * Copyright (C) 2001-2003 the VideoLAN team
00005  * $Id: libasf.c 12087 2005-08-09 14:43:04Z jpsaman $
00006  *
00007  * Authors: Laurent Aimar <[email protected]>
00008  *          Gildas Bazin <[email protected]>
00009  *
00010  * This program is free software; you can redistribute it and/or modify
00011  * it under the terms of the GNU General Public License as published by
00012  * the Free Software Foundation; either version 2 of the License, or
00013  * (at your option) any later version.
00014  *
00015  * This program is distributed in the hope that it will be useful,
00016  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00017  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018  * GNU General Public License for more details.
00019  *
00020  * You should have received a copy of the GNU General Public License
00021  * along with this program; if not, write to the Free Software
00022  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
00023  *****************************************************************************/
00024 
00025 #include <stdlib.h>                                      /* malloc(), free() */
00026 
00027 #include <vlc/vlc.h>
00028 #include <vlc/input.h>
00029 
00030 #include "codecs.h"                        /* BITMAPINFOHEADER, WAVEFORMATEX */
00031 #include "libasf.h"
00032 
00033 #define ASF_DEBUG 1
00034 
00035 #define FREE( p ) \
00036     if( p ) {free( p ); p = NULL; }
00037 
00038 #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"
00039 #define GUID_PRINT( guid )  \
00040     (guid).v1,              \
00041     (guid).v2,              \
00042     (guid).v3,              \
00043     (guid).v4[0],(guid).v4[1],(guid).v4[2],(guid).v4[3],    \
00044     (guid).v4[4],(guid).v4[5],(guid).v4[6],(guid).v4[7]
00045 
00046 /****************************************************************************
00047  *
00048  ****************************************************************************/
00049 static int ASF_ReadObject( stream_t *, asf_object_t *,  asf_object_t * );
00050 
00051 /****************************************************************************
00052  * GUID functions
00053  ****************************************************************************/
00054 void ASF_GetGUID( guid_t *p_guid, uint8_t *p_data )
00055 {
00056     p_guid->v1 = GetDWLE( p_data );
00057     p_guid->v2 = GetWLE( p_data + 4);
00058     p_guid->v3 = GetWLE( p_data + 6);
00059     memcpy( p_guid->v4, p_data + 8, 8 );
00060 }
00061 
00062 int ASF_CmpGUID( const guid_t *p_guid1, const guid_t *p_guid2 )
00063 {
00064     if( (p_guid1->v1 != p_guid2->v1 )||
00065         (p_guid1->v2 != p_guid2->v2 )||
00066         (p_guid1->v3 != p_guid2->v3 )||
00067         ( memcmp( p_guid1->v4, p_guid2->v4,8 )) )
00068     {
00069         return( 0 );
00070     }
00071     return( 1 ); /* match */
00072 }
00073 
00074 /****************************************************************************
00075  *
00076  ****************************************************************************/
00077 static int ASF_ReadObjectCommon( stream_t *s, asf_object_t *p_obj )
00078 {
00079     asf_object_common_t *p_common = (asf_object_common_t*)p_obj;
00080     uint8_t             *p_peek;
00081 
00082     if( stream_Peek( s, &p_peek, 24 ) < 24 )
00083     {
00084         return( VLC_EGENERIC );
00085     }
00086     ASF_GetGUID( &p_common->i_object_id, p_peek );
00087     p_common->i_object_size = GetQWLE( p_peek + 16 );
00088     p_common->i_object_pos  = stream_Tell( s );
00089     p_common->p_next = NULL;
00090 
00091 #ifdef ASF_DEBUG
00092     msg_Dbg( s,
00093              "found object guid: " GUID_FMT " size:"I64Fd,
00094              GUID_PRINT( p_common->i_object_id ),
00095              p_common->i_object_size );
00096 #endif
00097 
00098     return( VLC_SUCCESS );
00099 }
00100 
00101 static int ASF_NextObject( stream_t *s, asf_object_t *p_obj )
00102 {
00103     asf_object_t obj;
00104     if( p_obj == NULL )
00105     {
00106         if( ASF_ReadObjectCommon( s, &obj ) )
00107         {
00108             return( VLC_EGENERIC );
00109         }
00110         p_obj = &obj;
00111     }
00112 
00113     if( p_obj->common.i_object_size <= 0 )
00114     {
00115         return VLC_EGENERIC;
00116     }
00117     if( p_obj->common.p_father &&
00118         p_obj->common.p_father->common.i_object_size != 0 )
00119     {
00120         if( p_obj->common.p_father->common.i_object_pos +
00121             p_obj->common.p_father->common.i_object_size <
00122                 p_obj->common.i_object_pos + p_obj->common.i_object_size + 24 )
00123                                 /* 24 is min size of an object */
00124         {
00125             return VLC_EGENERIC;
00126         }
00127 
00128     }
00129 
00130     return stream_Seek( s, p_obj->common.i_object_pos +
00131                         p_obj->common.i_object_size );
00132 }
00133 
00134 static void ASF_FreeObject_Null( asf_object_t *pp_obj )
00135 {
00136     return;
00137 }
00138 
00139 static int  ASF_ReadObject_Header( stream_t *s, asf_object_t *p_obj )
00140 {
00141     asf_object_header_t *p_hdr = (asf_object_header_t*)p_obj;
00142     asf_object_t        *p_subobj;
00143     int                 i_peek;
00144     uint8_t             *p_peek;
00145 
00146     if( ( i_peek = stream_Peek( s, &p_peek, 30 ) ) < 30 )
00147     {
00148        return( VLC_EGENERIC );
00149     }
00150 
00151     p_hdr->i_sub_object_count = GetDWLE( p_peek + 24 );
00152     p_hdr->i_reserved1 = p_peek[28];
00153     p_hdr->i_reserved2 = p_peek[29];
00154     p_hdr->p_first = NULL;
00155     p_hdr->p_last  = NULL;
00156 
00157 #ifdef ASF_DEBUG
00158     msg_Dbg( s,
00159              "read \"header object\" subobj:%d, reserved1:%d, reserved2:%d",
00160              p_hdr->i_sub_object_count,
00161              p_hdr->i_reserved1,
00162              p_hdr->i_reserved2 );
00163 #endif
00164 
00165     /* Cannot fail as peek succeed */
00166     stream_Read( s, NULL, 30 );
00167 
00168     /* Now load sub object */
00169     for( ; ; )
00170     {
00171         p_subobj = malloc( sizeof( asf_object_t ) );
00172 
00173         if( ASF_ReadObject( s, p_subobj, (asf_object_t*)p_hdr ) )
00174         {
00175             free( p_subobj );
00176             break;
00177         }
00178         if( ASF_NextObject( s, p_subobj ) ) /* Go to the next object */
00179         {
00180             break;
00181         }
00182     }
00183     return VLC_SUCCESS;
00184 }
00185 
00186 static int ASF_ReadObject_Data( stream_t *s, asf_object_t *p_obj )
00187 {
00188     asf_object_data_t *p_data = (asf_object_data_t*)p_obj;
00189     int               i_peek;
00190     uint8_t           *p_peek;
00191 
00192     if( ( i_peek = stream_Peek( s, &p_peek, 50 ) ) < 50 )
00193     {
00194        return VLC_EGENERIC;
00195     }
00196     ASF_GetGUID( &p_data->i_file_id, p_peek + 24 );
00197     p_data->i_total_data_packets = GetQWLE( p_peek + 40 );
00198     p_data->i_reserved = GetWLE( p_peek + 48 );
00199 
00200 #ifdef ASF_DEBUG
00201     msg_Dbg( s,
00202              "read \"data object\" file_id:" GUID_FMT " total data packet:"
00203              I64Fd" reserved:%d",
00204              GUID_PRINT( p_data->i_file_id ),
00205              p_data->i_total_data_packets,
00206              p_data->i_reserved );
00207 #endif
00208 
00209     return VLC_SUCCESS;
00210 }
00211 
00212 static int ASF_ReadObject_Index( stream_t *s, asf_object_t *p_obj )
00213 {
00214     asf_object_index_t *p_index = (asf_object_index_t*)p_obj;
00215     int                i_peek;
00216     uint8_t            *p_peek;
00217 
00218     if( ( i_peek = stream_Peek( s, &p_peek, 56 ) ) < 56 )
00219     {
00220        return VLC_EGENERIC;
00221     }
00222     ASF_GetGUID( &p_index->i_file_id, p_peek + 24 );
00223     p_index->i_index_entry_time_interval = GetQWLE( p_peek + 40 );
00224     p_index->i_max_packet_count = GetDWLE( p_peek + 48 );
00225     p_index->i_index_entry_count = GetDWLE( p_peek + 52 );
00226     p_index->index_entry = NULL; /* FIXME */
00227 
00228 #ifdef ASF_DEBUG
00229     msg_Dbg( s,
00230             "read \"index object\" file_id:" GUID_FMT
00231             " index_entry_time_interval:"I64Fd" max_packet_count:%d "
00232             "index_entry_count:%ld",
00233             GUID_PRINT( p_index->i_file_id ),
00234             p_index->i_index_entry_time_interval,
00235             p_index->i_max_packet_count,
00236             (long int)p_index->i_index_entry_count );
00237 #endif
00238 
00239     return VLC_SUCCESS;
00240 }
00241 
00242 static void ASF_FreeObject_Index( asf_object_t *p_obj )
00243 {
00244     asf_object_index_t *p_index = (asf_object_index_t*)p_obj;
00245 
00246     FREE( p_index->index_entry );
00247 }
00248 
00249 static int ASF_ReadObject_file_properties( stream_t *s, asf_object_t *p_obj )
00250 {
00251     asf_object_file_properties_t *p_fp = (asf_object_file_properties_t*)p_obj;
00252     int      i_peek;
00253     uint8_t  *p_peek;
00254 
00255     if( ( i_peek = stream_Peek( s, &p_peek,  92) ) < 92 )
00256     {
00257        return VLC_EGENERIC;
00258     }
00259     ASF_GetGUID( &p_fp->i_file_id, p_peek + 24 );
00260     p_fp->i_file_size = GetQWLE( p_peek + 40 );
00261     p_fp->i_creation_date = GetQWLE( p_peek + 48 );
00262     p_fp->i_data_packets_count = GetQWLE( p_peek + 56 );
00263     p_fp->i_play_duration = GetQWLE( p_peek + 64 );
00264     p_fp->i_send_duration = GetQWLE( p_peek + 72 );
00265     p_fp->i_preroll = GetQWLE( p_peek + 80 );
00266     p_fp->i_flags = GetDWLE( p_peek + 88 );
00267     p_fp->i_min_data_packet_size = GetDWLE( p_peek + 92 );
00268     p_fp->i_max_data_packet_size = GetDWLE( p_peek + 96 );
00269     p_fp->i_max_bitrate = GetDWLE( p_peek + 100 );
00270 
00271 #ifdef ASF_DEBUG
00272     msg_Dbg( s,
00273             "read \"file properties object\" file_id:" GUID_FMT
00274             " file_size:"I64Fd" creation_date:"I64Fd" data_packets_count:"
00275             I64Fd" play_duration:"I64Fd" send_duration:"I64Fd" preroll:"
00276             I64Fd" flags:%d min_data_packet_size:%d max_data_packet_size:%d "
00277             "max_bitrate:%d",
00278             GUID_PRINT( p_fp->i_file_id ), p_fp->i_file_size,
00279             p_fp->i_creation_date, p_fp->i_data_packets_count,
00280             p_fp->i_play_duration, p_fp->i_send_duration,
00281             p_fp->i_preroll, p_fp->i_flags,
00282             p_fp->i_min_data_packet_size, p_fp->i_max_data_packet_size,
00283             p_fp->i_max_bitrate );
00284 #endif
00285 
00286     return VLC_SUCCESS;
00287 }
00288 
00289 static void ASF_FreeObject_metadata( asf_object_t *p_obj )
00290 {
00291     asf_object_metadata_t *p_meta =
00292         (asf_object_metadata_t *)p_obj;
00293     unsigned int i;
00294 
00295     for( i = 0; i < p_meta->i_record_entries_count; i++ )
00296     {
00297         if( p_meta->record[i].psz_name ) free( p_meta->record[i].psz_name );
00298         if( p_meta->record[i].p_data ) free( p_meta->record[i].p_data );
00299     }
00300     if( p_meta->record ) free( p_meta->record );
00301 }
00302 
00303 static int ASF_ReadObject_metadata( stream_t *s, asf_object_t *p_obj )
00304 {
00305     asf_object_metadata_t *p_meta =
00306         (asf_object_metadata_t *)p_obj;
00307 
00308     int i_peek, i_entries, i;
00309     uint8_t *p_peek;
00310 #ifdef ASF_DEBUG
00311     unsigned int j;
00312 #endif
00313 
00314     p_meta->i_record_entries_count = 0;
00315     p_meta->record = 0;
00316 
00317     if( stream_Peek( s, &p_peek, p_meta->i_object_size ) <
00318         (int)p_meta->i_object_size )
00319     {
00320        return VLC_EGENERIC;
00321     }
00322 
00323     i_peek = 24;
00324     i_entries = GetWLE( p_peek + i_peek ); i_peek += 2;
00325     for( i = 0; i < i_entries && i_peek < (int)p_meta->i_object_size -12; i++ )
00326     {
00327         asf_metadata_record_t record;
00328         int i_name, i_data, j;
00329 
00330         if( GetWLE( p_peek + i_peek ) != 0 )
00331         {
00332             ASF_FreeObject_metadata( p_obj );
00333             return VLC_EGENERIC;
00334         }
00335 
00336         i_peek += 2;
00337         record.i_stream = GetWLE( p_peek + i_peek ); i_peek += 2;
00338         i_name = GetWLE( p_peek + i_peek ); i_peek += 2;
00339         record.i_type = GetWLE( p_peek + i_peek ); i_peek += 2;
00340         i_data = GetDWLE( p_peek + i_peek ); i_peek += 4;
00341 
00342         if( record.i_type > ASF_METADATA_TYPE_WORD ||
00343             i_peek + i_data + i_name > (int)p_meta->i_object_size )
00344         {
00345             ASF_FreeObject_metadata( p_obj );
00346             return VLC_EGENERIC;
00347         }
00348 
00349         record.i_val = 0;
00350         record.i_data = 0;
00351         record.p_data = 0;
00352 
00353         /* get name */
00354         record.psz_name = malloc( i_name/2 + 1 );
00355         for( j = 0; j < i_name/2; j++ )
00356         {
00357             record.psz_name[j] = GetWLE( p_peek + i_peek ); i_peek += 2;
00358         }
00359         record.psz_name[j] = 0; /* just to make sure */
00360 
00361         /* get data */
00362         if( record.i_type == ASF_METADATA_TYPE_STRING )
00363         {
00364             record.p_data = malloc( i_data/2 + 1 );
00365             record.i_data = i_data/2;
00366             for( j = 0; j < i_data/2; j++ )
00367             {
00368                 record.p_data[j] = GetWLE( p_peek + i_peek ); i_peek += 2;
00369             }
00370             record.p_data[j] = 0; /* just to make sure */
00371         }
00372         else if( record.i_type == ASF_METADATA_TYPE_BYTE )
00373         {
00374             record.p_data = malloc( i_data );
00375             record.i_data = i_data;
00376             memcpy( record.p_data, p_peek + i_peek, i_data );
00377             p_peek += i_data;
00378         }
00379         else
00380         {
00381             if( record.i_type == ASF_METADATA_TYPE_QWORD )
00382             {
00383                 record.i_val = GetQWLE( p_peek + i_peek ); i_peek += 8;
00384             }
00385             else if( record.i_type == ASF_METADATA_TYPE_DWORD )
00386             {
00387                 record.i_val = GetDWLE( p_peek + i_peek ); i_peek += 4;
00388             }
00389             else
00390             {
00391                 record.i_val = GetWLE( p_peek + i_peek ); i_peek += 2;
00392             }
00393         }
00394 
00395         p_meta->i_record_entries_count++;
00396         p_meta->record =
00397             realloc( p_meta->record, p_meta->i_record_entries_count *
00398                      sizeof(asf_metadata_record_t) );
00399         memcpy( &p_meta->record[p_meta->i_record_entries_count-1],
00400                 &record, sizeof(asf_metadata_record_t) );
00401     }
00402 
00403 #ifdef ASF_DEBUG
00404     msg_Dbg( s,
00405             "read \"metadata object\" %d entries",
00406             p_meta->i_record_entries_count );
00407     for( j = 0; j < p_meta->i_record_entries_count; j++ )
00408     {
00409         asf_metadata_record_t *p_rec = &p_meta->record[j];
00410         
00411         if( p_rec->i_type == ASF_METADATA_TYPE_STRING )
00412             msg_Dbg( s, "  - %s=%s",
00413                      p_rec->psz_name, p_rec->p_data );
00414         else if( p_rec->i_type == ASF_METADATA_TYPE_BYTE )
00415             msg_Dbg( s, "  - %s (%i bytes)",
00416                      p_rec->psz_name, p_rec->i_data );
00417         else
00418             msg_Dbg( s, "  - %s="I64Fd,
00419                      p_rec->psz_name, p_rec->i_val );
00420     }
00421 #endif
00422 
00423     return VLC_SUCCESS;
00424 }
00425 
00426 static int ASF_ReadObject_header_extension( stream_t *s, asf_object_t *p_obj )
00427 {
00428     asf_object_header_extension_t *p_he =
00429         (asf_object_header_extension_t *)p_obj;
00430     int     i_peek;
00431     uint8_t *p_peek;
00432 
00433     if( ( i_peek = stream_Peek( s, &p_peek, p_he->i_object_size ) ) <  46)
00434     {
00435        return VLC_EGENERIC;
00436     }
00437     ASF_GetGUID( &p_he->i_reserved1, p_peek + 24 );
00438     p_he->i_reserved2 = GetWLE( p_peek + 40 );
00439     p_he->i_header_extension_size = GetDWLE( p_peek + 42 );
00440     if( p_he->i_header_extension_size )
00441     {
00442         p_he->p_header_extension_data =
00443             malloc( p_he->i_header_extension_size );
00444         memcpy( p_he->p_header_extension_data, p_peek + 46,
00445                 p_he->i_header_extension_size );
00446     }
00447     else
00448     {
00449         p_he->p_header_extension_data = NULL;
00450     }
00451 
00452 #ifdef ASF_DEBUG
00453     msg_Dbg( s,
00454             "read \"header extension object\" reserved1:" GUID_FMT
00455             " reserved2:%d header_extension_size:%d",
00456             GUID_PRINT( p_he->i_reserved1 ), p_he->i_reserved2,
00457             p_he->i_header_extension_size );
00458 #endif
00459 
00460     if( !p_he->i_header_extension_size ) return VLC_SUCCESS;
00461 
00462     /* Read the extension objects */
00463     stream_Read( s, NULL, 46 );
00464     for( ; ; )
00465     {
00466         asf_object_t *p_obj = malloc( sizeof( asf_object_t ) );
00467 
00468         if( ASF_ReadObject( s, p_obj, (asf_object_t*)p_he ) )
00469         {
00470             free( p_obj );
00471             break;
00472         }
00473 
00474         if( ASF_NextObject( s, p_obj ) ) /* Go to the next object */
00475         {
00476             break;
00477         }
00478     }
00479 
00480     return VLC_SUCCESS;
00481 }
00482 
00483 static void ASF_FreeObject_header_extension( asf_object_t *p_obj )
00484 {
00485     asf_object_header_extension_t *p_he =
00486         (asf_object_header_extension_t *)p_obj;
00487 
00488     FREE( p_he->p_header_extension_data );
00489 }
00490 
00491 static int ASF_ReadObject_stream_properties( stream_t *s, asf_object_t *p_obj )
00492 {
00493     asf_object_stream_properties_t *p_sp =
00494                     (asf_object_stream_properties_t*)p_obj;
00495     int     i_peek;
00496     uint8_t *p_peek;
00497 
00498     if( ( i_peek = stream_Peek( s, &p_peek,  p_sp->i_object_size ) ) < 74 )
00499     {
00500        return VLC_EGENERIC;
00501     }
00502     ASF_GetGUID( &p_sp->i_stream_type, p_peek + 24 );
00503     ASF_GetGUID( &p_sp->i_error_correction_type, p_peek + 40 );
00504     p_sp->i_time_offset = GetQWLE( p_peek + 56 );
00505     p_sp->i_type_specific_data_length = GetDWLE( p_peek + 64 );
00506     p_sp->i_error_correction_data_length = GetDWLE( p_peek + 68 );
00507     p_sp->i_flags = GetWLE( p_peek + 72 );
00508         p_sp->i_stream_number = p_sp->i_flags&0x07f;
00509     p_sp->i_reserved = GetDWLE( p_peek + 74 );
00510     if( p_sp->i_type_specific_data_length )
00511     {
00512         p_sp->p_type_specific_data =
00513             malloc( p_sp->i_type_specific_data_length );
00514         memcpy( p_sp->p_type_specific_data, p_peek + 78,
00515                 p_sp->i_type_specific_data_length );
00516     }
00517     else
00518     {
00519         p_sp->p_type_specific_data = NULL;
00520     }
00521     if( p_sp->i_error_correction_data_length )
00522     {
00523         p_sp->p_error_correction_data =
00524             malloc( p_sp->i_error_correction_data_length );
00525         memcpy( p_sp->p_error_correction_data,
00526                 p_peek + 78 + p_sp->i_type_specific_data_length,
00527                 p_sp->i_error_correction_data_length );
00528     }
00529     else
00530     {
00531         p_sp->p_error_correction_data = NULL;
00532     }
00533 
00534 #ifdef ASF_DEBUG
00535     msg_Dbg( s,
00536             "read \"stream Properties object\" stream_type:" GUID_FMT
00537             " error_correction_type:" GUID_FMT " time_offset:"I64Fd
00538             " type_specific_data_length:%d error_correction_data_length:%d"
00539             " flags:0x%x stream_number:%d",
00540             GUID_PRINT( p_sp->i_stream_type ),
00541             GUID_PRINT( p_sp->i_error_correction_type ),
00542             p_sp->i_time_offset,
00543             p_sp->i_type_specific_data_length,
00544             p_sp->i_error_correction_data_length,
00545             p_sp->i_flags,
00546             p_sp->i_stream_number );
00547 
00548 #endif
00549     return VLC_SUCCESS;
00550 }
00551 
00552 static void ASF_FreeObject_stream_properties( asf_object_t *p_obj )
00553 {
00554     asf_object_stream_properties_t *p_sp =
00555                 (asf_object_stream_properties_t*)p_obj;
00556 
00557     FREE( p_sp->p_type_specific_data );
00558     FREE( p_sp->p_error_correction_data );
00559 }
00560 
00561 
00562 static int ASF_ReadObject_codec_list( stream_t *s, asf_object_t *p_obj )
00563 {
00564     asf_object_codec_list_t *p_cl = (asf_object_codec_list_t*)p_obj;
00565     int     i_peek;
00566     uint8_t *p_peek, *p_data;
00567 
00568     unsigned int i_codec;
00569 
00570     if( ( i_peek = stream_Peek( s, &p_peek, p_cl->i_object_size ) ) < 44 )
00571     {
00572        return VLC_EGENERIC;
00573     }
00574 
00575     ASF_GetGUID( &p_cl->i_reserved, p_peek + 24 );
00576     p_cl->i_codec_entries_count = GetWLE( p_peek + 40 );
00577     if( p_cl->i_codec_entries_count > 0 )
00578     {
00579         p_cl->codec = calloc( p_cl->i_codec_entries_count,
00580                               sizeof( asf_codec_entry_t ) );
00581         memset( p_cl->codec, 0,
00582                 p_cl->i_codec_entries_count * sizeof( asf_codec_entry_t ) );
00583 
00584         p_data = p_peek + 44;
00585         for( i_codec = 0; i_codec < p_cl->i_codec_entries_count; i_codec++ )
00586         {
00587 #define codec p_cl->codec[i_codec]
00588             int i_len, i;
00589 
00590             codec.i_type = GetWLE( p_data ); p_data += 2;
00591             /* codec name */
00592             i_len = GetWLE( p_data ); p_data += 2;
00593             codec.psz_name = calloc( sizeof( char ), i_len + 1);
00594             for( i = 0; i < i_len; i++ )
00595             {
00596                 codec.psz_name[i] = GetWLE( p_data + 2*i );
00597             }
00598             codec.psz_name[i_len] = '\0';
00599             p_data += 2 * i_len;
00600 
00601             /* description */
00602             i_len = GetWLE( p_data ); p_data += 2;
00603             codec.psz_description = calloc( sizeof( char ), i_len + 1);
00604             for( i = 0; i < i_len; i++ )
00605             {
00606                 codec.psz_description[i] = GetWLE( p_data + 2*i );
00607             }
00608             codec.psz_description[i_len] = '\0';
00609             p_data += 2 * i_len;
00610 
00611             /* opaque information */
00612             codec.i_information_length = GetWLE( p_data ); p_data += 2;
00613             if( codec.i_information_length > 0 )
00614             {
00615                 codec.p_information = malloc( codec.i_information_length );
00616                 memcpy( codec.p_information, p_data, codec.i_information_length );
00617                 p_data += codec.i_information_length;
00618             }
00619             else
00620             {
00621                 codec.p_information = NULL;
00622             }
00623 #undef  codec
00624         }
00625     }
00626     else
00627     {
00628         p_cl->codec = NULL;
00629     }
00630 
00631 #ifdef ASF_DEBUG
00632     msg_Dbg( s, "read \"codec list object\" reserved_guid:" GUID_FMT
00633              " codec_entries_count:%d",
00634             GUID_PRINT( p_cl->i_reserved ), p_cl->i_codec_entries_count );
00635 
00636     for( i_codec = 0; i_codec < p_cl->i_codec_entries_count; i_codec++ )
00637     {
00638 #define codec p_cl->codec[i_codec]
00639         msg_Dbg( s, "  - codec[%d] %s name:\"%s\" "
00640                  "description:\"%s\" information_length:%d",
00641                  i_codec, ( codec.i_type == ASF_CODEC_TYPE_VIDEO ) ?
00642                  "video" : ( ( codec.i_type == ASF_CODEC_TYPE_AUDIO ) ?
00643                  "audio" : "unknown" ),
00644                  codec.psz_name, codec.psz_description,
00645                  codec.i_information_length );
00646 #undef  codec
00647     }
00648 #endif
00649 
00650     return VLC_SUCCESS;
00651 }
00652 
00653 static void ASF_FreeObject_codec_list( asf_object_t *p_obj )
00654 {
00655     asf_object_codec_list_t *p_cl = (asf_object_codec_list_t*)p_obj;
00656     unsigned int i_codec;
00657 
00658     for( i_codec = 0; i_codec < p_cl->i_codec_entries_count; i_codec++ )
00659     {
00660 #define codec p_cl->codec[i_codec]
00661         FREE( codec.psz_name );
00662         FREE( codec.psz_description );
00663         FREE( codec.p_information );
00664 #undef  codec
00665     }
00666     FREE( p_cl->codec );
00667 }
00668 
00669 /* Microsoft should go to hell. This time the length give number of bytes
00670  * and for the some others object, length give char16 count ... */
00671 static int ASF_ReadObject_content_description(stream_t *s, asf_object_t *p_obj)
00672 {
00673     asf_object_content_description_t *p_cd =
00674         (asf_object_content_description_t *)p_obj;
00675     uint8_t *p_peek, *p_data;
00676     int i_peek;
00677     int i_len, i_title, i_author, i_copyright, i_description, i_rating;
00678 
00679 #define GETSTRINGW( psz_str, i_size ) \
00680    psz_str = calloc( i_size/2 + 1, sizeof( char ) ); \
00681    for( i_len = 0; i_len < i_size/2; i_len++ ) \
00682    { \
00683        psz_str[i_len] = GetWLE( p_data + 2*i_len ); \
00684    } \
00685    psz_str[i_size/2] = '\0'; \
00686    p_data += i_size;
00687 
00688     if( ( i_peek = stream_Peek( s, &p_peek, p_cd->i_object_size ) ) < 34 )
00689     {
00690        return VLC_EGENERIC;
00691     }
00692     p_data = p_peek + 24;
00693 
00694     i_title = GetWLE( p_data ); p_data += 2;
00695     i_author= GetWLE( p_data ); p_data += 2;
00696     i_copyright     = GetWLE( p_data ); p_data += 2;
00697     i_description   = GetWLE( p_data ); p_data += 2;
00698     i_rating        = GetWLE( p_data ); p_data += 2;
00699 
00700     GETSTRINGW( p_cd->psz_title, i_title );
00701     GETSTRINGW( p_cd->psz_author, i_author );
00702     GETSTRINGW( p_cd->psz_copyright, i_copyright );
00703     GETSTRINGW( p_cd->psz_description, i_description );
00704     GETSTRINGW( p_cd->psz_rating, i_rating );
00705 
00706 #undef  GETSTRINGW
00707 
00708 #ifdef ASF_DEBUG
00709     msg_Dbg( s,
00710              "Read \"content description object\" title:\"%s\" author:\"%s\" copyright:\"%s\" description:\"%s\" rating:\"%s\"",
00711              p_cd->psz_title,
00712              p_cd->psz_author,
00713              p_cd->psz_copyright,
00714              p_cd->psz_description,
00715              p_cd->psz_rating );
00716 #endif
00717     return VLC_SUCCESS;
00718 }
00719 
00720 static void ASF_FreeObject_content_description( asf_object_t *p_obj)
00721 {
00722     asf_object_content_description_t *p_cd =
00723         (asf_object_content_description_t *)p_obj;
00724 
00725     FREE( p_cd->psz_title );
00726     FREE( p_cd->psz_author );
00727     FREE( p_cd->psz_copyright );
00728     FREE( p_cd->psz_description );
00729     FREE( p_cd->psz_rating );
00730 }
00731 
00732 /* Language list: */
00733 static int ASF_ReadObject_language_list(stream_t *s, asf_object_t *p_obj)
00734 {
00735     asf_object_language_list_t *p_ll =
00736         (asf_object_language_list_t*)p_obj;
00737     uint8_t *p_peek, *p_data;
00738     int i_peek;
00739     int i;
00740 
00741     if( ( i_peek = stream_Peek( s, &p_peek, p_ll->i_object_size ) ) < 26 )
00742        return VLC_EGENERIC;
00743 
00744     p_data = &p_peek[24];
00745 
00746     p_ll->i_language = GetWLE( &p_data[0] ); p_data += 2;
00747     if( p_ll->i_language > 0 )
00748     {
00749         p_ll->ppsz_language = calloc( p_ll->i_language, sizeof( char *) );
00750 
00751         for( i = 0; i < p_ll->i_language; i++ )
00752         {
00753             char *psz;
00754             int i_size = *p_data++;
00755             int i_len;
00756 
00757             psz = calloc( i_size/2 + 1, sizeof( char ) );
00758             for( i_len = 0; i_len < i_size/2; i_len++ )
00759             {
00760                 psz[i_len] = GetWLE( p_data + 2*i_len );
00761             }
00762             psz[i_size/2] = '\0'; \
00763             p_data += i_size;
00764 
00765             p_ll->ppsz_language[i] = psz;
00766         }
00767     }
00768 
00769 #ifdef ASF_DEBUG
00770     msg_Dbg( s, "Read \"language list object\" %d entries", 
00771              p_ll->i_language );
00772     for( i = 0; i < p_ll->i_language; i++ )
00773         msg_Dbg( s, "  - '%s'", 
00774                  p_ll->ppsz_language[i] );
00775 #endif
00776     return VLC_SUCCESS;
00777 }
00778 
00779 static void ASF_FreeObject_language_list( asf_object_t *p_obj)
00780 {
00781     asf_object_language_list_t *p_ll =
00782         (asf_object_language_list_t *)p_obj;
00783     int i;
00784 
00785     for( i = 0; i < p_ll->i_language; i++ )
00786         FREE( p_ll->ppsz_language[i] );
00787     FREE( p_ll->ppsz_language );
00788 }
00789 
00790 /* Stream bitrate properties */
00791 static int ASF_ReadObject_stream_bitrate_properties( stream_t *s,
00792                                                      asf_object_t *p_obj)
00793 {
00794     asf_object_stream_bitrate_properties_t *p_sb =
00795         (asf_object_stream_bitrate_properties_t *)p_obj;
00796     uint8_t *p_peek, *p_data;
00797     int i_peek;
00798     int i;
00799 
00800     if( ( i_peek = stream_Peek( s, &p_peek, p_sb->i_object_size ) ) < 26 )
00801        return VLC_EGENERIC;
00802 
00803     p_data = &p_peek[24];
00804 
00805     p_sb->i_bitrate = GetWLE( &p_data[0] ); p_data += 2;
00806     if( p_sb->i_bitrate > 127 ) p_sb->i_bitrate = 127;  /* Buggy ? */
00807     for( i = 0; i < p_sb->i_bitrate; i++ )
00808     {
00809         p_sb->bitrate[i].i_stream_number = GetWLE( &p_data[0] )& 0x7f;
00810         p_sb->bitrate[i].i_avg_bitrate = GetDWLE( &p_data[2] );
00811        
00812         p_data += 2+4;
00813     }
00814 
00815 #ifdef ASF_DEBUG
00816     msg_Dbg( s,"Read \"stream bitrate properties object\"" );
00817     for( i = 0; i < p_sb->i_bitrate; i++ )
00818     {
00819         msg_Dbg( s,"  - stream=%d bitrate=%d",
00820                  p_sb->bitrate[i].i_stream_number,
00821                  p_sb->bitrate[i].i_avg_bitrate ); 
00822     }
00823 #endif
00824     return VLC_SUCCESS;
00825 }
00826 static void ASF_FreeObject_stream_bitrate_properties( asf_object_t *p_obj)
00827 {
00828 }
00829 
00830 static int ASF_ReadObject_extended_stream_properties( stream_t *s,
00831                                                       asf_object_t *p_obj)
00832 {
00833     asf_object_extended_stream_properties_t *p_esp =
00834         (asf_object_extended_stream_properties_t*)p_obj;
00835     uint8_t *p_peek, *p_data;
00836     int i_peek, i;
00837 
00838     if( ( i_peek = stream_Peek( s, &p_peek, p_esp->i_object_size ) ) < 88 )
00839        return VLC_EGENERIC;
00840 
00841     p_data = &p_peek[24];
00842 
00843     p_esp->i_start_time = GetQWLE( &p_data[0] );
00844     p_esp->i_end_time = GetQWLE( &p_data[8] );
00845     p_esp->i_data_bitrate = GetDWLE( &p_data[16] );
00846     p_esp->i_buffer_size = GetDWLE( &p_data[20] );
00847     p_esp->i_initial_buffer_fullness = GetDWLE( &p_data[24] );
00848     p_esp->i_alternate_data_bitrate = GetDWLE( &p_data[28] );
00849     p_esp->i_alternate_buffer_size = GetDWLE( &p_data[32] );
00850     p_esp->i_alternate_initial_buffer_fullness = GetDWLE( &p_data[36] );
00851     p_esp->i_maximum_object_size = GetDWLE( &p_data[40] );
00852     p_esp->i_flags = GetDWLE( &p_data[44] );
00853     p_esp->i_stream_number = GetWLE( &p_data[48] );
00854     p_esp->i_language_index = GetWLE( &p_data[50] );
00855     p_esp->i_average_time_per_frame= GetQWLE( &p_data[52] );
00856     p_esp->i_stream_name_count = GetWLE( &p_data[60] );
00857     p_esp->i_payload_extention_system_count = GetWLE( &p_data[62] );
00858 
00859     p_data += 64;
00860 
00861     p_esp->pi_stream_name_language = calloc( sizeof(int),
00862                                              p_esp->i_stream_name_count );
00863     p_esp->ppsz_stream_name = calloc( sizeof(char*),
00864                                       p_esp->i_stream_name_count );
00865     for( i = 0; i < p_esp->i_stream_name_count; i++ )
00866     {
00867         int i_size;
00868         char *psz;
00869         int i_len;
00870 
00871         p_esp->pi_stream_name_language[i] = GetWLE( &p_data[0] );
00872         i_size = GetWLE( &p_data[2] );
00873         p_data += 2;
00874         
00875         psz = calloc( i_size/2 + 1, sizeof( char ) );
00876         for( i_len = 0; i_len < i_size/2; i_len++ )
00877         {
00878             psz[i_len] = GetWLE( p_data + 2*i_len );
00879         }
00880         psz[i_size/2] = '\0'; \
00881         p_data += i_size;
00882 
00883         p_esp->ppsz_stream_name[i] = psz;
00884     }
00885 
00886     for( i = 0; i < p_esp->i_payload_extention_system_count; i++ )
00887     {
00888         /* Skip them */
00889         int i_size = GetDWLE( &p_data[16 + 2] );
00890 
00891         p_data += 16+2+4+i_size;
00892     }
00893 
00894     p_esp->p_sp = NULL;
00895     if( p_data < &p_peek[i_peek] )
00896     {
00897         asf_object_t *p_sp;
00898         /* Cannot fail as peek succeed */
00899         stream_Read( s, NULL, p_data - p_peek );
00900         
00901         p_sp = malloc( sizeof( asf_object_t ) );
00902 
00903         if( ASF_ReadObject( s, p_sp, NULL ) )
00904         {
00905             free( p_sp );
00906         }
00907         else
00908         {
00909             /* This p_sp will be inserted by ReadRoot later */
00910             p_esp->p_sp = (asf_object_stream_properties_t*)p_sp;
00911         }
00912     }
00913 
00914 #ifdef ASF_DEBUG
00915     msg_Dbg( s, "Read \"extended stream properties object\":" );
00916     msg_Dbg( s, "  - start="I64Fd" end="I64Fd,
00917              p_esp->i_start_time, p_esp->i_end_time );
00918     msg_Dbg( s, "  - data bitrate=%d buffer=%d initial fullness=%d",
00919              p_esp->i_data_bitrate,
00920              p_esp->i_buffer_size,
00921              p_esp->i_initial_buffer_fullness );
00922     msg_Dbg( s, "  - alternate data bitrate=%d buffer=%d initial fullness=%d",
00923              p_esp->i_alternate_data_bitrate,
00924              p_esp->i_alternate_buffer_size,
00925              p_esp->i_alternate_initial_buffer_fullness );
00926     msg_Dbg( s, "  - maximum object size=%d", p_esp->i_maximum_object_size );
00927     msg_Dbg( s, "  - flags=0x%x", p_esp->i_flags );
00928     msg_Dbg( s, "  - stream number=%d language=%d",
00929              p_esp->i_stream_number, p_esp->i_language_index );
00930     msg_Dbg( s, "  - average time per frame="I64Fd,
00931              p_esp->i_average_time_per_frame );
00932     msg_Dbg( s, "  - stream name count=%d", p_esp->i_stream_name_count );
00933     for( i = 0; i < p_esp->i_stream_name_count; i++ )
00934         msg_Dbg( s, "     - lang id=%d name=%s",
00935                  p_esp->pi_stream_name_language[i],
00936                  p_esp->ppsz_stream_name[i] );
00937     msg_Dbg( s, "  - payload extention system count=%d",
00938              p_esp->i_payload_extention_system_count );
00939 #endif
00940     return VLC_SUCCESS;
00941 }
00942 static void ASF_FreeObject_extended_stream_properties( asf_object_t *p_obj)
00943 {
00944     asf_object_extended_stream_properties_t *p_esp =
00945         (asf_object_extended_stream_properties_t *)p_obj;
00946     int i;
00947 
00948     for( i = 0; i < p_esp->i_stream_name_count; i++ )
00949         FREE( p_esp->ppsz_stream_name[i] );
00950     FREE( p_esp->pi_stream_name_language );
00951     FREE( p_esp->ppsz_stream_name );
00952 }
00953 
00954 
00955 static int ASF_ReadObject_advanced_mutual_exclusion( stream_t *s,
00956                                                      asf_object_t *p_obj)
00957 {
00958     asf_object_advanced_mutual_exclusion_t *p_ae =
00959         (asf_object_advanced_mutual_exclusion_t *)p_obj;
00960     uint8_t *p_peek, *p_data;
00961     int i_peek;
00962     int i;
00963 
00964     if( ( i_peek = stream_Peek( s, &p_peek, p_ae->i_object_size ) ) < 42 )
00965        return VLC_EGENERIC;
00966 
00967     p_data = &p_peek[24];
00968 
00969     ASF_GetGUID( &p_ae->type, &p_data[0] );
00970     p_ae->i_stream_number_count = GetWLE( &p_data[16] );
00971 
00972     p_data += 16 + 2;
00973     p_ae->pi_stream_number = calloc( sizeof(int),
00974                                      p_ae->i_stream_number_count );
00975     for( i = 0; i < p_ae->i_stream_number_count; i++ )
00976     {
00977         p_ae->pi_stream_number[i] = GetWLE( p_data );
00978         p_data += 2;
00979     }
00980         
00981 #ifdef ASF_DEBUG
00982     msg_Dbg( s, "Read \"advanced mutual exclusion object\"" );
00983     for( i = 0; i < p_ae->i_stream_number_count; i++ )
00984         msg_Dbg( s, "  - stream=%d", p_ae->pi_stream_number[i] );
00985 #endif
00986     return VLC_SUCCESS;
00987 }
00988 static void ASF_FreeObject_advanced_mutual_exclusion( asf_object_t *p_obj)
00989 {
00990     asf_object_advanced_mutual_exclusion_t *p_ae =
00991         (asf_object_advanced_mutual_exclusion_t *)p_obj;
00992 
00993     FREE( p_ae->pi_stream_number );
00994 }
00995 
00996 
00997 static int ASF_ReadObject_stream_prioritization( stream_t *s,
00998                                                  asf_object_t *p_obj)
00999 {
01000     asf_object_stream_prioritization_t *p_sp =
01001         (asf_object_stream_prioritization_t *)p_obj;
01002     uint8_t *p_peek, *p_data;
01003     int i_peek;
01004     int i;
01005 
01006     if( ( i_peek = stream_Peek( s, &p_peek, p_sp->i_object_size ) ) < 26 )
01007        return VLC_EGENERIC;
01008 
01009     p_data = &p_peek[24];
01010 
01011     p_sp->i_priority_count = GetWLE( &p_data[0] );
01012     p_data += 2;
01013 
01014     p_sp->pi_priority_flag = calloc( sizeof(int), p_sp->i_priority_count );
01015     p_sp->pi_priority_stream_number =
01016                              calloc( sizeof(int), p_sp->i_priority_count );
01017 
01018     for( i = 0; i < p_sp->i_priority_count; i++ )
01019     {
01020         p_sp->pi_priority_stream_number[i] = GetWLE( p_data ); p_data += 2;
01021         p_sp->pi_priority_flag[i] = GetWLE( p_data ); p_data += 2;
01022     }
01023 #ifdef ASF_DEBUG
01024     msg_Dbg( s, "Read \"stream prioritization object\"" );
01025     for( i = 0; i < p_sp->i_priority_count; i++ )
01026         msg_Dbg( s, "  - Stream:%d flags=0x%x",
01027                  p_sp->pi_priority_stream_number[i],
01028                  p_sp->pi_priority_flag[i] );
01029 #endif
01030     return VLC_SUCCESS;
01031 }
01032 static void ASF_FreeObject_stream_prioritization( asf_object_t *p_obj)
01033 {
01034     asf_object_stream_prioritization_t *p_sp =
01035         (asf_object_stream_prioritization_t *)p_obj;
01036 
01037     FREE( p_sp->pi_priority_stream_number );
01038     FREE( p_sp->pi_priority_flag );
01039 }
01040 
01041 
01042 static int ASF_ReadObject_extended_content_description( stream_t *s,
01043                                                         asf_object_t *p_obj)
01044 {
01045     asf_object_extended_content_description_t *p_ec =
01046         (asf_object_extended_content_description_t *)p_obj;
01047     uint8_t *p_peek, *p_data;
01048     int i_peek;
01049     int i;
01050 
01051     if( ( i_peek = stream_Peek( s, &p_peek, p_ec->i_object_size ) ) < 26 )
01052        return VLC_EGENERIC;
01053 
01054     p_data = &p_peek[24];
01055 
01056     p_ec->i_count = GetWLE( p_data ); p_data += 2;
01057     p_ec->ppsz_name = calloc( sizeof(char*), p_ec->i_count );
01058     p_ec->ppsz_value = calloc( sizeof(char*), p_ec->i_count );
01059     for( i = 0; i < p_ec->i_count; i++ )
01060     {
01061         int i_size;
01062         int i_type;
01063         int i_len;
01064 #define GETSTRINGW( psz_str, i_size ) \
01065        psz_str = calloc( i_size/2 + 1, sizeof( char ) ); \
01066        for( i_len = 0; i_len < i_size/2; i_len++ ) \
01067        { \
01068            psz_str[i_len] = GetWLE( p_data + 2*i_len ); \
01069        } \
01070        psz_str[i_size/2] = '\0';
01071 
01072         i_size = GetWLE( p_data ); p_data += 2;
01073         GETSTRINGW( p_ec->ppsz_name[i], i_size );
01074         p_data += i_size;
01075 
01076         /* Grrr */
01077         i_type = GetWLE( p_data ); p_data += 2;
01078         i_size = GetWLE( p_data ); p_data += 2;
01079         if( i_type == 0 )
01080         {
01081             GETSTRINGW( p_ec->ppsz_value[i], i_size );
01082         }
01083         else if( i_type == 1 )
01084         {
01085             int j;
01086             /* Byte array */
01087             p_ec->ppsz_value[i] = malloc( 2*i_size + 1 );
01088             for( j = 0; j < i_size; j++ )
01089             {
01090                 static const char hex[16] = "0123456789ABCDEF";
01091                 p_ec->ppsz_value[i][2*j+0] = hex[p_data[0]>>4];
01092                 p_ec->ppsz_value[i][2*j+1] = hex[p_data[0]&0xf];
01093             }
01094             p_ec->ppsz_value[i][2*i_size] = '\0';
01095         }
01096         else if( i_type == 2 )
01097         {
01098             /* Bool */
01099             p_ec->ppsz_value[i] = strdup( *p_data ? "true" : "false" );
01100         }
01101         else if( i_type == 3 )
01102         {
01103             /* DWord */
01104             asprintf( &p_ec->ppsz_value[i], "%d", GetDWLE(p_data));
01105         }
01106         else if( i_type == 4 )
01107         {
01108             /* QWord */
01109             asprintf( &p_ec->ppsz_value[i], I64Fd, GetQWLE(p_data));
01110         }
01111         else if( i_type == 5 )
01112         {
01113             /* Word */
01114             asprintf( &p_ec->ppsz_value[i], "%d", GetWLE(p_data));
01115         }
01116         else
01117             p_ec->ppsz_value[i] = NULL;
01118 
01119         p_data += i_size;
01120         
01121 
01122 
01123 #undef GETSTRINGW
01124 
01125     }
01126 
01127 #ifdef ASF_DEBUG
01128     msg_Dbg( s, "Read \"extended content description object\"" );
01129     for( i = 0; i < p_ec->i_count; i++ )
01130         msg_Dbg( s, "  - '%s' = '%s'",
01131                  p_ec->ppsz_name[i],
01132                  p_ec->ppsz_value[i] );
01133 #endif
01134     return VLC_SUCCESS;
01135 }
01136 static void ASF_FreeObject_extended_content_description( asf_object_t *p_obj)
01137 {
01138     asf_object_extended_content_description_t *p_ec =
01139         (asf_object_extended_content_description_t *)p_obj;
01140     int i;
01141 
01142     for( i = 0; i < p_ec->i_count; i++ )
01143     {
01144         FREE( p_ec->ppsz_name[i] );
01145         FREE( p_ec->ppsz_value[i] );
01146     }
01147 }
01148 
01149 
01150 #if 0
01151 static int ASF_ReadObject_XXX(stream_t *s, asf_object_t *p_obj)
01152 {
01153     asf_object_XXX_t *p_XX =
01154         (asf_object_XXX_t *)p_obj;
01155     uint8_t *p_peek, *p_data;
01156     int i_peek;
01157 
01158     if( ( i_peek = stream_Peek( s, &p_peek, p_XX->i_object_size ) ) < XXX )
01159        return VLC_EGENERIC;
01160 
01161     p_data = &p_peek[24];
01162 
01163 #ifdef ASF_DEBUG
01164     msg_Dbg( s,
01165              "Read \"XXX object\"" );
01166 #endif
01167     return VLC_SUCCESS;
01168 }
01169 static void ASF_FreeObject_XXX( asf_object_t *p_obj)
01170 {
01171     asf_object_XXX_t *p_XX =
01172         (asf_object_XXX_t *)p_obj;
01173 }
01174 #endif
01175 
01176 
01177 /* */
01178 static struct
01179 {
01180     const guid_t  *p_id;
01181     int     i_type;
01182     int     (*ASF_ReadObject_function)( stream_t *, asf_object_t *p_obj );
01183     void    (*ASF_FreeObject_function)( asf_object_t *p_obj );
01184 
01185 } ASF_Object_Function [] =
01186 {
01187     { &asf_object_header_guid, ASF_OBJECT_HEADER,
01188       ASF_ReadObject_Header, ASF_FreeObject_Null },
01189     { &asf_object_data_guid, ASF_OBJECT_DATA,
01190       ASF_ReadObject_Data, ASF_FreeObject_Null },
01191     { &asf_object_index_guid, ASF_OBJECT_INDEX,
01192       ASF_ReadObject_Index, ASF_FreeObject_Index },
01193     { &asf_object_file_properties_guid, ASF_OBJECT_FILE_PROPERTIES,
01194       ASF_ReadObject_file_properties, ASF_FreeObject_Null },
01195     { &asf_object_stream_properties_guid, ASF_OBJECT_STREAM_PROPERTIES,
01196       ASF_ReadObject_stream_properties,ASF_FreeObject_stream_properties },
01197     { &asf_object_header_extension_guid, ASF_OBJECT_HEADER_EXTENSION,
01198       ASF_ReadObject_header_extension, ASF_FreeObject_header_extension},
01199     { &asf_object_metadata_guid, ASF_OBJECT_METADATA,
01200       ASF_ReadObject_metadata, ASF_FreeObject_metadata},
01201     { &asf_object_codec_list_guid, ASF_OBJECT_CODEC_LIST,
01202       ASF_ReadObject_codec_list, ASF_FreeObject_codec_list },
01203     { &asf_object_marker_guid, ASF_OBJECT_MARKER, NULL, NULL },
01204     { &asf_object_padding, ASF_OBJECT_PADDING, NULL, NULL },
01205     { &asf_object_content_description_guid, ASF_OBJECT_CONTENT_DESCRIPTION,
01206       ASF_ReadObject_content_description, ASF_FreeObject_content_description },
01207     { &asf_object_language_list, ASF_OBJECT_OTHER,
01208       ASF_ReadObject_language_list, ASF_FreeObject_language_list },
01209     { &asf_object_stream_bitrate_properties, ASF_OBJECT_OTHER,
01210       ASF_ReadObject_stream_bitrate_properties,
01211       ASF_FreeObject_stream_bitrate_properties },
01212     { &asf_object_extended_stream_properties, ASF_OBJECT_OTHER,
01213       ASF_ReadObject_extended_stream_properties,
01214       ASF_FreeObject_extended_stream_properties },
01215     { &asf_object_advanced_mutual_exclusion, ASF_OBJECT_OTHER,
01216       ASF_ReadObject_advanced_mutual_exclusion,
01217       ASF_FreeObject_advanced_mutual_exclusion },
01218     { &asf_object_stream_prioritization, ASF_OBJECT_OTHER,
01219       ASF_ReadObject_stream_prioritization,
01220       ASF_FreeObject_stream_prioritization },
01221     { &asf_object_extended_content_description, ASF_OBJECT_OTHER,
01222       ASF_ReadObject_extended_content_description,
01223       ASF_FreeObject_extended_content_description },
01224 
01225     { &asf_object_null_guid, 0, NULL, NULL }
01226 };
01227 
01228 static int ASF_ReadObject( stream_t *s, asf_object_t *p_obj,
01229                            asf_object_t *p_father )
01230 {
01231     int i_result;
01232     int i_index;
01233 
01234     if( !p_obj )
01235         return( 0 );
01236 
01237     memset( p_obj, 0, sizeof( p_obj ) );
01238 
01239     if( ASF_ReadObjectCommon( s, p_obj ) )
01240     {
01241         msg_Warn( s, "cannot read one asf object" );
01242         return VLC_EGENERIC;
01243     }
01244     p_obj->common.p_father = p_father;
01245     p_obj->common.p_first = NULL;
01246     p_obj->common.p_next = NULL;
01247     p_obj->common.p_last = NULL;
01248 
01249     if( p_obj->common.i_object_size < 24 )
01250     {
01251         msg_Warn( s, "found a corrupted asf object (size<24)" );
01252         return VLC_EGENERIC;
01253     }
01254 
01255     /* find this object */
01256     for( i_index = 0; ; i_index++ )
01257     {
01258         if( ASF_CmpGUID( ASF_Object_Function[i_index].p_id,
01259                          &p_obj->common.i_object_id ) ||
01260             ASF_CmpGUID( ASF_Object_Function[i_index].p_id,
01261                          &asf_object_null_guid ) )
01262         {
01263             break;
01264         }
01265     }
01266     p_obj->common.i_type = ASF_Object_Function[i_index].i_type;
01267 
01268     /* Now load this object */
01269     if( ASF_Object_Function[i_index].ASF_ReadObject_function == NULL )
01270     {
01271         msg_Warn( s, "unknown asf object (not loaded)" );
01272         i_result = VLC_SUCCESS;
01273     }
01274     else
01275     {
01276         /* XXX ASF_ReadObject_function realloc *pp_obj XXX */
01277         i_result =
01278           (ASF_Object_Function[i_index].ASF_ReadObject_function)( s, p_obj );
01279     }
01280 
01281     /* link this object with father */
01282     if( p_father )
01283     {
01284         if( p_father->common.p_first )
01285         {
01286             p_father->common.p_last->common.p_next = p_obj;
01287         }
01288         else
01289         {
01290             p_father->common.p_first = p_obj;
01291         }
01292         p_father->common.p_last = p_obj;
01293     }
01294 
01295     return( i_result );
01296 }
01297 
01298 static void ASF_FreeObject( stream_t *s, asf_object_t *p_obj )
01299 {
01300     int i_index;
01301     asf_object_t *p_child;
01302 
01303     if( !p_obj ) return;
01304 
01305     /* Free all child object */
01306     p_child = p_obj->common.p_first;
01307     while( p_child )
01308     {
01309         asf_object_t *p_next;
01310         p_next = p_child->common.p_next;
01311         ASF_FreeObject( s, p_child );
01312         p_child = p_next;
01313     }
01314 
01315     /* find this object */
01316     for( i_index = 0; ; i_index++ )
01317     {
01318         if( ASF_CmpGUID( ASF_Object_Function[i_index].p_id,
01319                      &p_obj->common.i_object_id )||
01320             ASF_CmpGUID( ASF_Object_Function[i_index].p_id,
01321                      &asf_object_null_guid ) )
01322         {
01323             break;
01324         }
01325     }
01326 
01327     /* Now free this object */
01328     if( ASF_Object_Function[i_index].ASF_FreeObject_function == NULL )
01329     {
01330         msg_Warn( s,
01331                   "unknown asf object " GUID_FMT,
01332                   GUID_PRINT( p_obj->common.i_object_id ) );
01333     }
01334     else
01335     {
01336 #ifdef ASF_DEBUG
01337         msg_Dbg( s,
01338                   "free asf object " GUID_FMT,
01339                   GUID_PRINT( p_obj->common.i_object_id ) );
01340 #endif
01341         (ASF_Object_Function[i_index].ASF_FreeObject_function)( p_obj );
01342     }
01343     free( p_obj );
01344     return;
01345 }
01346 
01347 /*****************************************************************************
01348  * ASF_ObjectDumpDebug:
01349  *****************************************************************************/
01350 static const struct
01351 {
01352     const guid_t *p_id;
01353     char *psz_name;
01354 } ASF_ObjectDumpDebugInfo[] =
01355 {
01356     { &asf_object_header_guid, "Header" },
01357     { &asf_object_data_guid, "Data" },
01358     { &asf_object_index_guid, "Index" },
01359     { &asf_object_file_properties_guid, "File Properties" },
01360     { &asf_object_stream_properties_guid, "Stream Properties" },
01361     { &asf_object_content_description_guid, "Content Description" },
01362     { &asf_object_header_extension_guid, "Header Extention" },
01363     { &asf_object_metadata_guid, "Metadata" },
01364     { &asf_object_codec_list_guid, "Codec List" },
01365     { &asf_object_marker_guid, "Marker" },
01366     { &asf_object_stream_type_audio, "Stream Type Audio" },
01367     { &asf_object_stream_type_video, "Stream Type Video" },
01368     { &asf_object_stream_type_command, "Stream Type Command" },
01369     { &asf_object_language_list, "Language List" },
01370     { &asf_object_stream_bitrate_properties, "Stream Bitrate Propoerties" },
01371     { &asf_object_padding, "Padding" },
01372     { &asf_object_extended_stream_properties, "Extended Stream Properties" },
01373     { &asf_object_advanced_mutual_exclusion, "Advanced Mutual Exclusion" },
01374     { &asf_object_stream_prioritization, "Stream Prioritization" },
01375     { &asf_object_extended_content_description, "Extended content description"},
01376 
01377     { NULL, "Unknown" },
01378 };
01379 
01380 
01381 static void ASF_ObjectDumpDebug( vlc_object_t *p_obj,
01382                                  asf_object_common_t *p_node, int i_level )
01383 {
01384     char str[1024];
01385     int i;
01386     union asf_object_u *p_child;
01387     char *psz_name;
01388 
01389     /* Find the name */
01390     for( i = 0; ASF_ObjectDumpDebugInfo[i].p_id != NULL; i++ )
01391     {
01392         if( ASF_CmpGUID( ASF_ObjectDumpDebugInfo[i].p_id,
01393                           &p_node->i_object_id ) )
01394             break;
01395     }
01396     psz_name = ASF_ObjectDumpDebugInfo[i].psz_name;
01397 
01398     memset( str, ' ', sizeof( str ) );
01399     for( i = 1; i < i_level; i++ )
01400     {
01401         str[i * 5] = '|';
01402     }
01403     snprintf( str + 5*i_level, 1024,
01404              "+ '%s' GUID "GUID_FMT" size:"I64Fu"pos:"I64Fu,
01405              psz_name,
01406              GUID_PRINT( p_node->i_object_id ),
01407              p_node->i_object_size, p_node->i_object_pos );
01408 
01409     msg_Dbg( p_obj, "%s", str );
01410 
01411     for( p_child = p_node->p_first; p_child != NULL;
01412                                              p_child = p_child->common.p_next )
01413     {
01414         ASF_ObjectDumpDebug( p_obj, &p_child->common, i_level + 1 );
01415     }
01416 }
01417 
01418 /*****************************************************************************
01419  * ASF_ReadObjetRoot : parse the entire stream/file
01420  *****************************************************************************/
01421 asf_object_root_t *ASF_ReadObjectRoot( stream_t *s, int b_seekable )
01422 {
01423     asf_object_root_t *p_root = malloc( sizeof( asf_object_root_t ) );
01424     asf_object_t *p_obj;
01425 
01426     p_root->i_type = ASF_OBJECT_ROOT;
01427     memcpy( &p_root->i_object_id, &asf_object_null_guid, sizeof( guid_t ) );
01428     p_root->i_object_pos = stream_Tell( s );
01429     p_root->i_object_size = 0;
01430     p_root->p_first = NULL;
01431     p_root->p_last  = NULL;
01432     p_root->p_next  = NULL;
01433     p_root->p_hdr   = NULL;
01434     p_root->p_data  = NULL;
01435     p_root->p_fp    = NULL;
01436     p_root->p_index = NULL;
01437     p_root->p_metadata = NULL;
01438 
01439     for( ; ; )
01440     {
01441         p_obj = malloc( sizeof( asf_object_t ) );
01442 
01443         if( ASF_ReadObject( s, p_obj, (asf_object_t*)p_root ) )
01444         {
01445             free( p_obj );
01446             break;
01447         }
01448         switch( p_obj->common.i_type )
01449         {
01450             case( ASF_OBJECT_HEADER ):
01451                 p_root->p_hdr = (asf_object_header_t*)p_obj;
01452                 break;
01453             case( ASF_OBJECT_DATA ):
01454                 p_root->p_data = (asf_object_data_t*)p_obj;
01455                 break;
01456             case( ASF_OBJECT_INDEX ):
01457                 p_root->p_index = (asf_object_index_t*)p_obj;
01458                 break;
01459             default:
01460                 msg_Warn( s, "unknow object found" );
01461                 break;
01462         }
01463         if( p_obj->common.i_type == ASF_OBJECT_DATA &&
01464             p_obj->common.i_object_size <= 50 )
01465         {
01466             /* probably a dump of broadcasted asf */
01467             break;
01468         }
01469         if( !b_seekable && p_root->p_hdr && p_root->p_data )
01470         {
01471             /* For unseekable stream it's enough to play */
01472             break;
01473         }
01474 
01475         if( ASF_NextObject( s, p_obj ) ) /* Go to the next object */
01476         {
01477             break;
01478         }
01479     }
01480 
01481     if( p_root->p_hdr != NULL && p_root->p_data != NULL )
01482     {
01483         p_root->p_fp = ASF_FindObject( p_root->p_hdr,
01484                                        &asf_object_file_properties_guid, 0 );
01485 
01486         if( p_root->p_fp )
01487         {
01488             asf_object_t *p_hdr_ext =
01489                 ASF_FindObject( p_root->p_hdr,
01490                                 &asf_object_header_extension_guid, 0 );
01491             if( p_hdr_ext )
01492             {
01493                 int i_ext_stream;
01494                 int i;
01495 
01496                 p_root->p_metadata =
01497                     ASF_FindObject( p_hdr_ext,
01498                                     &asf_object_metadata_guid, 0 );
01499                 /* Special case for broken designed file format :( */
01500                 i_ext_stream = ASF_CountObject( p_hdr_ext,
01501                                     &asf_object_extended_stream_properties );
01502                 for( i = 0; i < i_ext_stream; i++ )
01503                 {
01504                     asf_object_t *p_esp =
01505                         ASF_FindObject( p_hdr_ext,
01506                                    &asf_object_extended_stream_properties, i );
01507                     if( p_esp->ext_stream.p_sp )
01508                     {
01509                         asf_object_t *p_sp =
01510                                          (asf_object_t*)p_esp->ext_stream.p_sp;
01511 
01512                         /* Insert this p_sp */
01513                         p_root->p_hdr->p_last->common.p_next = p_sp;
01514                         p_root->p_hdr->p_last = p_sp;
01515 
01516                         p_sp->common.p_father = (asf_object_t*)p_root->p_hdr;
01517                     }
01518                 }
01519             }
01520 
01521             ASF_ObjectDumpDebug( VLC_OBJECT(s),
01522                                  (asf_object_common_t*)p_root, 0 );
01523             return p_root;
01524         }
01525         msg_Warn( s, "cannot find file properties object" );
01526     }
01527 
01528     /* Invalid file */
01529     ASF_FreeObjectRoot( s, p_root );
01530     return NULL;
01531 }
01532 
01533 void ASF_FreeObjectRoot( stream_t *s, asf_object_root_t *p_root )
01534 {
01535     asf_object_t *p_obj;
01536 
01537     p_obj = p_root->p_first;
01538     while( p_obj )
01539     {
01540         asf_object_t *p_next;
01541         p_next = p_obj->common.p_next;
01542         ASF_FreeObject( s, p_obj );
01543         p_obj = p_next;
01544     }
01545     free( p_root );
01546 }
01547 
01548 int  __ASF_CountObject( asf_object_t *p_obj, const guid_t *p_guid )
01549 {
01550     int i_count;
01551     asf_object_t *p_child;
01552 
01553     if( !p_obj ) return( 0 );
01554 
01555     i_count = 0;
01556     p_child = p_obj->common.p_first;
01557     while( p_child )
01558     {
01559         if( ASF_CmpGUID( &p_child->common.i_object_id, p_guid ) )
01560         {
01561             i_count++;
01562         }
01563         p_child = p_child->common.p_next;
01564     }
01565     return( i_count );
01566 }
01567 
01568 void *__ASF_FindObject( asf_object_t *p_obj, const guid_t *p_guid,
01569                         int i_number )
01570 {
01571     asf_object_t *p_child;
01572 
01573     p_child = p_obj->common.p_first;
01574 
01575     while( p_child )
01576     {
01577         if( ASF_CmpGUID( &p_child->common.i_object_id, p_guid ) )
01578         {
01579             if( i_number == 0 )
01580             {
01581                 /* We found it */
01582                 return( p_child );
01583             }
01584 
01585             i_number--;
01586         }
01587         p_child = p_child->common.p_next;
01588     }
01589     return( NULL );
01590 }

Generated on Tue Dec 20 10:14:31 2005 for vlc-0.8.4a by  doxygen 1.4.2