rv30.c 10.3 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
/*
 * RV30 decoder
 * Copyright (c) 2007 Konstantin Shishkov
 *
 * This file is part of FFmpeg.
 *
 * FFmpeg is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * FFmpeg is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with FFmpeg; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 */

/**
23
 * @file
24
 * RV30 decoder
25 26 27 28 29
 */

#include "avcodec.h"
#include "dsputil.h"
#include "mpegvideo.h"
30
#include "golomb.h"
31 32 33 34 35 36 37 38 39 40

#include "rv34.h"
#include "rv30data.h"


static int rv30_parse_slice_header(RV34DecContext *r, GetBitContext *gb, SliceInfo *si)
{
    int mb_bits;
    int w = r->s.width, h = r->s.height;
    int mb_size;
41
    int rpr;
42 43

    memset(si, 0, sizeof(SliceInfo));
44 45
    if(get_bits(gb, 3))
        return -1;
46 47 48 49 50 51
    si->type = get_bits(gb, 2);
    if(si->type == 1) si->type = 0;
    if(get_bits1(gb))
        return -1;
    si->quant = get_bits(gb, 5);
    skip_bits1(gb);
52
    si->pts = get_bits(gb, 13);
53
    rpr = get_bits(gb, r->rpr);
54 55 56 57 58
    if (r->s.avctx->extradata_size < 8 + rpr*2) {
        av_log(r->s.avctx, AV_LOG_WARNING,
               "Extradata does not contain selected resolution\n");
        rpr = 0;
    }
59 60 61
    if(rpr){
        w = r->s.avctx->extradata[6 + rpr*2] << 2;
        h = r->s.avctx->extradata[7 + rpr*2] << 2;
62
    }
63 64
    si->width  = w;
    si->height = h;
65 66 67 68 69 70 71 72
    mb_size = ((w + 15) >> 4) * ((h + 15) >> 4);
    mb_bits = ff_rv34_get_start_offset(gb, mb_size);
    si->start = get_bits(gb, mb_bits);
    skip_bits1(gb);
    return 0;
}

/**
73
 * Decode 4x4 intra types array.
74
 */
75
static int rv30_decode_intra_types(RV34DecContext *r, GetBitContext *gb, int8_t *dst)
76 77 78
{
    int i, j, k;

79
    for(i = 0; i < 4; i++, dst += r->intra_types_stride - 4){
80
        for(j = 0; j < 4; j+= 2){
81
            unsigned code = svq3_get_ue_golomb(gb) << 1;
82
            if (code > 80U*2U) {
83 84 85 86
                av_log(r->s.avctx, AV_LOG_ERROR, "Incorrect intra prediction code\n");
                return -1;
            }
            for(k = 0; k < 2; k++){
87
                int A = dst[-r->intra_types_stride] + 1;
88 89 90 91 92 93 94 95 96 97 98 99 100
                int B = dst[-1] + 1;
                *dst++ = rv30_itype_from_context[A * 90 + B * 9 + rv30_itype_code[code + k]];
                if(dst[-1] == 9){
                    av_log(r->s.avctx, AV_LOG_ERROR, "Incorrect intra prediction mode\n");
                    return -1;
                }
            }
        }
    }
    return 0;
}

/**
101
 * Decode macroblock information.
102 103 104 105 106 107 108
 */
static int rv30_decode_mb_info(RV34DecContext *r)
{
    static const int rv30_p_types[6] = { RV34_MB_SKIP, RV34_MB_P_16x16, RV34_MB_P_8x8, -1, RV34_MB_TYPE_INTRA, RV34_MB_TYPE_INTRA16x16 };
    static const int rv30_b_types[6] = { RV34_MB_SKIP, RV34_MB_B_DIRECT, RV34_MB_B_FORWARD, RV34_MB_B_BACKWARD, RV34_MB_TYPE_INTRA, RV34_MB_TYPE_INTRA16x16 };
    MpegEncContext *s = &r->s;
    GetBitContext *gb = &s->gb;
109
    unsigned code     = svq3_get_ue_golomb(gb);
110

111
    if (code > 11) {
112 113 114 115 116 117 118
        av_log(s->avctx, AV_LOG_ERROR, "Incorrect MB type code\n");
        return -1;
    }
    if(code > 5){
        av_log(s->avctx, AV_LOG_ERROR, "dquant needed\n");
        code -= 6;
    }
119
    if(s->pict_type != AV_PICTURE_TYPE_B)
120 121 122 123 124
        return rv30_p_types[code];
    else
        return rv30_b_types[code];
}

