History

lavc/vaapi_encode: Add VAAPI AV1 encoder

Fei Wang committed 3 years ago

Commit 3be81e31 parent 254c5a811 files · +1311 −33Browse files

Unified · Split

11 files
  1. Changelog +1 −0
  2. configure +3 −0
  3. doc/encoders.texi +14 −0
  4. libavcodec/Makefile +2 −0
  5. libavcodec/allcodecs.c +1 −0
  6. libavcodec/av1_levels.c +92 −0
  7. libavcodec/av1_levels.h +58 −0
  8. libavcodec/vaapi_encode.c +166 −32
  9. libavcodec/vaapi_encode.h +24 −0
  10. libavcodec/vaapi_encode_av1.c +949 −0
  11. libavcodec/version.h +1 −1
Changelog+1−0
@@ -34,6 +34,7 @@ version <next>: · 33 unmodified lines
34- Support HEVC,VP9,AV1 codec fourcclist in enhanced rtmp protocol34- Support HEVC,VP9,AV1 codec fourcclist in enhanced rtmp protocol
35- CRI USM demuxer35- CRI USM demuxer
36- ffmpeg CLI '-top' option deprecated in favor of the setfield filter36- ffmpeg CLI '-top' option deprecated in favor of the setfield filter
37- VAAPI AV1 encoder
37 38
38 39
39version 6.0:40version 6.0:
configure+3−0
@@ -3323,6 +3323,8 @@ av1_qsv_decoder_select="qsvdec" · 3322 unmodified lines
3323av1_qsv_encoder_select="qsvenc"3323av1_qsv_encoder_select="qsvenc"
3324av1_qsv_encoder_deps="libvpl"3324av1_qsv_encoder_deps="libvpl"
3325av1_amf_encoder_deps="amf"3325av1_amf_encoder_deps="amf"
3326av1_vaapi_encoder_deps="VAEncPictureParameterBufferAV1"
3327av1_vaapi_encoder_select="cbs_av1 vaapi_encode"
3326 3328
3327# parsers3329# parsers
3328aac_parser_select="adts_header mpeg4audio"3330aac_parser_select="adts_header mpeg4audio"
@@ -7108,6 +7110,7 @@ if enabled vaapi; then · 3779 unmodified lines
7108 check_type "va/va.h va/va_enc_jpeg.h" "VAEncPictureParameterBufferJPEG"7110 check_type "va/va.h va/va_enc_jpeg.h" "VAEncPictureParameterBufferJPEG"
7109 check_type "va/va.h va/va_enc_vp8.h" "VAEncPictureParameterBufferVP8"7111 check_type "va/va.h va/va_enc_vp8.h" "VAEncPictureParameterBufferVP8"
7110 check_type "va/va.h va/va_enc_vp9.h" "VAEncPictureParameterBufferVP9"7112 check_type "va/va.h va/va_enc_vp9.h" "VAEncPictureParameterBufferVP9"
7113 check_type "va/va.h va/va_enc_av1.h" "VAEncPictureParameterBufferAV1"
7111fi7114fi
7112 7115
7113if enabled_all opencl libdrm ; then7116if enabled_all opencl libdrm ; then
doc/encoders.texi+14−0
@@ -3995,6 +3995,20 @@ Average variable bitrate. · 3994 unmodified lines
3995Each encoder also has its own specific options:3995Each encoder also has its own specific options:
3996@table @option3996@table @option
3997 3997
3998@item av1_vaapi
3999@option{profile} sets the value of @emph{seq_profile}.
4000@option{tier} sets the value of @emph{seq_tier}.
4001@option{level} sets the value of @emph{seq_level_idx}.
4002
4003@table @option
4004@item tiles
4005Set the number of tiles to encode the input video with, as columns x rows.
4006(default is auto, which means use minimal tile column/row number).
4007@item tile_groups
4008Set tile groups number. All the tiles will be distributed as evenly as possible to
4009each tile group. (default is 1).
4010@end table
4011
3998@item h264_vaapi4012@item h264_vaapi
3999@option{profile} sets the value of @emph{profile_idc} and the @emph{constraint_set*_flag}s.4013@option{profile} sets the value of @emph{profile_idc} and the @emph{constraint_set*_flag}s.
4000@option{level} sets the value of @emph{level_idc}.4014@option{level} sets the value of @emph{level_idc}.
libavcodec/Makefile+2−0
@@ -258,6 +258,7 @@ OBJS-$(CONFIG_AV1_MEDIACODEC_DECODER) += mediacodecdec.o · 257 unmodified lines
258OBJS-$(CONFIG_AV1_MEDIACODEC_ENCODER) += mediacodecenc.o258OBJS-$(CONFIG_AV1_MEDIACODEC_ENCODER) += mediacodecenc.o
259OBJS-$(CONFIG_AV1_NVENC_ENCODER) += nvenc_av1.o nvenc.o259OBJS-$(CONFIG_AV1_NVENC_ENCODER) += nvenc_av1.o nvenc.o
260OBJS-$(CONFIG_AV1_QSV_ENCODER) += qsvenc_av1.o260OBJS-$(CONFIG_AV1_QSV_ENCODER) += qsvenc_av1.o
261OBJS-$(CONFIG_AV1_VAAPI_ENCODER) += vaapi_encode_av1.o av1_levels.o
261OBJS-$(CONFIG_AVRN_DECODER) += avrndec.o262OBJS-$(CONFIG_AVRN_DECODER) += avrndec.o
262OBJS-$(CONFIG_AVRP_DECODER) += r210dec.o263OBJS-$(CONFIG_AVRP_DECODER) += r210dec.o
263OBJS-$(CONFIG_AVRP_ENCODER) += r210enc.o264OBJS-$(CONFIG_AVRP_ENCODER) += r210enc.o
@@ -1322,6 +1323,7 @@ TESTPROGS = avcodec \ · 1058 unmodified lines
1322 jpeg2000dwt \1323 jpeg2000dwt \
1323 mathops \1324 mathops \
1324 1325
1326TESTPROGS-$(CONFIG_AV1_VAAPI_ENCODER) += av1_levels
1325TESTPROGS-$(CONFIG_CABAC) += cabac1327TESTPROGS-$(CONFIG_CABAC) += cabac
1326TESTPROGS-$(CONFIG_DCT) += avfft1328TESTPROGS-$(CONFIG_DCT) += avfft
1327TESTPROGS-$(CONFIG_FFT) += fft fft-fixed321329TESTPROGS-$(CONFIG_FFT) += fft fft-fixed32
libavcodec/allcodecs.c+1−0
@@ -845,6 +845,7 @@ extern const FFCodec ff_av1_nvenc_encoder; · 844 unmodified lines
845extern const FFCodec ff_av1_qsv_decoder;845extern const FFCodec ff_av1_qsv_decoder;
846extern const FFCodec ff_av1_qsv_encoder;846extern const FFCodec ff_av1_qsv_encoder;
847extern const FFCodec ff_av1_amf_encoder;847extern const FFCodec ff_av1_amf_encoder;
848extern const FFCodec ff_av1_vaapi_encoder;
848extern const FFCodec ff_libopenh264_encoder;849extern const FFCodec ff_libopenh264_encoder;
849extern const FFCodec ff_libopenh264_decoder;850extern const FFCodec ff_libopenh264_decoder;
850extern const FFCodec ff_h264_amf_encoder;851extern const FFCodec ff_h264_amf_encoder;
libavcodec/av1_levels.c+92−0
@@ -0,0 +1,92 @@
1/*
2 * Copyright (c) 2023 Intel Corporation
3 *
4 * This file is part of FFmpeg.
5 *
6 * FFmpeg is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * FFmpeg is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with FFmpeg; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21#include <stddef.h>
22#include "libavutil/macros.h"
23#include "av1_levels.h"
24
25/** ignore entries which named in spec but no details. Like level 2.2 and 7.0. */
26static const AV1LevelDescriptor av1_levels[] = {
27 // Name MaxVSize MainMbps MaxTiles
28 // | level_idx | MaxDisplayRate | HighMbps | MaxTileCols
29 // | | MaxPicSize | | MaxDecodeRate | | MainCR | |
30 // | | | MaxHSize | | | MaxHeaderRate | | | HighCR| |
31 // | | | | | | | | | | | | | |
32 { "2.0", 0, 147456, 2048, 1152, 4423680, 5529600, 150, 1.5, 0, 2, 0, 8, 4 },
33 { "2.1", 1, 278784, 2816, 1584, 8363520, 10454400, 150, 3.0, 0, 2, 0, 8, 4 },
34 { "3.0", 4, 665856, 4352, 2448, 19975680, 24969600, 150, 6.0, 0, 2, 0, 16, 6 },
35 { "3.1", 5, 1065024, 5504, 3096, 31950720, 39938400, 150, 10.0, 0, 2, 0, 16, 6 },
36 { "4.0", 8, 2359296, 6144, 3456, 70778880, 77856768, 300, 12.0, 30.0, 4, 4, 32, 8 },
37 { "4.1", 9, 2359296, 6144, 3456, 141557760, 155713536, 300, 20.0, 50.0, 4, 4, 32, 8 },
38 { "5.0", 12, 8912896, 8192, 4352, 267386880, 273715200, 300, 30.0, 100.0, 6, 4, 64, 8 },
39 { "5.1", 13, 8912896, 8192, 4352, 534773760, 547430400, 300, 40.0, 160.0, 8, 4, 64, 8 },
40 { "5.2", 14, 8912896, 8192, 4352, 1069547520, 1094860800, 300, 60.0, 240.0, 8, 4, 64, 8 },
41 { "5.3", 15, 8912896, 8192, 4352, 1069547520, 1176502272, 300, 60.0, 240.0, 8, 4, 64, 8 },
42 { "6.0", 16, 35651584, 16384, 8704, 1069547520, 1176502272, 300, 60.0, 240.0, 8, 4, 128, 16 },
43 { "6.1", 17, 35651584, 16384, 8704, 2139095040, 2189721600, 300, 100.0, 480.0, 8, 4, 128, 16 },
44 { "6.2", 18, 35651584, 16384, 8704, 4278190080, 4379443200, 300, 160.0, 800.0, 8, 4, 128, 16 },
45 { "6.3", 19, 35651584, 16384, 8704, 4278190080, 4706009088, 300, 160.0, 800.0, 8, 4, 128, 16 },
46};
47
48const AV1LevelDescriptor *ff_av1_guess_level(int64_t bitrate,
49 int tier,
50 int width,
51 int height,
52 int tiles,
53 int tile_cols,
54 float fps)
55{
56 int pic_size;
57 uint64_t display_rate;
58 float max_br;
59
60 pic_size = width * height;
61 display_rate = (uint64_t)pic_size * fps;
62
63 for (int i = 0; i < FF_ARRAY_ELEMS(av1_levels); i++) {
64 const AV1LevelDescriptor *level = &av1_levels[i];
65 // Limitation: decode rate, header rate, compress rate, etc. are not considered.
66 if (pic_size > level->max_pic_size)
67 continue;
68 if (width > level->max_h_size)
69 continue;
70 if (height > level->max_v_size)
71 continue;
72 if (display_rate > level->max_display_rate)
73 continue;
74
75 if (tier)
76 max_br = level->high_mbps;
77 else
78 max_br = level->main_mbps;
79 if (!max_br)
80 continue;
81 if (bitrate > (int64_t)(1000000.0 * max_br))
82 continue;
83
84 if (tiles > level->max_tiles)
85 continue;
86 if (tile_cols > level->max_tile_cols)
87 continue;
88 return level;
89 }
90
91 return NULL;
92}
libavcodec/av1_levels.h+58−0
@@ -0,0 +1,58 @@
1/*
2 * Copyright (c) 2023 Intel Corporation
3 *
4 * This file is part of FFmpeg.
5 *
6 * FFmpeg is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * FFmpeg is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with FFmpeg; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21#ifndef AVCODEC_AV1_LEVELS_H
22#define AVCODEC_AV1_LEVELS_H
23
24#include <stdint.h>
25
26typedef struct AV1LevelDescriptor {
27 char name[4];
28 uint8_t level_idx;
29
30 uint32_t max_pic_size;
31 uint32_t max_h_size;
32 uint32_t max_v_size;
33 uint64_t max_display_rate;
34 uint64_t max_decode_rate;
35
36 uint32_t max_header_rate;
37 float main_mbps;
38 float high_mbps;
39 uint32_t main_cr;
40 uint32_t high_cr;
41 uint32_t max_tiles;
42 uint32_t max_tile_cols;
43} AV1LevelDescriptor;
44
45/**
46 * Guess the level of a stream from some parameters.
47 *
48 * Unknown parameters may be zero, in which case they will be ignored.
49 */
50const AV1LevelDescriptor *ff_av1_guess_level(int64_t bitrate,
51 int tier,
52 int width,
53 int height,
54 int tile_rows,
55 int tile_cols,
56 float fps);
57
58#endif /* AVCODEC_AV1_LEVELS_H */
libavcodec/vaapi_encode.c+166−32
@@ -683,6 +683,11 @@ static int vaapi_encode_set_output_property(AVCodecContext *avctx, · 682 unmodified lines
683 pic->opaque_ref = NULL;683 pic->opaque_ref = NULL;
684 }684 }
685 685
686 if (ctx->codec->flags & FLAG_TIMESTAMP_NO_DELAY) {
687 pkt->dts = pkt->pts;
688 return 0;
689 }
690
686 if (ctx->output_delay == 0) {691 if (ctx->output_delay == 0) {
687 pkt->dts = pkt->pts;692 pkt->dts = pkt->pts;
688 } else if (pic->encode_order < ctx->decode_delay) {693 } else if (pic->encode_order < ctx->decode_delay) {
@@ -698,65 +703,160 @@ static int vaapi_encode_set_output_property(AVCodecContext *avctx, · 9 unmodified lines
698 return 0;703 return 0;
699}704}
700 705
701static int vaapi_encode_output(AVCodecContext *avctx,706static int vaapi_encode_get_coded_buffer_size(AVCodecContext *avctx, VABufferID buf_id)
702 VAAPIEncodePicture *pic, AVPacket *pkt)
703{707{
704 VAAPIEncodeContext *ctx = avctx->priv_data;708 VAAPIEncodeContext *ctx = avctx->priv_data;
705 VACodedBufferSegment *buf_list, *buf;709 VACodedBufferSegment *buf_list, *buf;
710 int size = 0;
706 VAStatus vas;711 VAStatus vas;
707 int total_size = 0;
708 uint8_t *ptr;
709 int err;712 int err;
710 713
711 err = vaapi_encode_wait(avctx, pic);714 vas = vaMapBuffer(ctx->hwctx->display, buf_id,
712 if (err < 0)
713 return err;
714
715 buf_list = NULL;
716 vas = vaMapBuffer(ctx->hwctx->display, pic->output_buffer,
717 (void**)&buf_list);715 (void**)&buf_list);
718 if (vas != VA_STATUS_SUCCESS) {716 if (vas != VA_STATUS_SUCCESS) {
719 av_log(avctx, AV_LOG_ERROR, "Failed to map output buffers: "717 av_log(avctx, AV_LOG_ERROR, "Failed to map output buffers: "
720 "%d (%s).\n", vas, vaErrorStr(vas));718 "%d (%s).\n", vas, vaErrorStr(vas));
721 err = AVERROR(EIO);719 err = AVERROR(EIO);
722 goto fail;720 return err;
723 }721 }
724 722
725 for (buf = buf_list; buf; buf = buf->next)723 for (buf = buf_list; buf; buf = buf->next)
726 total_size += buf->size;724 size += buf->size;
727 725
728 err = ff_get_encode_buffer(avctx, pkt, total_size, 0);726 vas = vaUnmapBuffer(ctx->hwctx->display, buf_id);
729 ptr = pkt->data;727 if (vas != VA_STATUS_SUCCESS) {
728 av_log(avctx, AV_LOG_ERROR, "Failed to unmap output buffers: "
729 "%d (%s).\n", vas, vaErrorStr(vas));
730 err = AVERROR(EIO);
731 return err;
732 }
730 733
731 if (err < 0)734 return size;
732 goto fail_mapped;735}
736
737static int vaapi_encode_get_coded_buffer_data(AVCodecContext *avctx,
738 VABufferID buf_id, uint8_t **dst)
739{
740 VAAPIEncodeContext *ctx = avctx->priv_data;
741 VACodedBufferSegment *buf_list, *buf;
742 VAStatus vas;
743 int err;
744
745 vas = vaMapBuffer(ctx->hwctx->display, buf_id,
746 (void**)&buf_list);
747 if (vas != VA_STATUS_SUCCESS) {
748 av_log(avctx, AV_LOG_ERROR, "Failed to map output buffers: "
749 "%d (%s).\n", vas, vaErrorStr(vas));
750 err = AVERROR(EIO);
751 return err;
752 }
733 753
734 for (buf = buf_list; buf; buf = buf->next) {754 for (buf = buf_list; buf; buf = buf->next) {
735 av_log(avctx, AV_LOG_DEBUG, "Output buffer: %u bytes "755 av_log(avctx, AV_LOG_DEBUG, "Output buffer: %u bytes "
736 "(status %08x).\n", buf->size, buf->status);756 "(status %08x).\n", buf->size, buf->status);
737 757
738 memcpy(ptr, buf->buf, buf->size);758 memcpy(*dst, buf->buf, buf->size);
739 ptr += buf->size;759 *dst += buf->size;
740 }760 }
741 761
742 vas = vaUnmapBuffer(ctx->hwctx->display, pic->output_buffer);762 vas = vaUnmapBuffer(ctx->hwctx->display, buf_id);
743 if (vas != VA_STATUS_SUCCESS) {763 if (vas != VA_STATUS_SUCCESS) {
744 av_log(avctx, AV_LOG_ERROR, "Failed to unmap output buffers: "764 av_log(avctx, AV_LOG_ERROR, "Failed to unmap output buffers: "
745 "%d (%s).\n", vas, vaErrorStr(vas));765 "%d (%s).\n", vas, vaErrorStr(vas));
746 err = AVERROR(EIO);766 err = AVERROR(EIO);
747 goto fail;767 return err;
768 }
769
770 return 0;
771}
772
773static int vaapi_encode_get_coded_data(AVCodecContext *avctx,
774 VAAPIEncodePicture *pic, AVPacket *pkt)
775{
776 VAAPIEncodeContext *ctx = avctx->priv_data;
777 VABufferID output_buffer_prev;
778 int total_size = 0;
779 uint8_t *ptr;
780 int ret;
781
782 if (ctx->coded_buffer_ref) {
783 output_buffer_prev = (VABufferID)(uintptr_t)ctx->coded_buffer_ref->data;
784 ret = vaapi_encode_get_coded_buffer_size(avctx, output_buffer_prev);
785 if (ret < 0)
786 goto end;
787 total_size += ret;
748 }788 }
749 789
790 ret = vaapi_encode_get_coded_buffer_size(avctx, pic->output_buffer);
791 if (ret < 0)
792 goto end;
793 total_size += ret;
794
795 ret = ff_get_encode_buffer(avctx, pkt, total_size, 0);
796 if (ret < 0)
797 goto end;
798 ptr = pkt->data;
799
800 if (ctx->coded_buffer_ref) {
801 ret = vaapi_encode_get_coded_buffer_data(avctx, output_buffer_prev, &ptr);
802 if (ret < 0)
803 goto end;
804 }
805
806 ret = vaapi_encode_get_coded_buffer_data(avctx, pic->output_buffer, &ptr);
807 if (ret < 0)
808 goto end;
809
810end:
811 if (ctx->coded_buffer_ref) {
812 av_buffer_unref(&ctx->coded_buffer_ref);
813 }
750 av_buffer_unref(&pic->output_buffer_ref);814 av_buffer_unref(&pic->output_buffer_ref);
751 pic->output_buffer = VA_INVALID_ID;815 pic->output_buffer = VA_INVALID_ID;
752 816
817 return ret;
818}
819
820static int vaapi_encode_output(AVCodecContext *avctx,
821 VAAPIEncodePicture *pic, AVPacket *pkt)
822{
823 VAAPIEncodeContext *ctx = avctx->priv_data;
824 AVPacket *pkt_ptr = pkt;
825 int err;
826
827 err = vaapi_encode_wait(avctx, pic);
828 if (err < 0)
829 return err;
830
831 if (pic->non_independent_frame) {
832 av_assert0(!ctx->coded_buffer_ref);
833 ctx->coded_buffer_ref = av_buffer_ref(pic->output_buffer_ref);
834
835 if (pic->tail_size) {
836 if (ctx->tail_pkt->size) {
837 err = AVERROR(AVERROR_BUG);
838 goto end;
839 }
840
841 err = ff_get_encode_buffer(avctx, ctx->tail_pkt, pic->tail_size, 0);
842 if (err < 0)
843 goto end;
844
845 memcpy(ctx->tail_pkt->data, pic->tail_data, pic->tail_size);
846 pkt_ptr = ctx->tail_pkt;
847 }
848 } else {
849 err = vaapi_encode_get_coded_data(avctx, pic, pkt);
850 if (err < 0)
851 goto end;
852 }
853
753 av_log(avctx, AV_LOG_DEBUG, "Output read for pic %"PRId64"/%"PRId64".\n",854 av_log(avctx, AV_LOG_DEBUG, "Output read for pic %"PRId64"/%"PRId64".\n",
754 pic->display_order, pic->encode_order);855 pic->display_order, pic->encode_order);
755 return 0;
756 856
757fail_mapped:857 vaapi_encode_set_output_property(avctx, pic, pkt_ptr);
758 vaUnmapBuffer(ctx->hwctx->display, pic->output_buffer);858
759fail:859end:
760 av_buffer_unref(&pic->output_buffer_ref);860 av_buffer_unref(&pic->output_buffer_ref);
761 pic->output_buffer = VA_INVALID_ID;861 pic->output_buffer = VA_INVALID_ID;
762 return err;862 return err;
@@ -1128,9 +1228,19 @@ static int vaapi_encode_pick_next(AVCodecContext *avctx, · 365 unmodified lines
1128 1228
1129 vaapi_encode_add_ref(avctx, pic, pic, 0, 1, 0);1229 vaapi_encode_add_ref(avctx, pic, pic, 0, 1, 0);
1130 if (pic->type != PICTURE_TYPE_IDR) {1230 if (pic->type != PICTURE_TYPE_IDR) {
1131 vaapi_encode_add_ref(avctx, pic, start,1231 // TODO: apply both previous and forward multi reference for all vaapi encoders.
1132 pic->type == PICTURE_TYPE_P,1232 // And L0/L1 reference frame number can be set dynamically through query
1133 b_counter > 0, 0);1233 // VAConfigAttribEncMaxRefFrames attribute.
1234 if (avctx->codec_id == AV_CODEC_ID_AV1) {
1235 for (i = 0; i < ctx->nb_next_prev; i++)
1236 vaapi_encode_add_ref(avctx, pic, ctx->next_prev[i],
1237 pic->type == PICTURE_TYPE_P,
1238 b_counter > 0, 0);
1239 } else
1240 vaapi_encode_add_ref(avctx, pic, start,
1241 pic->type == PICTURE_TYPE_P,
1242 b_counter > 0, 0);
1243
1134 vaapi_encode_add_ref(avctx, pic, ctx->next_prev[ctx->nb_next_prev - 1], 0, 0, 1);1244 vaapi_encode_add_ref(avctx, pic, ctx->next_prev[ctx->nb_next_prev - 1], 0, 0, 1);
1135 }1245 }
1136 1246
@@ -1292,6 +1402,19 @@ int ff_vaapi_encode_receive_packet(AVCodecContext *avctx, AVPacket *pkt) · 155 unmodified lines
1292 AVFrame *frame = ctx->frame;1402 AVFrame *frame = ctx->frame;
1293 int err;1403 int err;
1294 1404
1405start:
1406 /** if no B frame before repeat P frame, sent repeat P frame out. */
1407 if (ctx->tail_pkt->size) {
1408 for (VAAPIEncodePicture *tmp = ctx->pic_start; tmp; tmp = tmp->next) {
1409 if (tmp->type == PICTURE_TYPE_B && tmp->pts < ctx->tail_pkt->pts)
1410 break;
1411 else if (!tmp->next) {
1412 av_packet_move_ref(pkt, ctx->tail_pkt);
1413 goto end;
1414 }
1415 }
1416 }
1417
1295 err = ff_encode_get_frame(avctx, frame);1418 err = ff_encode_get_frame(avctx, frame);
1296 if (err < 0 && err != AVERROR_EOF)1419 if (err < 0 && err != AVERROR_EOF)
1297 return err;1420 return err;
@@ -1356,17 +1479,21 @@ int ff_vaapi_encode_receive_packet(AVCodecContext *avctx, AVPacket *pkt) · 58 unmodified lines
1356 return err;1479 return err;
1357 }1480 }
1358 1481
1359 vaapi_encode_set_output_property(avctx, pic, pkt);
1360 av_log(avctx, AV_LOG_DEBUG, "Output packet: pts %"PRId64", dts %"PRId64", "
1361 "size %d bytes.\n", pkt->pts, pkt->dts, pkt->size);
1362
1363 ctx->output_order = pic->encode_order;1482 ctx->output_order = pic->encode_order;
1364 vaapi_encode_clear_old(avctx);1483 vaapi_encode_clear_old(avctx);
1365 1484
1485 /** loop to get an available pkt in encoder flushing. */
1486 if (ctx->end_of_stream && !pkt->size)
1487 goto start;
1488
1489end:
1490 if (pkt->size)
1491 av_log(avctx, AV_LOG_DEBUG, "Output packet: pts %"PRId64", dts %"PRId64", "
1492 "size %d bytes.\n", pkt->pts, pkt->dts, pkt->size);
1493
1366 return 0;1494 return 0;
1367}1495}
1368 1496
1369
1370static av_cold void vaapi_encode_add_global_param(AVCodecContext *avctx, int type,1497static av_cold void vaapi_encode_add_global_param(AVCodecContext *avctx, int type,
1371 void *buffer, size_t size)1498 void *buffer, size_t size)
1372{1499{
@@ -2667,6 +2794,12 @@ av_cold int ff_vaapi_encode_init(AVCodecContext *avctx) · 1294 unmodified lines
2667 ctx->device = (AVHWDeviceContext*)ctx->device_ref->data;2794 ctx->device = (AVHWDeviceContext*)ctx->device_ref->data;
2668 ctx->hwctx = ctx->device->hwctx;2795 ctx->hwctx = ctx->device->hwctx;
2669 2796
2797 ctx->tail_pkt = av_packet_alloc();
2798 if (!ctx->tail_pkt) {
2799 err = AVERROR(ENOMEM);
2800 goto fail;
2801 }
2802
2670 err = vaapi_encode_profile_entrypoint(avctx);2803 err = vaapi_encode_profile_entrypoint(avctx);
2671 if (err < 0)2804 if (err < 0)
2672 goto fail;2805 goto fail;
@@ -2859,6 +2992,7 @@ av_cold int ff_vaapi_encode_close(AVCodecContext *avctx) · 186 unmodified lines
2859 }2992 }
2860 2993
2861 av_frame_free(&ctx->frame);2994 av_frame_free(&ctx->frame);
2995 av_packet_free(&ctx->tail_pkt);
2862 2996
2863 av_freep(&ctx->codec_sequence_params);2997 av_freep(&ctx->codec_sequence_params);
2864 av_freep(&ctx->codec_picture_params);2998 av_freep(&ctx->codec_picture_params);
libavcodec/vaapi_encode.h+24−0
@@ -133,6 +133,17 @@ typedef struct VAAPIEncodePicture { · 132 unmodified lines
133 133
134 int nb_slices;134 int nb_slices;
135 VAAPIEncodeSlice *slices;135 VAAPIEncodeSlice *slices;
136
137 /**
138 * indicate if current frame is an independent frame that the coded data
139 * can be pushed to downstream directly. Coded of non-independent frame
140 * data will be concatenated into next independent frame.
141 */
142 int non_independent_frame;
143 /** Tail data of current pic, used only for repeat header of AV1. */
144 char tail_data[MAX_PARAM_BUFFER_SIZE];
145 /** Byte length of tail_data. */
146 size_t tail_size;
136} VAAPIEncodePicture;147} VAAPIEncodePicture;
137 148
138typedef struct VAAPIEncodeProfile {149typedef struct VAAPIEncodeProfile {
@@ -367,6 +378,16 @@ typedef struct VAAPIEncodeContext { · 228 unmodified lines
367 AVFifo *encode_fifo;378 AVFifo *encode_fifo;
368 // Max number of frame buffered in encoder.379 // Max number of frame buffered in encoder.
369 int async_depth;380 int async_depth;
381
382 /** Head data for current output pkt, used only for AV1. */
383 //void *header_data;
384 //size_t header_data_size;
385
386 /** Buffered coded data of a pic if it is an non-independent frame. */
387 AVBufferRef *coded_buffer_ref;
388
389 /** Tail data of a pic, now only used for av1 repeat frame header. */
390 AVPacket *tail_pkt;
370} VAAPIEncodeContext;391} VAAPIEncodeContext;
371 392
372enum {393enum {
@@ -383,6 +404,9 @@ enum { · 10 unmodified lines
383 // Codec supports non-IDR key pictures (that is, key pictures do404 // Codec supports non-IDR key pictures (that is, key pictures do
384 // not necessarily empty the DPB).405 // not necessarily empty the DPB).
385 FLAG_NON_IDR_KEY_PICTURES = 1 << 5,406 FLAG_NON_IDR_KEY_PICTURES = 1 << 5,
407 // Codec output packet without timestamp delay, which means the
408 // output packet has same PTS and DTS.
409 FLAG_TIMESTAMP_NO_DELAY = 1 << 6,
386};410};
387 411
388typedef struct VAAPIEncodeType {412typedef struct VAAPIEncodeType {
libavcodec/vaapi_encode_av1.c+949−0
@@ -0,0 +1,949 @@
1/*
2 * Copyright (c) 2023 Intel Corporation
3 *
4 * This file is part of FFmpeg.
5 *
6 * FFmpeg is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * FFmpeg is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with FFmpeg; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21#include <va/va.h>
22#include <va/va_enc_av1.h>
23
24#include "libavutil/pixdesc.h"
25#include "libavutil/opt.h"
26
27#include "cbs_av1.h"
28#include "put_bits.h"
29#include "codec_internal.h"
30#include "av1_levels.h"
31#include "vaapi_encode.h"
32
33#define AV1_MAX_QUANT 255
34
35typedef struct VAAPIEncodeAV1Picture {
36 int64_t last_idr_frame;
37 int slot;
38} VAAPIEncodeAV1Picture;
39
40typedef struct VAAPIEncodeAV1Context {
41 VAAPIEncodeContext common;
42 AV1RawOBU sh; /**< sequence header.*/
43 AV1RawOBU fh; /**< frame header.*/
44 CodedBitstreamContext *cbc;
45 CodedBitstreamFragment current_obu;
46 VAConfigAttribValEncAV1 attr;
47 VAConfigAttribValEncAV1Ext1 attr_ext1;
48 VAConfigAttribValEncAV1Ext2 attr_ext2;
49
50 char sh_data[MAX_PARAM_BUFFER_SIZE]; /**< coded sequence header data. */
51 size_t sh_data_len; /**< bit length of sh_data. */
52 char fh_data[MAX_PARAM_BUFFER_SIZE]; /**< coded frame header data. */
53 size_t fh_data_len; /**< bit length of fh_data. */
54
55 uint8_t uniform_tile;
56 uint8_t use_128x128_superblock;
57 int sb_cols;
58 int sb_rows;
59 int tile_cols_log2;
60 int tile_rows_log2;
61 int max_tile_width_sb;
62 int max_tile_height_sb;
63 uint8_t width_in_sbs_minus_1[AV1_MAX_TILE_COLS];
64 uint8_t height_in_sbs_minus_1[AV1_MAX_TILE_ROWS];
65
66 int min_log2_tile_cols;
67 int max_log2_tile_cols;
68 int min_log2_tile_rows;
69 int max_log2_tile_rows;
70
71 int q_idx_idr;
72 int q_idx_p;
73 int q_idx_b;
74
75 /** bit positions in current frame header */
76 int qindex_offset;
77 int loopfilter_offset;
78 int cdef_start_offset;
79 int cdef_param_size;
80
81 /** user options */
82 int profile;
83 int level;
84 int tier;
85 int tile_cols, tile_rows;
86 int tile_groups;
87} VAAPIEncodeAV1Context;
88
89static void vaapi_encode_av1_trace_write_log(void *ctx,
90 PutBitContext *pbc, int length,
91 const char *str, const int *subscripts,
92 int64_t value)
93{
94 VAAPIEncodeAV1Context *priv = ctx;
95 int position;
96
97 position = put_bits_count(pbc);
98 av_assert0(position >= length);
99
100 if (!strcmp(str, "base_q_idx"))
101 priv->qindex_offset = position - length;
102 else if (!strcmp(str, "loop_filter_level[0]"))
103 priv->loopfilter_offset = position - length;
104 else if (!strcmp(str, "cdef_damping_minus_3"))
105 priv->cdef_start_offset = position - length;
106 else if (!strcmp(str, "cdef_uv_sec_strength[i]"))
107 priv->cdef_param_size = position - priv->cdef_start_offset;
108}
109
110static av_cold int vaapi_encode_av1_get_encoder_caps(AVCodecContext *avctx)
111{
112 VAAPIEncodeContext *ctx = avctx->priv_data;
113 VAAPIEncodeAV1Context *priv = avctx->priv_data;
114
115 // Surfaces must be aligned to superblock boundaries.
116 ctx->surface_width = FFALIGN(avctx->width, priv->use_128x128_superblock ? 128 : 64);
117 ctx->surface_height = FFALIGN(avctx->height, priv->use_128x128_superblock ? 128 : 64);
118
119 return 0;
120}
121
122static av_cold int vaapi_encode_av1_configure(AVCodecContext *avctx)
123{
124 VAAPIEncodeContext *ctx = avctx->priv_data;
125 VAAPIEncodeAV1Context *priv = avctx->priv_data;
126 int ret;
127
128 ret = ff_cbs_init(&priv->cbc, AV_CODEC_ID_AV1, avctx);
129 if (ret < 0)
130 return ret;
131 priv->cbc->trace_enable = 1;
132 priv->cbc->trace_level = AV_LOG_DEBUG;
133 priv->cbc->trace_context = ctx;
134 priv->cbc->trace_write_callback = vaapi_encode_av1_trace_write_log;
135
136 if (ctx->rc_mode->quality) {
137 priv->q_idx_p = av_clip(ctx->rc_quality, 0, AV1_MAX_QUANT);
138 if (fabs(avctx->i_quant_factor) > 0.0)
139 priv->q_idx_idr =
140 av_clip((fabs(avctx->i_quant_factor) * priv->q_idx_p +
141 avctx->i_quant_offset) + 0.5,
142 0, AV1_MAX_QUANT);
143 else
144 priv->q_idx_idr = priv->q_idx_p;
145
146 if (fabs(avctx->b_quant_factor) > 0.0)
147 priv->q_idx_b =
148 av_clip((fabs(avctx->b_quant_factor) * priv->q_idx_p +
149 avctx->b_quant_offset) + 0.5,
150 0, AV1_MAX_QUANT);
151 else
152 priv->q_idx_b = priv->q_idx_p;
153 } else {
154 /** Arbitrary value */
155 priv->q_idx_idr = priv->q_idx_p = priv->q_idx_b = 128;
156 }
157
158 return 0;
159}
160
161static int vaapi_encode_av1_add_obu(AVCodecContext *avctx,
162 CodedBitstreamFragment *au,
163 uint8_t type,
164 void *obu_unit)
165{
166 int ret;
167
168 ret = ff_cbs_insert_unit_content(au, -1,
169 type, obu_unit, NULL);
170 if (ret < 0) {
171 av_log(avctx, AV_LOG_ERROR, "Failed to add OBU unit: "
172 "type = %d.\n", type);
173 return ret;
174 }
175
176 return 0;
177}
178
179static int vaapi_encode_av1_write_obu(AVCodecContext *avctx,
180 char *data, size_t *data_len,
181 CodedBitstreamFragment *bs)
182{
183 VAAPIEncodeAV1Context *priv = avctx->priv_data;
184 int ret;
185
186 ret = ff_cbs_write_fragment_data(priv->cbc, bs);
187 if (ret < 0) {
188 av_log(avctx, AV_LOG_ERROR, "Failed to write packed header.\n");
189 return ret;
190 }
191
192 if ((size_t)8 * MAX_PARAM_BUFFER_SIZE < 8 * bs->data_size - bs->data_bit_padding) {
193 av_log(avctx, AV_LOG_ERROR, "Access unit too large: "
194 "%zu < %zu.\n", (size_t)8 * MAX_PARAM_BUFFER_SIZE,
195 8 * bs->data_size - bs->data_bit_padding);
196 return AVERROR(ENOSPC);
197 }
198
199 memcpy(data, bs->data, bs->data_size);
200 *data_len = 8 * bs->data_size - bs->data_bit_padding;
201
202 return 0;
203}
204
205static int tile_log2(int blkSize, int target) {
206 int k;
207 for (k = 0; (blkSize << k) < target; k++);
208 return k;
209}
210
211static int vaapi_encode_av1_set_tile(AVCodecContext *avctx)
212{
213 VAAPIEncodeAV1Context *priv = avctx->priv_data;
214 int mi_cols, mi_rows, sb_shift, sb_size;
215 int max_tile_area_sb, max_tile_area_sb_varied;
216 int tile_width_sb, tile_height_sb, widest_tile_sb;
217 int tile_cols, tile_rows;
218 int min_log2_tiles;
219 int i;
220
221 if (priv->tile_cols > AV1_MAX_TILE_COLS ||
222 priv->tile_rows > AV1_MAX_TILE_ROWS) {
223 av_log(avctx, AV_LOG_ERROR, "Invalid tile number %dx%d, should less than %dx%d.\n",
224 priv->tile_cols, priv->tile_rows, AV1_MAX_TILE_COLS, AV1_MAX_TILE_ROWS);
225 return AVERROR(EINVAL);
226 }
227
228 mi_cols = 2 * ((avctx->width + 7) >> 3);
229 mi_rows = 2 * ((avctx->height + 7) >> 3);
230 priv->sb_cols = priv->use_128x128_superblock ?
231 ((mi_cols + 31) >> 5) : ((mi_cols + 15) >> 4);
232 priv->sb_rows = priv->use_128x128_superblock ?
233 ((mi_rows + 31) >> 5) : ((mi_rows + 15) >> 4);
234 sb_shift = priv->use_128x128_superblock ? 5 : 4;
235 sb_size = sb_shift + 2;
236 priv->max_tile_width_sb = AV1_MAX_TILE_WIDTH >> sb_size;
237 max_tile_area_sb = AV1_MAX_TILE_AREA >> (2 * sb_size);
238
239 priv->min_log2_tile_cols = tile_log2(priv->max_tile_width_sb, priv->sb_cols);
240 priv->max_log2_tile_cols = tile_log2(1, FFMIN(priv->sb_cols, AV1_MAX_TILE_COLS));
241 priv->max_log2_tile_rows = tile_log2(1, FFMIN(priv->sb_rows, AV1_MAX_TILE_ROWS));
242 min_log2_tiles = FFMAX(priv->min_log2_tile_cols,
243 tile_log2(max_tile_area_sb, priv->sb_rows * priv->sb_cols));
244
245 tile_cols = av_clip(priv->tile_cols, (priv->sb_cols + priv->max_tile_width_sb - 1) / priv->max_tile_width_sb, priv->sb_cols);
246
247 if (!priv->tile_cols)
248 priv->tile_cols = tile_cols;
249 else if (priv->tile_cols != tile_cols){
250 av_log(avctx, AV_LOG_ERROR, "Invalid tile cols %d, should be in range of %d~%d\n",
251 priv->tile_cols,
252 (priv->sb_cols + priv->max_tile_width_sb - 1) / priv->max_tile_width_sb,
253 priv->sb_cols);
254 return AVERROR(EINVAL);
255 }
256
257 priv->tile_cols_log2 = tile_log2(1, priv->tile_cols);
258 tile_width_sb = (priv->sb_cols + (1 << priv->tile_cols_log2) - 1) >>
259 priv->tile_cols_log2;
260
261 if (priv->tile_rows > priv->sb_rows) {
262 av_log(avctx, AV_LOG_ERROR, "Invalid tile rows %d, should be less than %d.\n",
263 priv->tile_rows, priv->sb_rows);
264 return AVERROR(EINVAL);
265 }
266
267 /** Try user setting tile rows number first. */
268 tile_rows = priv->tile_rows ? priv->tile_rows : 1;
269 for (; tile_rows <= priv->sb_rows && tile_rows <= AV1_MAX_TILE_ROWS; tile_rows++) {
270 /** try uniformed tile. */
271 priv->tile_rows_log2 = tile_log2(1, tile_rows);
272 if ((priv->sb_cols + tile_width_sb - 1) / tile_width_sb == priv->tile_cols) {
273 for (i = 0; i < priv->tile_cols - 1; i++)
274 priv->width_in_sbs_minus_1[i] = tile_width_sb - 1;
275 priv->width_in_sbs_minus_1[i] = priv->sb_cols - (priv->tile_cols - 1) * tile_width_sb - 1;
276
277 tile_height_sb = (priv->sb_rows + (1 << priv->tile_rows_log2) - 1) >>
278 priv->tile_rows_log2;
279
280 if ((priv->sb_rows + tile_height_sb - 1) / tile_height_sb == tile_rows &&
281 tile_height_sb <= max_tile_area_sb / tile_width_sb) {
282 for (i = 0; i < tile_rows - 1; i++)
283 priv->height_in_sbs_minus_1[i] = tile_height_sb - 1;
284 priv->height_in_sbs_minus_1[i] = priv->sb_rows - (tile_rows - 1) * tile_height_sb - 1;
285
286 priv->uniform_tile = 1;
287 priv->min_log2_tile_rows = FFMAX(min_log2_tiles - priv->tile_cols_log2, 0);
288
289 break;
290 }
291 }
292
293 /** try non-uniformed tile. */
294 widest_tile_sb = 0;
295 for (i = 0; i < priv->tile_cols; i++) {
296 priv->width_in_sbs_minus_1[i] = (i + 1) * priv->sb_cols / priv->tile_cols - i * priv->sb_cols / priv->tile_cols - 1;
297 widest_tile_sb = FFMAX(widest_tile_sb, priv->width_in_sbs_minus_1[i] + 1);
298 }
299
300 if (min_log2_tiles)
301 max_tile_area_sb_varied = (priv->sb_rows * priv->sb_cols) >> (min_log2_tiles + 1);
302 else
303 max_tile_area_sb_varied = priv->sb_rows * priv->sb_cols;
304 priv->max_tile_height_sb = FFMAX(1, max_tile_area_sb_varied / widest_tile_sb);
305
306 if (tile_rows == av_clip(tile_rows, (priv->sb_rows + priv->max_tile_height_sb - 1) / priv->max_tile_height_sb, priv->sb_rows)) {
307 for (i = 0; i < tile_rows; i++)
308 priv->height_in_sbs_minus_1[i] = (i + 1) * priv->sb_rows / tile_rows - i * priv->sb_rows / tile_rows - 1;
309
310 break;
311 }
312
313 /** Return invalid parameter if explicit tile rows is set. */
314 if (priv->tile_rows) {
315 av_log(avctx, AV_LOG_ERROR, "Invalid tile rows %d.\n", priv->tile_rows);
316 return AVERROR(EINVAL);
317 }
318 }
319
320 priv->tile_rows = tile_rows;
321 av_log(avctx, AV_LOG_DEBUG, "Setting tile cols/rows to %d/%d.\n",
322 priv->tile_cols, priv->tile_rows);
323
324 /** check if tile cols/rows is supported by driver. */
325 if (priv->attr_ext2.bits.max_tile_num_minus1) {
326 if ((priv->tile_cols * priv->tile_rows - 1) > priv->attr_ext2.bits.max_tile_num_minus1) {
327 av_log(avctx, AV_LOG_ERROR, "Unsupported tile num %d * %d = %d by driver, "
328 "should be at most %d.\n", priv->tile_cols, priv->tile_rows,
329 priv->tile_cols * priv->tile_rows,
330 priv->attr_ext2.bits.max_tile_num_minus1 + 1);
331 return AVERROR(EINVAL);
332 }
333 }
334
335 /** check if tile group numbers is valid. */
336 if (priv->tile_groups > priv->tile_cols * priv->tile_rows) {
337 av_log(avctx, AV_LOG_WARNING, "Invalid tile groups number %d, "
338 "correct to %d.\n", priv->tile_groups, priv->tile_cols * priv->tile_rows);
339 priv->tile_groups = priv->tile_cols * priv->tile_rows;
340 }
341
342 return 0;
343}
344
345static int vaapi_encode_av1_write_sequence_header(AVCodecContext *avctx,
346 char *data, size_t *data_len)
347{
348 VAAPIEncodeAV1Context *priv = avctx->priv_data;
349
350 memcpy(data, &priv->sh_data, MAX_PARAM_BUFFER_SIZE * sizeof(char));
351 *data_len = priv->sh_data_len;
352
353 return 0;
354}
355
356static int vaapi_encode_av1_init_sequence_params(AVCodecContext *avctx)
357{
358 VAAPIEncodeContext *ctx = avctx->priv_data;
359 VAAPIEncodeAV1Context *priv = avctx->priv_data;
360 AV1RawOBU *sh_obu = &priv->sh;
361 AV1RawSequenceHeader *sh = &sh_obu->obu.sequence_header;
362 VAEncSequenceParameterBufferAV1 *vseq = ctx->codec_sequence_params;
363 CodedBitstreamFragment *obu = &priv->current_obu;
364 const AVPixFmtDescriptor *desc;
365 int ret;
366
367 memset(sh_obu, 0, sizeof(*sh_obu));
368 sh_obu->header.obu_type = AV1_OBU_SEQUENCE_HEADER;
369
370 desc = av_pix_fmt_desc_get(priv->common.input_frames->sw_format);
371 av_assert0(desc);
372
373 sh->seq_profile = avctx->profile;
374 if (!sh->seq_force_screen_content_tools)
375 sh->seq_force_integer_mv = AV1_SELECT_INTEGER_MV;
376 sh->frame_width_bits_minus_1 = av_log2(avctx->width);
377 sh->frame_height_bits_minus_1 = av_log2(avctx->height);
378 sh->max_frame_width_minus_1 = avctx->width - 1;
379 sh->max_frame_height_minus_1 = avctx->height - 1;
380 sh->seq_tier[0] = priv->tier;
381 /** enable order hint and reserve maximum 8 bits for it by default. */
382 sh->enable_order_hint = 1;
383 sh->order_hint_bits_minus_1 = 7;
384
385 sh->color_config = (AV1RawColorConfig) {
386 .high_bitdepth = desc->comp[0].depth == 8 ? 0 : 1,
387 .color_primaries = avctx->color_primaries,
388 .transfer_characteristics = avctx->color_trc,
389 .matrix_coefficients = avctx->colorspace,
390 .color_description_present_flag = (avctx->color_primaries != AVCOL_PRI_UNSPECIFIED ||
391 avctx->color_trc != AVCOL_TRC_UNSPECIFIED ||
392 avctx->colorspace != AVCOL_SPC_UNSPECIFIED),
393 .color_range = avctx->color_range == AVCOL_RANGE_JPEG,
394 .subsampling_x = desc->log2_chroma_w,
395 .subsampling_y = desc->log2_chroma_h,
396 };
397
398 switch (avctx->chroma_sample_location) {
399 case AVCHROMA_LOC_LEFT:
400 sh->color_config.chroma_sample_position = AV1_CSP_VERTICAL;
401 break;
402 case AVCHROMA_LOC_TOPLEFT:
403 sh->color_config.chroma_sample_position = AV1_CSP_COLOCATED;
404 break;
405 default:
406 sh->color_config.chroma_sample_position = AV1_CSP_UNKNOWN;
407 break;
408 }
409
410 if (avctx->level != AV_LEVEL_UNKNOWN) {
411 sh->seq_level_idx[0] = avctx->level;
412 } else {
413 const AV1LevelDescriptor *level;
414 float framerate;
415
416 if (avctx->framerate.num > 0 && avctx->framerate.den > 0)
417 framerate = avctx->framerate.num / avctx->framerate.den;
418 else
419 framerate = 0;
420
421 level = ff_av1_guess_level(avctx->bit_rate, priv->tier,
422 ctx->surface_width, ctx->surface_height,
423 priv->tile_rows * priv->tile_cols,
424 priv->tile_cols, framerate);
425 if (level) {
426 av_log(avctx, AV_LOG_VERBOSE, "Using level %s.\n", level->name);
427 sh->seq_level_idx[0] = level->level_idx;
428 } else {
429 av_log(avctx, AV_LOG_VERBOSE, "Stream will not conform to "
430 "any normal level, using maximum parameters level by default.\n");
431 sh->seq_level_idx[0] = 31;
432 sh->seq_tier[0] = 1;
433 }
434 }
435 vseq->seq_profile = sh->seq_profile;
436 vseq->seq_level_idx = sh->seq_level_idx[0];
437 vseq->seq_tier = sh->seq_tier[0];
438 vseq->order_hint_bits_minus_1 = sh->order_hint_bits_minus_1;
439 vseq->intra_period = ctx->gop_size;
440 vseq->ip_period = ctx->b_per_p + 1;
441
442 vseq->seq_fields.bits.enable_order_hint = sh->enable_order_hint;
443
444 if (!(ctx->va_rc_mode & VA_RC_CQP)) {
445 vseq->bits_per_second = ctx->va_bit_rate;
446 vseq->seq_fields.bits.enable_cdef = sh->enable_cdef = 1;
447 }
448
449 ret = vaapi_encode_av1_add_obu(avctx, obu, AV1_OBU_SEQUENCE_HEADER, &priv->sh);
450 if (ret < 0)
451 goto end;
452
453 ret = vaapi_encode_av1_write_obu(avctx, priv->sh_data, &priv->sh_data_len, obu);
454 if (ret < 0)
455 goto end;
456
457end:
458 ff_cbs_fragment_reset(obu);
459 return ret;
460}
461
462static int vaapi_encode_av1_init_picture_params(AVCodecContext *avctx,
463 VAAPIEncodePicture *pic)
464{
465 VAAPIEncodeContext *ctx = avctx->priv_data;
466 VAAPIEncodeAV1Context *priv = avctx->priv_data;
467 VAAPIEncodeAV1Picture *hpic = pic->priv_data;
468 AV1RawOBU *fh_obu = &priv->fh;
469 AV1RawFrameHeader *fh = &fh_obu->obu.frame.header;
470 VAEncPictureParameterBufferAV1 *vpic = pic->codec_picture_params;
471 CodedBitstreamFragment *obu = &priv->current_obu;
472 VAAPIEncodePicture *ref;
473 VAAPIEncodeAV1Picture *href;
474 int slot, i;
475 int ret;
476 static const int8_t default_loop_filter_ref_deltas[AV1_TOTAL_REFS_PER_FRAME] =
477 { 1, 0, 0, 0, -1, 0, -1, -1 };
478
479 memset(fh_obu, 0, sizeof(*fh_obu));
480 pic->nb_slices = priv->tile_groups;
481 pic->non_independent_frame = pic->encode_order < pic->display_order;
482 fh_obu->header.obu_type = AV1_OBU_FRAME_HEADER;
483 fh_obu->header.obu_has_size_field = 1;
484
485 switch (pic->type) {
486 case PICTURE_TYPE_IDR:
487 av_assert0(pic->nb_refs[0] == 0 || pic->nb_refs[1]);
488 fh->frame_type = AV1_FRAME_KEY;
489 fh->refresh_frame_flags = 0xFF;
490 fh->base_q_idx = priv->q_idx_idr;
491 hpic->slot = 0;
492 hpic->last_idr_frame = pic->display_order;
493 break;
494 case PICTURE_TYPE_P:
495 av_assert0(pic->nb_refs[0]);
496 fh->frame_type = AV1_FRAME_INTER;
497 fh->base_q_idx = priv->q_idx_p;
498 ref = pic->refs[0][pic->nb_refs[0] - 1];
499 href = ref->priv_data;
500 hpic->slot = !href->slot;
501 hpic->last_idr_frame = href->last_idr_frame;
502 fh->refresh_frame_flags = 1 << hpic->slot;
503
504 /** set the nearest frame in L0 as all reference frame. */
505 for (i = 0; i < AV1_REFS_PER_FRAME; i++) {
506 fh->ref_frame_idx[i] = href->slot;
507 }
508 fh->primary_ref_frame = href->slot;
509 fh->ref_order_hint[href->slot] = ref->display_order - href->last_idr_frame;
510 vpic->ref_frame_ctrl_l0.fields.search_idx0 = AV1_REF_FRAME_LAST;
511
512 /** set the 2nd nearest frame in L0 as Golden frame. */
513 if (pic->nb_refs[0] > 1) {
514 ref = pic->refs[0][pic->nb_refs[0] - 2];
515 href = ref->priv_data;
516 fh->ref_frame_idx[3] = href->slot;
517 fh->ref_order_hint[href->slot] = ref->display_order - href->last_idr_frame;
518 vpic->ref_frame_ctrl_l0.fields.search_idx1 = AV1_REF_FRAME_GOLDEN;
519 }
520 break;
521 case PICTURE_TYPE_B:
522 av_assert0(pic->nb_refs[0] && pic->nb_refs[1]);
523 fh->frame_type = AV1_FRAME_INTER;
524 fh->base_q_idx = priv->q_idx_b;
525 fh->refresh_frame_flags = 0x0;
526 fh->reference_select = 1;
527
528 /** B frame will not be referenced, disable its recon frame. */
529 vpic->picture_flags.bits.disable_frame_recon = 1;
530
531 /** Use LAST_FRAME and BWDREF_FRAME for reference. */
532 vpic->ref_frame_ctrl_l0.fields.search_idx0 = AV1_REF_FRAME_LAST;
533 vpic->ref_frame_ctrl_l1.fields.search_idx0 = AV1_REF_FRAME_BWDREF;
534
535 ref = pic->refs[0][pic->nb_refs[0] - 1];
536 href = ref->priv_data;
537 hpic->last_idr_frame = href->last_idr_frame;
538 fh->primary_ref_frame = href->slot;
539 fh->ref_order_hint[href->slot] = ref->display_order - href->last_idr_frame;
540 for (i = 0; i < AV1_REF_FRAME_GOLDEN; i++) {
541 fh->ref_frame_idx[i] = href->slot;
542 }
543
544 ref = pic->refs[1][pic->nb_refs[1] - 1];
545 href = ref->priv_data;
546 fh->ref_order_hint[href->slot] = ref->display_order - href->last_idr_frame;
547 for (i = AV1_REF_FRAME_GOLDEN; i < AV1_REFS_PER_FRAME; i++) {
548 fh->ref_frame_idx[i] = href->slot;
549 }
550 break;
551 default:
552 av_assert0(0 && "invalid picture type");
553 }
554
555 fh->show_frame = pic->display_order <= pic->encode_order;
556 fh->showable_frame = fh->frame_type != AV1_FRAME_KEY;
557 fh->frame_width_minus_1 = avctx->width - 1;
558 fh->frame_height_minus_1 = avctx->height - 1;
559 fh->render_width_minus_1 = fh->frame_width_minus_1;
560 fh->render_height_minus_1 = fh->frame_height_minus_1;
561 fh->order_hint = pic->display_order - hpic->last_idr_frame;
562 fh->tile_cols = priv->tile_cols;
563 fh->tile_rows = priv->tile_rows;
564 fh->tile_cols_log2 = priv->tile_cols_log2;
565 fh->tile_rows_log2 = priv->tile_rows_log2;
566 fh->uniform_tile_spacing_flag = priv->uniform_tile;
567 fh->tile_size_bytes_minus1 = priv->attr_ext2.bits.tile_size_bytes_minus1;
568
569 /** ignore ONLY_4x4 mode for codedlossless is not fully implemented. */
570 if (priv->attr_ext2.bits.tx_mode_support & 0x04)
571 fh->tx_mode = AV1_TX_MODE_SELECT;
572 else if (priv->attr_ext2.bits.tx_mode_support & 0x02)
573 fh->tx_mode = AV1_TX_MODE_LARGEST;
574 else {
575 av_log(avctx, AV_LOG_ERROR, "No available tx mode found.\n");
576 return AVERROR(EINVAL);
577 }
578
579 for (i = 0; i < fh->tile_cols; i++)
580 fh->width_in_sbs_minus_1[i] = vpic->width_in_sbs_minus_1[i] = priv->width_in_sbs_minus_1[i];
581
582 for (i = 0; i < fh->tile_rows; i++)
583 fh->height_in_sbs_minus_1[i] = vpic->height_in_sbs_minus_1[i] = priv->height_in_sbs_minus_1[i];
584
585 memcpy(fh->loop_filter_ref_deltas, default_loop_filter_ref_deltas,
586 AV1_TOTAL_REFS_PER_FRAME * sizeof(int8_t));
587
588 if (fh->frame_type == AV1_FRAME_KEY && fh->show_frame) {
589 fh->error_resilient_mode = 1;
590 }
591
592 if (fh->frame_type == AV1_FRAME_KEY || fh->error_resilient_mode)
593 fh->primary_ref_frame = AV1_PRIMARY_REF_NONE;
594
595 vpic->base_qindex = fh->base_q_idx;
596 vpic->frame_width_minus_1 = fh->frame_width_minus_1;
597 vpic->frame_height_minus_1 = fh->frame_height_minus_1;
598 vpic->primary_ref_frame = fh->primary_ref_frame;
599 vpic->reconstructed_frame = pic->recon_surface;
600 vpic->coded_buf = pic->output_buffer;
601 vpic->tile_cols = fh->tile_cols;
602 vpic->tile_rows = fh->tile_rows;
603 vpic->order_hint = fh->order_hint;
604#if VA_CHECK_VERSION(1, 15, 0)
605 vpic->refresh_frame_flags = fh->refresh_frame_flags;
606#endif
607
608 vpic->picture_flags.bits.enable_frame_obu = 0;
609 vpic->picture_flags.bits.frame_type = fh->frame_type;
610 vpic->picture_flags.bits.reduced_tx_set = fh->reduced_tx_set;
611 vpic->picture_flags.bits.error_resilient_mode = fh->error_resilient_mode;
612
613 /** let driver decide to use single or compound reference prediction mode. */
614 vpic->mode_control_flags.bits.reference_mode = fh->reference_select ? 2 : 0;
615 vpic->mode_control_flags.bits.tx_mode = fh->tx_mode;
616
617 vpic->tile_group_obu_hdr_info.bits.obu_has_size_field = 1;
618
619 /** set reference. */
620 for (i = 0; i < AV1_REFS_PER_FRAME; i++)
621 vpic->ref_frame_idx[i] = fh->ref_frame_idx[i];
622
623 for (i = 0; i < FF_ARRAY_ELEMS(vpic->reference_frames); i++)
624 vpic->reference_frames[i] = VA_INVALID_SURFACE;
625
626 for (i = 0; i < MAX_REFERENCE_LIST_NUM; i++) {
627 for (int j = 0; j < pic->nb_refs[i]; j++) {
628 VAAPIEncodePicture *ref_pic = pic->refs[i][j];
629
630 slot = ((VAAPIEncodeAV1Picture*)ref_pic->priv_data)->slot;
631 av_assert0(vpic->reference_frames[slot] == VA_INVALID_SURFACE);
632
633 vpic->reference_frames[slot] = ref_pic->recon_surface;
634 }
635 }
636
637 fh_obu->obu_size_byte_len = priv->attr_ext2.bits.obu_size_bytes_minus1 + 1;
638 ret = vaapi_encode_av1_add_obu(avctx, obu, AV1_OBU_FRAME_HEADER, &priv->fh);
639 if (ret < 0)
640 goto end;
641
642 ret = vaapi_encode_av1_write_obu(avctx, priv->fh_data, &priv->fh_data_len, obu);
643 if (ret < 0)
644 goto end;
645
646 if (!(ctx->va_rc_mode & VA_RC_CQP)) {
647 vpic->min_base_qindex = av_clip(avctx->qmin, 1, AV1_MAX_QUANT);
648 vpic->max_base_qindex = av_clip(avctx->qmax, 1, AV1_MAX_QUANT);
649
650 vpic->bit_offset_qindex = priv->qindex_offset;
651 vpic->bit_offset_loopfilter_params = priv->loopfilter_offset;
652 vpic->bit_offset_cdef_params = priv->cdef_start_offset;
653 vpic->size_in_bits_cdef_params = priv->cdef_param_size;
654 vpic->size_in_bits_frame_hdr_obu = priv->fh_data_len;
655 vpic->byte_offset_frame_hdr_obu_size = (((pic->type == PICTURE_TYPE_IDR) ?
656 priv->sh_data_len / 8 : 0) +
657 (fh_obu->header.obu_extension_flag ?
658 2 : 1));
659 }
660
661end:
662 ff_cbs_fragment_reset(obu);
663 return ret;
664}
665
666static int vaapi_encode_av1_init_slice_params(AVCodecContext *avctx,
667 VAAPIEncodePicture *pic,
668 VAAPIEncodeSlice *slice)
669{
670 VAAPIEncodeAV1Context *priv = avctx->priv_data;
671 VAEncTileGroupBufferAV1 *vslice = slice->codec_slice_params;
672 CodedBitstreamAV1Context *cbctx = priv->cbc->priv_data;
673 int div;
674
675 /** Set tile group info. */
676 div = priv->tile_cols * priv->tile_rows / priv->tile_groups;
677 vslice->tg_start = slice->index * div;
678 if (slice->index == (priv->tile_groups - 1)) {
679 vslice->tg_end = priv->tile_cols * priv->tile_rows - 1;
680 cbctx->seen_frame_header = 0;
681 } else {
682 vslice->tg_end = (slice->index + 1) * div - 1;
683 }
684
685 return 0;
686}
687
688static int vaapi_encode_av1_write_picture_header(AVCodecContext *avctx,
689 VAAPIEncodePicture *pic,
690 char *data, size_t *data_len)
691{
692 VAAPIEncodeAV1Context *priv = avctx->priv_data;
693 CodedBitstreamFragment *obu = &priv->current_obu;
694 CodedBitstreamAV1Context *cbctx = priv->cbc->priv_data;
695 AV1RawOBU *fh_obu = &priv->fh;
696 AV1RawFrameHeader *rep_fh = &fh_obu->obu.frame_header;
697 VAAPIEncodeAV1Picture *href;
698 int ret = 0;
699
700 pic->tail_size = 0;
701 /** Pack repeat frame header. */
702 if (pic->display_order > pic->encode_order) {
703 memset(fh_obu, 0, sizeof(*fh_obu));
704 href = pic->refs[0][pic->nb_refs[0] - 1]->priv_data;
705 fh_obu->header.obu_type = AV1_OBU_FRAME_HEADER;
706 fh_obu->header.obu_has_size_field = 1;
707
708 rep_fh->show_existing_frame = 1;
709 rep_fh->frame_to_show_map_idx = href->slot == 0;
710 rep_fh->frame_type = AV1_FRAME_INTER;
711 rep_fh->frame_width_minus_1 = avctx->width - 1;
712 rep_fh->frame_height_minus_1 = avctx->height - 1;
713 rep_fh->render_width_minus_1 = rep_fh->frame_width_minus_1;
714 rep_fh->render_height_minus_1 = rep_fh->frame_height_minus_1;
715
716 cbctx->seen_frame_header = 0;
717
718 ret = vaapi_encode_av1_add_obu(avctx, obu, AV1_OBU_FRAME_HEADER, &priv->fh);
719 if (ret < 0)
720 goto end;
721
722 ret = vaapi_encode_av1_write_obu(avctx, pic->tail_data, &pic->tail_size, obu);
723 if (ret < 0)
724 goto end;
725
726 pic->tail_size /= 8;
727 }
728
729 memcpy(data, &priv->fh_data, MAX_PARAM_BUFFER_SIZE * sizeof(char));
730 *data_len = priv->fh_data_len;
731
732end:
733 ff_cbs_fragment_reset(obu);
734 return ret;
735}
736
737static const VAAPIEncodeProfile vaapi_encode_av1_profiles[] = {
738 { AV_PROFILE_AV1_MAIN, 8, 3, 1, 1, VAProfileAV1Profile0 },
739 { AV_PROFILE_AV1_MAIN, 10, 3, 1, 1, VAProfileAV1Profile0 },
740 { AV_PROFILE_UNKNOWN }
741};
742
743static const VAAPIEncodeType vaapi_encode_type_av1 = {
744 .profiles = vaapi_encode_av1_profiles,
745 .flags = FLAG_B_PICTURES | FLAG_TIMESTAMP_NO_DELAY,
746 .default_quality = 25,
747
748 .get_encoder_caps = &vaapi_encode_av1_get_encoder_caps,
749 .configure = &vaapi_encode_av1_configure,
750
751 .sequence_header_type = VAEncPackedHeaderSequence,
752 .sequence_params_size = sizeof(VAEncSequenceParameterBufferAV1),
753 .init_sequence_params = &vaapi_encode_av1_init_sequence_params,
754 .write_sequence_header = &vaapi_encode_av1_write_sequence_header,
755
756 .picture_priv_data_size = sizeof(VAAPIEncodeAV1Picture),
757 .picture_header_type = VAEncPackedHeaderPicture,
758 .picture_params_size = sizeof(VAEncPictureParameterBufferAV1),
759 .init_picture_params = &vaapi_encode_av1_init_picture_params,
760 .write_picture_header = &vaapi_encode_av1_write_picture_header,
761
762 .slice_params_size = sizeof(VAEncTileGroupBufferAV1),
763 .init_slice_params = &vaapi_encode_av1_init_slice_params,
764};
765
766static av_cold int vaapi_encode_av1_init(AVCodecContext *avctx)
767{
768 VAAPIEncodeContext *ctx = avctx->priv_data;
769 VAAPIEncodeAV1Context *priv = avctx->priv_data;
770 VAConfigAttrib attr;
771 VAStatus vas;
772 int ret;
773
774 ctx->codec = &vaapi_encode_type_av1;
775
776 ctx->desired_packed_headers =
777 VA_ENC_PACKED_HEADER_SEQUENCE |
778 VA_ENC_PACKED_HEADER_PICTURE;
779
780 if (avctx->profile == AV_PROFILE_UNKNOWN)
781 avctx->profile = priv->profile;
782 if (avctx->level == AV_LEVEL_UNKNOWN)
783 avctx->level = priv->level;
784
785 if (avctx->level != AV_LEVEL_UNKNOWN && avctx->level & ~0x1f) {
786 av_log(avctx, AV_LOG_ERROR, "Invalid level %d\n", avctx->level);
787 return AVERROR(EINVAL);
788 }
789
790 ret = ff_vaapi_encode_init(avctx);
791 if (ret < 0)
792 return ret;
793
794 attr.type = VAConfigAttribEncAV1;
795 vas = vaGetConfigAttributes(ctx->hwctx->display,
796 ctx->va_profile,
797 ctx->va_entrypoint,
798 &attr, 1);
799 if (vas != VA_STATUS_SUCCESS) {
800 av_log(avctx, AV_LOG_ERROR, "Failed to query "
801 "config attribute: %d (%s).\n", vas, vaErrorStr(vas));
802 return AVERROR_EXTERNAL;
803 } else if (attr.value == VA_ATTRIB_NOT_SUPPORTED) {
804 priv->attr.value = 0;
805 av_log(avctx, AV_LOG_WARNING, "Attribute type:%d is not "
806 "supported.\n", attr.type);
807 } else {
808 priv->attr.value = attr.value;
809 }
810
811 attr.type = VAConfigAttribEncAV1Ext1;
812 vas = vaGetConfigAttributes(ctx->hwctx->display,
813 ctx->va_profile,
814 ctx->va_entrypoint,
815 &attr, 1);
816 if (vas != VA_STATUS_SUCCESS) {
817 av_log(avctx, AV_LOG_ERROR, "Failed to query "
818 "config attribute: %d (%s).\n", vas, vaErrorStr(vas));
819 return AVERROR_EXTERNAL;
820 } else if (attr.value == VA_ATTRIB_NOT_SUPPORTED) {
821 priv->attr_ext1.value = 0;
822 av_log(avctx, AV_LOG_WARNING, "Attribute type:%d is not "
823 "supported.\n", attr.type);
824 } else {
825 priv->attr_ext1.value = attr.value;
826 }
827
828 /** This attr provides essential indicators, return error if not support. */
829 attr.type = VAConfigAttribEncAV1Ext2;
830 vas = vaGetConfigAttributes(ctx->hwctx->display,
831 ctx->va_profile,
832 ctx->va_entrypoint,
833 &attr, 1);
834 if (vas != VA_STATUS_SUCCESS || attr.value == VA_ATTRIB_NOT_SUPPORTED) {
835 av_log(avctx, AV_LOG_ERROR, "Failed to query "
836 "config attribute: %d (%s).\n", vas, vaErrorStr(vas));
837 return AVERROR_EXTERNAL;
838 } else {
839 priv->attr_ext2.value = attr.value;
840 }
841
842 ret = vaapi_encode_av1_set_tile(avctx);
843 if (ret < 0)
844 return ret;
845
846 return 0;
847}
848
849static av_cold int vaapi_encode_av1_close(AVCodecContext *avctx)
850{
851 VAAPIEncodeAV1Context *priv = avctx->priv_data;
852
853 ff_cbs_fragment_free(&priv->current_obu);
854 ff_cbs_close(&priv->cbc);
855
856 return ff_vaapi_encode_close(avctx);
857}
858
859#define OFFSET(x) offsetof(VAAPIEncodeAV1Context, x)
860#define FLAGS (AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM)
861
862static const AVOption vaapi_encode_av1_options[] = {
863 VAAPI_ENCODE_COMMON_OPTIONS,
864 VAAPI_ENCODE_RC_OPTIONS,
865 { "profile", "Set profile (seq_profile)",
866 OFFSET(profile), AV_OPT_TYPE_INT,
867 { .i64 = AV_PROFILE_UNKNOWN }, AV_PROFILE_UNKNOWN, 0xff, FLAGS, "profile" },
868
869#define PROFILE(name, value) name, NULL, 0, AV_OPT_TYPE_CONST, \
870 { .i64 = value }, 0, 0, FLAGS, "profile"
871 { PROFILE("main", AV_PROFILE_AV1_MAIN) },
872 { PROFILE("high", AV_PROFILE_AV1_HIGH) },
873 { PROFILE("professional", AV_PROFILE_AV1_PROFESSIONAL) },
874#undef PROFILE
875
876 { "tier", "Set tier (seq_tier)",
877 OFFSET(tier), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, FLAGS, "tier" },
878 { "main", NULL, 0, AV_OPT_TYPE_CONST,
879 { .i64 = 0 }, 0, 0, FLAGS, "tier" },
880 { "high", NULL, 0, AV_OPT_TYPE_CONST,
881 { .i64 = 1 }, 0, 0, FLAGS, "tier" },
882 { "level", "Set level (seq_level_idx)",
883 OFFSET(level), AV_OPT_TYPE_INT,
884 { .i64 = AV_LEVEL_UNKNOWN }, AV_LEVEL_UNKNOWN, 0x1f, FLAGS, "level" },
885
886#define LEVEL(name, value) name, NULL, 0, AV_OPT_TYPE_CONST, \
887 { .i64 = value }, 0, 0, FLAGS, "level"
888 { LEVEL("2.0", 0) },
889 { LEVEL("2.1", 1) },
890 { LEVEL("3.0", 4) },
891 { LEVEL("3.1", 5) },
892 { LEVEL("4.0", 8) },
893 { LEVEL("4.1", 9) },
894 { LEVEL("5.0", 12) },
895 { LEVEL("5.1", 13) },
896 { LEVEL("5.2", 14) },
897 { LEVEL("5.3", 15) },
898 { LEVEL("6.0", 16) },
899 { LEVEL("6.1", 17) },
900 { LEVEL("6.2", 18) },
901 { LEVEL("6.3", 19) },
902#undef LEVEL
903
904 { "tiles", "Tile columns x rows (Use minimal tile column/row number automatically by default)",
905 OFFSET(tile_cols), AV_OPT_TYPE_IMAGE_SIZE, { .str = NULL }, 0, 0, FLAGS },
906 { "tile_groups", "Number of tile groups for encoding",
907 OFFSET(tile_groups), AV_OPT_TYPE_INT, { .i64 = 1 }, 1, AV1_MAX_TILE_ROWS * AV1_MAX_TILE_COLS, FLAGS },
908
909 { NULL },
910};
911
912static const FFCodecDefault vaapi_encode_av1_defaults[] = {
913 { "b", "0" },
914 { "bf", "2" },
915 { "g", "120" },
916 { "qmin", "1" },
917 { "qmax", "255" },
918 { NULL },
919};
920
921static const AVClass vaapi_encode_av1_class = {
922 .class_name = "av1_vaapi",
923 .item_name = av_default_item_name,
924 .option = vaapi_encode_av1_options,
925 .version = LIBAVUTIL_VERSION_INT,
926};
927
928const FFCodec ff_av1_vaapi_encoder = {
929 .p.name = "av1_vaapi",
930 CODEC_LONG_NAME("AV1 (VAAPI)"),
931 .p.type = AVMEDIA_TYPE_VIDEO,
932 .p.id = AV_CODEC_ID_AV1,
933 .priv_data_size = sizeof(VAAPIEncodeAV1Context),
934 .init = &vaapi_encode_av1_init,
935 FF_CODEC_RECEIVE_PACKET_CB(&ff_vaapi_encode_receive_packet),
936 .close = &vaapi_encode_av1_close,
937 .p.priv_class = &vaapi_encode_av1_class,
938 .p.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HARDWARE |
939 AV_CODEC_CAP_DR1 | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
940 .caps_internal = FF_CODEC_CAP_NOT_INIT_THREADSAFE |
941 FF_CODEC_CAP_INIT_CLEANUP,
942 .defaults = vaapi_encode_av1_defaults,
943 .p.pix_fmts = (const enum AVPixelFormat[]) {
944 AV_PIX_FMT_VAAPI,
945 AV_PIX_FMT_NONE,
946 },
947 .hw_configs = ff_vaapi_encode_hw_configs,
948 .p.wrapper_name = "vaapi",
949};
libavcodec/version.h+1−1
@@ -29,7 +29,7 @@ · 28 unmodified lines
29 29
30#include "version_major.h"30#include "version_major.h"
31 31
32#define LIBAVCODEC_VERSION_MINOR 2632#define LIBAVCODEC_VERSION_MINOR 27
33#define LIBAVCODEC_VERSION_MICRO 10033#define LIBAVCODEC_VERSION_MICRO 100
34 34
35#define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \35#define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t