summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTimur Pocheptsov <Timur.Pocheptsov@digia.com>2015-03-17 09:48:54 +0100
committerTimur Pocheptsov <Timur.Pocheptsov@digia.com>2015-03-20 13:23:00 +0000
commit09afe9377d41171368c083b7cb79fd888f6d8979 (patch)
treea992ca2f46756e3b6c7b32eb0d4a4fb8413c878e
parent10354f4127cc569535f28e7f758b58c5bd18bcd6 (diff)
AVFCameraViewfinderSettings - add NV12 format
Add QVideoFrame::Format_NV12 (AVFoundation has kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange and kCVPixelFormatType_420YpCbCr8BiPlanarFullRange). Report it (set it) only if it's supported by renderer's surface. Add bi-planar format support into CVPixelBufferVideoBuffer. Change-Id: Ibc1c2be056bddf5cf3b595570fc40c626ee3ccf5 Reviewed-by: Yoann Lopes <yoann.lopes@theqtcompany.com>
-rw-r--r--src/plugins/avfoundation/camera/avfcamerarenderercontrol.mm45
-rw-r--r--src/plugins/avfoundation/camera/avfcameraviewfindersettingscontrol.h1
-rw-r--r--src/plugins/avfoundation/camera/avfcameraviewfindersettingscontrol.mm77
3 files changed, 94 insertions, 29 deletions
diff --git a/src/plugins/avfoundation/camera/avfcamerarenderercontrol.mm b/src/plugins/avfoundation/camera/avfcamerarenderercontrol.mm
index 87bfeb82a..cf13635f0 100644
--- a/src/plugins/avfoundation/camera/avfcamerarenderercontrol.mm
+++ b/src/plugins/avfoundation/camera/avfcamerarenderercontrol.mm
@@ -32,6 +32,7 @@
****************************************************************************/
#include "avfcameraviewfindersettingscontrol.h"
+#include "private/qabstractvideobuffer_p.h"
#include "avfcamerarenderercontrol.h"
#include "avfcamerasession.h"
#include "avfcameraservice.h"
@@ -39,15 +40,17 @@
#include <QtMultimedia/qabstractvideosurface.h>
#include <QtMultimedia/qabstractvideobuffer.h>
+
#include <QtMultimedia/qvideosurfaceformat.h>
QT_USE_NAMESPACE
-class CVPixelBufferVideoBuffer : public QAbstractVideoBuffer
+class CVPixelBufferVideoBuffer : public QAbstractPlanarVideoBuffer
{
+ friend class CVPixelBufferVideoBufferPrivate;
public:
CVPixelBufferVideoBuffer(CVPixelBufferRef buffer)
- : QAbstractVideoBuffer(NoHandle)
+ : QAbstractPlanarVideoBuffer(NoHandle)
, m_buffer(buffer)
, m_mode(NotMapped)
{
@@ -61,6 +64,42 @@ public:
MapMode mapMode() const { return m_mode; }
+ int map(QAbstractVideoBuffer::MapMode mode, int *numBytes, int bytesPerLine[4], uchar *data[4])
+ {
+ // We only support RGBA or NV12 (or Apple's version of NV12),
+ // they are either 0 planes or 2.
+ const size_t nPlanes = CVPixelBufferGetPlaneCount(m_buffer);
+ Q_ASSERT(nPlanes <= 2);
+
+ if (!nPlanes) {
+ data[0] = map(mode, numBytes, bytesPerLine);
+ return data[0] ? 1 : 0;
+ }
+
+ // For a bi-planar format we have to set the parameters correctly:
+ if (mode != QAbstractVideoBuffer::NotMapped && m_mode == QAbstractVideoBuffer::NotMapped) {
+ CVPixelBufferLockBaseAddress(m_buffer, 0);
+
+ if (numBytes)
+ *numBytes = CVPixelBufferGetDataSize(m_buffer);
+
+ if (bytesPerLine) {
+ // At the moment we handle only bi-planar format.
+ bytesPerLine[0] = CVPixelBufferGetBytesPerRowOfPlane(m_buffer, 0);
+ bytesPerLine[1] = CVPixelBufferGetBytesPerRowOfPlane(m_buffer, 1);
+ }
+
+ if (data) {
+ data[0] = (uchar *)CVPixelBufferGetBaseAddressOfPlane(m_buffer, 0);
+ data[1] = (uchar *)CVPixelBufferGetBaseAddressOfPlane(m_buffer, 1);
+ }
+
+ m_mode = mode;
+ }
+
+ return nPlanes;
+ }
+
uchar *map(MapMode mode, int *numBytes, int *bytesPerLine)
{
if (mode != NotMapped && m_mode == NotMapped) {
@@ -73,7 +112,6 @@ public:
*bytesPerLine = CVPixelBufferGetBytesPerRow(m_buffer);
m_mode = mode;
-
return (uchar*)CVPixelBufferGetBaseAddress(m_buffer);
} else {
return 0;
@@ -93,6 +131,7 @@ private:
MapMode m_mode;
};
+
@interface AVFCaptureFramesDelegate : NSObject <AVCaptureVideoDataOutputSampleBufferDelegate>
{
@private
diff --git a/src/plugins/avfoundation/camera/avfcameraviewfindersettingscontrol.h b/src/plugins/avfoundation/camera/avfcameraviewfindersettingscontrol.h
index fccc938a9..cf2f512a7 100644
--- a/src/plugins/avfoundation/camera/avfcameraviewfindersettingscontrol.h
+++ b/src/plugins/avfoundation/camera/avfcameraviewfindersettingscontrol.h
@@ -74,6 +74,7 @@ private:
void setFramerate(qreal minFPS, qreal maxFPS, bool useActive);
void setPixelFormat(QVideoFrame::PixelFormat newFormat);
AVCaptureDeviceFormat *findBestFormatMatch(const QCameraViewfinderSettings &settings) const;
+ QVector<QVideoFrame::PixelFormat> viewfinderPixelFormats() const;
bool convertPixelFormatIfSupported(QVideoFrame::PixelFormat format, unsigned &avfFormat) const;
void applySettings();
QCameraViewfinderSettings requestedSettings() const;
diff --git a/src/plugins/avfoundation/camera/avfcameraviewfindersettingscontrol.mm b/src/plugins/avfoundation/camera/avfcameraviewfindersettingscontrol.mm
index 250aae9c1..60df1e2ed 100644
--- a/src/plugins/avfoundation/camera/avfcameraviewfindersettingscontrol.mm
+++ b/src/plugins/avfoundation/camera/avfcameraviewfindersettingscontrol.mm
@@ -38,6 +38,8 @@
#include "avfcameraservice.h"
#include "avfcameradebug.h"
+#include <QtMultimedia/qabstractvideosurface.h>
+
#include <QtCore/qvariant.h>
#include <QtCore/qsysinfo.h>
#include <QtCore/qvector.h>
@@ -52,28 +54,6 @@ QT_BEGIN_NAMESPACE
namespace {
-QVector<QVideoFrame::PixelFormat> qt_viewfinder_pixel_formats(AVCaptureVideoDataOutput *videoOutput)
-{
- Q_ASSERT(videoOutput);
-
- QVector<QVideoFrame::PixelFormat> qtFormats;
-
- NSArray *pixelFormats = [videoOutput availableVideoCVPixelFormatTypes];
- for (NSObject *obj in pixelFormats) {
- if (![obj isKindOfClass:[NSNumber class]])
- continue;
-
- NSNumber *formatAsNSNumber = static_cast<NSNumber *>(obj);
- // It's actually FourCharCode (== UInt32):
- const QVideoFrame::PixelFormat qtFormat(AVFCameraViewfinderSettingsControl2::
- QtPixelFormatFromCVFormat([formatAsNSNumber unsignedIntValue]));
- if (qtFormat != QVideoFrame::Format_Invalid)
- qtFormats << qtFormat;
- }
-
- return qtFormats;
-}
-
bool qt_framerates_sane(const QCameraViewfinderSettings &settings)
{
const qreal minFPS = settings.minimumFrameRate();
@@ -269,7 +249,8 @@ QList<QCameraViewfinderSettings> AVFCameraViewfinderSettingsControl2::supportedV
QVector<AVFPSRange> framerates;
- QVector<QVideoFrame::PixelFormat> pixelFormats(qt_viewfinder_pixel_formats(m_videoOutput));
+ QVector<QVideoFrame::PixelFormat> pixelFormats(viewfinderPixelFormats());
+
if (!pixelFormats.size())
pixelFormats << QVideoFrame::Format_Invalid; // The default value.
#if QT_MAC_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_7, __IPHONE_7_0)
@@ -397,6 +378,9 @@ QVideoFrame::PixelFormat AVFCameraViewfinderSettingsControl2::QtPixelFormatFromC
return QVideoFrame::Format_RGB24;
case kCVPixelFormatType_24BGR:
return QVideoFrame::Format_BGR24;
+ case kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange:
+ case kCVPixelFormatType_420YpCbCr8BiPlanarFullRange:
+ return QVideoFrame::Format_NV12;
default:
return QVideoFrame::Format_Invalid;
}
@@ -414,6 +398,9 @@ bool AVFCameraViewfinderSettingsControl2::CVPixelFormatFromQtFormat(QVideoFrame:
case QVideoFrame::Format_BGRA32:
conv = kCVPixelFormatType_32ARGB;
break;
+ case QVideoFrame::Format_NV12:
+ conv = kCVPixelFormatType_420YpCbCr8BiPlanarFullRange;
+ break;
// These two formats below are not supported
// by QSGVideoNodeFactory_RGB, so for now I have to
// disable them.
@@ -467,7 +454,37 @@ AVCaptureDeviceFormat *AVFCameraViewfinderSettingsControl2::findBestFormatMatch(
return nil;
}
-bool AVFCameraViewfinderSettingsControl2::convertPixelFormatIfSupported(QVideoFrame::PixelFormat qtFormat, unsigned &avfFormat)const
+QVector<QVideoFrame::PixelFormat> AVFCameraViewfinderSettingsControl2::viewfinderPixelFormats() const
+{
+ Q_ASSERT(m_videoOutput);
+
+ QVector<QVideoFrame::PixelFormat> qtFormats;
+ QList<QVideoFrame::PixelFormat> filter;
+
+ NSArray *pixelFormats = [m_videoOutput availableVideoCVPixelFormatTypes];
+ const QAbstractVideoSurface *surface = m_service->videoOutput() ? m_service->videoOutput()->surface() : 0;
+
+ if (surface)
+ filter = surface->supportedPixelFormats();
+
+ for (NSObject *obj in pixelFormats) {
+ if (![obj isKindOfClass:[NSNumber class]])
+ continue;
+
+ NSNumber *formatAsNSNumber = static_cast<NSNumber *>(obj);
+ // It's actually FourCharCode (== UInt32):
+ const QVideoFrame::PixelFormat qtFormat(QtPixelFormatFromCVFormat([formatAsNSNumber unsignedIntValue]));
+ if (qtFormat != QVideoFrame::Format_Invalid && (!surface || filter.contains(qtFormat))
+ && !qtFormats.contains(qtFormat)) { // Can happen, for example, with 8BiPlanar existing in video/full range.
+ qtFormats << qtFormat;
+ }
+ }
+
+ return qtFormats;
+}
+
+bool AVFCameraViewfinderSettingsControl2::convertPixelFormatIfSupported(QVideoFrame::PixelFormat qtFormat,
+ unsigned &avfFormat)const
{
Q_ASSERT(m_videoOutput);
@@ -479,17 +496,25 @@ bool AVFCameraViewfinderSettingsControl2::convertPixelFormatIfSupported(QVideoFr
if (!formats || !formats.count)
return false;
+ if (m_service->videoOutput() && m_service->videoOutput()->surface()) {
+ const QAbstractVideoSurface *surface = m_service->videoOutput()->surface();
+ if (!surface->supportedPixelFormats().contains(qtFormat))
+ return false;
+ }
+
+ bool found = false;
for (NSObject *obj in formats) {
if (![obj isKindOfClass:[NSNumber class]])
continue;
+
NSNumber *nsNum = static_cast<NSNumber *>(obj);
if ([nsNum unsignedIntValue] == conv) {
avfFormat = conv;
- return true;
+ found = true;
}
}
- return false;
+ return found;
}
void AVFCameraViewfinderSettingsControl2::applySettings()