static int AVI_ChunkRead_strf( stream_t *s, avi_chunk_t *p_chk ) { avi_chunk_t *p_strh; AVI_READCHUNK_ENTER; if( p_chk->common.p_father == NULL ) { msg_Err( (vlc_object_t*)s, "malformed avi file" ); AVI_READCHUNK_EXIT( VLC_EGENERIC ); } if( !( p_strh = AVI_ChunkFind( p_chk->common.p_father, AVIFOURCC_strh, 0 ) ) ) { msg_Err( (vlc_object_t*)s, "malformed avi file" ); AVI_READCHUNK_EXIT( VLC_EGENERIC ); } switch( p_strh->strh.i_type ) { case( AVIFOURCC_auds ): p_chk->strf.auds.i_cat = AUDIO_ES; p_chk->strf.auds.p_wf = malloc( __MAX( p_chk->common.i_chunk_size, sizeof( WAVEFORMATEX ) ) ); AVI_READ2BYTES( p_chk->strf.auds.p_wf->wFormatTag ); AVI_READ2BYTES( p_chk->strf.auds.p_wf->nChannels ); AVI_READ4BYTES( p_chk->strf.auds.p_wf->nSamplesPerSec ); AVI_READ4BYTES( p_chk->strf.auds.p_wf->nAvgBytesPerSec ); AVI_READ2BYTES( p_chk->strf.auds.p_wf->nBlockAlign ); AVI_READ2BYTES( p_chk->strf.auds.p_wf->wBitsPerSample ); if( p_chk->strf.auds.p_wf->wFormatTag != WAVE_FORMAT_PCM && p_chk->common.i_chunk_size > sizeof( WAVEFORMATEX ) ) { AVI_READ2BYTES( p_chk->strf.auds.p_wf->cbSize ); /* prevent segfault */ if( p_chk->strf.auds.p_wf->cbSize > p_chk->common.i_chunk_size - sizeof( WAVEFORMATEX ) ) { p_chk->strf.auds.p_wf->cbSize = p_chk->common.i_chunk_size - sizeof( WAVEFORMATEX ); } if( p_chk->strf.auds.p_wf->wFormatTag == WAVE_FORMAT_EXTENSIBLE ) { /* Found an extensible header atm almost nothing uses that. */ msg_Warn( (vlc_object_t*)s, "WAVE_FORMAT_EXTENSIBLE or " "vorbis audio dectected: not supported" ); } } else { p_chk->strf.auds.p_wf->cbSize = 0; } if( p_chk->strf.auds.p_wf->cbSize > 0 ) { memcpy( &p_chk->strf.auds.p_wf[1] , p_buff + 8 + sizeof( WAVEFORMATEX ), /* 8=fourrc+size */ p_chk->strf.auds.p_wf->cbSize ); } #ifdef AVI_DEBUG msg_Dbg( (vlc_object_t*)s, "strf: audio:0x%4.4x channels:%d %dHz %dbits/sample %dkb/s", p_chk->strf.auds.p_wf->wFormatTag, p_chk->strf.auds.p_wf->nChannels, p_chk->strf.auds.p_wf->nSamplesPerSec, p_chk->strf.auds.p_wf->wBitsPerSample, p_chk->strf.auds.p_wf->nAvgBytesPerSec * 8 / 1024 ); #endif break; case( AVIFOURCC_vids ): p_strh->strh.i_samplesize = 0; /* XXX for ffmpeg avi file */ p_chk->strf.vids.i_cat = VIDEO_ES; p_chk->strf.vids.p_bih = malloc( p_chk->common.i_chunk_size ); AVI_READ4BYTES( p_chk->strf.vids.p_bih->biSize ); AVI_READ4BYTES( p_chk->strf.vids.p_bih->biWidth ); AVI_READ4BYTES( p_chk->strf.vids.p_bih->biHeight ); AVI_READ2BYTES( p_chk->strf.vids.p_bih->biPlanes ); AVI_READ2BYTES( p_chk->strf.vids.p_bih->biBitCount ); AVI_READFOURCC( p_chk->strf.vids.p_bih->biCompression ); AVI_READ4BYTES( p_chk->strf.vids.p_bih->biSizeImage ); AVI_READ4BYTES( p_chk->strf.vids.p_bih->biXPelsPerMeter ); AVI_READ4BYTES( p_chk->strf.vids.p_bih->biYPelsPerMeter ); AVI_READ4BYTES( p_chk->strf.vids.p_bih->biClrUsed ); AVI_READ4BYTES( p_chk->strf.vids.p_bih->biClrImportant ); if( p_chk->strf.vids.p_bih->biSize > p_chk->common.i_chunk_size ) { p_chk->strf.vids.p_bih->biSize = p_chk->common.i_chunk_size; } if( p_chk->common.i_chunk_size - sizeof(BITMAPINFOHEADER) > 0 ) { memcpy( &p_chk->strf.vids.p_bih[1], p_buff + 8 + sizeof(BITMAPINFOHEADER), /* 8=fourrc+size */ p_chk->common.i_chunk_size -sizeof(BITMAPINFOHEADER) ); } #ifdef AVI_DEBUG msg_Dbg( (vlc_object_t*)s, "strf: video:%4.4s %"PRIu32"x%"PRIu32" planes:%d %dbpp", (char*)&p_chk->strf.vids.p_bih->biCompression, (uint32_t)p_chk->strf.vids.p_bih->biWidth, (uint32_t)p_chk->strf.vids.p_bih->biHeight, p_chk->strf.vids.p_bih->biPlanes, p_chk->strf.vids.p_bih->biBitCount ); #endif break; default: msg_Warn( (vlc_object_t*)s, "unknown stream type" ); p_chk->strf.common.i_cat = UNKNOWN_ES; break; } AVI_READCHUNK_EXIT( VLC_SUCCESS ); }
static int AVI_ChunkRead_indx( stream_t *s, avi_chunk_t *p_chk ) { unsigned int i_count, i; int32_t i_dummy; avi_chunk_indx_t *p_indx = (avi_chunk_indx_t*)p_chk; AVI_READCHUNK_ENTER; AVI_READ2BYTES( p_indx->i_longsperentry ); AVI_READ1BYTE ( p_indx->i_indexsubtype ); AVI_READ1BYTE ( p_indx->i_indextype ); AVI_READ4BYTES( p_indx->i_entriesinuse ); AVI_READ4BYTES( p_indx->i_id ); p_indx->idx.std = NULL; p_indx->idx.field = NULL; p_indx->idx.super = NULL; if( p_indx->i_indextype == AVI_INDEX_OF_CHUNKS && p_indx->i_indexsubtype == 0 ) { AVI_READ8BYTES( p_indx->i_baseoffset ); AVI_READ4BYTES( i_dummy ); i_count = __MIN( p_indx->i_entriesinuse, i_read / 8 ); p_indx->i_entriesinuse = i_count; p_indx->idx.std = calloc( i_count, sizeof( indx_std_entry_t ) ); for( i = 0; i < i_count; i++ ) { AVI_READ4BYTES( p_indx->idx.std[i].i_offset ); AVI_READ4BYTES( p_indx->idx.std[i].i_size ); } } else if( p_indx->i_indextype == AVI_INDEX_OF_CHUNKS && p_indx->i_indexsubtype == AVI_INDEX_2FIELD ) { AVI_READ8BYTES( p_indx->i_baseoffset ); AVI_READ4BYTES( i_dummy ); i_count = __MIN( p_indx->i_entriesinuse, i_read / 12 ); p_indx->i_entriesinuse = i_count; p_indx->idx.field = calloc( i_count, sizeof( indx_field_entry_t ) ); for( i = 0; i < i_count; i++ ) { AVI_READ4BYTES( p_indx->idx.field[i].i_offset ); AVI_READ4BYTES( p_indx->idx.field[i].i_size ); AVI_READ4BYTES( p_indx->idx.field[i].i_offsetfield2 ); } } else if( p_indx->i_indextype == AVI_INDEX_OF_INDEXES ) { p_indx->i_baseoffset = 0; AVI_READ4BYTES( i_dummy ); AVI_READ4BYTES( i_dummy ); AVI_READ4BYTES( i_dummy ); i_count = __MIN( p_indx->i_entriesinuse, i_read / 16 ); p_indx->i_entriesinuse = i_count; p_indx->idx.super = calloc( i_count, sizeof( indx_super_entry_t ) ); for( i = 0; i < i_count; i++ ) { AVI_READ8BYTES( p_indx->idx.super[i].i_offset ); AVI_READ4BYTES( p_indx->idx.super[i].i_size ); AVI_READ4BYTES( p_indx->idx.super[i].i_duration ); } } else { msg_Warn( (vlc_object_t*)s, "unknow type/subtype index" ); } #ifdef AVI_DEBUG msg_Dbg( (vlc_object_t*)s, "indx: type=%d subtype=%d entry=%d", p_indx->i_indextype, p_indx->i_indexsubtype, p_indx->i_entriesinuse ); #endif AVI_READCHUNK_EXIT( VLC_SUCCESS ); }
static int AVI_ChunkRead_strf( stream_t *s, avi_chunk_t *p_chk ) { avi_chunk_t *p_strh; AVI_READCHUNK_ENTER; if( p_chk->common.p_father == NULL ) { msg_Err( (vlc_object_t*)s, "malformed avi file" ); AVI_READCHUNK_EXIT( VLC_EGENERIC ); } if( !( p_strh = AVI_ChunkFind( p_chk->common.p_father, AVIFOURCC_strh, 0 ) ) ) { msg_Err( (vlc_object_t*)s, "malformed avi file" ); AVI_READCHUNK_EXIT( VLC_EGENERIC ); } switch( p_strh->strh.i_type ) { case( AVIFOURCC_auds ): p_chk->strf.auds.i_cat = AUDIO_ES; p_chk->strf.auds.p_wf = xmalloc( __MAX( p_chk->common.i_chunk_size, sizeof( WAVEFORMATEX ) ) ); if ( !p_chk->strf.auds.p_wf ) { AVI_READCHUNK_EXIT( VLC_ENOMEM ); } AVI_READ2BYTES( p_chk->strf.auds.p_wf->wFormatTag ); AVI_READ2BYTES( p_chk->strf.auds.p_wf->nChannels ); AVI_READ4BYTES( p_chk->strf.auds.p_wf->nSamplesPerSec ); AVI_READ4BYTES( p_chk->strf.auds.p_wf->nAvgBytesPerSec ); AVI_READ2BYTES( p_chk->strf.auds.p_wf->nBlockAlign ); AVI_READ2BYTES( p_chk->strf.auds.p_wf->wBitsPerSample ); if( p_chk->strf.auds.p_wf->wFormatTag != WAVE_FORMAT_PCM && p_chk->common.i_chunk_size > sizeof( WAVEFORMATEX ) ) { AVI_READ2BYTES( p_chk->strf.auds.p_wf->cbSize ); /* prevent segfault */ if( p_chk->strf.auds.p_wf->cbSize > p_chk->common.i_chunk_size - sizeof( WAVEFORMATEX ) ) { p_chk->strf.auds.p_wf->cbSize = p_chk->common.i_chunk_size - sizeof( WAVEFORMATEX ); } if( p_chk->strf.auds.p_wf->wFormatTag == WAVE_FORMAT_EXTENSIBLE ) { msg_Dbg( s, "Extended header found" ); } } else { p_chk->strf.auds.p_wf->cbSize = 0; } if( p_chk->strf.auds.p_wf->cbSize > 0 ) { memcpy( &p_chk->strf.auds.p_wf[1] , p_buff + 8 + sizeof( WAVEFORMATEX ), /* 8=fourcc+size */ p_chk->strf.auds.p_wf->cbSize ); } #ifdef AVI_DEBUG msg_Dbg( (vlc_object_t*)s, "strf: audio:0x%4.4x channels:%d %dHz %dbits/sample %dkb/s", p_chk->strf.auds.p_wf->wFormatTag, p_chk->strf.auds.p_wf->nChannels, p_chk->strf.auds.p_wf->nSamplesPerSec, p_chk->strf.auds.p_wf->wBitsPerSample, p_chk->strf.auds.p_wf->nAvgBytesPerSec * 8 / 1024 ); #endif break; case( AVIFOURCC_vids ): p_strh->strh.i_samplesize = 0; /* XXX for ffmpeg avi file */ p_chk->strf.vids.i_cat = VIDEO_ES; p_chk->strf.vids.p_bih = xmalloc( __MAX( p_chk->common.i_chunk_size, sizeof( *p_chk->strf.vids.p_bih ) ) ); if ( !p_chk->strf.vids.p_bih ) { AVI_READCHUNK_EXIT( VLC_ENOMEM ); } AVI_READ4BYTES( p_chk->strf.vids.p_bih->biSize ); AVI_READ4BYTES( p_chk->strf.vids.p_bih->biWidth ); AVI_READ4BYTES( p_chk->strf.vids.p_bih->biHeight ); AVI_READ2BYTES( p_chk->strf.vids.p_bih->biPlanes ); AVI_READ2BYTES( p_chk->strf.vids.p_bih->biBitCount ); AVI_READFOURCC( p_chk->strf.vids.p_bih->biCompression ); AVI_READ4BYTES( p_chk->strf.vids.p_bih->biSizeImage ); AVI_READ4BYTES( p_chk->strf.vids.p_bih->biXPelsPerMeter ); AVI_READ4BYTES( p_chk->strf.vids.p_bih->biYPelsPerMeter ); AVI_READ4BYTES( p_chk->strf.vids.p_bih->biClrUsed ); AVI_READ4BYTES( p_chk->strf.vids.p_bih->biClrImportant ); if( p_chk->strf.vids.p_bih->biSize > p_chk->common.i_chunk_size ) { p_chk->strf.vids.p_bih->biSize = p_chk->common.i_chunk_size; } if ( p_chk->common.i_chunk_size > sizeof(VLC_BITMAPINFOHEADER) ) { uint64_t i_extrasize = p_chk->common.i_chunk_size - sizeof(VLC_BITMAPINFOHEADER); /* There's a color palette appended, set up VLC_BITMAPINFO */ memcpy( &p_chk->strf.vids.p_bih[1], p_buff + 8 + sizeof(VLC_BITMAPINFOHEADER), /* 8=fourrc+size */ i_extrasize ); if ( !p_chk->strf.vids.p_bih->biClrUsed ) p_chk->strf.vids.p_bih->biClrUsed = (1 << p_chk->strf.vids.p_bih->biBitCount); if( i_extrasize / sizeof(uint32_t) > UINT32_MAX ) p_chk->strf.vids.p_bih->biClrUsed = UINT32_MAX; else { p_chk->strf.vids.p_bih->biClrUsed = __MIN( i_extrasize / sizeof(uint32_t), p_chk->strf.vids.p_bih->biClrUsed ); } /* stay within VLC's limits */ p_chk->strf.vids.p_bih->biClrUsed = __MIN( VIDEO_PALETTE_COLORS_MAX, p_chk->strf.vids.p_bih->biClrUsed ); } else p_chk->strf.vids.p_bih->biClrUsed = 0; #ifdef AVI_DEBUG msg_Dbg( (vlc_object_t*)s, "strf: video:%4.4s %"PRIu32"x%"PRIu32" planes:%d %dbpp", (char*)&p_chk->strf.vids.p_bih->biCompression, (uint32_t)p_chk->strf.vids.p_bih->biWidth, (uint32_t)p_chk->strf.vids.p_bih->biHeight, p_chk->strf.vids.p_bih->biPlanes, p_chk->strf.vids.p_bih->biBitCount ); #endif break; case AVIFOURCC_iavs: case AVIFOURCC_ivas: p_chk->strf.common.i_cat = UNKNOWN_ES; break; case( AVIFOURCC_txts ): p_chk->strf.common.i_cat = SPU_ES; break; default: msg_Warn( (vlc_object_t*)s, "unknown stream type: %4.4s", (char*)&p_strh->strh.i_type ); p_chk->strf.common.i_cat = UNKNOWN_ES; break; } AVI_READCHUNK_EXIT( VLC_SUCCESS ); }