From patchwork Fri Jan 22 20:21:33 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: simone@lisanet.de X-Patchwork-Id: 25117 Return-Path: X-Original-To: patchwork@ffaux-bg.ffmpeg.org Delivered-To: patchwork@ffaux-bg.ffmpeg.org Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org [79.124.17.100]) by ffaux.localdomain (Postfix) with ESMTP id 504BF44BE45 for ; Fri, 22 Jan 2021 22:28:09 +0200 (EET) Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 29A3A68A2B9; Fri, 22 Jan 2021 22:28:09 +0200 (EET) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from relay.yourmailgateway.de (relay.yourmailgateway.de [188.68.63.98]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id ADD2568A0BB for ; Fri, 22 Jan 2021 22:28:02 +0200 (EET) Received: from mors-relay-2501.netcup.net (localhost [127.0.0.1]) by mors-relay-2501.netcup.net (Postfix) with ESMTPS id 4DMrJL3fJZz6GbX for ; Fri, 22 Jan 2021 21:21:38 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=lisanet.de; s=key2; t=1611346898; bh=ZoJrUbUNhgkZA2YoGG1mb4EneBse7xzzQ0P4x8Sqw6E=; h=From:To:Cc:Subject:Date:From; b=bahVo28sduLHROhYVn3MiROZcbJZpJq6RZ1as+SD1QwRCRGFqFPhxo38vwoUMngSS klVsA7c1b2cvwrwBwKZ/7Dco3C6whK9+/QBEQkK8V26B7rv2AFFrk06B/1I2+PffDK js4usOt6IZkfnyVFaqs/4fXtwOVxs1hWZT8HdM68wA5LIS7pna11EvkzJi6ekNiAsQ UjwxRPjGCVxRZ3vBHmkLQ39An9WgS375v85OvChKjalfJxGRkXa5FuYztsUQZnB+sR kpM3/Kp3dZGHQqi3oUOVYdSY/ZwHL96DaqJ4l8JNSGGTYocjEvqywuTFlU9JE1mq+z WD+WQ+MsrOkEQ== Received: from policy01-mors.netcup.net (unknown [46.38.225.35]) by mors-relay-2501.netcup.net (Postfix) with ESMTPS id 4DMrJL3DJDz5Fk9 for ; Fri, 22 Jan 2021 21:21:38 +0100 (CET) X-Virus-Scanned: Debian amavisd-new at policy01-mors.netcup.net X-Spam-Flag: NO X-Spam-Score: -2.9 X-Spam-Level: X-Spam-Status: No, score=-2.9 required=6.31 tests=[ALL_TRUSTED=-1, BAYES_00=-1.9, SPF_PASS=-0.001, URIBL_BLOCKED=0.001] autolearn=ham autolearn_force=no Received: from mx2f68.netcup.net (unknown [10.243.12.53]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by policy01-mors.netcup.net (Postfix) with ESMTPS id 4DMrJK5hLrz8ss1 for ; Fri, 22 Jan 2021 21:21:37 +0100 (CET) Received: from localhost.localdomain (unknown [37.209.45.192]) by mx2f68.netcup.net (Postfix) with ESMTPSA id 5B049A77D3; Fri, 22 Jan 2021 21:21:36 +0100 (CET) Authentication-Results: mx2f68; spf=pass (sender IP is 37.209.45.192) smtp.mailfrom=simone@lisanet.de smtp.helo=localhost.localdomain Received-SPF: pass (mx2f68: connection is authenticated) From: simone@lisanet.de To: ffmpeg-devel@ffmpeg.org Date: Fri, 22 Jan 2021 21:21:33 +0100 Message-Id: <20210122202133.31519-1-simone@lisanet.de> X-Mailer: git-send-email 2.24.3 (Apple Git-128) MIME-Version: 1.0 X-PPP-Message-ID: <161134689651.10396.5534715132797845005@mx2f68.netcup.net> X-PPP-Vhost: lisanet.de X-NC-CID: uHIAzl2ofr7DTKgzw7zcQVfRCi8JJGf+cifFbskLi7kn Subject: [FFmpeg-devel] =?utf-8?q?=5BPATCH=5D_videotoolboxenc=3A_enable_cons?= =?utf-8?q?tant_quality_with_-q=3Av_on_Apple_Silicon_Macs_and_use_b-frames_f?= =?utf-8?q?=C3=BCr_HEVC_and_H264_and_b-pyramid_for_HEVC=2E?= 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: Simone Karin Lehmann Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" From: Simone Karin Lehmann Signed-off-by: Simone Karin Lehmann --- libavcodec/videotoolboxenc.c | 54 ++++++++++++++++++++++++++++-------- 1 file changed, 42 insertions(+), 12 deletions(-) diff --git a/libavcodec/videotoolboxenc.c b/libavcodec/videotoolboxenc.c index 400401550a..e8cbc9dd4d 100644 --- a/libavcodec/videotoolboxenc.c +++ b/libavcodec/videotoolboxenc.c @@ -224,7 +224,7 @@ typedef struct VTEncContext { int64_t require_sw; bool flushing; - bool has_b_frames; + int has_b_frames; bool warned_color_range; /* can't be bool type since AVOption will access it as int */ @@ -1014,6 +1014,12 @@ static int get_cv_ycbcr_matrix(AVCodecContext *avctx, CFStringRef *matrix) { return 0; } +// constant quality only on Macs with Apple Silicon +static bool vtenc_qscale_enabled(void) +{ + return TARGET_OS_OSX && TARGET_CPU_ARM64; +} + static int vtenc_create_encoder(AVCodecContext *avctx, CMVideoCodecType codec_type, CFStringRef profile_level, @@ -1025,7 +1031,9 @@ static int vtenc_create_encoder(AVCodecContext *avctx, VTEncContext *vtctx = avctx->priv_data; SInt32 bit_rate = avctx->bit_rate; SInt32 max_rate = avctx->rc_max_rate; + Float32 quality = avctx->global_quality / FF_QP2LAMBDA; CFNumberRef bit_rate_num; + CFNumberRef quality_num; CFNumberRef bytes_per_second; CFNumberRef one_second; CFArrayRef data_rate_limits; @@ -1056,15 +1064,33 @@ static int vtenc_create_encoder(AVCodecContext *avctx, return AVERROR_EXTERNAL; } - bit_rate_num = CFNumberCreate(kCFAllocatorDefault, - kCFNumberSInt32Type, - &bit_rate); - if (!bit_rate_num) return AVERROR(ENOMEM); + if (avctx->flags & AV_CODEC_FLAG_QSCALE && !vtenc_qscale_enabled()) { + av_log(avctx, AV_LOG_ERROR, "Error: -q:v qscale not available for encoder. Use -b:v bitrate instead.\n"); + return AVERROR_EXTERNAL; + } + + if (avctx->flags & AV_CODEC_FLAG_QSCALE) { + quality = quality >= 100 ? 1.0 : quality / 100; + quality_num = CFNumberCreate(kCFAllocatorDefault, + kCFNumberFloat32Type, + &quality); + if (!quality_num) return AVERROR(ENOMEM); - status = VTSessionSetProperty(vtctx->session, - kVTCompressionPropertyKey_AverageBitRate, - bit_rate_num); - CFRelease(bit_rate_num); + status = VTSessionSetProperty(vtctx->session, + kVTCompressionPropertyKey_Quality, + quality_num); + CFRelease(quality_num); + } else { + bit_rate_num = CFNumberCreate(kCFAllocatorDefault, + kCFNumberSInt32Type, + &bit_rate); + if (!bit_rate_num) return AVERROR(ENOMEM); + + status = VTSessionSetProperty(vtctx->session, + kVTCompressionPropertyKey_AverageBitRate, + bit_rate_num); + CFRelease(bit_rate_num); + } if (status) { av_log(avctx, AV_LOG_ERROR, "Error setting bitrate property: %d\n", status); @@ -1333,6 +1359,7 @@ static int vtenc_configure_encoder(AVCodecContext *avctx) } vtctx->codec_id = avctx->codec_id; + avctx->max_b_frames = 16; if (vtctx->codec_id == AV_CODEC_ID_H264) { vtctx->get_param_set_func = CMVideoFormatDescriptionGetH264ParameterSetAtIndex; @@ -1340,7 +1367,7 @@ static int vtenc_configure_encoder(AVCodecContext *avctx) vtctx->has_b_frames = avctx->max_b_frames > 0; if(vtctx->has_b_frames && vtctx->profile == H264_PROF_BASELINE){ av_log(avctx, AV_LOG_WARNING, "Cannot use B-frames with baseline profile. Output will not contain B-frames.\n"); - vtctx->has_b_frames = false; + vtctx->has_b_frames = 0; } if (vtctx->entropy == VT_CABAC && vtctx->profile == H264_PROF_BASELINE) { @@ -1353,6 +1380,8 @@ static int vtenc_configure_encoder(AVCodecContext *avctx) vtctx->get_param_set_func = compat_keys.CMVideoFormatDescriptionGetHEVCParameterSetAtIndex; if (!vtctx->get_param_set_func) return AVERROR(EINVAL); if (!get_vt_hevc_profile_level(avctx, &profile_level)) return AVERROR(EINVAL); + // HEVC has b-byramid + vtctx->has_b_frames = avctx->max_b_frames > 0 ? 2 : 0; } enc_info = CFDictionaryCreateMutable( @@ -1448,7 +1477,8 @@ static av_cold int vtenc_init(AVCodecContext *avctx) if (!status && has_b_frames_cfbool) { //Some devices don't output B-frames for main profile, even if requested. - vtctx->has_b_frames = CFBooleanGetValue(has_b_frames_cfbool); + // HEVC has b-pyramid + vtctx->has_b_frames = (CFBooleanGetValue(has_b_frames_cfbool) && avctx->codec_id == AV_CODEC_ID_HEVC) ? 2 : 1; CFRelease(has_b_frames_cfbool); } avctx->has_b_frames = vtctx->has_b_frames; @@ -2356,7 +2386,7 @@ static av_cold int vtenc_frame( if (vtctx->frame_ct_in == 0) { vtctx->first_pts = frame->pts; - } else if(vtctx->frame_ct_in == 1 && vtctx->has_b_frames) { + } else if(vtctx->frame_ct_in == vtctx->has_b_frames) { vtctx->dts_delta = frame->pts - vtctx->first_pts; }