summaryrefslogtreecommitdiff
path: root/libavformat/nut.c
diff options
context:
space:
mode:
authorMichael Niedermayer <michaelni@gmx.at>2004-04-06 17:40:17 +0000
committerMichael Niedermayer <michaelni@gmx.at>2004-04-06 17:40:17 +0000
commit465e1dadbef7596a3eb87089a66bb4ecdc26d3c4 (patch)
tree97cb01c13b8b0551f8b20d47063c0ff084e661dc /libavformat/nut.c
parent4568325a1810ea5d829230dc5e9ef0e56c51632f (diff)
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
Diffstat (limited to 'libavformat/nut.c')
-rw-r--r--libavformat/nut.c165
1 files changed, 113 insertions, 52 deletions
diff --git a/libavformat/nut.c b/libavformat/nut.c
index ffb7866081..a975c2c712 100644
--- a/libavformat/nut.c
+++ b/libavformat/nut.c
@@ -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;