From patchwork Wed May 22 18:03:00 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Zhao Zhili X-Patchwork-Id: 49151 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a59:542:0:b0:460:55fa:d5ed with SMTP id 63csp550175vqf; Wed, 22 May 2024 11:03:59 -0700 (PDT) X-Forwarded-Encrypted: i=2; AJvYcCVRSE/MFopivZ5hfLFXOoikaJj9zVr++GZbY/WLAHMHsvHE4yQfXK8bVKidl6yw/j9DrrlptnmkFflGhZsFwQFyC0st07Jr46TYyQ== X-Google-Smtp-Source: AGHT+IGeWQwiXTAbjXsJ4+edBJS32XtrMFiRajMzqyFfHK7HpJIuhJtrdc/dBFoexr/tQH6Ucubt X-Received: by 2002:a2e:9ad6:0:b0:2e2:72a7:8440 with SMTP id 38308e7fff4ca-2e9495404c1mr22818311fa.41.1716401038835; Wed, 22 May 2024 11:03:58 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1716401038; cv=none; d=google.com; s=arc-20160816; b=PTJ3ie00mjKITrk7Or5MM38yNjEblBn1XOholo8W2XFLONtejjN+tAuhs5jALebH5L S9UQ7gku0v1jLQUEQkj8pSe7QHXIP+iLy8rS7iTMOFgyhTj3lcjkUwHpTdpylMKz+g0s fmVr7CoSJdEKeq8VDJS92z16FDEO+1hZK3DtO8i6xwM7ZFZXAGHA7+fDVDap26fWAYV5 PcJ+5LwZcoayAyYlC7tmGNA3yfRRTig2hafmsIDMWeDwQaBiNVyjetkPX+ou5YUT3VsM Vux28qf1mjSoPKz+f/+F/LNLb7YrcGfxO/eu40bJf46OETapQLTgqcsBGYDouEGT9kUi 40XQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:content-transfer-encoding:cc:reply-to :list-subscribe:list-help:list-post:list-archive:list-unsubscribe :list-id:precedence:subject:mime-version:date:to:from:message-id :dkim-signature:delivered-to; bh=RZL22Sj6CnE414Yoj2pbyZcv2SK0q3vRGS5hqcGamck=; fh=HnHYuZ9XgUo86ZRXTLWWmQxhslYEI9B9taZ5X1DLFfc=; b=ja1EzBSsl6pfytXXbgz31QgNMQIWuKD0aVk0498W3vZQnYhe4u1pUT8JQHRPEbI2mL rGjO6zjXSjNocP9fpP/bEWEYf5PEern5rFJ10u6F4snNNE4lrpvhdLfzaAxBdCpcgxlZ 2FR504vZ/i33Hji7Bzs9go2+awgiHmDGBcjrIZhNUZOIla1GjPuOm6KFYUgjNUXPv29N /l+M3j5hyokk9VPYmMtwFycbij9fWNhWjFhOjaWLbI9jmcMQr7AOcdP/3deZRKmA5mcV 3KuXctvAvA1LA653to6jCZbKFQH+Y+Nh+zUPMh8m8l5Z1BczLwCiGDcryFROEyKqcaC8 RoLg==; dara=google.com ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@foxmail.com header.s=s201512 header.b=X4D3HEPT; 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=foxmail.com Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id a640c23a62f3a-a5cdb2880a3si794413766b.627.2024.05.22.11.03.46; Wed, 22 May 2024 11:03:58 -0700 (PDT) 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=@foxmail.com header.s=s201512 header.b=X4D3HEPT; 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=foxmail.com Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id B6C2868D36D; Wed, 22 May 2024 21:03:41 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from out162-62-57-210.mail.qq.com (out162-62-57-210.mail.qq.com [162.62.57.210]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id CFBAE68D1CA for ; Wed, 22 May 2024 21:03:32 +0300 (EEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=foxmail.com; s=s201512; t=1716401003; bh=eF2k1w7VBnbt04YWsOv7BL+a+v4RxiXQaEOFiLVSv6U=; h=From:To:Cc:Subject:Date; b=X4D3HEPT8KKq1wdXf6hFBWV0MkeQeSuY16DMsKuh5x68fM9tPw/c7aYeC7zzeiStl 2WUHsa/SOTW42IErFyoOtzmbgC7cPzkpRsk1FaoaRej94Mcg24gQGwppcV42CXWwla +3PmsfKYfChL3gri2pppvDYJM4OnOV4AKx0j3XBE= Received: from localhost.localdomain ([113.118.103.69]) by newxmesmtplogicsvrszc5-2.qq.com (NewEsmtp) with SMTP id D5B2A53; Thu, 23 May 2024 02:03:21 +0800 X-QQ-mid: xmsmtpt1716401001th84x970g Message-ID: X-QQ-XMAILINFO: NafziRg7Bx69eZrfGbDKQhqUjc7lT7C7HIflc8wjVFhk6v3MpxhOt4B5tAVAPS IUL+ZA8d9xv3IXA+zi6VH2KGHH/zS5tYIA55Xgn/TKnoXl77o78nSZcQL7gpkeeQXALXq6dQo9PI fApdrofRnHcamU9ObJQ+FWQMoY0dAFCdzK5BZB92B8JkVimk4S0SO9mOrPLdWpYp0Kt9kWP6iZ4f vBWvdLagJ+JNIpxGvSVtRITtGAdpdXlu5JG5rF+rv4RL+Jkt/ImsS16XhSOCkkBDDy/Bfij06YL/ kvI2S7znnTwRWKiZX/rnx+cNtDKHT9UNUl8oR8GKnqYpCJrqhq4EaX+G1qnMf/YRYZjF2uZCCrSN CwMYvax6bZ0nQh7Lgx/0ahXKQ2AYXKC2KKASOE032300ikZWfY2TXhZ8A+sxj8yVDc8m6+wmnX1K zceyO7vvSiYaK/qpFT+8AuSpSK4+UKkV9rqNaAesJXjLZJ/mhdiXaVl+noxLlmukXUkvjvJMheO4 ICFXy0WIGUhih2yYIipXcRhb8I5Hf7oZuIBLk8xcUgxyln2xpurDWeBI8qH6UAmjH71HhWl0MTCH 8YLn8HjdSmh5pi/t9SWIBbjx0aOFYVi8Hqt04p+7Hnmc6uwW4FyA8H9kN80YPJgzFJjq5kqaiVOt evxhRzDfgdm5XoVigQLrJ+xQ9Wz6DmoB9HMJM0AksN9r7Jsd9B5btyDFLX78pEgFOgkPPXWZZgev VA9M77WFtJqPK1m1XUAOdQ1B+q6okWeBDwBpn4TN/mrtoOiMIngUIGSYGuajVCtO/CU7Tf8KWhq/ UcztrMu3K184kYsOMJBUyRXT2aWjqXlNTsHtlZKxVHf+8ejXYw4ymBCHf1UO75prTSCUIbjHtCiT mjl35i+OvYi55p+cLcxKMWXh/5BLuj00zcr0ZxNc6d9ZvcLm5DT7v2N+ANv6rPMGcUw9QAtIm0ap bUHVL/OSej6AioXLzjNqltK1YRZA83H/VxpXwbzho= X-QQ-XMRINFO: NyFYKkN4Ny6FSmKK/uo/jdU= From: Zhao Zhili To: ffmpeg-devel@ffmpeg.org Date: Thu, 23 May 2024 02:03:00 +0800 X-OQ-MSGID: <20240522180300.409959-1-quinkblack@foxmail.com> X-Mailer: git-send-email 2.34.1 MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH] avcodec/h265_metadata: Add option to set width/height after crop X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.29 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: Zhao Zhili Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" X-TUID: mfp/WrC3tYFo From: Zhao Zhili It's a common usecase to request a video size after crop. Before this patch, user must know the video size before crop, then set crop_right/crop_bottom accordingly. Since HEVC can have different CTU size, it's not easy to get/deduce the video size before crop. With the new width/height options, there is no such requirement. Signed-off-by: Zhao Zhili --- doc/bitstream_filters.texi | 4 ++ libavcodec/bsf/h265_metadata.c | 101 ++++++++++++++++++++++++++++++++- libavcodec/version.h | 2 +- 3 files changed, 103 insertions(+), 4 deletions(-) diff --git a/doc/bitstream_filters.texi b/doc/bitstream_filters.texi index 3d4dda04fc..c03f04f858 100644 --- a/doc/bitstream_filters.texi +++ b/doc/bitstream_filters.texi @@ -456,6 +456,10 @@ will replace the current ones if the stream is already cropped. These fields are set in pixels. Note that some sizes may not be representable if the chroma is subsampled (H.265 section 7.4.3.2.1). +@item width +@item height +Set width and height after crop. + @item level Set the level in the VPS and SPS. See H.265 section A.4 and tables A.6 and A.7. diff --git a/libavcodec/bsf/h265_metadata.c b/libavcodec/bsf/h265_metadata.c index c9e1cc3eed..eba00c20d5 100644 --- a/libavcodec/bsf/h265_metadata.c +++ b/libavcodec/bsf/h265_metadata.c @@ -58,6 +58,8 @@ typedef struct H265MetadataContext { int crop_right; int crop_top; int crop_bottom; + int width; + int height; int level; int level_guess; @@ -187,12 +189,94 @@ static int h265_metadata_update_vps(AVBSFContext *bsf, return 0; } +static int h265_metadata_deduce_crop(AVBSFContext *bsf, const H265RawSPS *sps, + int *crop_left, int *crop_right, + int *crop_top, int *crop_bottom) +{ + const H265MetadataContext *ctx = bsf->priv_data; + int left = ctx->crop_left; + int right = ctx->crop_right; + int top = ctx->crop_top; + int bottom = ctx->crop_bottom; + + if (ctx->width > 0) { + if (ctx->width > sps->pic_width_in_luma_samples) { + av_log(bsf, AV_LOG_ERROR, + "The width option value %d is larger than picture width %d\n", + ctx->width, sps->pic_width_in_luma_samples); + return AVERROR(EINVAL); + } + + if (left < 0) { + if (right > 0) + left = sps->pic_width_in_luma_samples - ctx->width - right; + else + left = 0; + } + + if (right < 0) + right = sps->pic_width_in_luma_samples - ctx->width - left; + + if (left < 0 || right < 0 || (left + right + ctx->width) != + sps->pic_width_in_luma_samples) { + av_log(bsf, AV_LOG_ERROR, + "Invalid value for crop_left %d, crop_right %d, width after " + "crop %d, with picture width %d\n", + ctx->crop_left, ctx->crop_right, ctx->width, + sps->pic_width_in_luma_samples); + return AVERROR(EINVAL); + } + } + + if (ctx->height > 0) { + if (ctx->height > sps->pic_height_in_luma_samples) { + av_log(bsf, AV_LOG_ERROR, + "The height option value %d is larger than picture height %d\n", + ctx->height, sps->pic_height_in_luma_samples); + return AVERROR(EINVAL); + } + + if (top < 0) { + if (bottom > 0) + top = sps->pic_height_in_luma_samples - ctx->height - bottom; + else + top = 0; + } + + if (bottom < 0) + bottom = sps->pic_height_in_luma_samples - ctx->height - top; + + if (top < 0 || bottom < 0 || (top + bottom + ctx->height) != + sps->pic_height_in_luma_samples) { + av_log(bsf, AV_LOG_ERROR, + "Invalid value for crop_top %d, crop_bottom %d, height after " + "crop %d, with picture height %d\n", + ctx->crop_top, ctx->crop_bottom, ctx->height, + sps->pic_height_in_luma_samples); + return AVERROR(EINVAL); + } + } + + *crop_left = left; + *crop_right = right; + *crop_top = top; + *crop_bottom = bottom; + + return 0; +} + static int h265_metadata_update_sps(AVBSFContext *bsf, H265RawSPS *sps) { H265MetadataContext *ctx = bsf->priv_data; int need_vui = 0; int crop_unit_x, crop_unit_y; + /* Use local variables to avoid modifying context fields in case of video + * resolution changed. Crop doesn't work well with resolution change, this + * is the best we can do. + */ + int crop_left, crop_right, crop_top, crop_bottom; + int ret; if (ctx->sample_aspect_ratio.num && ctx->sample_aspect_ratio.den) { int num, den, i; @@ -289,6 +373,11 @@ static int h265_metadata_update_sps(AVBSFContext *bsf, } } + ret = h265_metadata_deduce_crop(bsf, sps, &crop_left, &crop_right, + &crop_top, &crop_bottom); + if (ret < 0) + return ret; + if (sps->separate_colour_plane_flag || sps->chroma_format_idc == 0) { crop_unit_x = 1; crop_unit_y = 1; @@ -297,14 +386,14 @@ static int h265_metadata_update_sps(AVBSFContext *bsf, crop_unit_y = 1 + (sps->chroma_format_idc < 2); } #define CROP(border, unit) do { \ - if (ctx->crop_ ## border >= 0) { \ - if (ctx->crop_ ## border % unit != 0) { \ + if (crop_ ## border >= 0) { \ + if (crop_ ## border % unit != 0) { \ av_log(bsf, AV_LOG_ERROR, "Invalid value for crop_%s: " \ "must be a multiple of %d.\n", #border, unit); \ return AVERROR(EINVAL); \ } \ sps->conf_win_ ## border ## _offset = \ - ctx->crop_ ## border / unit; \ + crop_ ## border / unit; \ sps->conformance_window_flag = 1; \ } \ } while (0) @@ -453,6 +542,12 @@ static const AVOption h265_metadata_options[] = { { "crop_bottom", "Set bottom border crop offset", OFFSET(crop_bottom), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, HEVC_MAX_HEIGHT, FLAGS }, + { "width", "Set width after crop", + OFFSET(width), AV_OPT_TYPE_INT, + { .i64 = -1 }, -1, HEVC_MAX_WIDTH, FLAGS }, + { "height", "Set height after crop", + OFFSET(height), AV_OPT_TYPE_INT, + { .i64 = -1 }, -1, HEVC_MAX_HEIGHT, FLAGS }, { "level", "Set level (tables A.6 and A.7)", OFFSET(level), AV_OPT_TYPE_INT, diff --git a/libavcodec/version.h b/libavcodec/version.h index 3d2de546b3..f9b09b4b25 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -30,7 +30,7 @@ #include "version_major.h" #define LIBAVCODEC_VERSION_MINOR 5 -#define LIBAVCODEC_VERSION_MICRO 104 +#define LIBAVCODEC_VERSION_MICRO 105 #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ LIBAVCODEC_VERSION_MINOR, \