[FFmpeg-devel] [PATCH] lavc: add ProRes RAW videotoolbox hwaccel (PR #20298)

2025-08-20 Thread wangbin via ffmpeg-devel
PR #20298 opened by wangbin
URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/20298
Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/20298.patch


>From 6f824aec76c409efd1da50dd97f947c7a19c86f1 Mon Sep 17 00:00:00 2001
From: wangbin 
Date: Thu, 21 Aug 2025 10:45:16 +0800
Subject: [PATCH] lavc: add ProRes RAW videotoolbox hwaccel

---
 Changelog |  1 +
 configure |  2 ++
 libavcodec/hwaccels.h |  1 +
 libavcodec/prores_raw.c   |  6 +
 libavcodec/videotoolbox.c | 52 +++
 5 files changed, 62 insertions(+)

diff --git a/Changelog b/Changelog
index 838114934c..86a984245e 100644
--- a/Changelog
+++ b/Changelog
@@ -39,6 +39,7 @@ version 8.0:
 - ProRes RAW Vulkan hwaccel
 - ffprobe -codec option
 - EXIF Metadata Parsing
+- ProRes RAW VideoToolbox hwaccel
 
 
 version 7.1:
diff --git a/configure b/configure
index e1809a3e58..c0eab1d9c5 100755
--- a/configure
+++ b/configure
@@ -3297,6 +3297,8 @@ mpeg4_videotoolbox_hwaccel_deps="videotoolbox"
 mpeg4_videotoolbox_hwaccel_select="mpeg4_decoder"
 prores_videotoolbox_hwaccel_deps="videotoolbox"
 prores_videotoolbox_hwaccel_select="prores_decoder"
+prores_raw_videotoolbox_hwaccel_deps="videotoolbox"
+prores_raw_videotoolbox_hwaccel_select="prores_raw_decoder"
 prores_raw_vulkan_hwaccel_deps="vulkan spirv_compiler"
 prores_raw_vulkan_hwaccel_select="prores_raw_decoder"
 vc1_d3d11va_hwaccel_deps="d3d11va"
diff --git a/libavcodec/hwaccels.h b/libavcodec/hwaccels.h
index 4b205d386e..40fdf60d37 100644
--- a/libavcodec/hwaccels.h
+++ b/libavcodec/hwaccels.h
@@ -67,6 +67,7 @@ extern const struct FFHWAccel ff_mpeg4_vaapi_hwaccel;
 extern const struct FFHWAccel ff_mpeg4_vdpau_hwaccel;
 extern const struct FFHWAccel ff_mpeg4_videotoolbox_hwaccel;
 extern const struct FFHWAccel ff_prores_videotoolbox_hwaccel;
+extern const struct FFHWAccel ff_prores_raw_videotoolbox_hwaccel;
 extern const struct FFHWAccel ff_prores_raw_vulkan_hwaccel;
 extern const struct FFHWAccel ff_vc1_d3d11va_hwaccel;
 extern const struct FFHWAccel ff_vc1_d3d11va2_hwaccel;
diff --git a/libavcodec/prores_raw.c b/libavcodec/prores_raw.c
index b2aa97ddda..c150d3e915 100644
--- a/libavcodec/prores_raw.c
+++ b/libavcodec/prores_raw.c
@@ -317,6 +317,9 @@ static enum AVPixelFormat get_pixel_format(AVCodecContext 
*avctx,
 enum AVPixelFormat pix_fmts[] = {
 #if CONFIG_PRORES_RAW_VULKAN_HWACCEL
 AV_PIX_FMT_VULKAN,
+#endif
+#if CONFIG_PRORES_RAW_VIDEOTOOLBOX_HWACCEL
+AV_PIX_FMT_VIDEOTOOLBOX,
 #endif
 pix_fmt,
 AV_PIX_FMT_NONE,
@@ -531,6 +534,9 @@ const FFCodec ff_prores_raw_decoder = {
 .hw_configs = (const AVCodecHWConfigInternal *const []) {
 #if CONFIG_PRORES_RAW_VULKAN_HWACCEL
 HWACCEL_VULKAN(prores_raw),
+#endif
+#if CONFIG_PRORES_RAW_VIDEOTOOLBOX_HWACCEL
+HWACCEL_VIDEOTOOLBOX(prores_raw),
 #endif
 NULL
 },
diff --git a/libavcodec/videotoolbox.c b/libavcodec/videotoolbox.c
index ccba249140..e0a93d349e 100644
--- a/libavcodec/videotoolbox.c
+++ b/libavcodec/videotoolbox.c
@@ -37,6 +37,7 @@
 #include "hwaccel_internal.h"
 #include "mpegvideo.h"
 #include "proresdec.h"
+#include "prores_raw.h"
 #include 
 #include 
 #include 
@@ -946,6 +947,14 @@ static int videotoolbox_start(AVCodecContext *avctx)
 break;
 }
 break;
+case AV_CODEC_ID_PRORES_RAW :
+switch (avctx->profile) {
+case AV_PROFILE_PRORES_RAW: // kCMVideoCodecType_AppleProResRAW
+case AV_PROFILE_PRORES_RAW_HQ:  // kCMVideoCodecType_AppleProResRAWHQ
+videotoolbox->cm_codec_type = av_bswap32(avctx->codec_tag);
+break;
+}
+break;
 case AV_CODEC_ID_VP9 :
 videotoolbox->cm_codec_type = kCMVideoCodecType_VP9;
 break;
@@ -1181,6 +1190,31 @@ static int videotoolbox_prores_end_frame(AVCodecContext 
*avctx)
 return ff_videotoolbox_common_end_frame(avctx, frame);
 }
 
+static int videotoolbox_prores_raw_start_frame(AVCodecContext *avctx,
+   const AVBufferRef *buffer_ref,
+   const uint8_t *buffer,
+   uint32_t size)
+{
+VTContext *vtctx = avctx->internal->hwaccel_priv_data;
+
+return ff_videotoolbox_buffer_copy(vtctx, buffer, size);
+}
+
+static int videotoolbox_prores_raw_decode_slice(AVCodecContext *avctx,
+  const uint8_t *buffer,
+  uint32_t size)
+{
+return 0;
+}
+
+static int videotoolbox_prores_raw_end_frame(AVCodecContext *avctx)
+{
+ProResRAWContext *ctx = avctx->priv_data;
+AVFrame *frame = ctx->frame;
+
+return ff_videotoolbox_common_end_frame(avctx, frame);
+}
+
 static enum AVPixelFormat videotoolbox_best_pixel_format(AVCodecContext 
*avctx) {
 int depth;
 const AVPixFmtDescriptor *descriptor = 
av_pix_fmt_desc_get(avctx->sw_pix_fmt);
@@ -1192,6 +1226,9 @@ s

[FFmpeg-devel] [PATCH] lavc/videotoolboxenc: add mjpeg (PR #20360)

2025-08-28 Thread wangbin via ffmpeg-devel
PR #20360 opened by wangbin
URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/20360
Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/20360.patch


>From 3a08d1b2c4c6ab01f0e29da1c43d15b9c75f7f68 Mon Sep 17 00:00:00 2001
From: wangbin 
Date: Thu, 28 Aug 2025 16:45:10 +0800
Subject: [PATCH] lavc/videotoolboxenc: add mjpeg

---
 Changelog|  2 +-
 libavcodec/allcodecs.c   |  1 +
 libavcodec/videotoolboxenc.c | 66 +---
 3 files changed, 64 insertions(+), 5 deletions(-)

diff --git a/Changelog b/Changelog
index 96d616991d..53c87e5a29 100644
--- a/Changelog
+++ b/Changelog
@@ -4,7 +4,7 @@ releases are sorted from youngest to oldest.
 version :
 - ffprobe -codec option
 - EXIF Metadata Parsing
-
+- VideoToolbox MJPEG encoder
 
 version 8.0:
 - Whisper filter
diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c
index f5ec2e01e8..c3010580ab 100644
--- a/libavcodec/allcodecs.c
+++ b/libavcodec/allcodecs.c
@@ -890,6 +890,7 @@ extern const FFCodec ff_mjpeg_cuvid_decoder;
 extern const FFCodec ff_mjpeg_qsv_encoder;
 extern const FFCodec ff_mjpeg_qsv_decoder;
 extern const FFCodec ff_mjpeg_vaapi_encoder;
+extern const FFCodec ff_mjpeg_videotoolbox_encoder;
 extern const FFCodec ff_mp3_mediacodec_decoder;
 extern const FFCodec ff_mp3_mf_encoder;
 extern const FFCodec ff_mpeg1_cuvid_decoder;
diff --git a/libavcodec/videotoolboxenc.c b/libavcodec/videotoolboxenc.c
index b748ecda61..6abcb8158b 100644
--- a/libavcodec/videotoolboxenc.c
+++ b/libavcodec/videotoolboxenc.c
@@ -289,6 +289,8 @@ typedef struct VTEncContext {
 int power_efficient;
 int max_ref_frames;
 int spatialaq;
+
+int quality;
 } VTEncContext;
 
 static void vtenc_free_buf_node(BufNode *info)
@@ -523,6 +525,7 @@ static CMVideoCodecType get_cm_codec_type(AVCodecContext 
*avctx,
 {
 const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(avctx->pix_fmt == 
AV_PIX_FMT_VIDEOTOOLBOX ? avctx->sw_pix_fmt : avctx->pix_fmt);
 switch (avctx->codec_id) {
+case AV_CODEC_ID_MJPEG: return kCMVideoCodecType_JPEG;
 case AV_CODEC_ID_H264: return kCMVideoCodecType_H264;
 case AV_CODEC_ID_HEVC:
 if (desc && (desc->flags & AV_PIX_FMT_FLAG_ALPHA) && alpha_quality > 
0.0) {
@@ -1195,6 +1198,9 @@ static int vtenc_create_encoder(AVCodecContext   *avctx,
 int64_t  one_second_value = 0;
 void *nums[2];
 
+if (vtctx->quality)
+quality = vtctx->quality;
+
 int status = VTCompressionSessionCreate(kCFAllocatorDefault,
 avctx->width,
 avctx->height,
@@ -1247,7 +1253,7 @@ static int vtenc_create_encoder(AVCodecContext   *avctx,
 return AVERROR_EXTERNAL;
 }
 
-if (avctx->flags & AV_CODEC_FLAG_QSCALE) {
+if (avctx->flags & AV_CODEC_FLAG_QSCALE || avctx->codec_id == 
AV_CODEC_ID_MJPEG) {
 quality = quality >= 100 ? 1.0 : quality / 100;
 quality_num = CFNumberCreate(kCFAllocatorDefault,
  kCFNumberFloat32Type,
@@ -1258,7 +1264,7 @@ static int vtenc_create_encoder(AVCodecContext   *avctx,
   kVTCompressionPropertyKey_Quality,
   quality_num);
 CFRelease(quality_num);
-} else if (avctx->codec_id != AV_CODEC_ID_PRORES) {
+} else if (avctx->codec_id != AV_CODEC_ID_PRORES && avctx->codec_id != 
AV_CODEC_ID_MJPEG) {
 bit_rate_num = CFNumberCreate(kCFAllocatorDefault,
   kCFNumberSInt32Type,
   &bit_rate);
@@ -1374,7 +1380,7 @@ static int vtenc_create_encoder(AVCodecContext   *avctx,
 }
 }
 
-if (avctx->gop_size > 0 && avctx->codec_id != AV_CODEC_ID_PRORES) {
+if (avctx->gop_size > 0 && avctx->codec_id != AV_CODEC_ID_PRORES && 
avctx->codec_id != AV_CODEC_ID_MJPEG) {
 CFNumberRef interval = CFNumberCreate(kCFAllocatorDefault,
   kCFNumberIntType,
   &avctx->gop_size);
@@ -1523,7 +1529,7 @@ static int vtenc_create_encoder(AVCodecContext   *avctx,
 }
 }
 
-if (!vtctx->has_b_frames && avctx->codec_id != AV_CODEC_ID_PRORES) {
+if (!vtctx->has_b_frames && avctx->codec_id != AV_CODEC_ID_PRORES && 
avctx->codec_id != AV_CODEC_ID_MJPEG) {
 status = VTSessionSetProperty(vtctx->session,
   
kVTCompressionPropertyKey_AllowFrameReordering,
   kCFBooleanFalse);
@@ -2901,6 +2907,24 @@ static const enum AVPixelFormat prores_pix_fmts[] = {
 AV_PIX_FMT_NONE
 };
 
+static const enum AVPixelFormat mjpeg_pix_fmts[] = {
+AV_PIX_FMT_VIDEOTOOLBOX,
+AV_PIX_FMT_NV12,
+AV_PIX_FMT_NV16,
+AV_PIX_FMT_NV24,
+AV_PIX_FMT_YUV420P,
+AV_PIX_FMT_BGRA,
+AV_PIX_FMT_P010,
+AV_PIX_FMT_P210,
+AV_PIX_FMT_P216,
+AV_PIX_FMT_P4