avi.c
来自「VLC媒体播放程序」· C语言 代码 · 共 2,041 行 · 第 1/5 页
C
2,041 行
case FOURCC_3IVD: case FOURCC_3ivd: case FOURCC_3VID: case FOURCC_3vid: return FOURCC_DIV3; case FOURCC_DIVX: case FOURCC_divx: case FOURCC_MP4S: case FOURCC_mp4s: case FOURCC_M4S2: case FOURCC_m4s2: case FOURCC_xvid: case FOURCC_XVID: case FOURCC_XviD: case FOURCC_DX50: case FOURCC_dx50: case FOURCC_mp4v: case FOURCC_4: case FOURCC_3IV2: case FOURCC_3iv2: return FOURCC_mp4v; } default: return VLC_FOURCC( 'u', 'n', 'd', 'f' ); }}/**************************************************************************** * ****************************************************************************/static void AVI_ParseStreamHeader( vlc_fourcc_t i_id, int *pi_number, int *pi_type ){#define SET_PTR( p, v ) if( p ) *(p) = (v); int c1, c2; c1 = ((uint8_t *)&i_id)[0]; c2 = ((uint8_t *)&i_id)[1]; if( c1 < '0' || c1 > '9' || c2 < '0' || c2 > '9' ) { SET_PTR( pi_number, 100 ); /* > max stream number */ SET_PTR( pi_type, UNKNOWN_ES ); } else { SET_PTR( pi_number, (c1 - '0') * 10 + (c2 - '0' ) ); switch( VLC_TWOCC( ((uint8_t *)&i_id)[2], ((uint8_t *)&i_id)[3] ) ) { case AVITWOCC_wb: SET_PTR( pi_type, AUDIO_ES ); break; case AVITWOCC_dc: case AVITWOCC_db: SET_PTR( pi_type, VIDEO_ES ); break; default: SET_PTR( pi_type, UNKNOWN_ES ); break; } }#undef SET_PTR}/**************************************************************************** * ****************************************************************************/static int AVI_PacketGetHeader( input_thread_t *p_input, avi_packet_t *p_pk ){ uint8_t *p_peek; if( stream_Peek( p_input->s, &p_peek, 16 ) < 16 ) { return VLC_EGENERIC; } p_pk->i_fourcc = VLC_FOURCC( p_peek[0], p_peek[1], p_peek[2], p_peek[3] ); p_pk->i_size = GetDWLE( p_peek + 4 ); p_pk->i_pos = stream_Tell( p_input->s ); if( p_pk->i_fourcc == AVIFOURCC_LIST || p_pk->i_fourcc == AVIFOURCC_RIFF ) { p_pk->i_type = VLC_FOURCC( p_peek[8], p_peek[9], p_peek[10], p_peek[11] ); } else { p_pk->i_type = 0; } memcpy( p_pk->i_peek, p_peek + 8, 8 ); AVI_ParseStreamHeader( p_pk->i_fourcc, &p_pk->i_stream, &p_pk->i_cat ); return VLC_SUCCESS;}static int AVI_PacketNext( input_thread_t *p_input ){ avi_packet_t avi_ck; int i_skip = 0; if( AVI_PacketGetHeader( p_input, &avi_ck ) ) { return VLC_EGENERIC; } if( avi_ck.i_fourcc == AVIFOURCC_LIST && ( avi_ck.i_type == AVIFOURCC_rec || avi_ck.i_type == AVIFOURCC_movi ) ) { i_skip = 12; } else if( avi_ck.i_fourcc == AVIFOURCC_RIFF && avi_ck.i_type == AVIFOURCC_AVIX ) { i_skip = 24; } else { i_skip = __EVEN( avi_ck.i_size ) + 8; } if( stream_Read( p_input->s, NULL, i_skip ) != i_skip ) { return VLC_EGENERIC; } return VLC_SUCCESS;}static int AVI_PacketRead( input_thread_t *p_input, avi_packet_t *p_pk, block_t **pp_frame ){ size_t i_size; i_size = __EVEN( p_pk->i_size + 8 ); if( ( *pp_frame = stream_Block( p_input->s, i_size ) ) == NULL ) { return VLC_EGENERIC; } (*pp_frame)->p_buffer += 8; (*pp_frame)->i_buffer -= 8; if( i_size != p_pk->i_size + 8 ) { (*pp_frame)->i_buffer--; } return VLC_SUCCESS;}static int AVI_PacketSearch( input_thread_t *p_input ){ demux_sys_t *p_sys = p_input->p_demux_data; avi_packet_t avi_pk; int i_count = 0; for( ;; ) { if( stream_Read( p_input->s, NULL, 1 ) != 1 ) { return VLC_EGENERIC; } AVI_PacketGetHeader( p_input, &avi_pk ); if( avi_pk.i_stream < p_sys->i_track && ( avi_pk.i_cat == AUDIO_ES || avi_pk.i_cat == VIDEO_ES ) ) { return VLC_SUCCESS; } switch( avi_pk.i_fourcc ) { case AVIFOURCC_JUNK: case AVIFOURCC_LIST: case AVIFOURCC_RIFF: case AVIFOURCC_idx1: return VLC_SUCCESS; } /* Prevents from eating all the CPU with broken files. * This value should be low enough so that it doesn't affect the * reading speed too much (not that we care much anyway because * this code is called only on broken files). */ if( !(++i_count % 1024) ) { if( p_input->b_die ) return VLC_EGENERIC; msleep( 10000 ); if( !(i_count % (1024 * 10)) ) msg_Warn( p_input, "trying to resync..." ); } }}/**************************************************************************** * Index stuff. ****************************************************************************/static void AVI_IndexAddEntry( demux_sys_t *p_sys, int i_stream, AVIIndexEntry_t *p_index){ avi_track_t *tk = p_sys->track[i_stream]; /* Update i_movi_lastchunk_pos */ if( p_sys->i_movi_lastchunk_pos < p_index->i_pos ) { p_sys->i_movi_lastchunk_pos = p_index->i_pos; } /* add the entry */ if( tk->i_idxnb >= tk->i_idxmax ) { tk->i_idxmax += 16384; tk->p_index = realloc( tk->p_index, tk->i_idxmax * sizeof( AVIIndexEntry_t ) ); if( tk->p_index == NULL ) { return; } } /* calculate cumulate length */ if( tk->i_idxnb > 0 ) { p_index->i_lengthtotal = tk->p_index[tk->i_idxnb - 1].i_length + tk->p_index[tk->i_idxnb - 1].i_lengthtotal; } else { p_index->i_lengthtotal = 0; } tk->p_index[tk->i_idxnb++] = *p_index;}static int AVI_IndexLoad_idx1( input_thread_t *p_input ){ demux_sys_t *p_sys = p_input->p_demux_data; avi_chunk_list_t *p_riff; avi_chunk_list_t *p_movi; avi_chunk_idx1_t *p_idx1; unsigned int i_stream; unsigned int i_index; off_t i_offset; unsigned int i; p_riff = AVI_ChunkFind( &p_sys->ck_root, AVIFOURCC_RIFF, 0); p_idx1 = AVI_ChunkFind( p_riff, AVIFOURCC_idx1, 0); p_movi = AVI_ChunkFind( p_riff, AVIFOURCC_movi, 0); if( !p_idx1 ) { msg_Warn( p_input, "cannot find idx1 chunk, no index defined" ); return VLC_EGENERIC; } /* *** calculate offset *** */ /* Well, avi is __SHIT__ so test more than one entry * (needed for some avi files) */ i_offset = 0; for( i = 0; i < __MIN( p_idx1->i_entry_count, 10 ); i++ ) { if( p_idx1->entry[i].i_pos < p_movi->i_chunk_pos ) { i_offset = p_movi->i_chunk_pos + 8; break; } } for( i_index = 0; i_index < p_idx1->i_entry_count; i_index++ ) { unsigned int i_cat; AVI_ParseStreamHeader( p_idx1->entry[i_index].i_fourcc, &i_stream, &i_cat ); if( i_stream < p_sys->i_track && i_cat == p_sys->track[i_stream]->i_cat ) { AVIIndexEntry_t index; index.i_id = p_idx1->entry[i_index].i_fourcc; index.i_flags = p_idx1->entry[i_index].i_flags&(~AVIIF_FIXKEYFRAME); index.i_pos = p_idx1->entry[i_index].i_pos + i_offset; index.i_length = p_idx1->entry[i_index].i_length; AVI_IndexAddEntry( p_sys, i_stream, &index ); } } return VLC_SUCCESS;}static void __Parse_indx( input_thread_t *p_input, int i_stream, avi_chunk_indx_t *p_indx ){ demux_sys_t *p_sys = p_input->p_demux_data; AVIIndexEntry_t index; int32_t i; msg_Dbg( p_input, "loading subindex(0x%x) %d entries", p_indx->i_indextype, p_indx->i_entriesinuse ); if( p_indx->i_indexsubtype == 0 ) { for( i = 0; i < p_indx->i_entriesinuse; i++ ) { index.i_id = p_indx->i_id; index.i_flags = p_indx->idx.std[i].i_size & 0x80000000 ? 0 : AVIIF_KEYFRAME; index.i_pos = p_indx->i_baseoffset + p_indx->idx.std[i].i_offset - 8; index.i_length = p_indx->idx.std[i].i_size&0x7fffffff; AVI_IndexAddEntry( p_sys, i_stream, &index ); } } else if( p_indx->i_indexsubtype == AVI_INDEX_2FIELD ) { for( i = 0; i < p_indx->i_entriesinuse; i++ ) { index.i_id = p_indx->i_id; index.i_flags = p_indx->idx.field[i].i_size & 0x80000000 ? 0 : AVIIF_KEYFRAME; index.i_pos = p_indx->i_baseoffset + p_indx->idx.field[i].i_offset - 8; index.i_length = p_indx->idx.field[i].i_size; AVI_IndexAddEntry( p_sys, i_stream, &index ); } } else { msg_Warn( p_input, "unknow subtype index(0x%x)", p_indx->i_indexsubtype ); }}static void AVI_IndexLoad_indx( input_thread_t *p_input ){ demux_sys_t *p_sys = p_input->p_demux_data; unsigned int i_stream; int32_t i; avi_chunk_list_t *p_riff; avi_chunk_list_t *p_hdrl; p_riff = AVI_ChunkFind( &p_sys->ck_root, AVIFOURCC_RIFF, 0); p_hdrl = AVI_ChunkFind( p_riff, AVIFOURCC_hdrl, 0 ); for( i_stream = 0; i_stream < p_sys->i_track; i_stream++ ) { avi_chunk_list_t *p_strl; avi_chunk_indx_t *p_indx;#define p_stream p_sys->track[i_stream] p_strl = AVI_ChunkFind( p_hdrl, AVIFOURCC_strl, i_stream ); p_indx = AVI_ChunkFind( p_strl, AVIFOURCC_indx, 0 ); if( !p_indx ) { msg_Warn( p_input, "cannot find indx (misdetect/broken OpenDML file?)" ); continue; } if( p_indx->i_indextype == AVI_INDEX_OF_CHUNKS ) { __Parse_indx( p_input, i_stream, p_indx ); } else if( p_indx->i_indextype == AVI_INDEX_OF_INDEXES ) { avi_chunk_indx_t ck_sub; for( i = 0; i < p_indx->i_entriesinuse; i++ ) { if( stream_Seek( p_input->s, p_indx->idx.super[i].i_offset )|| AVI_ChunkRead( p_input->s, &ck_sub, NULL ) ) { break; } __Parse_indx( p_input, i_stream, &ck_sub ); } } else { msg_Warn( p_input, "unknow type index(0x%x)", p_indx->i_indextype ); }#undef p_stream }}static void AVI_IndexLoad( input_thread_t *p_input ){ demux_sys_t *p_sys = p_input->p_demux_data; unsigned int i_stream; for( i_stream = 0; i_stream < p_sys->i_track; i_stream++ ) { p_sys->track[i_stream]->i_idxnb = 0; p_sys->track[i_stream]->i_idxmax = 0; p_sys->track[i_stream]->p_index = NULL; } if( p_sys->b_odml ) { AVI_IndexLoad_indx( p_input ); } else if( AVI_IndexLoad_idx1( p_input ) ) { /* try indx if idx1 failed as some "normal" file have indx too */ AVI_IndexLoad_indx( p_input ); } for( i_stream = 0; i_stream < p_sys->i_track; i_stream++ ) { msg_Dbg( p_input, "s
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?