📄 avi.c
字号:
i_count = p_fifo->i_depth; while( i_count > 1 ) { avi_idx1_entry_t *p_idx; block_t *p_data; p_data = block_FifoGet( p_fifo ); if( p_fifo->i_depth > 0 ) { block_t *p_next = block_FifoShow( p_fifo ); p_data->i_length = p_next->i_dts - p_data->i_dts; } p_stream->i_frames++; if( p_data->i_length < 0 ) { msg_Warn( p_mux, "argg length < 0 l" ); block_Release( p_data ); i_count--; continue; } p_stream->i_duration += p_data->i_length; p_stream->i_totalsize += p_data->i_buffer; /* add idx1 entry for this frame */ p_idx = &p_sys->idx1.entry[p_sys->idx1.i_entry_count]; memcpy( p_idx->fcc, p_stream->fcc, 4 ); p_idx->i_flags = AVIIF_KEYFRAME; p_idx->i_pos = p_sys->i_movi_size + 4; p_idx->i_length= p_data->i_buffer; p_sys->idx1.i_entry_count++; if( p_sys->idx1.i_entry_count >= p_sys->idx1.i_entry_max ) { p_sys->idx1.i_entry_max += 10000; p_sys->idx1.entry = realloc( p_sys->idx1.entry, p_sys->idx1.i_entry_max * sizeof( avi_idx1_entry_t ) ); } p_data = block_Realloc( p_data, 8, p_data->i_buffer ); if( p_data ) { SetFCC( p_data->p_buffer, p_stream->fcc ); SetDWLE( p_data->p_buffer + 4, p_data->i_buffer - 8 ); if( p_data->i_buffer & 0x01 ) { p_data = block_Realloc( p_data, 0, p_data->i_buffer + 1 ); } p_sys->i_movi_size += p_data->i_buffer; sout_AccessOutWrite( p_mux->p_access, p_data ); } i_count--; } } return( 0 );}/****************************************************************************//****************************************************************************//****************************************************************************//****************************************************************************/typedef struct buffer_out_s{ int i_buffer_size; int i_buffer; uint8_t *p_buffer;} buffer_out_t;static void bo_Init( buffer_out_t *p_bo, int i_size, uint8_t *p_buffer ){ p_bo->i_buffer_size = i_size; p_bo->i_buffer = 0; p_bo->p_buffer = p_buffer;}static void bo_AddByte( buffer_out_t *p_bo, uint8_t i ){ if( p_bo->i_buffer < p_bo->i_buffer_size ) { p_bo->p_buffer[p_bo->i_buffer] = i; } p_bo->i_buffer++;}static void bo_AddWordLE( buffer_out_t *p_bo, uint16_t i ){ bo_AddByte( p_bo, i &0xff ); bo_AddByte( p_bo, ( ( i >> 8) &0xff ) );}static void bo_AddWordBE( buffer_out_t *p_bo, uint16_t i ){ bo_AddByte( p_bo, ( ( i >> 8) &0xff ) ); bo_AddByte( p_bo, i &0xff );}static void bo_AddDWordLE( buffer_out_t *p_bo, uint32_t i ){ bo_AddWordLE( p_bo, i &0xffff ); bo_AddWordLE( p_bo, ( ( i >> 16) &0xffff ) );}static void bo_AddDWordBE( buffer_out_t *p_bo, uint32_t i ){ bo_AddWordBE( p_bo, ( ( i >> 16) &0xffff ) ); bo_AddWordBE( p_bo, i &0xffff );}#if 0static void bo_AddLWordLE( buffer_out_t *p_bo, uint64_t i ){ bo_AddDWordLE( p_bo, i &0xffffffff ); bo_AddDWordLE( p_bo, ( ( i >> 32) &0xffffffff ) );}static void bo_AddLWordBE( buffer_out_t *p_bo, uint64_t i ){ bo_AddDWordBE( p_bo, ( ( i >> 32) &0xffffffff ) ); bo_AddDWordBE( p_bo, i &0xffffffff );}#endifstatic void bo_AddFCC( buffer_out_t *p_bo, char *fcc ){ bo_AddByte( p_bo, fcc[0] ); bo_AddByte( p_bo, fcc[1] ); bo_AddByte( p_bo, fcc[2] ); bo_AddByte( p_bo, fcc[3] );}static void bo_AddMem( buffer_out_t *p_bo, int i_size, uint8_t *p_mem ){ int i; for( i = 0; i < i_size; i++ ) { bo_AddByte( p_bo, p_mem[i] ); }}/**************************************************************************** **************************************************************************** ** ** avi header generation ** **************************************************************************** ****************************************************************************/#define AVI_BOX_ENTER( fcc ) \ buffer_out_t _bo_sav_; \ bo_AddFCC( p_bo, fcc ); \ _bo_sav_ = *p_bo; \ bo_AddDWordLE( p_bo, 0 )#define AVI_BOX_ENTER_LIST( fcc ) \ AVI_BOX_ENTER( "LIST" ); \ bo_AddFCC( p_bo, fcc )#define AVI_BOX_EXIT( i_err ) \ if( p_bo->i_buffer&0x01 ) bo_AddByte( p_bo, 0 ); \ bo_AddDWordLE( &_bo_sav_, p_bo->i_buffer - _bo_sav_.i_buffer - 4 ); \ return( i_err );static int avi_HeaderAdd_avih( sout_mux_t *p_mux, buffer_out_t *p_bo ){ sout_mux_sys_t *p_sys = p_mux->p_sys; avi_stream_t *p_video = NULL; int i_stream; uint32_t i_microsecperframe; int i_maxbytespersec; int i_totalframes; AVI_BOX_ENTER( "avih" ); if( p_sys->i_stream_video >= 0 ) { p_video = &p_sys->stream[p_sys->i_stream_video]; if( p_video->i_frames <= 0 ) { // p_video = NULL; } } if( p_video ) { i_microsecperframe = (uint32_t)( (float)1000000 / (float)p_sys->stream[p_sys->i_stream_video].f_fps ); i_totalframes = p_sys->stream[p_sys->i_stream_video].i_frames; } else { msg_Warn( p_mux, "avi file without video track isn't a good idea..." ); i_microsecperframe = 0; i_totalframes = 0; } for( i_stream = 0,i_maxbytespersec = 0; i_stream < p_sys->i_streams; i_stream++ ) { if( p_sys->stream[i_stream].i_duration > 0 ) { i_maxbytespersec += p_sys->stream[p_sys->i_stream_video].i_totalsize / p_sys->stream[p_sys->i_stream_video].i_duration; } } bo_AddDWordLE( p_bo, i_microsecperframe ); bo_AddDWordLE( p_bo, i_maxbytespersec ); bo_AddDWordLE( p_bo, 0 ); /* padding */ bo_AddDWordLE( p_bo, AVIF_TRUSTCKTYPE | AVIF_HASINDEX | AVIF_ISINTERLEAVED ); /* flags */ bo_AddDWordLE( p_bo, i_totalframes ); bo_AddDWordLE( p_bo, 0 ); /* initial frame */ bo_AddDWordLE( p_bo, p_sys->i_streams ); /* streams count */ bo_AddDWordLE( p_bo, 1024 * 1024 ); /* suggested buffer size */ if( p_video ) { bo_AddDWordLE( p_bo, p_video->p_bih->biWidth ); bo_AddDWordLE( p_bo, p_video->p_bih->biHeight ); } else { bo_AddDWordLE( p_bo, 0 ); bo_AddDWordLE( p_bo, 0 ); } bo_AddDWordLE( p_bo, 0 ); /* ???? */ bo_AddDWordLE( p_bo, 0 ); /* ???? */ bo_AddDWordLE( p_bo, 0 ); /* ???? */ bo_AddDWordLE( p_bo, 0 ); /* ???? */ AVI_BOX_EXIT( 0 );}static int avi_HeaderAdd_strh( sout_mux_t *p_mux, buffer_out_t *p_bo, avi_stream_t *p_stream ){ AVI_BOX_ENTER( "strh" ); switch( p_stream->i_cat ) { case VIDEO_ES: { bo_AddFCC( p_bo, "vids" ); bo_AddDWordBE( p_bo, p_stream->p_bih->biCompression ); bo_AddDWordLE( p_bo, 0 ); /* flags */ bo_AddWordLE( p_bo, 0 ); /* priority */ bo_AddWordLE( p_bo, 0 ); /* langage */ bo_AddDWordLE( p_bo, 0 ); /* initial frame */ bo_AddDWordLE( p_bo, 1000 );/* scale */ bo_AddDWordLE( p_bo, (uint32_t)( 1000 * p_stream->f_fps )); bo_AddDWordLE( p_bo, 0 ); /* start */ bo_AddDWordLE( p_bo, p_stream->i_frames ); bo_AddDWordLE( p_bo, 1024 * 1024 ); bo_AddDWordLE( p_bo, -1 ); /* quality */ bo_AddDWordLE( p_bo, 0 ); /* samplesize */ bo_AddWordLE( p_bo, 0 ); /* ??? */ bo_AddWordLE( p_bo, 0 ); /* ??? */ bo_AddWordLE( p_bo, p_stream->p_bih->biWidth ); bo_AddWordLE( p_bo, p_stream->p_bih->biHeight ); } break; case AUDIO_ES: { int i_rate, i_scale, i_samplesize; i_samplesize = p_stream->p_wf->nBlockAlign; if( i_samplesize > 1 ) { i_scale = i_samplesize; i_rate = /*i_scale **/ p_stream->i_bitrate / 8; } else { i_samplesize = 1; i_scale = 1000; i_rate = 1000 * p_stream->i_bitrate / 8; } bo_AddFCC( p_bo, "auds" ); bo_AddDWordLE( p_bo, 0 ); /* tag */ bo_AddDWordLE( p_bo, 0 ); /* flags */ bo_AddWordLE( p_bo, 0 ); /* priority */ bo_AddWordLE( p_bo, 0 ); /* langage */ bo_AddDWordLE( p_bo, 0 ); /* initial frame */ bo_AddDWordLE( p_bo, i_scale );/* scale */ bo_AddDWordLE( p_bo, i_rate ); bo_AddDWordLE( p_bo, 0 ); /* start */ bo_AddDWordLE( p_bo, p_stream->i_frames ); bo_AddDWordLE( p_bo, 10 * 1024 ); bo_AddDWordLE( p_bo, -1 ); /* quality */ bo_AddDWordLE( p_bo, i_samplesize ); bo_AddWordLE( p_bo, 0 ); /* ??? */ bo_AddWordLE( p_bo, 0 ); /* ??? */ bo_AddWordLE( p_bo, 0 ); bo_AddWordLE( p_bo, 0 ); } break; } AVI_BOX_EXIT( 0 );}static int avi_HeaderAdd_strf( sout_mux_t *p_mux, buffer_out_t *p_bo, avi_stream_t *p_stream ){ AVI_BOX_ENTER( "strf" ); switch( p_stream->i_cat ) { case AUDIO_ES: bo_AddWordLE( p_bo, p_stream->p_wf->wFormatTag ); bo_AddWordLE( p_bo, p_stream->p_wf->nChannels ); bo_AddDWordLE( p_bo, p_stream->p_wf->nSamplesPerSec ); bo_AddDWordLE( p_bo, p_stream->p_wf->nAvgBytesPerSec ); bo_AddWordLE( p_bo, p_stream->p_wf->nBlockAlign ); bo_AddWordLE( p_bo, p_stream->p_wf->wBitsPerSample ); bo_AddWordLE( p_bo, p_stream->p_wf->cbSize ); bo_AddMem( p_bo, p_stream->p_wf->cbSize, (uint8_t*)&p_stream->p_wf[1] ); break; case VIDEO_ES: bo_AddDWordLE( p_bo, p_stream->p_bih->biSize ); bo_AddDWordLE( p_bo, p_stream->p_bih->biWidth ); bo_AddDWordLE( p_bo, p_stream->p_bih->biHeight ); bo_AddWordLE( p_bo, p_stream->p_bih->biPlanes ); bo_AddWordLE( p_bo, p_stream->p_bih->biBitCount ); if( VLC_FOURCC( 0, 0, 0, 1 ) == 0x00000001 ) { bo_AddDWordBE( p_bo, p_stream->p_bih->biCompression ); } else { bo_AddDWordLE( p_bo, p_stream->p_bih->biCompression ); } bo_AddDWordLE( p_bo, p_stream->p_bih->biSizeImage ); bo_AddDWordLE( p_bo, p_stream->p_bih->biXPelsPerMeter ); bo_AddDWordLE( p_bo, p_stream->p_bih->biYPelsPerMeter ); bo_AddDWordLE( p_bo, p_stream->p_bih->biClrUsed ); bo_AddDWordLE( p_bo, p_stream->p_bih->biClrImportant ); bo_AddMem( p_bo, p_stream->p_bih->biSize - sizeof( BITMAPINFOHEADER ), (uint8_t*)&p_stream->p_bih[1] ); break; } AVI_BOX_EXIT( 0 );}static int avi_HeaderAdd_strl( sout_mux_t *p_mux, buffer_out_t *p_bo, avi_stream_t *p_stream ){ AVI_BOX_ENTER_LIST( "strl" ); avi_HeaderAdd_strh( p_mux, p_bo, p_stream ); avi_HeaderAdd_strf( p_mux, p_bo, p_stream ); AVI_BOX_EXIT( 0 );}static block_t *avi_HeaderCreateRIFF( sout_mux_t *p_mux ){ sout_mux_sys_t *p_sys = p_mux->p_sys; block_t *p_hdr; int i_stream; int i_maxbytespersec; int i_junk; buffer_out_t bo; p_hdr = block_New( p_mux, HDR_SIZE ); memset( p_hdr->p_buffer, 0, HDR_SIZE ); bo_Init( &bo, HDR_SIZE, p_hdr->p_buffer ); bo_AddFCC( &bo, "RIFF" ); bo_AddDWordLE( &bo, p_sys->i_movi_size + HDR_SIZE - 8 + p_sys->i_idx1_size ); bo_AddFCC( &bo, "AVI " ); bo_AddFCC( &bo, "LIST" ); bo_AddDWordLE( &bo, HDR_SIZE - 8); bo_AddFCC( &bo, "hdrl" ); avi_HeaderAdd_avih( p_mux, &bo ); for( i_stream = 0,i_maxbytespersec = 0; i_stream < p_sys->i_streams; i_stream++ ) { avi_HeaderAdd_strl( p_mux, &bo, &p_sys->stream[i_stream] ); } i_junk = HDR_SIZE - bo.i_buffer - 8 - 12; bo_AddFCC( &bo, "JUNK" ); bo_AddDWordLE( &bo, i_junk ); bo.i_buffer += i_junk; bo_AddFCC( &bo, "LIST" ); bo_AddDWordLE( &bo, p_sys->i_movi_size + 4 ); bo_AddFCC( &bo, "movi" ); return( p_hdr );}static block_t * avi_HeaderCreateidx1( sout_mux_t *p_mux ){ sout_mux_sys_t *p_sys = p_mux->p_sys; block_t *p_idx1; uint32_t i_idx1_size; unsigned int i; buffer_out_t bo; i_idx1_size = 16 * p_sys->idx1.i_entry_count; p_idx1 = block_New( p_mux, i_idx1_size + 8 ); memset( p_idx1->p_buffer, 0, i_idx1_size ); bo_Init( &bo, i_idx1_size, p_idx1->p_buffer ); bo_AddFCC( &bo, "idx1" ); bo_AddDWordLE( &bo, i_idx1_size ); for( i = 0; i < p_sys->idx1.i_entry_count; i++ ) { bo_AddFCC( &bo, p_sys->idx1.entry[i].fcc ); bo_AddDWordLE( &bo, p_sys->idx1.entry[i].i_flags ); bo_AddDWordLE( &bo, p_sys->idx1.entry[i].i_pos ); bo_AddDWordLE( &bo, p_sys->idx1.entry[i].i_length ); } return( p_idx1 );}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -