[FFmpeg-devel,v3,1/2] avcodec/videotoolbox: add support for 10bit pixel format

Submitted by der richter on April 13, 2019, 2:36 p.m.

Details

Message ID 20190413143601.74858-1-der.richter@gmx.de
State New
Headers show

Commit Message

der richter April 13, 2019, 2:36 p.m.
From: fumoboy007 <fumoboy007@me.com>

this patch was originally posted on issue #7704 and was slightly
adjusted to check for the availability of the pixel format.
---
 configure                          |  2 ++
 fftools/ffmpeg_videotoolbox.c      |  3 +++
 libavcodec/videotoolbox.c          | 34 +++++++++++++++++++++++++-----
 libavutil/hwcontext_videotoolbox.c |  3 +++
 4 files changed, 37 insertions(+), 5 deletions(-)

--
2.21.0

Comments

Jan Ekström April 15, 2019, 11:55 p.m.
On Sat, Apr 13, 2019 at 5:36 PM der richter <der.richter@gmx.de> wrote:
>
> From: fumoboy007 <fumoboy007@me.com>
>
> this patch was originally posted on issue #7704 and was slightly
> adjusted to check for the availability of the pixel format.
> ---

Functionally tested on a macOS 10.13.x + XCode 10.1, as well as
forcibly made the kCVPixelFormatType_420YpCbCr10BiPlanarVideoRange
check fail, and it still built fine. 10bit HEVC content is now
properly getting decoded onto P010 surfaces through VT instead of
getting dithered to NV12.

In other words, from my side LGTM.

Best regards,
Jan
Jan Ekström April 16, 2019, 12:58 a.m.
On Tue, Apr 16, 2019 at 2:55 AM Jan Ekström <jeebjp@gmail.com> wrote:
>
> On Sat, Apr 13, 2019 at 5:36 PM der richter <der.richter@gmx.de> wrote:
> >
> > From: fumoboy007 <fumoboy007@me.com>
> >
> > this patch was originally posted on issue #7704 and was slightly
> > adjusted to check for the availability of the pixel format.
> > ---
>
> Functionally tested on a macOS 10.13.x + XCode 10.1, as well as
> forcibly made the kCVPixelFormatType_420YpCbCr10BiPlanarVideoRange
> check fail, and it still built fine. 10bit HEVC content is now
> properly getting decoded onto P010 surfaces through VT instead of
> getting dithered to NV12.
>
> In other words, from my side LGTM.
>
> Best regards,
> Jan

Additionally tested with ffmpeg.c and P010 images seem to be flowing
with hwaccel videotoolbox.

Applied as 036b4b0f85933f49a7094b5b568a93f68c9cd544 .

Jan

Patch hide | download patch | download mbox

diff --git a/configure b/configure
index 331393f8d5..a89da70aab 100755
--- a/configure
+++ b/configure
@@ -2253,6 +2253,7 @@  TOOLCHAIN_FEATURES="

 TYPES_LIST="
     kCMVideoCodecType_HEVC
+    kCVPixelFormatType_420YpCbCr10BiPlanarVideoRange
     socklen_t
     struct_addrinfo
     struct_group_source_req
