From 6b3d27b420221f9fcc09828249da6919fb54ccea Mon Sep 17 00:00:00 2001
From: fumoboy007 <fumoboy007@me.com>
Date: Sun, 27 Jan 2019 19:52:05 -0800
Subject: [PATCH] Support 10-bit color when using VideoToolbox to decode
---
fftools/ffmpeg_videotoolbox.c | 1 +
libavcodec/videotoolbox.c | 33 +++++++++++++++++++++++++-----
libavutil/hwcontext_videotoolbox.c | 1 +
3 files changed, 30 insertions(+), 5 deletions(-)
diff --git a/fftools/ffmpeg_videotoolbox.c b/fftools/ffmpeg_videotoolbox.c
index b820aec017..e13592caeb 100644
|
a
|
b
|
static int videotoolbox_retrieve_data(AVCodecContext *s, AVFrame *frame)
|
| 53 | 53 | #ifdef kCFCoreFoundationVersionNumber10_7 |
| 54 | 54 | case kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange: vt->tmp_frame->format = AV_PIX_FMT_NV12; break; |
| 55 | 55 | #endif |
| | 56 | case kCVPixelFormatType_420YpCbCr10BiPlanarVideoRange: vt->tmp_frame->format = AV_PIX_FMT_P010; break; |
| 56 | 57 | default: |
| 57 | 58 | av_log(NULL, AV_LOG_ERROR, |
| 58 | 59 | "%s: Unsupported pixel format: %s\n", |
diff --git a/libavcodec/videotoolbox.c b/libavcodec/videotoolbox.c
index da7236f100..df22786532 100644
|
a
|
b
|
|
| 26 | 26 | #include "vt_internal.h" |
| 27 | 27 | #include "libavutil/avutil.h" |
| 28 | 28 | #include "libavutil/hwcontext.h" |
| | 29 | #include "libavutil/pixdesc.h" |
| 29 | 30 | #include "bytestream.h" |
| 30 | 31 | #include "decode.h" |
| 31 | 32 | #include "h264dec.h" |
| … |
… |
static int videotoolbox_uninit(AVCodecContext *avctx)
|
| 1026 | 1027 | return 0; |
| 1027 | 1028 | } |
| 1028 | 1029 | |
| | 1030 | static enum AVPixelFormat videotoolbox_best_pixel_format(AVCodecContext *avctx) { |
| | 1031 | const AVPixFmtDescriptor *descriptor = av_pix_fmt_desc_get(avctx->pix_fmt); |
| | 1032 | if (descriptor != NULL) { |
| | 1033 | int depth = descriptor->comp[0].depth; |
| | 1034 | if (depth > 8) { |
| | 1035 | return AV_PIX_FMT_P010; |
| | 1036 | } |
| | 1037 | } |
| | 1038 | |
| | 1039 | return AV_PIX_FMT_NV12; // same as av_videotoolbox_alloc_context() |
| | 1040 | } |
| | 1041 | |
| 1029 | 1042 | static int videotoolbox_common_init(AVCodecContext *avctx) |
| 1030 | 1043 | { |
| 1031 | 1044 | VTContext *vtctx = avctx->internal->hwaccel_priv_data; |
| … |
… |
static int videotoolbox_common_init(AVCodecContext *avctx)
|
| 1059 | 1072 | |
| 1060 | 1073 | hw_frames = (AVHWFramesContext*)avctx->hw_frames_ctx->data; |
| 1061 | 1074 | hw_frames->format = AV_PIX_FMT_VIDEOTOOLBOX; |
| 1062 | | hw_frames->sw_format = AV_PIX_FMT_NV12; // same as av_videotoolbox_alloc_context() |
| | 1075 | hw_frames->sw_format = videotoolbox_best_pixel_format(avctx); |
| 1063 | 1076 | hw_frames->width = avctx->width; |
| 1064 | 1077 | hw_frames->height = avctx->height; |
| 1065 | 1078 | |
| … |
… |
static int videotoolbox_frame_params(AVCodecContext *avctx,
|
| 1103 | 1116 | frames_ctx->format = AV_PIX_FMT_VIDEOTOOLBOX; |
| 1104 | 1117 | frames_ctx->width = avctx->coded_width; |
| 1105 | 1118 | frames_ctx->height = avctx->coded_height; |
| 1106 | | frames_ctx->sw_format = AV_PIX_FMT_NV12; |
| | 1119 | frames_ctx->sw_format = videotoolbox_best_pixel_format(avctx); |
| 1107 | 1120 | |
| 1108 | 1121 | return 0; |
| 1109 | 1122 | } |
| … |
… |
const AVHWAccel ff_mpeg4_videotoolbox_hwaccel = {
|
| 1200 | 1213 | .priv_data_size = sizeof(VTContext), |
| 1201 | 1214 | }; |
| 1202 | 1215 | |
| 1203 | | AVVideotoolboxContext *av_videotoolbox_alloc_context(void) |
| | 1216 | static AVVideotoolboxContext *av_videotoolbox_alloc_context_with_pix_fmt(enum AVPixelFormat pix_fmt) |
| 1204 | 1217 | { |
| 1205 | 1218 | AVVideotoolboxContext *ret = av_mallocz(sizeof(*ret)); |
| 1206 | 1219 | |
| 1207 | 1220 | if (ret) { |
| 1208 | 1221 | ret->output_callback = videotoolbox_decoder_callback; |
| 1209 | | ret->cv_pix_fmt_type = kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange; |
| | 1222 | |
| | 1223 | OSType cv_pix_fmt_type = av_map_videotoolbox_format_from_pixfmt(pix_fmt); |
| | 1224 | if (cv_pix_fmt_type == 0) { |
| | 1225 | cv_pix_fmt_type = kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange; |
| | 1226 | } |
| | 1227 | ret->cv_pix_fmt_type = cv_pix_fmt_type; |
| 1210 | 1228 | } |
| 1211 | 1229 | |
| 1212 | 1230 | return ret; |
| 1213 | 1231 | } |
| 1214 | 1232 | |
| | 1233 | AVVideotoolboxContext *av_videotoolbox_alloc_context(void) |
| | 1234 | { |
| | 1235 | return av_videotoolbox_alloc_context_with_pix_fmt(AV_PIX_FMT_NONE); |
| | 1236 | } |
| | 1237 | |
| 1215 | 1238 | int av_videotoolbox_default_init(AVCodecContext *avctx) |
| 1216 | 1239 | { |
| 1217 | 1240 | return av_videotoolbox_default_init2(avctx, NULL); |
| … |
… |
int av_videotoolbox_default_init(AVCodecContext *avctx)
|
| 1219 | 1242 | |
| 1220 | 1243 | int av_videotoolbox_default_init2(AVCodecContext *avctx, AVVideotoolboxContext *vtctx) |
| 1221 | 1244 | { |
| 1222 | | avctx->hwaccel_context = vtctx ?: av_videotoolbox_alloc_context(); |
| | 1245 | avctx->hwaccel_context = vtctx ?: av_videotoolbox_alloc_context_with_pix_fmt(videotoolbox_best_pixel_format(avctx)); |
| 1223 | 1246 | if (!avctx->hwaccel_context) |
| 1224 | 1247 | return AVERROR(ENOMEM); |
| 1225 | 1248 | return videotoolbox_start(avctx); |
diff --git a/libavutil/hwcontext_videotoolbox.c b/libavutil/hwcontext_videotoolbox.c
index cc00f1f2f2..5da8b91016 100644
|
a
|
b
|
static const struct {
|
| 42 | 42 | #ifdef kCFCoreFoundationVersionNumber10_7 |
| 43 | 43 | { kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange, AV_PIX_FMT_NV12 }, |
| 44 | 44 | #endif |
| | 45 | { kCVPixelFormatType_420YpCbCr10BiPlanarVideoRange, AV_PIX_FMT_P010 }, |
| 45 | 46 | }; |
| 46 | 47 | |
| 47 | 48 | enum AVPixelFormat av_map_videotoolbox_format_to_pixfmt(uint32_t cv_fmt) |