Kostya Shishkov's avatar
Kostya Shishkov committed
125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149
static inline void rv30_weak_loop_filter(uint8_t *src, const int step,
                                         const int stride, const int lim)
{
    uint8_t *cm = ff_cropTbl + MAX_NEG_CROP;
    int i, diff;

    for(i = 0; i < 4; i++){
        diff = ((src[-2*step] - src[1*step]) - (src[-1*step] - src[0*step])*4) >> 3;
        diff = av_clip(diff, -lim, lim);
        src[-1*step] = cm[src[-1*step] + diff];
        src[ 0*step] = cm[src[ 0*step] - diff];
        src += stride;
    }
}

static void rv30_loop_filter(RV34DecContext *r, int row)
{
    MpegEncContext *s = &r->s;
    int mb_pos, mb_x;
    int i, j, k;
    uint8_t *Y, *C;
    int loc_lim, cur_lim, left_lim = 0, top_lim = 0;

    mb_pos = row * s->mb_stride;
    for(mb_x = 0; mb_x < s->mb_width; mb_x++, mb_pos++){
150
        int mbtype = s->current_picture_ptr->f.mb_type[mb_pos];
Kostya Shishkov's avatar
Kostya Shishkov committed
151 152 153 154 155 156 157 158 159 160 161
        if(IS_INTRA(mbtype) || IS_SEPARATE_DC(mbtype))
            r->deblock_coefs[mb_pos] = 0xFFFF;
        if(IS_INTRA(mbtype))
            r->cbp_chroma[mb_pos] = 0xFF;
    }

    /* all vertical edges are filtered first
     * and horizontal edges are filtered on the next iteration
     */
    mb_pos = row * s->mb_stride;
    for(mb_x = 0; mb_x < s->mb_width; mb_x++, mb_pos++){
162
        cur_lim = rv30_loop_filt_lim[s->current_picture_ptr->f.qscale_table[mb_pos]];
Kostya Shishkov's avatar
Kostya Shishkov committed
163
        if(mb_x)
164
            left_lim = rv30_loop_filt_lim[s->current_picture_ptr->f.qscale_table[mb_pos - 1]];
Kostya Shishkov's avatar
Kostya Shishkov committed
165
        for(j = 0; j < 16; j += 4){
166
            Y = s->current_picture_ptr->f.data[0] + mb_x*16 + (row*16 + j) * s->linesize + 4 * !mb_x;
Kostya Shishkov's avatar
Kostya Shishkov committed
167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185
            for(i = !mb_x; i < 4; i++, Y += 4){
                int ij = i + j;
                loc_lim = 0;
                if(r->deblock_coefs[mb_pos] & (1 << ij))
                    loc_lim = cur_lim;
                else if(!i && r->deblock_coefs[mb_pos - 1] & (1 << (ij + 3)))
                    loc_lim = left_lim;
                else if( i && r->deblock_coefs[mb_pos]     & (1 << (ij - 1)))
                    loc_lim = cur_lim;
                if(loc_lim)
                    rv30_weak_loop_filter(Y, 1, s->linesize, loc_lim);
            }
        }
        for(k = 0; k < 2; k++){
            int cur_cbp, left_cbp = 0;
            cur_cbp = (r->cbp_chroma[mb_pos] >> (k*4)) & 0xF;
            if(mb_x)
                left_cbp = (r->cbp_chroma[mb_pos - 1] >> (k*4)) & 0xF;
            for(j = 0; j < 8; j += 4){
186
                C = s->current_picture_ptr->f.data[k + 1] + mb_x*8 + (row*8 + j) * s->uvlinesize + 4 * !mb_x;
Kostya Shishkov's avatar
Kostya Shishkov committed
187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203
                for(i = !mb_x; i < 2; i++, C += 4){
                    int ij = i + (j >> 1);
                    loc_lim = 0;
                    if(cur_cbp && (1 << ij))
                        loc_lim = cur_lim;
                    else if(!i && left_cbp & (1 << (ij + 1)))
                        loc_lim = left_lim;
                    else if( i && cur_cbp  & (1 << (ij - 1)))
                        loc_lim = cur_lim;
                    if(loc_lim)
                        rv30_weak_loop_filter(C, 1, s->uvlinesize, loc_lim);
                }
            }
        }
    }
    mb_pos = row * s->mb_stride;
    for(mb_x = 0; mb_x < s->mb_width; mb_x++, mb_pos++){
204
        cur_lim = rv30_loop_filt_lim[s->current_picture_ptr->f.qscale_table[mb_pos]];
Kostya Shishkov's avatar
Kostya Shishkov committed
205
        if(row)
206
            top_lim = rv30_loop_filt_lim[s->current_picture_ptr->f.qscale_table[mb_pos - s->mb_stride]];
Kostya Shishkov's avatar
Kostya Shishkov committed
207
        for(j = 4*!row; j < 16; j += 4){
208
            Y = s->current_picture_ptr->f.data[0] + mb_x*16 + (row*16 + j) * s->linesize;
Kostya Shishkov's avatar
Kostya Shishkov committed
209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227
            for(i = 0; i < 4; i++, Y += 4){
                int ij = i + j;
                loc_lim = 0;
                if(r->deblock_coefs[mb_pos] & (1 << ij))
                    loc_lim = cur_lim;
                else if(!j && r->deblock_coefs[mb_pos - s->mb_stride] & (1 << (ij + 12)))
                    loc_lim = top_lim;
                else if( j && r->deblock_coefs[mb_pos]                & (1 << (ij - 4)))
                    loc_lim = cur_lim;
                if(loc_lim)
                    rv30_weak_loop_filter(Y, s->linesize, 1, loc_lim);
            }
        }
        for(k = 0; k < 2; k++){
            int cur_cbp, top_cbp = 0;
            cur_cbp = (r->cbp_chroma[mb_pos] >> (k*4)) & 0xF;
            if(row)
                top_cbp = (r->cbp_chroma[mb_pos - s->mb_stride] >> (k*4)) & 0xF;
            for(j = 4*!row; j < 8; j += 4){
228
                C = s->current_picture_ptr->f.data[k+1] + mb_x*8 + (row*8 + j) * s->uvlinesize;
Kostya Shishkov's avatar
Kostya Shishkov committed
229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245
                for(i = 0; i < 2; i++, C += 4){
                    int ij = i + (j >> 1);
                    loc_lim = 0;
                    if(r->cbp_chroma[mb_pos] && (1 << ij))
                        loc_lim = cur_lim;
                    else if(!j && top_cbp & (1 << (ij + 2)))
                        loc_lim = top_lim;
                    else if( j && cur_cbp & (1 << (ij - 2)))
                        loc_lim = cur_lim;
                    if(loc_lim)
                        rv30_weak_loop_filter(C, s->uvlinesize, 1, loc_lim);
                }
            }
        }
    }
}

