From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from ffbox0-bg.ffmpeg.org (ffbox0-bg.ffmpeg.org [79.124.17.100]) by master.gitmailbox.com (Postfix) with ESMTPS id 2D4C2496D6 for ; Thu, 20 Nov 2025 03:13:26 +0000 (UTC) Authentication-Results: ffbox; dkim=fail (body hash mismatch (got b'2v4vOyD7wHA4xl0PW3h/PnbllPeNuckXM0CQeMUeoIU=', expected b'vzKp0j7HYTR1xttFNDyghDulFoF6ahWz0Ua7WNcpSVU=')) header.d=ffmpeg.org header.i=@ffmpeg.org header.a=rsa-sha256 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ffmpeg.org; i=@ffmpeg.org; q=dns/txt; s=mail; t=1763608394; h=mime-version : to : date : message-id : reply-to : subject : list-id : list-archive : list-archive : list-help : list-owner : list-post : list-subscribe : list-unsubscribe : from : cc : content-type : content-transfer-encoding : from; bh=2v4vOyD7wHA4xl0PW3h/PnbllPeNuckXM0CQeMUeoIU=; b=kRA76lQvfU8OWom/1r3sU9qpOuHdH9DigVsmX+pNZZWIjDewjJRFO3J9hvQpxrULUk1dq SiXdm/KrVqHlxZ1O9hQY2hmO4ubaO2HuMDLAZupuyIvpFxj9Abpwd8sFFX6RdW4Sf1NiU3o /XZVbMM2tpsWmAGl1rZo4dmOZQGKSj8gQY8loKOjq3fbo0gX5yTkvL9AZ54/18sh+xSliZs MhOlylJRWOqNQIgNqRDaZ2b/zXzGjeDiYDMjv1sH/dB6P3aDO1nrTfJ8XV3woNo7SetJrpN D0i6u0esEwMhBaBgzQ3ASE0qIOSuZG7IGgis1LXIKKyDrKnDbXxvnhi6Q9dg== Received: from [172.19.0.2] (unknown [172.19.0.2]) by ffbox0-bg.ffmpeg.org (Postfix) with ESMTP id 02BF368FED6; Thu, 20 Nov 2025 05:13:14 +0200 (EET) ARC-Seal: i=1; cv=none; a=rsa-sha256; d=ffmpeg.org; s=arc; t=1763608392; b=ISAc7Jmjb6qxp0iJ4BdleJnL4Jlqt4hXgA7O5Wof1+FT0ua/AtrrnHaEOYJzzm8iYSrYm KLP39g9t6k/AqHGcZKlZ7heKF1BpU5hnKKaeNQpKWQAlhRRBF9Q5mKbFae2Q9awo7C/dqjk s567+2SQyiao96tE7fhCiGXKwvUx1kPZfv49ChJ5X2bRLVt3aJqbS755NjUNDS4u4E8+zjY hFIYrNXg+m9AvyIVRLNeqfc+vTfHxdN2OqlFqvV7lYN7ohGrTnn5tJ5n4d+v1Xqc0WdTfpB PDH0gRvXshC8ei0+r5UozDb2LRzs6chcqz73kBYfbhwsrrpUPdOIhIReYNpg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=ffmpeg.org; s=arc; t=1763608392; h=from : sender : reply-to : subject : date : message-id : to : cc : mime-version : content-type : content-transfer-encoding : content-id : content-description : resent-date : resent-from : resent-sender : resent-to : resent-cc : resent-message-id : in-reply-to : references : list-id : list-help : list-unsubscribe : list-subscribe : list-post : list-owner : list-archive; bh=MpN00Ai+mCS80nYHVmYMfxHM4poo8oX7WI4c5H2xd5Y=; b=W80XjJ09PVXbp4C3YbrcQ8dn154VykEYRaJrTvIiHziHRewi9Vp4I30Yz3lctl66lMtaO bRYgjVfupBVELEL8kh+tQ2bDRyW/yiJVGw3FdNBfH8tDGk4twaX4GEe2nUg8svB89NWvnhj vGM0LASXUu3A0poHQ9+Avnv9w3aVwSUFBxMwnsRqhItD8sfuyIJ9Fle5nCtGRXNkReyKYr+ pgbUmzKuKvPhJixguzxbK3c13T+8TkredYzO2yZ9hCifB2L/fUkBFYKowlKLVf2VQe0NzwH WjE3SwXgj/ktgxcrei66okjxST2oqMsjkRGMkN2A0MGXk2VTflbuXyGnwSEQ== ARC-Authentication-Results: i=1; ffmpeg.org; dkim=pass header.d=ffmpeg.org header.i=@ffmpeg.org; arc=none; dmarc=pass header.from=ffmpeg.org policy.dmarc=quarantine Authentication-Results: ffmpeg.org; dkim=pass header.d=ffmpeg.org header.i=@ffmpeg.org; arc=none (Message is not ARC signed); dmarc=pass (Used From Domain Record) header.from=ffmpeg.org policy.dmarc=quarantine DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ffmpeg.org; i=@ffmpeg.org; q=dns/txt; s=mail; t=1763608384; h=content-type : mime-version : content-transfer-encoding : from : to : reply-to : subject : date : from; bh=vzKp0j7HYTR1xttFNDyghDulFoF6ahWz0Ua7WNcpSVU=; b=wrPukg6Cn/E8ImlA7+9QwtHcRPteMtnU5yka5c0UT/sV6SQIM4aMsbn+Q9yVifFm8h+CF zqOi1jOTDhizcIdML42NmX92ywFtZtHbGxvhISteSmp0xgDmAV47Yph5/K7ieTPn2Mpf3I8 LbaJOvedteLVuYBA7f9lcKbES5zDLjafjew9u8KwFaM6gVVWAUMWqE4WDGtGpPvVAkB9pa+ 2qqk99J+O5Up6q0QvPRVIPCLv8zoBoM4bFH/zqHCBzHV+8czCxvubOZvc/ecp/7XcMuecio MSt6xO210JEO0xgNC3L+1yiV1Ad8ajrGCqOVn2okbtOGJhuDBfJ0xya0ZPvQ== Received: from 188d6d40ca7a (code.ffmpeg.org [188.245.149.3]) by ffbox0-bg.ffmpeg.org (Postfix) with ESMTPS id 54BDB68FE6C for ; Thu, 20 Nov 2025 05:13:04 +0200 (EET) MIME-Version: 1.0 To: ffmpeg-devel@ffmpeg.org Date: Thu, 20 Nov 2025 03:13:04 -0000 Message-ID: <176360838449.59.13524077322116155863@2cb04c0e5124> Message-ID-Hash: W3QRXYLSHZNOQ7O2XUFEPAJNT7CFCDRJ X-Message-ID-Hash: W3QRXYLSHZNOQ7O2XUFEPAJNT7CFCDRJ X-MailFrom: code@ffmpeg.org X-Mailman-Rule-Hits: nonmember-moderation X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; loop; banned-address; header-match-ffmpeg-devel.ffmpeg.org-0; header-match-ffmpeg-devel.ffmpeg.org-1; header-match-ffmpeg-devel.ffmpeg.org-2; header-match-ffmpeg-devel.ffmpeg.org-3; emergency; member-moderation X-Mailman-Version: 3.3.10 Precedence: list Reply-To: FFmpeg development discussions and patches Subject: [FFmpeg-devel] [PATCH] [release/8.0]: videotoolbox: fix crash with negative linesize and move videotoolbox filter to the right place (PR #20975) List-Id: FFmpeg development discussions and patches Archived-At: Archived-At: List-Archive: List-Archive: List-Help: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: From: Zhao Zhili via ffmpeg-devel Cc: Zhao Zhili Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Archived-At: List-Archive: List-Post: PR #20975 opened by Zhao Zhili (quink) URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/20975 Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/20975.patch >>From e74cabe39e131684a1139cbc128bbfec2241c738 Mon Sep 17 00:00:00 2001 From: Zhao Zhili Date: Sat, 15 Nov 2025 23:58:14 +0800 Subject: [PATCH 1/3] doc/filters: add section for VideoToolbox filter Move scale_vt and transpose_vt to this section. transpose_vt was incorrectly placed in the Vulkan section previously. (cherry picked from commit 925282fafcf844eb9ea9095a80eba81009d85b3f) --- doc/filters.texi | 169 ++++++++++++++++++++++++++++------------------- 1 file changed, 100 insertions(+), 69 deletions(-) diff --git a/doc/filters.texi b/doc/filters.texi index 0b0663cd9d..f0962755df 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -21294,27 +21294,6 @@ If the specified expression is not valid, it is kept at its current value. @end table -@section scale_vt - -Scale and convert the color parameters using VTPixelTransferSession. - -The filter accepts the following options: -@table @option -@item w -@item h -Set the output video dimension expression. Default value is the input dimension. - -@item color_matrix -Set the output colorspace matrix. - -@item color_primaries -Set the output color primaries. - -@item color_transfer -Set the output transfer characteristics. - -@end table - @section scharr Apply scharr operator to input video stream. @@ -28730,6 +28709,106 @@ drawbox=x=-t:y=0.5*(ih-iw/2.4)-t:w=iw+t*2:h=iw/2.4+t*2:t=2:c=red @c man end VAAPI VIDEO FILTERS +@chapter VideoToolbox Video Filters +@c man begin VIDEOTOOLBOX VIDEO FILTERS + +Below is a description of the currently available VideoToolbox video filters. + +VideoToolbox filter depends on VideoToolbox framework, and is auto detected +when building ffmpeg for an Apple platform such as macOS. Add +@code{--enable-videotoolbox} to configure if autodetect is disabled. + +@section scale_vt + +Scale and convert the color parameters using VTPixelTransferSession. + +The filter accepts the following options: +@table @option +@item w +@item h +Set the output video dimension expression. Default value is the input dimension. + +@item color_matrix +Set the output colorspace matrix. + +@item color_primaries +Set the output color primaries. + +@item color_transfer +Set the output transfer characteristics. + +@end table + +@subsection Examples + +@itemize +@item +Perform HDR to SDR conversion, and scale to half size of input +@example +ffmpeg -hwaccel videotoolbox \ + -hwaccel_output_format videotoolbox_vld \ + -i hdr.mov \ + -c:v hevc_videotoolbox \ + -profile:v main \ + -b:v 3M \ + -vf scale_vt=w=iw/2:h=ih/2:color_matrix=bt709:color_primaries=bt709:color_transfer=bt709 \ + -c:a copy \ + -tag:v hvc1 \ + sdr.mp4 +@end example + +@end itemize + +@section transpose_vt + +Transpose rows with columns in the input video and optionally flip it. +For more in depth examples see the @ref{transpose} video filter, which shares mostly the same options. + +It accepts the following parameters: + +@table @option + +@item dir +Specify the transposition direction. + +Can assume the following values: +@table @samp +@item cclock_flip +Rotate by 90 degrees counterclockwise and vertically flip. (default) + +@item clock +Rotate by 90 degrees clockwise. + +@item cclock +Rotate by 90 degrees counterclockwise. + +@item clock_flip +Rotate by 90 degrees clockwise and vertically flip. + +@item hflip +Flip the input video horizontally. + +@item vflip +Flip the input video vertically. + +@end table + +@item passthrough +Do not apply the transposition if the input geometry matches the one +specified by the specified value. It accepts the following values: +@table @samp +@item none +Always apply transposition. (default) +@item portrait +Preserve portrait geometry (when @var{height} >= @var{width}). +@item landscape +Preserve landscape geometry (when @var{width} >= @var{height}). +@end table + +@end table + +@c man end VIDEOTOOLBOX VIDEO FILTERS + @chapter Vulkan Video Filters @c man begin VULKAN VIDEO FILTERS @@ -29031,54 +29110,6 @@ Default value is @code{0}. @end table -@section transpose_vt - -Transpose rows with columns in the input video and optionally flip it. -For more in depth examples see the @ref{transpose} video filter, which shares mostly the same options. - -It accepts the following parameters: - -@table @option - -@item dir -Specify the transposition direction. - -Can assume the following values: -@table @samp -@item cclock_flip -Rotate by 90 degrees counterclockwise and vertically flip. (default) - -@item clock -Rotate by 90 degrees clockwise. - -@item cclock -Rotate by 90 degrees counterclockwise. - -@item clock_flip -Rotate by 90 degrees clockwise and vertically flip. - -@item hflip -Flip the input video horizontally. - -@item vflip -Flip the input video vertically. - -@end table - -@item passthrough -Do not apply the transposition if the input geometry matches the one -specified by the specified value. It accepts the following values: -@table @samp -@item none -Always apply transposition. (default) -@item portrait -Preserve portrait geometry (when @var{height} >= @var{width}). -@item landscape -Preserve landscape geometry (when @var{width} >= @var{height}). -@end table - -@end table - @section transpose_vulkan Transpose rows with columns in the input video and optionally flip it. -- 2.49.1 >>From 5d72d77d730ec9451edb6487aeb344e8f3c793b9 Mon Sep 17 00:00:00 2001 From: Zhao Zhili Date: Tue, 18 Nov 2025 12:46:13 +0800 Subject: [PATCH 2/3] avcodec/videotoolboxenc: improve Lock/Unlock BaseAddress error handling 1. Fix continue after CVPixelBufferLockBaseAddress. 2. Remove redundant "Error: " in error message. (cherry picked from commit 0da15c93c8411f435b37ab7d504a650ee881cb0f) --- libavcodec/videotoolboxenc.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/libavcodec/videotoolboxenc.c b/libavcodec/videotoolboxenc.c index 729072c0b9..c9c4014a6b 100644 --- a/libavcodec/videotoolboxenc.c +++ b/libavcodec/videotoolboxenc.c @@ -2414,12 +2414,8 @@ static int copy_avframe_to_pixel_buffer(AVCodecContext *avctx, status = CVPixelBufferLockBaseAddress(cv_img, 0); if (status) { - av_log( - avctx, - AV_LOG_ERROR, - "Error: Could not lock base address of CVPixelBuffer: %d.\n", - status - ); + av_log(avctx, AV_LOG_ERROR, "Could not lock base address of CVPixelBuffer: %d.\n", status); + return AVERROR_EXTERNAL; } if (CVPixelBufferIsPlanar(cv_img)) { @@ -2481,7 +2477,7 @@ static int copy_avframe_to_pixel_buffer(AVCodecContext *avctx, status = CVPixelBufferUnlockBaseAddress(cv_img, 0); if (status) { - av_log(avctx, AV_LOG_ERROR, "Error: Could not unlock CVPixelBuffer base address: %d.\n", status); + av_log(avctx, AV_LOG_ERROR, "Could not unlock CVPixelBuffer base address: %d.\n", status); return AVERROR_EXTERNAL; } -- 2.49.1 >>From 84dedda9246a064e97ccacbc82d553c1ca4558ce Mon Sep 17 00:00:00 2001 From: Zhao Zhili Date: Tue, 18 Nov 2025 11:02:59 +0800 Subject: [PATCH 3/3] avcodec/videotoolboxenc: fix crash with negative linesize (cherry picked from commit 7049df14c83a89e2d32eb138feeb692170d24dc5) --- libavcodec/videotoolboxenc.c | 196 ++++++----------------------------- 1 file changed, 31 insertions(+), 165 deletions(-) diff --git a/libavcodec/videotoolboxenc.c b/libavcodec/videotoolboxenc.c index c9c4014a6b..ef32c81278 100644 --- a/libavcodec/videotoolboxenc.c +++ b/libavcodec/videotoolboxenc.c @@ -28,6 +28,7 @@ #include "libavutil/opt.h" #include "libavutil/avassert.h" #include "libavutil/avstring.h" +#include "libavutil/imgutils.h" #include "libavcodec/avcodec.h" #include "libavutil/pixdesc.h" #include "libavutil/hwcontext_videotoolbox.h" @@ -2328,89 +2329,20 @@ static int vtenc_cm_to_avpacket( return 0; } -/* - * contiguous_buf_size is 0 if not contiguous, and the size of the buffer - * containing all planes if so. - */ -static int get_cv_pixel_info( - AVCodecContext *avctx, - const AVFrame *frame, - int *color, - int *plane_count, - size_t *widths, - size_t *heights, - size_t *strides, - size_t *contiguous_buf_size) -{ - const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(avctx->pix_fmt); - VTEncContext *vtctx = avctx->priv_data; - int av_format = frame->format; - int av_color_range = avctx->color_range; - int i; - int range_guessed; - int status; - - if (!desc) - return AVERROR(EINVAL); - - status = get_cv_pixel_format(avctx, av_format, av_color_range, color, &range_guessed); - if (status) - return status; - - if (range_guessed) { - if (!vtctx->warned_color_range) { - vtctx->warned_color_range = true; - av_log(avctx, - AV_LOG_WARNING, - "Color range not set for %s. Using MPEG range.\n", - av_get_pix_fmt_name(av_format)); - } - } - - *plane_count = av_pix_fmt_count_planes(avctx->pix_fmt); - - for (i = 0; i < desc->nb_components; i++) { - int p = desc->comp[i].plane; - bool hasAlpha = (desc->flags & AV_PIX_FMT_FLAG_ALPHA); - bool isAlpha = hasAlpha && (p + 1 == *plane_count); - bool isChroma = (p != 0) && !isAlpha; - int shiftw = isChroma ? desc->log2_chroma_w : 0; - int shifth = isChroma ? desc->log2_chroma_h : 0; - widths[p] = (avctx->width + ((1 << shiftw) >> 1)) >> shiftw; - heights[p] = (avctx->height + ((1 << shifth) >> 1)) >> shifth; - strides[p] = frame->linesize[p]; - } - - *contiguous_buf_size = 0; - for (i = 0; i < *plane_count; i++) { - if (i < *plane_count - 1 && - frame->data[i] + strides[i] * heights[i] != frame->data[i + 1]) { - *contiguous_buf_size = 0; - break; - } - - *contiguous_buf_size += strides[i] * heights[i]; - } - - return 0; -} - -//Not used on OSX - frame is never copied. static int copy_avframe_to_pixel_buffer(AVCodecContext *avctx, const AVFrame *frame, - CVPixelBufferRef cv_img, - const size_t *plane_strides, - const size_t *plane_rows) + CVPixelBufferRef cv_img) { - int i, j; - size_t plane_count; int status; - int rows; - int src_stride; - int dst_stride; - uint8_t *src_addr; - uint8_t *dst_addr; - size_t copy_bytes; + + int num_planes = av_pix_fmt_count_planes(frame->format); + size_t num_cv_plane = CVPixelBufferIsPlanar(cv_img) ? + CVPixelBufferGetPlaneCount(cv_img) : 1; + if (num_planes != num_cv_plane) { + av_log(avctx, AV_LOG_ERROR, + "Different number of planes in AVFrame and CVPixelBuffer.\n"); + return AVERROR_BUG; + } status = CVPixelBufferLockBaseAddress(cv_img, 0); if (status) { @@ -2418,62 +2350,14 @@ static int copy_avframe_to_pixel_buffer(AVCodecContext *avctx, return AVERROR_EXTERNAL; } - if (CVPixelBufferIsPlanar(cv_img)) { - plane_count = CVPixelBufferGetPlaneCount(cv_img); - for (i = 0; frame->data[i]; i++) { - if (i == plane_count) { - CVPixelBufferUnlockBaseAddress(cv_img, 0); - av_log(avctx, - AV_LOG_ERROR, - "Error: different number of planes in AVFrame and CVPixelBuffer.\n" - ); - - return AVERROR_EXTERNAL; - } - - dst_addr = (uint8_t*)CVPixelBufferGetBaseAddressOfPlane(cv_img, i); - src_addr = (uint8_t*)frame->data[i]; - dst_stride = CVPixelBufferGetBytesPerRowOfPlane(cv_img, i); - src_stride = plane_strides[i]; - rows = plane_rows[i]; - - if (dst_stride == src_stride) { - memcpy(dst_addr, src_addr, src_stride * rows); - } else { - copy_bytes = dst_stride < src_stride ? dst_stride : src_stride; - - for (j = 0; j < rows; j++) { - memcpy(dst_addr + j * dst_stride, src_addr + j * src_stride, copy_bytes); - } - } - } - } else { - if (frame->data[1]) { - CVPixelBufferUnlockBaseAddress(cv_img, 0); - av_log(avctx, - AV_LOG_ERROR, - "Error: different number of planes in AVFrame and non-planar CVPixelBuffer.\n" - ); - - return AVERROR_EXTERNAL; - } - - dst_addr = (uint8_t*)CVPixelBufferGetBaseAddress(cv_img); - src_addr = (uint8_t*)frame->data[0]; - dst_stride = CVPixelBufferGetBytesPerRow(cv_img); - src_stride = plane_strides[0]; - rows = plane_rows[0]; - - if (dst_stride == src_stride) { - memcpy(dst_addr, src_addr, src_stride * rows); - } else { - copy_bytes = dst_stride < src_stride ? dst_stride : src_stride; - - for (j = 0; j < rows; j++) { - memcpy(dst_addr + j * dst_stride, src_addr + j * src_stride, copy_bytes); - } - } + int dst_stride[4] = {0}; + uint8_t *dst_addr[4] = {0}; + for (int i = 0; i < num_planes; i++) { + dst_addr[i] = (uint8_t*)CVPixelBufferGetBaseAddressOfPlane(cv_img, i); + dst_stride[i] = CVPixelBufferGetBytesPerRowOfPlane(cv_img, i); } + av_image_copy2(dst_addr, dst_stride, frame->data, frame->linesize, + frame->format, frame->width, frame->height); status = CVPixelBufferUnlockBaseAddress(cv_img, 0); if (status) { @@ -2489,13 +2373,7 @@ static int create_cv_pixel_buffer(AVCodecContext *avctx, CVPixelBufferRef *cv_img, BufNode *node) { - int plane_count; - int color; - size_t widths [AV_NUM_DATA_POINTERS]; - size_t heights[AV_NUM_DATA_POINTERS]; - size_t strides[AV_NUM_DATA_POINTERS]; int status; - size_t contiguous_buf_size; CVPixelBufferPoolRef pix_buf_pool; VTEncContext* vtctx = avctx->priv_data; @@ -2515,33 +2393,21 @@ static int create_cv_pixel_buffer(AVCodecContext *avctx, return 0; } - memset(widths, 0, sizeof(widths)); - memset(heights, 0, sizeof(heights)); - memset(strides, 0, sizeof(strides)); - - status = get_cv_pixel_info( - avctx, - frame, - &color, - &plane_count, - widths, - heights, - strides, - &contiguous_buf_size - ); - + int range_guessed; + status = get_cv_pixel_format(avctx, frame->format, avctx->color_range, + &(int) {0}, &range_guessed); if (status) { - av_log( - avctx, - AV_LOG_ERROR, - "Error: Cannot convert format %d color_range %d: %d\n", - frame->format, - frame->color_range, - status - ); - + av_log(avctx, AV_LOG_ERROR, "Cannot convert format %d color_range %d: %d\n", + frame->format, frame->color_range, status); return status; } + if (range_guessed) { + if (!vtctx->warned_color_range) { + vtctx->warned_color_range = true; + av_log(avctx, AV_LOG_WARNING, "Color range not set for %s. Using MPEG range.\n", + av_get_pix_fmt_name(frame->format)); + } + } pix_buf_pool = VTCompressionSessionGetPixelBufferPool(vtctx->session); if (!pix_buf_pool) { @@ -2578,7 +2444,7 @@ static int create_cv_pixel_buffer(AVCodecContext *avctx, return AVERROR_EXTERNAL; } - status = copy_avframe_to_pixel_buffer(avctx, frame, *cv_img, strides, heights); + status = copy_avframe_to_pixel_buffer(avctx, frame, *cv_img); if (status) { CFRelease(*cv_img); *cv_img = NULL; -- 2.49.1 _______________________________________________ ffmpeg-devel mailing list -- ffmpeg-devel@ffmpeg.org To unsubscribe send an email to ffmpeg-devel-leave@ffmpeg.org