xref: /third_party/ffmpeg/libavcodec/rv30.c (revision cabdff1a)
1cabdff1aSopenharmony_ci/*
2cabdff1aSopenharmony_ci * RV30 decoder
3cabdff1aSopenharmony_ci * Copyright (c) 2007 Konstantin Shishkov
4cabdff1aSopenharmony_ci *
5cabdff1aSopenharmony_ci * This file is part of FFmpeg.
6cabdff1aSopenharmony_ci *
7cabdff1aSopenharmony_ci * FFmpeg is free software; you can redistribute it and/or
8cabdff1aSopenharmony_ci * modify it under the terms of the GNU Lesser General Public
9cabdff1aSopenharmony_ci * License as published by the Free Software Foundation; either
10cabdff1aSopenharmony_ci * version 2.1 of the License, or (at your option) any later version.
11cabdff1aSopenharmony_ci *
12cabdff1aSopenharmony_ci * FFmpeg is distributed in the hope that it will be useful,
13cabdff1aSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of
14cabdff1aSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15cabdff1aSopenharmony_ci * Lesser General Public License for more details.
16cabdff1aSopenharmony_ci *
17cabdff1aSopenharmony_ci * You should have received a copy of the GNU Lesser General Public
18cabdff1aSopenharmony_ci * License along with FFmpeg; if not, write to the Free Software
19cabdff1aSopenharmony_ci * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20cabdff1aSopenharmony_ci */
21cabdff1aSopenharmony_ci
22cabdff1aSopenharmony_ci/**
23cabdff1aSopenharmony_ci * @file
24cabdff1aSopenharmony_ci * RV30 decoder
25cabdff1aSopenharmony_ci */
26cabdff1aSopenharmony_ci
27cabdff1aSopenharmony_ci#include "avcodec.h"
28cabdff1aSopenharmony_ci#include "codec_internal.h"
29cabdff1aSopenharmony_ci#include "mpegutils.h"
30cabdff1aSopenharmony_ci#include "mpegvideo.h"
31cabdff1aSopenharmony_ci#include "mpegvideodec.h"
32cabdff1aSopenharmony_ci#include "golomb.h"
33cabdff1aSopenharmony_ci
34cabdff1aSopenharmony_ci#include "rv34.h"
35cabdff1aSopenharmony_ci#include "rv30data.h"
36cabdff1aSopenharmony_ci
37cabdff1aSopenharmony_ci
38cabdff1aSopenharmony_cistatic int rv30_parse_slice_header(RV34DecContext *r, GetBitContext *gb, SliceInfo *si)
39cabdff1aSopenharmony_ci{
40cabdff1aSopenharmony_ci    AVCodecContext *avctx = r->s.avctx;
41cabdff1aSopenharmony_ci    int mb_bits;
42cabdff1aSopenharmony_ci    int w = r->s.width, h = r->s.height;
43cabdff1aSopenharmony_ci    int mb_size;
44cabdff1aSopenharmony_ci    int rpr;
45cabdff1aSopenharmony_ci
46cabdff1aSopenharmony_ci    memset(si, 0, sizeof(SliceInfo));
47cabdff1aSopenharmony_ci    if(get_bits(gb, 3))
48cabdff1aSopenharmony_ci        return -1;
49cabdff1aSopenharmony_ci    si->type = get_bits(gb, 2);
50cabdff1aSopenharmony_ci    if(si->type == 1) si->type = 0;
51cabdff1aSopenharmony_ci    if(get_bits1(gb))
52cabdff1aSopenharmony_ci        return -1;
53cabdff1aSopenharmony_ci    si->quant = get_bits(gb, 5);
54cabdff1aSopenharmony_ci    skip_bits1(gb);
55cabdff1aSopenharmony_ci    si->pts = get_bits(gb, 13);
56cabdff1aSopenharmony_ci    rpr = get_bits(gb, av_log2(r->max_rpr) + 1);
57cabdff1aSopenharmony_ci    if(rpr){
58cabdff1aSopenharmony_ci        if (rpr > r->max_rpr) {
59cabdff1aSopenharmony_ci            av_log(avctx, AV_LOG_ERROR, "rpr too large\n");
60cabdff1aSopenharmony_ci            return AVERROR_INVALIDDATA;
61cabdff1aSopenharmony_ci        }
62cabdff1aSopenharmony_ci
63cabdff1aSopenharmony_ci        if (avctx->extradata_size < rpr * 2 + 8) {
64cabdff1aSopenharmony_ci            av_log(avctx, AV_LOG_ERROR,
65cabdff1aSopenharmony_ci                   "Insufficient extradata - need at least %d bytes, got %d\n",
66cabdff1aSopenharmony_ci                   8 + rpr * 2, avctx->extradata_size);
67cabdff1aSopenharmony_ci            return AVERROR(EINVAL);
68cabdff1aSopenharmony_ci        }
69cabdff1aSopenharmony_ci
70cabdff1aSopenharmony_ci        w = r->s.avctx->extradata[6 + rpr*2] << 2;
71cabdff1aSopenharmony_ci        h = r->s.avctx->extradata[7 + rpr*2] << 2;
72cabdff1aSopenharmony_ci    } else {
73cabdff1aSopenharmony_ci        w = r->orig_width;
74cabdff1aSopenharmony_ci        h = r->orig_height;
75cabdff1aSopenharmony_ci    }
76cabdff1aSopenharmony_ci    si->width  = w;
77cabdff1aSopenharmony_ci    si->height = h;
78cabdff1aSopenharmony_ci    mb_size = ((w + 15) >> 4) * ((h + 15) >> 4);
79cabdff1aSopenharmony_ci    mb_bits = ff_rv34_get_start_offset(gb, mb_size);
80cabdff1aSopenharmony_ci    si->start = get_bits(gb, mb_bits);
81cabdff1aSopenharmony_ci    skip_bits1(gb);
82cabdff1aSopenharmony_ci    return 0;
83cabdff1aSopenharmony_ci}
84cabdff1aSopenharmony_ci
85cabdff1aSopenharmony_ci/**
86cabdff1aSopenharmony_ci * Decode 4x4 intra types array.
87cabdff1aSopenharmony_ci */
88cabdff1aSopenharmony_cistatic int rv30_decode_intra_types(RV34DecContext *r, GetBitContext *gb, int8_t *dst)
89cabdff1aSopenharmony_ci{
90cabdff1aSopenharmony_ci    int i, j, k;
91cabdff1aSopenharmony_ci
92cabdff1aSopenharmony_ci    for(i = 0; i < 4; i++, dst += r->intra_types_stride - 4){
93cabdff1aSopenharmony_ci        for(j = 0; j < 4; j+= 2){
94cabdff1aSopenharmony_ci            unsigned code = get_interleaved_ue_golomb(gb) << 1;
95cabdff1aSopenharmony_ci            if (code > 80U*2U) {
96cabdff1aSopenharmony_ci                av_log(r->s.avctx, AV_LOG_ERROR, "Incorrect intra prediction code\n");
97cabdff1aSopenharmony_ci                return -1;
98cabdff1aSopenharmony_ci            }
99cabdff1aSopenharmony_ci            for(k = 0; k < 2; k++){
100cabdff1aSopenharmony_ci                int A = dst[-r->intra_types_stride] + 1;
101cabdff1aSopenharmony_ci                int B = dst[-1] + 1;
102cabdff1aSopenharmony_ci                *dst++ = rv30_itype_from_context[A * 90 + B * 9 + rv30_itype_code[code + k]];
103cabdff1aSopenharmony_ci                if(dst[-1] == 9){
104cabdff1aSopenharmony_ci                    av_log(r->s.avctx, AV_LOG_ERROR, "Incorrect intra prediction mode\n");
105cabdff1aSopenharmony_ci                    return -1;
106cabdff1aSopenharmony_ci                }
107cabdff1aSopenharmony_ci            }
108cabdff1aSopenharmony_ci        }
109cabdff1aSopenharmony_ci    }
110cabdff1aSopenharmony_ci    return 0;
111cabdff1aSopenharmony_ci}
112cabdff1aSopenharmony_ci
113cabdff1aSopenharmony_ci/**
114cabdff1aSopenharmony_ci * Decode macroblock information.
115cabdff1aSopenharmony_ci */
116cabdff1aSopenharmony_cistatic int rv30_decode_mb_info(RV34DecContext *r)
117cabdff1aSopenharmony_ci{
118cabdff1aSopenharmony_ci    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 };
119cabdff1aSopenharmony_ci    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 };
120cabdff1aSopenharmony_ci    MpegEncContext *s = &r->s;
121cabdff1aSopenharmony_ci    GetBitContext *gb = &s->gb;
122cabdff1aSopenharmony_ci    unsigned code = get_interleaved_ue_golomb(gb);
123cabdff1aSopenharmony_ci
124cabdff1aSopenharmony_ci    if (code > 11) {
125cabdff1aSopenharmony_ci        av_log(s->avctx, AV_LOG_ERROR, "Incorrect MB type code\n");
126cabdff1aSopenharmony_ci        return -1;
127cabdff1aSopenharmony_ci    }
128cabdff1aSopenharmony_ci    if(code > 5){
129cabdff1aSopenharmony_ci        av_log(s->avctx, AV_LOG_ERROR, "dquant needed\n");
130cabdff1aSopenharmony_ci        code -= 6;
131cabdff1aSopenharmony_ci    }
132cabdff1aSopenharmony_ci    if(s->pict_type != AV_PICTURE_TYPE_B)
133cabdff1aSopenharmony_ci        return rv30_p_types[code];
134cabdff1aSopenharmony_ci    else
135cabdff1aSopenharmony_ci        return rv30_b_types[code];
136cabdff1aSopenharmony_ci}
137cabdff1aSopenharmony_ci
138cabdff1aSopenharmony_cistatic inline void rv30_weak_loop_filter(uint8_t *src, const int step,
139cabdff1aSopenharmony_ci                                         const int stride, const int lim)
140cabdff1aSopenharmony_ci{
141cabdff1aSopenharmony_ci    const uint8_t *cm = ff_crop_tab + MAX_NEG_CROP;
142cabdff1aSopenharmony_ci    int i, diff;
143cabdff1aSopenharmony_ci
144cabdff1aSopenharmony_ci    for(i = 0; i < 4; i++){
145cabdff1aSopenharmony_ci        diff = ((src[-2*step] - src[1*step]) - (src[-1*step] - src[0*step])*4) >> 3;
146cabdff1aSopenharmony_ci        diff = av_clip(diff, -lim, lim);
147cabdff1aSopenharmony_ci        src[-1*step] = cm[src[-1*step] + diff];
148cabdff1aSopenharmony_ci        src[ 0*step] = cm[src[ 0*step] - diff];
149cabdff1aSopenharmony_ci        src += stride;
150cabdff1aSopenharmony_ci    }
151cabdff1aSopenharmony_ci}
152cabdff1aSopenharmony_ci
153cabdff1aSopenharmony_cistatic void rv30_loop_filter(RV34DecContext *r, int row)
154cabdff1aSopenharmony_ci{
155cabdff1aSopenharmony_ci    MpegEncContext *s = &r->s;
156cabdff1aSopenharmony_ci    int mb_pos, mb_x;
157cabdff1aSopenharmony_ci    int i, j, k;
158cabdff1aSopenharmony_ci    uint8_t *Y, *C;
159cabdff1aSopenharmony_ci    int loc_lim, cur_lim, left_lim = 0, top_lim = 0;
160cabdff1aSopenharmony_ci
161cabdff1aSopenharmony_ci    mb_pos = row * s->mb_stride;
162cabdff1aSopenharmony_ci    for(mb_x = 0; mb_x < s->mb_width; mb_x++, mb_pos++){
163cabdff1aSopenharmony_ci        int mbtype = s->current_picture_ptr->mb_type[mb_pos];
164cabdff1aSopenharmony_ci        if(IS_INTRA(mbtype) || IS_SEPARATE_DC(mbtype))
165cabdff1aSopenharmony_ci            r->deblock_coefs[mb_pos] = 0xFFFF;
166cabdff1aSopenharmony_ci        if(IS_INTRA(mbtype))
167cabdff1aSopenharmony_ci            r->cbp_chroma[mb_pos] = 0xFF;
168cabdff1aSopenharmony_ci    }
169cabdff1aSopenharmony_ci
170cabdff1aSopenharmony_ci    /* all vertical edges are filtered first
171cabdff1aSopenharmony_ci     * and horizontal edges are filtered on the next iteration
172cabdff1aSopenharmony_ci     */
173cabdff1aSopenharmony_ci    mb_pos = row * s->mb_stride;
174cabdff1aSopenharmony_ci    for(mb_x = 0; mb_x < s->mb_width; mb_x++, mb_pos++){
175cabdff1aSopenharmony_ci        cur_lim = rv30_loop_filt_lim[s->current_picture_ptr->qscale_table[mb_pos]];
176cabdff1aSopenharmony_ci        if(mb_x)
177cabdff1aSopenharmony_ci            left_lim = rv30_loop_filt_lim[s->current_picture_ptr->qscale_table[mb_pos - 1]];
178cabdff1aSopenharmony_ci        for(j = 0; j < 16; j += 4){
179cabdff1aSopenharmony_ci            Y = s->current_picture_ptr->f->data[0] + mb_x*16 + (row*16 + j) * s->linesize + 4 * !mb_x;
180cabdff1aSopenharmony_ci            for(i = !mb_x; i < 4; i++, Y += 4){
181cabdff1aSopenharmony_ci                int ij = i + j;
182cabdff1aSopenharmony_ci                loc_lim = 0;
183cabdff1aSopenharmony_ci                if(r->deblock_coefs[mb_pos] & (1 << ij))
184cabdff1aSopenharmony_ci                    loc_lim = cur_lim;
185cabdff1aSopenharmony_ci                else if(!i && r->deblock_coefs[mb_pos - 1] & (1 << (ij + 3)))
186cabdff1aSopenharmony_ci                    loc_lim = left_lim;
187cabdff1aSopenharmony_ci                else if( i && r->deblock_coefs[mb_pos]     & (1 << (ij - 1)))
188cabdff1aSopenharmony_ci                    loc_lim = cur_lim;
189cabdff1aSopenharmony_ci                if(loc_lim)
190cabdff1aSopenharmony_ci                    rv30_weak_loop_filter(Y, 1, s->linesize, loc_lim);
191cabdff1aSopenharmony_ci            }
192cabdff1aSopenharmony_ci        }
193cabdff1aSopenharmony_ci        for(k = 0; k < 2; k++){
194cabdff1aSopenharmony_ci            int cur_cbp, left_cbp = 0;
195cabdff1aSopenharmony_ci            cur_cbp = (r->cbp_chroma[mb_pos] >> (k*4)) & 0xF;
196cabdff1aSopenharmony_ci            if(mb_x)
197cabdff1aSopenharmony_ci                left_cbp = (r->cbp_chroma[mb_pos - 1] >> (k*4)) & 0xF;
198cabdff1aSopenharmony_ci            for(j = 0; j < 8; j += 4){
199cabdff1aSopenharmony_ci                C = s->current_picture_ptr->f->data[k + 1] + mb_x*8 + (row*8 + j) * s->uvlinesize + 4 * !mb_x;
200cabdff1aSopenharmony_ci                for(i = !mb_x; i < 2; i++, C += 4){
201cabdff1aSopenharmony_ci                    int ij = i + (j >> 1);
202cabdff1aSopenharmony_ci                    loc_lim = 0;
203cabdff1aSopenharmony_ci                    if (cur_cbp & (1 << ij))
204cabdff1aSopenharmony_ci                        loc_lim = cur_lim;
205cabdff1aSopenharmony_ci                    else if(!i && left_cbp & (1 << (ij + 1)))
206cabdff1aSopenharmony_ci                        loc_lim = left_lim;
207cabdff1aSopenharmony_ci                    else if( i && cur_cbp  & (1 << (ij - 1)))
208cabdff1aSopenharmony_ci                        loc_lim = cur_lim;
209cabdff1aSopenharmony_ci                    if(loc_lim)
210cabdff1aSopenharmony_ci                        rv30_weak_loop_filter(C, 1, s->uvlinesize, loc_lim);
211cabdff1aSopenharmony_ci                }
212cabdff1aSopenharmony_ci            }
213cabdff1aSopenharmony_ci        }
214cabdff1aSopenharmony_ci    }
215cabdff1aSopenharmony_ci    mb_pos = row * s->mb_stride;
216cabdff1aSopenharmony_ci    for(mb_x = 0; mb_x < s->mb_width; mb_x++, mb_pos++){
217cabdff1aSopenharmony_ci        cur_lim = rv30_loop_filt_lim[s->current_picture_ptr->qscale_table[mb_pos]];
218cabdff1aSopenharmony_ci        if(row)
219cabdff1aSopenharmony_ci            top_lim = rv30_loop_filt_lim[s->current_picture_ptr->qscale_table[mb_pos - s->mb_stride]];
220cabdff1aSopenharmony_ci        for(j = 4*!row; j < 16; j += 4){
221cabdff1aSopenharmony_ci            Y = s->current_picture_ptr->f->data[0] + mb_x*16 + (row*16 + j) * s->linesize;
222cabdff1aSopenharmony_ci            for(i = 0; i < 4; i++, Y += 4){
223cabdff1aSopenharmony_ci                int ij = i + j;
224cabdff1aSopenharmony_ci                loc_lim = 0;
225cabdff1aSopenharmony_ci                if(r->deblock_coefs[mb_pos] & (1 << ij))
226cabdff1aSopenharmony_ci                    loc_lim = cur_lim;
227cabdff1aSopenharmony_ci                else if(!j && r->deblock_coefs[mb_pos - s->mb_stride] & (1 << (ij + 12)))
228cabdff1aSopenharmony_ci                    loc_lim = top_lim;
229cabdff1aSopenharmony_ci                else if( j && r->deblock_coefs[mb_pos]                & (1 << (ij - 4)))
230cabdff1aSopenharmony_ci                    loc_lim = cur_lim;
231cabdff1aSopenharmony_ci                if(loc_lim)
232cabdff1aSopenharmony_ci                    rv30_weak_loop_filter(Y, s->linesize, 1, loc_lim);
233cabdff1aSopenharmony_ci            }
234cabdff1aSopenharmony_ci        }
235cabdff1aSopenharmony_ci        for(k = 0; k < 2; k++){
236cabdff1aSopenharmony_ci            int cur_cbp, top_cbp = 0;
237cabdff1aSopenharmony_ci            cur_cbp = (r->cbp_chroma[mb_pos] >> (k*4)) & 0xF;
238cabdff1aSopenharmony_ci            if(row)
239cabdff1aSopenharmony_ci                top_cbp = (r->cbp_chroma[mb_pos - s->mb_stride] >> (k*4)) & 0xF;
240cabdff1aSopenharmony_ci            for(j = 4*!row; j < 8; j += 4){
241cabdff1aSopenharmony_ci                C = s->current_picture_ptr->f->data[k+1] + mb_x*8 + (row*8 + j) * s->uvlinesize;
242cabdff1aSopenharmony_ci                for(i = 0; i < 2; i++, C += 4){
243cabdff1aSopenharmony_ci                    int ij = i + (j >> 1);
244cabdff1aSopenharmony_ci                    loc_lim = 0;
245cabdff1aSopenharmony_ci                    if (r->cbp_chroma[mb_pos] & (1 << ij))
246cabdff1aSopenharmony_ci                        loc_lim = cur_lim;
247cabdff1aSopenharmony_ci                    else if(!j && top_cbp & (1 << (ij + 2)))
248cabdff1aSopenharmony_ci                        loc_lim = top_lim;
249cabdff1aSopenharmony_ci                    else if( j && cur_cbp & (1 << (ij - 2)))
250cabdff1aSopenharmony_ci                        loc_lim = cur_lim;
251cabdff1aSopenharmony_ci                    if(loc_lim)
252cabdff1aSopenharmony_ci                        rv30_weak_loop_filter(C, s->uvlinesize, 1, loc_lim);
253cabdff1aSopenharmony_ci                }
254cabdff1aSopenharmony_ci            }
255cabdff1aSopenharmony_ci        }
256cabdff1aSopenharmony_ci    }
257cabdff1aSopenharmony_ci}
258cabdff1aSopenharmony_ci
259cabdff1aSopenharmony_ci/**
260cabdff1aSopenharmony_ci * Initialize decoder.
261cabdff1aSopenharmony_ci */
262cabdff1aSopenharmony_cistatic av_cold int rv30_decode_init(AVCodecContext *avctx)
263cabdff1aSopenharmony_ci{
264cabdff1aSopenharmony_ci    RV34DecContext *r = avctx->priv_data;
265cabdff1aSopenharmony_ci    int ret;
266cabdff1aSopenharmony_ci
267cabdff1aSopenharmony_ci    r->orig_width  = avctx->coded_width;
268cabdff1aSopenharmony_ci    r->orig_height = avctx->coded_height;
269cabdff1aSopenharmony_ci
270cabdff1aSopenharmony_ci    if (avctx->extradata_size < 2) {
271cabdff1aSopenharmony_ci        av_log(avctx, AV_LOG_ERROR, "Extradata is too small.\n");
272cabdff1aSopenharmony_ci        return AVERROR(EINVAL);
273cabdff1aSopenharmony_ci    }
274cabdff1aSopenharmony_ci    r->rv30 = 1;
275cabdff1aSopenharmony_ci    if ((ret = ff_rv34_decode_init(avctx)) < 0)
276cabdff1aSopenharmony_ci        return ret;
277cabdff1aSopenharmony_ci
278cabdff1aSopenharmony_ci    r->max_rpr = avctx->extradata[1] & 7;
279cabdff1aSopenharmony_ci    if(avctx->extradata_size < 2*r->max_rpr + 8){
280cabdff1aSopenharmony_ci        av_log(avctx, AV_LOG_WARNING, "Insufficient extradata - need at least %d bytes, got %d\n",
281cabdff1aSopenharmony_ci               2*r->max_rpr + 8, avctx->extradata_size);
282cabdff1aSopenharmony_ci    }
283cabdff1aSopenharmony_ci
284cabdff1aSopenharmony_ci    r->parse_slice_header = rv30_parse_slice_header;
285cabdff1aSopenharmony_ci    r->decode_intra_types = rv30_decode_intra_types;
286cabdff1aSopenharmony_ci    r->decode_mb_info     = rv30_decode_mb_info;
287cabdff1aSopenharmony_ci    r->loop_filter        = rv30_loop_filter;
288cabdff1aSopenharmony_ci    r->luma_dc_quant_i = rv30_luma_dc_quant;
289cabdff1aSopenharmony_ci    r->luma_dc_quant_p = rv30_luma_dc_quant;
290cabdff1aSopenharmony_ci    ff_rv30dsp_init(&r->rdsp);
291cabdff1aSopenharmony_ci    return 0;
292cabdff1aSopenharmony_ci}
293cabdff1aSopenharmony_ci
294cabdff1aSopenharmony_ciconst FFCodec ff_rv30_decoder = {
295cabdff1aSopenharmony_ci    .p.name                = "rv30",
296cabdff1aSopenharmony_ci    .p.long_name           = NULL_IF_CONFIG_SMALL("RealVideo 3.0"),
297cabdff1aSopenharmony_ci    .p.type                = AVMEDIA_TYPE_VIDEO,
298cabdff1aSopenharmony_ci    .p.id                  = AV_CODEC_ID_RV30,
299cabdff1aSopenharmony_ci    .priv_data_size        = sizeof(RV34DecContext),
300cabdff1aSopenharmony_ci    .init                  = rv30_decode_init,
301cabdff1aSopenharmony_ci    .close                 = ff_rv34_decode_end,
302cabdff1aSopenharmony_ci    FF_CODEC_DECODE_CB(ff_rv34_decode_frame),
303cabdff1aSopenharmony_ci    .p.capabilities        = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY |
304cabdff1aSopenharmony_ci                             AV_CODEC_CAP_FRAME_THREADS,
305cabdff1aSopenharmony_ci    .flush                 = ff_mpeg_flush,
306cabdff1aSopenharmony_ci    .p.pix_fmts            = (const enum AVPixelFormat[]) {
307cabdff1aSopenharmony_ci        AV_PIX_FMT_YUV420P,
308cabdff1aSopenharmony_ci        AV_PIX_FMT_NONE
309cabdff1aSopenharmony_ci    },
310cabdff1aSopenharmony_ci    .update_thread_context = ONLY_IF_THREADS_ENABLED(ff_rv34_decode_update_thread_context),
311cabdff1aSopenharmony_ci    .caps_internal         = FF_CODEC_CAP_INIT_THREADSAFE |
312cabdff1aSopenharmony_ci                             FF_CODEC_CAP_ALLOCATE_PROGRESS,
313cabdff1aSopenharmony_ci};
314