[FFmpeg-soc] [soc]: r483 - rv40/rv40.c
kostya
subversion at mplayerhq.hu
Wed Jul 18 19:08:54 CEST 2007
Author: kostya
Date: Wed Jul 18 19:08:54 2007
New Revision: 483
Log:
New slice-based decoding scheme.
Modified:
rv40/rv40.c
Modified: rv40/rv40.c
==============================================================================
--- rv40/rv40.c (original)
+++ rv40/rv40.c Wed Jul 18 19:08:54 2007
@@ -51,6 +51,16 @@ typedef struct RV40VLC{
VLC coefficient; ///< VLCs used for decoding big coefficients
}RV40VLC;
+/** Essential slice information */
+typedef struct SliceInfo{
+ int type; ///< slice type (intra, inter)
+ int size; ///< size of the slice in bits
+ int quant; ///< quantizer used for this slice
+ int vlc_set; ///< VLCs used for this slice
+ int start, end; ///< start and end macroblocks of the slice
+ int header_size; ///< header size in bits
+}SliceInfo;
+
/** Decoder context */
typedef struct RV40DecContext{
MpegEncContext s;
@@ -66,6 +76,9 @@ typedef struct RV40DecContext{
RV40VLC *cur_vlcs; ///< VLC set used for current frame decoding
int bits; ///< slice size in bits
H264PredContext h; ///< functions for 4x4 and 16x16 intra block prediction
+ SliceInfo prev_si; ///< info for the saved slice
+ uint8_t *slice_data; ///< saved slice data
+ int has_slice; ///< has previously saved slice
}RV40DecContext;
static RV40VLC intra_vlcs[NUM_INTRA_TABLES], inter_vlcs[NUM_INTER_TABLES];
@@ -466,18 +479,19 @@ static void rv40_parse_picture_size(GetB
*h = get_dimension(gb, rv40_standard_heights, rv40_standard_heights2);
}
-static int rv40_parse_slice_header(RV40DecContext *r, GetBitContext *gb)
+static int rv40_parse_slice_header(RV40DecContext *r, GetBitContext *gb, SliceInfo *si)
{
int t, mb_bits;
int w, h;
+ memset(si, 0, sizeof(SliceInfo));
if(get_bits1(gb))
return -1;
- r->ptype = get_bits(gb, 2);
- r->quant = get_bits(gb, 5);
+ si->type = get_bits(gb, 2);
+ si->quant = get_bits(gb, 5);
if(get_bits(gb, 2))
return -1;
- r->vlc_set = get_bits(gb, 2) + 1;
+ si->vlc_set = get_bits(gb, 2) + 1;
if(get_bits1(gb))
return -1;
t = get_bits(gb, 13); /// ???
@@ -485,7 +499,8 @@ static int rv40_parse_slice_header(RV40D
// r->s.avctx->coded_width = w;
// r->s.avctx->coded_height = h;
mb_bits = av_log2((w + 7) >> 3) + av_log2((h + 7) >> 3);
- r->block_start = get_bits(gb, mb_bits);
+ si->start = get_bits(gb, mb_bits);
+ si->header_size = get_bits_count(gb);
return 0;
}
@@ -712,6 +727,17 @@ static int rv40_decode_slice(RV40DecCont
MpegEncContext *s = &r->s;
int mb_pos;
+ init_get_bits(&r->s.gb, r->slice_data, r->prev_si.size);
+ skip_bits(&r->s.gb, r->prev_si.header_size);
+ if ((s->mb_x == 0 && s->mb_y == 0) || s->current_picture_ptr==NULL) {
+ s->current_picture_ptr = (AVFrame*)&s->picture[ff_find_unused_picture(s, 0)];
+ if(MPV_frame_start(s, s->avctx) < 0)
+ return -1;
+ ff_er_frame_start(s);
+ s->current_picture_ptr = &s->current_picture;
+ }
+if(r->prev_si.type)return 0;
+
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);
@@ -723,7 +749,7 @@ 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(!check_slice_end(r, &s->gb, s)) {
+ while(s->mb_num_left--) {
ff_update_block_index(s);
s->dsp.clear_blocks(s->block[0]);
@@ -760,7 +786,7 @@ static int rv40_decode_init(AVCodecConte
MPV_decode_defaults(s);
s->avctx= avctx;
- s->out_format = FMT_H264;
+ s->out_format = FMT_H263;
s->codec_id= avctx->codec_id;
s->width = avctx->width;
@@ -796,6 +822,7 @@ static int rv40_decode_frame(AVCodecCont
RV40DecContext *r = avctx->priv_data;
MpegEncContext *s = &r->s;
AVFrame *pict = data;
+ SliceInfo si;
/* no supplementary picture */
if (buf_size == 0) {
@@ -803,25 +830,23 @@ static int rv40_decode_frame(AVCodecCont
}
init_get_bits(&s->gb, buf, buf_size*8);
- r->bits = buf_size * 8;
- rv40_parse_slice_header(r, &r->s.gb);
- s->pict_type = r->ptype+1;
- r->cur_vlcs = &intra_vlcs[r->vlc_set];
+ rv40_parse_slice_header(r, &r->s.gb, &si);
+ si.size = buf_size * 8;
+ si.end = s->mb_width * s->mb_height;
-if(s->pict_type != I_TYPE)return -1;
- if ((s->mb_x == 0 && s->mb_y == 0) || s->current_picture_ptr==NULL) {
- if(s->current_picture_ptr){ //FIXME write parser so we always have complete frames?
- ff_er_frame_end(s);
- MPV_frame_end(s);
- s->mb_x= s->mb_y = s->resync_mb_x = s->resync_mb_y= 0;
- }
- if(MPV_frame_start(s, avctx) < 0)
- return -1;
- ff_er_frame_start(s);
+ if(si.start > r->prev_si.start && si.type == r->prev_si.type) r->prev_si.end = si.start;
+ if(r->has_slice){
+ //XXX: Take it directly from slice info
+ r->cur_vlcs = &intra_vlcs[r->prev_si.vlc_set];
+ r->quant = r->prev_si.quant;
+ r->bits = r->prev_si.size;
+ r->block_start = r->prev_si.start;
+ s->mb_num_left = r->prev_si.end - r->prev_si.start;
+ s->pict_type = r->prev_si.type ? P_TYPE : I_TYPE;
+ rv40_decode_slice(r);
}
- rv40_decode_slice(r);
- if(s->current_picture_ptr != NULL && s->mb_y>=s->mb_height){
+ if(r->has_slice && (si.start < r->prev_si.start || si.type != r->prev_si.type)){ // output complete frame
ff_er_frame_end(s);
MPV_frame_end(s);
if (s->pict_type == B_TYPE || s->low_delay) {
@@ -837,6 +862,11 @@ if(s->pict_type != I_TYPE)return -1;
s->current_picture_ptr= NULL; //so we can detect if frame_end wasnt called (find some nicer solution...)
s->mb_x = s->mb_y = 0;
}
+ //save slice for future decoding
+ r->slice_data = av_realloc(r->slice_data, buf_size + FF_INPUT_BUFFER_PADDING_SIZE);
+ memcpy(r->slice_data, buf, buf_size);
+ r->prev_si = si;
+ r->has_slice = 1;
return buf_size;
}
@@ -849,6 +879,7 @@ static int rv40_decode_end(AVCodecContex
av_freep(&r->intra_types_hist);
r->intra_types = NULL;
+ av_freep(&r->slice_data);
return 0;
}
More information about the FFmpeg-soc
mailing list