Всем доброго времени.
Собственно сабж..
Суть в том, что оно (API) не дает поветить несколько видео-виджетов на одну камеру по-быстрому.
Нужно извращаться чтобы это обойти..
Кто-нибудь сталкивался с такй задачей?
Сохраняй в буфер, а потом уже с него на виджеты.
Хмм.. кажется получилось (по-другому). :P
Мне нужно было выводить несколько картинок (дублировать их) используя только одну камеру.
Вот что вышло:
1) VideoProducer - "размножает" видео-стрим от одной камеры всем получателям.
= videoproducer.h =
C++ (Qt)
#ifndef VIDEOPRODUCER_H
#define VIDEOPRODUCER_H
#include <QObject>
class QAbstractVideoSurface;
class VideoProducer : public QObject
{
Q_OBJECT
public:
Q_PROPERTY(QAbstractVideoSurface *videoSurface READ videoSurface WRITE setVideoSurface)
explicit VideoProducer(QObject *parent = 0);
~VideoProducer();
QAbstractVideoSurface *videoSurface() const;
void setVideoSurface(QAbstractVideoSurface *surface);
static void registerQmlType();
private:
void closeSurface();
QAbstractVideoSurface *m_surface;
};
#endif // VIDEOPRODUCER_H
= videoproducer.cpp =
C++ (Qt)
#include "videoproducer.h"
#include <QCamera>
#include <QCameraInfo>
#include <QAbstractVideoSurface>
#include <QVideoSurfaceFormat>
#include <QList>
#include <QtQml/qqml.h>
class InterceptorSurface : public QAbstractVideoSurface
{
public:
static InterceptorSurface *instance()
{
static InterceptorSurface inst;
return &inst;
}
void registerVideoProducer(VideoProducer *producer)
{
if (!m_producers.contains(producer))
m_producers.append(producer);
}
void unregisterVideoProducer(VideoProducer *producer)
{
for (int i = 0; i < m_producers.count() ; ++i) {
if (m_producers.at(i) == producer) {
m_producers.takeAt(i);
return;
}
}
}
QList<QVideoFrame::PixelFormat> supportedPixelFormats(QAbstractVideoBuffer::HandleType handleType) const
{
return QList<QVideoFrame::PixelFormat>()
<< QVideoFrame::Format_ARGB32
<< QVideoFrame::Format_ARGB32_Premultiplied
<< QVideoFrame::Format_RGB32
<< QVideoFrame::Format_RGB24
<< QVideoFrame::Format_RGB565
<< QVideoFrame::Format_RGB555
<< QVideoFrame::Format_ARGB8565_Premultiplied
<< QVideoFrame::Format_BGRA32
<< QVideoFrame::Format_BGRA32_Premultiplied
<< QVideoFrame::Format_BGR32
<< QVideoFrame::Format_BGR24
<< QVideoFrame::Format_BGR565
<< QVideoFrame::Format_BGR555
<< QVideoFrame::Format_BGRA5658_Premultiplied
<< QVideoFrame::Format_AYUV444
<< QVideoFrame::Format_AYUV444_Premultiplied
<< QVideoFrame::Format_YUV444
<< QVideoFrame::Format_YUV420P
<< QVideoFrame::Format_YV12
<< QVideoFrame::Format_UYVY
<< QVideoFrame::Format_YUYV
<< QVideoFrame::Format_NV12
<< QVideoFrame::Format_NV21
<< QVideoFrame::Format_IMC1
<< QVideoFrame::Format_IMC2
<< QVideoFrame::Format_IMC3
<< QVideoFrame::Format_IMC4
<< QVideoFrame::Format_Y8
<< QVideoFrame::Format_Y16
<< QVideoFrame::Format_Jpeg
<< QVideoFrame::Format_CameraRaw
<< QVideoFrame::Format_AdobeDng;
}
bool start(const QVideoSurfaceFormat &format)
{
if (m_format != format)
m_format = format;
return QAbstractVideoSurface::start(format);
}
bool present(const QVideoFrame &frame)
{
if (!frame.isValid())
return false;
QVideoFrame copy(frame);
if (copy.map(QAbstractVideoBuffer::ReadOnly)) {
foreach (VideoProducer *producer, m_producers) {
QAbstractVideoSurface *surface = producer->videoSurface();
if (!surface)
continue;
if (!surface->isActive())
surface->start(m_format);
surface->present(copy);
}
copy.unmap();
}
return true;
}
private:
InterceptorSurface(QObject *parent = 0)
: QAbstractVideoSurface(parent)
{
m_camera = new QCamera(this);
m_camera->setViewfinder(this);
m_camera->start();
}
QCamera *m_camera;
QList<VideoProducer *> m_producers;
QVideoSurfaceFormat m_format;
};
void VideoProducer::registerQmlType()
{
qmlRegisterType<VideoProducer>("VideoProducer", 0, 1, "VideoProducer");
}
VideoProducer::VideoProducer(QObject *parent)
: QObject(parent)
, m_surface(0)
{
InterceptorSurface::instance()->registerVideoProducer(this);
}
VideoProducer::~VideoProducer()
{
InterceptorSurface::instance()->unregisterVideoProducer(this);
closeSurface();
}
QAbstractVideoSurface *VideoProducer::videoSurface() const
{
return m_surface;
}
void VideoProducer::setVideoSurface(QAbstractVideoSurface *surface)
{
closeSurface();
m_surface = surface;
}
void VideoProducer::closeSurface()
{
if (m_surface && m_surface->isActive())
m_surface->stop();
}
2) = main.qml =
Java
import QtQuick 2.2
import QtQuick.Window 2.1
import QtMultimedia 5.0
import VideoProducer 0.1
Window {
id: root
visible: true
width: 360
height: 360
VideoProducer {
id: videoProducer1;
}
VideoProducer {
id: videoProducer2;
}
Column {
VideoOutput {
width: 200; height: 200
source: videoProducer1;
}
VideoOutput {
width: 200; height: 200
source: videoProducer2;
}
}
}
3) = main.cpp =
C++ (Qt)
#include <QApplication>
#include <QQmlApplicationEngine>
#include"videoproducer.h"
int main(int argc, char *argv[])
{
VideoProducer::registerQmlType();
QApplication app(argc, argv);
QQmlApplicationEngine engine;
engine.load(QUrl(QStringLiteral("qrc:///main.qml")));
return app.exec();
}
Вроде оно все работает, но непонятен момент, откуда брать список поддерживаемых пиксель-форматов supportedPixelFormats()?
Сейчас я там "тупо" перечисляю все возможные форматы.. но как-то это не правильно..
Есть у кого идеи, или может быть, замечания (что не так?) ? :)