Qt: Preliminary QCamera support

This commit is contained in:
Vicki Pfau 2017-07-26 13:51:30 -07:00
parent a1acf8bcef
commit cf15ea91d7
5 changed files with 125 additions and 3 deletions

View File

@ -157,6 +157,8 @@ if(Qt5Multimedia_FOUND)
list(APPEND AUDIO_SRC
AudioProcessorQt.cpp
AudioDevice.cpp)
list(APPEND SOURCE_FILES
VideoDumper.cpp)
if (WIN32 AND QT_STATIC)
list(APPEND QT_LIBRARIES qtaudio_windows strmiids winmm)
endif()

View File

@ -13,6 +13,9 @@
#include <QApplication>
#include <QTimer>
#include <QWidget>
#ifdef BUILD_QT_MULTIMEDIA
#include <QCamera>
#endif
#include <mgba/core/interface.h>
#include <mgba-util/configuration.h>
@ -53,6 +56,10 @@ InputController::InputController(int playerId, QWidget* topLevel, QObject* paren
m_gamepadTimer.setInterval(50);
m_gamepadTimer.start();
#ifdef BUILD_QT_MULTIMEDIA
connect(&m_videoDumper, &VideoDumper::imageAvailable, this, &InputController::setCamImage);
#endif
mInputBindKey(&m_inputMap, KEYBOARD, Qt::Key_X, GBA_KEY_A);
mInputBindKey(&m_inputMap, KEYBOARD, Qt::Key_Z, GBA_KEY_B);
mInputBindKey(&m_inputMap, KEYBOARD, Qt::Key_A, GBA_KEY_L);
@ -79,13 +86,33 @@ InputController::InputController(int playerId, QWidget* topLevel, QObject* paren
setLuminanceLevel(0);
#endif
m_image.p = this;
m_image.startRequestImage = [](mImageSource* context) {
InputControllerImage* image = static_cast<InputControllerImage*>(context);
if (image->image.isNull()) {
image->image.load(":/res/no-cam.png");
}
#ifdef BUILD_QT_MULTIMEDIA
if (image->p->m_config->getQtOption("cameraDriver").toInt() == static_cast<int>(CameraDriver::QT_MULTIMEDIA)) {
if (!image->p->m_camera) {
image->p->m_camera = new QCamera;
}
image->p->m_camera->setViewfinder(&image->p->m_videoDumper);
image->p->m_camera->start();
}
#endif
};
m_image.stopRequestImage = nullptr;
m_image.stopRequestImage = [](mImageSource* context) {
InputControllerImage* image = static_cast<InputControllerImage*>(context);
#ifdef BUILD_QT_MULTIMEDIA
if (image->p->m_camera) {
image->p->m_camera->stop();
delete image->p->m_camera;
}
#endif
};
m_image.requestImage = [](mImageSource* context, unsigned w, unsigned h, const uint32_t** buffer, size_t* stride) {
InputControllerImage* image = static_cast<InputControllerImage*>(context);
image->resizedImage = image->image.scaled(w, h, Qt::KeepAspectRatioByExpanding);
@ -650,6 +677,11 @@ void InputController::loadCamImage(const QString& path) {
m_image.resizedImage = QImage();
}
void InputController::setCamImage(const QImage& image) {
m_image.image = image;
m_image.resizedImage = QImage();
}
void InputController::increaseLuminanceLevel() {
setLuminanceLevel(m_luxLevel + 1);
}

View File

@ -22,9 +22,16 @@
#include "platform/sdl/sdl-events.h"
#endif
#ifdef BUILD_QT_MULTIMEDIA
#include "VideoDumper.h"
#endif
struct mRotationSource;
struct mRumble;
class QCamera;
namespace QGBA {
class ConfigController;
@ -33,6 +40,13 @@ class InputController : public QObject {
Q_OBJECT
public:
enum class CameraDriver : int {
NONE = 0,
#ifdef BUILD_QT_MULTIMEDIA
QT_MULTIMEDIA = 1,
#endif
};
static const uint32_t KEYBOARD = 0x51545F4B;
InputController(int playerId = 0, QWidget* topLevel = nullptr, QObject* parent = nullptr);
@ -81,8 +95,6 @@ public:
void stealFocus(QWidget* focus);
void releaseFocus(QWidget* focus);
void loadCamImage(const QString& path);
mRumble* rumble();
mRotationSource* rotationSource();
mImageSource* imageSource() { return &m_image; }
@ -106,6 +118,9 @@ public slots:
void setLuminanceLevel(int level);
void setLuminanceValue(uint8_t value);
void loadCamImage(const QString& path);
void setCamImage(const QImage& image);
private:
void postPendingEvent(GBAKey);
void clearPendingEvent(GBAKey);
@ -125,6 +140,11 @@ private:
QImage resizedImage;
} m_image;
#ifdef BUILD_QT_MULTIMEDIA
QCamera* m_camera = nullptr;
VideoDumper m_videoDumper;
#endif
mInputMap m_inputMap;
ConfigController* m_config = nullptr;
int m_playerId;

View File

@ -0,0 +1,41 @@
/* Copyright (c) 2013-2017 Jeffrey Pfau
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "VideoDumper.h"
#include <QImage>
using namespace QGBA;
VideoDumper::VideoDumper(QObject* parent)
: QAbstractVideoSurface(parent)
{
}
bool VideoDumper::present(const QVideoFrame& frame) {
QVideoFrame mappedFrame(frame);
if (!mappedFrame.map(QAbstractVideoBuffer::ReadOnly)) {
return false;
}
QImage::Format format = QVideoFrame::imageFormatFromPixelFormat(mappedFrame.pixelFormat());
const uchar* bits = mappedFrame.bits();
QImage image(bits, mappedFrame.width(), mappedFrame.height(), mappedFrame.bytesPerLine(),
format);
image = std::move(image.copy()); // Create a deep copy of the bits
emit imageAvailable(image);
mappedFrame.unmap();
return true;
}
QList<QVideoFrame::PixelFormat> VideoDumper::supportedPixelFormats(QAbstractVideoBuffer::HandleType) const {
QList<QVideoFrame::PixelFormat> list;
list.append(QVideoFrame::Format_ARGB32);
list.append(QVideoFrame::Format_ARGB32_Premultiplied);
list.append(QVideoFrame::Format_RGB32);
list.append(QVideoFrame::Format_RGB24);
list.append(QVideoFrame::Format_RGB565);
list.append(QVideoFrame::Format_RGB555);
return list;
}

View File

@ -0,0 +1,27 @@
/* Copyright (c) 2013-2017 Jeffrey Pfau
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef QGBA_VIDEO_DUMPER
#define QGBA_VIDEO_DUMPER
#include <QAbstractVideoSurface>
namespace QGBA {
class VideoDumper : public QAbstractVideoSurface {
Q_OBJECT
public:
VideoDumper(QObject* parent = nullptr);
bool present(const QVideoFrame& frame) override;
QList<QVideoFrame::PixelFormat> supportedPixelFormats(QAbstractVideoBuffer::HandleType type = QAbstractVideoBuffer::NoHandle) const override;
signals:
void imageAvailable(const QImage& image);
};
}
#endif