@ -19,6 +19,7 @@
# include "avformat.h"
# include "avformat.h"
# include "avi.h"
# include "avi.h"
# include "tick.h"
# include "tick.h"
# include "mpegaudio.h"
# define PACKET_SIZE 3200
# define PACKET_SIZE 3200
# define PACKET_HEADER_SIZE 12
# define PACKET_HEADER_SIZE 12
@ -78,7 +79,9 @@ static const GUID audio_stream = {
} ;
} ;
static const GUID audio_conceal_none = {
static const GUID audio_conceal_none = {
0x49f1a440 , 0x4ece , 0x11d0 , { 0xa3 , 0xac , 0x00 , 0xa0 , 0xc9 , 0x03 , 0x48 , 0xf6 } ,
// 0x49f1a440, 0x4ece, 0x11d0, { 0xa3, 0xac, 0x00, 0xa0, 0xc9, 0x03, 0x48, 0xf6 },
// New value lifted from avifile
0x20fb5700 , 0x5b55 , 0x11cf , { 0xa8 , 0xfd , 0x00 , 0x80 , 0x5f , 0x5c , 0x44 , 0x2b } ,
} ;
} ;
static const GUID video_stream = {
static const GUID video_stream = {
@ -198,7 +201,7 @@ static void end_header(ByteIOContext *pb, INT64 pos)
}
}
/* write an asf chunk (only used in streaming case) */
/* write an asf chunk (only used in streaming case) */
static void put_chunk ( AVFormatContext * s , int type , int payload_length )
static void put_chunk ( AVFormatContext * s , int type , int payload_length , int flags )
{
{
ASFContext * asf = s - > priv_data ;
ASFContext * asf = s - > priv_data ;
ByteIOContext * pb = & s - > pb ;
ByteIOContext * pb = & s - > pb ;
@ -208,7 +211,7 @@ static void put_chunk(AVFormatContext *s, int type, int payload_length)
put_le16 ( pb , type ) ;
put_le16 ( pb , type ) ;
put_le16 ( pb , length ) ;
put_le16 ( pb , length ) ;
put_le32 ( pb , asf - > seqno ) ;
put_le32 ( pb , asf - > seqno ) ;
put_le16 ( pb , 0 ) ; /* unknown bytes */
put_le16 ( pb , flags ) ; /* unknown bytes */
put_le16 ( pb , length ) ;
put_le16 ( pb , length ) ;
asf - > seqno + + ;
asf - > seqno + + ;
}
}
@ -232,18 +235,26 @@ static int asf_write_header1(AVFormatContext *s, INT64 file_size, INT64 data_chu
int has_title ;
int has_title ;
AVCodecContext * enc ;
AVCodecContext * enc ;
INT64 header_offset , cur_pos , hpos ;
INT64 header_offset , cur_pos , hpos ;
int bit_rate ;
has_title = ( s - > title [ 0 ] ! = ' \0 ' ) ;
has_title = ( s - > title [ 0 ] ! = ' \0 ' ) ;
if ( ! url_is_streamed ( & s - > pb ) ) {
bit_rate = 0 ;
for ( n = 0 ; n < s - > nb_streams ; n + + ) {
enc = & s - > streams [ n ] - > codec ;
bit_rate + = enc - > bit_rate ;
}
if ( url_is_streamed ( & s - > pb ) ) {
put_chunk ( s , 0x4824 , 0 , 0xc00 ) ; /* start of stream (length will be patched later) */
}
put_guid ( pb , & asf_header ) ;
put_guid ( pb , & asf_header ) ;
put_le64 ( pb , 0 ) ; /* header length, will be patched after */
put_le64 ( pb , 0 ) ; /* header length, will be patched after */
put_le32 ( pb , 3 + has_title + s - > nb_streams ) ; /* number of chunks in header */
put_le32 ( pb , 3 + has_title + s - > nb_streams ) ; /* number of chunks in header */
put_byte ( pb , 1 ) ; /* ??? */
put_byte ( pb , 1 ) ; /* ??? */
put_byte ( pb , 2 ) ; /* ??? */
put_byte ( pb , 2 ) ; /* ??? */
} else {
put_chunk ( s , 0x4824 , 0 ) ; /* start of stream (length will be patched later) */
}
/* file header */
/* file header */
header_offset = url_ftell ( pb ) ;
header_offset = url_ftell ( pb ) ;
@ -260,7 +271,7 @@ static int asf_write_header1(AVFormatContext *s, INT64 file_size, INT64 data_chu
put_le32 ( pb , url_is_streamed ( & s - > pb ) ? 1 : 0 ) ; /* ??? */
put_le32 ( pb , url_is_streamed ( & s - > pb ) ? 1 : 0 ) ; /* ??? */
put_le32 ( pb , asf - > packet_size ) ; /* packet size */
put_le32 ( pb , asf - > packet_size ) ; /* packet size */
put_le32 ( pb , asf - > packet_size ) ; /* packet size */
put_le32 ( pb , asf - > packet_size ) ; /* packet size */
put_le32 ( pb , 80 * asf - > packet_size ) ; /* frame_size ??? */
put_le32 ( pb , bit_rate ) ; /* Nominal data rate in bps */
end_header ( pb , hpos ) ;
end_header ( pb , hpos ) ;
/* unknown headers */
/* unknown headers */
@ -287,7 +298,9 @@ static int asf_write_header1(AVFormatContext *s, INT64 file_size, INT64 data_chu
/* stream headers */
/* stream headers */
for ( n = 0 ; n < s - > nb_streams ; n + + ) {
for ( n = 0 ; n < s - > nb_streams ; n + + ) {
INT64 es_pos ;
ASFStream * stream = & asf - > streams [ n ] ;
ASFStream * stream = & asf - > streams [ n ] ;
enc = & s - > streams [ n ] - > codec ;
enc = & s - > streams [ n ] - > codec ;
asf - > streams [ n ] . num = n + 1 ;
asf - > streams [ n ] . num = n + 1 ;
asf - > streams [ n ] . seq = 0 ;
asf - > streams [ n ] . seq = 0 ;
@ -323,6 +336,7 @@ static int asf_write_header1(AVFormatContext *s, INT64 file_size, INT64 data_chu
put_guid ( pb , & video_conceal_none ) ;
put_guid ( pb , & video_conceal_none ) ;
}
}
put_le64 ( pb , 0 ) ; /* ??? */
put_le64 ( pb , 0 ) ; /* ??? */
es_pos = url_ftell ( pb ) ;
put_le32 ( pb , extra_size ) ; /* wav header len */
put_le32 ( pb , extra_size ) ; /* wav header len */
put_le32 ( pb , extra_size2 ) ; /* additional data len */
put_le32 ( pb , extra_size2 ) ; /* additional data len */
put_le16 ( pb , n + 1 ) ; /* stream number */
put_le16 ( pb , n + 1 ) ; /* stream number */
@ -330,8 +344,16 @@ static int asf_write_header1(AVFormatContext *s, INT64 file_size, INT64 data_chu
if ( enc - > codec_type = = CODEC_TYPE_AUDIO ) {
if ( enc - > codec_type = = CODEC_TYPE_AUDIO ) {
/* WAVEFORMATEX header */
/* WAVEFORMATEX header */
if ( put_wav_header ( pb , enc ) < 0 )
int wavsize = put_wav_header ( pb , enc ) ;
if ( wavsize < 0 )
return - 1 ;
return - 1 ;
if ( wavsize ! = extra_size ) {
cur_pos = url_ftell ( pb ) ;
url_fseek ( pb , es_pos , SEEK_SET ) ;
put_le32 ( pb , wavsize ) ; /* wav header len */
url_fseek ( pb , cur_pos , SEEK_SET ) ;
}
} else {
} else {
put_le32 ( pb , enc - > width ) ;
put_le32 ( pb , enc - > width ) ;
put_le32 ( pb , enc - > height ) ;
put_le32 ( pb , enc - > height ) ;
@ -370,17 +392,19 @@ static int asf_write_header1(AVFormatContext *s, INT64 file_size, INT64 data_chu
cur_pos = url_ftell ( pb ) ;
cur_pos = url_ftell ( pb ) ;
header_size = cur_pos - header_offset ;
header_size = cur_pos - header_offset ;
if ( ! url_is_streamed ( & s - > pb ) ) {
if ( url_is_streamed ( & s - > pb ) ) {
header_size + = 24 + 6 ;
header_size + = 8 + 30 + 50 ;
url_fseek ( pb , header_offset - 14 , SEEK_SET ) ;
put_le64 ( pb , header_size ) ;
url_fseek ( pb , header_offset - 10 - 30 , SEEK_SET ) ;
} else {
header_size + = 8 + 50 ;
url_fseek ( pb , header_offset - 10 , SEEK_SET ) ;
put_le16 ( pb , header_size ) ;
put_le16 ( pb , header_size ) ;
url_fseek ( pb , header_offset - 2 , SEEK_SET ) ;
url_fseek ( pb , header_offset - 2 - 30 , SEEK_SET ) ;
put_le16 ( pb , header_size ) ;
put_le16 ( pb , header_size ) ;
header_size - = 8 + 30 + 50 ;
}
}
header_size + = 24 + 6 ;
url_fseek ( pb , header_offset - 14 , SEEK_SET ) ;
put_le64 ( pb , header_size ) ;
url_fseek ( pb , cur_pos , SEEK_SET ) ;
url_fseek ( pb , cur_pos , SEEK_SET ) ;
/* movie chunk, followed by packets of packet_size */
/* movie chunk, followed by packets of packet_size */
@ -406,7 +430,7 @@ static int asf_write_header(AVFormatContext *s)
asf - > packet_size = PACKET_SIZE ;
asf - > packet_size = PACKET_SIZE ;
asf - > nb_packets = 0 ;
asf - > nb_packets = 0 ;
if ( asf_write_header1 ( s , 0 , 24 ) < 0 ) {
if ( asf_write_header1 ( s , 0 , 50 ) < 0 ) {
free ( asf ) ;
free ( asf ) ;
return - 1 ;
return - 1 ;
}
}
@ -424,7 +448,7 @@ static int asf_write_header(AVFormatContext *s)
}
}
/* write a fixed size packet */
/* write a fixed size packet */
static void put_packet ( AVFormatContext * s ,
static int put_packet ( AVFormatContext * s ,
unsigned int timestamp , unsigned int duration ,
unsigned int timestamp , unsigned int duration ,
int nb_frames , int padsize )
int nb_frames , int padsize )
{
{
@ -433,7 +457,7 @@ static void put_packet(AVFormatContext *s,
int flags ;
int flags ;
if ( url_is_streamed ( & s - > pb ) ) {
if ( url_is_streamed ( & s - > pb ) ) {
put_chunk ( s , 0x4424 , asf - > packet_size ) ;
put_chunk ( s , 0x4424 , asf - > packet_size , 0 ) ;
}
}
put_byte ( pb , 0x82 ) ;
put_byte ( pb , 0x82 ) ;
@ -449,12 +473,14 @@ static void put_packet(AVFormatContext *s,
put_byte ( pb , flags ) ; /* flags */
put_byte ( pb , flags ) ; /* flags */
put_byte ( pb , 0x5d ) ;
put_byte ( pb , 0x5d ) ;
if ( flags & 0x10 )
if ( flags & 0x10 )
put_le16 ( pb , padsize ) ;
put_le16 ( pb , padsize - 2 ) ;
if ( flags & 0x08 )
if ( flags & 0x08 )
put_byte ( pb , padsize ) ;
put_byte ( pb , padsize - 1 ) ;
put_le32 ( pb , timestamp ) ;
put_le32 ( pb , timestamp ) ;
put_le16 ( pb , duration ) ;
put_le16 ( pb , duration ) ;
put_byte ( pb , nb_frames | 0x80 ) ;
put_byte ( pb , nb_frames | 0x80 ) ;
return PACKET_HEADER_SIZE + ( ( flags & 0x18 ) > > 3 ) ;
}
}
static void flush_packet ( AVFormatContext * s )
static void flush_packet ( AVFormatContext * s )
@ -462,24 +488,12 @@ static void flush_packet(AVFormatContext *s)
ASFContext * asf = s - > priv_data ;
ASFContext * asf = s - > priv_data ;
int hdr_size , ptr ;
int hdr_size , ptr ;
put_packet ( s , asf - > packet_timestamp_start ,
hdr_size = put_packet ( s , asf - > packet_timestamp_start ,
asf - > packet_timestamp_end - asf - > packet_timestamp_start ,
asf - > packet_timestamp_end - asf - > packet_timestamp_start ,
asf - > packet_nb_frames , asf - > packet_size_left ) ;
asf - > packet_nb_frames , asf - > packet_size_left ) ;
/* compute padding */
/* Clear out the padding bytes */
hdr_size = PACKET_HEADER_SIZE ;
ptr = asf - > packet_size - hdr_size - asf - > packet_size_left ;
if ( asf - > packet_size_left > 0 ) {
/* if padding needed, don't forget to count the
padding byte in the header size */
hdr_size + + ;
asf - > packet_size_left - - ;
/* XXX: I do not test again exact limit to avoid boundary problems */
if ( asf - > packet_size_left > 200 ) {
hdr_size + + ;
asf - > packet_size_left - - ;
}
}
ptr = asf - > packet_size - PACKET_HEADER_SIZE - asf - > packet_size_left ;
memset ( asf - > packet_buf + ptr , 0 , asf - > packet_size_left ) ;
memset ( asf - > packet_buf + ptr , 0 , asf - > packet_size_left ) ;
put_buffer ( & s - > pb , asf - > packet_buf , asf - > packet_size - hdr_size ) ;
put_buffer ( & s - > pb , asf - > packet_buf , asf - > packet_size - hdr_size ) ;
@ -502,7 +516,7 @@ static void put_frame_header(AVFormatContext *s, ASFStream *stream, int timestam
int val ;
int val ;
val = stream - > num ;
val = stream - > num ;
if ( s - > streams [ val - 1 ] - > codec . key_frame )
if ( s - > streams [ val - 1 ] - > codec . key_frame /* && frag_offset == 0 */ )
val | = 0x80 ;
val | = 0x80 ;
put_byte ( pb , val ) ;
put_byte ( pb , val ) ;
put_byte ( pb , stream - > seq ) ;
put_byte ( pb , stream - > seq ) ;
@ -561,6 +575,7 @@ static int asf_write_packet(AVFormatContext *s, int stream_index,
INT64 duration ;
INT64 duration ;
AVCodecContext * codec ;
AVCodecContext * codec ;
stream = & asf - > streams [ stream_index ] ;
codec = & s - > streams [ stream_index ] - > codec ;
codec = & s - > streams [ stream_index ] - > codec ;
stream = & asf - > streams [ stream_index ] ;
stream = & asf - > streams [ stream_index ] ;
@ -590,7 +605,7 @@ static int asf_write_trailer(AVFormatContext *s)
flush_packet ( s ) ;
flush_packet ( s ) ;
if ( url_is_streamed ( & s - > pb ) ) {
if ( url_is_streamed ( & s - > pb ) ) {
put_chunk ( s , 0x4524 , 0 ) ; /* end of stream */
put_chunk ( s , 0x4524 , 0 , 0 ) ; /* end of stream */
} else {
} else {
/* rewrite an updated header */
/* rewrite an updated header */
file_size = url_ftell ( & s - > pb ) ;
file_size = url_ftell ( & s - > pb ) ;
@ -752,6 +767,26 @@ static int asf_read_header(AVFormatContext *s, AVFormatParameters *ap)
st - > codec . codec_id = wav_codec_get_id ( id , bps ) ;
st - > codec . codec_id = wav_codec_get_id ( id , bps ) ;
size = get_le16 ( pb ) ;
size = get_le16 ( pb ) ;
url_fskip ( pb , size ) ;
url_fskip ( pb , size ) ;
/* We have to init the frame size at some point .... */
switch ( st - > codec . codec_id ) {
case CODEC_ID_MP3LAME :
st - > codec . frame_size = MPA_FRAME_SIZE ;
break ;
case CODEC_ID_PCM_S16LE :
case CODEC_ID_PCM_S16BE :
case CODEC_ID_PCM_U16LE :
case CODEC_ID_PCM_U16BE :
case CODEC_ID_PCM_S8 :
case CODEC_ID_PCM_U8 :
case CODEC_ID_PCM_ALAW :
case CODEC_ID_PCM_MULAW :
st - > codec . frame_size = 1 ;
break ;
default :
/* This is probably wrong, but it prevents a crash later */
st - > codec . frame_size = 1 ;
break ;
}
} else {
} else {
get_le32 ( pb ) ;
get_le32 ( pb ) ;
get_le32 ( pb ) ;
get_le32 ( pb ) ;
@ -879,6 +914,7 @@ static int asf_read_packet(AVFormatContext *s, AVPacket *pkt)
ASFStream * asf_st ;
ASFStream * asf_st ;
ByteIOContext * pb = & s - > pb ;
ByteIOContext * pb = & s - > pb ;
int ret , num , seq , frag_offset , payload_size , frag_len ;
int ret , num , seq , frag_offset , payload_size , frag_len ;
int key_frame ;
int timestamp , i ;
int timestamp , i ;
for ( ; ; ) {
for ( ; ; ) {
@ -892,7 +928,13 @@ static int asf_read_packet(AVFormatContext *s, AVPacket *pkt)
return - EIO ;
return - EIO ;
}
}
/* read frame header */
/* read frame header */
num = get_byte ( pb ) & 0x7f ;
num = get_byte ( pb ) ;
if ( num & 0x80 )
key_frame = 1 ;
else
key_frame = 0 ;
num & = 0x7f ;
seq = get_byte ( pb ) ;
seq = get_byte ( pb ) ;
frag_offset = get_le32 ( pb ) ;
frag_offset = get_le32 ( pb ) ;
get_byte ( pb ) ; /* flags */
get_byte ( pb ) ; /* flags */
@ -919,6 +961,10 @@ static int asf_read_packet(AVFormatContext *s, AVPacket *pkt)
/* new packet */
/* new packet */
av_new_packet ( & asf_st - > pkt , payload_size ) ;
av_new_packet ( & asf_st - > pkt , payload_size ) ;
asf_st - > seq = seq ;
asf_st - > seq = seq ;
if ( key_frame )
asf_st - > pkt . flags | = PKT_FLAG_KEY ;
asf_st - > pkt . pts = timestamp ;
} else {
} else {
if ( seq = = asf_st - > seq & &
if ( seq = = asf_st - > seq & &
frag_offset = = asf_st - > frag_offset ) {
frag_offset = = asf_st - > frag_offset ) {