Browse code

avcodec/nvenc: Add options for level and tier

Previous version reviewed-by: Philip Langdale <philipl@overt.org>
Signed-off-by: Michael Niedermayer <michaelni@gmx.at>

Timo Rothenpieler authored on 2015/04/04 20:34:14
Showing 2 changed files
... ...
@@ -15,6 +15,7 @@ version <next>:
15 15
 - basic APNG encoder and muxer
16 16
 - unpack DivX-style packed B-frames in MPEG-4 bitstream filter
17 17
 - WebM Live Chunk Muxer
18
+- nvenc level and tier options
18 19
 
19 20
 
20 21
 version 2.6:
... ...
@@ -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 },