@ -32,17 +32,59 @@ typedef struct {
/* use for reading */
AVPacket pkt ;
int frag_offset ;
int timestamp ;
INT64 duration ;
int ds_span ; /* descrambling */
int ds_packet_size ;
int ds_chunk_size ;
int ds_data_size ;
int ds_silence_data ;
} ASFStream ;
typedef struct {
UINT32 v1 ;
UINT16 v2 ;
UINT16 v3 ;
UINT8 v4 [ 8 ] ;
} GUID ;
typedef struct __attribute__ ( ( packed ) ) {
GUID guid ; // generated by client computer
uint64_t file_size ; // in bytes
// invalid if broadcasting
uint64_t create_time ; // time of creation, in 100-nanosecond units since 1.1.1601
// invalid if broadcasting
uint64_t packets_count ; // how many packets are there in the file
// invalid if broadcasting
uint64_t play_time ; // play time, in 100-nanosecond units
// invalid if broadcasting
uint64_t send_time ; // time to send file, in 100-nanosecond units
// invalid if broadcasting (could be ignored)
uint32_t preroll ; // timestamp of the first packet, in milliseconds
// if nonzero - substract from time
uint32_t ignore ; // preroll is 64bit - but let's just ignore it
uint32_t flags ; // 0x01 - broadcast
// 0x02 - seekable
// rest is reserved should be 0
uint32_t min_pktsize ; // size of a data packet
// invalid if broadcasting
uint32_t max_pktsize ; // shall be the same as for min_pktsize
// invalid if broadcasting
uint32_t max_bitrate ; // bandwith of stream in bps
// should be the sum of bitrates of the
// individual media streams
} ASFMainHeader ;
typedef struct {
int seqno ;
int packet_size ;
int is_streamed ;
ASFStream streams [ 2 ] ;
int asfid2avid [ 128 ] ;
ASFStream streams [ 1 28 ] ; // it's max number
/* non streamed additonnal info */
int data_offset ;
INT64 nb_packets ;
INT64 duration ; /* in 100ns units */
/* packet filling */
@ -53,16 +95,30 @@ typedef struct {
UINT8 packet_buf [ PACKET_SIZE ] ;
ByteIOContext pb ;
/* only for reading */
uint64_t data_offset ; /* begining of the first data packet */
ASFMainHeader hdr ;
int packet_flags ;
int packet_property ;
int packet_timestamp ;
int packet_segsizetype ;
int packet_segments ;
int packet_seq ;
int packet_replic_size ;
int packet_key_frame ;
int packet_padsize ;
int packet_frag_offset ;
int packet_frag_size ;
int packet_frag_timestamp ;
int packet_obj_size ;
int packet_time_delta ;
int packet_time_start ;
int stream_index ;
ASFStream * asf_st ; /* currently decoded stream */
} ASFContext ;
typedef struct {
UINT32 v1 ;
UINT16 v2 ;
UINT16 v3 ;
UINT8 v4 [ 8 ] ;
} GUID ;
static const GUID asf_header = {
0x75B22630 , 0x668E , 0x11CF , { 0xA6 , 0xD9 , 0x00 , 0xAA , 0x00 , 0x62 , 0xCE , 0x6C } ,
} ;
@ -120,7 +176,7 @@ static const GUID head1_guid = {
static const GUID head2_guid = {
0xabd3d211 , 0xa9ba , 0x11cf , { 0x8e , 0xe6 , 0x00 , 0xc0 , 0x0c , 0x20 , 0x53 , 0x65 } ,
} ;
/* I am not a number !!! This GUID is the one found on the PC used to
generate the stream */
static const GUID my_guid = {
@ -142,11 +198,11 @@ CodecTag codec_asf_bmp_tags[] = {
{ CODEC_ID_MPEG4 , MKTAG ( ' M ' , ' 4 ' , ' S ' , ' 2 ' ) } ,
{ CODEC_ID_MPEG4 , MKTAG ( ' m ' , ' 4 ' , ' s ' , ' 2 ' ) } ,
{ CODEC_ID_MPEG4 , MKTAG ( 0x04 , 0 , 0 , 0 ) } , /* some broken avi use this */
{ CODEC_ID_MSMPEG4V3 , MKTAG ( ' M ' , ' P ' , ' 4 ' , ' 3 ' ) } , /* default signature when using MSMPEG4 */
{ CODEC_ID_MSMPEG4V3 , MKTAG ( ' M ' , ' P ' , ' 4 ' , ' 3 ' ) } , /* default signature when using MSMPEG4 */
{ CODEC_ID_MSMPEG4V3 , MKTAG ( ' D ' , ' I ' , ' V ' , ' 3 ' ) } ,
{ CODEC_ID_MSMPEG4V2 , MKTAG ( ' M ' , ' P ' , ' 4 ' , ' 2 ' ) } ,
{ CODEC_ID_MSMPEG4V1 , MKTAG ( ' M ' , ' P ' , ' G ' , ' 4 ' ) } ,
{ CODEC_ID_WMV1 , MKTAG ( ' W ' , ' M ' , ' V ' , ' 1 ' ) } ,
{ CODEC_ID_MSMPEG4V2 , MKTAG ( ' M ' , ' P ' , ' 4 ' , ' 2 ' ) } ,
{ CODEC_ID_MSMPEG4V1 , MKTAG ( ' M ' , ' P ' , ' G ' , ' 4 ' ) } ,
{ CODEC_ID_WMV1 , MKTAG ( ' W ' , ' M ' , ' V ' , ' 1 ' ) } ,
{ 0 , 0 } ,
} ;
@ -171,7 +227,7 @@ static void put_str16(ByteIOContext *s, const char *tag)
for ( ; ; ) {
c = ( UINT8 ) * tag + + ;
put_le16 ( s , c ) ;
if ( c = = ' \0 ' )
if ( c = = ' \0 ' )
break ;
}
}
@ -183,7 +239,7 @@ static void put_str16_nolen(ByteIOContext *s, const char *tag)
for ( ; ; ) {
c = ( UINT8 ) * tag + + ;
put_le16 ( s , c ) ;
if ( c = = ' \0 ' )
if ( c = = ' \0 ' )
break ;
}
}
@ -217,8 +273,8 @@ static void put_chunk(AVFormatContext *s, int type, int payload_length, int flag
int length ;
length = payload_length + 8 ;
put_le16 ( pb , type ) ;
put_le16 ( pb , length ) ;
put_le16 ( pb , type ) ;
put_le16 ( pb , length ) ;
put_le32 ( pb , asf - > seqno ) ;
put_le16 ( pb , flags ) ; /* unknown bytes */
put_le16 ( pb , length ) ;
@ -229,7 +285,7 @@ static void put_chunk(AVFormatContext *s, int type, int payload_length, int flag
static INT64 unix_to_file_time ( int ti )
{
INT64 t ;
t = ti * INT64_C ( 10000000 ) ;
t + = INT64_C ( 116444736000000000 ) ;
return t ;
@ -260,11 +316,11 @@ static int asf_write_header1(AVFormatContext *s, INT64 file_size, INT64 data_chu
}
put_guid ( pb , & asf_header ) ;
put_le64 ( pb , 0 ) ; /* header length, will be patched after */
put_le64 ( pb , - 1 ) ; /* header length, will be patched after */
put_le32 ( pb , 3 + has_title + s - > nb_streams ) ; /* number of chunks in header */
put_byte ( pb , 1 ) ; /* ??? */
put_byte ( pb , 2 ) ; /* ??? */
/* file header */
header_offset = url_ftell ( pb ) ;
hpos = put_header ( pb , & file_header ) ;
@ -275,9 +331,9 @@ static int asf_write_header1(AVFormatContext *s, INT64 file_size, INT64 data_chu
put_le64 ( pb , asf - > nb_packets ) ; /* number of packets */
put_le64 ( pb , asf - > duration ) ; /* end time stamp (in 100ns units) */
put_le64 ( pb , asf - > duration ) ; /* duration (in 100ns units) */
put_le32 ( pb , 0 ) ; /* start time stamp */
put_le32 ( pb , 0 ) ; /* ??? */
put_le32 ( pb , asf - > is_streamed ? 1 : 0 ) ; /* ??? */
put_le32 ( pb , 0 ) ; /* start time stamp */
put_le32 ( pb , 0 ) ; /* ??? */
put_le32 ( pb , asf - > is_streamed ? 1 : 0 ) ; /* ??? */
put_le32 ( pb , asf - > packet_size ) ; /* packet size */
put_le32 ( pb , asf - > packet_size ) ; /* packet size */
put_le32 ( pb , bit_rate ) ; /* Nominal data rate in bps */
@ -313,7 +369,7 @@ static int asf_write_header1(AVFormatContext *s, INT64 file_size, INT64 data_chu
enc = & s - > streams [ n ] - > codec ;
asf - > streams [ n ] . num = n + 1 ;
asf - > streams [ n ] . seq = 0 ;
switch ( enc - > codec_type ) {
case CODEC_TYPE_AUDIO :
wav_extra_size = 0 ;
@ -350,7 +406,7 @@ static int asf_write_header1(AVFormatContext *s, INT64 file_size, INT64 data_chu
put_le32 ( pb , extra_size2 ) ; /* additional data len */
put_le16 ( pb , n + 1 ) ; /* stream number */
put_le32 ( pb , 0 ) ; /* ??? */
if ( enc - > codec_type = = CODEC_TYPE_AUDIO ) {
/* WAVEFORMATEX header */
int wavsize = put_wav_header ( pb , enc ) ;
@ -464,8 +520,8 @@ static int asf_write_stream_header(AVFormatContext *s)
}
/* write a fixed size packet */
static int put_packet ( AVFormatContext * s ,
unsigned int timestamp , unsigned int duration ,
static int put_packet ( AVFormatContext * s ,
unsigned int timestamp , unsigned int duration ,
int nb_frames , int padsize )
{
ASFContext * asf = s - > priv_data ;
@ -478,7 +534,7 @@ static int put_packet(AVFormatContext *s,
put_byte ( pb , 0x82 ) ;
put_le16 ( pb , 0 ) ;
flags = 0x01 ; /* nb segments present */
if ( padsize > 0 ) {
if ( padsize < 256 )
@ -503,17 +559,17 @@ static void flush_packet(AVFormatContext *s)
{
ASFContext * asf = s - > priv_data ;
int hdr_size , ptr ;
hdr_size = put_packet ( s , asf - > packet_timestamp_start ,
asf - > packet_timestamp_end - asf - > packet_timestamp_start ,
hdr_size = put_packet ( s , asf - > packet_timestamp_start ,
asf - > packet_timestamp_end - asf - > packet_timestamp_start ,
asf - > packet_nb_frames , asf - > packet_size_left ) ;
/* Clear out the padding bytes */
ptr = asf - > packet_size - hdr_size - 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_flush_packet ( & s - > pb ) ;
asf - > nb_packets + + ;
asf - > packet_nb_frames = 0 ;
@ -547,14 +603,14 @@ static void put_frame_header(AVFormatContext *s, ASFStream *stream, int timestam
/* Output a frame. We suppose that payload_size <= PACKET_SIZE.
It is there that you understand that the ASF format is really
crap . They have misread the MPEG Systems spec !
crap . They have misread the MPEG Systems spec !
*/
static void put_frame ( AVFormatContext * s , ASFStream * stream , int timestamp ,
UINT8 * buf , int payload_size )
{
ASFContext * asf = s - > priv_data ;
int frag_pos , frag_len , frag_len1 ;
frag_pos = 0 ;
while ( frag_pos < payload_size ) {
frag_len = payload_size - frag_pos ;
@ -594,23 +650,23 @@ static int asf_write_packet(AVFormatContext *s, int stream_index,
stream = & asf - > streams [ stream_index ] ;
codec = & s - > streams [ stream_index ] - > codec ;
stream = & asf - > streams [ stream_index ] ;
if ( codec - > codec_type = = CODEC_TYPE_AUDIO ) {
timestamp = ( int ) ticker_abs ( & stream - > pts_ticker , codec - > frame_number ) ;
duration = ( codec - > frame_number * codec - > frame_size * INT64_C ( 10000000 ) ) /
duration = ( codec - > frame_number * codec - > frame_size * INT64_C ( 10000000 ) ) /
codec - > sample_rate ;
} else {
timestamp = ( int ) ticker_abs ( & stream - > pts_ticker , codec - > frame_number ) ;
duration = codec - > frame_number *
duration = codec - > frame_number *
( ( INT64_C ( 10000000 ) * FRAME_RATE_BASE ) / codec - > frame_rate ) ;
}
if ( duration > asf - > duration )
asf - > duration = duration ;
put_frame ( s , stream , timestamp , buf , size ) ;
return 0 ;
}
static int asf_write_trailer ( AVFormatContext * s )
{
ASFContext * asf = s - > priv_data ;
@ -643,7 +699,7 @@ static void print_guid(const GUID *g)
{
int i ;
printf ( " 0x%08x, 0x%04x, 0x%04x, { " , g - > v1 , g - > v2 , g - > v3 ) ;
for ( i = 0 ; i < 8 ; i + + )
for ( i = 0 ; i < 8 ; i + + )
printf ( " 0x%02x, " , g - > v4 [ i ] ) ;
printf ( " } \n " ) ;
}
@ -747,34 +803,35 @@ static int asf_read_header(AVFormatContext *s, AVFormatParameters *ap)
if ( gsize < 24 )
goto fail ;
if ( ! memcmp ( & g , & file_header , sizeof ( GUID ) ) ) {
get_guid ( pb , & g ) ;
get_le64 ( pb ) ; /* file size */
get_le64 ( pb ) ; /* file time */
get_le64 ( pb ) ; /* nb_packets */
get_le64 ( pb ) ; /* length 0 in us */
get_le64 ( pb ) ; /* length 1 in us */
get_le32 ( pb ) ;
get_le32 ( pb ) ;
get_le32 ( pb ) ;
asf - > packet_size = get_le32 ( pb ) ;
get_le32 ( pb ) ;
get_le32 ( pb ) ;
get_guid ( pb , & asf - > hdr . guid ) ;
asf - > hdr . file_size = get_le64 ( pb ) ;
asf - > hdr . create_time = get_le64 ( pb ) ;
asf - > hdr . packets_count = get_le64 ( pb ) ;
asf - > hdr . play_time = get_le64 ( pb ) ;
asf - > hdr . send_time = get_le64 ( pb ) ;
asf - > hdr . preroll = get_le32 ( pb ) ;
asf - > hdr . ignore = get_le32 ( pb ) ;
asf - > hdr . flags = get_le32 ( pb ) ;
asf - > hdr . min_pktsize = get_le32 ( pb ) ;
asf - > hdr . max_pktsize = get_le32 ( pb ) ;
asf - > hdr . max_bitrate = get_le32 ( pb ) ;
asf - > packet_size = asf - > hdr . max_pktsize ;
} else if ( ! memcmp ( & g , & stream_header , sizeof ( GUID ) ) ) {
int type , id , total_size ;
unsigned int tag1 ;
INT64 pos1 , pos2 ;
pos1 = url_ftell ( pb ) ;
st = av_mallocz ( sizeof ( AVStream ) ) ;
if ( ! st )
goto fail ;
s - > streams [ s - > nb_streams + + ] = st ;
s - > streams [ s - > nb_streams ] = st ;
asf_st = av_mallocz ( sizeof ( ASFStream ) ) ;
if ( ! asf_st )
goto fail ;
st - > priv_data = asf_st ;
st - > time_length = ( asf - > hdr . send_time - asf - > hdr . preroll ) / 10000 ;
get_guid ( pb , & g ) ;
if ( ! memcmp ( & g , & audio_stream , sizeof ( GUID ) ) ) {
type = CODEC_TYPE_AUDIO ;
@ -787,21 +844,44 @@ static int asf_read_header(AVFormatContext *s, AVFormatParameters *ap)
total_size = get_le64 ( pb ) ;
get_le32 ( pb ) ;
get_le32 ( pb ) ;
st - > id = get_le16 ( pb ) ; /* stream id */
st - > id = get_le16 ( pb ) & 0x7f ; /* stream id */
// mapping of asf ID to AV stream ID;
asf - > asfid2avid [ st - > id ] = s - > nb_streams + + ;
get_le32 ( pb ) ;
st - > codec . codec_type = type ;
if ( type = = CODEC_TYPE_AUDIO ) {
id = get_le16 ( pb ) ;
id = get_le16 ( pb ) ;
st - > codec . codec_tag = id ;
st - > codec . channels = get_le16 ( pb ) ;
st - > codec . sample_rate = get_le32 ( pb ) ;
st - > codec . sample_rate = get_le32 ( pb ) ;
st - > codec . bit_rate = get_le32 ( pb ) * 8 ;
get_le16 ( pb ) ; /* block align */
st - > codec . block_align = get_le16 ( pb ) ; /* block align */
bps = get_le16 ( pb ) ; /* bits per sample */
st - > codec . codec_id = wav_codec_get_id ( id , bps ) ;
size = get_le16 ( pb ) ;
url_fskip ( pb , size ) ;
/* We have to init the frame size at some point .... */
size = get_le16 ( pb ) ;
st - > extra_data = av_mallocz ( size ) ;
get_buffer ( pb , st - > extra_data , size ) ;
st - > extra_data_size = size ;
/* We have to init the frame size at some point .... */
pos2 = url_ftell ( pb ) ;
if ( gsize > ( pos2 + 8 - pos1 + 24 ) )
{
asf_st - > ds_span = get_byte ( pb ) ;
asf_st - > ds_packet_size = get_le16 ( pb ) ;
asf_st - > ds_chunk_size = get_le16 ( pb ) ;
asf_st - > ds_data_size = get_le16 ( pb ) ;
asf_st - > ds_silence_data = get_byte ( pb ) ;
}
//printf("Descrambling: ps:%d cs:%d ds:%d s:%d sd:%d\n",
// asf_st->ds_packet_size, asf_st->ds_chunk_size,
// asf_st->ds_data_size, asf_st->ds_span, asf_st->ds_silence_data);
if ( asf_st - > ds_span > 1 )
{
if ( ! asf_st - > ds_chunk_size
| | ( asf_st - > ds_packet_size / asf_st - > ds_chunk_size < = 1 ) )
asf_st - > ds_span = 0 ; // disable descrambling
}
switch ( st - > codec . codec_id ) {
case CODEC_ID_MP3LAME :
st - > codec . frame_size = MPA_FRAME_SIZE ;
@ -828,14 +908,15 @@ static int asf_read_header(AVFormatContext *s, AVFormatParameters *ap)
size = get_le16 ( pb ) ; /* size */
get_le32 ( pb ) ; /* size */
st - > codec . width = get_le32 ( pb ) ;
st - > codec . height = get_le32 ( pb ) ;
st - > codec . frame_rate = 25 * FRAME_RATE_BASE ; /* XXX: find it */
st - > codec . height = get_le32 ( pb ) ;
/* not available for asf */
st - > codec . frame_rate = 25 * FRAME_RATE_BASE ; /* XXX: find it */
get_le16 ( pb ) ; /* panes */
get_le16 ( pb ) ; /* depth */
tag1 = get_le32 ( pb ) ;
st - > codec . codec_tag = tag1 ;
st - > codec . codec_id = codec_get_id ( codec_asf_bmp_tags , tag1 ) ;
url_fskip ( pb , size - 5 * 4 ) ;
url_fskip ( pb , size - 5 * 4 ) ;
}
pos2 = url_ftell ( pb ) ;
url_fskip ( pb , gsize - ( pos2 - pos1 + 24 ) ) ;
@ -867,7 +948,7 @@ static int asf_read_header(AVFormatContext *s, AVFormatParameters *ap)
get_guid ( pb , & g ) ;
print_guid ( & g ) ;
n = get_le32 ( pb ) ;
for ( i = 0 ; i < n ; i + + ) {
num = get_le16 ( pb ) ; /* stream number */
@ -910,129 +991,218 @@ static int asf_read_header(AVFormatContext *s, AVFormatParameters *ap)
return - 1 ;
}
# define DO_2BITS(bits, var, defval) \
switch ( bits & 3 ) \
{ \
case 3 : var = get_le32 ( pb ) ; rsize + = 4 ; break ; \
case 2 : var = get_le16 ( pb ) ; rsize + = 2 ; break ; \
case 1 : var = get_byte ( pb ) ; rsize + + ; break ; \
default : var = defval ; break ; \
}
static int asf_get_packet ( AVFormatContext * s )
{
ASFContext * asf = s - > priv_data ;
ByteIOContext * pb = & s - > pb ;
int c , flags , timestamp , hdr_size ;
hdr_size = 12 ;
c = get_byte ( pb ) ;
uint32_t packet_length , padsize ;
int rsize = 11 ;
int c = get_byte ( pb ) ;
if ( c ! = 0x82 )
return - EIO ;
get_le16 ( pb ) ;
flags = get_byte ( pb ) ;
get_byte ( pb ) ;
asf - > packet_padsize = 0 ;
if ( flags & 0x10 ) {
asf - > packet_padsize = get_le16 ( pb ) ;
hdr_size + = 2 ;
} else if ( flags & 0x08 ) {
asf - > packet_padsize = get_byte ( pb ) ;
hdr_size + + ;
{
printf ( " BAD HRD %x at:%Ld \n " , c , url_ftell ( pb ) ) ;
return - EIO ;
}
if ( ( c & 0x0f ) = = 2 ) { // always true for now
if ( get_le16 ( pb ) ! = 0 )
{
printf ( " BAD NO ZERO \n " ) ;
return - EIO ;
}
}
timestamp = get_le32 ( pb ) ;
asf - > packet_flags = get_byte ( pb ) ;
asf - > packet_property = get_byte ( pb ) ;
DO_2BITS ( asf - > packet_flags > > 5 , packet_length , asf - > packet_size ) ;
DO_2BITS ( asf - > packet_flags > > 1 , padsize , 0 ) ; // sequence ignored
DO_2BITS ( asf - > packet_flags > > 3 , padsize , 0 ) ; // padding length
asf - > packet_timestamp = get_le32 ( pb ) ;
get_le16 ( pb ) ; /* duration */
get_byte ( pb ) ; /* nb_frames */
// rsize has 11 bytes static bytes which have to be present
if ( asf - > packet_flags & 0x01 ) {
asf - > packet_segsizetype = get_byte ( pb ) ; rsize + + ;
asf - > packet_segments = asf - > packet_segsizetype & 0x3f ;
} else {
asf - > packet_segments = 1 ;
asf - > packet_segsizetype = 0x80 ;
}
asf - > packet_size_left = packet_length - padsize - rsize ;
asf - > packet_padsize = padsize ;
# ifdef DEBUG
printf ( " packet: size=%d padsize=%d \n " , asf - > packet_size , asf - > packet_padsize ) ;
printf ( " packet: size=%d padsize=%d left=%d \n " , asf - > packet_size , asf - > packet_padsize , asf - > packet_size_left ) ;
# endif
asf - > packet_size_left = asf - > packet_size - hdr_size ;
return 0 ;
}
static int asf_read_packet ( AVFormatContext * s , AVPacket * pkt )
{
ASFContext * asf = s - > priv_data ;
AVStream * st ;
ASFStream * asf_st ;
ASFStream * asf_st = 0 ;
ByteIOContext * pb = & s - > pb ;
int ret , num , seq , frag_offset , payload_size , frag_len ;
int key_frame ;
int timestamp , i ;
for ( ; ; ) {
if ( asf - > packet_size_left < FRAME_HEADER_SIZE | |
asf - > packet_size_left < = asf - > packet_padsize ) {
static int pc = 0 ;
for ( ; ; ) {
int rsize = 0 ;
if ( asf - > packet_size_left < FRAME_HEADER_SIZE ) {
//asf->packet_size_left <= asf->packet_padsize) {
int ret ;
//printf("PACKETLEFTSIZE %d\n", asf->packet_size_left);
/* fail safe */
if ( asf - > packet_size_left )
url_fskip ( pb , asf - > packet_size_left ) ;
ret = asf_get_packet ( s ) ;
if ( ret < 0 )
return - EIO ;
}
/* read frame header */
num = get_byte ( pb ) ;
if ( num & 0x80 )
key_frame = 1 ;
else
key_frame = 0 ;
num & = 0x7f ;
seq = get_byte ( pb ) ;
frag_offset = get_le32 ( pb ) ;
get_byte ( pb ) ; /* flags */
payload_size = get_le32 ( pb ) ;
timestamp = get_le32 ( pb ) ;
frag_len = get_le16 ( pb ) ;
# ifdef DEBUG
printf ( " num=%d seq=%d totsize=%d frag_off=%d frag_size=%d \n " ,
num , seq , payload_size , frag_offset , frag_len ) ;
# endif
st = NULL ;
for ( i = 0 ; i < s - > nb_streams ; i + + ) {
st = s - > streams [ i ] ;
if ( st - > id = = num )
break ;
}
asf - > packet_size_left - = FRAME_HEADER_SIZE + frag_len ;
if ( i = = s - > nb_streams ) {
/* unhandled packet (should not happen) */
url_fskip ( pb , frag_len ) ;
} else {
asf_st = st - > priv_data ;
if ( asf_st - > frag_offset = = 0 ) {
/* new packet */
av_new_packet ( & asf_st - > pkt , payload_size ) ;
asf_st - > seq = seq ;
if ( key_frame )
asf_st - > pkt . flags | = PKT_FLAG_KEY ;
asf_st - > pkt . pts = timestamp ;
} else {
if ( seq = = asf_st - > seq & &
frag_offset = = asf_st - > frag_offset ) {
/* continuing packet */
} else {
/* cannot continue current packet: free it */
av_free_packet ( & asf_st - > pkt ) ;
asf_st - > frag_offset = 0 ;
if ( frag_offset ! = 0 ) {
/* cannot create new packet */
url_fskip ( pb , frag_len ) ;
goto next_frame ;
} else {
/* create new packet */
av_new_packet ( & asf_st - > pkt , payload_size ) ;
asf_st - > seq = seq ;
}
}
}
/* read data */
get_buffer ( pb , asf_st - > pkt . data + frag_offset , frag_len ) ;
asf_st - > frag_offset + = frag_len ;
/* test if whole packet read */
if ( asf_st - > frag_offset = = asf_st - > pkt . size ) {
/* return packet */
asf_st - > pkt . stream_index = i ;
asf_st - > frag_offset = 0 ;
memcpy ( pkt , & asf_st - > pkt , sizeof ( AVPacket ) ) ;
break ;
}
}
next_frame : ;
url_fskip ( pb , asf - > packet_size_left ) ;
if ( asf - > packet_padsize )
url_fskip ( pb , asf - > packet_padsize ) ;
ret = asf_get_packet ( s ) ;
//printf("READ ASF PACKET %d r:%d c:%d\n", ret, asf->packet_size_left, pc++);
if ( ret < 0 )
return - EIO ;
continue ;
}
if ( 1 ) { // FIXME - handle replicated multi packets
/* read frame header */
int num = get_byte ( pb ) ;
rsize + + ;
asf - > packet_key_frame = ( num & 0x80 ) > > 7 ;
asf - > stream_index = asf - > asfid2avid [ num & 0x7f ] ;
if ( asf - > stream_index < 0 )
{
/* unhandled packet (should not happen) */
url_fskip ( pb , asf - > packet_frag_size ) ;
asf - > packet_size_left - = asf - > packet_frag_size ;
//printf("#####xxxxxx###### skip %d\n", asf->packet_frag_size);
continue ;
// FIXME
}
asf - > asf_st = s - > streams [ asf - > stream_index ] - > priv_data ;
//printf("ASFST %p %d <> %d\n", asf->asf_st, asf->stream_index, num & 0x7f);
// sequence should be ignored!
DO_2BITS ( asf - > packet_property > > 4 , asf - > packet_seq , 0 ) ;
DO_2BITS ( asf - > packet_property > > 2 , asf - > packet_frag_offset , 0 ) ;
DO_2BITS ( asf - > packet_property , asf - > packet_replic_size , 0 ) ;
if ( asf - > packet_replic_size > 1 ) {
// it should be always at least 8 bytes - FIXME validate
asf - > packet_obj_size = get_le32 ( pb ) ;
asf - > packet_frag_timestamp = get_le32 ( pb ) ; // timestamp
rsize + = asf - > packet_replic_size ; // FIXME - check validity
} else {
// multipacket - frag_offset is beginig timestamp
asf - > packet_time_start = asf - > packet_frag_offset ;
asf - > packet_frag_offset = 0 ;
asf - > packet_frag_timestamp = asf - > packet_timestamp ;
if ( asf - > packet_replic_size = = 1 ) {
asf - > packet_time_delta = get_byte ( pb ) ;
rsize + + ;
}
}
if ( asf - > packet_flags & 0x01 ) {
DO_2BITS ( asf - > packet_segsizetype > > 6 , asf - > packet_frag_size , 0 ) ; // 0 is illegal
//printf("Fragsize %d\n", asf->packet_frag_size);
} else {
asf - > packet_frag_size = asf - > packet_size_left - rsize ;
//printf("Using rest %d %d %d\n", asf->packet_frag_size, asf->packet_size_left, rsize);
}
# undef DO_2BITS
asf - > packet_size_left - = rsize ;
//printf("___objsize____ %d %d rs:%d\n", asf->packet_obj_size, asf->packet_frag_offset, rsize);
}
asf_st = asf - > asf_st ;
if ( ( asf - > packet_frag_offset ! = asf_st - > frag_offset
| | ( asf - > packet_frag_offset
& & asf - > packet_seq ! = asf_st - > seq ) ) // seq should be ignored
) {
/* cannot continue current packet: free it */
// FIXME better check if packet was already allocated
printf ( " asf parser skips: %d - %d o:%d - %d %d %d fl:%d \n " ,
asf_st - > pkt . size ,
asf - > packet_obj_size ,
asf - > packet_frag_offset , asf_st - > frag_offset ,
asf - > packet_seq , asf_st - > seq , asf - > packet_frag_size ) ;
if ( asf_st - > pkt . size )
av_free_packet ( & asf_st - > pkt ) ;
asf_st - > frag_offset = 0 ;
if ( asf - > packet_frag_offset ! = 0 ) {
/* cannot create new packet */
url_fskip ( pb , asf - > packet_frag_size ) ;
printf ( " asf parser skiping %db \n " , asf - > packet_frag_size ) ;
asf - > packet_size_left - = asf - > packet_frag_size ;
continue ;
}
}
if ( asf - > packet_replic_size = = 1 )
{
// frag_size is now begining timestamp
asf - > packet_frag_timestamp = asf - > packet_time_start ;
asf - > packet_obj_size = asf - > packet_frag_size = get_byte ( pb ) ;
asf - > packet_size_left - - ;
//printf("COMPRESS size %d %d\n", asf->packet_obj_size, asf->packet_frag_timestamp);
}
//printf("PACKET OFFSET %d\n", asf_st->frag_offset);
if ( asf_st - > frag_offset = = 0 ) {
/* new packet */
av_new_packet ( & asf_st - > pkt , asf - > packet_obj_size ) ;
asf_st - > seq = asf - > packet_seq ;
asf_st - > pkt . pts = asf - > packet_frag_timestamp - asf - > hdr . preroll ;
asf_st - > pkt . stream_index = asf - > stream_index ;
if ( asf - > packet_key_frame )
asf_st - > pkt . flags | = PKT_FLAG_KEY ;
}
/* read data */
//printf("READ PACKET s:%d os:%d o:%d,%d l:%d DATA:%p\n",
// asf->packet_size, asf_st->pkt.size, asf->packet_frag_offset,
// asf_st->frag_offset, asf->packet_frag_size, asf_st->pkt.data);
get_buffer ( pb , asf_st - > pkt . data + asf - > packet_frag_offset ,
asf - > packet_frag_size ) ;
asf_st - > frag_offset + = asf - > packet_frag_size ;
asf - > packet_size_left - = asf - > packet_frag_size ;
/* test if whole packet is read */
if ( asf_st - > frag_offset = = asf_st - > pkt . size ) {
/* return packet */
if ( asf_st - > ds_span > 1 ) {
// descramble packet
char * newdata = av_malloc ( asf_st - > pkt . size ) ;
if ( newdata ) {
int offset = 0 ;
while ( offset < asf_st - > pkt . size ) {
int off = offset / asf_st - > ds_chunk_size ;
int row = off / asf_st - > ds_span ;
int col = off % asf_st - > ds_span ;
int idx = row + col * asf_st - > ds_packet_size / asf_st - > ds_chunk_size ;
//printf("off:%d row:%d col:%d idx:%d\n", off, row, col, idx);
memcpy ( newdata + offset ,
asf_st - > pkt . data + idx * asf_st - > ds_chunk_size ,
asf_st - > ds_chunk_size ) ;
offset + = asf_st - > ds_chunk_size ;
}
av_free ( asf_st - > pkt . data ) ;
asf_st - > pkt . data = newdata ;
}
}
asf_st - > frag_offset = 0 ;
memcpy ( pkt , & asf_st - > pkt , sizeof ( AVPacket ) ) ;
//printf("packet %d %d\n", asf_st->pkt.size, asf->packet_frag_size);
asf_st - > pkt . size = 0 ;
asf_st - > pkt . data = 0 ;
// FIXME descrambling
break ; // packet completed
}
}
return 0 ;
}
@ -1049,6 +1219,12 @@ static int asf_read_close(AVFormatContext *s)
return 0 ;
}
static int asf_read_seek ( AVFormatContext * s , int64_t pts )
{
printf ( " SEEK TO %Ld " , pts ) ;
return - 1 ;
}
AVInputFormat asf_iformat = {
" asf " ,
" asf format " ,
@ -1057,6 +1233,7 @@ AVInputFormat asf_iformat = {
asf_read_header ,
asf_read_packet ,
asf_read_close ,
asf_read_seek ,
} ;
AVOutputFormat asf_oformat = {