@ -31,7 +31,8 @@ typedef struct AVIIndex {
} AVIIndex ;
typedef struct {
offset_t movi_list ;
offset_t movi_list , frames_hdr_all , frames_hdr_strm [ MAX_STREAMS ] ;
int audio_strm_length [ MAX_STREAMS ] ;
AVIIndex * first , * last ;
} AVIContext ;
@ -109,11 +110,36 @@ void put_bmp_header(ByteIOContext *pb, AVCodecContext *enc)
put_le32 ( pb , 0 ) ;
}
void parse_specific_params ( AVCodecContext * stream , int * au_byterate , int * au_ssize , int * au_scale )
{
switch ( stream - > codec_id ) {
case CODEC_ID_PCM_S16LE :
* au_scale = * au_ssize = 2 * stream - > channels ;
* au_byterate = * au_ssize * stream - > sample_rate ;
break ;
case CODEC_ID_PCM_U8 :
case CODEC_ID_PCM_ALAW :
case CODEC_ID_PCM_MULAW :
* au_scale = * au_ssize = stream - > channels ;
* au_byterate = * au_ssize * stream - > sample_rate ;
break ;
case CODEC_ID_MP2 :
* au_ssize = 1 ;
* au_scale = 1 ;
* au_byterate = stream - > bit_rate / 8 ;
default :
* au_ssize = 1 ;
* au_scale = 1 ;
* au_byterate = stream - > bit_rate / 8 ;
break ;
}
}
static int avi_write_header ( AVFormatContext * s )
{
AVIContext * avi ;
ByteIOContext * pb = & s - > pb ;
int bitrate , n , i , nb_frames ;
int bitrate , n , i , nb_frames , au_byterate , au_ssize , au_scale ;
AVCodecContext * stream , * video_enc ;
offset_t list1 , list2 , strh , strf ;
@ -154,6 +180,7 @@ static int avi_write_header(AVFormatContext *s)
put_le32 ( pb , bitrate / 8 ) ; /* XXX: not quite exact */
put_le32 ( pb , 0 ) ; /* padding */
put_le32 ( pb , AVIF_TRUSTCKTYPE | AVIF_HASINDEX | AVIF_ISINTERLEAVED ) ; /* flags */
avi - > frames_hdr_all = url_ftell ( pb ) ; /* remember this offset to fill later */
put_le32 ( pb , nb_frames ) ; /* nb frames, filled later */
put_le32 ( pb , 0 ) ; /* initial frame */
put_le32 ( pb , s - > nb_streams ) ; /* nb streams */
@ -185,9 +212,10 @@ static int avi_write_header(AVFormatContext *s)
put_le32 ( pb , 1000 ) ; /* scale */
put_le32 ( pb , ( 1000 * stream - > frame_rate ) / FRAME_RATE_BASE ) ; /* rate */
put_le32 ( pb , 0 ) ; /* start */
avi - > frames_hdr_strm [ i ] = url_ftell ( pb ) ; /* remember this offset to fill later */
put_le32 ( pb , nb_frames ) ; /* length, XXX: fill later */
put_le32 ( pb , 1024 * 1024 ) ; /* suggested buffer size */
put_le32 ( pb , 10000 ) ; /* quality */
put_le32 ( pb , - 1 ) ; /* quality */
put_le32 ( pb , stream - > width * stream - > height * 3 ) ; /* sample size */
put_le16 ( pb , 0 ) ;
put_le16 ( pb , 0 ) ;
@ -196,18 +224,20 @@ static int avi_write_header(AVFormatContext *s)
break ;
case CODEC_TYPE_AUDIO :
put_tag ( pb , " auds " ) ;
put_le32 ( pb , 0 ) ;
put_le32 ( pb , 1 ) ; /* tag */
put_le32 ( pb , 0 ) ; /* flags */
put_le16 ( pb , 0 ) ; /* priority */
put_le16 ( pb , 0 ) ; /* language */
put_le32 ( pb , 0 ) ; /* initial frame */
put_le32 ( pb , 1 ) ; /* scale */
put_le32 ( pb , stream - > bit_rate / 8 ) ; /* rate */
parse_specific_params ( stream , & au_byterate , & au_ssize , & au_scale ) ;
put_le32 ( pb , au_scale ) ; /* scale */
put_le32 ( pb , au_byterate ) ; /* rate */
put_le32 ( pb , 0 ) ; /* start */
avi - > frames_hdr_strm [ i ] = url_ftell ( pb ) ; /* remember this offset to fill later */
put_le32 ( pb , 0 ) ; /* length, XXX: filled later */
put_le32 ( pb , 12 * 1024 ) ; /* suggested buffer size */
put_le32 ( pb , - 1 ) ; /* quality */
put_le32 ( pb , 1 ) ; /* sample size */
put_le32 ( pb , au_ssize ) ; /* sample size */
put_le32 ( pb , 0 ) ;
put_le32 ( pb , 0 ) ;
break ;
@ -265,6 +295,8 @@ static int avi_write_packet(AVFormatContext *s, int stream_index,
tag [ 3 ] = ' b ' ;
flags = 0x10 ;
}
if ( enc - > codec_type = = CODEC_TYPE_AUDIO )
avi - > audio_strm_length [ stream_index ] + = size ;
if ( ! url_is_streamed ( & s - > pb ) ) {
idx = malloc ( sizeof ( AVIIndex ) ) ;
@ -295,6 +327,8 @@ static int avi_write_trailer(AVFormatContext *s)
ByteIOContext * pb = & s - > pb ;
AVIContext * avi = s - > priv_data ;
offset_t file_size , idx_chunk ;
int n , nb_frames , au_byterate , au_ssize , au_scale ;
AVCodecContext * stream ;
AVIIndex * idx ;
if ( ! url_is_streamed ( & s - > pb ) ) {
@ -315,6 +349,32 @@ static int avi_write_trailer(AVFormatContext *s)
file_size = url_ftell ( pb ) ;
url_fseek ( pb , 4 , SEEK_SET ) ;
put_le32 ( pb , ( UINT32 ) ( file_size - 8 ) ) ;
/* Fill in frame/sample counters */
nb_frames = 0 ;
for ( n = 0 ; n < s - > nb_streams ; n + + ) {
if ( avi - > frames_hdr_strm [ n ] ! = 0 ) {
stream = & s - > streams [ n ] - > codec ;
url_fseek ( pb , avi - > frames_hdr_strm [ n ] , SEEK_SET ) ;
if ( stream - > codec_type = = CODEC_TYPE_VIDEO ) {
put_le32 ( pb , stream - > frame_number ) ;
if ( nb_frames < stream - > frame_number )
nb_frames = stream - > frame_number ;
} else {
if ( stream - > codec_id = = CODEC_ID_MP2 ) {
put_le32 ( pb , stream - > frame_number ) ;
nb_frames + = stream - > frame_number ;
} else {
parse_specific_params ( stream , & au_byterate , & au_ssize , & au_scale ) ;
put_le32 ( pb , avi - > audio_strm_length [ n ] / au_ssize ) ;
}
}
}
}
if ( avi - > frames_hdr_all ! = 0 ) {
url_fseek ( pb , avi - > frames_hdr_all , SEEK_SET ) ;
put_le32 ( pb , nb_frames ) ;
}
url_fseek ( pb , file_size , SEEK_SET ) ;
}
put_flush_packet ( pb ) ;