[FFmpeg-soc] [soc]: r1149 - rv40/rv40.c
kostya
subversion at mplayerhq.hu
Wed Aug 22 13:44:29 CEST 2007
Author: kostya
Date: Wed Aug 22 13:44:29 2007
New Revision: 1149
Log:
Yet another slice decoding approach.
Now slices may be decoded one-by-one like in rv10.c,
without saving previous slice or combining slices
together.
Modified:
rv40/rv40.c
Modified: rv40/rv40.c
==============================================================================
--- rv40/rv40.c (original)
+++ rv40/rv40.c Wed Aug 22 13:44:29 2007
@@ -1558,13 +1558,22 @@ static int check_slice_end(RV40DecContex
return 0;
}
-static int rv40_decode_slice(RV40DecContext *r)
+static int rv40_decode_slice(RV40DecContext *r, int size, int end, int *last)
{
MpegEncContext *s = &r->s;
+ GetBitContext *gb = &s->gb;
int mb_pos;
+ int mb_w = s->mb_width, mb_h = s->mb_height;
+ *last = 1;
init_get_bits(&r->s.gb, r->slice_data, r->si.size);
- skip_bits(&r->s.gb, r->si.header_size);
+ if(rv40_parse_slice_header(r, gb, &r->si) < 0){
+ av_log(s->avctx, AV_LOG_ERROR, "Error parsing slice header\n");
+ return -1;
+ }
+ if(r->prev_si.type != -1 && (r->si.type != r->prev_si.type || r->si.start <= r->prev_si.start || r->si.width != r->prev_si.width || r->si.height != r->prev_si.height)){
+ av_log(s->avctx, AV_LOG_ERROR, "Slice headers mismatch\n");
+ }
if ((s->mb_x == 0 && s->mb_y == 0) || s->current_picture_ptr==NULL) {
if(r->si.width) s->avctx->coded_width = r->si.width;
if(r->si.height)s->avctx->coded_height = r->si.height;
@@ -1576,12 +1585,16 @@ static int rv40_decode_slice(RV40DecCont
s->mb_x = s->mb_y = 0;
}
+ r->si.size = size;
+ r->si.end = s->mb_width * s->mb_height;
r->quant = r->si.quant;
r->bits = r->si.size;
r->block_start = r->si.start;
s->mb_num_left = r->si.end - r->si.start;
r->skip_blocks = 0;
+ r->prev_si = r->si;
+
mb_pos = s->mb_x + s->mb_y * s->mb_width;
if(r->block_start != mb_pos){
av_log(s->avctx, AV_LOG_ERROR, "Slice indicates MB offset %d, got %d\n", r->block_start, mb_pos);
@@ -1593,11 +1606,12 @@ static int rv40_decode_slice(RV40DecCont
s->resync_mb_x= s->mb_x;
s->resync_mb_y= s->mb_y;
ff_init_block_index(s);
- while(s->mb_num_left-- && s->mb_y < s->mb_height) {
+ while(!check_slice_end(r, s) && s->mb_num_left-- && s->mb_y < s->mb_height) {
ff_update_block_index(s);
s->dsp.clear_blocks(s->block[0]);
- rv40_decode_macroblock(r, r->intra_types + (s->mb_x + 1) * 4);
+ if(rv40_decode_macroblock(r, r->intra_types + (s->mb_x + 1) * 4) < 0)
+ break;
if (++s->mb_x == s->mb_width) {
s->mb_x = 0;
s->mb_y++;
@@ -1610,6 +1624,14 @@ static int rv40_decode_slice(RV40DecCont
s->first_slice_line=0;
}
ff_er_add_slice(s, s->resync_mb_x, s->resync_mb_y, s->mb_x-1, s->mb_y, AC_END|DC_END|MV_END);
+ *last = 0;
+ if(s->mb_y >= s->mb_height || r->bits < get_bits_count(gb))
+ *last = 1;
+ if(r->bits > get_bits_count(gb) && show_bits(gb, r->bits-get_bits_count(gb)))
+ *last = 1;
+ // XXX: this is needed to handle incorrectly parsed B-frames
+ if(r->bits == get_bits_count(gb) && r->si.type == 3 && r->slice_data[r->bits/8 - 1]&1)
+ *last = 1;
return 0;
}
@@ -1849,6 +1871,7 @@ static int rv40_decode_init(AVCodecConte
rv40_init_tables();
tables_done = 1;
}
+ r->prev_si.type = -1;
return 0;
}
@@ -1887,6 +1910,8 @@ static int rv40_decode_frame(AVCodecCont
SliceInfo si;
int i;
int slice_count, *slice_offset;
+ int zero_offset = {0};
+ int last;
/* no supplementary picture */
if (buf_size == 0) {
@@ -1903,10 +1928,10 @@ static int rv40_decode_frame(AVCodecCont
slice_count = avctx->slice_count;
slice_offset = avctx->slice_offset;
}else{
- slice_offset = find_slice_offsets(buf, buf_size, &slice_count);
+ slice_count = 1;
+ slice_offset = &zero_offset;
}
- s->current_picture_ptr= NULL;
for(i=0; i<slice_count; i++){
int offset= slice_offset[i];
int size;
@@ -1916,9 +1941,6 @@ static int rv40_decode_frame(AVCodecCont
else
size= slice_offset[i+1] - offset;
- init_get_bits(&s->gb, buf + offset, size * 8);
- rv40_parse_slice_header(r, &r->s.gb, &r->si);
- if(r->si.type == -1) continue;
r->si.size = size * 8;
r->si.end = s->mb_width * s->mb_height;
if(i+1 < slice_count){
@@ -1928,17 +1950,15 @@ static int rv40_decode_frame(AVCodecCont
r->si.end = si.start;
}
r->slice_data = buf + offset;
- rv40_decode_slice(r);
+ rv40_decode_slice(r, r->si.size, r->si.end, &last);
+ if(last)
+ break;
s->mb_num_left = r->si.end - r->si.start;
//rv40_postprocess(r);
}
- if(!avctx->slice_count)
- av_free(slice_offset);
- if(!s->current_picture_ptr){
- av_log(avctx, AV_LOG_ERROR, "No decodable slices\n");
- return -1;
- }
+ if(s->mb_y >= s->mb_height || last){
+ r->prev_si.type = -1;
ff_er_frame_end(s);
MPV_frame_end(s);
if (s->pict_type == B_TYPE || s->low_delay) {
@@ -1952,6 +1972,7 @@ static int rv40_decode_frame(AVCodecCont
ff_print_debug_info(s, pict);
}
s->current_picture_ptr= NULL; //so we can detect if frame_end wasnt called (find some nicer solution...)
+ }
return buf_size;
}
More information about the FFmpeg-soc
mailing list