From patchwork Sat Jan 21 18:02:51 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Pavel Koshevoy X-Patchwork-Id: 2279 Delivered-To: ffmpegpatchwork@gmail.com Received: by 10.103.89.21 with SMTP id n21csp588892vsb; Sat, 21 Jan 2017 10:09:59 -0800 (PST) X-Received: by 10.28.173.74 with SMTP id w71mr7395335wme.14.1485022199279; Sat, 21 Jan 2017 10:09:59 -0800 (PST) Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id u27si12375887wru.142.2017.01.21.10.09.58; Sat, 21 Jan 2017 10:09:59 -0800 (PST) Received-SPF: pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) client-ip=79.124.17.100; Authentication-Results: mx.google.com; dkim=neutral (body hash did not verify) header.i=@gmail.com; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=gmail.com Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 49FD568A86C; Sat, 21 Jan 2017 20:09:45 +0200 (EET) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail-pf0-f196.google.com (mail-pf0-f196.google.com [209.85.192.196]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 4BDBE68A145 for ; Sat, 21 Jan 2017 20:09:38 +0200 (EET) Received: by mail-pf0-f196.google.com with SMTP id 19so7420789pfo.3 for ; Sat, 21 Jan 2017 10:09:50 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=QNVXfsiFKHccWmGNS3m4jtzz4dmU2jO7GLxeBG6hj4k=; b=qouo/vBwl+7o3Wo+hlm5lJfMFEF2JEznE8wahXuOzqTBV4YPzR0qKbXLdhvjXJUuP1 uQGhvTl5c14FeU3Px/nIskLuDvk5G+LLnBCFDc6ioEJ4ck82pyvBsidOykgIH34Q3EFl Hmt+Z3WYd+9vZ518HJXf1NLN03E3wKjjL5pV/XGZK9nEKL8pOnBbFPvnupp1XTJv3LLo VRA1+qOFIIdKtLiwAQZG+AZMkCx2MVN0AFa1t7hoxc+AvfHoKX3BnnYtYXb/wNai28zT DD/SqsV6vC1PvPh77yHoaeqlTkIT8DZkzS6CTcTPoH+wEpYCEHss1eBV+mrrhKJZ425Q ze8g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=QNVXfsiFKHccWmGNS3m4jtzz4dmU2jO7GLxeBG6hj4k=; b=haRZ1fH2TxQMCYkQCN5IiiN81Qe7rIj1EDKnOseTtbjRov0D4dhkXy/aFjIXKceY5z IqLBoBqsGrtjdGG80mzwuEg70dFUBp5hFakuz6qtvQHs28DKSqTP0sXVX95M96uQyApN W8+sVr5e9UPknQCegpLx53qJ2n2+bYkon1lXfZWnb1rSY+me9WMpF0PgiAPh9X4NSmQB 6K476TP/IHG+5xAObeyIKVvvCn4jmn5W/19Xsasx0fiW00TEkMShVuwGnAMqZxANZIBc mcTD5f9+dWvoaDZaH6aXmDypTq6wF8yLn/97DZ5IF7WV2JgJveaijYrzJdioX3UNXrnz wv3A== X-Gm-Message-State: AIkVDXJOdHv8NNyGb7VNro6xB+FBx3uNMqzOEEC0WL5V1FekVaWEwOwFJyryzz1z8sEi1g== X-Received: by 10.99.55.26 with SMTP id e26mr23696718pga.15.1485021780645; Sat, 21 Jan 2017 10:03:00 -0800 (PST) Received: from homestead.aragog.com ([136.60.170.51]) by smtp.gmail.com with ESMTPSA id m14sm25705673pgn.19.2017.01.21.10.02.59 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Sat, 21 Jan 2017 10:02:59 -0800 (PST) From: pkoshevoy@gmail.com To: ffmpeg-devel@ffmpeg.org Date: Sat, 21 Jan 2017 11:02:51 -0700 Message-Id: <1485021771-29275-1-git-send-email-pkoshevoy@gmail.com> X-Mailer: git-send-email 2.6.6 In-Reply-To: <3bf67bd7-e111-83da-b4b9-698f5798cc39@rothenpieler.org> References: <3bf67bd7-e111-83da-b4b9-698f5798cc39@rothenpieler.org> Subject: [FFmpeg-devel] [PATCH] lavc/cuvid: fail early if GPU can't handle video parameters (v4) X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: FFmpeg development discussions and patches Cc: Pavel Koshevoy MIME-Version: 1.0 Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" From: Pavel Koshevoy Evidently CUVID doesn't support decoding 422 or 444 chroma formats, and only a limited set of resolutions per codec are supported. Unfortunately CUVID silently drops packets for video of unsupported resolution. However, it will error-out at cuvidCreateDecoder call if the indicated video resolution is not supported. Given that stream resolution and pixel format are typically known as a result of probing it is better to use this information during avcodec_open2 call to fail immediately, rather than proceeding to decode and never receiving any frames from the decoder nor receiving any indication of decode failure. --- libavcodec/cuvid.c | 64 +++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 59 insertions(+), 5 deletions(-) diff --git a/libavcodec/cuvid.c b/libavcodec/cuvid.c index 8fc713d..adaf75e 100644 --- a/libavcodec/cuvid.c +++ b/libavcodec/cuvid.c @@ -612,7 +612,11 @@ static av_cold int cuvid_decode_end(AVCodecContext *avctx) return 0; } -static int cuvid_test_dummy_decoder(AVCodecContext *avctx, CUVIDPARSERPARAMS *cuparseinfo) +static int cuvid_test_dummy_decoder(AVCodecContext *avctx, + const CUVIDPARSERPARAMS *cuparseinfo, + cudaVideoChromaFormat probed_chroma_format, + int probed_width, + int probed_height) { CuvidContext *ctx = avctx->priv_data; CUVIDDECODECREATEINFO cuinfo; @@ -622,11 +626,11 @@ static int cuvid_test_dummy_decoder(AVCodecContext *avctx, CUVIDPARSERPARAMS *cu memset(&cuinfo, 0, sizeof(cuinfo)); cuinfo.CodecType = cuparseinfo->CodecType; - cuinfo.ChromaFormat = cudaVideoChromaFormat_420; + cuinfo.ChromaFormat = probed_chroma_format; cuinfo.OutputFormat = cudaVideoSurfaceFormat_NV12; - cuinfo.ulWidth = 1280; - cuinfo.ulHeight = 720; + cuinfo.ulWidth = probed_width; + cuinfo.ulHeight = probed_height; cuinfo.ulTargetWidth = cuinfo.ulWidth; cuinfo.ulTargetHeight = cuinfo.ulHeight; @@ -653,6 +657,36 @@ static int cuvid_test_dummy_decoder(AVCodecContext *avctx, CUVIDPARSERPARAMS *cu return 0; } +static int convert_to_cuda_video_chroma_format(enum AVPixelFormat pix_fmt, + cudaVideoChromaFormat *out) +{ + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(pix_fmt); + if (!(out && desc && + (desc->nb_components == 1 || desc->nb_components == 3) && + (desc->log2_chroma_w < 2 && desc->log2_chroma_h < 2))) + { + return AVERROR(EINVAL); + } + + if (desc->nb_components == 1) + { + *out = cudaVideoChromaFormat_Monochrome; + } + else if (desc->flags == AV_PIX_FMT_FLAG_PLANAR) + { + *out = ((desc->log2_chroma_w == 0) ? cudaVideoChromaFormat_444 : + (desc->log2_chroma_h == 0) ? cudaVideoChromaFormat_422 : + cudaVideoChromaFormat_420); + } + else + { + return AVERROR(EINVAL); + } + + // unfortunately, 420 is the only one that works: + return (*out == cudaVideoChromaFormat_420) ? 0 : AVERROR_EXTERNAL; +} + static av_cold int cuvid_decode_init(AVCodecContext *avctx) { CuvidContext *ctx = avctx->priv_data; @@ -663,12 +697,29 @@ static av_cold int cuvid_decode_init(AVCodecContext *avctx) CUcontext cuda_ctx = NULL; CUcontext dummy; const AVBitStreamFilter *bsf; + cudaVideoChromaFormat probed_chroma_format; + int probed_width; + int probed_height; int ret = 0; enum AVPixelFormat pix_fmts[3] = { AV_PIX_FMT_CUDA, AV_PIX_FMT_NV12, AV_PIX_FMT_NONE }; + enum AVPixelFormat probed_pix_fmt = (avctx->pix_fmt <= 0 ? + AV_PIX_FMT_YUV420P : + avctx->pix_fmt); + + ret = convert_to_cuda_video_chroma_format(probed_pix_fmt, &probed_chroma_format); + if (ret < 0) { + const char * pix_fmt_name = av_get_pix_fmt_name(probed_pix_fmt); + pix_fmt_name || (pix_fmt_name = "unknown"); + av_log(avctx, AV_LOG_ERROR, "pixel format is not supported: %s\n", pix_fmt_name); + return ret; + } + probed_width = avctx->coded_width ? avctx->coded_width : 1280; + probed_height = avctx->coded_height ? avctx->coded_height : 720; + // Accelerated transcoding scenarios with 'ffmpeg' require that the // pix_fmt be set to AV_PIX_FMT_CUDA early. The sw_pix_fmt, and the // pix_fmt for non-accelerated transcoding, do not need to be correct @@ -824,7 +875,10 @@ static av_cold int cuvid_decode_init(AVCodecContext *avctx) if (ret < 0) goto error; - ret = cuvid_test_dummy_decoder(avctx, &ctx->cuparseinfo); + ret = cuvid_test_dummy_decoder(avctx, &ctx->cuparseinfo, + probed_chroma_format, + probed_width, + probed_height); if (ret < 0) goto error;