@ -28,7 +28,6 @@
* - seeking
* - seeking
* - index writing
* - index writing
* - index packet reading support
* - index packet reading support
* - startcode searching for broken streams
*/
*/
//#define DEBUG 1
//#define DEBUG 1
@ -91,6 +90,7 @@ typedef struct {
int64_t last_frame_start [ 3 ] ;
int64_t last_frame_start [ 3 ] ;
FrameCode frame_code [ 256 ] ;
FrameCode frame_code [ 256 ] ;
int stream_count ;
int stream_count ;
uint64_t next_startcode ; ///< stores the next startcode if it has alraedy been parsed but the stream isnt seekable
StreamContext * stream ;
StreamContext * stream ;
} NUTContext ;
} NUTContext ;
@ -131,14 +131,15 @@ static void update_lru(int *lru, int current, int count){
static void update ( NUTContext * nut , int stream_index , int64_t frame_start , int frame_type , int frame_code , int key_frame , int size , int64_t pts ) {
static void update ( NUTContext * nut , int stream_index , int64_t frame_start , int frame_type , int frame_code , int key_frame , int size , int64_t pts ) {
StreamContext * stream = & nut - > stream [ stream_index ] ;
StreamContext * stream = & nut - > stream [ stream_index ] ;
const int flags = nut - > frame_code [ frame_code ] . flags ;
stream - > last_key_frame = key_frame ;
stream - > last_key_frame = key_frame ;
nut - > last_frame_start [ frame_type ] = frame_start ;
nut - > last_frame_start [ frame_type ] = frame_start ;
update_lru ( stream - > lru_pts_delta , pts - stream - > last_pts , 3 ) ;
if ( frame_type = = 0 )
update_lru ( stream - > lru_size , size , 2 ) ;
update_lru ( stream - > lru_pts_delta , pts - stream - > last_pts , 3 ) ;
update_lru ( stream - > lru_size , size , 2 ) ;
stream - > last_pts = pts ;
stream - > last_pts = pts ;
if ( nut - > frame_code [ frame_code ] . flags & FLAG_PTS
if ( ( flags & FLAG_PTS ) & & ( flags & FLAG_FULL_PTS ) )
& & nut - > frame_code [ frame_code ] . flags & FLAG_FULL_PTS )
stream - > last_full_pts = pts ;
stream - > last_full_pts = pts ;
}
}
@ -244,16 +245,11 @@ static void build_frame_code(AVFormatContext *s){
nut - > frame_code [ ' N ' ] . flags = 1 ;
nut - > frame_code [ ' N ' ] . flags = 1 ;
}
}
static int bytes_left ( ByteIOContext * bc )
{
return bc - > buf_end - bc - > buf_ptr ;
}
static uint64_t get_v ( ByteIOContext * bc )
static uint64_t get_v ( ByteIOContext * bc )
{
{
uint64_t val = 0 ;
uint64_t val = 0 ;
for ( ; bytes_left ( bc ) > 0 ; )
for ( ; ; )
{
{
int tmp = get_byte ( bc ) ;
int tmp = get_byte ( bc ) ;
@ -291,17 +287,18 @@ static int get_packetheader(NUTContext *nut, ByteIOContext *bc, int prefix_lengt
if ( start ! = nut - > packet_start + nut - > written_packet_size ) {
if ( start ! = nut - > packet_start + nut - > written_packet_size ) {
av_log ( nut - > avf , AV_LOG_ERROR , " get_packetheader called at weird position \n " ) ;
av_log ( nut - > avf , AV_LOG_ERROR , " get_packetheader called at weird position \n " ) ;
return - 1 ;
if ( prefix_length < 8 )
return - 1 ;
}
}
if ( calculate_checksum )
init_checksum ( bc , calculate_checksum ? update_adler32 : NULL , 0 ) ;
init_checksum ( bc , update_adler32 , 0 ) ;
size = get_v ( bc ) ;
size = get_v ( bc ) ;
last_size = get_v ( bc ) ;
last_size = get_v ( bc ) ;
if ( nut - > written_packet_size ! = last_size ) {
if ( nut - > written_packet_size ! = last_size ) {
av_log ( nut - > avf , AV_LOG_ERROR , " packet size missmatch %d != %lld at %lld \n " , nut - > written_packet_size , last_size , start ) ;
av_log ( nut - > avf , AV_LOG_ERROR , " packet size missmatch %d != %lld at %lld \n " , nut - > written_packet_size , last_size , start ) ;
return - 1 ;
if ( prefix_length < 8 )
return - 1 ;
}
}
nut - > last_packet_start = nut - > packet_start ;
nut - > last_packet_start = nut - > packet_start ;
@ -335,7 +332,7 @@ static uint64_t find_any_startcode(ByteIOContext *bc, int64_t pos){
if ( pos > = 0 )
if ( pos > = 0 )
url_fseek ( bc , pos , SEEK_SET ) ; //note, this may fail if the stream isnt seekable, but that shouldnt matter, as in this case we simply start where we are currently
url_fseek ( bc , pos , SEEK_SET ) ; //note, this may fail if the stream isnt seekable, but that shouldnt matter, as in this case we simply start where we are currently
while ( bytes_left ( bc ) ) {
while ( ! url_feof ( bc ) ) {
state = ( state < < 8 ) | get_byte ( bc ) ;
state = ( state < < 8 ) | get_byte ( bc ) ;
if ( ( state > > 56 ) ! = ' N ' )
if ( ( state > > 56 ) ! = ' N ' )
continue ;
continue ;
@ -348,6 +345,7 @@ static uint64_t find_any_startcode(ByteIOContext *bc, int64_t pos){
return state ;
return state ;
}
}
}
}
av_log ( NULL , AV_LOG_DEBUG , " searched until %lld \n " , url_ftell ( bc ) ) ;
return 0 ;
return 0 ;
}
}
@ -366,11 +364,6 @@ static int find_startcode(ByteIOContext *bc, uint64_t code, int64_t pos){
static int put_v ( ByteIOContext * bc , uint64_t val )
static int put_v ( ByteIOContext * bc , uint64_t val )
{
{
int i ;
int i ;
// if (bytes_left(s)*8 < 9)
// return -1;
if ( bytes_left ( bc ) < 1 )
return - 1 ;
val & = 0x7FFFFFFFFFFFFFFFULL ; // FIXME can only encode upto 63 bits currently
val & = 0x7FFFFFFFFFFFFFFFULL ; // FIXME can only encode upto 63 bits currently
i = get_length ( val ) ;
i = get_length ( val ) ;
@ -1047,7 +1040,7 @@ static int nut_read_header(AVFormatContext *s, AVFormatParameters *ap)
av_log ( s , AV_LOG_ERROR , " EOF before video frames \n " ) ;
av_log ( s , AV_LOG_ERROR , " EOF before video frames \n " ) ;
return - 1 ;
return - 1 ;
} else if ( startcode = = KEYFRAME_STARTCODE ) {
} else if ( startcode = = KEYFRAME_STARTCODE ) {
url_fseek ( bc , - 8 , SEEK_CUR ) ; //FIXME
nut - > next_startcode = startcode ;
break ;
break ;
} else if ( startcode ! = INFO_STARTCODE ) {
} else if ( startcode ! = INFO_STARTCODE ) {
continue ;
continue ;
@ -1059,34 +1052,16 @@ static int nut_read_header(AVFormatContext *s, AVFormatParameters *ap)
return 0 ;
return 0 ;
}
}
static int nut_read_packet ( AVFormatContext * s , AVPacket * pkt )
static int decode_frame ( NUTContext * nut , AVPacket * pkt , int frame_code , int frame_type ) {
{
AVFormatContext * s = nut - > avf ;
NUTContext * nut = s - > priv_data ;
StreamContext * stream ;
StreamContext * stream ;
ByteIOContext * bc = & s - > pb ;
ByteIOContext * bc = & s - > pb ;
int size , frame_code , f lags , size_mul , size_lsb , stream_id ;
int size , flags , size_mul , size_lsb , stream_id ;
int key_frame = 0 ;
int key_frame = 0 ;
int frame_type = 0 ;
int64_t pts = 0 ;
int64_t pts = 0 ;
const int64_t frame_start = url_ftell ( bc ) ;
const int prefix_len = frame_type = = 2 ? 8 + 1 : 1 ;
const int64_t frame_start = url_ftell ( bc ) + prefix_len ;
if ( url_feof ( bc ) )
return - 1 ;
frame_code = get_byte ( bc ) ;
if ( frame_code = = ' N ' ) {
uint64_t tmp = frame_code ;
tmp < < = 8 ; tmp | = get_byte ( bc ) ;
tmp < < = 16 ; tmp | = get_be16 ( bc ) ;
tmp < < = 32 ; tmp | = get_be32 ( bc ) ;
if ( tmp = = KEYFRAME_STARTCODE )
{
frame_code = get_byte ( bc ) ;
frame_type = 2 ;
}
else
av_log ( s , AV_LOG_ERROR , " error in zero bit / startcode %LX \n " , tmp ) ;
}
flags = nut - > frame_code [ frame_code ] . flags ;
flags = nut - > frame_code [ frame_code ] . flags ;
size_mul = nut - > frame_code [ frame_code ] . size_mul ;
size_mul = nut - > frame_code [ frame_code ] . size_mul ;
size_lsb = nut - > frame_code [ frame_code ] . size_lsb ;
size_lsb = nut - > frame_code [ frame_code ] . size_lsb ;
@ -1094,12 +1069,10 @@ static int nut_read_packet(AVFormatContext *s, AVPacket *pkt)
if ( flags & FLAG_FRAME_TYPE ) {
if ( flags & FLAG_FRAME_TYPE ) {
reset ( s ) ;
reset ( s ) ;
if ( frame_type = = 2 ) {
if ( get_packetheader ( nut , bc , prefix_len , 0 ) < 0 )
get_packetheader ( nut , bc , 8 + 1 , 0 ) ;
return - 1 ;
} else {
if ( frame_type ! = 2 )
get_packetheader ( nut , bc , 1 , 0 ) ;
frame_type = 1 ;
frame_type = 1 ;
}
}
}
if ( stream_id = = - 1 )
if ( stream_id = = - 1 )
@ -1109,6 +1082,8 @@ static int nut_read_packet(AVFormatContext *s, AVPacket *pkt)
return - 1 ;
return - 1 ;
}
}
stream = & nut - > stream [ stream_id ] ;
stream = & nut - > stream [ stream_id ] ;
// av_log(s, AV_LOG_DEBUG, "ft:%d ppts:%d %d %d\n", frame_type, stream->lru_pts_delta[0], stream->lru_pts_delta[1], stream->lru_pts_delta[2]);
if ( flags & FLAG_PRED_KEY_FRAME ) {
if ( flags & FLAG_PRED_KEY_FRAME ) {
if ( flags & FLAG_KEY_FRAME )
if ( flags & FLAG_KEY_FRAME )
@ -1140,7 +1115,12 @@ static int nut_read_packet(AVFormatContext *s, AVPacket *pkt)
size = size_lsb ;
size = size_lsb ;
}
}
//av_log(s, AV_LOG_DEBUG, "fs:%lld fc:%d ft:%d kf:%d pts:%lld\n", frame_start, frame_code, frame_type, key_frame, pts);
//av_log(s, AV_LOG_DEBUG, "fs:%lld fc:%d ft:%d kf:%d pts:%lld size:%d\n", frame_start, frame_code, frame_type, key_frame, pts, size);
if ( url_ftell ( bc ) - nut - > packet_start + size > nut - > written_packet_size ) {
av_log ( s , AV_LOG_ERROR , " frame size too large \n " ) ;
return - 1 ;
}
av_new_packet ( pkt , size ) ;
av_new_packet ( pkt , size ) ;
get_buffer ( bc , pkt - > data , size ) ;
get_buffer ( bc , pkt - > data , size ) ;
@ -1150,10 +1130,91 @@ static int nut_read_packet(AVFormatContext *s, AVPacket *pkt)
pkt - > pts = pts * AV_TIME_BASE * stream - > rate_den / stream - > rate_num ;
pkt - > pts = pts * AV_TIME_BASE * stream - > rate_den / stream - > rate_num ;
update ( nut , stream_id , frame_start , frame_type , frame_code , key_frame , size , pts ) ;
update ( nut , stream_id , frame_start , frame_type , frame_code , key_frame , size , pts ) ;
return 0 ;
return 0 ;
}
}
static int nut_read_packet ( AVFormatContext * s , AVPacket * pkt )
{
NUTContext * nut = s - > priv_data ;
ByteIOContext * bc = & s - > pb ;
int size , frame_code = 0 ;
int frame_type = 0 ;
int64_t pos ;
for ( ; ; ) {
uint64_t tmp = nut - > next_startcode ;
nut - > next_startcode = 0 ;
if ( url_feof ( bc ) )
return - 1 ;
if ( ! tmp ) {
frame_code = get_byte ( bc ) ;
if ( frame_code = = ' N ' ) {
tmp = frame_code ;
tmp < < = 8 ; tmp | = get_byte ( bc ) ;
tmp < < = 16 ; tmp | = get_be16 ( bc ) ;
tmp < < = 32 ; tmp | = get_be32 ( bc ) ;
}
}
switch ( tmp ) {
case KEYFRAME_STARTCODE :
frame_type = 2 ;
break ;
case MAIN_STARTCODE :
case STREAM_STARTCODE :
case INDEX_STARTCODE :
get_packetheader ( nut , bc , 8 , 0 ) ;
url_fseek ( bc , nut - > written_packet_size + nut - > packet_start , SEEK_SET ) ;
break ;
case INFO_STARTCODE :
if ( decode_info_header ( nut ) < 0 )
goto resync ;
break ;
case 0 :
if ( decode_frame ( nut , pkt , frame_code , frame_type ) > = 0 )
return 0 ;
default :
resync :
frame_type = 0 ;
av_log ( s , AV_LOG_DEBUG , " syncing from %lld \n " , nut - > packet_start + 1 ) ;
tmp = find_any_startcode ( bc , nut - > packet_start + 1 ) ;
if ( tmp = = 0 )
return - 1 ;
av_log ( s , AV_LOG_DEBUG , " sync \n " ) ;
if ( url_is_streamed ( bc ) ) {
nut - > next_startcode = tmp ;
break ;
}
pos = url_ftell ( bc ) - 8 ;
av_log ( s , AV_LOG_DEBUG , " at %lld code=%llX \n " , pos , tmp ) ;
if ( tmp = = KEYFRAME_STARTCODE ) {
get_byte ( bc ) ;
}
get_v ( bc ) ;
size = get_v ( bc ) ;
while ( size > 2 & & size < 100000 & & nut - > packet_start < pos - size ) {
url_fseek ( bc , pos - size , SEEK_SET ) ;
frame_code = get_byte ( bc ) ;
if ( ! ( nut - > frame_code [ frame_code ] . flags & FLAG_FRAME_TYPE ) )
break ;
if ( get_v ( bc ) ! = size )
break ;
pos - = size ;
size = get_v ( bc ) ;
av_log ( s , AV_LOG_DEBUG , " steping back to %lld next %d \n " , pos , size ) ;
}
url_fseek ( bc , pos , SEEK_SET ) ;
nut - > written_packet_size = size ;
nut - > packet_start = pos - size ;
}
}
}
static int nut_read_close ( AVFormatContext * s )
static int nut_read_close ( AVFormatContext * s )
{
{
NUTContext * nut = s - > priv_data ;
NUTContext * nut = s - > priv_data ;