@@ -6012,6 +6013,7 @@  enabled avfoundation && {
 enabled videotoolbox && {
     check_lib coreservices CoreServices/CoreServices.h UTGetOSTypeFromString "-framework CoreServices"
     check_func_headers CoreMedia/CMFormatDescription.h kCMVideoCodecType_HEVC "-framework CoreMedia"
+    check_func_headers CoreVideo/CVPixelBuffer.h kCVPixelFormatType_420YpCbCr10BiPlanarVideoRange "-framework CoreVideo"
 }

 check_struct "sys/time.h sys/resource.h" "struct rusage" ru_maxrss
diff --git a/fftools/ffmpeg_videotoolbox.c b/fftools/ffmpeg_videotoolbox.c
index b820aec017..ad6174d3c7 100644
--- a/fftools/ffmpeg_videotoolbox.c
+++ b/fftools/ffmpeg_videotoolbox.c
@@ -52,6 +52,9 @@  static int videotoolbox_retrieve_data(AVCodecContext *s, AVFrame *frame)
     case kCVPixelFormatType_32BGRA:           vt->tmp_frame->format = AV_PIX_FMT_BGRA; break;
 #ifdef kCFCoreFoundationVersionNumber10_7
     case kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange: vt->tmp_frame->format = AV_PIX_FMT_NV12; break;
+#endif
+#if HAVE_KCVPIXELFORMATTYPE_420YPCBCR10BIPLANARVIDEORANGE
+    case kCVPixelFormatType_420YpCbCr10BiPlanarVideoRange: vt->tmp_frame->format = AV_PIX_FMT_P010; break;
 #endif
     default:
         av_log(NULL, AV_LOG_ERROR,
diff --git a/libavcodec/videotoolbox.c b/libavcodec/videotoolbox.c
index fb3501f413..c718e82cc5 100644
--- a/libavcodec/videotoolbox.c
+++ b/libavcodec/videotoolbox.c
@@ -26,6 +26,7 @@ 
 #include "vt_internal.h"
 #include "libavutil/avutil.h"
 #include "libavutil/hwcontext.h"
+#include "libavutil/pixdesc.h"
 #include "bytestream.h"
 #include "decode.h"
 #include "h264dec.h"
@@ -1020,6 +1021,19 @@  static int videotoolbox_uninit(AVCodecContext *avctx)
     return 0;
 }

+static enum AVPixelFormat videotoolbox_best_pixel_format(AVCodecContext *avctx) {
+    const AVPixFmtDescriptor *descriptor = av_pix_fmt_desc_get(avctx->pix_fmt);
+    if (!descriptor)
+        return AV_PIX_FMT_NV12; // same as av_videotoolbox_alloc_context()
+
+    int depth = descriptor->comp[0].depth;
+    if (depth > 8) {
+        return AV_PIX_FMT_P010;
+    }
+
+    return AV_PIX_FMT_NV12;
+}
+
 static int videotoolbox_common_init(AVCodecContext *avctx)
 {
     VTContext *vtctx = avctx->internal->hwaccel_priv_data;
@@ -1053,7 +1067,7 @@  static int videotoolbox_common_init(AVCodecContext *avctx)

         hw_frames = (AVHWFramesContext*)avctx->hw_frames_ctx->data;
         hw_frames->format = AV_PIX_FMT_VIDEOTOOLBOX;
-        hw_frames->sw_format = AV_PIX_FMT_NV12; // same as av_videotoolbox_alloc_context()
+        hw_frames->sw_format = videotoolbox_best_pixel_format(avctx);
         hw_frames->width = avctx->width;
         hw_frames->height = avctx->height;

@@ -1097,7 +1111,7 @@  static int videotoolbox_frame_params(AVCodecContext *avctx,
     frames_ctx->format            = AV_PIX_FMT_VIDEOTOOLBOX;
     frames_ctx->width             = avctx->coded_width;
     frames_ctx->height            = avctx->coded_height;
-    frames_ctx->sw_format         = AV_PIX_FMT_NV12;
+    frames_ctx->sw_format         = videotoolbox_best_pixel_format(avctx);

     return 0;
 }
@@ -1194,18 +1208,28 @@  const AVHWAccel ff_mpeg4_videotoolbox_hwaccel = {
     .priv_data_size = sizeof(VTContext),
 };

-AVVideotoolboxContext *av_videotoolbox_alloc_context(void)
+static AVVideotoolboxContext *av_videotoolbox_alloc_context_with_pix_fmt(enum AVPixelFormat pix_fmt)
 {
     AVVideotoolboxContext *ret = av_mallocz(sizeof(*ret));

     if (ret) {
         ret->output_callback = videotoolbox_decoder_callback;
-        ret->cv_pix_fmt_type = kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange;
+
+        OSType cv_pix_fmt_type = av_map_videotoolbox_format_from_pixfmt(pix_fmt);
+        if (cv_pix_fmt_type == 0) {
+            cv_pix_fmt_type = kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange;
+        }
+        ret->cv_pix_fmt_type = cv_pix_fmt_type;
     }

     return ret;
 }

+AVVideotoolboxContext *av_videotoolbox_alloc_context(void)
+{
+    return av_videotoolbox_alloc_context_with_pix_fmt(AV_PIX_FMT_NONE);
+}
+
 int av_videotoolbox_default_init(AVCodecContext *avctx)
 {
     return av_videotoolbox_default_init2(avctx, NULL);
@@ -1213,7 +1237,7 @@  int av_videotoolbox_default_init(AVCodecContext *avctx)

 int av_videotoolbox_default_init2(AVCodecContext *avctx, AVVideotoolboxContext *vtctx)
 {
-    avctx->hwaccel_context = vtctx ?: av_videotoolbox_alloc_context();
+    avctx->hwaccel_context = vtctx ?: av_videotoolbox_alloc_context_with_pix_fmt(videotoolbox_best_pixel_format(avctx));
     if (!avctx->hwaccel_context)
         return AVERROR(ENOMEM);
     return videotoolbox_start(avctx);
diff --git a/libavutil/hwcontext_videotoolbox.c b/libavutil/hwcontext_videotoolbox.c
index cc00f1f2f2..6eac2c0774 100644
--- a/libavutil/hwcontext_videotoolbox.c
+++ b/libavutil/hwcontext_videotoolbox.c
@@ -42,6 +42,9 @@  static const struct {
 #ifdef kCFCoreFoundationVersionNumber10_7
     { kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange,  AV_PIX_FMT_NV12 },
 #endif
+#if HAVE_KCVPIXELFORMATTYPE_420YPCBCR10BIPLANARVIDEORANGE
+    { kCVPixelFormatType_420YpCbCr10BiPlanarVideoRange, AV_PIX_FMT_P010 },
+#endif
 };

 enum AVPixelFormat av_map_videotoolbox_format_to_pixfmt(uint32_t cv_fmt)