This repository has been archived by the owner on Feb 9, 2021. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy path0010-lavc-vaapi_encode-add-support-for-maxframesize.patch
193 lines (176 loc) · 6.68 KB
/
0010-lavc-vaapi_encode-add-support-for-maxframesize.patch
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
From 5f9d6daadcd8c604570c110a8c0fd80516788746 Mon Sep 17 00:00:00 2001
From: Linjie Fu <[email protected]>
Date: Mon, 22 Jun 2020 09:51:24 +0800
Subject: [PATCH] lavc/vaapi_encode: add support for maxframesize
Add support for max frame size:
- max_frame_size (bytes) to indicate the max allowed size for frame.
If the frame size exceeds the limitation, encoder will to control the frame
size by adjusting QP value.
- MFS_NUM_PASSES to indicate number of passes for QP adjust.
- MFS_DELTA_QP to indicate adjust qp value per pass.
To simplify the usage, default QP adjust is set to delta_qp[4] = {1, 1, 1, 1}.
Use new_qp for encoder if frame size exceeds the limitation:
new_qp = base_qp + delta_qp[0] + delta_qp[1] + ...
ffmpeg -hwaccel vaapi -vaapi_device /dev/dri/renderD128 -f rawvideo \
-v verbose -s:v 352x288 -i ./input.yuv -vf format=nv12,hwupload \
-c:v h264_vaapi -profile:v main -g 30 -bf 3 -max_frame_size 40000 \
-vframes 100 -y ./max_frame_size.h264
Max frame size was enabled since VA-API version (1, 3, 0), but query is available
since (1, 5, 0). It will be passed as a parameter in picParam and should be set
for each frame.
Signed-off-by: Linjie Fu <[email protected]>
---
libavcodec/vaapi_encode.c | 68 ++++++++++++++++++++++++++++++++++++++++++++++-
libavcodec/vaapi_encode.h | 19 +++++++++++--
2 files changed, 84 insertions(+), 3 deletions(-)
diff --git a/libavcodec/vaapi_encode.c b/libavcodec/vaapi_encode.c
index e39db20..832dc03 100644
--- a/libavcodec/vaapi_encode.c
+++ b/libavcodec/vaapi_encode.c
@@ -265,7 +265,16 @@ static int vaapi_encode_issue(AVCodecContext *avctx,
if (err < 0)
goto fail;
}
-
+#if VA_CHECK_VERSION(1, 5, 0)
+ if (ctx->max_frame_size) {
+ err = vaapi_encode_make_misc_param_buffer(avctx, pic,
+ VAEncMiscParameterTypeMultiPassFrameSize,
+ &ctx->mfs_params,
+ sizeof(ctx->mfs_params));
+ if (err < 0)
+ goto fail;
+ }
+#endif
if (pic->type == PICTURE_TYPE_IDR) {
if (ctx->va_packed_headers & VA_ENC_PACKED_HEADER_SEQUENCE &&
ctx->codec->write_sequence_header) {
@@ -1776,6 +1785,54 @@ rc_mode_found:
return 0;
}
+static av_cold int vaapi_encode_init_max_frame_size(AVCodecContext *avctx)
+{
+#if VA_CHECK_VERSION(1, 5, 0)
+ VAAPIEncodeContext *ctx = avctx->priv_data;
+ VAConfigAttrib attr = { VAConfigAttribMaxFrameSize };
+ VAStatus vas;
+ int i;
+
+ vas = vaGetConfigAttributes(ctx->hwctx->display,
+ ctx->va_profile,
+ ctx->va_entrypoint,
+ &attr, 1);
+ if (vas != VA_STATUS_SUCCESS) {
+ ctx->max_frame_size = 0;
+ av_log(avctx, AV_LOG_ERROR, "Failed to query max frame size "
+ "config attribute: %d (%s).\n", vas, vaErrorStr(vas));
+ return AVERROR_EXTERNAL;
+ }
+
+ if (attr.value == VA_ATTRIB_NOT_SUPPORTED) {
+ ctx->max_frame_size = 0;
+ av_log(avctx, AV_LOG_WARNING, "Max frame size attribute "
+ "is not supported.\n");
+ } else {
+ ctx->delta_qp = av_mallocz_array(MFS_NUM_PASSES, sizeof(uint8_t));
+ if (!ctx->delta_qp) {
+ return AVERROR(ENOMEM);
+ }
+ for (i = 0; i <MFS_NUM_PASSES; i++)
+ ctx->delta_qp[i] = MFS_DELTA_QP;
+
+ ctx->mfs_params = (VAEncMiscParameterBufferMultiPassFrameSize){
+ .max_frame_size = ctx->max_frame_size,
+ .num_passes = MFS_NUM_PASSES,
+ .delta_qp = ctx->delta_qp,
+ };
+
+ av_log(avctx, AV_LOG_VERBOSE, "Max Frame Size: %d bytes.\n ",
+ ctx->max_frame_size);
+ }
+#else
+ av_log(avctx, AV_LOG_WARNING, "Max Frame Size is "
+ "not supported with this VA version.\n");
+#endif
+
+ return 0;
+}
+
static av_cold int vaapi_encode_init_gop_structure(AVCodecContext *avctx)
{
VAAPIEncodeContext *ctx = avctx->priv_data;
@@ -2285,6 +2342,12 @@ av_cold int ff_vaapi_encode_init(AVCodecContext *avctx)
goto fail;
}
+ if (ctx->max_frame_size) {
+ err = vaapi_encode_init_max_frame_size(avctx);
+ if (err < 0)
+ goto fail;
+ }
+
vas = vaCreateConfig(ctx->hwctx->display,
ctx->va_profile, ctx->va_entrypoint,
ctx->config_attributes, ctx->nb_config_attributes,
@@ -2408,6 +2471,9 @@ av_cold int ff_vaapi_encode_close(AVCodecContext *avctx)
ctx->va_config = VA_INVALID_ID;
}
+ if (ctx->delta_qp)
+ av_freep(&ctx->delta_qp);
+
av_frame_free(&ctx->frame);
av_freep(&ctx->codec_sequence_params);
diff --git a/libavcodec/vaapi_encode.h b/libavcodec/vaapi_encode.h
index 85d2a8f..6a4a428 100644
--- a/libavcodec/vaapi_encode.h
+++ b/libavcodec/vaapi_encode.h
@@ -54,6 +54,11 @@ enum {
PICTURE_TYPE_B = 3,
};
+enum {
+ MFS_NUM_PASSES = 4,
+ MFS_DELTA_QP = 1,
+};
+
typedef struct VAAPIEncodeSlice {
int index;
int row_start;
@@ -186,6 +191,9 @@ typedef struct VAAPIEncodeContext {
// Desired B frame reference depth.
int desired_b_depth;
+ // Max Frame Size
+ int max_frame_size;
+
// Explicitly set RC mode (otherwise attempt to pick from
// available modes).
int explicit_rc_mode;
@@ -266,7 +274,9 @@ typedef struct VAAPIEncodeContext {
#if VA_CHECK_VERSION(0, 36, 0)
VAEncMiscParameterBufferQualityLevel quality_params;
#endif
-
+#if VA_CHECK_VERSION(1, 3, 0)
+ VAEncMiscParameterBufferMultiPassFrameSize mfs_params;
+#endif
// Per-sequence parameter structure (VAEncSequenceParameterBuffer*).
void *codec_sequence_params;
@@ -313,6 +323,7 @@ typedef struct VAAPIEncodeContext {
int idr_counter;
int gop_counter;
int end_of_stream;
+ uint8_t *delta_qp;
// Whether the driver supports ROI at all.
int roi_allowed;
@@ -440,7 +451,11 @@ int ff_vaapi_encode_close(AVCodecContext *avctx);
{ "b_depth", \
"Maximum B-frame reference depth", \
OFFSET(common.desired_b_depth), AV_OPT_TYPE_INT, \
- { .i64 = 1 }, 1, INT_MAX, FLAGS }
+ { .i64 = 1 }, 1, INT_MAX, FLAGS }, \
+ { "max_frame_size", \
+ "Maximum frame size (in bytes)",\
+ OFFSET(common.max_frame_size), AV_OPT_TYPE_INT, \
+ { .i64 = 0 }, 0, INT_MAX, FLAGS }
#define VAAPI_ENCODE_RC_MODE(name, desc) \
{ #name, desc, 0, AV_OPT_TYPE_CONST, { .i64 = RC_MODE_ ## name }, \
--
2.7.4