avcodec/videotoolbox: add support for 10bit pixel format
authorfumoboy007 <fumoboy007@me.com>
Sat, 13 Apr 2019 14:36:00 +0000 (16:36 +0200)
committerJan Ekström <jeebjp@gmail.com>
Tue, 16 Apr 2019 00:43:06 +0000 (03:43 +0300)
this patch was originally posted on issue #7704 and was slightly
adjusted to check for the availability of the pixel format.

configure
fftools/ffmpeg_videotoolbox.c
libavcodec/videotoolbox.c
libavutil/hwcontext_videotoolbox.c

index c2580b3..e10e2c2 100755 (executable)
--- a/configure
+++ b/configure
@@ -2253,6 +2253,7 @@ TOOLCHAIN_FEATURES="
 
 TYPES_LIST="
     kCMVideoCodecType_HEVC
+    kCVPixelFormatType_420YpCbCr10BiPlanarVideoRange
     socklen_t
     struct_addrinfo
     struct_group_source_req
@@ -6014,6 +6015,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
index b820aec..ad6174d 100644 (file)
@@ -53,6 +53,9 @@ static int videotoolbox_retrieve_data(AVCodecContext *s, AVFrame *frame)
 #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,
                "%s: Unsupported pixel format: %s\n",
index fb3501f..c718e82 100644 (file)
@@ -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);
index cc00f1f..6eac2c0 100644 (file)
@@ -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)