[FFmpeg-soc] [soc]: r1168 - rv40/rv40.c
kostya
subversion at mplayerhq.hu
Thu Aug 23 18:05:26 CEST 2007
Author: kostya
Date: Thu Aug 23 18:05:26 2007
New Revision: 1168
Log:
Handle case when slice tail is sent as another slice
Modified:
rv40/rv40.c
Modified: rv40/rv40.c
==============================================================================
--- rv40/rv40.c (original)
+++ rv40/rv40.c Thu Aug 23 18:05:26 2007
@@ -86,6 +86,14 @@ typedef struct SliceInfo{
int height; ///< coded height
}SliceInfo;
+/** Slice information saved for truncated slices */
+typedef struct SavedSliceInfo{
+ uint8_t *data; ///< bitstream data
+ int data_size; ///< data size
+ int bits_used; ///< bits used up to last decoded block
+ int mb_x, mb_y; ///< coordinates of the last decoded block
+}SavedSliceInfo;
+
/** Decoder context */
typedef struct RV40DecContext{
MpegEncContext s;
@@ -113,6 +121,9 @@ typedef struct RV40DecContext{
int chroma_vlc; ///< which VLC set will be used for chroma blocks decoding
int is16; ///< current block has additional 16x16 specific features or not
int dmv[4][2]; ///< differential motion vectors for the current macroblock
+
+ int truncated; ///< flag signalling that slice ended prematurely
+ SavedSliceInfo ssi; ///< data for truncated slice
}RV40DecContext;
static RV40VLC intra_vlcs[NUM_INTRA_TABLES], inter_vlcs[NUM_INTER_TABLES];
@@ -1568,11 +1579,26 @@ static int rv40_decode_slice(RV40DecCont
init_get_bits(&r->s.gb, r->slice_data, r->si.size);
if(rv40_parse_slice_header(r, gb, &r->si) < 0){
- av_log(s->avctx, AV_LOG_ERROR, "Error parsing slice header\n");
- *last = 0;
- 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)){
+ if(!r->truncated){
+ av_log(s->avctx, AV_LOG_ERROR, "Error parsing slice header\n");
+ *last = 0;
+ return -1;
+ }else{
+ r->ssi.data = av_realloc(r->ssi.data, r->ssi.data_size + (size>>3));
+ memcpy(r->ssi.data + r->ssi.data_size, r->slice_data, size >> 3);
+ r->ssi.data_size += size >> 3; // XXX: overflow check?
+ size = r->ssi.data_size * 8;
+ init_get_bits(&r->s.gb, r->ssi.data, r->ssi.data_size * 8);
+ r->si = r->prev_si;
+ skip_bits(gb, r->ssi.bits_used);
+ s->mb_x = r->ssi.mb_x;
+ s->mb_y = r->ssi.mb_y;
+ r->si.start = s->mb_x + s->mb_y * s->mb_width;
+ }
+ }else
+ r->truncated = 0;
+
+ if(!r->truncated && 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) {
@@ -1584,6 +1610,7 @@ static int rv40_decode_slice(RV40DecCont
ff_er_frame_start(s);
s->current_picture_ptr = &s->current_picture;
s->mb_x = s->mb_y = 0;
+ r->truncated = 0;
}
r->si.size = size;
@@ -1597,20 +1624,29 @@ static int rv40_decode_slice(RV40DecCont
r->prev_si = r->si;
mb_pos = s->mb_x + s->mb_y * s->mb_width;
- if(r->block_start != mb_pos){
+ if(!r->truncated && 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);
s->mb_x = r->block_start % s->mb_width;
s->mb_y = r->block_start / s->mb_width;
}
- memset(r->intra_types_hist, -1, r->intra_types_stride * 4 * 2 * sizeof(int));
- s->first_slice_line = 1;
- s->resync_mb_x= s->mb_x;
- s->resync_mb_y= s->mb_y;
+ if(!r->truncated){
+ memset(r->intra_types_hist, -1, r->intra_types_stride * 4 * 2 * sizeof(int));
+ s->first_slice_line = 1;
+ s->resync_mb_x= s->mb_x;
+ s->resync_mb_y= s->mb_y;
+ }
ff_init_block_index(s);
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]);
+ /* save information about decoded position in case of truncated slice */
+ if(r->bits > get_bits_count(gb)){
+ r->ssi.bits_used = get_bits_count(gb);
+ r->ssi.mb_x = s->mb_x;
+ r->ssi.mb_y = s->mb_y;
+ }
+
if(rv40_decode_macroblock(r, r->intra_types + (s->mb_x + 1) * 4) < 0)
break;
if (++s->mb_x == s->mb_width) {
@@ -1624,6 +1660,7 @@ static int rv40_decode_slice(RV40DecCont
if(s->mb_x == s->resync_mb_x)
s->first_slice_line=0;
}
+ r->truncated = 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))
@@ -1631,6 +1668,12 @@ static int rv40_decode_slice(RV40DecCont
if(r->bits > get_bits_count(gb) && show_bits(gb, r->bits-get_bits_count(gb)))
*last = 1;
+ if(r->bits < get_bits_count(gb)){
+ r->truncated = 1;
+ r->ssi.data = av_realloc(r->ssi.data, r->bits >> 3);
+ memcpy(r->ssi.data, r->slice_data, r->bits >> 3);
+ *last = 0;
+ }
return 0;
}
@@ -1943,8 +1986,13 @@ static int rv40_decode_frame(AVCodecCont
r->si.end = s->mb_width * s->mb_height;
if(i+1 < slice_count){
init_get_bits(&s->gb, buf+slice_offset[i+1], (buf_size-slice_offset[i+1])*8);
- rv40_parse_slice_header(r, &r->s.gb, &si);
- if(si.type != -1)
+ if(rv40_parse_slice_header(r, &r->s.gb, &si) < 0){
+ if(i+2 < slice_count)
+ size = slice_offset[i+2] - offset;
+ else
+ size = buf_size - offset;
+ r->si.size = size * 8;
+ }else
r->si.end = si.start;
}
r->slice_data = buf + offset;
@@ -1983,6 +2031,7 @@ static int rv40_decode_end(AVCodecContex
av_freep(&r->intra_types_hist);
r->intra_types = NULL;
av_freep(&r->mb_type);
+ av_freep(&r->ssi.data);
return 0;
}
More information about the FFmpeg-soc
mailing list