diff options
author | Timo Rothenpieler <timo@rothenpieler.org> | 2017-11-11 16:08:53 +0100 |
---|---|---|
committer | Timo Rothenpieler <timo@rothenpieler.org> | 2017-11-12 15:46:39 +0100 |
commit | c60bc02bf4bc4f6f57fd0fd4c5b2e63253623185 (patch) | |
tree | bc59c1032381e8f6881afaae955ffe49bd36e532 /libavcodec | |
parent | 3e0e1634585b1a26b7d753aa42c7f350636927ae (diff) | |
download | ffmpeg-c60bc02bf4bc4f6f57fd0fd4c5b2e63253623185.tar.gz |
avcodec/nvdec: check hardware capabilities
Diffstat (limited to 'libavcodec')
-rw-r--r-- | libavcodec/nvdec.c | 56 |
1 files changed, 56 insertions, 0 deletions
diff --git a/libavcodec/nvdec.c b/libavcodec/nvdec.c index 58ebeeb9c1..6287897343 100644 --- a/libavcodec/nvdec.c +++ b/libavcodec/nvdec.c @@ -74,6 +74,56 @@ static int map_chroma_format(enum AVPixelFormat pix_fmt) return -1; } +static int nvdec_test_capabilities(NVDECDecoder *decoder, + CUVIDDECODECREATEINFO *params, void *logctx) +{ + CUresult err; + CUVIDDECODECAPS caps = { 0 }; + + caps.eCodecType = params->CodecType; + caps.eChromaFormat = params->ChromaFormat; + caps.nBitDepthMinus8 = params->bitDepthMinus8; + + err = decoder->cvdl->cuvidGetDecoderCaps(&caps); + if (err != CUDA_SUCCESS) { + av_log(logctx, AV_LOG_ERROR, "Failed querying decoder capabilities\n"); + return AVERROR_UNKNOWN; + } + + av_log(logctx, AV_LOG_VERBOSE, "NVDEC capabilities:\n"); + av_log(logctx, AV_LOG_VERBOSE, "format supported: %s, max_mb_count: %d\n", + caps.bIsSupported ? "yes" : "no", caps.nMaxMBCount); + av_log(logctx, AV_LOG_VERBOSE, "min_width: %d, max_width: %d\n", + caps.nMinWidth, caps.nMaxWidth); + av_log(logctx, AV_LOG_VERBOSE, "min_height: %d, max_height: %d\n", + caps.nMinHeight, caps.nMaxHeight); + + if (!caps.bIsSupported) { + av_log(logctx, AV_LOG_ERROR, "Hardware is lacking required capabilities\n"); + return AVERROR(EINVAL); + } + + if (params->ulWidth > caps.nMaxWidth || params->ulWidth < caps.nMinWidth) { + av_log(logctx, AV_LOG_ERROR, "Video width %d not within range from %d to %d\n", + (int)params->ulWidth, caps.nMinWidth, caps.nMaxWidth); + return AVERROR(EINVAL); + } + + if (params->ulHeight > caps.nMaxHeight || params->ulHeight < caps.nMinHeight) { + av_log(logctx, AV_LOG_ERROR, "Video height %d not within range from %d to %d\n", + (int)params->ulHeight, caps.nMinHeight, caps.nMaxHeight); + return AVERROR(EINVAL); + } + + if ((params->ulWidth * params->ulHeight) / 256 > caps.nMaxMBCount) { + av_log(logctx, AV_LOG_ERROR, "Video macroblock count %d exceeds maximum of %d\n", + (int)(params->ulWidth * params->ulHeight) / 256, caps.nMaxMBCount); + return AVERROR(EINVAL); + } + + return 0; +} + static void nvdec_decoder_free(void *opaque, uint8_t *data) { NVDECDecoder *decoder = (NVDECDecoder*)data; @@ -132,6 +182,12 @@ static int nvdec_decoder_create(AVBufferRef **out, AVBufferRef *hw_device_ref, goto fail; } + ret = nvdec_test_capabilities(decoder, params, logctx); + if (ret < 0) { + decoder->cudl->cuCtxPopCurrent(&dummy); + goto fail; + } + err = decoder->cvdl->cuvidCreateDecoder(&decoder->decoder, params); decoder->cudl->cuCtxPopCurrent(&dummy); |