📄 avi.c
字号:
i, tk->i_samplesize, tk->i_blocksize ); tk->i_samplesize = tk->i_blocksize; } if( tk->i_codec == VLC_FOURCC( 'v', 'o', 'r', 'b' ) ) { tk->i_blocksize = 0; /* fix vorbis VBR decoding */ } es_format_Init( &fmt, AUDIO_ES, tk->i_codec ); fmt.audio.i_channels = p_auds->p_wf->nChannels; fmt.audio.i_rate = p_auds->p_wf->nSamplesPerSec; fmt.i_bitrate = p_auds->p_wf->nAvgBytesPerSec*8; fmt.audio.i_blockalign = p_auds->p_wf->nBlockAlign; fmt.audio.i_bitspersample = p_auds->p_wf->wBitsPerSample; fmt.b_packetized = !tk->i_blocksize; msg_Dbg( p_demux, "stream[%d] audio(0x%x) %d channels %dHz %dbits", i, p_auds->p_wf->wFormatTag, p_auds->p_wf->nChannels, p_auds->p_wf->nSamplesPerSec, p_auds->p_wf->wBitsPerSample ); fmt.i_extra = __MIN( p_auds->p_wf->cbSize, p_auds->i_chunk_size - sizeof(WAVEFORMATEX) ); fmt.p_extra = tk->p_extra = malloc( fmt.i_extra ); if( !fmt.p_extra ) goto error; memcpy( fmt.p_extra, &p_auds->p_wf[1], fmt.i_extra ); /* Rewrite the vorbis headers from Xiph-like format * to VLC internal format * * Xiph format: * - 1st byte == N, is the number of packets - 1 * - Following bytes are the size of the N first packets: * while( *p == 0xFF ) { size += 0xFF; p++ } size += *p; * (the size of the last packet is the size of remaining * data in the buffer) * - Finally, all the packets concatenated * * VLC format: * - Size of the packet on 16 bits (big endian) FIXME: should be 32 bits to be safe * - The packet itself * - Size of the next packet, and so on ... */ if( tk->i_codec == VLC_FOURCC( 'v', 'o', 'r', 'b' ) ) { uint8_t *p_extra = fmt.p_extra; size_t i_extra = fmt.i_extra; if( i_extra <= 1 ) break; if( *p_extra++ != 2 ) break; /* 3 packets - 1 = 2 */ i_extra--; size_t i_identifier_len = 0; while( *p_extra == 0xFF ) { i_identifier_len += 0xFF; p_extra++; if( --i_extra <= 1 ) break; } i_identifier_len += *p_extra++; if( i_identifier_len > --i_extra ) break; size_t i_comment_len = 0; while( *p_extra == 0xFF ) { i_comment_len += 0xFF; p_extra++; if( --i_extra <= 1 ) break; } i_comment_len += *p_extra++; if( i_comment_len > --i_extra ) break; size_t i_cookbook_len = i_extra; size_t i_headers_size = 3 * 2 + i_identifier_len + i_comment_len + i_cookbook_len; uint8_t *p_out = malloc( i_headers_size ); if( !p_out ) goto error; free( fmt.p_extra ); fmt.p_extra = tk->p_extra = p_out; fmt.i_extra = i_headers_size; #define copy_packet( len ) \ *p_out++ = len >> 8; \ *p_out++ = len & 0xFF; \ memcpy( p_out, p_extra, len ); \ p_out += len; \ p_extra += len; copy_packet( i_identifier_len ); copy_packet( i_comment_len ); copy_packet( i_cookbook_len ); #undef copy_packet break; } break; case( AVIFOURCC_vids ): tk->i_cat = VIDEO_ES; tk->i_codec = AVI_FourccGetCodec( VIDEO_ES, p_vids->p_bih->biCompression ); if( p_vids->p_bih->biCompression == 0x00 ) { switch( p_vids->p_bih->biBitCount ) { case 32: tk->i_codec = VLC_FOURCC('R','V','3','2'); break; case 24: tk->i_codec = VLC_FOURCC('R','V','2','4'); break; case 16: /* tk->i_codec = VLC_FOURCC('R','V','1','6');*/ /* break;*/ case 15: tk->i_codec = VLC_FOURCC('R','V','1','5'); break; case 9: tk->i_codec = VLC_FOURCC( 'Y', 'V', 'U', '9' ); /* <- TODO check that */ break; case 8: tk->i_codec = VLC_FOURCC('Y','8','0','0'); break; } es_format_Init( &fmt, VIDEO_ES, tk->i_codec ); if( p_vids->p_bih->biBitCount == 24 ) { /* This is in BGR format */ fmt.video.i_bmask = 0x00ff0000; fmt.video.i_gmask = 0x0000ff00; fmt.video.i_rmask = 0x000000ff; } } else { es_format_Init( &fmt, VIDEO_ES, p_vids->p_bih->biCompression ); if( tk->i_codec == FOURCC_mp4v && !strncasecmp( (char*)&p_strh->i_handler, "XVID", 4 ) ) { fmt.i_codec = VLC_FOURCC( 'X', 'V', 'I', 'D' ); } } tk->i_samplesize = 0; fmt.video.i_width = p_vids->p_bih->biWidth; fmt.video.i_height = p_vids->p_bih->biHeight; fmt.video.i_bits_per_pixel = p_vids->p_bih->biBitCount; fmt.video.i_frame_rate = tk->i_rate; fmt.video.i_frame_rate_base = tk->i_scale; fmt.i_extra = __MIN( p_vids->p_bih->biSize - sizeof( BITMAPINFOHEADER ), p_vids->i_chunk_size - sizeof(BITMAPINFOHEADER) ); fmt.p_extra = &p_vids->p_bih[1]; msg_Dbg( p_demux, "stream[%d] video(%4.4s) %"PRIu32"x%"PRIu32" %dbpp %ffps", i, (char*)&p_vids->p_bih->biCompression, (uint32_t)p_vids->p_bih->biWidth, (uint32_t)p_vids->p_bih->biHeight, p_vids->p_bih->biBitCount, (float)tk->i_rate/(float)tk->i_scale ); if( p_vids->p_bih->biCompression == 0x00 ) { /* RGB DIB are coded from bottom to top */ fmt.video.i_height = (unsigned int)(-(int)p_vids->p_bih->biHeight); } /* Extract palette from extradata if bpp <= 8 * (assumes that extradata contains only palette but appears * to be true for all palettized codecs we support) */ if( fmt.i_extra && fmt.video.i_bits_per_pixel <= 8 && fmt.video.i_bits_per_pixel > 0 ) { int i; fmt.video.p_palette = calloc( sizeof(video_palette_t), 1 ); fmt.video.p_palette->i_entries = 1; /* Apparently this is necessary. But why ? */ fmt.i_extra = p_vids->i_chunk_size - sizeof(BITMAPINFOHEADER); for( i = 0; i < __MIN(fmt.i_extra/4, 256); i++ ) { ((uint32_t *)&fmt.video.p_palette->palette[0][0])[i] = GetDWLE((uint32_t*)fmt.p_extra + i); } } break; case( AVIFOURCC_txts): tk->i_cat = SPU_ES; tk->i_codec = VLC_FOURCC( 's', 'u', 'b', 't' ); msg_Dbg( p_demux, "stream[%d] subtitles", i ); es_format_Init( &fmt, SPU_ES, tk->i_codec ); break; case( AVIFOURCC_iavs): case( AVIFOURCC_ivas): p_sys->b_muxed = true; msg_Dbg( p_demux, "stream[%d] iavs with handler %4.4s", i, (char *)&p_strh->i_handler ); if( p_strh->i_handler == FOURCC_dvsd || p_strh->i_handler == FOURCC_dvhd || p_strh->i_handler == FOURCC_dvsl || p_strh->i_handler == FOURCC_dv25 || p_strh->i_handler == FOURCC_dv50 ) { tk->p_out_muxed = stream_DemuxNew( p_demux, (char *)"rawdv", p_demux->out ); if( !tk->p_out_muxed ) msg_Err( p_demux, "could not load the DV parser" ); else break; } free( tk ); continue; case( AVIFOURCC_mids): msg_Dbg( p_demux, "stream[%d] midi is UNSUPPORTED", i ); default: msg_Warn( p_demux, "stream[%d] unknown type %4.4s", i, (char *)&p_strh->i_type ); free( tk ); continue; } if( p_strn ) { /* The charset of p_strn is undefined */ EnsureUTF8( p_strn->p_str ); fmt.psz_description = strdup( p_strn->p_str ); } if( tk->p_out_muxed == NULL ) tk->p_es = es_out_Add( p_demux->out, &fmt ); TAB_APPEND( p_sys->i_track, p_sys->track, tk ); } if( p_sys->i_track <= 0 ) { msg_Err( p_demux, "no valid track" ); goto error; } i_do_index = config_GetInt( p_demux, "avi-index" ); if( i_do_index == 1 ) /* Always fix */ {aviindex: if( p_sys->b_seekable ) { AVI_IndexCreate( p_demux ); } else { msg_Warn( p_demux, "cannot create index (unseekable stream)" ); AVI_IndexLoad( p_demux ); } } else { AVI_IndexLoad( p_demux ); } /* *** movie length in sec *** */ p_sys->i_length = AVI_MovieGetLength( p_demux ); if( p_sys->i_length < (mtime_t)p_avih->i_totalframes * (mtime_t)p_avih->i_microsecperframe / (mtime_t)1000000 ) { msg_Warn( p_demux, "broken or missing index, 'seek' will be " "approximative or will exhibit strange behavior" ); if( i_do_index == 0 && !b_index ) { if( !p_sys->b_seekable ) { b_index = true; goto aviindex; } int i_create; i_create = intf_UserYesNo( p_demux, _("AVI Index") , _( "This AVI file is broken. Seeking will not " "work correctly.\nDo you want to " "try to repair it?\n\nThis might take a long time." ), _( "Repair" ), _( "Don't repair" ), _( "Cancel") ); if( i_create == DIALOG_OK_YES ) { b_index = true; msg_Dbg( p_demux, "Fixing AVI index" ); goto aviindex; } else if( i_create == DIALOG_CANCELLED ) { /* Kill input */ vlc_object_kill( p_demux->p_parent ); goto error; } } } /* fix some BeOS MediaKit generated file */ for( i = 0 ; i < p_sys->i_track; i++ ) { avi_track_t *tk = p_sys->track[i]; avi_chunk_list_t *p_strl; avi_chunk_strh_t *p_strh; avi_chunk_strf_auds_t *p_auds; if( tk->i_cat != AUDIO_ES ) { continue; } if( tk->i_idxnb < 1 || tk->i_scale != 1 || tk->i_samplesize != 0 ) { continue; } p_strl = AVI_ChunkFind( p_hdrl, AVIFOURCC_strl, i ); p_strh = AVI_ChunkFind( p_strl, AVIFOURCC_strh, 0 ); p_auds = AVI_ChunkFind( p_strl, AVIFOURCC_strf, 0 ); if( p_auds->p_wf->wFormatTag != WAVE_FORMAT_PCM && (unsigned int)tk->i_rate == p_auds->p_wf->nSamplesPerSec ) { int64_t i_track_length = tk->p_index[tk->i_idxnb-1].i_length + tk->p_index[tk->i_idxnb-1].i_lengthtotal; mtime_t i_length = (mtime_t)p_avih->i_totalframes * (mtime_t)p_avih->i_microsecperframe; if( i_length == 0 ) { msg_Warn( p_demux, "track[%d] cannot be fixed (BeOS MediaKit generated)", i ); continue; } tk->i_samplesize = 1; tk->i_rate = i_track_length * (int64_t)1000000/ i_length; msg_Warn( p_demux, "track[%d] fixed with rate=%d scale=%d (BeOS MediaKit generated)", i, tk->i_rate, tk->i_scale ); } } if( p_sys->b_seekable ) { /* we have read all chunk so go back to movi */ stream_Seek( p_demux->s, p_movi->i_chunk_pos ); } /* Skip movi header */ stream_Read( p_demux->s, NULL, 12 ); p_sys->i_movi_begin = p_movi->i_chunk_pos; return VLC_SUCCESS;error: if( p_sys->meta ) { vlc_meta_Delete( p_sys->meta ); } AVI_ChunkFreeRoot( p_demux->s, &p_sys->ck_root ); free( p_sys ); return VLC_EGENERIC;}/***************************************************************************** * Close: frees unused data *****************************************************************************/static void Close ( vlc_object_t * p_this ){ demux_t * p_demux = (demux_t *)p_this; unsigned int i; demux_sys_t *p_sys = p_demux->p_sys ; for( i = 0; i < p_sys->i_track; i++ ) { if( p_sys->track[i] ) { if( p_sys->track[i]->p_out_muxed ) stream_DemuxDelete( p_sys->track[i]->p_out_muxed ); free( p_sys->track[i]->p_index ); free( p_sys->track[i]->p_extra ); free( p_sys->track[i] ); } } free( p_sys->track ); AVI_ChunkFreeRoot( p_demux->s, &p_sys->ck_root ); vlc_meta_Delete( p_sys->meta ); free( p_sys );}/***************************************************************************** * Demux_Seekable: reads and demuxes data packets for stream seekable ***************************************************************************** * AVIDemux: reads and demuxes data packets ***************************************************************************** * Returns -1 in case of error, 0 in case of EOF, 1 otherwise *****************************************************************************/typedef struct{ bool b_ok; int i_toread; off_t i_posf; /* where we will read : if i_idxposb == 0 : begining of chunk (+8 to acces data)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -