summaryrefslogtreecommitdiff
path: root/libavcodec/nvenc.c
diff options
context:
space:
mode:
authorOliver Collyer <ovcollyer@mac.com>2016-08-25 16:18:03 +0100
committerTimo Rothenpieler <timo@rothenpieler.org>2016-08-28 16:47:54 +0200
commitd1bf8a3aa878003f5019bb97c3228f8027e5d116 (patch)
tree0c9b7d623b28e6fe489906543116a1debb5dd54d /libavcodec/nvenc.c
parent325e56479ff64c884f3bcccf922a7f7163488b89 (diff)
avcodec/nvenc: added support for 10 bit HEVC encoding
Signed-off-by: Timo Rothenpieler <timo@rothenpieler.org>
Diffstat (limited to 'libavcodec/nvenc.c')
-rw-r--r--libavcodec/nvenc.c73
1 files changed, 69 insertions, 4 deletions
diff --git a/libavcodec/nvenc.c b/libavcodec/nvenc.c
index 984dd3bc3f..5706590334 100644
--- a/libavcodec/nvenc.c
+++ b/libavcodec/nvenc.c
@@ -76,13 +76,21 @@
const enum AVPixelFormat ff_nvenc_pix_fmts[] = {
AV_PIX_FMT_YUV420P,
AV_PIX_FMT_NV12,
+ AV_PIX_FMT_P010,
AV_PIX_FMT_YUV444P,
+ AV_PIX_FMT_YUV444P16,
#if CONFIG_CUDA
AV_PIX_FMT_CUDA,
#endif
AV_PIX_FMT_NONE
};
+#define IS_10BIT(pix_fmt) (pix_fmt == AV_PIX_FMT_P010 || \
+ pix_fmt == AV_PIX_FMT_YUV444P16)
+
+#define IS_YUV444(pix_fmt) (pix_fmt == AV_PIX_FMT_YUV444P || \
+ pix_fmt == AV_PIX_FMT_YUV444P16)
+
static const struct {
NVENCSTATUS nverr;
int averr;
@@ -273,7 +281,7 @@ static int nvenc_check_capabilities(AVCodecContext *avctx)
}
ret = nvenc_check_cap(avctx, NV_ENC_CAPS_SUPPORT_YUV444_ENCODE);
- if (ctx->data_pix_fmt == AV_PIX_FMT_YUV444P && ret <= 0) {
+ if (IS_YUV444(ctx->data_pix_fmt) && ret <= 0) {
av_log(avctx, AV_LOG_VERBOSE, "YUV444P not supported\n");
return AVERROR(ENOSYS);
}
@@ -314,6 +322,12 @@ static int nvenc_check_capabilities(AVCodecContext *avctx)
return AVERROR(ENOSYS);
}
+ ret = nvenc_check_cap(avctx, NV_ENC_CAPS_SUPPORT_10BIT_ENCODE);
+ if (IS_10BIT(ctx->data_pix_fmt) && ret <= 0) {
+ av_log(avctx, AV_LOG_VERBOSE, "10 bit encode not supported\n");
+ return AVERROR(ENOSYS);
+ }
+
return 0;
}
@@ -800,9 +814,26 @@ static av_cold int nvenc_setup_hevc_config(AVCodecContext *avctx)
hevc->outputPictureTimingSEI = 1;
}
- /* No other profile is supported in the current SDK version 5 */
- cc->profileGUID = NV_ENC_HEVC_PROFILE_MAIN_GUID;
- avctx->profile = FF_PROFILE_HEVC_MAIN;
+ switch(ctx->profile) {
+ case NV_ENC_HEVC_PROFILE_MAIN:
+ cc->profileGUID = NV_ENC_HEVC_PROFILE_MAIN_GUID;
+ avctx->profile = FF_PROFILE_HEVC_MAIN;
+ break;
+ case NV_ENC_HEVC_PROFILE_MAIN_10:
+ cc->profileGUID = NV_ENC_HEVC_PROFILE_MAIN10_GUID;
+ avctx->profile = FF_PROFILE_HEVC_MAIN_10;
+ break;
+ }
+
+ // force setting profile as main10 if input is 10 bit
+ if (IS_10BIT(ctx->data_pix_fmt)) {
+ cc->profileGUID = NV_ENC_HEVC_PROFILE_MAIN10_GUID;
+ avctx->profile = FF_PROFILE_HEVC_MAIN_10;
+ }
+
+ hevc->chromaFormatIDC = IS_YUV444(ctx->data_pix_fmt) ? 3 : 1;
+
+ hevc->pixelBitDepthMinus8 = IS_10BIT(ctx->data_pix_fmt) ? 2 : 0;
hevc->level = ctx->level;
@@ -958,10 +989,18 @@ static av_cold int nvenc_alloc_surface(AVCodecContext *avctx, int idx)
ctx->surfaces[idx].format = NV_ENC_BUFFER_FORMAT_NV12_PL;
break;
+ case AV_PIX_FMT_P010:
+ ctx->surfaces[idx].format = NV_ENC_BUFFER_FORMAT_YUV420_10BIT;
+ break;
+
case AV_PIX_FMT_YUV444P:
ctx->surfaces[idx].format = NV_ENC_BUFFER_FORMAT_YUV444_PL;
break;
+ case AV_PIX_FMT_YUV444P16:
+ ctx->surfaces[idx].format = NV_ENC_BUFFER_FORMAT_YUV444_10BIT;
+ break;
+
default:
av_log(avctx, AV_LOG_FATAL, "Invalid input pixel format\n");
return AVERROR(EINVAL);
@@ -1238,6 +1277,16 @@ static int nvenc_copy_frame(AVCodecContext *avctx, NvencSurface *inSurf,
av_image_copy_plane(buf, lockBufferParams->pitch,
frame->data[1], frame->linesize[1],
avctx->width, avctx->height >> 1);
+ } else if (frame->format == AV_PIX_FMT_P010) {
+ av_image_copy_plane(buf, lockBufferParams->pitch,
+ frame->data[0], frame->linesize[0],
+ avctx->width << 1, avctx->height);
+
+ buf += off;
+
+ av_image_copy_plane(buf, lockBufferParams->pitch,
+ frame->data[1], frame->linesize[1],
+ avctx->width << 1, avctx->height >> 1);
} else if (frame->format == AV_PIX_FMT_YUV444P) {
av_image_copy_plane(buf, lockBufferParams->pitch,
frame->data[0], frame->linesize[0],
@@ -1254,6 +1303,22 @@ static int nvenc_copy_frame(AVCodecContext *avctx, NvencSurface *inSurf,
av_image_copy_plane(buf, lockBufferParams->pitch,
frame->data[2], frame->linesize[2],
avctx->width, avctx->height);
+ } else if (frame->format == AV_PIX_FMT_YUV444P16) {
+ av_image_copy_plane(buf, lockBufferParams->pitch,
+ frame->data[0], frame->linesize[0],
+ avctx->width << 1, avctx->height);
+
+ buf += off;
+
+ av_image_copy_plane(buf, lockBufferParams->pitch,
+ frame->data[1], frame->linesize[1],
+ avctx->width << 1, avctx->height);
+
+ buf += off;
+
+ av_image_copy_plane(buf, lockBufferParams->pitch,
+ frame->data[2], frame->linesize[2],
+ avctx->width << 1, avctx->height);
} else {
av_log(avctx, AV_LOG_FATAL, "Invalid pixel format!\n");
return AVERROR(EINVAL);