1cabdff1aSopenharmony_ci/*
2cabdff1aSopenharmony_ci * This file is part of FFmpeg.
3cabdff1aSopenharmony_ci *
4cabdff1aSopenharmony_ci * FFmpeg is free software; you can redistribute it and/or
5cabdff1aSopenharmony_ci * modify it under the terms of the GNU Lesser General Public
6cabdff1aSopenharmony_ci * License as published by the Free Software Foundation; either
7cabdff1aSopenharmony_ci * version 2.1 of the License, or (at your option) any later version.
8cabdff1aSopenharmony_ci *
9cabdff1aSopenharmony_ci * FFmpeg is distributed in the hope that it will be useful,
10cabdff1aSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of
11cabdff1aSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12cabdff1aSopenharmony_ci * Lesser General Public License for more details.
13cabdff1aSopenharmony_ci *
14cabdff1aSopenharmony_ci * You should have received a copy of the GNU Lesser General Public
15cabdff1aSopenharmony_ci * License along with FFmpeg; if not, write to the Free Software
16cabdff1aSopenharmony_ci * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17cabdff1aSopenharmony_ci */
18cabdff1aSopenharmony_ci
19cabdff1aSopenharmony_ci#include <string.h>
20cabdff1aSopenharmony_ci
21cabdff1aSopenharmony_ci#include <va/va.h>
22cabdff1aSopenharmony_ci#include <va/va_enc_h264.h>
23cabdff1aSopenharmony_ci
24cabdff1aSopenharmony_ci#include "libavutil/avassert.h"
25cabdff1aSopenharmony_ci#include "libavutil/common.h"
26cabdff1aSopenharmony_ci#include "libavutil/internal.h"
27cabdff1aSopenharmony_ci#include "libavutil/opt.h"
28cabdff1aSopenharmony_ci
29cabdff1aSopenharmony_ci#include "avcodec.h"
30cabdff1aSopenharmony_ci#include "cbs.h"
31cabdff1aSopenharmony_ci#include "cbs_h264.h"
32cabdff1aSopenharmony_ci#include "codec_internal.h"
33cabdff1aSopenharmony_ci#include "h264.h"
34cabdff1aSopenharmony_ci#include "h264_levels.h"
35cabdff1aSopenharmony_ci#include "h264_sei.h"
36cabdff1aSopenharmony_ci#include "vaapi_encode.h"
37cabdff1aSopenharmony_ci#include "version.h"
38cabdff1aSopenharmony_ci
39cabdff1aSopenharmony_cienum {
40cabdff1aSopenharmony_ci    SEI_TIMING         = 0x01,
41cabdff1aSopenharmony_ci    SEI_IDENTIFIER     = 0x02,
42cabdff1aSopenharmony_ci    SEI_RECOVERY_POINT = 0x04,
43cabdff1aSopenharmony_ci};
44cabdff1aSopenharmony_ci
45cabdff1aSopenharmony_ci// Random (version 4) ISO 11578 UUID.
46cabdff1aSopenharmony_cistatic const uint8_t vaapi_encode_h264_sei_identifier_uuid[16] = {
47cabdff1aSopenharmony_ci    0x59, 0x94, 0x8b, 0x28, 0x11, 0xec, 0x45, 0xaf,
48cabdff1aSopenharmony_ci    0x96, 0x75, 0x19, 0xd4, 0x1f, 0xea, 0xa9, 0x4d,
49cabdff1aSopenharmony_ci};
50cabdff1aSopenharmony_ci
51cabdff1aSopenharmony_citypedef struct VAAPIEncodeH264Picture {
52cabdff1aSopenharmony_ci    int frame_num;
53cabdff1aSopenharmony_ci    int pic_order_cnt;
54cabdff1aSopenharmony_ci
55cabdff1aSopenharmony_ci    int64_t last_idr_frame;
56cabdff1aSopenharmony_ci    uint16_t idr_pic_id;
57cabdff1aSopenharmony_ci
58cabdff1aSopenharmony_ci    int primary_pic_type;
59cabdff1aSopenharmony_ci    int slice_type;
60cabdff1aSopenharmony_ci
61cabdff1aSopenharmony_ci    int cpb_delay;
62cabdff1aSopenharmony_ci    int dpb_delay;
63cabdff1aSopenharmony_ci} VAAPIEncodeH264Picture;
64cabdff1aSopenharmony_ci
65cabdff1aSopenharmony_citypedef struct VAAPIEncodeH264Context {
66cabdff1aSopenharmony_ci    VAAPIEncodeContext common;
67cabdff1aSopenharmony_ci
68cabdff1aSopenharmony_ci    // User options.
69cabdff1aSopenharmony_ci    int qp;
70cabdff1aSopenharmony_ci    int quality;
71cabdff1aSopenharmony_ci    int coder;
72cabdff1aSopenharmony_ci    int aud;
73cabdff1aSopenharmony_ci    int sei;
74cabdff1aSopenharmony_ci    int profile;
75cabdff1aSopenharmony_ci    int level;
76cabdff1aSopenharmony_ci
77cabdff1aSopenharmony_ci    // Derived settings.
78cabdff1aSopenharmony_ci    int mb_width;
79cabdff1aSopenharmony_ci    int mb_height;
80cabdff1aSopenharmony_ci
81cabdff1aSopenharmony_ci    int fixed_qp_idr;
82cabdff1aSopenharmony_ci    int fixed_qp_p;
83cabdff1aSopenharmony_ci    int fixed_qp_b;
84cabdff1aSopenharmony_ci
85cabdff1aSopenharmony_ci    int dpb_frames;
86cabdff1aSopenharmony_ci
87cabdff1aSopenharmony_ci    // Writer structures.
88cabdff1aSopenharmony_ci    CodedBitstreamContext *cbc;
89cabdff1aSopenharmony_ci    CodedBitstreamFragment current_access_unit;
90cabdff1aSopenharmony_ci
91cabdff1aSopenharmony_ci    H264RawAUD   raw_aud;
92cabdff1aSopenharmony_ci    H264RawSPS   raw_sps;
93cabdff1aSopenharmony_ci    H264RawPPS   raw_pps;
94cabdff1aSopenharmony_ci    H264RawSlice raw_slice;
95cabdff1aSopenharmony_ci
96cabdff1aSopenharmony_ci    H264RawSEIBufferingPeriod      sei_buffering_period;
97cabdff1aSopenharmony_ci    H264RawSEIPicTiming            sei_pic_timing;
98cabdff1aSopenharmony_ci    H264RawSEIRecoveryPoint        sei_recovery_point;
99cabdff1aSopenharmony_ci    SEIRawUserDataUnregistered     sei_identifier;
100cabdff1aSopenharmony_ci    char                          *sei_identifier_string;
101cabdff1aSopenharmony_ci
102cabdff1aSopenharmony_ci    int aud_needed;
103cabdff1aSopenharmony_ci    int sei_needed;
104cabdff1aSopenharmony_ci    int sei_cbr_workaround_needed;
105cabdff1aSopenharmony_ci} VAAPIEncodeH264Context;
106cabdff1aSopenharmony_ci
107cabdff1aSopenharmony_ci
108cabdff1aSopenharmony_cistatic int vaapi_encode_h264_write_access_unit(AVCodecContext *avctx,
109cabdff1aSopenharmony_ci                                               char *data, size_t *data_len,
110cabdff1aSopenharmony_ci                                               CodedBitstreamFragment *au)
111cabdff1aSopenharmony_ci{
112cabdff1aSopenharmony_ci    VAAPIEncodeH264Context *priv = avctx->priv_data;
113cabdff1aSopenharmony_ci    int err;
114cabdff1aSopenharmony_ci
115cabdff1aSopenharmony_ci    err = ff_cbs_write_fragment_data(priv->cbc, au);
116cabdff1aSopenharmony_ci    if (err < 0) {
117cabdff1aSopenharmony_ci        av_log(avctx, AV_LOG_ERROR, "Failed to write packed header.\n");
118cabdff1aSopenharmony_ci        return err;
119cabdff1aSopenharmony_ci    }
120cabdff1aSopenharmony_ci
121cabdff1aSopenharmony_ci    if (*data_len < 8 * au->data_size - au->data_bit_padding) {
122cabdff1aSopenharmony_ci        av_log(avctx, AV_LOG_ERROR, "Access unit too large: "
123cabdff1aSopenharmony_ci               "%zu < %zu.\n", *data_len,
124cabdff1aSopenharmony_ci               8 * au->data_size - au->data_bit_padding);
125cabdff1aSopenharmony_ci        return AVERROR(ENOSPC);
126cabdff1aSopenharmony_ci    }
127cabdff1aSopenharmony_ci
128cabdff1aSopenharmony_ci    memcpy(data, au->data, au->data_size);
129cabdff1aSopenharmony_ci    *data_len = 8 * au->data_size - au->data_bit_padding;
130cabdff1aSopenharmony_ci
131cabdff1aSopenharmony_ci    return 0;
132cabdff1aSopenharmony_ci}
133cabdff1aSopenharmony_ci
134cabdff1aSopenharmony_cistatic int vaapi_encode_h264_add_nal(AVCodecContext *avctx,
135cabdff1aSopenharmony_ci                                     CodedBitstreamFragment *au,
136cabdff1aSopenharmony_ci                                     void *nal_unit)
137cabdff1aSopenharmony_ci{
138cabdff1aSopenharmony_ci    H264RawNALUnitHeader *header = nal_unit;
139cabdff1aSopenharmony_ci    int err;
140cabdff1aSopenharmony_ci
141cabdff1aSopenharmony_ci    err = ff_cbs_insert_unit_content(au, -1,
142cabdff1aSopenharmony_ci                                     header->nal_unit_type, nal_unit, NULL);
143cabdff1aSopenharmony_ci    if (err < 0) {
144cabdff1aSopenharmony_ci        av_log(avctx, AV_LOG_ERROR, "Failed to add NAL unit: "
145cabdff1aSopenharmony_ci               "type = %d.\n", header->nal_unit_type);
146cabdff1aSopenharmony_ci        return err;
147cabdff1aSopenharmony_ci    }
148cabdff1aSopenharmony_ci
149cabdff1aSopenharmony_ci    return 0;
150cabdff1aSopenharmony_ci}
151cabdff1aSopenharmony_ci
152cabdff1aSopenharmony_cistatic int vaapi_encode_h264_write_sequence_header(AVCodecContext *avctx,
153cabdff1aSopenharmony_ci                                                   char *data, size_t *data_len)
154cabdff1aSopenharmony_ci{
155cabdff1aSopenharmony_ci    VAAPIEncodeH264Context *priv = avctx->priv_data;
156cabdff1aSopenharmony_ci    CodedBitstreamFragment   *au = &priv->current_access_unit;
157cabdff1aSopenharmony_ci    int err;
158cabdff1aSopenharmony_ci
159cabdff1aSopenharmony_ci    if (priv->aud_needed) {
160cabdff1aSopenharmony_ci        err = vaapi_encode_h264_add_nal(avctx, au, &priv->raw_aud);
161cabdff1aSopenharmony_ci        if (err < 0)
162cabdff1aSopenharmony_ci            goto fail;
163cabdff1aSopenharmony_ci        priv->aud_needed = 0;
164cabdff1aSopenharmony_ci    }
165cabdff1aSopenharmony_ci
166cabdff1aSopenharmony_ci    err = vaapi_encode_h264_add_nal(avctx, au, &priv->raw_sps);
167cabdff1aSopenharmony_ci    if (err < 0)
168cabdff1aSopenharmony_ci        goto fail;
169cabdff1aSopenharmony_ci
170cabdff1aSopenharmony_ci    err = vaapi_encode_h264_add_nal(avctx, au, &priv->raw_pps);
171cabdff1aSopenharmony_ci    if (err < 0)
172cabdff1aSopenharmony_ci        goto fail;
173cabdff1aSopenharmony_ci
174cabdff1aSopenharmony_ci    err = vaapi_encode_h264_write_access_unit(avctx, data, data_len, au);
175cabdff1aSopenharmony_cifail:
176cabdff1aSopenharmony_ci    ff_cbs_fragment_reset(au);
177cabdff1aSopenharmony_ci    return err;
178cabdff1aSopenharmony_ci}
179cabdff1aSopenharmony_ci
180cabdff1aSopenharmony_cistatic int vaapi_encode_h264_write_slice_header(AVCodecContext *avctx,
181cabdff1aSopenharmony_ci                                                VAAPIEncodePicture *pic,
182cabdff1aSopenharmony_ci                                                VAAPIEncodeSlice *slice,
183cabdff1aSopenharmony_ci                                                char *data, size_t *data_len)
184cabdff1aSopenharmony_ci{
185cabdff1aSopenharmony_ci    VAAPIEncodeH264Context *priv = avctx->priv_data;
186cabdff1aSopenharmony_ci    CodedBitstreamFragment   *au = &priv->current_access_unit;
187cabdff1aSopenharmony_ci    int err;
188cabdff1aSopenharmony_ci
189cabdff1aSopenharmony_ci    if (priv->aud_needed) {
190cabdff1aSopenharmony_ci        err = vaapi_encode_h264_add_nal(avctx, au, &priv->raw_aud);
191cabdff1aSopenharmony_ci        if (err < 0)
192cabdff1aSopenharmony_ci            goto fail;
193cabdff1aSopenharmony_ci        priv->aud_needed = 0;
194cabdff1aSopenharmony_ci    }
195cabdff1aSopenharmony_ci
196cabdff1aSopenharmony_ci    err = vaapi_encode_h264_add_nal(avctx, au, &priv->raw_slice);
197cabdff1aSopenharmony_ci    if (err < 0)
198cabdff1aSopenharmony_ci        goto fail;
199cabdff1aSopenharmony_ci
200cabdff1aSopenharmony_ci    err = vaapi_encode_h264_write_access_unit(avctx, data, data_len, au);
201cabdff1aSopenharmony_cifail:
202cabdff1aSopenharmony_ci    ff_cbs_fragment_reset(au);
203cabdff1aSopenharmony_ci    return err;
204cabdff1aSopenharmony_ci}
205cabdff1aSopenharmony_ci
206cabdff1aSopenharmony_cistatic int vaapi_encode_h264_write_extra_header(AVCodecContext *avctx,
207cabdff1aSopenharmony_ci                                                VAAPIEncodePicture *pic,
208cabdff1aSopenharmony_ci                                                int index, int *type,
209cabdff1aSopenharmony_ci                                                char *data, size_t *data_len)
210cabdff1aSopenharmony_ci{
211cabdff1aSopenharmony_ci    VAAPIEncodeH264Context *priv = avctx->priv_data;
212cabdff1aSopenharmony_ci    CodedBitstreamFragment   *au = &priv->current_access_unit;
213cabdff1aSopenharmony_ci    int err;
214cabdff1aSopenharmony_ci
215cabdff1aSopenharmony_ci    if (priv->sei_needed) {
216cabdff1aSopenharmony_ci        if (priv->aud_needed) {
217cabdff1aSopenharmony_ci            err = vaapi_encode_h264_add_nal(avctx, au, &priv->raw_aud);
218cabdff1aSopenharmony_ci            if (err < 0)
219cabdff1aSopenharmony_ci                goto fail;
220cabdff1aSopenharmony_ci            priv->aud_needed = 0;
221cabdff1aSopenharmony_ci        }
222cabdff1aSopenharmony_ci
223cabdff1aSopenharmony_ci        if (priv->sei_needed & SEI_IDENTIFIER) {
224cabdff1aSopenharmony_ci            err = ff_cbs_sei_add_message(priv->cbc, au, 1,
225cabdff1aSopenharmony_ci                                         SEI_TYPE_USER_DATA_UNREGISTERED,
226cabdff1aSopenharmony_ci                                         &priv->sei_identifier, NULL);
227cabdff1aSopenharmony_ci            if (err < 0)
228cabdff1aSopenharmony_ci                goto fail;
229cabdff1aSopenharmony_ci        }
230cabdff1aSopenharmony_ci        if (priv->sei_needed & SEI_TIMING) {
231cabdff1aSopenharmony_ci            if (pic->type == PICTURE_TYPE_IDR) {
232cabdff1aSopenharmony_ci                err = ff_cbs_sei_add_message(priv->cbc, au, 1,
233cabdff1aSopenharmony_ci                                             SEI_TYPE_BUFFERING_PERIOD,
234cabdff1aSopenharmony_ci                                             &priv->sei_buffering_period, NULL);
235cabdff1aSopenharmony_ci                if (err < 0)
236cabdff1aSopenharmony_ci                    goto fail;
237cabdff1aSopenharmony_ci            }
238cabdff1aSopenharmony_ci            err = ff_cbs_sei_add_message(priv->cbc, au, 1,
239cabdff1aSopenharmony_ci                                         SEI_TYPE_PIC_TIMING,
240cabdff1aSopenharmony_ci                                         &priv->sei_pic_timing, NULL);
241cabdff1aSopenharmony_ci            if (err < 0)
242cabdff1aSopenharmony_ci                goto fail;
243cabdff1aSopenharmony_ci        }
244cabdff1aSopenharmony_ci        if (priv->sei_needed & SEI_RECOVERY_POINT) {
245cabdff1aSopenharmony_ci            err = ff_cbs_sei_add_message(priv->cbc, au, 1,
246cabdff1aSopenharmony_ci                                         SEI_TYPE_RECOVERY_POINT,
247cabdff1aSopenharmony_ci                                         &priv->sei_recovery_point, NULL);
248cabdff1aSopenharmony_ci            if (err < 0)
249cabdff1aSopenharmony_ci                goto fail;
250cabdff1aSopenharmony_ci        }
251cabdff1aSopenharmony_ci
252cabdff1aSopenharmony_ci        priv->sei_needed = 0;
253cabdff1aSopenharmony_ci
254cabdff1aSopenharmony_ci        err = vaapi_encode_h264_write_access_unit(avctx, data, data_len, au);
255cabdff1aSopenharmony_ci        if (err < 0)
256cabdff1aSopenharmony_ci            goto fail;
257cabdff1aSopenharmony_ci
258cabdff1aSopenharmony_ci        ff_cbs_fragment_reset(au);
259cabdff1aSopenharmony_ci
260cabdff1aSopenharmony_ci        *type = VAEncPackedHeaderRawData;
261cabdff1aSopenharmony_ci        return 0;
262cabdff1aSopenharmony_ci
263cabdff1aSopenharmony_ci#if !CONFIG_VAAPI_1
264cabdff1aSopenharmony_ci    } else if (priv->sei_cbr_workaround_needed) {
265cabdff1aSopenharmony_ci        // Insert a zero-length header using the old SEI type.  This is
266cabdff1aSopenharmony_ci        // required to avoid triggering broken behaviour on Intel platforms
267cabdff1aSopenharmony_ci        // in CBR mode where an invalid SEI message is generated by the
268cabdff1aSopenharmony_ci        // driver and inserted into the stream.
269cabdff1aSopenharmony_ci        *data_len = 0;
270cabdff1aSopenharmony_ci        *type = VAEncPackedHeaderH264_SEI;
271cabdff1aSopenharmony_ci        priv->sei_cbr_workaround_needed = 0;
272cabdff1aSopenharmony_ci        return 0;
273cabdff1aSopenharmony_ci#endif
274cabdff1aSopenharmony_ci
275cabdff1aSopenharmony_ci    } else {
276cabdff1aSopenharmony_ci        return AVERROR_EOF;
277cabdff1aSopenharmony_ci    }
278cabdff1aSopenharmony_ci
279cabdff1aSopenharmony_cifail:
280cabdff1aSopenharmony_ci    ff_cbs_fragment_reset(au);
281cabdff1aSopenharmony_ci    return err;
282cabdff1aSopenharmony_ci}
283cabdff1aSopenharmony_ci
284cabdff1aSopenharmony_cistatic int vaapi_encode_h264_init_sequence_params(AVCodecContext *avctx)
285cabdff1aSopenharmony_ci{
286cabdff1aSopenharmony_ci    VAAPIEncodeContext                *ctx = avctx->priv_data;
287cabdff1aSopenharmony_ci    VAAPIEncodeH264Context           *priv = avctx->priv_data;
288cabdff1aSopenharmony_ci    H264RawSPS                        *sps = &priv->raw_sps;
289cabdff1aSopenharmony_ci    H264RawPPS                        *pps = &priv->raw_pps;
290cabdff1aSopenharmony_ci    VAEncSequenceParameterBufferH264 *vseq = ctx->codec_sequence_params;
291cabdff1aSopenharmony_ci    VAEncPictureParameterBufferH264  *vpic = ctx->codec_picture_params;
292cabdff1aSopenharmony_ci
293cabdff1aSopenharmony_ci    memset(sps, 0, sizeof(*sps));
294cabdff1aSopenharmony_ci    memset(pps, 0, sizeof(*pps));
295cabdff1aSopenharmony_ci
296cabdff1aSopenharmony_ci    sps->nal_unit_header.nal_ref_idc   = 3;
297cabdff1aSopenharmony_ci    sps->nal_unit_header.nal_unit_type = H264_NAL_SPS;
298cabdff1aSopenharmony_ci
299cabdff1aSopenharmony_ci    sps->profile_idc = avctx->profile & 0xff;
300cabdff1aSopenharmony_ci
301cabdff1aSopenharmony_ci    if (avctx->profile == FF_PROFILE_H264_CONSTRAINED_BASELINE ||
302cabdff1aSopenharmony_ci        avctx->profile == FF_PROFILE_H264_MAIN)
303cabdff1aSopenharmony_ci        sps->constraint_set1_flag = 1;
304cabdff1aSopenharmony_ci
305cabdff1aSopenharmony_ci    if (avctx->profile == FF_PROFILE_H264_HIGH)
306cabdff1aSopenharmony_ci        sps->constraint_set3_flag = ctx->gop_size == 1;
307cabdff1aSopenharmony_ci
308cabdff1aSopenharmony_ci    if (avctx->profile == FF_PROFILE_H264_MAIN ||
309cabdff1aSopenharmony_ci        avctx->profile == FF_PROFILE_H264_HIGH) {
310cabdff1aSopenharmony_ci        sps->constraint_set4_flag = 1;
311cabdff1aSopenharmony_ci        sps->constraint_set5_flag = ctx->b_per_p == 0;
312cabdff1aSopenharmony_ci    }
313cabdff1aSopenharmony_ci
314cabdff1aSopenharmony_ci    if (ctx->gop_size == 1)
315cabdff1aSopenharmony_ci        priv->dpb_frames = 0;
316cabdff1aSopenharmony_ci    else
317cabdff1aSopenharmony_ci        priv->dpb_frames = 1 + ctx->max_b_depth;
318cabdff1aSopenharmony_ci
319cabdff1aSopenharmony_ci    if (avctx->level != FF_LEVEL_UNKNOWN) {
320cabdff1aSopenharmony_ci        sps->level_idc = avctx->level;
321cabdff1aSopenharmony_ci    } else {
322cabdff1aSopenharmony_ci        const H264LevelDescriptor *level;
323cabdff1aSopenharmony_ci        int framerate;
324cabdff1aSopenharmony_ci
325cabdff1aSopenharmony_ci        if (avctx->framerate.num > 0 && avctx->framerate.den > 0)
326cabdff1aSopenharmony_ci            framerate = avctx->framerate.num / avctx->framerate.den;
327cabdff1aSopenharmony_ci        else
328cabdff1aSopenharmony_ci            framerate = 0;
329cabdff1aSopenharmony_ci
330cabdff1aSopenharmony_ci        level = ff_h264_guess_level(sps->profile_idc,
331cabdff1aSopenharmony_ci                                    avctx->bit_rate,
332cabdff1aSopenharmony_ci                                    framerate,
333cabdff1aSopenharmony_ci                                    priv->mb_width  * 16,
334cabdff1aSopenharmony_ci                                    priv->mb_height * 16,
335cabdff1aSopenharmony_ci                                    priv->dpb_frames);
336cabdff1aSopenharmony_ci        if (level) {
337cabdff1aSopenharmony_ci            av_log(avctx, AV_LOG_VERBOSE, "Using level %s.\n", level->name);
338cabdff1aSopenharmony_ci            if (level->constraint_set3_flag)
339cabdff1aSopenharmony_ci                sps->constraint_set3_flag = 1;
340cabdff1aSopenharmony_ci            sps->level_idc = level->level_idc;
341cabdff1aSopenharmony_ci        } else {
342cabdff1aSopenharmony_ci            av_log(avctx, AV_LOG_WARNING, "Stream will not conform "
343cabdff1aSopenharmony_ci                   "to any level: using level 6.2.\n");
344cabdff1aSopenharmony_ci            sps->level_idc = 62;
345cabdff1aSopenharmony_ci        }
346cabdff1aSopenharmony_ci    }
347cabdff1aSopenharmony_ci
348cabdff1aSopenharmony_ci    sps->seq_parameter_set_id = 0;
349cabdff1aSopenharmony_ci    sps->chroma_format_idc    = 1;
350cabdff1aSopenharmony_ci
351cabdff1aSopenharmony_ci    sps->log2_max_frame_num_minus4 = 4;
352cabdff1aSopenharmony_ci    sps->pic_order_cnt_type        = 0;
353cabdff1aSopenharmony_ci    sps->log2_max_pic_order_cnt_lsb_minus4 = 4;
354cabdff1aSopenharmony_ci
355cabdff1aSopenharmony_ci    sps->max_num_ref_frames = priv->dpb_frames;
356cabdff1aSopenharmony_ci
357cabdff1aSopenharmony_ci    sps->pic_width_in_mbs_minus1        = priv->mb_width  - 1;
358cabdff1aSopenharmony_ci    sps->pic_height_in_map_units_minus1 = priv->mb_height - 1;
359cabdff1aSopenharmony_ci
360cabdff1aSopenharmony_ci    sps->frame_mbs_only_flag = 1;
361cabdff1aSopenharmony_ci    sps->direct_8x8_inference_flag = 1;
362cabdff1aSopenharmony_ci
363cabdff1aSopenharmony_ci    if (avctx->width  != 16 * priv->mb_width ||
364cabdff1aSopenharmony_ci        avctx->height != 16 * priv->mb_height) {
365cabdff1aSopenharmony_ci        sps->frame_cropping_flag = 1;
366cabdff1aSopenharmony_ci
367cabdff1aSopenharmony_ci        sps->frame_crop_left_offset   = 0;
368cabdff1aSopenharmony_ci        sps->frame_crop_right_offset  =
369cabdff1aSopenharmony_ci            (16 * priv->mb_width - avctx->width) / 2;
370cabdff1aSopenharmony_ci        sps->frame_crop_top_offset    = 0;
371cabdff1aSopenharmony_ci        sps->frame_crop_bottom_offset =
372cabdff1aSopenharmony_ci            (16 * priv->mb_height - avctx->height) / 2;
373cabdff1aSopenharmony_ci    } else {
374cabdff1aSopenharmony_ci        sps->frame_cropping_flag = 0;
375cabdff1aSopenharmony_ci    }
376cabdff1aSopenharmony_ci
377cabdff1aSopenharmony_ci    sps->vui_parameters_present_flag = 1;
378cabdff1aSopenharmony_ci
379cabdff1aSopenharmony_ci    if (avctx->sample_aspect_ratio.num != 0 &&
380cabdff1aSopenharmony_ci        avctx->sample_aspect_ratio.den != 0) {
381cabdff1aSopenharmony_ci        static const AVRational sar_idc[] = {
382cabdff1aSopenharmony_ci            {   0,  0 },
383cabdff1aSopenharmony_ci            {   1,  1 }, {  12, 11 }, {  10, 11 }, {  16, 11 },
384cabdff1aSopenharmony_ci            {  40, 33 }, {  24, 11 }, {  20, 11 }, {  32, 11 },
385cabdff1aSopenharmony_ci            {  80, 33 }, {  18, 11 }, {  15, 11 }, {  64, 33 },
386cabdff1aSopenharmony_ci            { 160, 99 }, {   4,  3 }, {   3,  2 }, {   2,  1 },
387cabdff1aSopenharmony_ci        };
388cabdff1aSopenharmony_ci        int num, den, i;
389cabdff1aSopenharmony_ci        av_reduce(&num, &den, avctx->sample_aspect_ratio.num,
390cabdff1aSopenharmony_ci                  avctx->sample_aspect_ratio.den, 65535);
391cabdff1aSopenharmony_ci        for (i = 0; i < FF_ARRAY_ELEMS(sar_idc); i++) {
392cabdff1aSopenharmony_ci            if (num == sar_idc[i].num &&
393cabdff1aSopenharmony_ci                den == sar_idc[i].den) {
394cabdff1aSopenharmony_ci                sps->vui.aspect_ratio_idc = i;
395cabdff1aSopenharmony_ci                break;
396cabdff1aSopenharmony_ci            }
397cabdff1aSopenharmony_ci        }
398cabdff1aSopenharmony_ci        if (i >= FF_ARRAY_ELEMS(sar_idc)) {
399cabdff1aSopenharmony_ci            sps->vui.aspect_ratio_idc = 255;
400cabdff1aSopenharmony_ci            sps->vui.sar_width  = num;
401cabdff1aSopenharmony_ci            sps->vui.sar_height = den;
402cabdff1aSopenharmony_ci        }
403cabdff1aSopenharmony_ci        sps->vui.aspect_ratio_info_present_flag = 1;
404cabdff1aSopenharmony_ci    }
405cabdff1aSopenharmony_ci
406cabdff1aSopenharmony_ci    // Unspecified video format, from table E-2.
407cabdff1aSopenharmony_ci    sps->vui.video_format             = 5;
408cabdff1aSopenharmony_ci    sps->vui.video_full_range_flag    =
409cabdff1aSopenharmony_ci        avctx->color_range == AVCOL_RANGE_JPEG;
410cabdff1aSopenharmony_ci    sps->vui.colour_primaries         = avctx->color_primaries;
411cabdff1aSopenharmony_ci    sps->vui.transfer_characteristics = avctx->color_trc;
412cabdff1aSopenharmony_ci    sps->vui.matrix_coefficients      = avctx->colorspace;
413cabdff1aSopenharmony_ci    if (avctx->color_primaries != AVCOL_PRI_UNSPECIFIED ||
414cabdff1aSopenharmony_ci        avctx->color_trc       != AVCOL_TRC_UNSPECIFIED ||
415cabdff1aSopenharmony_ci        avctx->colorspace      != AVCOL_SPC_UNSPECIFIED)
416cabdff1aSopenharmony_ci        sps->vui.colour_description_present_flag = 1;
417cabdff1aSopenharmony_ci    if (avctx->color_range     != AVCOL_RANGE_UNSPECIFIED ||
418cabdff1aSopenharmony_ci        sps->vui.colour_description_present_flag)
419cabdff1aSopenharmony_ci        sps->vui.video_signal_type_present_flag = 1;
420cabdff1aSopenharmony_ci
421cabdff1aSopenharmony_ci    if (avctx->chroma_sample_location != AVCHROMA_LOC_UNSPECIFIED) {
422cabdff1aSopenharmony_ci        sps->vui.chroma_loc_info_present_flag = 1;
423cabdff1aSopenharmony_ci        sps->vui.chroma_sample_loc_type_top_field    =
424cabdff1aSopenharmony_ci        sps->vui.chroma_sample_loc_type_bottom_field =
425cabdff1aSopenharmony_ci            avctx->chroma_sample_location - 1;
426cabdff1aSopenharmony_ci    }
427cabdff1aSopenharmony_ci
428cabdff1aSopenharmony_ci    sps->vui.timing_info_present_flag = 1;
429cabdff1aSopenharmony_ci    if (avctx->framerate.num > 0 && avctx->framerate.den > 0) {
430cabdff1aSopenharmony_ci        sps->vui.num_units_in_tick = avctx->framerate.den;
431cabdff1aSopenharmony_ci        sps->vui.time_scale        = 2 * avctx->framerate.num;
432cabdff1aSopenharmony_ci        sps->vui.fixed_frame_rate_flag = 1;
433cabdff1aSopenharmony_ci    } else {
434cabdff1aSopenharmony_ci        sps->vui.num_units_in_tick = avctx->time_base.num;
435cabdff1aSopenharmony_ci        sps->vui.time_scale        = 2 * avctx->time_base.den;
436cabdff1aSopenharmony_ci        sps->vui.fixed_frame_rate_flag = 0;
437cabdff1aSopenharmony_ci    }
438cabdff1aSopenharmony_ci
439cabdff1aSopenharmony_ci    if (priv->sei & SEI_TIMING) {
440cabdff1aSopenharmony_ci        H264RawHRD *hrd = &sps->vui.nal_hrd_parameters;
441cabdff1aSopenharmony_ci        H264RawSEIBufferingPeriod *bp = &priv->sei_buffering_period;
442cabdff1aSopenharmony_ci
443cabdff1aSopenharmony_ci        sps->vui.nal_hrd_parameters_present_flag = 1;
444cabdff1aSopenharmony_ci
445cabdff1aSopenharmony_ci        hrd->cpb_cnt_minus1 = 0;
446cabdff1aSopenharmony_ci
447cabdff1aSopenharmony_ci        // Try to scale these to a sensible range so that the
448cabdff1aSopenharmony_ci        // golomb encode of the value is not overlong.
449cabdff1aSopenharmony_ci        hrd->bit_rate_scale =
450cabdff1aSopenharmony_ci            av_clip_uintp2(av_log2(ctx->va_bit_rate) - 15 - 6, 4);
451cabdff1aSopenharmony_ci        hrd->bit_rate_value_minus1[0] =
452cabdff1aSopenharmony_ci            (ctx->va_bit_rate >> hrd->bit_rate_scale + 6) - 1;
453cabdff1aSopenharmony_ci
454cabdff1aSopenharmony_ci        hrd->cpb_size_scale =
455cabdff1aSopenharmony_ci            av_clip_uintp2(av_log2(ctx->hrd_params.buffer_size) - 15 - 4, 4);
456cabdff1aSopenharmony_ci        hrd->cpb_size_value_minus1[0] =
457cabdff1aSopenharmony_ci            (ctx->hrd_params.buffer_size >> hrd->cpb_size_scale + 4) - 1;
458cabdff1aSopenharmony_ci
459cabdff1aSopenharmony_ci        // CBR mode as defined for the HRD cannot be achieved without filler
460cabdff1aSopenharmony_ci        // data, so this flag cannot be set even with VAAPI CBR modes.
461cabdff1aSopenharmony_ci        hrd->cbr_flag[0] = 0;
462cabdff1aSopenharmony_ci
463cabdff1aSopenharmony_ci        hrd->initial_cpb_removal_delay_length_minus1 = 23;
464cabdff1aSopenharmony_ci        hrd->cpb_removal_delay_length_minus1         = 23;
465cabdff1aSopenharmony_ci        hrd->dpb_output_delay_length_minus1          = 7;
466cabdff1aSopenharmony_ci        hrd->time_offset_length                      = 0;
467cabdff1aSopenharmony_ci
468cabdff1aSopenharmony_ci        bp->seq_parameter_set_id = sps->seq_parameter_set_id;
469cabdff1aSopenharmony_ci
470cabdff1aSopenharmony_ci        // This calculation can easily overflow 32 bits.
471cabdff1aSopenharmony_ci        bp->nal.initial_cpb_removal_delay[0] = 90000 *
472cabdff1aSopenharmony_ci            (uint64_t)ctx->hrd_params.initial_buffer_fullness /
473cabdff1aSopenharmony_ci            ctx->hrd_params.buffer_size;
474cabdff1aSopenharmony_ci        bp->nal.initial_cpb_removal_delay_offset[0] = 0;
475cabdff1aSopenharmony_ci    } else {
476cabdff1aSopenharmony_ci        sps->vui.nal_hrd_parameters_present_flag = 0;
477cabdff1aSopenharmony_ci        sps->vui.low_delay_hrd_flag = 1 - sps->vui.fixed_frame_rate_flag;
478cabdff1aSopenharmony_ci    }
479cabdff1aSopenharmony_ci
480cabdff1aSopenharmony_ci    sps->vui.bitstream_restriction_flag    = 1;
481cabdff1aSopenharmony_ci    sps->vui.motion_vectors_over_pic_boundaries_flag = 1;
482cabdff1aSopenharmony_ci    sps->vui.log2_max_mv_length_horizontal = 15;
483cabdff1aSopenharmony_ci    sps->vui.log2_max_mv_length_vertical   = 15;
484cabdff1aSopenharmony_ci    sps->vui.max_num_reorder_frames        = ctx->max_b_depth;
485cabdff1aSopenharmony_ci    sps->vui.max_dec_frame_buffering       = ctx->max_b_depth + 1;
486cabdff1aSopenharmony_ci
487cabdff1aSopenharmony_ci    pps->nal_unit_header.nal_ref_idc = 3;
488cabdff1aSopenharmony_ci    pps->nal_unit_header.nal_unit_type = H264_NAL_PPS;
489cabdff1aSopenharmony_ci
490cabdff1aSopenharmony_ci    pps->pic_parameter_set_id = 0;
491cabdff1aSopenharmony_ci    pps->seq_parameter_set_id = 0;
492cabdff1aSopenharmony_ci
493cabdff1aSopenharmony_ci    pps->entropy_coding_mode_flag =
494cabdff1aSopenharmony_ci        !(sps->profile_idc == FF_PROFILE_H264_BASELINE ||
495cabdff1aSopenharmony_ci          sps->profile_idc == FF_PROFILE_H264_EXTENDED ||
496cabdff1aSopenharmony_ci          sps->profile_idc == FF_PROFILE_H264_CAVLC_444);
497cabdff1aSopenharmony_ci    if (!priv->coder && pps->entropy_coding_mode_flag)
498cabdff1aSopenharmony_ci        pps->entropy_coding_mode_flag = 0;
499cabdff1aSopenharmony_ci
500cabdff1aSopenharmony_ci    pps->num_ref_idx_l0_default_active_minus1 = 0;
501cabdff1aSopenharmony_ci    pps->num_ref_idx_l1_default_active_minus1 = 0;
502cabdff1aSopenharmony_ci
503cabdff1aSopenharmony_ci    pps->pic_init_qp_minus26 = priv->fixed_qp_idr - 26;
504cabdff1aSopenharmony_ci
505cabdff1aSopenharmony_ci    if (sps->profile_idc == FF_PROFILE_H264_BASELINE ||
506cabdff1aSopenharmony_ci        sps->profile_idc == FF_PROFILE_H264_EXTENDED ||
507cabdff1aSopenharmony_ci        sps->profile_idc == FF_PROFILE_H264_MAIN) {
508cabdff1aSopenharmony_ci        pps->more_rbsp_data = 0;
509cabdff1aSopenharmony_ci    } else {
510cabdff1aSopenharmony_ci        pps->more_rbsp_data = 1;
511cabdff1aSopenharmony_ci
512cabdff1aSopenharmony_ci        pps->transform_8x8_mode_flag = 1;
513cabdff1aSopenharmony_ci    }
514cabdff1aSopenharmony_ci
515cabdff1aSopenharmony_ci    *vseq = (VAEncSequenceParameterBufferH264) {
516cabdff1aSopenharmony_ci        .seq_parameter_set_id = sps->seq_parameter_set_id,
517cabdff1aSopenharmony_ci        .level_idc        = sps->level_idc,
518cabdff1aSopenharmony_ci        .intra_period     = ctx->gop_size,
519cabdff1aSopenharmony_ci        .intra_idr_period = ctx->gop_size,
520cabdff1aSopenharmony_ci        .ip_period        = ctx->b_per_p + 1,
521cabdff1aSopenharmony_ci
522cabdff1aSopenharmony_ci        .bits_per_second       = ctx->va_bit_rate,
523cabdff1aSopenharmony_ci        .max_num_ref_frames    = sps->max_num_ref_frames,
524cabdff1aSopenharmony_ci        .picture_width_in_mbs  = sps->pic_width_in_mbs_minus1 + 1,
525cabdff1aSopenharmony_ci        .picture_height_in_mbs = sps->pic_height_in_map_units_minus1 + 1,
526cabdff1aSopenharmony_ci
527cabdff1aSopenharmony_ci        .seq_fields.bits = {
528cabdff1aSopenharmony_ci            .chroma_format_idc                 = sps->chroma_format_idc,
529cabdff1aSopenharmony_ci            .frame_mbs_only_flag               = sps->frame_mbs_only_flag,
530cabdff1aSopenharmony_ci            .mb_adaptive_frame_field_flag      = sps->mb_adaptive_frame_field_flag,
531cabdff1aSopenharmony_ci            .seq_scaling_matrix_present_flag   = sps->seq_scaling_matrix_present_flag,
532cabdff1aSopenharmony_ci            .direct_8x8_inference_flag         = sps->direct_8x8_inference_flag,
533cabdff1aSopenharmony_ci            .log2_max_frame_num_minus4         = sps->log2_max_frame_num_minus4,
534cabdff1aSopenharmony_ci            .pic_order_cnt_type                = sps->pic_order_cnt_type,
535cabdff1aSopenharmony_ci            .log2_max_pic_order_cnt_lsb_minus4 = sps->log2_max_pic_order_cnt_lsb_minus4,
536cabdff1aSopenharmony_ci            .delta_pic_order_always_zero_flag  = sps->delta_pic_order_always_zero_flag,
537cabdff1aSopenharmony_ci        },
538cabdff1aSopenharmony_ci
539cabdff1aSopenharmony_ci        .bit_depth_luma_minus8   = sps->bit_depth_luma_minus8,
540cabdff1aSopenharmony_ci        .bit_depth_chroma_minus8 = sps->bit_depth_chroma_minus8,
541cabdff1aSopenharmony_ci
542cabdff1aSopenharmony_ci        .frame_cropping_flag      = sps->frame_cropping_flag,
543cabdff1aSopenharmony_ci        .frame_crop_left_offset   = sps->frame_crop_left_offset,
544cabdff1aSopenharmony_ci        .frame_crop_right_offset  = sps->frame_crop_right_offset,
545cabdff1aSopenharmony_ci        .frame_crop_top_offset    = sps->frame_crop_top_offset,
546cabdff1aSopenharmony_ci        .frame_crop_bottom_offset = sps->frame_crop_bottom_offset,
547cabdff1aSopenharmony_ci
548cabdff1aSopenharmony_ci        .vui_parameters_present_flag = sps->vui_parameters_present_flag,
549cabdff1aSopenharmony_ci
550cabdff1aSopenharmony_ci        .vui_fields.bits = {
551cabdff1aSopenharmony_ci            .aspect_ratio_info_present_flag = sps->vui.aspect_ratio_info_present_flag,
552cabdff1aSopenharmony_ci            .timing_info_present_flag       = sps->vui.timing_info_present_flag,
553cabdff1aSopenharmony_ci            .bitstream_restriction_flag     = sps->vui.bitstream_restriction_flag,
554cabdff1aSopenharmony_ci            .log2_max_mv_length_horizontal  = sps->vui.log2_max_mv_length_horizontal,
555cabdff1aSopenharmony_ci            .log2_max_mv_length_vertical    = sps->vui.log2_max_mv_length_vertical,
556cabdff1aSopenharmony_ci        },
557cabdff1aSopenharmony_ci
558cabdff1aSopenharmony_ci        .aspect_ratio_idc  = sps->vui.aspect_ratio_idc,
559cabdff1aSopenharmony_ci        .sar_width         = sps->vui.sar_width,
560cabdff1aSopenharmony_ci        .sar_height        = sps->vui.sar_height,
561cabdff1aSopenharmony_ci        .num_units_in_tick = sps->vui.num_units_in_tick,
562cabdff1aSopenharmony_ci        .time_scale        = sps->vui.time_scale,
563cabdff1aSopenharmony_ci    };
564cabdff1aSopenharmony_ci
565cabdff1aSopenharmony_ci    *vpic = (VAEncPictureParameterBufferH264) {
566cabdff1aSopenharmony_ci        .CurrPic = {
567cabdff1aSopenharmony_ci            .picture_id = VA_INVALID_ID,
568cabdff1aSopenharmony_ci            .flags      = VA_PICTURE_H264_INVALID,
569cabdff1aSopenharmony_ci        },
570cabdff1aSopenharmony_ci
571cabdff1aSopenharmony_ci        .coded_buf = VA_INVALID_ID,
572cabdff1aSopenharmony_ci
573cabdff1aSopenharmony_ci        .pic_parameter_set_id = pps->pic_parameter_set_id,
574cabdff1aSopenharmony_ci        .seq_parameter_set_id = pps->seq_parameter_set_id,
575cabdff1aSopenharmony_ci
576cabdff1aSopenharmony_ci        .pic_init_qp                  = pps->pic_init_qp_minus26 + 26,
577cabdff1aSopenharmony_ci        .num_ref_idx_l0_active_minus1 = pps->num_ref_idx_l0_default_active_minus1,
578cabdff1aSopenharmony_ci        .num_ref_idx_l1_active_minus1 = pps->num_ref_idx_l1_default_active_minus1,
579cabdff1aSopenharmony_ci
580cabdff1aSopenharmony_ci        .chroma_qp_index_offset        = pps->chroma_qp_index_offset,
581cabdff1aSopenharmony_ci        .second_chroma_qp_index_offset = pps->second_chroma_qp_index_offset,
582cabdff1aSopenharmony_ci
583cabdff1aSopenharmony_ci        .pic_fields.bits = {
584cabdff1aSopenharmony_ci            .entropy_coding_mode_flag        = pps->entropy_coding_mode_flag,
585cabdff1aSopenharmony_ci            .weighted_pred_flag              = pps->weighted_pred_flag,
586cabdff1aSopenharmony_ci            .weighted_bipred_idc             = pps->weighted_bipred_idc,
587cabdff1aSopenharmony_ci            .constrained_intra_pred_flag     = pps->constrained_intra_pred_flag,
588cabdff1aSopenharmony_ci            .transform_8x8_mode_flag         = pps->transform_8x8_mode_flag,
589cabdff1aSopenharmony_ci            .deblocking_filter_control_present_flag =
590cabdff1aSopenharmony_ci                pps->deblocking_filter_control_present_flag,
591cabdff1aSopenharmony_ci            .redundant_pic_cnt_present_flag  = pps->redundant_pic_cnt_present_flag,
592cabdff1aSopenharmony_ci            .pic_order_present_flag          =
593cabdff1aSopenharmony_ci                pps->bottom_field_pic_order_in_frame_present_flag,
594cabdff1aSopenharmony_ci            .pic_scaling_matrix_present_flag = pps->pic_scaling_matrix_present_flag,
595cabdff1aSopenharmony_ci        },
596cabdff1aSopenharmony_ci    };
597cabdff1aSopenharmony_ci
598cabdff1aSopenharmony_ci    return 0;
599cabdff1aSopenharmony_ci}
600cabdff1aSopenharmony_ci
601cabdff1aSopenharmony_cistatic int vaapi_encode_h264_init_picture_params(AVCodecContext *avctx,
602cabdff1aSopenharmony_ci                                                 VAAPIEncodePicture *pic)
603cabdff1aSopenharmony_ci{
604cabdff1aSopenharmony_ci    VAAPIEncodeContext               *ctx = avctx->priv_data;
605cabdff1aSopenharmony_ci    VAAPIEncodeH264Context          *priv = avctx->priv_data;
606cabdff1aSopenharmony_ci    VAAPIEncodeH264Picture          *hpic = pic->priv_data;
607cabdff1aSopenharmony_ci    VAAPIEncodePicture              *prev = pic->prev;
608cabdff1aSopenharmony_ci    VAAPIEncodeH264Picture         *hprev = prev ? prev->priv_data : NULL;
609cabdff1aSopenharmony_ci    VAEncPictureParameterBufferH264 *vpic = pic->codec_picture_params;
610cabdff1aSopenharmony_ci    int i;
611cabdff1aSopenharmony_ci
612cabdff1aSopenharmony_ci    if (pic->type == PICTURE_TYPE_IDR) {
613cabdff1aSopenharmony_ci        av_assert0(pic->display_order == pic->encode_order);
614cabdff1aSopenharmony_ci
615cabdff1aSopenharmony_ci        hpic->frame_num      = 0;
616cabdff1aSopenharmony_ci        hpic->last_idr_frame = pic->display_order;
617cabdff1aSopenharmony_ci        hpic->idr_pic_id     = hprev ? hprev->idr_pic_id + 1 : 0;
618cabdff1aSopenharmony_ci
619cabdff1aSopenharmony_ci        hpic->primary_pic_type = 0;
620cabdff1aSopenharmony_ci        hpic->slice_type       = 7;
621cabdff1aSopenharmony_ci    } else {
622cabdff1aSopenharmony_ci        av_assert0(prev);
623cabdff1aSopenharmony_ci
624cabdff1aSopenharmony_ci        hpic->frame_num = hprev->frame_num + prev->is_reference;
625cabdff1aSopenharmony_ci
626cabdff1aSopenharmony_ci        hpic->last_idr_frame = hprev->last_idr_frame;
627cabdff1aSopenharmony_ci        hpic->idr_pic_id     = hprev->idr_pic_id;
628cabdff1aSopenharmony_ci
629cabdff1aSopenharmony_ci        if (pic->type == PICTURE_TYPE_I) {
630cabdff1aSopenharmony_ci            hpic->slice_type       = 7;
631cabdff1aSopenharmony_ci            hpic->primary_pic_type = 0;
632cabdff1aSopenharmony_ci        } else if (pic->type == PICTURE_TYPE_P) {
633cabdff1aSopenharmony_ci            hpic->slice_type       = 5;
634cabdff1aSopenharmony_ci            hpic->primary_pic_type = 1;
635cabdff1aSopenharmony_ci        } else {
636cabdff1aSopenharmony_ci            hpic->slice_type       = 6;
637cabdff1aSopenharmony_ci            hpic->primary_pic_type = 2;
638cabdff1aSopenharmony_ci        }
639cabdff1aSopenharmony_ci    }
640cabdff1aSopenharmony_ci    hpic->pic_order_cnt = pic->display_order - hpic->last_idr_frame;
641cabdff1aSopenharmony_ci    hpic->dpb_delay     = pic->display_order - pic->encode_order + ctx->max_b_depth;
642cabdff1aSopenharmony_ci    hpic->cpb_delay     = pic->encode_order - hpic->last_idr_frame;
643cabdff1aSopenharmony_ci
644cabdff1aSopenharmony_ci    if (priv->aud) {
645cabdff1aSopenharmony_ci        priv->aud_needed = 1;
646cabdff1aSopenharmony_ci        priv->raw_aud = (H264RawAUD) {
647cabdff1aSopenharmony_ci            .nal_unit_header = {
648cabdff1aSopenharmony_ci                .nal_unit_type = H264_NAL_AUD,
649cabdff1aSopenharmony_ci            },
650cabdff1aSopenharmony_ci            .primary_pic_type  = hpic->primary_pic_type,
651cabdff1aSopenharmony_ci        };
652cabdff1aSopenharmony_ci    } else {
653cabdff1aSopenharmony_ci        priv->aud_needed = 0;
654cabdff1aSopenharmony_ci    }
655cabdff1aSopenharmony_ci
656cabdff1aSopenharmony_ci    priv->sei_needed = 0;
657cabdff1aSopenharmony_ci
658cabdff1aSopenharmony_ci    if (priv->sei & SEI_IDENTIFIER && pic->encode_order == 0)
659cabdff1aSopenharmony_ci        priv->sei_needed |= SEI_IDENTIFIER;
660cabdff1aSopenharmony_ci#if !CONFIG_VAAPI_1
661cabdff1aSopenharmony_ci    if (ctx->va_rc_mode == VA_RC_CBR)
662cabdff1aSopenharmony_ci        priv->sei_cbr_workaround_needed = 1;
663cabdff1aSopenharmony_ci#endif
664cabdff1aSopenharmony_ci
665cabdff1aSopenharmony_ci    if (priv->sei & SEI_TIMING) {
666cabdff1aSopenharmony_ci        priv->sei_pic_timing = (H264RawSEIPicTiming) {
667cabdff1aSopenharmony_ci            .cpb_removal_delay = 2 * hpic->cpb_delay,
668cabdff1aSopenharmony_ci            .dpb_output_delay  = 2 * hpic->dpb_delay,
669cabdff1aSopenharmony_ci        };
670cabdff1aSopenharmony_ci
671cabdff1aSopenharmony_ci        priv->sei_needed |= SEI_TIMING;
672cabdff1aSopenharmony_ci    }
673cabdff1aSopenharmony_ci
674cabdff1aSopenharmony_ci    if (priv->sei & SEI_RECOVERY_POINT && pic->type == PICTURE_TYPE_I) {
675cabdff1aSopenharmony_ci        priv->sei_recovery_point = (H264RawSEIRecoveryPoint) {
676cabdff1aSopenharmony_ci            .recovery_frame_cnt = 0,
677cabdff1aSopenharmony_ci            .exact_match_flag   = 1,
678cabdff1aSopenharmony_ci            .broken_link_flag   = ctx->b_per_p > 0,
679cabdff1aSopenharmony_ci        };
680cabdff1aSopenharmony_ci
681cabdff1aSopenharmony_ci        priv->sei_needed |= SEI_RECOVERY_POINT;
682cabdff1aSopenharmony_ci    }
683cabdff1aSopenharmony_ci
684cabdff1aSopenharmony_ci    vpic->CurrPic = (VAPictureH264) {
685cabdff1aSopenharmony_ci        .picture_id          = pic->recon_surface,
686cabdff1aSopenharmony_ci        .frame_idx           = hpic->frame_num,
687cabdff1aSopenharmony_ci        .flags               = 0,
688cabdff1aSopenharmony_ci        .TopFieldOrderCnt    = hpic->pic_order_cnt,
689cabdff1aSopenharmony_ci        .BottomFieldOrderCnt = hpic->pic_order_cnt,
690cabdff1aSopenharmony_ci    };
691cabdff1aSopenharmony_ci
692cabdff1aSopenharmony_ci    for (i = 0; i < pic->nb_refs; i++) {
693cabdff1aSopenharmony_ci        VAAPIEncodePicture      *ref = pic->refs[i];
694cabdff1aSopenharmony_ci        VAAPIEncodeH264Picture *href;
695cabdff1aSopenharmony_ci
696cabdff1aSopenharmony_ci        av_assert0(ref && ref->encode_order < pic->encode_order);
697cabdff1aSopenharmony_ci        href = ref->priv_data;
698cabdff1aSopenharmony_ci
699cabdff1aSopenharmony_ci        vpic->ReferenceFrames[i] = (VAPictureH264) {
700cabdff1aSopenharmony_ci            .picture_id          = ref->recon_surface,
701cabdff1aSopenharmony_ci            .frame_idx           = href->frame_num,
702cabdff1aSopenharmony_ci            .flags               = VA_PICTURE_H264_SHORT_TERM_REFERENCE,
703cabdff1aSopenharmony_ci            .TopFieldOrderCnt    = href->pic_order_cnt,
704cabdff1aSopenharmony_ci            .BottomFieldOrderCnt = href->pic_order_cnt,
705cabdff1aSopenharmony_ci        };
706cabdff1aSopenharmony_ci    }
707cabdff1aSopenharmony_ci    for (; i < FF_ARRAY_ELEMS(vpic->ReferenceFrames); i++) {
708cabdff1aSopenharmony_ci        vpic->ReferenceFrames[i] = (VAPictureH264) {
709cabdff1aSopenharmony_ci            .picture_id = VA_INVALID_ID,
710cabdff1aSopenharmony_ci            .flags      = VA_PICTURE_H264_INVALID,
711cabdff1aSopenharmony_ci        };
712cabdff1aSopenharmony_ci    }
713cabdff1aSopenharmony_ci
714cabdff1aSopenharmony_ci    vpic->coded_buf = pic->output_buffer;
715cabdff1aSopenharmony_ci
716cabdff1aSopenharmony_ci    vpic->frame_num = hpic->frame_num;
717cabdff1aSopenharmony_ci
718cabdff1aSopenharmony_ci    vpic->pic_fields.bits.idr_pic_flag       = (pic->type == PICTURE_TYPE_IDR);
719cabdff1aSopenharmony_ci    vpic->pic_fields.bits.reference_pic_flag = (pic->type != PICTURE_TYPE_B);
720cabdff1aSopenharmony_ci
721cabdff1aSopenharmony_ci    return 0;
722cabdff1aSopenharmony_ci}
723cabdff1aSopenharmony_ci
724cabdff1aSopenharmony_cistatic void vaapi_encode_h264_default_ref_pic_list(AVCodecContext *avctx,
725cabdff1aSopenharmony_ci                                                   VAAPIEncodePicture *pic,
726cabdff1aSopenharmony_ci                                                   VAAPIEncodePicture **rpl0,
727cabdff1aSopenharmony_ci                                                   VAAPIEncodePicture **rpl1,
728cabdff1aSopenharmony_ci                                                   int *rpl_size)
729cabdff1aSopenharmony_ci{
730cabdff1aSopenharmony_ci    VAAPIEncodePicture *prev;
731cabdff1aSopenharmony_ci    VAAPIEncodeH264Picture *hp, *hn, *hc;
732cabdff1aSopenharmony_ci    int i, j, n = 0;
733cabdff1aSopenharmony_ci
734cabdff1aSopenharmony_ci    prev = pic->prev;
735cabdff1aSopenharmony_ci    av_assert0(prev);
736cabdff1aSopenharmony_ci    hp = pic->priv_data;
737cabdff1aSopenharmony_ci
738cabdff1aSopenharmony_ci    for (i = 0; i < pic->prev->nb_dpb_pics; i++) {
739cabdff1aSopenharmony_ci        hn = prev->dpb[i]->priv_data;
740cabdff1aSopenharmony_ci        av_assert0(hn->frame_num < hp->frame_num);
741cabdff1aSopenharmony_ci
742cabdff1aSopenharmony_ci        if (pic->type == PICTURE_TYPE_P) {
743cabdff1aSopenharmony_ci            for (j = n; j > 0; j--) {
744cabdff1aSopenharmony_ci                hc = rpl0[j - 1]->priv_data;
745cabdff1aSopenharmony_ci                av_assert0(hc->frame_num != hn->frame_num);
746cabdff1aSopenharmony_ci                if (hc->frame_num > hn->frame_num)
747cabdff1aSopenharmony_ci                    break;
748cabdff1aSopenharmony_ci                rpl0[j] = rpl0[j - 1];
749cabdff1aSopenharmony_ci            }
750cabdff1aSopenharmony_ci            rpl0[j] = prev->dpb[i];
751cabdff1aSopenharmony_ci
752cabdff1aSopenharmony_ci        } else if (pic->type == PICTURE_TYPE_B) {
753cabdff1aSopenharmony_ci            for (j = n; j > 0; j--) {
754cabdff1aSopenharmony_ci                hc = rpl0[j - 1]->priv_data;
755cabdff1aSopenharmony_ci                av_assert0(hc->pic_order_cnt != hp->pic_order_cnt);
756cabdff1aSopenharmony_ci                if (hc->pic_order_cnt < hp->pic_order_cnt) {
757cabdff1aSopenharmony_ci                    if (hn->pic_order_cnt > hp->pic_order_cnt ||
758cabdff1aSopenharmony_ci                        hn->pic_order_cnt < hc->pic_order_cnt)
759cabdff1aSopenharmony_ci                        break;
760cabdff1aSopenharmony_ci                } else {
761cabdff1aSopenharmony_ci                    if (hn->pic_order_cnt > hc->pic_order_cnt)
762cabdff1aSopenharmony_ci                        break;
763cabdff1aSopenharmony_ci                }
764cabdff1aSopenharmony_ci                rpl0[j] = rpl0[j - 1];
765cabdff1aSopenharmony_ci            }
766cabdff1aSopenharmony_ci            rpl0[j] = prev->dpb[i];
767cabdff1aSopenharmony_ci
768cabdff1aSopenharmony_ci            for (j = n; j > 0; j--) {
769cabdff1aSopenharmony_ci                hc = rpl1[j - 1]->priv_data;
770cabdff1aSopenharmony_ci                av_assert0(hc->pic_order_cnt != hp->pic_order_cnt);
771cabdff1aSopenharmony_ci                if (hc->pic_order_cnt > hp->pic_order_cnt) {
772cabdff1aSopenharmony_ci                    if (hn->pic_order_cnt < hp->pic_order_cnt ||
773cabdff1aSopenharmony_ci                        hn->pic_order_cnt > hc->pic_order_cnt)
774cabdff1aSopenharmony_ci                        break;
775cabdff1aSopenharmony_ci                } else {
776cabdff1aSopenharmony_ci                    if (hn->pic_order_cnt < hc->pic_order_cnt)
777cabdff1aSopenharmony_ci                        break;
778cabdff1aSopenharmony_ci                }
779cabdff1aSopenharmony_ci                rpl1[j] = rpl1[j - 1];
780cabdff1aSopenharmony_ci            }
781cabdff1aSopenharmony_ci            rpl1[j] = prev->dpb[i];
782cabdff1aSopenharmony_ci        }
783cabdff1aSopenharmony_ci
784cabdff1aSopenharmony_ci        ++n;
785cabdff1aSopenharmony_ci    }
786cabdff1aSopenharmony_ci
787cabdff1aSopenharmony_ci    if (pic->type == PICTURE_TYPE_B) {
788cabdff1aSopenharmony_ci        for (i = 0; i < n; i++) {
789cabdff1aSopenharmony_ci            if (rpl0[i] != rpl1[i])
790cabdff1aSopenharmony_ci                break;
791cabdff1aSopenharmony_ci        }
792cabdff1aSopenharmony_ci        if (i == n)
793cabdff1aSopenharmony_ci            FFSWAP(VAAPIEncodePicture*, rpl1[0], rpl1[1]);
794cabdff1aSopenharmony_ci    }
795cabdff1aSopenharmony_ci
796cabdff1aSopenharmony_ci    if (pic->type == PICTURE_TYPE_P ||
797cabdff1aSopenharmony_ci        pic->type == PICTURE_TYPE_B) {
798cabdff1aSopenharmony_ci        av_log(avctx, AV_LOG_DEBUG, "Default RefPicList0 for fn=%d/poc=%d:",
799cabdff1aSopenharmony_ci               hp->frame_num, hp->pic_order_cnt);
800cabdff1aSopenharmony_ci        for (i = 0; i < n; i++) {
801cabdff1aSopenharmony_ci            hn = rpl0[i]->priv_data;
802cabdff1aSopenharmony_ci            av_log(avctx, AV_LOG_DEBUG, "  fn=%d/poc=%d",
803cabdff1aSopenharmony_ci                   hn->frame_num, hn->pic_order_cnt);
804cabdff1aSopenharmony_ci        }
805cabdff1aSopenharmony_ci        av_log(avctx, AV_LOG_DEBUG, "\n");
806cabdff1aSopenharmony_ci    }
807cabdff1aSopenharmony_ci    if (pic->type == PICTURE_TYPE_B) {
808cabdff1aSopenharmony_ci        av_log(avctx, AV_LOG_DEBUG, "Default RefPicList1 for fn=%d/poc=%d:",
809cabdff1aSopenharmony_ci               hp->frame_num, hp->pic_order_cnt);
810cabdff1aSopenharmony_ci        for (i = 0; i < n; i++) {
811cabdff1aSopenharmony_ci            hn = rpl1[i]->priv_data;
812cabdff1aSopenharmony_ci            av_log(avctx, AV_LOG_DEBUG, "  fn=%d/poc=%d",
813cabdff1aSopenharmony_ci                   hn->frame_num, hn->pic_order_cnt);
814cabdff1aSopenharmony_ci        }
815cabdff1aSopenharmony_ci        av_log(avctx, AV_LOG_DEBUG, "\n");
816cabdff1aSopenharmony_ci    }
817cabdff1aSopenharmony_ci
818cabdff1aSopenharmony_ci    *rpl_size = n;
819cabdff1aSopenharmony_ci}
820cabdff1aSopenharmony_ci
821cabdff1aSopenharmony_cistatic int vaapi_encode_h264_init_slice_params(AVCodecContext *avctx,
822cabdff1aSopenharmony_ci                                               VAAPIEncodePicture *pic,
823cabdff1aSopenharmony_ci                                               VAAPIEncodeSlice *slice)
824cabdff1aSopenharmony_ci{
825cabdff1aSopenharmony_ci    VAAPIEncodeH264Context          *priv = avctx->priv_data;
826cabdff1aSopenharmony_ci    VAAPIEncodeH264Picture          *hpic = pic->priv_data;
827cabdff1aSopenharmony_ci    VAAPIEncodePicture              *prev = pic->prev;
828cabdff1aSopenharmony_ci    H264RawSPS                       *sps = &priv->raw_sps;
829cabdff1aSopenharmony_ci    H264RawPPS                       *pps = &priv->raw_pps;
830cabdff1aSopenharmony_ci    H264RawSliceHeader                *sh = &priv->raw_slice.header;
831cabdff1aSopenharmony_ci    VAEncPictureParameterBufferH264 *vpic = pic->codec_picture_params;
832cabdff1aSopenharmony_ci    VAEncSliceParameterBufferH264 *vslice = slice->codec_slice_params;
833cabdff1aSopenharmony_ci    int i, j;
834cabdff1aSopenharmony_ci
835cabdff1aSopenharmony_ci    if (pic->type == PICTURE_TYPE_IDR) {
836cabdff1aSopenharmony_ci        sh->nal_unit_header.nal_unit_type = H264_NAL_IDR_SLICE;
837cabdff1aSopenharmony_ci        sh->nal_unit_header.nal_ref_idc   = 3;
838cabdff1aSopenharmony_ci    } else {
839cabdff1aSopenharmony_ci        sh->nal_unit_header.nal_unit_type = H264_NAL_SLICE;
840cabdff1aSopenharmony_ci        sh->nal_unit_header.nal_ref_idc   = pic->is_reference;
841cabdff1aSopenharmony_ci    }
842cabdff1aSopenharmony_ci
843cabdff1aSopenharmony_ci    sh->first_mb_in_slice = slice->block_start;
844cabdff1aSopenharmony_ci    sh->slice_type        = hpic->slice_type;
845cabdff1aSopenharmony_ci
846cabdff1aSopenharmony_ci    sh->pic_parameter_set_id = pps->pic_parameter_set_id;
847cabdff1aSopenharmony_ci
848cabdff1aSopenharmony_ci    sh->frame_num = hpic->frame_num &
849cabdff1aSopenharmony_ci        ((1 << (4 + sps->log2_max_frame_num_minus4)) - 1);
850cabdff1aSopenharmony_ci    sh->idr_pic_id = hpic->idr_pic_id;
851cabdff1aSopenharmony_ci    sh->pic_order_cnt_lsb = hpic->pic_order_cnt &
852cabdff1aSopenharmony_ci        ((1 << (4 + sps->log2_max_pic_order_cnt_lsb_minus4)) - 1);
853cabdff1aSopenharmony_ci
854cabdff1aSopenharmony_ci    sh->direct_spatial_mv_pred_flag = 1;
855cabdff1aSopenharmony_ci
856cabdff1aSopenharmony_ci    if (pic->type == PICTURE_TYPE_B)
857cabdff1aSopenharmony_ci        sh->slice_qp_delta = priv->fixed_qp_b - (pps->pic_init_qp_minus26 + 26);
858cabdff1aSopenharmony_ci    else if (pic->type == PICTURE_TYPE_P)
859cabdff1aSopenharmony_ci        sh->slice_qp_delta = priv->fixed_qp_p - (pps->pic_init_qp_minus26 + 26);
860cabdff1aSopenharmony_ci    else
861cabdff1aSopenharmony_ci        sh->slice_qp_delta = priv->fixed_qp_idr - (pps->pic_init_qp_minus26 + 26);
862cabdff1aSopenharmony_ci
863cabdff1aSopenharmony_ci    if (pic->is_reference && pic->type != PICTURE_TYPE_IDR) {
864cabdff1aSopenharmony_ci        VAAPIEncodePicture *discard_list[MAX_DPB_SIZE];
865cabdff1aSopenharmony_ci        int discard = 0, keep = 0;
866cabdff1aSopenharmony_ci
867cabdff1aSopenharmony_ci        // Discard everything which is in the DPB of the previous frame but
868cabdff1aSopenharmony_ci        // not in the DPB of this one.
869cabdff1aSopenharmony_ci        for (i = 0; i < prev->nb_dpb_pics; i++) {
870cabdff1aSopenharmony_ci            for (j = 0; j < pic->nb_dpb_pics; j++) {
871cabdff1aSopenharmony_ci                if (prev->dpb[i] == pic->dpb[j])
872cabdff1aSopenharmony_ci                    break;
873cabdff1aSopenharmony_ci            }
874cabdff1aSopenharmony_ci            if (j == pic->nb_dpb_pics) {
875cabdff1aSopenharmony_ci                discard_list[discard] = prev->dpb[i];
876cabdff1aSopenharmony_ci                ++discard;
877cabdff1aSopenharmony_ci            } else {
878cabdff1aSopenharmony_ci                ++keep;
879cabdff1aSopenharmony_ci            }
880cabdff1aSopenharmony_ci        }
881cabdff1aSopenharmony_ci        av_assert0(keep <= priv->dpb_frames);
882cabdff1aSopenharmony_ci
883cabdff1aSopenharmony_ci        if (discard == 0) {
884cabdff1aSopenharmony_ci            sh->adaptive_ref_pic_marking_mode_flag = 0;
885cabdff1aSopenharmony_ci        } else {
886cabdff1aSopenharmony_ci            sh->adaptive_ref_pic_marking_mode_flag = 1;
887cabdff1aSopenharmony_ci            for (i = 0; i < discard; i++) {
888cabdff1aSopenharmony_ci                VAAPIEncodeH264Picture *old = discard_list[i]->priv_data;
889cabdff1aSopenharmony_ci                av_assert0(old->frame_num < hpic->frame_num);
890cabdff1aSopenharmony_ci                sh->mmco[i].memory_management_control_operation = 1;
891cabdff1aSopenharmony_ci                sh->mmco[i].difference_of_pic_nums_minus1 =
892cabdff1aSopenharmony_ci                    hpic->frame_num - old->frame_num - 1;
893cabdff1aSopenharmony_ci            }
894cabdff1aSopenharmony_ci            sh->mmco[i].memory_management_control_operation = 0;
895cabdff1aSopenharmony_ci        }
896cabdff1aSopenharmony_ci    }
897cabdff1aSopenharmony_ci
898cabdff1aSopenharmony_ci    // If the intended references are not the first entries of RefPicListN
899cabdff1aSopenharmony_ci    // by default, use ref-pic-list-modification to move them there.
900cabdff1aSopenharmony_ci    if (pic->type == PICTURE_TYPE_P || pic->type == PICTURE_TYPE_B) {
901cabdff1aSopenharmony_ci        VAAPIEncodePicture *def_l0[MAX_DPB_SIZE], *def_l1[MAX_DPB_SIZE];
902cabdff1aSopenharmony_ci        VAAPIEncodeH264Picture *href;
903cabdff1aSopenharmony_ci        int n;
904cabdff1aSopenharmony_ci
905cabdff1aSopenharmony_ci        vaapi_encode_h264_default_ref_pic_list(avctx, pic,
906cabdff1aSopenharmony_ci                                               def_l0, def_l1, &n);
907cabdff1aSopenharmony_ci
908cabdff1aSopenharmony_ci        if (pic->type == PICTURE_TYPE_P) {
909cabdff1aSopenharmony_ci            int need_rplm = 0;
910cabdff1aSopenharmony_ci            for (i = 0; i < pic->nb_refs; i++) {
911cabdff1aSopenharmony_ci                av_assert0(pic->refs[i]);
912cabdff1aSopenharmony_ci                if (pic->refs[i] != def_l0[i])
913cabdff1aSopenharmony_ci                    need_rplm = 1;
914cabdff1aSopenharmony_ci            }
915cabdff1aSopenharmony_ci
916cabdff1aSopenharmony_ci            sh->ref_pic_list_modification_flag_l0 = need_rplm;
917cabdff1aSopenharmony_ci            if (need_rplm) {
918cabdff1aSopenharmony_ci                int pic_num = hpic->frame_num;
919cabdff1aSopenharmony_ci                for (i = 0; i < pic->nb_refs; i++) {
920cabdff1aSopenharmony_ci                    href = pic->refs[i]->priv_data;
921cabdff1aSopenharmony_ci                    av_assert0(href->frame_num != pic_num);
922cabdff1aSopenharmony_ci                    if (href->frame_num < pic_num) {
923cabdff1aSopenharmony_ci                        sh->rplm_l0[i].modification_of_pic_nums_idc = 0;
924cabdff1aSopenharmony_ci                        sh->rplm_l0[i].abs_diff_pic_num_minus1 =
925cabdff1aSopenharmony_ci                            pic_num - href->frame_num - 1;
926cabdff1aSopenharmony_ci                    } else {
927cabdff1aSopenharmony_ci                        sh->rplm_l0[i].modification_of_pic_nums_idc = 1;
928cabdff1aSopenharmony_ci                        sh->rplm_l0[i].abs_diff_pic_num_minus1 =
929cabdff1aSopenharmony_ci                            href->frame_num - pic_num - 1;
930cabdff1aSopenharmony_ci                    }
931cabdff1aSopenharmony_ci                    pic_num = href->frame_num;
932cabdff1aSopenharmony_ci                }
933cabdff1aSopenharmony_ci                sh->rplm_l0[i].modification_of_pic_nums_idc = 3;
934cabdff1aSopenharmony_ci            }
935cabdff1aSopenharmony_ci
936cabdff1aSopenharmony_ci        } else {
937cabdff1aSopenharmony_ci            int need_rplm_l0 = 0, need_rplm_l1 = 0;
938cabdff1aSopenharmony_ci            int n0 = 0, n1 = 0;
939cabdff1aSopenharmony_ci            for (i = 0; i < pic->nb_refs; i++) {
940cabdff1aSopenharmony_ci                av_assert0(pic->refs[i]);
941cabdff1aSopenharmony_ci                href = pic->refs[i]->priv_data;
942cabdff1aSopenharmony_ci                av_assert0(href->pic_order_cnt != hpic->pic_order_cnt);
943cabdff1aSopenharmony_ci                if (href->pic_order_cnt < hpic->pic_order_cnt) {
944cabdff1aSopenharmony_ci                    if (pic->refs[i] != def_l0[n0])
945cabdff1aSopenharmony_ci                        need_rplm_l0 = 1;
946cabdff1aSopenharmony_ci                    ++n0;
947cabdff1aSopenharmony_ci                } else {
948cabdff1aSopenharmony_ci                    if (pic->refs[i] != def_l1[n1])
949cabdff1aSopenharmony_ci                        need_rplm_l1 = 1;
950cabdff1aSopenharmony_ci                    ++n1;
951cabdff1aSopenharmony_ci                }
952cabdff1aSopenharmony_ci            }
953cabdff1aSopenharmony_ci
954cabdff1aSopenharmony_ci            sh->ref_pic_list_modification_flag_l0 = need_rplm_l0;
955cabdff1aSopenharmony_ci            if (need_rplm_l0) {
956cabdff1aSopenharmony_ci                int pic_num = hpic->frame_num;
957cabdff1aSopenharmony_ci                for (i = j = 0; i < pic->nb_refs; i++) {
958cabdff1aSopenharmony_ci                    href = pic->refs[i]->priv_data;
959cabdff1aSopenharmony_ci                    if (href->pic_order_cnt > hpic->pic_order_cnt)
960cabdff1aSopenharmony_ci                        continue;
961cabdff1aSopenharmony_ci                    av_assert0(href->frame_num != pic_num);
962cabdff1aSopenharmony_ci                    if (href->frame_num < pic_num) {
963cabdff1aSopenharmony_ci                        sh->rplm_l0[j].modification_of_pic_nums_idc = 0;
964cabdff1aSopenharmony_ci                        sh->rplm_l0[j].abs_diff_pic_num_minus1 =
965cabdff1aSopenharmony_ci                            pic_num - href->frame_num - 1;
966cabdff1aSopenharmony_ci                    } else {
967cabdff1aSopenharmony_ci                        sh->rplm_l0[j].modification_of_pic_nums_idc = 1;
968cabdff1aSopenharmony_ci                        sh->rplm_l0[j].abs_diff_pic_num_minus1 =
969cabdff1aSopenharmony_ci                            href->frame_num - pic_num - 1;
970cabdff1aSopenharmony_ci                    }
971cabdff1aSopenharmony_ci                    pic_num = href->frame_num;
972cabdff1aSopenharmony_ci                    ++j;
973cabdff1aSopenharmony_ci                }
974cabdff1aSopenharmony_ci                av_assert0(j == n0);
975cabdff1aSopenharmony_ci                sh->rplm_l0[j].modification_of_pic_nums_idc = 3;
976cabdff1aSopenharmony_ci            }
977cabdff1aSopenharmony_ci
978cabdff1aSopenharmony_ci            sh->ref_pic_list_modification_flag_l1 = need_rplm_l1;
979cabdff1aSopenharmony_ci            if (need_rplm_l1) {
980cabdff1aSopenharmony_ci                int pic_num = hpic->frame_num;
981cabdff1aSopenharmony_ci                for (i = j = 0; i < pic->nb_refs; i++) {
982cabdff1aSopenharmony_ci                    href = pic->refs[i]->priv_data;
983cabdff1aSopenharmony_ci                    if (href->pic_order_cnt < hpic->pic_order_cnt)
984cabdff1aSopenharmony_ci                        continue;
985cabdff1aSopenharmony_ci                    av_assert0(href->frame_num != pic_num);
986cabdff1aSopenharmony_ci                    if (href->frame_num < pic_num) {
987cabdff1aSopenharmony_ci                        sh->rplm_l1[j].modification_of_pic_nums_idc = 0;
988cabdff1aSopenharmony_ci                        sh->rplm_l1[j].abs_diff_pic_num_minus1 =
989cabdff1aSopenharmony_ci                            pic_num - href->frame_num - 1;
990cabdff1aSopenharmony_ci                    } else {
991cabdff1aSopenharmony_ci                        sh->rplm_l1[j].modification_of_pic_nums_idc = 1;
992cabdff1aSopenharmony_ci                        sh->rplm_l1[j].abs_diff_pic_num_minus1 =
993cabdff1aSopenharmony_ci                            href->frame_num - pic_num - 1;
994cabdff1aSopenharmony_ci                    }
995cabdff1aSopenharmony_ci                    pic_num = href->frame_num;
996cabdff1aSopenharmony_ci                    ++j;
997cabdff1aSopenharmony_ci                }
998cabdff1aSopenharmony_ci                av_assert0(j == n1);
999cabdff1aSopenharmony_ci                sh->rplm_l1[j].modification_of_pic_nums_idc = 3;
1000cabdff1aSopenharmony_ci            }
1001cabdff1aSopenharmony_ci        }
1002cabdff1aSopenharmony_ci    }
1003cabdff1aSopenharmony_ci
1004cabdff1aSopenharmony_ci    vslice->macroblock_address = slice->block_start;
1005cabdff1aSopenharmony_ci    vslice->num_macroblocks    = slice->block_size;
1006cabdff1aSopenharmony_ci
1007cabdff1aSopenharmony_ci    vslice->macroblock_info = VA_INVALID_ID;
1008cabdff1aSopenharmony_ci
1009cabdff1aSopenharmony_ci    vslice->slice_type           = sh->slice_type % 5;
1010cabdff1aSopenharmony_ci    vslice->pic_parameter_set_id = sh->pic_parameter_set_id;
1011cabdff1aSopenharmony_ci    vslice->idr_pic_id           = sh->idr_pic_id;
1012cabdff1aSopenharmony_ci
1013cabdff1aSopenharmony_ci    vslice->pic_order_cnt_lsb = sh->pic_order_cnt_lsb;
1014cabdff1aSopenharmony_ci
1015cabdff1aSopenharmony_ci    vslice->direct_spatial_mv_pred_flag = sh->direct_spatial_mv_pred_flag;
1016cabdff1aSopenharmony_ci
1017cabdff1aSopenharmony_ci    for (i = 0; i < FF_ARRAY_ELEMS(vslice->RefPicList0); i++) {
1018cabdff1aSopenharmony_ci        vslice->RefPicList0[i].picture_id = VA_INVALID_ID;
1019cabdff1aSopenharmony_ci        vslice->RefPicList0[i].flags      = VA_PICTURE_H264_INVALID;
1020cabdff1aSopenharmony_ci        vslice->RefPicList1[i].picture_id = VA_INVALID_ID;
1021cabdff1aSopenharmony_ci        vslice->RefPicList1[i].flags      = VA_PICTURE_H264_INVALID;
1022cabdff1aSopenharmony_ci    }
1023cabdff1aSopenharmony_ci
1024cabdff1aSopenharmony_ci    av_assert0(pic->nb_refs <= 2);
1025cabdff1aSopenharmony_ci    if (pic->nb_refs >= 1) {
1026cabdff1aSopenharmony_ci        // Backward reference for P- or B-frame.
1027cabdff1aSopenharmony_ci        av_assert0(pic->type == PICTURE_TYPE_P ||
1028cabdff1aSopenharmony_ci                   pic->type == PICTURE_TYPE_B);
1029cabdff1aSopenharmony_ci        vslice->RefPicList0[0] = vpic->ReferenceFrames[0];
1030cabdff1aSopenharmony_ci    }
1031cabdff1aSopenharmony_ci    if (pic->nb_refs >= 2) {
1032cabdff1aSopenharmony_ci        // Forward reference for B-frame.
1033cabdff1aSopenharmony_ci        av_assert0(pic->type == PICTURE_TYPE_B);
1034cabdff1aSopenharmony_ci        vslice->RefPicList1[0] = vpic->ReferenceFrames[1];
1035cabdff1aSopenharmony_ci    }
1036cabdff1aSopenharmony_ci
1037cabdff1aSopenharmony_ci    vslice->slice_qp_delta = sh->slice_qp_delta;
1038cabdff1aSopenharmony_ci
1039cabdff1aSopenharmony_ci    return 0;
1040cabdff1aSopenharmony_ci}
1041cabdff1aSopenharmony_ci
1042cabdff1aSopenharmony_cistatic av_cold int vaapi_encode_h264_configure(AVCodecContext *avctx)
1043cabdff1aSopenharmony_ci{
1044cabdff1aSopenharmony_ci    VAAPIEncodeContext      *ctx = avctx->priv_data;
1045cabdff1aSopenharmony_ci    VAAPIEncodeH264Context *priv = avctx->priv_data;
1046cabdff1aSopenharmony_ci    int err;
1047cabdff1aSopenharmony_ci
1048cabdff1aSopenharmony_ci    err = ff_cbs_init(&priv->cbc, AV_CODEC_ID_H264, avctx);
1049cabdff1aSopenharmony_ci    if (err < 0)
1050cabdff1aSopenharmony_ci        return err;
1051cabdff1aSopenharmony_ci
1052cabdff1aSopenharmony_ci    priv->mb_width  = FFALIGN(avctx->width,  16) / 16;
1053cabdff1aSopenharmony_ci    priv->mb_height = FFALIGN(avctx->height, 16) / 16;
1054cabdff1aSopenharmony_ci
1055cabdff1aSopenharmony_ci    if (ctx->va_rc_mode == VA_RC_CQP) {
1056cabdff1aSopenharmony_ci        priv->fixed_qp_p = av_clip(ctx->rc_quality, 1, 51);
1057cabdff1aSopenharmony_ci        if (avctx->i_quant_factor > 0.0)
1058cabdff1aSopenharmony_ci            priv->fixed_qp_idr =
1059cabdff1aSopenharmony_ci                av_clip((avctx->i_quant_factor * priv->fixed_qp_p +
1060cabdff1aSopenharmony_ci                         avctx->i_quant_offset) + 0.5, 1, 51);
1061cabdff1aSopenharmony_ci        else
1062cabdff1aSopenharmony_ci            priv->fixed_qp_idr = priv->fixed_qp_p;
1063cabdff1aSopenharmony_ci        if (avctx->b_quant_factor > 0.0)
1064cabdff1aSopenharmony_ci            priv->fixed_qp_b =
1065cabdff1aSopenharmony_ci                av_clip((avctx->b_quant_factor * priv->fixed_qp_p +
1066cabdff1aSopenharmony_ci                         avctx->b_quant_offset) + 0.5, 1, 51);
1067cabdff1aSopenharmony_ci        else
1068cabdff1aSopenharmony_ci            priv->fixed_qp_b = priv->fixed_qp_p;
1069cabdff1aSopenharmony_ci
1070cabdff1aSopenharmony_ci        av_log(avctx, AV_LOG_DEBUG, "Using fixed QP = "
1071cabdff1aSopenharmony_ci               "%d / %d / %d for IDR- / P- / B-frames.\n",
1072cabdff1aSopenharmony_ci               priv->fixed_qp_idr, priv->fixed_qp_p, priv->fixed_qp_b);
1073cabdff1aSopenharmony_ci
1074cabdff1aSopenharmony_ci    } else {
1075cabdff1aSopenharmony_ci        // These still need to be  set for pic_init_qp/slice_qp_delta.
1076cabdff1aSopenharmony_ci        priv->fixed_qp_idr = 26;
1077cabdff1aSopenharmony_ci        priv->fixed_qp_p   = 26;
1078cabdff1aSopenharmony_ci        priv->fixed_qp_b   = 26;
1079cabdff1aSopenharmony_ci    }
1080cabdff1aSopenharmony_ci
1081cabdff1aSopenharmony_ci    if (!ctx->rc_mode->hrd) {
1082cabdff1aSopenharmony_ci        // Timing SEI requires a mode respecting HRD parameters.
1083cabdff1aSopenharmony_ci        priv->sei &= ~SEI_TIMING;
1084cabdff1aSopenharmony_ci    }
1085cabdff1aSopenharmony_ci
1086cabdff1aSopenharmony_ci    if (priv->sei & SEI_IDENTIFIER) {
1087cabdff1aSopenharmony_ci        const char *lavc  = LIBAVCODEC_IDENT;
1088cabdff1aSopenharmony_ci        const char *vaapi = VA_VERSION_S;
1089cabdff1aSopenharmony_ci        const char *driver;
1090cabdff1aSopenharmony_ci        int len;
1091cabdff1aSopenharmony_ci
1092cabdff1aSopenharmony_ci        memcpy(priv->sei_identifier.uuid_iso_iec_11578,
1093cabdff1aSopenharmony_ci               vaapi_encode_h264_sei_identifier_uuid,
1094cabdff1aSopenharmony_ci               sizeof(priv->sei_identifier.uuid_iso_iec_11578));
1095cabdff1aSopenharmony_ci
1096cabdff1aSopenharmony_ci        driver = vaQueryVendorString(ctx->hwctx->display);
1097cabdff1aSopenharmony_ci        if (!driver)
1098cabdff1aSopenharmony_ci            driver = "unknown driver";
1099cabdff1aSopenharmony_ci
1100cabdff1aSopenharmony_ci        len = snprintf(NULL, 0, "%s / VAAPI %s / %s", lavc, vaapi, driver);
1101cabdff1aSopenharmony_ci        if (len >= 0) {
1102cabdff1aSopenharmony_ci            priv->sei_identifier_string = av_malloc(len + 1);
1103cabdff1aSopenharmony_ci            if (!priv->sei_identifier_string)
1104cabdff1aSopenharmony_ci                return AVERROR(ENOMEM);
1105cabdff1aSopenharmony_ci
1106cabdff1aSopenharmony_ci            snprintf(priv->sei_identifier_string, len + 1,
1107cabdff1aSopenharmony_ci                     "%s / VAAPI %s / %s", lavc, vaapi, driver);
1108cabdff1aSopenharmony_ci
1109cabdff1aSopenharmony_ci            priv->sei_identifier.data        = priv->sei_identifier_string;
1110cabdff1aSopenharmony_ci            priv->sei_identifier.data_length = len + 1;
1111cabdff1aSopenharmony_ci        }
1112cabdff1aSopenharmony_ci    }
1113cabdff1aSopenharmony_ci
1114cabdff1aSopenharmony_ci    ctx->roi_quant_range = 51 + 6 * (ctx->profile->depth - 8);
1115cabdff1aSopenharmony_ci
1116cabdff1aSopenharmony_ci    return 0;
1117cabdff1aSopenharmony_ci}
1118cabdff1aSopenharmony_ci
1119cabdff1aSopenharmony_cistatic const VAAPIEncodeProfile vaapi_encode_h264_profiles[] = {
1120cabdff1aSopenharmony_ci    { FF_PROFILE_H264_HIGH, 8, 3, 1, 1, VAProfileH264High },
1121cabdff1aSopenharmony_ci    { FF_PROFILE_H264_MAIN, 8, 3, 1, 1, VAProfileH264Main },
1122cabdff1aSopenharmony_ci    { FF_PROFILE_H264_CONSTRAINED_BASELINE,
1123cabdff1aSopenharmony_ci                            8, 3, 1, 1, VAProfileH264ConstrainedBaseline },
1124cabdff1aSopenharmony_ci    { FF_PROFILE_UNKNOWN }
1125cabdff1aSopenharmony_ci};
1126cabdff1aSopenharmony_ci
1127cabdff1aSopenharmony_cistatic const VAAPIEncodeType vaapi_encode_type_h264 = {
1128cabdff1aSopenharmony_ci    .profiles              = vaapi_encode_h264_profiles,
1129cabdff1aSopenharmony_ci
1130cabdff1aSopenharmony_ci    .flags                 = FLAG_SLICE_CONTROL |
1131cabdff1aSopenharmony_ci                             FLAG_B_PICTURES |
1132cabdff1aSopenharmony_ci                             FLAG_B_PICTURE_REFERENCES |
1133cabdff1aSopenharmony_ci                             FLAG_NON_IDR_KEY_PICTURES,
1134cabdff1aSopenharmony_ci
1135cabdff1aSopenharmony_ci    .default_quality       = 20,
1136cabdff1aSopenharmony_ci
1137cabdff1aSopenharmony_ci    .configure             = &vaapi_encode_h264_configure,
1138cabdff1aSopenharmony_ci
1139cabdff1aSopenharmony_ci    .picture_priv_data_size = sizeof(VAAPIEncodeH264Picture),
1140cabdff1aSopenharmony_ci
1141cabdff1aSopenharmony_ci    .sequence_params_size  = sizeof(VAEncSequenceParameterBufferH264),
1142cabdff1aSopenharmony_ci    .init_sequence_params  = &vaapi_encode_h264_init_sequence_params,
1143cabdff1aSopenharmony_ci
1144cabdff1aSopenharmony_ci    .picture_params_size   = sizeof(VAEncPictureParameterBufferH264),
1145cabdff1aSopenharmony_ci    .init_picture_params   = &vaapi_encode_h264_init_picture_params,
1146cabdff1aSopenharmony_ci
1147cabdff1aSopenharmony_ci    .slice_params_size     = sizeof(VAEncSliceParameterBufferH264),
1148cabdff1aSopenharmony_ci    .init_slice_params     = &vaapi_encode_h264_init_slice_params,
1149cabdff1aSopenharmony_ci
1150cabdff1aSopenharmony_ci    .sequence_header_type  = VAEncPackedHeaderSequence,
1151cabdff1aSopenharmony_ci    .write_sequence_header = &vaapi_encode_h264_write_sequence_header,
1152cabdff1aSopenharmony_ci
1153cabdff1aSopenharmony_ci    .slice_header_type     = VAEncPackedHeaderH264_Slice,
1154cabdff1aSopenharmony_ci    .write_slice_header    = &vaapi_encode_h264_write_slice_header,
1155cabdff1aSopenharmony_ci
1156cabdff1aSopenharmony_ci    .write_extra_header    = &vaapi_encode_h264_write_extra_header,
1157cabdff1aSopenharmony_ci};
1158cabdff1aSopenharmony_ci
1159cabdff1aSopenharmony_cistatic av_cold int vaapi_encode_h264_init(AVCodecContext *avctx)
1160cabdff1aSopenharmony_ci{
1161cabdff1aSopenharmony_ci    VAAPIEncodeContext      *ctx = avctx->priv_data;
1162cabdff1aSopenharmony_ci    VAAPIEncodeH264Context *priv = avctx->priv_data;
1163cabdff1aSopenharmony_ci
1164cabdff1aSopenharmony_ci    ctx->codec = &vaapi_encode_type_h264;
1165cabdff1aSopenharmony_ci
1166cabdff1aSopenharmony_ci    if (avctx->profile == FF_PROFILE_UNKNOWN)
1167cabdff1aSopenharmony_ci        avctx->profile = priv->profile;
1168cabdff1aSopenharmony_ci    if (avctx->level == FF_LEVEL_UNKNOWN)
1169cabdff1aSopenharmony_ci        avctx->level = priv->level;
1170cabdff1aSopenharmony_ci    if (avctx->compression_level == FF_COMPRESSION_DEFAULT)
1171cabdff1aSopenharmony_ci        avctx->compression_level = priv->quality;
1172cabdff1aSopenharmony_ci
1173cabdff1aSopenharmony_ci    // Reject unsupported profiles.
1174cabdff1aSopenharmony_ci    switch (avctx->profile) {
1175cabdff1aSopenharmony_ci    case FF_PROFILE_H264_BASELINE:
1176cabdff1aSopenharmony_ci        av_log(avctx, AV_LOG_WARNING, "H.264 baseline profile is not "
1177cabdff1aSopenharmony_ci               "supported, using constrained baseline profile instead.\n");
1178cabdff1aSopenharmony_ci        avctx->profile = FF_PROFILE_H264_CONSTRAINED_BASELINE;
1179cabdff1aSopenharmony_ci        break;
1180cabdff1aSopenharmony_ci    case FF_PROFILE_H264_EXTENDED:
1181cabdff1aSopenharmony_ci        av_log(avctx, AV_LOG_ERROR, "H.264 extended profile "
1182cabdff1aSopenharmony_ci               "is not supported.\n");
1183cabdff1aSopenharmony_ci        return AVERROR_PATCHWELCOME;
1184cabdff1aSopenharmony_ci    case FF_PROFILE_H264_HIGH_10:
1185cabdff1aSopenharmony_ci    case FF_PROFILE_H264_HIGH_10_INTRA:
1186cabdff1aSopenharmony_ci        av_log(avctx, AV_LOG_ERROR, "H.264 10-bit profiles "
1187cabdff1aSopenharmony_ci               "are not supported.\n");
1188cabdff1aSopenharmony_ci        return AVERROR_PATCHWELCOME;
1189cabdff1aSopenharmony_ci    case FF_PROFILE_H264_HIGH_422:
1190cabdff1aSopenharmony_ci    case FF_PROFILE_H264_HIGH_422_INTRA:
1191cabdff1aSopenharmony_ci    case FF_PROFILE_H264_HIGH_444:
1192cabdff1aSopenharmony_ci    case FF_PROFILE_H264_HIGH_444_PREDICTIVE:
1193cabdff1aSopenharmony_ci    case FF_PROFILE_H264_HIGH_444_INTRA:
1194cabdff1aSopenharmony_ci    case FF_PROFILE_H264_CAVLC_444:
1195cabdff1aSopenharmony_ci        av_log(avctx, AV_LOG_ERROR, "H.264 non-4:2:0 profiles "
1196cabdff1aSopenharmony_ci               "are not supported.\n");
1197cabdff1aSopenharmony_ci        return AVERROR_PATCHWELCOME;
1198cabdff1aSopenharmony_ci    }
1199cabdff1aSopenharmony_ci
1200cabdff1aSopenharmony_ci    if (avctx->level != FF_LEVEL_UNKNOWN && avctx->level & ~0xff) {
1201cabdff1aSopenharmony_ci        av_log(avctx, AV_LOG_ERROR, "Invalid level %d: must fit "
1202cabdff1aSopenharmony_ci               "in 8-bit unsigned integer.\n", avctx->level);
1203cabdff1aSopenharmony_ci        return AVERROR(EINVAL);
1204cabdff1aSopenharmony_ci    }
1205cabdff1aSopenharmony_ci
1206cabdff1aSopenharmony_ci    ctx->desired_packed_headers =
1207cabdff1aSopenharmony_ci        VA_ENC_PACKED_HEADER_SEQUENCE | // SPS and PPS.
1208cabdff1aSopenharmony_ci        VA_ENC_PACKED_HEADER_SLICE    | // Slice headers.
1209cabdff1aSopenharmony_ci        VA_ENC_PACKED_HEADER_MISC;      // SEI.
1210cabdff1aSopenharmony_ci
1211cabdff1aSopenharmony_ci    ctx->surface_width  = FFALIGN(avctx->width,  16);
1212cabdff1aSopenharmony_ci    ctx->surface_height = FFALIGN(avctx->height, 16);
1213cabdff1aSopenharmony_ci
1214cabdff1aSopenharmony_ci    ctx->slice_block_height = ctx->slice_block_width = 16;
1215cabdff1aSopenharmony_ci
1216cabdff1aSopenharmony_ci    if (priv->qp > 0)
1217cabdff1aSopenharmony_ci        ctx->explicit_qp = priv->qp;
1218cabdff1aSopenharmony_ci
1219cabdff1aSopenharmony_ci    return ff_vaapi_encode_init(avctx);
1220cabdff1aSopenharmony_ci}
1221cabdff1aSopenharmony_ci
1222cabdff1aSopenharmony_cistatic av_cold int vaapi_encode_h264_close(AVCodecContext *avctx)
1223cabdff1aSopenharmony_ci{
1224cabdff1aSopenharmony_ci    VAAPIEncodeH264Context *priv = avctx->priv_data;
1225cabdff1aSopenharmony_ci
1226cabdff1aSopenharmony_ci    ff_cbs_fragment_free(&priv->current_access_unit);
1227cabdff1aSopenharmony_ci    ff_cbs_close(&priv->cbc);
1228cabdff1aSopenharmony_ci    av_freep(&priv->sei_identifier_string);
1229cabdff1aSopenharmony_ci
1230cabdff1aSopenharmony_ci    return ff_vaapi_encode_close(avctx);
1231cabdff1aSopenharmony_ci}
1232cabdff1aSopenharmony_ci
1233cabdff1aSopenharmony_ci#define OFFSET(x) offsetof(VAAPIEncodeH264Context, x)
1234cabdff1aSopenharmony_ci#define FLAGS (AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM)
1235cabdff1aSopenharmony_cistatic const AVOption vaapi_encode_h264_options[] = {
1236cabdff1aSopenharmony_ci    VAAPI_ENCODE_COMMON_OPTIONS,
1237cabdff1aSopenharmony_ci    VAAPI_ENCODE_RC_OPTIONS,
1238cabdff1aSopenharmony_ci
1239cabdff1aSopenharmony_ci    { "qp", "Constant QP (for P-frames; scaled by qfactor/qoffset for I/B)",
1240cabdff1aSopenharmony_ci      OFFSET(qp), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 52, FLAGS },
1241cabdff1aSopenharmony_ci    { "quality", "Set encode quality (trades off against speed, higher is faster)",
1242cabdff1aSopenharmony_ci      OFFSET(quality), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, INT_MAX, FLAGS },
1243cabdff1aSopenharmony_ci    { "coder", "Entropy coder type",
1244cabdff1aSopenharmony_ci      OFFSET(coder), AV_OPT_TYPE_INT, { .i64 = 1 }, 0, 1, FLAGS, "coder" },
1245cabdff1aSopenharmony_ci        { "cavlc", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 0 }, INT_MIN, INT_MAX, FLAGS, "coder" },
1246cabdff1aSopenharmony_ci        { "cabac", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 1 }, INT_MIN, INT_MAX, FLAGS, "coder" },
1247cabdff1aSopenharmony_ci        { "vlc",   NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 0 }, INT_MIN, INT_MAX, FLAGS, "coder" },
1248cabdff1aSopenharmony_ci        { "ac",    NULL, 0, AV_OPT_TYPE_CONST, { .i64 = 1 }, INT_MIN, INT_MAX, FLAGS, "coder" },
1249cabdff1aSopenharmony_ci
1250cabdff1aSopenharmony_ci    { "aud", "Include AUD",
1251cabdff1aSopenharmony_ci      OFFSET(aud), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, FLAGS },
1252cabdff1aSopenharmony_ci
1253cabdff1aSopenharmony_ci    { "sei", "Set SEI to include",
1254cabdff1aSopenharmony_ci      OFFSET(sei), AV_OPT_TYPE_FLAGS,
1255cabdff1aSopenharmony_ci      { .i64 = SEI_IDENTIFIER | SEI_TIMING | SEI_RECOVERY_POINT },
1256cabdff1aSopenharmony_ci      0, INT_MAX, FLAGS, "sei" },
1257cabdff1aSopenharmony_ci    { "identifier", "Include encoder version identifier",
1258cabdff1aSopenharmony_ci      0, AV_OPT_TYPE_CONST, { .i64 = SEI_IDENTIFIER },
1259cabdff1aSopenharmony_ci      INT_MIN, INT_MAX, FLAGS, "sei" },
1260cabdff1aSopenharmony_ci    { "timing", "Include timing parameters (buffering_period and pic_timing)",
1261cabdff1aSopenharmony_ci      0, AV_OPT_TYPE_CONST, { .i64 = SEI_TIMING },
1262cabdff1aSopenharmony_ci      INT_MIN, INT_MAX, FLAGS, "sei" },
1263cabdff1aSopenharmony_ci    { "recovery_point", "Include recovery points where appropriate",
1264cabdff1aSopenharmony_ci      0, AV_OPT_TYPE_CONST, { .i64 = SEI_RECOVERY_POINT },
1265cabdff1aSopenharmony_ci      INT_MIN, INT_MAX, FLAGS, "sei" },
1266cabdff1aSopenharmony_ci
1267cabdff1aSopenharmony_ci    { "profile", "Set profile (profile_idc and constraint_set*_flag)",
1268cabdff1aSopenharmony_ci      OFFSET(profile), AV_OPT_TYPE_INT,
1269cabdff1aSopenharmony_ci      { .i64 = FF_PROFILE_UNKNOWN }, FF_PROFILE_UNKNOWN, 0xffff, FLAGS, "profile" },
1270cabdff1aSopenharmony_ci
1271cabdff1aSopenharmony_ci#define PROFILE(name, value)  name, NULL, 0, AV_OPT_TYPE_CONST, \
1272cabdff1aSopenharmony_ci      { .i64 = value }, 0, 0, FLAGS, "profile"
1273cabdff1aSopenharmony_ci    { PROFILE("constrained_baseline", FF_PROFILE_H264_CONSTRAINED_BASELINE) },
1274cabdff1aSopenharmony_ci    { PROFILE("main",                 FF_PROFILE_H264_MAIN) },
1275cabdff1aSopenharmony_ci    { PROFILE("high",                 FF_PROFILE_H264_HIGH) },
1276cabdff1aSopenharmony_ci#undef PROFILE
1277cabdff1aSopenharmony_ci
1278cabdff1aSopenharmony_ci    { "level", "Set level (level_idc)",
1279cabdff1aSopenharmony_ci      OFFSET(level), AV_OPT_TYPE_INT,
1280cabdff1aSopenharmony_ci      { .i64 = FF_LEVEL_UNKNOWN }, FF_LEVEL_UNKNOWN, 0xff, FLAGS, "level" },
1281cabdff1aSopenharmony_ci
1282cabdff1aSopenharmony_ci#define LEVEL(name, value) name, NULL, 0, AV_OPT_TYPE_CONST, \
1283cabdff1aSopenharmony_ci      { .i64 = value }, 0, 0, FLAGS, "level"
1284cabdff1aSopenharmony_ci    { LEVEL("1",   10) },
1285cabdff1aSopenharmony_ci    { LEVEL("1.1", 11) },
1286cabdff1aSopenharmony_ci    { LEVEL("1.2", 12) },
1287cabdff1aSopenharmony_ci    { LEVEL("1.3", 13) },
1288cabdff1aSopenharmony_ci    { LEVEL("2",   20) },
1289cabdff1aSopenharmony_ci    { LEVEL("2.1", 21) },
1290cabdff1aSopenharmony_ci    { LEVEL("2.2", 22) },
1291cabdff1aSopenharmony_ci    { LEVEL("3",   30) },
1292cabdff1aSopenharmony_ci    { LEVEL("3.1", 31) },
1293cabdff1aSopenharmony_ci    { LEVEL("3.2", 32) },
1294cabdff1aSopenharmony_ci    { LEVEL("4",   40) },
1295cabdff1aSopenharmony_ci    { LEVEL("4.1", 41) },
1296cabdff1aSopenharmony_ci    { LEVEL("4.2", 42) },
1297cabdff1aSopenharmony_ci    { LEVEL("5",   50) },
1298cabdff1aSopenharmony_ci    { LEVEL("5.1", 51) },
1299cabdff1aSopenharmony_ci    { LEVEL("5.2", 52) },
1300cabdff1aSopenharmony_ci    { LEVEL("6",   60) },
1301cabdff1aSopenharmony_ci    { LEVEL("6.1", 61) },
1302cabdff1aSopenharmony_ci    { LEVEL("6.2", 62) },
1303cabdff1aSopenharmony_ci#undef LEVEL
1304cabdff1aSopenharmony_ci
1305cabdff1aSopenharmony_ci    { NULL },
1306cabdff1aSopenharmony_ci};
1307cabdff1aSopenharmony_ci
1308cabdff1aSopenharmony_cistatic const FFCodecDefault vaapi_encode_h264_defaults[] = {
1309cabdff1aSopenharmony_ci    { "b",              "0"   },
1310cabdff1aSopenharmony_ci    { "bf",             "2"   },
1311cabdff1aSopenharmony_ci    { "g",              "120" },
1312cabdff1aSopenharmony_ci    { "i_qfactor",      "1"   },
1313cabdff1aSopenharmony_ci    { "i_qoffset",      "0"   },
1314cabdff1aSopenharmony_ci    { "b_qfactor",      "6/5" },
1315cabdff1aSopenharmony_ci    { "b_qoffset",      "0"   },
1316cabdff1aSopenharmony_ci    { "qmin",           "-1"  },
1317cabdff1aSopenharmony_ci    { "qmax",           "-1"  },
1318cabdff1aSopenharmony_ci    { NULL },
1319cabdff1aSopenharmony_ci};
1320cabdff1aSopenharmony_ci
1321cabdff1aSopenharmony_cistatic const AVClass vaapi_encode_h264_class = {
1322cabdff1aSopenharmony_ci    .class_name = "h264_vaapi",
1323cabdff1aSopenharmony_ci    .item_name  = av_default_item_name,
1324cabdff1aSopenharmony_ci    .option     = vaapi_encode_h264_options,
1325cabdff1aSopenharmony_ci    .version    = LIBAVUTIL_VERSION_INT,
1326cabdff1aSopenharmony_ci};
1327cabdff1aSopenharmony_ci
1328cabdff1aSopenharmony_ciconst FFCodec ff_h264_vaapi_encoder = {
1329cabdff1aSopenharmony_ci    .p.name         = "h264_vaapi",
1330cabdff1aSopenharmony_ci    .p.long_name    = NULL_IF_CONFIG_SMALL("H.264/AVC (VAAPI)"),
1331cabdff1aSopenharmony_ci    .p.type         = AVMEDIA_TYPE_VIDEO,
1332cabdff1aSopenharmony_ci    .p.id           = AV_CODEC_ID_H264,
1333cabdff1aSopenharmony_ci    .priv_data_size = sizeof(VAAPIEncodeH264Context),
1334cabdff1aSopenharmony_ci    .init           = &vaapi_encode_h264_init,
1335cabdff1aSopenharmony_ci    FF_CODEC_RECEIVE_PACKET_CB(&ff_vaapi_encode_receive_packet),
1336cabdff1aSopenharmony_ci    .close          = &vaapi_encode_h264_close,
1337cabdff1aSopenharmony_ci    .p.priv_class   = &vaapi_encode_h264_class,
1338cabdff1aSopenharmony_ci    .p.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HARDWARE |
1339cabdff1aSopenharmony_ci                      AV_CODEC_CAP_DR1,
1340cabdff1aSopenharmony_ci    .caps_internal  = FF_CODEC_CAP_INIT_CLEANUP,
1341cabdff1aSopenharmony_ci    .defaults       = vaapi_encode_h264_defaults,
1342cabdff1aSopenharmony_ci    .p.pix_fmts = (const enum AVPixelFormat[]) {
1343cabdff1aSopenharmony_ci        AV_PIX_FMT_VAAPI,
1344cabdff1aSopenharmony_ci        AV_PIX_FMT_NONE,
1345cabdff1aSopenharmony_ci    },
1346cabdff1aSopenharmony_ci    .hw_configs     = ff_vaapi_encode_hw_configs,
1347cabdff1aSopenharmony_ci    .p.wrapper_name = "vaapi",
1348cabdff1aSopenharmony_ci};
1349