xref: /third_party/ffmpeg/libavcodec/dvenc.c (revision cabdff1a)
1cabdff1aSopenharmony_ci/*
2cabdff1aSopenharmony_ci * DV encoder
3cabdff1aSopenharmony_ci * Copyright (c) 2003 Roman Shaposhnik
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 * quant_deadzone code and fixes sponsored by NOA GmbH
22cabdff1aSopenharmony_ci */
23cabdff1aSopenharmony_ci
24cabdff1aSopenharmony_ci/**
25cabdff1aSopenharmony_ci * @file
26cabdff1aSopenharmony_ci * DV encoder
27cabdff1aSopenharmony_ci */
28cabdff1aSopenharmony_ci
29cabdff1aSopenharmony_ci#include "config.h"
30cabdff1aSopenharmony_ci
31cabdff1aSopenharmony_ci#include "libavutil/attributes.h"
32cabdff1aSopenharmony_ci#include "libavutil/internal.h"
33cabdff1aSopenharmony_ci#include "libavutil/mem_internal.h"
34cabdff1aSopenharmony_ci#include "libavutil/opt.h"
35cabdff1aSopenharmony_ci#include "libavutil/pixdesc.h"
36cabdff1aSopenharmony_ci#include "libavutil/thread.h"
37cabdff1aSopenharmony_ci
38cabdff1aSopenharmony_ci#include "avcodec.h"
39cabdff1aSopenharmony_ci#include "codec_internal.h"
40cabdff1aSopenharmony_ci#include "dv.h"
41cabdff1aSopenharmony_ci#include "dv_profile_internal.h"
42cabdff1aSopenharmony_ci#include "dv_tablegen.h"
43cabdff1aSopenharmony_ci#include "encode.h"
44cabdff1aSopenharmony_ci#include "fdctdsp.h"
45cabdff1aSopenharmony_ci#include "mathops.h"
46cabdff1aSopenharmony_ci#include "me_cmp.h"
47cabdff1aSopenharmony_ci#include "pixblockdsp.h"
48cabdff1aSopenharmony_ci#include "put_bits.h"
49cabdff1aSopenharmony_ci
50cabdff1aSopenharmony_cistatic av_cold int dvvideo_encode_init(AVCodecContext *avctx)
51cabdff1aSopenharmony_ci{
52cabdff1aSopenharmony_ci    DVVideoContext *s = avctx->priv_data;
53cabdff1aSopenharmony_ci    FDCTDSPContext fdsp;
54cabdff1aSopenharmony_ci    MECmpContext mecc;
55cabdff1aSopenharmony_ci    PixblockDSPContext pdsp;
56cabdff1aSopenharmony_ci    int ret;
57cabdff1aSopenharmony_ci
58cabdff1aSopenharmony_ci    s->sys = av_dv_codec_profile2(avctx->width, avctx->height, avctx->pix_fmt, avctx->time_base);
59cabdff1aSopenharmony_ci    if (!s->sys) {
60cabdff1aSopenharmony_ci        av_log(avctx, AV_LOG_ERROR, "Found no DV profile for %ix%i %s video. "
61cabdff1aSopenharmony_ci                                    "Valid DV profiles are:\n",
62cabdff1aSopenharmony_ci               avctx->width, avctx->height, av_get_pix_fmt_name(avctx->pix_fmt));
63cabdff1aSopenharmony_ci        ff_dv_print_profiles(avctx, AV_LOG_ERROR);
64cabdff1aSopenharmony_ci        return AVERROR(EINVAL);
65cabdff1aSopenharmony_ci    }
66cabdff1aSopenharmony_ci
67cabdff1aSopenharmony_ci    ret = ff_dv_init_dynamic_tables(s, s->sys);
68cabdff1aSopenharmony_ci    if (ret < 0) {
69cabdff1aSopenharmony_ci        av_log(avctx, AV_LOG_ERROR, "Error initializing work tables.\n");
70cabdff1aSopenharmony_ci        return ret;
71cabdff1aSopenharmony_ci    }
72cabdff1aSopenharmony_ci
73cabdff1aSopenharmony_ci    memset(&fdsp,0, sizeof(fdsp));
74cabdff1aSopenharmony_ci    memset(&mecc,0, sizeof(mecc));
75cabdff1aSopenharmony_ci    memset(&pdsp,0, sizeof(pdsp));
76cabdff1aSopenharmony_ci    ff_fdctdsp_init(&fdsp, avctx);
77cabdff1aSopenharmony_ci    ff_me_cmp_init(&mecc, avctx);
78cabdff1aSopenharmony_ci    ff_pixblockdsp_init(&pdsp, avctx);
79cabdff1aSopenharmony_ci    ret = ff_set_cmp(&mecc, mecc.ildct_cmp, avctx->ildct_cmp);
80cabdff1aSopenharmony_ci    if (ret < 0)
81cabdff1aSopenharmony_ci        return AVERROR(EINVAL);
82cabdff1aSopenharmony_ci
83cabdff1aSopenharmony_ci    s->get_pixels = pdsp.get_pixels;
84cabdff1aSopenharmony_ci    s->ildct_cmp  = mecc.ildct_cmp[5];
85cabdff1aSopenharmony_ci
86cabdff1aSopenharmony_ci    s->fdct[0]    = fdsp.fdct;
87cabdff1aSopenharmony_ci    s->fdct[1]    = fdsp.fdct248;
88cabdff1aSopenharmony_ci
89cabdff1aSopenharmony_ci#if !CONFIG_HARDCODED_TABLES
90cabdff1aSopenharmony_ci    {
91cabdff1aSopenharmony_ci        static AVOnce init_static_once = AV_ONCE_INIT;
92cabdff1aSopenharmony_ci        ff_thread_once(&init_static_once, dv_vlc_map_tableinit);
93cabdff1aSopenharmony_ci    }
94cabdff1aSopenharmony_ci#endif
95cabdff1aSopenharmony_ci
96cabdff1aSopenharmony_ci    return ff_dvvideo_init(avctx);
97cabdff1aSopenharmony_ci}
98cabdff1aSopenharmony_ci
99cabdff1aSopenharmony_ci/* bit budget for AC only in 5 MBs */
100cabdff1aSopenharmony_cistatic const int vs_total_ac_bits_hd = (68 * 6 + 52*2) * 5;
101cabdff1aSopenharmony_cistatic const int vs_total_ac_bits = (100 * 4 + 68 * 2) * 5;
102cabdff1aSopenharmony_cistatic const int mb_area_start[5] = { 1, 6, 21, 43, 64 };
103cabdff1aSopenharmony_ci
104cabdff1aSopenharmony_ci#if CONFIG_SMALL
105cabdff1aSopenharmony_ci/* Convert run and level (where level != 0) pair into VLC, returning bit size */
106cabdff1aSopenharmony_cistatic av_always_inline int dv_rl2vlc(int run, int level, int sign,
107cabdff1aSopenharmony_ci                                      uint32_t *vlc)
108cabdff1aSopenharmony_ci{
109cabdff1aSopenharmony_ci    int size;
110cabdff1aSopenharmony_ci    if (run < DV_VLC_MAP_RUN_SIZE && level < DV_VLC_MAP_LEV_SIZE) {
111cabdff1aSopenharmony_ci        *vlc = dv_vlc_map[run][level].vlc | sign;
112cabdff1aSopenharmony_ci        size = dv_vlc_map[run][level].size;
113cabdff1aSopenharmony_ci    } else {
114cabdff1aSopenharmony_ci        if (level < DV_VLC_MAP_LEV_SIZE) {
115cabdff1aSopenharmony_ci            *vlc = dv_vlc_map[0][level].vlc | sign;
116cabdff1aSopenharmony_ci            size = dv_vlc_map[0][level].size;
117cabdff1aSopenharmony_ci        } else {
118cabdff1aSopenharmony_ci            *vlc = 0xfe00 | (level << 1) | sign;
119cabdff1aSopenharmony_ci            size = 16;
120cabdff1aSopenharmony_ci        }
121cabdff1aSopenharmony_ci        if (run) {
122cabdff1aSopenharmony_ci            *vlc |= ((run < 16) ? dv_vlc_map[run - 1][0].vlc :
123cabdff1aSopenharmony_ci                     (0x1f80 | (run - 1))) << size;
124cabdff1aSopenharmony_ci            size +=  (run < 16) ? dv_vlc_map[run - 1][0].size : 13;
125cabdff1aSopenharmony_ci        }
126cabdff1aSopenharmony_ci    }
127cabdff1aSopenharmony_ci
128cabdff1aSopenharmony_ci    return size;
129cabdff1aSopenharmony_ci}
130cabdff1aSopenharmony_ci
131cabdff1aSopenharmony_cistatic av_always_inline int dv_rl2vlc_size(int run, int level)
132cabdff1aSopenharmony_ci{
133cabdff1aSopenharmony_ci    int size;
134cabdff1aSopenharmony_ci
135cabdff1aSopenharmony_ci    if (run < DV_VLC_MAP_RUN_SIZE && level < DV_VLC_MAP_LEV_SIZE) {
136cabdff1aSopenharmony_ci        size = dv_vlc_map[run][level].size;
137cabdff1aSopenharmony_ci    } else {
138cabdff1aSopenharmony_ci        size = (level < DV_VLC_MAP_LEV_SIZE) ? dv_vlc_map[0][level].size : 16;
139cabdff1aSopenharmony_ci        if (run)
140cabdff1aSopenharmony_ci            size += (run < 16) ? dv_vlc_map[run - 1][0].size : 13;
141cabdff1aSopenharmony_ci    }
142cabdff1aSopenharmony_ci    return size;
143cabdff1aSopenharmony_ci}
144cabdff1aSopenharmony_ci#else
145cabdff1aSopenharmony_cistatic av_always_inline int dv_rl2vlc(int run, int l, int sign, uint32_t *vlc)
146cabdff1aSopenharmony_ci{
147cabdff1aSopenharmony_ci    *vlc = dv_vlc_map[run][l].vlc | sign;
148cabdff1aSopenharmony_ci    return dv_vlc_map[run][l].size;
149cabdff1aSopenharmony_ci}
150cabdff1aSopenharmony_ci
151cabdff1aSopenharmony_cistatic av_always_inline int dv_rl2vlc_size(int run, int l)
152cabdff1aSopenharmony_ci{
153cabdff1aSopenharmony_ci    return dv_vlc_map[run][l].size;
154cabdff1aSopenharmony_ci}
155cabdff1aSopenharmony_ci#endif
156cabdff1aSopenharmony_ci
157cabdff1aSopenharmony_citypedef struct EncBlockInfo {
158cabdff1aSopenharmony_ci    int      area_q[4];
159cabdff1aSopenharmony_ci    int      bit_size[4];
160cabdff1aSopenharmony_ci    int      prev[5];
161cabdff1aSopenharmony_ci    int      cur_ac;
162cabdff1aSopenharmony_ci    int      cno;
163cabdff1aSopenharmony_ci    int      dct_mode;
164cabdff1aSopenharmony_ci    int16_t  mb[64];
165cabdff1aSopenharmony_ci    uint8_t  next[64];
166cabdff1aSopenharmony_ci    uint8_t  sign[64];
167cabdff1aSopenharmony_ci    uint8_t  partial_bit_count;
168cabdff1aSopenharmony_ci    uint32_t partial_bit_buffer; /* we can't use uint16_t here */
169cabdff1aSopenharmony_ci    /* used by DV100 only: a copy of the weighted and classified but
170cabdff1aSopenharmony_ci       not-yet-quantized AC coefficients. This is necessary for
171cabdff1aSopenharmony_ci       re-quantizing at different steps. */
172cabdff1aSopenharmony_ci    int16_t  save[64];
173cabdff1aSopenharmony_ci    int      min_qlevel; /* DV100 only: minimum qlevel (for AC coefficients >255) */
174cabdff1aSopenharmony_ci} EncBlockInfo;
175cabdff1aSopenharmony_ci
176cabdff1aSopenharmony_cistatic av_always_inline PutBitContext *dv_encode_ac(EncBlockInfo *bi,
177cabdff1aSopenharmony_ci                                                    PutBitContext *pb_pool,
178cabdff1aSopenharmony_ci                                                    PutBitContext *pb_end)
179cabdff1aSopenharmony_ci{
180cabdff1aSopenharmony_ci    int prev, bits_left;
181cabdff1aSopenharmony_ci    PutBitContext *pb = pb_pool;
182cabdff1aSopenharmony_ci    int size          = bi->partial_bit_count;
183cabdff1aSopenharmony_ci    uint32_t vlc      = bi->partial_bit_buffer;
184cabdff1aSopenharmony_ci
185cabdff1aSopenharmony_ci    bi->partial_bit_count  =
186cabdff1aSopenharmony_ci    bi->partial_bit_buffer = 0;
187cabdff1aSopenharmony_ci    for (;;) {
188cabdff1aSopenharmony_ci        /* Find suitable storage space */
189cabdff1aSopenharmony_ci        for (; size > (bits_left = put_bits_left(pb)); pb++) {
190cabdff1aSopenharmony_ci            if (bits_left) {
191cabdff1aSopenharmony_ci                size -= bits_left;
192cabdff1aSopenharmony_ci                put_bits(pb, bits_left, vlc >> size);
193cabdff1aSopenharmony_ci                vlc = av_mod_uintp2(vlc, size);
194cabdff1aSopenharmony_ci            }
195cabdff1aSopenharmony_ci            if (pb + 1 >= pb_end) {
196cabdff1aSopenharmony_ci                bi->partial_bit_count  = size;
197cabdff1aSopenharmony_ci                bi->partial_bit_buffer = vlc;
198cabdff1aSopenharmony_ci                return pb;
199cabdff1aSopenharmony_ci            }
200cabdff1aSopenharmony_ci        }
201cabdff1aSopenharmony_ci
202cabdff1aSopenharmony_ci        /* Store VLC */
203cabdff1aSopenharmony_ci        put_bits(pb, size, vlc);
204cabdff1aSopenharmony_ci
205cabdff1aSopenharmony_ci        if (bi->cur_ac >= 64)
206cabdff1aSopenharmony_ci            break;
207cabdff1aSopenharmony_ci
208cabdff1aSopenharmony_ci        /* Construct the next VLC */
209cabdff1aSopenharmony_ci        prev       = bi->cur_ac;
210cabdff1aSopenharmony_ci        bi->cur_ac = bi->next[prev];
211cabdff1aSopenharmony_ci        if (bi->cur_ac < 64) {
212cabdff1aSopenharmony_ci            size = dv_rl2vlc(bi->cur_ac - prev - 1, bi->mb[bi->cur_ac],
213cabdff1aSopenharmony_ci                             bi->sign[bi->cur_ac], &vlc);
214cabdff1aSopenharmony_ci        } else {
215cabdff1aSopenharmony_ci            size = 4;
216cabdff1aSopenharmony_ci            vlc  = 6; /* End Of Block stamp */
217cabdff1aSopenharmony_ci        }
218cabdff1aSopenharmony_ci    }
219cabdff1aSopenharmony_ci    return pb;
220cabdff1aSopenharmony_ci}
221cabdff1aSopenharmony_ci
222cabdff1aSopenharmony_cistatic av_always_inline int dv_guess_dct_mode(DVVideoContext *s, uint8_t *data,
223cabdff1aSopenharmony_ci                                              ptrdiff_t linesize)
224cabdff1aSopenharmony_ci{
225cabdff1aSopenharmony_ci    if (s->avctx->flags & AV_CODEC_FLAG_INTERLACED_DCT) {
226cabdff1aSopenharmony_ci        int ps = s->ildct_cmp(NULL, data, NULL, linesize, 8) - 400;
227cabdff1aSopenharmony_ci        if (ps > 0) {
228cabdff1aSopenharmony_ci            int is = s->ildct_cmp(NULL, data,            NULL, linesize * 2, 4) +
229cabdff1aSopenharmony_ci                     s->ildct_cmp(NULL, data + linesize, NULL, linesize * 2, 4);
230cabdff1aSopenharmony_ci            return ps > is;
231cabdff1aSopenharmony_ci        }
232cabdff1aSopenharmony_ci    }
233cabdff1aSopenharmony_ci
234cabdff1aSopenharmony_ci    return 0;
235cabdff1aSopenharmony_ci}
236cabdff1aSopenharmony_ci
237cabdff1aSopenharmony_cistatic const int dv_weight_bits = 18;
238cabdff1aSopenharmony_cistatic const int dv_weight_88[64] = {
239cabdff1aSopenharmony_ci    131072, 257107, 257107, 242189, 252167, 242189, 235923, 237536,
240cabdff1aSopenharmony_ci    237536, 235923, 229376, 231390, 223754, 231390, 229376, 222935,
241cabdff1aSopenharmony_ci    224969, 217965, 217965, 224969, 222935, 200636, 218652, 211916,
242cabdff1aSopenharmony_ci    212325, 211916, 218652, 200636, 188995, 196781, 205965, 206433,
243cabdff1aSopenharmony_ci    206433, 205965, 196781, 188995, 185364, 185364, 200636, 200704,
244cabdff1aSopenharmony_ci    200636, 185364, 185364, 174609, 180568, 195068, 195068, 180568,
245cabdff1aSopenharmony_ci    174609, 170091, 175557, 189591, 175557, 170091, 165371, 170627,
246cabdff1aSopenharmony_ci    170627, 165371, 160727, 153560, 160727, 144651, 144651, 136258,
247cabdff1aSopenharmony_ci};
248cabdff1aSopenharmony_cistatic const int dv_weight_248[64] = {
249cabdff1aSopenharmony_ci    131072, 262144, 257107, 257107, 242189, 242189, 242189, 242189,
250cabdff1aSopenharmony_ci    237536, 237536, 229376, 229376, 200636, 200636, 224973, 224973,
251cabdff1aSopenharmony_ci    223754, 223754, 235923, 235923, 229376, 229376, 217965, 217965,
252cabdff1aSopenharmony_ci    211916, 211916, 196781, 196781, 185364, 185364, 206433, 206433,
253cabdff1aSopenharmony_ci    211916, 211916, 222935, 222935, 200636, 200636, 205964, 205964,
254cabdff1aSopenharmony_ci    200704, 200704, 180568, 180568, 175557, 175557, 195068, 195068,
255cabdff1aSopenharmony_ci    185364, 185364, 188995, 188995, 174606, 174606, 175557, 175557,
256cabdff1aSopenharmony_ci    170627, 170627, 153560, 153560, 165371, 165371, 144651, 144651,
257cabdff1aSopenharmony_ci};
258cabdff1aSopenharmony_ci
259cabdff1aSopenharmony_ci/* setting this to 1 results in a faster codec but
260cabdff1aSopenharmony_ci * somewhat lower image quality */
261cabdff1aSopenharmony_ci#define DV100_SACRIFICE_QUALITY_FOR_SPEED 1
262cabdff1aSopenharmony_ci#define DV100_ENABLE_FINER 1
263cabdff1aSopenharmony_ci
264cabdff1aSopenharmony_ci/* pack combination of QNO and CNO into a single 8-bit value */
265cabdff1aSopenharmony_ci#define DV100_MAKE_QLEVEL(qno,cno) ((qno<<2) | (cno))
266cabdff1aSopenharmony_ci#define DV100_QLEVEL_QNO(qlevel) (qlevel>>2)
267cabdff1aSopenharmony_ci#define DV100_QLEVEL_CNO(qlevel) (qlevel&0x3)
268cabdff1aSopenharmony_ci
269cabdff1aSopenharmony_ci#define DV100_NUM_QLEVELS 31
270cabdff1aSopenharmony_ci
271cabdff1aSopenharmony_ci/* The quantization step is determined by a combination of QNO and
272cabdff1aSopenharmony_ci   CNO. We refer to these combinations as "qlevels" (this term is our
273cabdff1aSopenharmony_ci   own, it's not mentioned in the spec). We use CNO, a multiplier on
274cabdff1aSopenharmony_ci   the quantization step, to "fill in the gaps" between quantization
275cabdff1aSopenharmony_ci   steps associated with successive values of QNO. e.g. there is no
276cabdff1aSopenharmony_ci   QNO for a quantization step of 10, but we can use QNO=5 CNO=1 to
277cabdff1aSopenharmony_ci   get the same result. The table below encodes combinations of QNO
278cabdff1aSopenharmony_ci   and CNO in order of increasing quantization coarseness. */
279cabdff1aSopenharmony_cistatic const uint8_t dv100_qlevels[DV100_NUM_QLEVELS] = {
280cabdff1aSopenharmony_ci    DV100_MAKE_QLEVEL( 1,0), //  1*1= 1
281cabdff1aSopenharmony_ci    DV100_MAKE_QLEVEL( 1,0), //  1*1= 1
282cabdff1aSopenharmony_ci    DV100_MAKE_QLEVEL( 2,0), //  2*1= 2
283cabdff1aSopenharmony_ci    DV100_MAKE_QLEVEL( 3,0), //  3*1= 3
284cabdff1aSopenharmony_ci    DV100_MAKE_QLEVEL( 4,0), //  4*1= 4
285cabdff1aSopenharmony_ci    DV100_MAKE_QLEVEL( 5,0), //  5*1= 5
286cabdff1aSopenharmony_ci    DV100_MAKE_QLEVEL( 6,0), //  6*1= 6
287cabdff1aSopenharmony_ci    DV100_MAKE_QLEVEL( 7,0), //  7*1= 7
288cabdff1aSopenharmony_ci    DV100_MAKE_QLEVEL( 8,0), //  8*1= 8
289cabdff1aSopenharmony_ci    DV100_MAKE_QLEVEL( 5,1), //  5*2=10
290cabdff1aSopenharmony_ci    DV100_MAKE_QLEVEL( 6,1), //  6*2=12
291cabdff1aSopenharmony_ci    DV100_MAKE_QLEVEL( 7,1), //  7*2=14
292cabdff1aSopenharmony_ci    DV100_MAKE_QLEVEL( 9,0), // 16*1=16
293cabdff1aSopenharmony_ci    DV100_MAKE_QLEVEL(10,0), // 18*1=18
294cabdff1aSopenharmony_ci    DV100_MAKE_QLEVEL(11,0), // 20*1=20
295cabdff1aSopenharmony_ci    DV100_MAKE_QLEVEL(12,0), // 22*1=22
296cabdff1aSopenharmony_ci    DV100_MAKE_QLEVEL(13,0), // 24*1=24
297cabdff1aSopenharmony_ci    DV100_MAKE_QLEVEL(14,0), // 28*1=28
298cabdff1aSopenharmony_ci    DV100_MAKE_QLEVEL( 9,1), // 16*2=32
299cabdff1aSopenharmony_ci    DV100_MAKE_QLEVEL(10,1), // 18*2=36
300cabdff1aSopenharmony_ci    DV100_MAKE_QLEVEL(11,1), // 20*2=40
301cabdff1aSopenharmony_ci    DV100_MAKE_QLEVEL(12,1), // 22*2=44
302cabdff1aSopenharmony_ci    DV100_MAKE_QLEVEL(13,1), // 24*2=48
303cabdff1aSopenharmony_ci    DV100_MAKE_QLEVEL(15,0), // 52*1=52
304cabdff1aSopenharmony_ci    DV100_MAKE_QLEVEL(14,1), // 28*2=56
305cabdff1aSopenharmony_ci    DV100_MAKE_QLEVEL( 9,2), // 16*4=64
306cabdff1aSopenharmony_ci    DV100_MAKE_QLEVEL(10,2), // 18*4=72
307cabdff1aSopenharmony_ci    DV100_MAKE_QLEVEL(11,2), // 20*4=80
308cabdff1aSopenharmony_ci    DV100_MAKE_QLEVEL(12,2), // 22*4=88
309cabdff1aSopenharmony_ci    DV100_MAKE_QLEVEL(13,2), // 24*4=96
310cabdff1aSopenharmony_ci    // ...
311cabdff1aSopenharmony_ci    DV100_MAKE_QLEVEL(15,3), // 52*8=416
312cabdff1aSopenharmony_ci};
313cabdff1aSopenharmony_ci
314cabdff1aSopenharmony_cistatic const int dv100_min_bias = 0;
315cabdff1aSopenharmony_cistatic const int dv100_chroma_bias = 0;
316cabdff1aSopenharmony_cistatic const int dv100_starting_qno = 1;
317cabdff1aSopenharmony_ci
318cabdff1aSopenharmony_ci#if DV100_SACRIFICE_QUALITY_FOR_SPEED
319cabdff1aSopenharmony_cistatic const int dv100_qlevel_inc = 4;
320cabdff1aSopenharmony_ci#else
321cabdff1aSopenharmony_cistatic const int dv100_qlevel_inc = 1;
322cabdff1aSopenharmony_ci#endif
323cabdff1aSopenharmony_ci
324cabdff1aSopenharmony_ci// 1/qstep, shifted up by 16 bits
325cabdff1aSopenharmony_cistatic const int dv100_qstep_bits = 16;
326cabdff1aSopenharmony_cistatic const int dv100_qstep_inv[16] = {
327cabdff1aSopenharmony_ci        65536,  65536,  32768,  21845,  16384,  13107,  10923,  9362,  8192,  4096,  3641,  3277,  2979,  2731,  2341,  1260,
328cabdff1aSopenharmony_ci};
329cabdff1aSopenharmony_ci
330cabdff1aSopenharmony_ci/* DV100 weights are pre-zigzagged, inverted and multiplied by 2^16
331cabdff1aSopenharmony_ci   (in DV100 the AC components are divided by the spec weights) */
332cabdff1aSopenharmony_cistatic const int dv_weight_1080[2][64] = {
333cabdff1aSopenharmony_ci    { 8192, 65536, 65536, 61681, 61681, 61681, 58254, 58254,
334cabdff1aSopenharmony_ci      58254, 58254, 58254, 58254, 55188, 58254, 58254, 55188,
335cabdff1aSopenharmony_ci      55188, 55188, 55188, 55188, 55188, 24966, 27594, 26214,
336cabdff1aSopenharmony_ci      26214, 26214, 27594, 24966, 23831, 24385, 25575, 25575,
337cabdff1aSopenharmony_ci      25575, 25575, 24385, 23831, 23302, 23302, 24966, 24966,
338cabdff1aSopenharmony_ci      24966, 23302, 23302, 21845, 22795, 24385, 24385, 22795,
339cabdff1aSopenharmony_ci      21845, 21400, 21845, 23831, 21845, 21400, 10382, 10700,
340cabdff1aSopenharmony_ci      10700, 10382, 10082, 9620, 10082, 9039, 9039, 8525, },
341cabdff1aSopenharmony_ci    { 8192, 65536, 65536, 61681, 61681, 61681, 41943, 41943,
342cabdff1aSopenharmony_ci      41943, 41943, 40330, 41943, 40330, 41943, 40330, 40330,
343cabdff1aSopenharmony_ci      40330, 38836, 38836, 40330, 40330, 24966, 27594, 26214,
344cabdff1aSopenharmony_ci      26214, 26214, 27594, 24966, 23831, 24385, 25575, 25575,
345cabdff1aSopenharmony_ci      25575, 25575, 24385, 23831, 11523, 11523, 12483, 12483,
346cabdff1aSopenharmony_ci      12483, 11523, 11523, 10923, 11275, 12193, 12193, 11275,
347cabdff1aSopenharmony_ci      10923, 5323, 5490, 5924, 5490, 5323, 5165, 5323,
348cabdff1aSopenharmony_ci      5323, 5165, 5017, 4788, 5017, 4520, 4520, 4263, }
349cabdff1aSopenharmony_ci};
350cabdff1aSopenharmony_ci
351cabdff1aSopenharmony_cistatic const int dv_weight_720[2][64] = {
352cabdff1aSopenharmony_ci    { 8192, 65536, 65536, 61681, 61681, 61681, 58254, 58254,
353cabdff1aSopenharmony_ci      58254, 58254, 58254, 58254, 55188, 58254, 58254, 55188,
354cabdff1aSopenharmony_ci      55188, 55188, 55188, 55188, 55188, 24966, 27594, 26214,
355cabdff1aSopenharmony_ci      26214, 26214, 27594, 24966, 23831, 24385, 25575, 25575,
356cabdff1aSopenharmony_ci      25575, 25575, 24385, 23831, 15420, 15420, 16644, 16644,
357cabdff1aSopenharmony_ci      16644, 15420, 15420, 10923, 11398, 12193, 12193, 11398,
358cabdff1aSopenharmony_ci      10923, 10700, 10923, 11916, 10923, 10700, 5191, 5350,
359cabdff1aSopenharmony_ci      5350, 5191, 5041, 4810, 5041, 4520, 4520, 4263, },
360cabdff1aSopenharmony_ci    { 8192, 43691, 43691, 40330, 40330, 40330, 29127, 29127,
361cabdff1aSopenharmony_ci      29127, 29127, 29127, 29127, 27594, 29127, 29127, 27594,
362cabdff1aSopenharmony_ci      27594, 27594, 27594, 27594, 27594, 12483, 13797, 13107,
363cabdff1aSopenharmony_ci      13107, 13107, 13797, 12483, 11916, 12193, 12788, 12788,
364cabdff1aSopenharmony_ci      12788, 12788, 12193, 11916, 5761, 5761, 6242, 6242,
365cabdff1aSopenharmony_ci      6242, 5761, 5761, 5461, 5638, 5461, 6096, 5638,
366cabdff1aSopenharmony_ci      5461, 2661, 2745, 2962, 2745, 2661, 2583, 2661,
367cabdff1aSopenharmony_ci      2661, 2583, 2509, 2394, 2509, 2260, 2260, 2131, }
368cabdff1aSopenharmony_ci};
369cabdff1aSopenharmony_ci
370cabdff1aSopenharmony_cistatic av_always_inline int dv_set_class_number_sd(DVVideoContext *s,
371cabdff1aSopenharmony_ci                                                   int16_t *blk, EncBlockInfo *bi,
372cabdff1aSopenharmony_ci                                                   const uint8_t *zigzag_scan,
373cabdff1aSopenharmony_ci                                                   const int *weight, int bias)
374cabdff1aSopenharmony_ci{
375cabdff1aSopenharmony_ci    int i, area;
376cabdff1aSopenharmony_ci    /* We offer two different methods for class number assignment: the
377cabdff1aSopenharmony_ci     * method suggested in SMPTE 314M Table 22, and an improved
378cabdff1aSopenharmony_ci     * method. The SMPTE method is very conservative; it assigns class
379cabdff1aSopenharmony_ci     * 3 (i.e. severe quantization) to any block where the largest AC
380cabdff1aSopenharmony_ci     * component is greater than 36. FFmpeg's DV encoder tracks AC bit
381cabdff1aSopenharmony_ci     * consumption precisely, so there is no need to bias most blocks
382cabdff1aSopenharmony_ci     * towards strongly lossy compression. Instead, we assign class 2
383cabdff1aSopenharmony_ci     * to most blocks, and use class 3 only when strictly necessary
384cabdff1aSopenharmony_ci     * (for blocks whose largest AC component exceeds 255). */
385cabdff1aSopenharmony_ci
386cabdff1aSopenharmony_ci#if 0 /* SMPTE spec method */
387cabdff1aSopenharmony_ci    static const int classes[] = { 12, 24, 36, 0xffff };
388cabdff1aSopenharmony_ci#else /* improved FFmpeg method */
389cabdff1aSopenharmony_ci    static const int classes[] = { -1, -1, 255, 0xffff };
390cabdff1aSopenharmony_ci#endif
391cabdff1aSopenharmony_ci    int max  = classes[0];
392cabdff1aSopenharmony_ci    int prev = 0;
393cabdff1aSopenharmony_ci    const unsigned deadzone = s->quant_deadzone;
394cabdff1aSopenharmony_ci    const unsigned threshold = 2 * deadzone;
395cabdff1aSopenharmony_ci
396cabdff1aSopenharmony_ci    bi->mb[0] = blk[0];
397cabdff1aSopenharmony_ci
398cabdff1aSopenharmony_ci    for (area = 0; area < 4; area++) {
399cabdff1aSopenharmony_ci        bi->prev[area]     = prev;
400cabdff1aSopenharmony_ci        bi->bit_size[area] = 1; // 4 areas 4 bits for EOB :)
401cabdff1aSopenharmony_ci        for (i = mb_area_start[area]; i < mb_area_start[area + 1]; i++) {
402cabdff1aSopenharmony_ci            int level = blk[zigzag_scan[i]];
403cabdff1aSopenharmony_ci
404cabdff1aSopenharmony_ci            if (level + deadzone > threshold) {
405cabdff1aSopenharmony_ci                bi->sign[i] = (level >> 31) & 1;
406cabdff1aSopenharmony_ci                /* Weight it and shift down into range, adding for rounding.
407cabdff1aSopenharmony_ci                 * The extra division by a factor of 2^4 reverses the 8x
408cabdff1aSopenharmony_ci                 * expansion of the DCT AND the 2x doubling of the weights. */
409cabdff1aSopenharmony_ci                level     = (FFABS(level) * weight[i] + (1 << (dv_weight_bits + 3))) >>
410cabdff1aSopenharmony_ci                            (dv_weight_bits + 4);
411cabdff1aSopenharmony_ci                if (!level)
412cabdff1aSopenharmony_ci                    continue;
413cabdff1aSopenharmony_ci                bi->mb[i] = level;
414cabdff1aSopenharmony_ci                if (level > max)
415cabdff1aSopenharmony_ci                    max = level;
416cabdff1aSopenharmony_ci                bi->bit_size[area] += dv_rl2vlc_size(i - prev - 1, level);
417cabdff1aSopenharmony_ci                bi->next[prev]      = i;
418cabdff1aSopenharmony_ci                prev                = i;
419cabdff1aSopenharmony_ci            }
420cabdff1aSopenharmony_ci        }
421cabdff1aSopenharmony_ci    }
422cabdff1aSopenharmony_ci    bi->next[prev] = i;
423cabdff1aSopenharmony_ci    for (bi->cno = 0; max > classes[bi->cno]; bi->cno++)
424cabdff1aSopenharmony_ci        ;
425cabdff1aSopenharmony_ci
426cabdff1aSopenharmony_ci    bi->cno += bias;
427cabdff1aSopenharmony_ci
428cabdff1aSopenharmony_ci    if (bi->cno >= 3) {
429cabdff1aSopenharmony_ci        bi->cno = 3;
430cabdff1aSopenharmony_ci        prev    = 0;
431cabdff1aSopenharmony_ci        i       = bi->next[prev];
432cabdff1aSopenharmony_ci        for (area = 0; area < 4; area++) {
433cabdff1aSopenharmony_ci            bi->prev[area]     = prev;
434cabdff1aSopenharmony_ci            bi->bit_size[area] = 1; // 4 areas 4 bits for EOB :)
435cabdff1aSopenharmony_ci            for (; i < mb_area_start[area + 1]; i = bi->next[i]) {
436cabdff1aSopenharmony_ci                bi->mb[i] >>= 1;
437cabdff1aSopenharmony_ci
438cabdff1aSopenharmony_ci                if (bi->mb[i]) {
439cabdff1aSopenharmony_ci                    bi->bit_size[area] += dv_rl2vlc_size(i - prev - 1, bi->mb[i]);
440cabdff1aSopenharmony_ci                    bi->next[prev]      = i;
441cabdff1aSopenharmony_ci                    prev                = i;
442cabdff1aSopenharmony_ci                }
443cabdff1aSopenharmony_ci            }
444cabdff1aSopenharmony_ci        }
445cabdff1aSopenharmony_ci        bi->next[prev] = i;
446cabdff1aSopenharmony_ci    }
447cabdff1aSopenharmony_ci
448cabdff1aSopenharmony_ci    return bi->bit_size[0] + bi->bit_size[1] +
449cabdff1aSopenharmony_ci           bi->bit_size[2] + bi->bit_size[3];
450cabdff1aSopenharmony_ci}
451cabdff1aSopenharmony_ci
452cabdff1aSopenharmony_ci/* this function just copies the DCT coefficients and performs
453cabdff1aSopenharmony_ci   the initial (non-)quantization. */
454cabdff1aSopenharmony_cistatic inline void dv_set_class_number_hd(DVVideoContext *s,
455cabdff1aSopenharmony_ci                                          int16_t *blk, EncBlockInfo *bi,
456cabdff1aSopenharmony_ci                                          const uint8_t *zigzag_scan,
457cabdff1aSopenharmony_ci                                          const int *weight, int bias)
458cabdff1aSopenharmony_ci{
459cabdff1aSopenharmony_ci    int i, max = 0;
460cabdff1aSopenharmony_ci
461cabdff1aSopenharmony_ci    /* the first quantization (none at all) */
462cabdff1aSopenharmony_ci    bi->area_q[0] = 1;
463cabdff1aSopenharmony_ci
464cabdff1aSopenharmony_ci    /* weigh AC components and store to save[] */
465cabdff1aSopenharmony_ci    /* (i=0 is the DC component; we only include it to make the
466cabdff1aSopenharmony_ci       number of loop iterations even, for future possible SIMD optimization) */
467cabdff1aSopenharmony_ci    for (i = 0; i < 64; i += 2) {
468cabdff1aSopenharmony_ci        int level0, level1;
469cabdff1aSopenharmony_ci
470cabdff1aSopenharmony_ci        /* get the AC component (in zig-zag order) */
471cabdff1aSopenharmony_ci        level0 = blk[zigzag_scan[i+0]];
472cabdff1aSopenharmony_ci        level1 = blk[zigzag_scan[i+1]];
473cabdff1aSopenharmony_ci
474cabdff1aSopenharmony_ci        /* extract sign and make it the lowest bit */
475cabdff1aSopenharmony_ci        bi->sign[i+0] = (level0>>31)&1;
476cabdff1aSopenharmony_ci        bi->sign[i+1] = (level1>>31)&1;
477cabdff1aSopenharmony_ci
478cabdff1aSopenharmony_ci        /* take absolute value of the level */
479cabdff1aSopenharmony_ci        level0 = FFABS(level0);
480cabdff1aSopenharmony_ci        level1 = FFABS(level1);
481cabdff1aSopenharmony_ci
482cabdff1aSopenharmony_ci        /* weigh it */
483cabdff1aSopenharmony_ci        level0 = (level0*weight[i+0] + 4096 + (1<<17)) >> 18;
484cabdff1aSopenharmony_ci        level1 = (level1*weight[i+1] + 4096 + (1<<17)) >> 18;
485cabdff1aSopenharmony_ci
486cabdff1aSopenharmony_ci        /* save unquantized value */
487cabdff1aSopenharmony_ci        bi->save[i+0] = level0;
488cabdff1aSopenharmony_ci        bi->save[i+1] = level1;
489cabdff1aSopenharmony_ci
490cabdff1aSopenharmony_ci         /* find max component */
491cabdff1aSopenharmony_ci        if (bi->save[i+0] > max)
492cabdff1aSopenharmony_ci            max = bi->save[i+0];
493cabdff1aSopenharmony_ci        if (bi->save[i+1] > max)
494cabdff1aSopenharmony_ci            max = bi->save[i+1];
495cabdff1aSopenharmony_ci    }
496cabdff1aSopenharmony_ci
497cabdff1aSopenharmony_ci    /* copy DC component */
498cabdff1aSopenharmony_ci    bi->mb[0] = blk[0];
499cabdff1aSopenharmony_ci
500cabdff1aSopenharmony_ci    /* the EOB code is 4 bits */
501cabdff1aSopenharmony_ci    bi->bit_size[0] = 4;
502cabdff1aSopenharmony_ci    bi->bit_size[1] = bi->bit_size[2] = bi->bit_size[3] = 0;
503cabdff1aSopenharmony_ci
504cabdff1aSopenharmony_ci    /* ensure that no AC coefficients are cut off */
505cabdff1aSopenharmony_ci    bi->min_qlevel = ((max+256) >> 8);
506cabdff1aSopenharmony_ci
507cabdff1aSopenharmony_ci    bi->area_q[0] = 25; /* set to an "impossible" value */
508cabdff1aSopenharmony_ci    bi->cno = 0;
509cabdff1aSopenharmony_ci}
510cabdff1aSopenharmony_ci
511cabdff1aSopenharmony_cistatic av_always_inline int dv_init_enc_block(EncBlockInfo* bi, uint8_t *data, int linesize,
512cabdff1aSopenharmony_ci                                              DVVideoContext *s, int chroma)
513cabdff1aSopenharmony_ci{
514cabdff1aSopenharmony_ci    LOCAL_ALIGNED_16(int16_t, blk, [64]);
515cabdff1aSopenharmony_ci
516cabdff1aSopenharmony_ci    bi->area_q[0] = bi->area_q[1] = bi->area_q[2] = bi->area_q[3] = 0;
517cabdff1aSopenharmony_ci    bi->partial_bit_count = 0;
518cabdff1aSopenharmony_ci    bi->partial_bit_buffer = 0;
519cabdff1aSopenharmony_ci    bi->cur_ac = 0;
520cabdff1aSopenharmony_ci
521cabdff1aSopenharmony_ci    if (data) {
522cabdff1aSopenharmony_ci        if (DV_PROFILE_IS_HD(s->sys)) {
523cabdff1aSopenharmony_ci            s->get_pixels(blk, data, linesize * (1 << bi->dct_mode));
524cabdff1aSopenharmony_ci            s->fdct[0](blk);
525cabdff1aSopenharmony_ci        } else {
526cabdff1aSopenharmony_ci            bi->dct_mode = dv_guess_dct_mode(s, data, linesize);
527cabdff1aSopenharmony_ci            s->get_pixels(blk, data, linesize);
528cabdff1aSopenharmony_ci            s->fdct[bi->dct_mode](blk);
529cabdff1aSopenharmony_ci        }
530cabdff1aSopenharmony_ci    } else {
531cabdff1aSopenharmony_ci        /* We rely on the fact that encoding all zeros leads to an immediate EOB,
532cabdff1aSopenharmony_ci           which is precisely what the spec calls for in the "dummy" blocks. */
533cabdff1aSopenharmony_ci        memset(blk, 0, 64*sizeof(*blk));
534cabdff1aSopenharmony_ci        bi->dct_mode = 0;
535cabdff1aSopenharmony_ci    }
536cabdff1aSopenharmony_ci
537cabdff1aSopenharmony_ci    if (DV_PROFILE_IS_HD(s->sys)) {
538cabdff1aSopenharmony_ci        const int *weights;
539cabdff1aSopenharmony_ci        if (s->sys->height == 1080) {
540cabdff1aSopenharmony_ci            weights = dv_weight_1080[chroma];
541cabdff1aSopenharmony_ci        } else { /* 720p */
542cabdff1aSopenharmony_ci            weights = dv_weight_720[chroma];
543cabdff1aSopenharmony_ci        }
544cabdff1aSopenharmony_ci        dv_set_class_number_hd(s, blk, bi,
545cabdff1aSopenharmony_ci                               ff_zigzag_direct,
546cabdff1aSopenharmony_ci                               weights,
547cabdff1aSopenharmony_ci                               dv100_min_bias+chroma*dv100_chroma_bias);
548cabdff1aSopenharmony_ci    } else {
549cabdff1aSopenharmony_ci        dv_set_class_number_sd(s, blk, bi,
550cabdff1aSopenharmony_ci                               bi->dct_mode ? ff_dv_zigzag248_direct : ff_zigzag_direct,
551cabdff1aSopenharmony_ci                               bi->dct_mode ? dv_weight_248 : dv_weight_88,
552cabdff1aSopenharmony_ci                               chroma);
553cabdff1aSopenharmony_ci    }
554cabdff1aSopenharmony_ci
555cabdff1aSopenharmony_ci    return bi->bit_size[0] + bi->bit_size[1] + bi->bit_size[2] + bi->bit_size[3];
556cabdff1aSopenharmony_ci}
557cabdff1aSopenharmony_ci
558cabdff1aSopenharmony_ci/* DV100 quantize
559cabdff1aSopenharmony_ci   Perform quantization by divinding the AC component by the qstep.
560cabdff1aSopenharmony_ci   As an optimization we use a fixed-point integer multiply instead
561cabdff1aSopenharmony_ci   of a divide. */
562cabdff1aSopenharmony_cistatic av_always_inline int dv100_quantize(int level, int qsinv)
563cabdff1aSopenharmony_ci{
564cabdff1aSopenharmony_ci    /* this code is equivalent to */
565cabdff1aSopenharmony_ci    /* return (level + qs/2) / qs; */
566cabdff1aSopenharmony_ci
567cabdff1aSopenharmony_ci    return (level * qsinv + 1024 + (1<<(dv100_qstep_bits-1))) >> dv100_qstep_bits;
568cabdff1aSopenharmony_ci
569cabdff1aSopenharmony_ci    /* the extra +1024 is needed to make the rounding come out right. */
570cabdff1aSopenharmony_ci
571cabdff1aSopenharmony_ci    /* I (DJM) have verified that the results are exactly the same as
572cabdff1aSopenharmony_ci       division for level 0-2048 at all QNOs. */
573cabdff1aSopenharmony_ci}
574cabdff1aSopenharmony_ci
575cabdff1aSopenharmony_cistatic int dv100_actual_quantize(EncBlockInfo *b, int qlevel)
576cabdff1aSopenharmony_ci{
577cabdff1aSopenharmony_ci    int prev, k, qsinv;
578cabdff1aSopenharmony_ci
579cabdff1aSopenharmony_ci    int qno = DV100_QLEVEL_QNO(dv100_qlevels[qlevel]);
580cabdff1aSopenharmony_ci    int cno = DV100_QLEVEL_CNO(dv100_qlevels[qlevel]);
581cabdff1aSopenharmony_ci
582cabdff1aSopenharmony_ci    if (b->area_q[0] == qno && b->cno == cno)
583cabdff1aSopenharmony_ci        return b->bit_size[0];
584cabdff1aSopenharmony_ci
585cabdff1aSopenharmony_ci    qsinv = dv100_qstep_inv[qno];
586cabdff1aSopenharmony_ci
587cabdff1aSopenharmony_ci    /* record the new qstep */
588cabdff1aSopenharmony_ci    b->area_q[0] = qno;
589cabdff1aSopenharmony_ci    b->cno = cno;
590cabdff1aSopenharmony_ci
591cabdff1aSopenharmony_ci    /* reset encoded size (EOB = 4 bits) */
592cabdff1aSopenharmony_ci    b->bit_size[0] = 4;
593cabdff1aSopenharmony_ci
594cabdff1aSopenharmony_ci    /* visit nonzero components and quantize */
595cabdff1aSopenharmony_ci    prev = 0;
596cabdff1aSopenharmony_ci    for (k = 1; k < 64; k++) {
597cabdff1aSopenharmony_ci        /* quantize */
598cabdff1aSopenharmony_ci        int ac = dv100_quantize(b->save[k], qsinv) >> cno;
599cabdff1aSopenharmony_ci        if (ac) {
600cabdff1aSopenharmony_ci            if (ac > 255)
601cabdff1aSopenharmony_ci                ac = 255;
602cabdff1aSopenharmony_ci            b->mb[k] = ac;
603cabdff1aSopenharmony_ci            b->bit_size[0] += dv_rl2vlc_size(k - prev - 1, ac);
604cabdff1aSopenharmony_ci            b->next[prev] = k;
605cabdff1aSopenharmony_ci            prev = k;
606cabdff1aSopenharmony_ci        }
607cabdff1aSopenharmony_ci    }
608cabdff1aSopenharmony_ci    b->next[prev] = k;
609cabdff1aSopenharmony_ci
610cabdff1aSopenharmony_ci    return b->bit_size[0];
611cabdff1aSopenharmony_ci}
612cabdff1aSopenharmony_ci
613cabdff1aSopenharmony_cistatic inline void dv_guess_qnos_hd(EncBlockInfo *blks, int *qnos)
614cabdff1aSopenharmony_ci{
615cabdff1aSopenharmony_ci    EncBlockInfo *b;
616cabdff1aSopenharmony_ci    int min_qlevel[5];
617cabdff1aSopenharmony_ci    int qlevels[5];
618cabdff1aSopenharmony_ci    int size[5];
619cabdff1aSopenharmony_ci    int i, j;
620cabdff1aSopenharmony_ci    /* cache block sizes at hypothetical qlevels */
621cabdff1aSopenharmony_ci    uint16_t size_cache[5*8][DV100_NUM_QLEVELS] = {{0}};
622cabdff1aSopenharmony_ci
623cabdff1aSopenharmony_ci    /* get minimum qlevels */
624cabdff1aSopenharmony_ci    for (i = 0; i < 5; i++) {
625cabdff1aSopenharmony_ci        min_qlevel[i] = 1;
626cabdff1aSopenharmony_ci        for (j = 0; j < 8; j++) {
627cabdff1aSopenharmony_ci            if (blks[8*i+j].min_qlevel > min_qlevel[i])
628cabdff1aSopenharmony_ci                min_qlevel[i] = blks[8*i+j].min_qlevel;
629cabdff1aSopenharmony_ci        }
630cabdff1aSopenharmony_ci    }
631cabdff1aSopenharmony_ci
632cabdff1aSopenharmony_ci    /* initialize sizes */
633cabdff1aSopenharmony_ci    for (i = 0; i < 5; i++) {
634cabdff1aSopenharmony_ci        qlevels[i] = dv100_starting_qno;
635cabdff1aSopenharmony_ci        if (qlevels[i] < min_qlevel[i])
636cabdff1aSopenharmony_ci            qlevels[i] = min_qlevel[i];
637cabdff1aSopenharmony_ci
638cabdff1aSopenharmony_ci        qnos[i] = DV100_QLEVEL_QNO(dv100_qlevels[qlevels[i]]);
639cabdff1aSopenharmony_ci        size[i] = 0;
640cabdff1aSopenharmony_ci        for (j = 0; j < 8; j++) {
641cabdff1aSopenharmony_ci            size_cache[8*i+j][qlevels[i]] = dv100_actual_quantize(&blks[8*i+j], qlevels[i]);
642cabdff1aSopenharmony_ci            size[i] += size_cache[8*i+j][qlevels[i]];
643cabdff1aSopenharmony_ci        }
644cabdff1aSopenharmony_ci    }
645cabdff1aSopenharmony_ci
646cabdff1aSopenharmony_ci    /* must we go coarser? */
647cabdff1aSopenharmony_ci    if (size[0]+size[1]+size[2]+size[3]+size[4] > vs_total_ac_bits_hd) {
648cabdff1aSopenharmony_ci        int largest = size[0] % 5; /* 'random' number */
649cabdff1aSopenharmony_ci        int qlevels_done = 0;
650cabdff1aSopenharmony_ci
651cabdff1aSopenharmony_ci        do {
652cabdff1aSopenharmony_ci            /* find the macroblock with the lowest qlevel */
653cabdff1aSopenharmony_ci            for (i = 0; i < 5; i++) {
654cabdff1aSopenharmony_ci                if (qlevels[i] < qlevels[largest])
655cabdff1aSopenharmony_ci                    largest = i;
656cabdff1aSopenharmony_ci            }
657cabdff1aSopenharmony_ci
658cabdff1aSopenharmony_ci            i = largest;
659cabdff1aSopenharmony_ci            /* ensure that we don't enter infinite loop */
660cabdff1aSopenharmony_ci            largest = (largest+1) % 5;
661cabdff1aSopenharmony_ci
662cabdff1aSopenharmony_ci            /* quantize a little bit more */
663cabdff1aSopenharmony_ci            qlevels[i] += dv100_qlevel_inc;
664cabdff1aSopenharmony_ci            if (qlevels[i] > DV100_NUM_QLEVELS-1) {
665cabdff1aSopenharmony_ci                qlevels[i] = DV100_NUM_QLEVELS-1;
666cabdff1aSopenharmony_ci                qlevels_done++;
667cabdff1aSopenharmony_ci            }
668cabdff1aSopenharmony_ci
669cabdff1aSopenharmony_ci            qnos[i] = DV100_QLEVEL_QNO(dv100_qlevels[qlevels[i]]);
670cabdff1aSopenharmony_ci            size[i] = 0;
671cabdff1aSopenharmony_ci
672cabdff1aSopenharmony_ci            /* for each block */
673cabdff1aSopenharmony_ci            b = &blks[8*i];
674cabdff1aSopenharmony_ci            for (j = 0; j < 8; j++, b++) {
675cabdff1aSopenharmony_ci                /* accumulate block size into macroblock */
676cabdff1aSopenharmony_ci                if(size_cache[8*i+j][qlevels[i]] == 0) {
677cabdff1aSopenharmony_ci                    /* it is safe to use actual_quantize() here because we only go from finer to coarser,
678cabdff1aSopenharmony_ci                       and it saves the final actual_quantize() down below */
679cabdff1aSopenharmony_ci                    size_cache[8*i+j][qlevels[i]] = dv100_actual_quantize(b, qlevels[i]);
680cabdff1aSopenharmony_ci                }
681cabdff1aSopenharmony_ci                size[i] += size_cache[8*i+j][qlevels[i]];
682cabdff1aSopenharmony_ci            } /* for each block */
683cabdff1aSopenharmony_ci
684cabdff1aSopenharmony_ci        } while (vs_total_ac_bits_hd < size[0] + size[1] + size[2] + size[3] + size[4] && qlevels_done < 5);
685cabdff1aSopenharmony_ci
686cabdff1aSopenharmony_ci        // can we go finer?
687cabdff1aSopenharmony_ci    } else if (DV100_ENABLE_FINER &&
688cabdff1aSopenharmony_ci               size[0]+size[1]+size[2]+size[3]+size[4] < vs_total_ac_bits_hd) {
689cabdff1aSopenharmony_ci        int save_qlevel;
690cabdff1aSopenharmony_ci        int largest = size[0] % 5; /* 'random' number */
691cabdff1aSopenharmony_ci
692cabdff1aSopenharmony_ci        while (qlevels[0] > min_qlevel[0] ||
693cabdff1aSopenharmony_ci               qlevels[1] > min_qlevel[1] ||
694cabdff1aSopenharmony_ci               qlevels[2] > min_qlevel[2] ||
695cabdff1aSopenharmony_ci               qlevels[3] > min_qlevel[3] ||
696cabdff1aSopenharmony_ci               qlevels[4] > min_qlevel[4]) {
697cabdff1aSopenharmony_ci
698cabdff1aSopenharmony_ci            /* find the macroblock with the highest qlevel */
699cabdff1aSopenharmony_ci            for (i = 0; i < 5; i++) {
700cabdff1aSopenharmony_ci                if (qlevels[i] > min_qlevel[i] && qlevels[i] > qlevels[largest])
701cabdff1aSopenharmony_ci                    largest = i;
702cabdff1aSopenharmony_ci            }
703cabdff1aSopenharmony_ci
704cabdff1aSopenharmony_ci            i = largest;
705cabdff1aSopenharmony_ci
706cabdff1aSopenharmony_ci            /* ensure that we don't enter infinite loop */
707cabdff1aSopenharmony_ci            largest = (largest+1) % 5;
708cabdff1aSopenharmony_ci
709cabdff1aSopenharmony_ci            if (qlevels[i] <= min_qlevel[i]) {
710cabdff1aSopenharmony_ci                /* can't unquantize any more */
711cabdff1aSopenharmony_ci                continue;
712cabdff1aSopenharmony_ci            }
713cabdff1aSopenharmony_ci            /* quantize a little bit less */
714cabdff1aSopenharmony_ci            save_qlevel = qlevels[i];
715cabdff1aSopenharmony_ci            qlevels[i] -= dv100_qlevel_inc;
716cabdff1aSopenharmony_ci            if (qlevels[i] < min_qlevel[i])
717cabdff1aSopenharmony_ci                qlevels[i] = min_qlevel[i];
718cabdff1aSopenharmony_ci
719cabdff1aSopenharmony_ci            qnos[i] = DV100_QLEVEL_QNO(dv100_qlevels[qlevels[i]]);
720cabdff1aSopenharmony_ci
721cabdff1aSopenharmony_ci            size[i] = 0;
722cabdff1aSopenharmony_ci
723cabdff1aSopenharmony_ci            /* for each block */
724cabdff1aSopenharmony_ci            b = &blks[8*i];
725cabdff1aSopenharmony_ci            for (j = 0; j < 8; j++, b++) {
726cabdff1aSopenharmony_ci                /* accumulate block size into macroblock */
727cabdff1aSopenharmony_ci                if(size_cache[8*i+j][qlevels[i]] == 0) {
728cabdff1aSopenharmony_ci                    size_cache[8*i+j][qlevels[i]] = dv100_actual_quantize(b, qlevels[i]);
729cabdff1aSopenharmony_ci                }
730cabdff1aSopenharmony_ci                size[i] += size_cache[8*i+j][qlevels[i]];
731cabdff1aSopenharmony_ci            } /* for each block */
732cabdff1aSopenharmony_ci
733cabdff1aSopenharmony_ci            /* did we bust the limit? */
734cabdff1aSopenharmony_ci            if (vs_total_ac_bits_hd < size[0] + size[1] + size[2] + size[3] + size[4]) {
735cabdff1aSopenharmony_ci                /* go back down and exit */
736cabdff1aSopenharmony_ci                qlevels[i] = save_qlevel;
737cabdff1aSopenharmony_ci                qnos[i] = DV100_QLEVEL_QNO(dv100_qlevels[qlevels[i]]);
738cabdff1aSopenharmony_ci                break;
739cabdff1aSopenharmony_ci            }
740cabdff1aSopenharmony_ci        }
741cabdff1aSopenharmony_ci    }
742cabdff1aSopenharmony_ci
743cabdff1aSopenharmony_ci    /* now do the actual quantization */
744cabdff1aSopenharmony_ci    for (i = 0; i < 5; i++) {
745cabdff1aSopenharmony_ci        /* for each block */
746cabdff1aSopenharmony_ci        b = &blks[8*i];
747cabdff1aSopenharmony_ci        size[i] = 0;
748cabdff1aSopenharmony_ci        for (j = 0; j < 8; j++, b++) {
749cabdff1aSopenharmony_ci            /* accumulate block size into macroblock */
750cabdff1aSopenharmony_ci            size[i] += dv100_actual_quantize(b, qlevels[i]);
751cabdff1aSopenharmony_ci        } /* for each block */
752cabdff1aSopenharmony_ci    }
753cabdff1aSopenharmony_ci}
754cabdff1aSopenharmony_ci
755cabdff1aSopenharmony_cistatic inline void dv_guess_qnos(EncBlockInfo *blks, int *qnos)
756cabdff1aSopenharmony_ci{
757cabdff1aSopenharmony_ci    int size[5];
758cabdff1aSopenharmony_ci    int i, j, k, a, prev, a2;
759cabdff1aSopenharmony_ci    EncBlockInfo *b;
760cabdff1aSopenharmony_ci
761cabdff1aSopenharmony_ci    size[0] =
762cabdff1aSopenharmony_ci    size[1] =
763cabdff1aSopenharmony_ci    size[2] =
764cabdff1aSopenharmony_ci    size[3] =
765cabdff1aSopenharmony_ci    size[4] = 1 << 24;
766cabdff1aSopenharmony_ci    do {
767cabdff1aSopenharmony_ci        b = blks;
768cabdff1aSopenharmony_ci        for (i = 0; i < 5; i++) {
769cabdff1aSopenharmony_ci            if (!qnos[i])
770cabdff1aSopenharmony_ci                continue;
771cabdff1aSopenharmony_ci
772cabdff1aSopenharmony_ci            qnos[i]--;
773cabdff1aSopenharmony_ci            size[i] = 0;
774cabdff1aSopenharmony_ci            for (j = 0; j < 6; j++, b++) {
775cabdff1aSopenharmony_ci                for (a = 0; a < 4; a++) {
776cabdff1aSopenharmony_ci                    if (b->area_q[a] != ff_dv_quant_shifts[qnos[i] + ff_dv_quant_offset[b->cno]][a]) {
777cabdff1aSopenharmony_ci                        b->bit_size[a] = 1; // 4 areas 4 bits for EOB :)
778cabdff1aSopenharmony_ci                        b->area_q[a]++;
779cabdff1aSopenharmony_ci                        prev = b->prev[a];
780cabdff1aSopenharmony_ci                        av_assert2(b->next[prev] >= mb_area_start[a + 1] || b->mb[prev]);
781cabdff1aSopenharmony_ci                        for (k = b->next[prev]; k < mb_area_start[a + 1]; k = b->next[k]) {
782cabdff1aSopenharmony_ci                            b->mb[k] >>= 1;
783cabdff1aSopenharmony_ci                            if (b->mb[k]) {
784cabdff1aSopenharmony_ci                                b->bit_size[a] += dv_rl2vlc_size(k - prev - 1, b->mb[k]);
785cabdff1aSopenharmony_ci                                prev            = k;
786cabdff1aSopenharmony_ci                            } else {
787cabdff1aSopenharmony_ci                                if (b->next[k] >= mb_area_start[a + 1] && b->next[k] < 64) {
788cabdff1aSopenharmony_ci                                    for (a2 = a + 1; b->next[k] >= mb_area_start[a2 + 1]; a2++)
789cabdff1aSopenharmony_ci                                        b->prev[a2] = prev;
790cabdff1aSopenharmony_ci                                    av_assert2(a2 < 4);
791cabdff1aSopenharmony_ci                                    av_assert2(b->mb[b->next[k]]);
792cabdff1aSopenharmony_ci                                    b->bit_size[a2] += dv_rl2vlc_size(b->next[k] - prev - 1, b->mb[b->next[k]]) -
793cabdff1aSopenharmony_ci                                                       dv_rl2vlc_size(b->next[k] - k    - 1, b->mb[b->next[k]]);
794cabdff1aSopenharmony_ci                                    av_assert2(b->prev[a2] == k && (a2 + 1 >= 4 || b->prev[a2 + 1] != k));
795cabdff1aSopenharmony_ci                                    b->prev[a2] = prev;
796cabdff1aSopenharmony_ci                                }
797cabdff1aSopenharmony_ci                                b->next[prev] = b->next[k];
798cabdff1aSopenharmony_ci                            }
799cabdff1aSopenharmony_ci                        }
800cabdff1aSopenharmony_ci                        b->prev[a + 1] = prev;
801cabdff1aSopenharmony_ci                    }
802cabdff1aSopenharmony_ci                    size[i] += b->bit_size[a];
803cabdff1aSopenharmony_ci                }
804cabdff1aSopenharmony_ci            }
805cabdff1aSopenharmony_ci            if (vs_total_ac_bits >= size[0] + size[1] + size[2] + size[3] + size[4])
806cabdff1aSopenharmony_ci                return;
807cabdff1aSopenharmony_ci        }
808cabdff1aSopenharmony_ci    } while (qnos[0] | qnos[1] | qnos[2] | qnos[3] | qnos[4]);
809cabdff1aSopenharmony_ci
810cabdff1aSopenharmony_ci    for (a = 2; a == 2 || vs_total_ac_bits < size[0]; a += a) {
811cabdff1aSopenharmony_ci        b       = blks;
812cabdff1aSopenharmony_ci        size[0] = 5 * 6 * 4; // EOB
813cabdff1aSopenharmony_ci        for (j = 0; j < 6 * 5; j++, b++) {
814cabdff1aSopenharmony_ci            prev = b->prev[0];
815cabdff1aSopenharmony_ci            for (k = b->next[prev]; k < 64; k = b->next[k]) {
816cabdff1aSopenharmony_ci                if (b->mb[k] < a && b->mb[k] > -a) {
817cabdff1aSopenharmony_ci                    b->next[prev] = b->next[k];
818cabdff1aSopenharmony_ci                } else {
819cabdff1aSopenharmony_ci                    size[0] += dv_rl2vlc_size(k - prev - 1, b->mb[k]);
820cabdff1aSopenharmony_ci                    prev     = k;
821cabdff1aSopenharmony_ci                }
822cabdff1aSopenharmony_ci            }
823cabdff1aSopenharmony_ci        }
824cabdff1aSopenharmony_ci    }
825cabdff1aSopenharmony_ci}
826cabdff1aSopenharmony_ci
827cabdff1aSopenharmony_ci/* update all cno values into the blocks, over-writing the old values without
828cabdff1aSopenharmony_ci   touching anything else. (only used for DV100) */
829cabdff1aSopenharmony_cistatic inline void dv_revise_cnos(uint8_t *dif, EncBlockInfo *blk, const AVDVProfile *profile)
830cabdff1aSopenharmony_ci{
831cabdff1aSopenharmony_ci    uint8_t *data;
832cabdff1aSopenharmony_ci    int mb_index, i;
833cabdff1aSopenharmony_ci
834cabdff1aSopenharmony_ci    for (mb_index = 0; mb_index < 5; mb_index++) {
835cabdff1aSopenharmony_ci        data = dif + mb_index*80 + 4;
836cabdff1aSopenharmony_ci        for (i = 0; i < profile->bpm; i++) {
837cabdff1aSopenharmony_ci            /* zero out the class number */
838cabdff1aSopenharmony_ci            data[1] &= 0xCF;
839cabdff1aSopenharmony_ci            /* add the new one */
840cabdff1aSopenharmony_ci            data[1] |= blk[profile->bpm*mb_index+i].cno << 4;
841cabdff1aSopenharmony_ci
842cabdff1aSopenharmony_ci            data += profile->block_sizes[i] >> 3;
843cabdff1aSopenharmony_ci        }
844cabdff1aSopenharmony_ci    }
845cabdff1aSopenharmony_ci}
846cabdff1aSopenharmony_ci
847cabdff1aSopenharmony_cistatic int dv_encode_video_segment(AVCodecContext *avctx, void *arg)
848cabdff1aSopenharmony_ci{
849cabdff1aSopenharmony_ci    DVVideoContext *s = avctx->priv_data;
850cabdff1aSopenharmony_ci    DVwork_chunk *work_chunk = arg;
851cabdff1aSopenharmony_ci    int mb_index, i, j;
852cabdff1aSopenharmony_ci    int mb_x, mb_y, c_offset;
853cabdff1aSopenharmony_ci    ptrdiff_t linesize, y_stride;
854cabdff1aSopenharmony_ci    uint8_t *y_ptr;
855cabdff1aSopenharmony_ci    uint8_t *dif, *p;
856cabdff1aSopenharmony_ci    LOCAL_ALIGNED_8(uint8_t, scratch, [128]);
857cabdff1aSopenharmony_ci    EncBlockInfo enc_blks[5 * DV_MAX_BPM];
858cabdff1aSopenharmony_ci    PutBitContext pbs[5 * DV_MAX_BPM];
859cabdff1aSopenharmony_ci    PutBitContext *pb;
860cabdff1aSopenharmony_ci    EncBlockInfo *enc_blk;
861cabdff1aSopenharmony_ci    int vs_bit_size = 0;
862cabdff1aSopenharmony_ci    int qnos[5];
863cabdff1aSopenharmony_ci    int *qnosp = &qnos[0];
864cabdff1aSopenharmony_ci
865cabdff1aSopenharmony_ci    p = dif = &s->buf[work_chunk->buf_offset * 80];
866cabdff1aSopenharmony_ci    enc_blk = &enc_blks[0];
867cabdff1aSopenharmony_ci    for (mb_index = 0; mb_index < 5; mb_index++) {
868cabdff1aSopenharmony_ci        dv_calculate_mb_xy(s, work_chunk, mb_index, &mb_x, &mb_y);
869cabdff1aSopenharmony_ci
870cabdff1aSopenharmony_ci        qnos[mb_index] = DV_PROFILE_IS_HD(s->sys) ? 1 : 15;
871cabdff1aSopenharmony_ci
872cabdff1aSopenharmony_ci        y_ptr    = s->frame->data[0] + (mb_y * s->frame->linesize[0] + mb_x) * 8;
873cabdff1aSopenharmony_ci        linesize = s->frame->linesize[0];
874cabdff1aSopenharmony_ci
875cabdff1aSopenharmony_ci        if (s->sys->height == 1080 && mb_y < 134)
876cabdff1aSopenharmony_ci            enc_blk->dct_mode = dv_guess_dct_mode(s, y_ptr, linesize);
877cabdff1aSopenharmony_ci        else
878cabdff1aSopenharmony_ci            enc_blk->dct_mode = 0;
879cabdff1aSopenharmony_ci        for (i = 1; i < 8; i++)
880cabdff1aSopenharmony_ci            enc_blk[i].dct_mode = enc_blk->dct_mode;
881cabdff1aSopenharmony_ci
882cabdff1aSopenharmony_ci        /* initializing luminance blocks */
883cabdff1aSopenharmony_ci        if ((s->sys->pix_fmt == AV_PIX_FMT_YUV420P)                      ||
884cabdff1aSopenharmony_ci            (s->sys->pix_fmt == AV_PIX_FMT_YUV411P && mb_x >= (704 / 8)) ||
885cabdff1aSopenharmony_ci            (s->sys->height >= 720 && mb_y != 134)) {
886cabdff1aSopenharmony_ci            y_stride = s->frame->linesize[0] * (1 << (3*!enc_blk->dct_mode));
887cabdff1aSopenharmony_ci        } else {
888cabdff1aSopenharmony_ci            y_stride = 16;
889cabdff1aSopenharmony_ci        }
890cabdff1aSopenharmony_ci        y_ptr    = s->frame->data[0] +
891cabdff1aSopenharmony_ci                   (mb_y * s->frame->linesize[0] + mb_x) * 8;
892cabdff1aSopenharmony_ci        linesize = s->frame->linesize[0];
893cabdff1aSopenharmony_ci
894cabdff1aSopenharmony_ci        if (s->sys->video_stype == 4) { /* SD 422 */
895cabdff1aSopenharmony_ci            vs_bit_size +=
896cabdff1aSopenharmony_ci                dv_init_enc_block(enc_blk + 0, y_ptr,                linesize, s, 0) +
897cabdff1aSopenharmony_ci                dv_init_enc_block(enc_blk + 1, NULL,                 linesize, s, 0) +
898cabdff1aSopenharmony_ci                dv_init_enc_block(enc_blk + 2, y_ptr + 8,            linesize, s, 0) +
899cabdff1aSopenharmony_ci                dv_init_enc_block(enc_blk + 3, NULL,                 linesize, s, 0);
900cabdff1aSopenharmony_ci        } else {
901cabdff1aSopenharmony_ci            vs_bit_size +=
902cabdff1aSopenharmony_ci                dv_init_enc_block(enc_blk + 0, y_ptr,                linesize, s, 0) +
903cabdff1aSopenharmony_ci                dv_init_enc_block(enc_blk + 1, y_ptr + 8,            linesize, s, 0) +
904cabdff1aSopenharmony_ci                dv_init_enc_block(enc_blk + 2, y_ptr +     y_stride, linesize, s, 0) +
905cabdff1aSopenharmony_ci                dv_init_enc_block(enc_blk + 3, y_ptr + 8 + y_stride, linesize, s, 0);
906cabdff1aSopenharmony_ci        }
907cabdff1aSopenharmony_ci        enc_blk += 4;
908cabdff1aSopenharmony_ci
909cabdff1aSopenharmony_ci        /* initializing chrominance blocks */
910cabdff1aSopenharmony_ci        c_offset = ((mb_y >>  (s->sys->pix_fmt == AV_PIX_FMT_YUV420P)) * s->frame->linesize[1] +
911cabdff1aSopenharmony_ci                    (mb_x >> ((s->sys->pix_fmt == AV_PIX_FMT_YUV411P) ? 2 : 1))) * 8;
912cabdff1aSopenharmony_ci        for (j = 2; j; j--) {
913cabdff1aSopenharmony_ci            uint8_t *c_ptr = s->frame->data[j] + c_offset;
914cabdff1aSopenharmony_ci            linesize = s->frame->linesize[j];
915cabdff1aSopenharmony_ci            y_stride = (mb_y == 134) ? 8 : (s->frame->linesize[j] * (1 << (3*!enc_blk->dct_mode)));
916cabdff1aSopenharmony_ci            if (s->sys->pix_fmt == AV_PIX_FMT_YUV411P && mb_x >= (704 / 8)) {
917cabdff1aSopenharmony_ci                uint8_t *d;
918cabdff1aSopenharmony_ci                uint8_t *b = scratch;
919cabdff1aSopenharmony_ci                for (i = 0; i < 8; i++) {
920cabdff1aSopenharmony_ci                    d      = c_ptr + linesize * 8;
921cabdff1aSopenharmony_ci                    b[0]   = c_ptr[0];
922cabdff1aSopenharmony_ci                    b[1]   = c_ptr[1];
923cabdff1aSopenharmony_ci                    b[2]   = c_ptr[2];
924cabdff1aSopenharmony_ci                    b[3]   = c_ptr[3];
925cabdff1aSopenharmony_ci                    b[4]   = d[0];
926cabdff1aSopenharmony_ci                    b[5]   = d[1];
927cabdff1aSopenharmony_ci                    b[6]   = d[2];
928cabdff1aSopenharmony_ci                    b[7]   = d[3];
929cabdff1aSopenharmony_ci                    c_ptr += linesize;
930cabdff1aSopenharmony_ci                    b     += 16;
931cabdff1aSopenharmony_ci                }
932cabdff1aSopenharmony_ci                c_ptr    = scratch;
933cabdff1aSopenharmony_ci                linesize = 16;
934cabdff1aSopenharmony_ci            }
935cabdff1aSopenharmony_ci
936cabdff1aSopenharmony_ci            vs_bit_size += dv_init_enc_block(enc_blk++, c_ptr, linesize, s, 1);
937cabdff1aSopenharmony_ci            if (s->sys->bpm == 8)
938cabdff1aSopenharmony_ci                vs_bit_size += dv_init_enc_block(enc_blk++, c_ptr + y_stride,
939cabdff1aSopenharmony_ci                                                 linesize, s, 1);
940cabdff1aSopenharmony_ci        }
941cabdff1aSopenharmony_ci    }
942cabdff1aSopenharmony_ci
943cabdff1aSopenharmony_ci    if (DV_PROFILE_IS_HD(s->sys)) {
944cabdff1aSopenharmony_ci        /* unconditional */
945cabdff1aSopenharmony_ci        dv_guess_qnos_hd(&enc_blks[0], qnosp);
946cabdff1aSopenharmony_ci    } else if (vs_total_ac_bits < vs_bit_size) {
947cabdff1aSopenharmony_ci        dv_guess_qnos(&enc_blks[0], qnosp);
948cabdff1aSopenharmony_ci    }
949cabdff1aSopenharmony_ci
950cabdff1aSopenharmony_ci    /* DIF encoding process */
951cabdff1aSopenharmony_ci    for (j = 0; j < 5 * s->sys->bpm;) {
952cabdff1aSopenharmony_ci        int start_mb = j;
953cabdff1aSopenharmony_ci
954cabdff1aSopenharmony_ci        p[3] = *qnosp++;
955cabdff1aSopenharmony_ci        p += 4;
956cabdff1aSopenharmony_ci
957cabdff1aSopenharmony_ci        /* First pass over individual cells only */
958cabdff1aSopenharmony_ci        for (i = 0; i < s->sys->bpm; i++, j++) {
959cabdff1aSopenharmony_ci            int sz = s->sys->block_sizes[i] >> 3;
960cabdff1aSopenharmony_ci
961cabdff1aSopenharmony_ci            init_put_bits(&pbs[j], p, sz);
962cabdff1aSopenharmony_ci            put_sbits(&pbs[j], 9, ((enc_blks[j].mb[0] >> 3) - 1024 + 2) >> 2);
963cabdff1aSopenharmony_ci            put_bits(&pbs[j], 1, DV_PROFILE_IS_HD(s->sys) && i ? 1 : enc_blks[j].dct_mode);
964cabdff1aSopenharmony_ci            put_bits(&pbs[j], 2, enc_blks[j].cno);
965cabdff1aSopenharmony_ci
966cabdff1aSopenharmony_ci            dv_encode_ac(&enc_blks[j], &pbs[j], &pbs[j + 1]);
967cabdff1aSopenharmony_ci            p += sz;
968cabdff1aSopenharmony_ci        }
969cabdff1aSopenharmony_ci
970cabdff1aSopenharmony_ci        /* Second pass over each MB space */
971cabdff1aSopenharmony_ci        pb = &pbs[start_mb];
972cabdff1aSopenharmony_ci        for (i = 0; i < s->sys->bpm; i++)
973cabdff1aSopenharmony_ci            if (enc_blks[start_mb + i].partial_bit_count)
974cabdff1aSopenharmony_ci                pb = dv_encode_ac(&enc_blks[start_mb + i], pb,
975cabdff1aSopenharmony_ci                                  &pbs[start_mb + s->sys->bpm]);
976cabdff1aSopenharmony_ci    }
977cabdff1aSopenharmony_ci
978cabdff1aSopenharmony_ci    /* Third and final pass over the whole video segment space */
979cabdff1aSopenharmony_ci    pb = &pbs[0];
980cabdff1aSopenharmony_ci    for (j = 0; j < 5 * s->sys->bpm; j++) {
981cabdff1aSopenharmony_ci        if (enc_blks[j].partial_bit_count)
982cabdff1aSopenharmony_ci            pb = dv_encode_ac(&enc_blks[j], pb, &pbs[s->sys->bpm * 5]);
983cabdff1aSopenharmony_ci        if (enc_blks[j].partial_bit_count)
984cabdff1aSopenharmony_ci            av_log(avctx, AV_LOG_ERROR, "ac bitstream overflow\n");
985cabdff1aSopenharmony_ci    }
986cabdff1aSopenharmony_ci
987cabdff1aSopenharmony_ci    for (j = 0; j < 5 * s->sys->bpm; j++) {
988cabdff1aSopenharmony_ci        flush_put_bits(&pbs[j]);
989cabdff1aSopenharmony_ci        memset(put_bits_ptr(&pbs[j]), 0xff, put_bytes_left(&pbs[j], 0));
990cabdff1aSopenharmony_ci    }
991cabdff1aSopenharmony_ci
992cabdff1aSopenharmony_ci    if (DV_PROFILE_IS_HD(s->sys))
993cabdff1aSopenharmony_ci        dv_revise_cnos(dif, enc_blks, s->sys);
994cabdff1aSopenharmony_ci
995cabdff1aSopenharmony_ci    return 0;
996cabdff1aSopenharmony_ci}
997cabdff1aSopenharmony_ci
998cabdff1aSopenharmony_cistatic inline int dv_write_pack(enum dv_pack_type pack_id, DVVideoContext *c,
999cabdff1aSopenharmony_ci                                uint8_t *buf)
1000cabdff1aSopenharmony_ci{
1001cabdff1aSopenharmony_ci    /*
1002cabdff1aSopenharmony_ci     * Here's what SMPTE314M says about these two:
1003cabdff1aSopenharmony_ci     *    (page 6) APTn, AP1n, AP2n, AP3n: These data shall be identical
1004cabdff1aSopenharmony_ci     *             as track application IDs (APTn = 001, AP1n =
1005cabdff1aSopenharmony_ci     *             001, AP2n = 001, AP3n = 001), if the source signal
1006cabdff1aSopenharmony_ci     *             comes from a digital VCR. If the signal source is
1007cabdff1aSopenharmony_ci     *             unknown, all bits for these data shall be set to 1.
1008cabdff1aSopenharmony_ci     *    (page 12) STYPE: STYPE defines a signal type of video signal
1009cabdff1aSopenharmony_ci     *                     00000b = 4:1:1 compression
1010cabdff1aSopenharmony_ci     *                     00100b = 4:2:2 compression
1011cabdff1aSopenharmony_ci     *                     XXXXXX = Reserved
1012cabdff1aSopenharmony_ci     * Now, I've got two problems with these statements:
1013cabdff1aSopenharmony_ci     *   1. it looks like APT == 111b should be a safe bet, but it isn't.
1014cabdff1aSopenharmony_ci     *      It seems that for PAL as defined in IEC 61834 we have to set
1015cabdff1aSopenharmony_ci     *      APT to 000 and for SMPTE314M to 001.
1016cabdff1aSopenharmony_ci     *   2. It is not at all clear what STYPE is used for 4:2:0 PAL
1017cabdff1aSopenharmony_ci     *      compression scheme (if any).
1018cabdff1aSopenharmony_ci     */
1019cabdff1aSopenharmony_ci    uint8_t aspect = 0;
1020cabdff1aSopenharmony_ci    int apt = (c->sys->pix_fmt == AV_PIX_FMT_YUV420P ? 0 : 1);
1021cabdff1aSopenharmony_ci    int fs;
1022cabdff1aSopenharmony_ci
1023cabdff1aSopenharmony_ci    if (c->avctx->height >= 720)
1024cabdff1aSopenharmony_ci        fs = c->avctx->height == 720 || c->frame->top_field_first ? 0x40 : 0x00;
1025cabdff1aSopenharmony_ci    else
1026cabdff1aSopenharmony_ci        fs = c->frame->top_field_first ? 0x00 : 0x40;
1027cabdff1aSopenharmony_ci
1028cabdff1aSopenharmony_ci    if (DV_PROFILE_IS_HD(c->sys) ||
1029cabdff1aSopenharmony_ci        (int)(av_q2d(c->avctx->sample_aspect_ratio) *
1030cabdff1aSopenharmony_ci              c->avctx->width / c->avctx->height * 10) >= 17)
1031cabdff1aSopenharmony_ci        /* HD formats are always 16:9 */
1032cabdff1aSopenharmony_ci        aspect = 0x02;
1033cabdff1aSopenharmony_ci
1034cabdff1aSopenharmony_ci    buf[0] = (uint8_t) pack_id;
1035cabdff1aSopenharmony_ci    switch (pack_id) {
1036cabdff1aSopenharmony_ci    case dv_header525: /* I can't imagine why these two weren't defined as real */
1037cabdff1aSopenharmony_ci    case dv_header625: /* packs in SMPTE314M -- they definitely look like ones */
1038cabdff1aSopenharmony_ci        buf[1] =  0xf8       | /* reserved -- always 1 */
1039cabdff1aSopenharmony_ci                 (apt & 0x07); /* APT: Track application ID */
1040cabdff1aSopenharmony_ci        buf[2] = (0    << 7) | /* TF1: audio data is 0 - valid; 1 - invalid */
1041cabdff1aSopenharmony_ci                 (0x0f << 3) | /* reserved -- always 1 */
1042cabdff1aSopenharmony_ci                 (apt & 0x07); /* AP1: Audio application ID */
1043cabdff1aSopenharmony_ci        buf[3] = (0    << 7) | /* TF2: video data is 0 - valid; 1 - invalid */
1044cabdff1aSopenharmony_ci                 (0x0f << 3) | /* reserved -- always 1 */
1045cabdff1aSopenharmony_ci                 (apt & 0x07); /* AP2: Video application ID */
1046cabdff1aSopenharmony_ci        buf[4] = (0    << 7) | /* TF3: subcode(SSYB) is 0 - valid; 1 - invalid */
1047cabdff1aSopenharmony_ci                 (0x0f << 3) | /* reserved -- always 1 */
1048cabdff1aSopenharmony_ci                 (apt & 0x07); /* AP3: Subcode application ID */
1049cabdff1aSopenharmony_ci        break;
1050cabdff1aSopenharmony_ci    case dv_video_source:
1051cabdff1aSopenharmony_ci        buf[1] = 0xff;         /* reserved -- always 1 */
1052cabdff1aSopenharmony_ci        buf[2] = (1 << 7) |    /* B/W: 0 - b/w, 1 - color */
1053cabdff1aSopenharmony_ci                 (1 << 6) |    /* following CLF is valid - 0, invalid - 1 */
1054cabdff1aSopenharmony_ci                 (3 << 4) |    /* CLF: color frames ID (see ITU-R BT.470-4) */
1055cabdff1aSopenharmony_ci                 0xf;          /* reserved -- always 1 */
1056cabdff1aSopenharmony_ci        buf[3] = (3 << 6)           | /* reserved -- always 1 */
1057cabdff1aSopenharmony_ci                 (c->sys->dsf << 5) | /*  system: 60fields/50fields */
1058cabdff1aSopenharmony_ci                 c->sys->video_stype; /* signal type video compression */
1059cabdff1aSopenharmony_ci        buf[4] = 0xff;         /* VISC: 0xff -- no information */
1060cabdff1aSopenharmony_ci        break;
1061cabdff1aSopenharmony_ci    case dv_video_control:
1062cabdff1aSopenharmony_ci        buf[1] = (0 << 6) |    /* Copy generation management (CGMS) 0 -- free */
1063cabdff1aSopenharmony_ci                 0x3f;         /* reserved -- always 1 */
1064cabdff1aSopenharmony_ci        buf[2] = 0xc8 |        /* reserved -- always b11001xxx */
1065cabdff1aSopenharmony_ci                 aspect;
1066cabdff1aSopenharmony_ci        buf[3] = (1 << 7) |    /* frame/field flag 1 -- frame, 0 -- field */
1067cabdff1aSopenharmony_ci                 fs       |    /* first/second field flag 0 -- field 2, 1 -- field 1 */
1068cabdff1aSopenharmony_ci                 (1 << 5) |    /* frame change flag 0 -- same picture as before, 1 -- different */
1069cabdff1aSopenharmony_ci                 (1 << 4) |    /* 1 - interlaced, 0 - noninterlaced */
1070cabdff1aSopenharmony_ci                 0xc;          /* reserved -- always b1100 */
1071cabdff1aSopenharmony_ci        buf[4] = 0xff;         /* reserved -- always 1 */
1072cabdff1aSopenharmony_ci        break;
1073cabdff1aSopenharmony_ci    default:
1074cabdff1aSopenharmony_ci        buf[1] =
1075cabdff1aSopenharmony_ci        buf[2] =
1076cabdff1aSopenharmony_ci        buf[3] =
1077cabdff1aSopenharmony_ci        buf[4] = 0xff;
1078cabdff1aSopenharmony_ci    }
1079cabdff1aSopenharmony_ci    return 5;
1080cabdff1aSopenharmony_ci}
1081cabdff1aSopenharmony_ci
1082cabdff1aSopenharmony_cistatic inline int dv_write_dif_id(enum dv_section_type t, uint8_t chan_num,
1083cabdff1aSopenharmony_ci                                  uint8_t seq_num, uint8_t dif_num,
1084cabdff1aSopenharmony_ci                                  uint8_t *buf)
1085cabdff1aSopenharmony_ci{
1086cabdff1aSopenharmony_ci    int fsc = chan_num & 1;
1087cabdff1aSopenharmony_ci    int fsp = 1 - (chan_num >> 1);
1088cabdff1aSopenharmony_ci
1089cabdff1aSopenharmony_ci    buf[0] = (uint8_t) t;      /* Section type */
1090cabdff1aSopenharmony_ci    buf[1] = (seq_num  << 4) | /* DIF seq number 0-9 for 525/60; 0-11 for 625/50 */
1091cabdff1aSopenharmony_ci             (fsc << 3) |      /* FSC: for 50 and 100Mb/s 0 - first channel; 1 - second */
1092cabdff1aSopenharmony_ci             (fsp << 2) |      /* FSP: for 100Mb/s 1 - channels 0-1; 0 - channels 2-3 */
1093cabdff1aSopenharmony_ci             3;                /* reserved -- always 1 */
1094cabdff1aSopenharmony_ci    buf[2] = dif_num;          /* DIF block number Video: 0-134, Audio: 0-8 */
1095cabdff1aSopenharmony_ci    return 3;
1096cabdff1aSopenharmony_ci}
1097cabdff1aSopenharmony_ci
1098cabdff1aSopenharmony_cistatic inline int dv_write_ssyb_id(uint8_t syb_num, uint8_t fr, uint8_t *buf)
1099cabdff1aSopenharmony_ci{
1100cabdff1aSopenharmony_ci    if (syb_num == 0 || syb_num == 6) {
1101cabdff1aSopenharmony_ci        buf[0] = (fr << 7) | /* FR ID 1 - first half of each channel; 0 - second */
1102cabdff1aSopenharmony_ci                 (0  << 4) | /* AP3 (Subcode application ID) */
1103cabdff1aSopenharmony_ci                 0x0f;       /* reserved -- always 1 */
1104cabdff1aSopenharmony_ci    } else if (syb_num == 11) {
1105cabdff1aSopenharmony_ci        buf[0] = (fr << 7) | /* FR ID 1 - first half of each channel; 0 - second */
1106cabdff1aSopenharmony_ci                 0x7f;       /* reserved -- always 1 */
1107cabdff1aSopenharmony_ci    } else {
1108cabdff1aSopenharmony_ci        buf[0] = (fr << 7) | /* FR ID 1 - first half of each channel; 0 - second */
1109cabdff1aSopenharmony_ci                 (0  << 4) | /* APT (Track application ID) */
1110cabdff1aSopenharmony_ci                 0x0f;       /* reserved -- always 1 */
1111cabdff1aSopenharmony_ci    }
1112cabdff1aSopenharmony_ci    buf[1] = 0xf0 |            /* reserved -- always 1 */
1113cabdff1aSopenharmony_ci             (syb_num & 0x0f); /* SSYB number 0 - 11   */
1114cabdff1aSopenharmony_ci    buf[2] = 0xff;             /* reserved -- always 1 */
1115cabdff1aSopenharmony_ci    return 3;
1116cabdff1aSopenharmony_ci}
1117cabdff1aSopenharmony_ci
1118cabdff1aSopenharmony_cistatic void dv_format_frame(DVVideoContext *c, uint8_t *buf)
1119cabdff1aSopenharmony_ci{
1120cabdff1aSopenharmony_ci    int chan, i, j, k;
1121cabdff1aSopenharmony_ci    /* We work with 720p frames split in half. The odd half-frame is chan 2,3 */
1122cabdff1aSopenharmony_ci    int chan_offset = 2*(c->sys->height == 720 && c->avctx->frame_number & 1);
1123cabdff1aSopenharmony_ci
1124cabdff1aSopenharmony_ci    for (chan = 0; chan < c->sys->n_difchan; chan++) {
1125cabdff1aSopenharmony_ci        for (i = 0; i < c->sys->difseg_size; i++) {
1126cabdff1aSopenharmony_ci            memset(buf, 0xff, 80 * 6); /* first 6 DIF blocks are for control data */
1127cabdff1aSopenharmony_ci
1128cabdff1aSopenharmony_ci            /* DV header: 1DIF */
1129cabdff1aSopenharmony_ci            buf += dv_write_dif_id(dv_sect_header, chan+chan_offset, i, 0, buf);
1130cabdff1aSopenharmony_ci            buf += dv_write_pack((c->sys->dsf ? dv_header625 : dv_header525),
1131cabdff1aSopenharmony_ci                                 c, buf);
1132cabdff1aSopenharmony_ci            buf += 72; /* unused bytes */
1133cabdff1aSopenharmony_ci
1134cabdff1aSopenharmony_ci            /* DV subcode: 2DIFs */
1135cabdff1aSopenharmony_ci            for (j = 0; j < 2; j++) {
1136cabdff1aSopenharmony_ci                buf += dv_write_dif_id(dv_sect_subcode, chan+chan_offset, i, j, buf);
1137cabdff1aSopenharmony_ci                for (k = 0; k < 6; k++)
1138cabdff1aSopenharmony_ci                    buf += dv_write_ssyb_id(k, (i < c->sys->difseg_size / 2), buf) + 5;
1139cabdff1aSopenharmony_ci                buf += 29; /* unused bytes */
1140cabdff1aSopenharmony_ci            }
1141cabdff1aSopenharmony_ci
1142cabdff1aSopenharmony_ci            /* DV VAUX: 3DIFS */
1143cabdff1aSopenharmony_ci            for (j = 0; j < 3; j++) {
1144cabdff1aSopenharmony_ci                buf += dv_write_dif_id(dv_sect_vaux, chan+chan_offset, i, j, buf);
1145cabdff1aSopenharmony_ci                buf += dv_write_pack(dv_video_source,  c, buf);
1146cabdff1aSopenharmony_ci                buf += dv_write_pack(dv_video_control, c, buf);
1147cabdff1aSopenharmony_ci                buf += 7 * 5;
1148cabdff1aSopenharmony_ci                buf += dv_write_pack(dv_video_source,  c, buf);
1149cabdff1aSopenharmony_ci                buf += dv_write_pack(dv_video_control, c, buf);
1150cabdff1aSopenharmony_ci                buf += 4 * 5 + 2; /* unused bytes */
1151cabdff1aSopenharmony_ci            }
1152cabdff1aSopenharmony_ci
1153cabdff1aSopenharmony_ci            /* DV Audio/Video: 135 Video DIFs + 9 Audio DIFs */
1154cabdff1aSopenharmony_ci            for (j = 0; j < 135; j++) {
1155cabdff1aSopenharmony_ci                if (j % 15 == 0) {
1156cabdff1aSopenharmony_ci                    memset(buf, 0xff, 80);
1157cabdff1aSopenharmony_ci                    buf += dv_write_dif_id(dv_sect_audio, chan+chan_offset, i, j/15, buf);
1158cabdff1aSopenharmony_ci                    buf += 77; /* audio control & shuffled PCM audio */
1159cabdff1aSopenharmony_ci                }
1160cabdff1aSopenharmony_ci                buf += dv_write_dif_id(dv_sect_video, chan+chan_offset, i, j, buf);
1161cabdff1aSopenharmony_ci                buf += 77; /* 1 video macroblock: 1 bytes control
1162cabdff1aSopenharmony_ci                            * 4 * 14 bytes Y 8x8 data
1163cabdff1aSopenharmony_ci                            * 10 bytes Cr 8x8 data
1164cabdff1aSopenharmony_ci                            * 10 bytes Cb 8x8 data */
1165cabdff1aSopenharmony_ci            }
1166cabdff1aSopenharmony_ci        }
1167cabdff1aSopenharmony_ci    }
1168cabdff1aSopenharmony_ci}
1169cabdff1aSopenharmony_ci
1170cabdff1aSopenharmony_cistatic int dvvideo_encode_frame(AVCodecContext *c, AVPacket *pkt,
1171cabdff1aSopenharmony_ci                                const AVFrame *frame, int *got_packet)
1172cabdff1aSopenharmony_ci{
1173cabdff1aSopenharmony_ci    DVVideoContext *s = c->priv_data;
1174cabdff1aSopenharmony_ci    int ret;
1175cabdff1aSopenharmony_ci
1176cabdff1aSopenharmony_ci    if ((ret = ff_get_encode_buffer(c, pkt, s->sys->frame_size, 0)) < 0)
1177cabdff1aSopenharmony_ci        return ret;
1178cabdff1aSopenharmony_ci    /* Fixme: Only zero the part that is not overwritten later. */
1179cabdff1aSopenharmony_ci    memset(pkt->data, 0, pkt->size);
1180cabdff1aSopenharmony_ci
1181cabdff1aSopenharmony_ci    c->pix_fmt                = s->sys->pix_fmt;
1182cabdff1aSopenharmony_ci    s->frame                  = frame;
1183cabdff1aSopenharmony_ci    s->buf = pkt->data;
1184cabdff1aSopenharmony_ci
1185cabdff1aSopenharmony_ci    dv_format_frame(s, pkt->data);
1186cabdff1aSopenharmony_ci
1187cabdff1aSopenharmony_ci    c->execute(c, dv_encode_video_segment, s->work_chunks, NULL,
1188cabdff1aSopenharmony_ci               dv_work_pool_size(s->sys), sizeof(DVwork_chunk));
1189cabdff1aSopenharmony_ci
1190cabdff1aSopenharmony_ci    emms_c();
1191cabdff1aSopenharmony_ci
1192cabdff1aSopenharmony_ci    *got_packet = 1;
1193cabdff1aSopenharmony_ci
1194cabdff1aSopenharmony_ci    return 0;
1195cabdff1aSopenharmony_ci}
1196cabdff1aSopenharmony_ci
1197cabdff1aSopenharmony_ci#define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM
1198cabdff1aSopenharmony_ci#define OFFSET(x) offsetof(DVVideoContext, x)
1199cabdff1aSopenharmony_cistatic const AVOption dv_options[] = {
1200cabdff1aSopenharmony_ci    { "quant_deadzone",        "Quantizer dead zone",    OFFSET(quant_deadzone),       AV_OPT_TYPE_INT, { .i64 = 7 }, 0, 1024, VE },
1201cabdff1aSopenharmony_ci    { NULL },
1202cabdff1aSopenharmony_ci};
1203cabdff1aSopenharmony_ci
1204cabdff1aSopenharmony_cistatic const AVClass dvvideo_encode_class = {
1205cabdff1aSopenharmony_ci    .class_name = "dvvideo encoder",
1206cabdff1aSopenharmony_ci    .item_name  = av_default_item_name,
1207cabdff1aSopenharmony_ci    .option     = dv_options,
1208cabdff1aSopenharmony_ci    .version    = LIBAVUTIL_VERSION_INT,
1209cabdff1aSopenharmony_ci};
1210cabdff1aSopenharmony_ci
1211cabdff1aSopenharmony_ciconst FFCodec ff_dvvideo_encoder = {
1212cabdff1aSopenharmony_ci    .p.name         = "dvvideo",
1213cabdff1aSopenharmony_ci    .p.long_name    = NULL_IF_CONFIG_SMALL("DV (Digital Video)"),
1214cabdff1aSopenharmony_ci    .p.type         = AVMEDIA_TYPE_VIDEO,
1215cabdff1aSopenharmony_ci    .p.id           = AV_CODEC_ID_DVVIDEO,
1216cabdff1aSopenharmony_ci    .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS |
1217cabdff1aSopenharmony_ci                      AV_CODEC_CAP_SLICE_THREADS,
1218cabdff1aSopenharmony_ci    .priv_data_size = sizeof(DVVideoContext),
1219cabdff1aSopenharmony_ci    .init           = dvvideo_encode_init,
1220cabdff1aSopenharmony_ci    FF_CODEC_ENCODE_CB(dvvideo_encode_frame),
1221cabdff1aSopenharmony_ci    .p.pix_fmts     = (const enum AVPixelFormat[]) {
1222cabdff1aSopenharmony_ci        AV_PIX_FMT_YUV411P, AV_PIX_FMT_YUV422P,
1223cabdff1aSopenharmony_ci        AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE
1224cabdff1aSopenharmony_ci    },
1225cabdff1aSopenharmony_ci    .p.priv_class   = &dvvideo_encode_class,
1226cabdff1aSopenharmony_ci    .caps_internal  = FF_CODEC_CAP_INIT_THREADSAFE,
1227cabdff1aSopenharmony_ci};
1228