diff options
Diffstat (limited to 'src/plugins/multimedia/darwin/qavfhelpers.mm')
-rw-r--r-- | src/plugins/multimedia/darwin/qavfhelpers.mm | 252 |
1 files changed, 103 insertions, 149 deletions
diff --git a/src/plugins/multimedia/darwin/qavfhelpers.mm b/src/plugins/multimedia/darwin/qavfhelpers.mm index 52215e883..51ae9eedc 100644 --- a/src/plugins/multimedia/darwin/qavfhelpers.mm +++ b/src/plugins/multimedia/darwin/qavfhelpers.mm @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2022 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #include <qavfhelpers_p.h> #include <CoreMedia/CMFormatDescription.h> #include <CoreVideo/CoreVideo.h> @@ -43,86 +7,73 @@ #import <CoreVideo/CoreVideo.h> -QVideoFrameFormat::PixelFormat QAVFHelpers::fromCVPixelFormat(unsigned avPixelFormat) +namespace { + +using PixelFormat = QVideoFrameFormat::PixelFormat; +using ColorRange = QVideoFrameFormat::ColorRange; + +// clang-format off +constexpr std::tuple<CvPixelFormat, PixelFormat, ColorRange> PixelFormatMap[] = { + { kCVPixelFormatType_32ARGB, PixelFormat::Format_ARGB8888, ColorRange::ColorRange_Unknown }, + { kCVPixelFormatType_32BGRA, PixelFormat::Format_BGRA8888, ColorRange::ColorRange_Unknown }, + { kCVPixelFormatType_420YpCbCr8Planar, PixelFormat::Format_YUV420P, ColorRange::ColorRange_Unknown }, + { kCVPixelFormatType_420YpCbCr8PlanarFullRange, PixelFormat::Format_YUV420P, ColorRange::ColorRange_Full }, + { kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange, PixelFormat::Format_NV12, ColorRange::ColorRange_Video }, + { kCVPixelFormatType_420YpCbCr8BiPlanarFullRange, PixelFormat::Format_NV12, ColorRange::ColorRange_Full }, + { kCVPixelFormatType_420YpCbCr10BiPlanarVideoRange, PixelFormat::Format_P010, ColorRange::ColorRange_Video }, + { kCVPixelFormatType_420YpCbCr10BiPlanarFullRange, PixelFormat::Format_P010, ColorRange::ColorRange_Full }, + { kCVPixelFormatType_422YpCbCr8, PixelFormat::Format_UYVY, ColorRange::ColorRange_Video }, + { kCVPixelFormatType_422YpCbCr8_yuvs, PixelFormat::Format_YUYV, ColorRange::ColorRange_Video }, + { kCVPixelFormatType_OneComponent8, PixelFormat::Format_Y8, ColorRange::ColorRange_Unknown }, + { kCVPixelFormatType_OneComponent16, PixelFormat::Format_Y16, ColorRange::ColorRange_Unknown }, + + // The cases with kCMVideoCodecType_JPEG/kCMVideoCodecType_JPEG_OpenDML as cv pixel format should be investigated. + // Matching kCMVideoCodecType_JPEG_OpenDML to ColorRange_Full is a little hack to distinguish between + // kCMVideoCodecType_JPEG and kCMVideoCodecType_JPEG_OpenDML. + { kCMVideoCodecType_JPEG, PixelFormat::Format_Jpeg, ColorRange::ColorRange_Unknown }, + { kCMVideoCodecType_JPEG_OpenDML, PixelFormat::Format_Jpeg, ColorRange::ColorRange_Full } +}; +// clang-format on + +template<typename Type, typename... Args> +Type findInPixelFormatMap(Type defaultValue, Args... args) { - switch (avPixelFormat) { - case kCVPixelFormatType_32ARGB: - return QVideoFrameFormat::Format_ARGB8888; - case kCVPixelFormatType_32BGRA: - return QVideoFrameFormat::Format_BGRA8888; - case kCVPixelFormatType_420YpCbCr8Planar: - case kCVPixelFormatType_420YpCbCr8PlanarFullRange: - return QVideoFrameFormat::Format_YUV420P; - case kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange: - case kCVPixelFormatType_420YpCbCr8BiPlanarFullRange: - return QVideoFrameFormat::Format_NV12; - case kCVPixelFormatType_420YpCbCr10BiPlanarVideoRange: - case kCVPixelFormatType_420YpCbCr10BiPlanarFullRange: - return QVideoFrameFormat::Format_P010; - case kCVPixelFormatType_422YpCbCr8: - return QVideoFrameFormat::Format_UYVY; - case kCVPixelFormatType_422YpCbCr8_yuvs: - return QVideoFrameFormat::Format_YUYV; - case kCVPixelFormatType_OneComponent8: - return QVideoFrameFormat::Format_Y8; - case q_kCVPixelFormatType_OneComponent16: - return QVideoFrameFormat::Format_Y16; - - case kCMVideoCodecType_JPEG: - case kCMVideoCodecType_JPEG_OpenDML: - return QVideoFrameFormat::Format_Jpeg; - default: - return QVideoFrameFormat::Format_Invalid; - } + auto checkElement = [&](const auto &element) { + return ((args == std::get<Args>(element)) && ...); + }; + + auto found = std::find_if(std::begin(PixelFormatMap), std::end(PixelFormatMap), checkElement); + return found == std::end(PixelFormatMap) ? defaultValue : std::get<Type>(*found); +} + } -bool QAVFHelpers::toCVPixelFormat(QVideoFrameFormat::PixelFormat qtFormat, unsigned &conv) +ColorRange QAVFHelpers::colorRangeForCVPixelFormat(CvPixelFormat cvPixelFormat) { - switch (qtFormat) { - case QVideoFrameFormat::Format_ARGB8888: - conv = kCVPixelFormatType_32ARGB; - break; - case QVideoFrameFormat::Format_BGRA8888: - conv = kCVPixelFormatType_32BGRA; - break; - case QVideoFrameFormat::Format_YUV420P: - conv = kCVPixelFormatType_420YpCbCr8PlanarFullRange; - break; - case QVideoFrameFormat::Format_NV12: - conv = kCVPixelFormatType_420YpCbCr8BiPlanarFullRange; - break; - case QVideoFrameFormat::Format_P010: - conv = kCVPixelFormatType_420YpCbCr10BiPlanarFullRange; - break; - case QVideoFrameFormat::Format_UYVY: - conv = kCVPixelFormatType_422YpCbCr8; - break; - case QVideoFrameFormat::Format_YUYV: - conv = kCVPixelFormatType_422YpCbCr8_yuvs; - break; - case QVideoFrameFormat::Format_Y8: - conv = kCVPixelFormatType_OneComponent8; - break; - case QVideoFrameFormat::Format_Y16: - conv = q_kCVPixelFormatType_OneComponent16; - break; - default: - return false; - } + return findInPixelFormatMap(ColorRange::ColorRange_Unknown, cvPixelFormat); +} - return true; +PixelFormat QAVFHelpers::fromCVPixelFormat(CvPixelFormat cvPixelFormat) +{ + return findInPixelFormatMap(PixelFormat::Format_Invalid, cvPixelFormat); +} + +CvPixelFormat QAVFHelpers::toCVPixelFormat(PixelFormat pixelFmt, ColorRange colorRange) +{ + return findInPixelFormatMap(CvPixelFormatInvalid, pixelFmt, colorRange); } QVideoFrameFormat QAVFHelpers::videoFormatForImageBuffer(CVImageBufferRef buffer, bool openGL) { - auto avPixelFormat = CVPixelBufferGetPixelFormatType(buffer); + auto cvPixelFormat = CVPixelBufferGetPixelFormatType(buffer); + auto pixelFormat = fromCVPixelFormat(cvPixelFormat); if (openGL) { - if (avPixelFormat == kCVPixelFormatType_32BGRA) - avPixelFormat = QVideoFrameFormat::Format_SamplerRect; + if (cvPixelFormat == kCVPixelFormatType_32BGRA) + pixelFormat = QVideoFrameFormat::Format_SamplerRect; else - qWarning() << "Accelerated macOS OpenGL video supports BGRA only, got CV pixel format" << avPixelFormat; + qWarning() << "Accelerated macOS OpenGL video supports BGRA only, got CV pixel format" + << cvPixelFormat; } - auto pixelFormat = fromCVPixelFormat(avPixelFormat); size_t width = CVPixelBufferGetWidth(buffer); size_t height = CVPixelBufferGetHeight(buffer); @@ -132,57 +83,60 @@ QVideoFrameFormat QAVFHelpers::videoFormatForImageBuffer(CVImageBufferRef buffer auto colorSpace = QVideoFrameFormat::ColorSpace_Undefined; auto colorTransfer = QVideoFrameFormat::ColorTransfer_Unknown; - CFStringRef cSpace = reinterpret_cast<CFStringRef>( - CVBufferGetAttachment(buffer, kCVImageBufferYCbCrMatrixKey, nullptr)); - if (CFEqual(cSpace, kCVImageBufferYCbCrMatrix_ITU_R_709_2)) { - colorSpace = QVideoFrameFormat::ColorSpace_BT709; - } else if (CFEqual(cSpace, kCVImageBufferYCbCrMatrix_ITU_R_601_4) || - CFEqual(cSpace, kCVImageBufferYCbCrMatrix_SMPTE_240M_1995)) { - colorSpace = QVideoFrameFormat::ColorSpace_BT601; - } else if (@available(macOS 10.11, iOS 9.0, *)) { - if (CFEqual(cSpace, kCVImageBufferYCbCrMatrix_ITU_R_2020)) { - colorSpace = QVideoFrameFormat::ColorSpace_BT2020; + if (CFStringRef cSpace = reinterpret_cast<CFStringRef>( + CVBufferGetAttachment(buffer, kCVImageBufferYCbCrMatrixKey, nullptr))) { + if (CFEqual(cSpace, kCVImageBufferYCbCrMatrix_ITU_R_709_2)) { + colorSpace = QVideoFrameFormat::ColorSpace_BT709; + } else if (CFEqual(cSpace, kCVImageBufferYCbCrMatrix_ITU_R_601_4) + || CFEqual(cSpace, kCVImageBufferYCbCrMatrix_SMPTE_240M_1995)) { + colorSpace = QVideoFrameFormat::ColorSpace_BT601; + } else if (@available(macOS 10.11, iOS 9.0, *)) { + if (CFEqual(cSpace, kCVImageBufferYCbCrMatrix_ITU_R_2020)) { + colorSpace = QVideoFrameFormat::ColorSpace_BT2020; + } } } - CFStringRef cTransfer = reinterpret_cast<CFStringRef>( - CVBufferGetAttachment(buffer, kCVImageBufferTransferFunctionKey, nullptr)); - - if (CFEqual(cTransfer, kCVImageBufferTransferFunction_ITU_R_709_2)) { - colorTransfer = QVideoFrameFormat::ColorTransfer_BT709; - } else if (CFEqual(cTransfer, kCVImageBufferTransferFunction_SMPTE_240M_1995)) { - colorTransfer = QVideoFrameFormat::ColorTransfer_BT601; - } else if (CFEqual(cTransfer, kCVImageBufferTransferFunction_sRGB)) { - colorTransfer = QVideoFrameFormat::ColorTransfer_Gamma22; - } else if (CFEqual(cTransfer, kCVImageBufferTransferFunction_UseGamma)) { - auto gamma = reinterpret_cast<CFNumberRef>( - CVBufferGetAttachment(buffer, kCVImageBufferGammaLevelKey, nullptr)); - double g; - CFNumberGetValue(gamma, kCFNumberFloat32Type, &g); - // These are best fit values given what we have in our enum - if (g < 0.8) - ; // unknown - else if (g < 1.5) - colorTransfer = QVideoFrameFormat::ColorTransfer_Linear; - else if (g < 2.1) + if (CFStringRef cTransfer = reinterpret_cast<CFStringRef>( + CVBufferGetAttachment(buffer, kCVImageBufferTransferFunctionKey, nullptr))) { + + if (CFEqual(cTransfer, kCVImageBufferTransferFunction_ITU_R_709_2)) { colorTransfer = QVideoFrameFormat::ColorTransfer_BT709; - else if (g < 2.5) + } else if (CFEqual(cTransfer, kCVImageBufferTransferFunction_SMPTE_240M_1995)) { + colorTransfer = QVideoFrameFormat::ColorTransfer_BT601; + } else if (CFEqual(cTransfer, kCVImageBufferTransferFunction_sRGB)) { colorTransfer = QVideoFrameFormat::ColorTransfer_Gamma22; - else if (g < 3.2) - colorTransfer = QVideoFrameFormat::ColorTransfer_Gamma28; - } - if (@available(macOS 10.12, iOS 11.0, *)) { - if (CFEqual(cTransfer, kCVImageBufferTransferFunction_ITU_R_2020)) - colorTransfer = QVideoFrameFormat::ColorTransfer_BT709; - } - if (@available(macOS 10.12, iOS 11.0, *)) { - if (CFEqual(cTransfer, kCVImageBufferTransferFunction_ITU_R_2100_HLG)) { - colorTransfer = QVideoFrameFormat::ColorTransfer_STD_B67; - } else if (CFEqual(cTransfer, kCVImageBufferTransferFunction_SMPTE_ST_2084_PQ)) { - colorTransfer = QVideoFrameFormat::ColorTransfer_ST2084; + } else if (CFEqual(cTransfer, kCVImageBufferTransferFunction_UseGamma)) { + auto gamma = reinterpret_cast<CFNumberRef>( + CVBufferGetAttachment(buffer, kCVImageBufferGammaLevelKey, nullptr)); + double g; + CFNumberGetValue(gamma, kCFNumberFloat32Type, &g); + // These are best fit values given what we have in our enum + if (g < 0.8) + ; // unknown + else if (g < 1.5) + colorTransfer = QVideoFrameFormat::ColorTransfer_Linear; + else if (g < 2.1) + colorTransfer = QVideoFrameFormat::ColorTransfer_BT709; + else if (g < 2.5) + colorTransfer = QVideoFrameFormat::ColorTransfer_Gamma22; + else if (g < 3.2) + colorTransfer = QVideoFrameFormat::ColorTransfer_Gamma28; + } + if (@available(macOS 10.12, iOS 11.0, *)) { + if (CFEqual(cTransfer, kCVImageBufferTransferFunction_ITU_R_2020)) + colorTransfer = QVideoFrameFormat::ColorTransfer_BT709; + } + if (@available(macOS 10.12, iOS 11.0, *)) { + if (CFEqual(cTransfer, kCVImageBufferTransferFunction_ITU_R_2100_HLG)) { + colorTransfer = QVideoFrameFormat::ColorTransfer_STD_B67; + } else if (CFEqual(cTransfer, kCVImageBufferTransferFunction_SMPTE_ST_2084_PQ)) { + colorTransfer = QVideoFrameFormat::ColorTransfer_ST2084; + } } } + format.setColorRange(colorRangeForCVPixelFormat(cvPixelFormat)); format.setColorSpace(colorSpace); format.setColorTransfer(colorTransfer); return format; |