summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorYoann Lopes <yoann.lopes@digia.com>2014-02-07 14:23:32 +0100
committerThe Qt Project <gerrit-noreply@qt-project.org>2014-02-14 15:05:13 +0100
commit54066d2c216e871e3f4c08590f0e010dd2e76e69 (patch)
tree2366ddd520ed4f337b3f31d5deedb226dd2e7bd9 /src
parentc6ec402d257dfc49a98d2f88989b6dfee7bc4e8a (diff)
AVFoundation: mirror viewfinder frames of front-facing cameras.
Change-Id: I95920aa459ff0931819cb6f8278ab296db542601 Reviewed-by: Andy Nichols <andy.nichols@digia.com>
Diffstat (limited to 'src')
-rw-r--r--src/plugins/avfoundation/camera/avfcamerasession.h1
-rw-r--r--src/plugins/avfoundation/camera/avfcamerasession.mm10
-rw-r--r--src/plugins/avfoundation/camera/avfvideorenderercontrol.h7
-rw-r--r--src/plugins/avfoundation/camera/avfvideorenderercontrol.mm45
4 files changed, 56 insertions, 7 deletions
diff --git a/src/plugins/avfoundation/camera/avfcamerasession.h b/src/plugins/avfoundation/camera/avfcamerasession.h
index 48681aae7..2630a35f7 100644
--- a/src/plugins/avfoundation/camera/avfcamerasession.h
+++ b/src/plugins/avfoundation/camera/avfcamerasession.h
@@ -64,6 +64,7 @@ public:
void setVideoOutput(AVFVideoRendererControl *output);
AVCaptureSession *captureSession() const { return m_captureSession; }
+ AVCaptureDevice *videoCaptureDevice() const;
QCamera::State state() const;
QCamera::State requestedState() const { return m_state; }
diff --git a/src/plugins/avfoundation/camera/avfcamerasession.mm b/src/plugins/avfoundation/camera/avfcamerasession.mm
index 5f1385a7e..93c2bacd0 100644
--- a/src/plugins/avfoundation/camera/avfcamerasession.mm
+++ b/src/plugins/avfoundation/camera/avfcamerasession.mm
@@ -155,7 +155,15 @@ void AVFCameraSession::setVideoOutput(AVFVideoRendererControl *output)
{
m_videoOutput = output;
if (output)
- output->configureAVCaptureSession(m_captureSession);
+ output->configureAVCaptureSession(this);
+}
+
+AVCaptureDevice *AVFCameraSession::videoCaptureDevice() const
+{
+ if (m_videoInput)
+ return m_videoInput.device;
+
+ return 0;
}
QCamera::State AVFCameraSession::state() const
diff --git a/src/plugins/avfoundation/camera/avfvideorenderercontrol.h b/src/plugins/avfoundation/camera/avfvideorenderercontrol.h
index 57978c05a..c080451c3 100644
--- a/src/plugins/avfoundation/camera/avfvideorenderercontrol.h
+++ b/src/plugins/avfoundation/camera/avfvideorenderercontrol.h
@@ -66,7 +66,7 @@ public:
QAbstractVideoSurface *surface() const;
void setSurface(QAbstractVideoSurface *surface);
- void configureAVCaptureSession(AVCaptureSession *captureSession);
+ void configureAVCaptureSession(AVFCameraSession *cameraSession);
void syncHandleViewfinderFrame(const QVideoFrame &frame);
Q_SIGNALS:
@@ -74,13 +74,16 @@ Q_SIGNALS:
private Q_SLOTS:
void handleViewfinderFrame();
+ void updateCaptureConnection();
private:
QAbstractVideoSurface *m_surface;
AVFCaptureFramesDelegate *m_viewfinderFramesDelegate;
- AVCaptureSession *m_captureSession;
+ AVFCameraSession *m_cameraSession;
AVCaptureVideoDataOutput *m_videoDataOutput;
+ bool m_needsHorizontalMirroring;
+
QVideoFrame m_lastViewfinderFrame;
QMutex m_vfMutex;
};
diff --git a/src/plugins/avfoundation/camera/avfvideorenderercontrol.mm b/src/plugins/avfoundation/camera/avfvideorenderercontrol.mm
index 6efa3cbf8..1a2054452 100644
--- a/src/plugins/avfoundation/camera/avfvideorenderercontrol.mm
+++ b/src/plugins/avfoundation/camera/avfvideorenderercontrol.mm
@@ -146,13 +146,14 @@ private:
AVFVideoRendererControl::AVFVideoRendererControl(QObject *parent)
: QVideoRendererControl(parent)
, m_surface(0)
+ , m_needsHorizontalMirroring(false)
{
m_viewfinderFramesDelegate = [[AVFCaptureFramesDelegate alloc] initWithRenderer:this];
}
AVFVideoRendererControl::~AVFVideoRendererControl()
{
- [m_captureSession removeOutput:m_videoDataOutput];
+ [m_cameraSession->captureSession() removeOutput:m_videoDataOutput];
[m_viewfinderFramesDelegate release];
}
@@ -169,9 +170,13 @@ void AVFVideoRendererControl::setSurface(QAbstractVideoSurface *surface)
}
}
-void AVFVideoRendererControl::configureAVCaptureSession(AVCaptureSession *captureSession)
+void AVFVideoRendererControl::configureAVCaptureSession(AVFCameraSession *cameraSession)
{
- m_captureSession = captureSession;
+ m_cameraSession = cameraSession;
+ connect(m_cameraSession, SIGNAL(readyToConfigureConnections()),
+ this, SLOT(updateCaptureConnection()));
+
+ m_needsHorizontalMirroring = false;
m_videoDataOutput = [[[AVCaptureVideoDataOutput alloc] init] autorelease];
@@ -188,7 +193,23 @@ void AVFVideoRendererControl::configureAVCaptureSession(AVCaptureSession *captur
[NSNumber numberWithInt:kCVPixelFormatType_32BGRA]
forKey:(id)kCVPixelBufferPixelFormatTypeKey];
- [m_captureSession addOutput:m_videoDataOutput];
+ [m_cameraSession->captureSession() addOutput:m_videoDataOutput];
+}
+
+void AVFVideoRendererControl::updateCaptureConnection()
+{
+ AVCaptureConnection *connection = [m_videoDataOutput connectionWithMediaType:AVMediaTypeVideo];
+ if (connection == nil || !m_cameraSession->videoCaptureDevice())
+ return;
+
+ // Frames of front-facing cameras should be mirrored horizontally (it's the default when using
+ // AVCaptureVideoPreviewLayer but not with AVCaptureVideoDataOutput)
+ if (connection.isVideoMirroringSupported)
+ connection.videoMirrored = m_cameraSession->videoCaptureDevice().position == AVCaptureDevicePositionFront;
+
+ // If the connection does't support mirroring, we'll have to do it ourselves
+ m_needsHorizontalMirroring = !connection.isVideoMirrored
+ && m_cameraSession->videoCaptureDevice().position == AVCaptureDevicePositionFront;
}
//can be called from non main thread
@@ -203,6 +224,22 @@ void AVFVideoRendererControl::syncHandleViewfinderFrame(const QVideoFrame &frame
}
m_lastViewfinderFrame = frame;
+
+ if (m_needsHorizontalMirroring) {
+ m_lastViewfinderFrame.map(QAbstractVideoBuffer::ReadOnly);
+
+ // no deep copy
+ QImage image(m_lastViewfinderFrame.bits(),
+ m_lastViewfinderFrame.size().width(),
+ m_lastViewfinderFrame.size().height(),
+ m_lastViewfinderFrame.bytesPerLine(),
+ QImage::Format_RGB32);
+
+ QImage mirrored = image.mirrored(true, false);
+
+ m_lastViewfinderFrame.unmap();
+ m_lastViewfinderFrame = QVideoFrame(mirrored);
+ }
}
void AVFVideoRendererControl::handleViewfinderFrame()