246
/**
247
 * Initialize decoder.
248
 */
249
static av_cold int rv30_decode_init(AVCodecContext *avctx)
250 251 252 253 254 255
{
    RV34DecContext *r = avctx->priv_data;

    r->rv30 = 1;
    ff_rv34_decode_init(avctx);
    if(avctx->extradata_size < 2){
256
        av_log(avctx, AV_LOG_ERROR, "Extradata is too small.\n");
257 258 259 260
        return -1;
    }
    r->rpr = (avctx->extradata[1] & 7) >> 1;
    r->rpr = FFMIN(r->rpr + 1, 3);
261 262 263 264
    if(avctx->extradata_size - 8 < (r->rpr - 1) * 2){
        av_log(avctx, AV_LOG_ERROR, "Insufficient extradata - need at least %d bytes, got %d\n",
               6 + r->rpr * 2, avctx->extradata_size);
    }
265 266 267
    r->parse_slice_header = rv30_parse_slice_header;
    r->decode_intra_types = rv30_decode_intra_types;
    r->decode_mb_info     = rv30_decode_mb_info;
Kostya Shishkov's avatar
Kostya Shishkov committed
268
    r->loop_filter        = rv30_loop_filter;
269 270 271 272 273
    r->luma_dc_quant_i = rv30_luma_dc_quant;
    r->luma_dc_quant_p = rv30_luma_dc_quant;
    return 0;
}

274
AVCodec ff_rv30_decoder = {
275 276
    .name                  = "rv30",
    .type                  = AVMEDIA_TYPE_VIDEO,
277
    .id                    = AV_CODEC_ID_RV30,
278 279 280 281 282 283 284 285 286
    .priv_data_size        = sizeof(RV34DecContext),
    .init                  = rv30_decode_init,
    .close                 = ff_rv34_decode_end,
    .decode                = ff_rv34_decode_frame,
    .capabilities          = CODEC_CAP_DR1 | CODEC_CAP_DELAY |
                             CODEC_CAP_FRAME_THREADS,
    .flush                 = ff_mpeg_flush,
    .long_name             = NULL_IF_CONFIG_SMALL("RealVideo 3.0"),
    .pix_fmts              = ff_pixfmt_list_420,
287 288
    .init_thread_copy      = ONLY_IF_THREADS_ENABLED(ff_rv34_decode_init_thread_copy),
    .update_thread_context = ONLY_IF_THREADS_ENABLED(ff_rv34_decode_update_thread_context),
289
};