Previous version reviewed-by: Philip Langdale <philipl@overt.org>
Signed-off-by: Michael Niedermayer <michaelni@gmx.at>
... | ... |
@@ -129,6 +129,12 @@ typedef struct NvencDynLoadFunctions |
129 | 129 |
#endif |
130 | 130 |
} NvencDynLoadFunctions; |
131 | 131 |
|
132 |
+typedef struct NvencValuePair |
|
133 |
+{ |
|
134 |
+ const char *str; |
|
135 |
+ uint32_t num; |
|
136 |
+} NvencValuePair; |
|
137 |
+ |
|
132 | 138 |
typedef struct NvencContext |
133 | 139 |
{ |
134 | 140 |
AVClass *avclass; |
... | ... |
@@ -152,11 +158,76 @@ typedef struct NvencContext |
152 | 152 |
|
153 | 153 |
char *preset; |
154 | 154 |
char *profile; |
155 |
+ char *level; |
|
156 |
+ char *tier; |
|
155 | 157 |
int cbr; |
156 | 158 |
int twopass; |
157 | 159 |
int gpu; |
158 | 160 |
} NvencContext; |
159 | 161 |
|
162 |
+static const NvencValuePair nvenc_h264_level_pairs[] = { |
|
163 |
+ { "auto", NV_ENC_LEVEL_AUTOSELECT }, |
|
164 |
+ { "1" , NV_ENC_LEVEL_H264_1 }, |
|
165 |
+ { "1.0" , NV_ENC_LEVEL_H264_1 }, |
|
166 |
+ { "1b" , NV_ENC_LEVEL_H264_1b }, |
|
167 |
+ { "1.0b", NV_ENC_LEVEL_H264_1b }, |
|
168 |
+ { "1.1" , NV_ENC_LEVEL_H264_11 }, |
|
169 |
+ { "1.2" , NV_ENC_LEVEL_H264_12 }, |
|
170 |
+ { "1.3" , NV_ENC_LEVEL_H264_13 }, |
|
171 |
+ { "2" , NV_ENC_LEVEL_H264_2 }, |
|
172 |
+ { "2.0" , NV_ENC_LEVEL_H264_2 }, |
|
173 |
+ { "2.1" , NV_ENC_LEVEL_H264_21 }, |
|
174 |
+ { "2.2" , NV_ENC_LEVEL_H264_22 }, |
|
175 |
+ { "3" , NV_ENC_LEVEL_H264_3 }, |
|
176 |
+ { "3.0" , NV_ENC_LEVEL_H264_3 }, |
|
177 |
+ { "3.1" , NV_ENC_LEVEL_H264_31 }, |
|
178 |
+ { "3.2" , NV_ENC_LEVEL_H264_32 }, |
|
179 |
+ { "4" , NV_ENC_LEVEL_H264_4 }, |
|
180 |
+ { "4.0" , NV_ENC_LEVEL_H264_4 }, |
|
181 |
+ { "4.1" , NV_ENC_LEVEL_H264_41 }, |
|
182 |
+ { "4.2" , NV_ENC_LEVEL_H264_42 }, |
|
183 |
+ { "5" , NV_ENC_LEVEL_H264_5 }, |
|
184 |
+ { "5.0" , NV_ENC_LEVEL_H264_5 }, |
|
185 |
+ { "5.1" , NV_ENC_LEVEL_H264_51 }, |
|
186 |
+ { NULL } |
|
187 |
+}; |
|
188 |
+ |
|
189 |
+static const NvencValuePair nvenc_h265_level_pairs[] = { |
|
190 |
+ { "auto", NV_ENC_LEVEL_AUTOSELECT }, |
|
191 |
+ { "1" , NV_ENC_LEVEL_HEVC_1 }, |
|
192 |
+ { "1.0" , NV_ENC_LEVEL_HEVC_1 }, |
|
193 |
+ { "2" , NV_ENC_LEVEL_HEVC_2 }, |
|
194 |
+ { "2.0" , NV_ENC_LEVEL_HEVC_2 }, |
|
195 |
+ { "2.1" , NV_ENC_LEVEL_HEVC_21 }, |
|
196 |
+ { "3" , NV_ENC_LEVEL_HEVC_3 }, |
|
197 |
+ { "3.0" , NV_ENC_LEVEL_HEVC_3 }, |
|
198 |
+ { "3.1" , NV_ENC_LEVEL_HEVC_31 }, |
|
199 |
+ { "4" , NV_ENC_LEVEL_HEVC_4 }, |
|
200 |
+ { "4.0" , NV_ENC_LEVEL_HEVC_4 }, |
|
201 |
+ { "4.1" , NV_ENC_LEVEL_HEVC_41 }, |
|
202 |
+ { "5" , NV_ENC_LEVEL_HEVC_5 }, |
|
203 |
+ { "5.0" , NV_ENC_LEVEL_HEVC_5 }, |
|
204 |
+ { "5.1" , NV_ENC_LEVEL_HEVC_51 }, |
|
205 |
+ { "5.2" , NV_ENC_LEVEL_HEVC_52 }, |
|
206 |
+ { "6" , NV_ENC_LEVEL_HEVC_6 }, |
|
207 |
+ { "6.0" , NV_ENC_LEVEL_HEVC_6 }, |
|
208 |
+ { "6.1" , NV_ENC_LEVEL_HEVC_61 }, |
|
209 |
+ { "6.2" , NV_ENC_LEVEL_HEVC_62 }, |
|
210 |
+ { NULL } |
|
211 |
+}; |
|
212 |
+ |
|
213 |
+static int input_string_to_uint32(AVCodecContext *avctx, const NvencValuePair *pair, const char *input, uint32_t *output) |
|
214 |
+{ |
|
215 |
+ for (; pair->str; ++pair) { |
|
216 |
+ if (!strcmp(input, pair->str)) { |
|
217 |
+ *output = pair->num; |
|
218 |
+ return 0; |
|
219 |
+ } |
|
220 |
+ } |
|
221 |
+ |
|
222 |
+ return AVERROR(EINVAL); |
|
223 |
+} |
|
224 |
+ |
|
160 | 225 |
static NvencData* data_queue_dequeue(NvencDataList* queue) |
161 | 226 |
{ |
162 | 227 |
uint32_t mask; |
... | ... |
@@ -777,6 +848,18 @@ static av_cold int nvenc_encode_init(AVCodecContext *avctx) |
777 | 777 |
goto error; |
778 | 778 |
} |
779 | 779 |
} |
780 |
+ |
|
781 |
+ if (ctx->level) { |
|
782 |
+ res = input_string_to_uint32(avctx, nvenc_h264_level_pairs, ctx->level, &ctx->encode_config.encodeCodecConfig.h264Config.level); |
|
783 |
+ |
|
784 |
+ if (res) { |
|
785 |
+ av_log(avctx, AV_LOG_FATAL, "Level \"%s\" is unknown! Supported levels: auto, 1, 1b, 1.1, 1.2, 1.3, 2, 2.1, 2.2, 3, 3.1, 3.2, 4, 4.1, 4.2, 5, 5.1\n", ctx->level); |
|
786 |
+ goto error; |
|
787 |
+ } |
|
788 |
+ } else { |
|
789 |
+ ctx->encode_config.encodeCodecConfig.h264Config.level = NV_ENC_LEVEL_AUTOSELECT; |
|
790 |
+ } |
|
791 |
+ |
|
780 | 792 |
break; |
781 | 793 |
case AV_CODEC_ID_H265: |
782 | 794 |
ctx->encode_config.encodeCodecConfig.hevcConfig.disableSPSPPS = (avctx->flags & CODEC_FLAG_GLOBAL_HEADER) ? 1 : 0; |
... | ... |
@@ -785,6 +868,30 @@ static av_cold int nvenc_encode_init(AVCodecContext *avctx) |
785 | 785 |
/* No other profile is supported in the current SDK version 5 */ |
786 | 786 |
ctx->encode_config.profileGUID = NV_ENC_HEVC_PROFILE_MAIN_GUID; |
787 | 787 |
avctx->profile = FF_PROFILE_HEVC_MAIN; |
788 |
+ |
|
789 |
+ if (ctx->level) { |
|
790 |
+ res = input_string_to_uint32(avctx, nvenc_h265_level_pairs, ctx->level, &ctx->encode_config.encodeCodecConfig.hevcConfig.level); |
|
791 |
+ |
|
792 |
+ if (res) { |
|
793 |
+ av_log(avctx, AV_LOG_FATAL, "Level \"%s\" is unknown! Supported levels: auto, 1, 2, 2.1, 3, 3.1, 4, 4.1, 5, 5.1, 5.2, 6, 6.1, 6.2\n", ctx->level); |
|
794 |
+ goto error; |
|
795 |
+ } |
|
796 |
+ } else { |
|
797 |
+ ctx->encode_config.encodeCodecConfig.hevcConfig.level = NV_ENC_LEVEL_AUTOSELECT; |
|
798 |
+ } |
|
799 |
+ |
|
800 |
+ if (ctx->tier) { |
|
801 |
+ if (!strcmp(ctx->tier, "main")) { |
|
802 |
+ ctx->encode_config.encodeCodecConfig.hevcConfig.tier = NV_ENC_TIER_HEVC_MAIN; |
|
803 |
+ } else if (!strcmp(ctx->tier, "high")) { |
|
804 |
+ ctx->encode_config.encodeCodecConfig.hevcConfig.tier = NV_ENC_TIER_HEVC_HIGH; |
|
805 |
+ } else { |
|
806 |
+ av_log(avctx, AV_LOG_FATAL, "Tier \"%s\" is unknown! Supported tiers: main, high\n", ctx->tier); |
|
807 |
+ res = AVERROR(EINVAL); |
|
808 |
+ goto error; |
|
809 |
+ } |
|
810 |
+ } |
|
811 |
+ |
|
788 | 812 |
break; |
789 | 813 |
/* Earlier switch/case will return if unknown codec is passed. */ |
790 | 814 |
} |
... | ... |
@@ -1277,7 +1384,9 @@ static enum AVPixelFormat pix_fmts_nvenc[] = { |
1277 | 1277 |
#define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM |
1278 | 1278 |
static const AVOption options[] = { |
1279 | 1279 |
{ "preset", "Set the encoding preset (one of hq, hp, bd, ll, llhq, llhp, default)", OFFSET(preset), AV_OPT_TYPE_STRING, { .str = "hq" }, 0, 0, VE }, |
1280 |
- { "profile", "Set the encoding profile (high, main or baseline)", OFFSET(profile), AV_OPT_TYPE_STRING, { 0 }, 0, 0, VE}, |
|
1280 |
+ { "profile", "Set the encoding profile (high, main or baseline)", OFFSET(profile), AV_OPT_TYPE_STRING, { 0 }, 0, 0, VE }, |
|
1281 |
+ { "level", "Set the encoding level restriction (auto, 1.0, 1.0b, 1.1, 1.2, ..., 4.2, 5.0, 5.1)", OFFSET(level), AV_OPT_TYPE_STRING, { 0 }, 0, 0, VE }, |
|
1282 |
+ { "tier", "Set the encoding tier (main or high)", OFFSET(tier), AV_OPT_TYPE_STRING, { 0 }, 0, 0, VE }, |
|
1281 | 1283 |
{ "cbr", "Use cbr encoding mode", OFFSET(cbr), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, VE }, |
1282 | 1284 |
{ "2pass", "Use 2pass cbr encoding mode (low latency mode only)", OFFSET(twopass), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 1, VE }, |
1283 | 1285 |
{ "gpu", "Selects which NVENC capable GPU to use. First GPU is 0, second is 1, and so on.", OFFSET(gpu), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, VE }, |