Commit 465e1dad authored by Michael Niedermayer's avatar Michael Niedermayer

10l (bytes_left() -> url_feof())

10l (updating LRU delta pts for type 1/2 frames)
ensure that checksumming isnt enabled if its not needed
search for next startcode and then search backward to the next valid frame if an inconsistancy is detected
deal with non-frame startcodes in the middle of the stream

Originally committed as revision 2972 to svn://svn.ffmpeg.org/ffmpeg/trunk
parent 4568325a
......@@ -48,7 +48,6 @@ int init_put_byte(ByteIOContext *s,
s->eof_reached = 0;
s->is_streamed = 0;
s->max_packet_size = 0;
s->checksum_ptr= NULL;
s->update_checksum= NULL;
return 0;
}
......@@ -60,7 +59,7 @@ static void flush_buffer(ByteIOContext *s)
if (s->buf_ptr > s->buffer) {
if (s->write_packet)
s->write_packet(s->opaque, s->buffer, s->buf_ptr - s->buffer);
if(s->checksum_ptr){
if(s->update_checksum){
s->checksum= s->update_checksum(s->checksum, s->checksum_ptr, s->buf_ptr - s->checksum_ptr);
s->checksum_ptr= s->buffer;
}
......@@ -250,7 +249,7 @@ static void fill_buffer(ByteIOContext *s)
if (s->eof_reached)
return;
if(s->checksum_ptr){
if(s->update_checksum){
s->checksum= s->update_checksum(s->checksum, s->checksum_ptr, s->buf_end - s->checksum_ptr);
s->checksum_ptr= s->buffer;
}
......@@ -269,14 +268,16 @@ static void fill_buffer(ByteIOContext *s)
unsigned long get_checksum(ByteIOContext *s){
s->checksum= s->update_checksum(s->checksum, s->checksum_ptr, s->buf_ptr - s->checksum_ptr);
s->checksum_ptr= NULL;
s->update_checksum= NULL;
return s->checksum;
}
void init_checksum(ByteIOContext *s, unsigned long (*update_checksum)(unsigned long c, const uint8_t *p, unsigned int len), unsigned long checksum){
s->update_checksum= update_checksum;
s->checksum= s->update_checksum(checksum, NULL, 0);
s->checksum_ptr= s->buf_ptr;
if(s->update_checksum){
s->checksum= s->update_checksum(checksum, NULL, 0);
s->checksum_ptr= s->buf_ptr;
}
}
/* NOTE: return 0 if EOF, so you cannot use it if EOF handling is
......
......@@ -28,7 +28,6 @@
* - seeking
* - index writing
* - index packet reading support
* - startcode searching for broken streams
*/
//#define DEBUG 1
......@@ -91,6 +90,7 @@ typedef struct {
int64_t last_frame_start[3];
FrameCode frame_code[256];
int stream_count;
uint64_t next_startcode; ///< stores the next startcode if it has alraedy been parsed but the stream isnt seekable
StreamContext *stream;
} 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){
StreamContext *stream= &nut->stream[stream_index];
const int flags=nut->frame_code[frame_code].flags;
stream->last_key_frame= key_frame;
nut->last_frame_start[ frame_type ]= frame_start;
update_lru(stream->lru_pts_delta, pts - stream->last_pts, 3);
update_lru(stream->lru_size , size, 2);
if(frame_type == 0)
update_lru(stream->lru_pts_delta, pts - stream->last_pts, 3);
update_lru(stream->lru_size, size, 2);
stream->last_pts= pts;
if( nut->frame_code[frame_code].flags & FLAG_PTS
&& nut->frame_code[frame_code].flags & FLAG_FULL_PTS)
if((flags & FLAG_PTS) && (flags & FLAG_FULL_PTS))
stream->last_full_pts= pts;
}
......@@ -244,16 +245,11 @@ static void build_frame_code(AVFormatContext *s){
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)
{
uint64_t val = 0;
for(; bytes_left(bc) > 0; )
for(;;)
{
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){
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, update_adler32, 0);
init_checksum(bc, calculate_checksum ? update_adler32 : NULL, 0);
size= get_v(bc);
last_size= get_v(bc);
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);
return -1;
if(prefix_length<8)
return -1;
}
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)
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);
if((state>>56) != 'N')
continue;
......@@ -348,6 +345,7 @@ static uint64_t find_any_startcode(ByteIOContext *bc, int64_t pos){
return state;
}
}
av_log(NULL, AV_LOG_DEBUG, "searched until %lld\n", url_ftell(bc));
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)
{
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
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");
return -1;
}else if(startcode == KEYFRAME_STARTCODE){
url_fseek(bc, -8, SEEK_CUR); //FIXME
nut->next_startcode= startcode;
break;
}else if(startcode != INFO_STARTCODE){
continue;
......@@ -1059,34 +1052,16 @@ static int nut_read_header(AVFormatContext *s, AVFormatParameters *ap)
return 0;
}
static int nut_read_packet(AVFormatContext *s, AVPacket *pkt)
{
NUTContext *nut = s->priv_data;
static int decode_frame(NUTContext *nut, AVPacket *pkt, int frame_code, int frame_type){
AVFormatContext *s= nut->avf;
StreamContext *stream;
ByteIOContext *bc = &s->pb;
int size, frame_code, flags, size_mul, size_lsb, stream_id;
int size, flags, size_mul, size_lsb, stream_id;
int key_frame = 0;
int frame_type= 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;
size_mul= nut->frame_code[frame_code].size_mul;
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){
reset(s);
if(frame_type==2){
get_packetheader(nut, bc, 8+1, 0);
}else{
get_packetheader(nut, bc, 1, 0);
if(get_packetheader(nut, bc, prefix_len, 0) < 0)
return -1;
if(frame_type!=2)
frame_type= 1;
}
}
if(stream_id==-1)
......@@ -1109,6 +1082,8 @@ static int nut_read_packet(AVFormatContext *s, AVPacket *pkt)
return -1;
}
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_KEY_FRAME)
......@@ -1140,7 +1115,12 @@ static int nut_read_packet(AVFormatContext *s, AVPacket *pkt)
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);
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;
update(nut, stream_id, frame_start, frame_type, frame_code, key_frame, size, pts);
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)
{
NUTContext *nut = s->priv_data;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment