From patchwork Sun Feb 12 19:51:01 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: =?utf-8?q?Miroslav_Sluge=C5=88?= X-Patchwork-Id: 2526 Delivered-To: ffmpegpatchwork@gmail.com Received: by 10.103.89.21 with SMTP id n21csp597142vsb; Sun, 12 Feb 2017 11:51:17 -0800 (PST) X-Received: by 10.28.185.77 with SMTP id j74mr16262289wmf.76.1486929077170; Sun, 12 Feb 2017 11:51:17 -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 e13si10938985wrc.236.2017.02.12.11.51.16; Sun, 12 Feb 2017 11:51:17 -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=@email.cz; dkim=neutral (body hash did not verify) header.i=@email.cz; 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=email.cz Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 5F706689B97; Sun, 12 Feb 2017 21:51:09 +0200 (EET) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mxf2.seznam.cz (mxf2.seznam.cz [77.75.76.123]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 1BB6C680CD1 for ; Sun, 12 Feb 2017 21:51:03 +0200 (EET) Received: from email.seznam.cz by email-smtpc7a.ng.seznam.cz (email-smtpc7a.ng.seznam.cz [10.23.10.195]) id 29f26f9a1d25778629604697; Sun, 12 Feb 2017 20:51:04 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=email.cz; s=beta; t=1486929064; bh=DDv0PQY+DhW/tFsFmPeC6dgCNSswZVispV2s6Rvjjn0=; h=DKIM-Signature:Received:From:Subject:To:Message-ID:Date: User-Agent:MIME-Version:Content-Type; b=obxm+MqSILD9XucAuxui/CKJlOTKnfmPCPt8DV/2+xcb6xLCkn/AYjvE+eSer6o7u M8G8SY2Q0IFDl0jwzQANKOsRt5ilKa8qe0PNGla4adJnFHBGwjSpLEazjh2+wwKFtm xO3wOiHZKklde839hRq6ho6plR6mK64XeN4OWGvU= DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=email.cz; s=beta; t=1486929064; bh=DDv0PQY+DhW/tFsFmPeC6dgCNSswZVispV2s6Rvjjn0=; h=Received:From:Subject:To:Message-ID:Date:User-Agent:MIME-Version: Content-Type; b=WFsNNapCnVOPe789KA1/l2KYB4NdNOJeVa0J2myIRlWSO16Y+YIYZjuTMcOGo/wkM Vca7pe2Keq1wT460F6dDenSxhwEvHzBZtrVtPuitoN5Jx07XX8P5Vo6FwNQUyzG6Fx xXZqBABy5/SOi7ZDuzl9xtr4WfjOBJz7zeaRm1ys= Received: from [192.168.0.6] (ip-94-113-140-7.net.upcbroadband.cz [94.113.140.7]) by email-relay20.ng.seznam.cz (Seznam SMTPD 1.3.56) with ESMTP; Sun, 12 Feb 2017 20:51:02 +0100 (CET) From: =?UTF-8?Q?Miroslav_Sluge=c5=88?= To: ffmpeg-devel@ffmpeg.org Message-ID: <58A0BCA5.7030009@email.cz> Date: Sun, 12 Feb 2017 20:51:01 +0100 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:38.0) Gecko/20100101 Thunderbird/38.0.1 MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH] (for discussion): cuvid: allow to crop and resize in decoder 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 Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" This patch is for discussion only, not ready to commit yet. 1. Cuvid decoder actualy support scaling input to requested resolution without any performance penalty (like libnpp does), so this patch is proof of concept that it is working like expected. 2. Cuvid also supports cropping, but from tests only in 4px steps, this is also very nice, because hwaccel cuvid hasn't any cropping filter. Anybody feel free to adopt this patch and modify it for final commit. From 9f5dfd6e9cabd3d419a3a58f7bfa3b3c1e179638 Mon Sep 17 00:00:00 2001 From: Miroslav Slugen Date: Sun, 12 Feb 2017 20:29:34 +0100 Subject: [PATCH 1/1] cuvid: add resize and crop futures --- ffmpeg.h | 2 ++ ffmpeg_opt.c | 12 +++++++ libavcodec/cuvid.c | 95 ++++++++++++++++++++++++++++++++++++++++++++++-------- 3 files changed, 96 insertions(+), 13 deletions(-) diff --git a/ffmpeg.h b/ffmpeg.h index 85a8f18..0374f11 100644 --- a/ffmpeg.h +++ b/ffmpeg.h @@ -132,6 +132,8 @@ typedef struct OptionsContext { int nb_hwaccel_output_formats; SpecifierOpt *autorotate; int nb_autorotate; + SpecifierOpt *resize; + int nb_resize; /* output options */ StreamMap *stream_maps; diff --git a/ffmpeg_opt.c b/ffmpeg_opt.c index 6a47d32..fcf4792 100644 --- a/ffmpeg_opt.c +++ b/ffmpeg_opt.c @@ -659,6 +659,7 @@ static void add_input_streams(OptionsContext *o, AVFormatContext *ic) char *codec_tag = NULL; char *next; char *discard_str = NULL; + char *resize_str = NULL; const AVClass *cc = avcodec_get_class(); const AVOption *discard_opt = av_opt_find(&cc, "skip_frame", NULL, 0, 0); @@ -722,6 +723,14 @@ static void add_input_streams(OptionsContext *o, AVFormatContext *ic) case AVMEDIA_TYPE_VIDEO: if(!ist->dec) ist->dec = avcodec_find_decoder(par->codec_id); + + MATCH_PER_STREAM_OPT(resize, str, resize_str, ic, st); + if (resize_str) { + av_parse_video_size(&ist->dec_ctx->width, &ist->dec_ctx->height, resize_str); + ist->dec_ctx->coded_width = ist->dec_ctx->width; + ist->dec_ctx->coded_height = ist->dec_ctx->height; + } + #if FF_API_EMU_EDGE if (av_codec_get_lowres(st->codec)) { av_codec_set_lowres(ist->dec_ctx, av_codec_get_lowres(st->codec)); @@ -3591,6 +3600,9 @@ const OptionDef options[] = { { "hwaccel_output_format", OPT_VIDEO | OPT_STRING | HAS_ARG | OPT_EXPERT | OPT_SPEC | OPT_INPUT, { .off = OFFSET(hwaccel_output_formats) }, "select output format used with HW accelerated decoding", "format" }, + { "resize", OPT_VIDEO | OPT_STRING | HAS_ARG | OPT_EXPERT | + OPT_SPEC | OPT_INPUT | OPT_OUTPUT, { .off = OFFSET(resize) }, + "resizer builtin input or output" }, #if CONFIG_VDA || CONFIG_VIDEOTOOLBOX { "videotoolbox_pixfmt", HAS_ARG | OPT_STRING | OPT_EXPERT, { &videotoolbox_pixfmt}, "" }, #endif diff --git a/libavcodec/cuvid.c b/libavcodec/cuvid.c index a2e125d..7370ed1 100644 --- a/libavcodec/cuvid.c +++ b/libavcodec/cuvid.c @@ -21,6 +21,7 @@ #include "compat/cuda/dynlink_loader.h" +#include "libavutil/avstring.h" #include "libavutil/buffer.h" #include "libavutil/mathematics.h" #include "libavutil/hwcontext.h" @@ -43,6 +44,15 @@ typedef struct CuvidContext char *cu_gpu; int nb_surfaces; int drop_second_field; + char *crop; + char *resize; + + struct { + short left; + short top; + short right; + short bottom; + } offset; AVBufferRef *hwdevice; AVBufferRef *hwframe; @@ -57,6 +67,10 @@ typedef struct CuvidContext int internal_error; int decoder_flushing; + int width; + int height; + int coded_width; + int coded_height; cudaVideoCodec codec_type; cudaVideoChromaFormat chroma_format; @@ -105,6 +119,7 @@ static int CUDAAPI cuvid_handle_video_sequence(void *opaque, CUVIDEOFORMAT* form AVHWFramesContext *hwframe_ctx = (AVHWFramesContext*)ctx->hwframe->data; CUVIDDECODECREATEINFO cuinfo; int surface_fmt; + int width, height; enum AVPixelFormat pix_fmts[3] = { AV_PIX_FMT_CUDA, AV_PIX_FMT_NONE, // Will be updated below @@ -144,8 +159,8 @@ static int CUDAAPI cuvid_handle_video_sequence(void *opaque, CUVIDEOFORMAT* form avctx->pix_fmt = surface_fmt; - avctx->width = format->display_area.right; - avctx->height = format->display_area.bottom; + width = format->display_area.right - format->display_area.left; + height = format->display_area.bottom - format->display_area.top; ff_set_sar(avctx, av_div_q( (AVRational){ format->display_aspect_ratio.x, format->display_aspect_ratio.y }, @@ -174,8 +189,10 @@ static int CUDAAPI cuvid_handle_video_sequence(void *opaque, CUVIDEOFORMAT* form } if (ctx->cudecoder - && avctx->coded_width == format->coded_width - && avctx->coded_height == format->coded_height + && ctx->width == width + && ctx->height == height + && ctx->coded_width == format->coded_width + && ctx->coded_height == format->coded_height && ctx->chroma_format == format->chroma_format && ctx->codec_type == format->codec) return 1; @@ -204,11 +221,15 @@ static int CUDAAPI cuvid_handle_video_sequence(void *opaque, CUVIDEOFORMAT* form return 0; } - avctx->coded_width = format->coded_width; - avctx->coded_height = format->coded_height; - + ctx->width = width; + ctx->height = height; + ctx->coded_width = format->coded_width; + ctx->coded_height = format->coded_height; ctx->chroma_format = format->chroma_format; + avctx->coded_width = avctx->width; + avctx->coded_height = avctx->height; + memset(&cuinfo, 0, sizeof(cuinfo)); cuinfo.CodecType = ctx->codec_type = format->codec; @@ -228,15 +249,24 @@ static int CUDAAPI cuvid_handle_video_sequence(void *opaque, CUVIDEOFORMAT* form return 0; } - cuinfo.ulWidth = avctx->coded_width; - cuinfo.ulHeight = avctx->coded_height; - cuinfo.ulTargetWidth = cuinfo.ulWidth; - cuinfo.ulTargetHeight = cuinfo.ulHeight; + cuinfo.ulWidth = ctx->coded_width; + cuinfo.ulHeight = ctx->coded_height; + + /* cropping depends on original resolution */ + cuinfo.display_area.left = ctx->offset.left; + cuinfo.display_area.top = ctx->offset.top; + cuinfo.display_area.right = cuinfo.ulWidth - ctx->offset.right; + cuinfo.display_area.bottom = cuinfo.ulHeight - ctx->offset.bottom; + /* scaling to requested resolution */ + cuinfo.ulTargetWidth = avctx->width; + cuinfo.ulTargetHeight = avctx->height; + + /* aspect ratio conversion, 1:1, depends on scaled resolution */ cuinfo.target_rect.left = 0; cuinfo.target_rect.top = 0; - cuinfo.target_rect.right = cuinfo.ulWidth; - cuinfo.target_rect.bottom = cuinfo.ulHeight; + cuinfo.target_rect.right = cuinfo.ulTargetWidth; + cuinfo.target_rect.bottom = cuinfo.ulTargetHeight; cuinfo.ulNumDecodeSurfaces = ctx->nb_surfaces; cuinfo.ulNumOutputSurfaces = 1; @@ -636,6 +666,11 @@ static int cuvid_test_dummy_decoder(AVCodecContext *avctx, cuinfo.ulTargetWidth = cuinfo.ulWidth; cuinfo.ulTargetHeight = cuinfo.ulHeight; + cuinfo.display_area.left = 0; + cuinfo.display_area.top = 0; + cuinfo.display_area.right = cuinfo.ulWidth; + cuinfo.display_area.bottom = cuinfo.ulHeight; + cuinfo.target_rect.left = 0; cuinfo.target_rect.top = 0; cuinfo.target_rect.right = cuinfo.ulWidth; @@ -822,6 +857,38 @@ static av_cold int cuvid_decode_init(AVCodecContext *avctx) FFMIN(sizeof(ctx->cuparse_ext.raw_seqhdr_data), avctx->extradata_size)); } + ctx->offset.top = 0; + ctx->offset.bottom = 0; + ctx->offset.left = 0; + ctx->offset.right = 0; + if (ctx->crop) { + char *crop_str, *saveptr; + int crop_idx = 0; + crop_str = av_strdup(ctx->crop); + crop_str = av_strtok(crop_str, "x", &saveptr); + while (crop_str) { + switch (crop_idx++) { + case 0: + ctx->offset.top = atoi(crop_str); + break; + case 1: + ctx->offset.bottom = atoi(crop_str); + break; + case 2: + ctx->offset.left = atoi(crop_str); + break; + case 3: + ctx->offset.right = atoi(crop_str); + break; + default: + break; + } + crop_str = av_strtok(NULL, "x", &saveptr); + } + free(crop_str); + } + + ctx->cuparseinfo.ulMaxNumDecodeSurfaces = ctx->nb_surfaces; ctx->cuparseinfo.ulMaxDisplayDelay = 4; ctx->cuparseinfo.pUserData = avctx; @@ -934,6 +1001,8 @@ static const AVOption options[] = { { "gpu", "GPU to be used for decoding", OFFSET(cu_gpu), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, VD }, { "surfaces", "Maximum surfaces to be used for decoding", OFFSET(nb_surfaces), AV_OPT_TYPE_INT, { .i64 = 25 }, 0, INT_MAX, VD }, { "drop_second_field", "Drop second field when deinterlacing", OFFSET(drop_second_field), AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, VD }, + { "crop", "Crop (top)x(bottom)x(left)x(right)", OFFSET(crop), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, VD }, + { "resize", "Resize (width)x(height)", OFFSET(resize), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, VD }, { NULL } }; -- 2.1.4