问题
I have implemented a camera capture using QCamera with QAbstractVideoSurface. I extended the QAbstractVideoSurface to a derived class to marshal the captures into a buffer for future processing. Everything works fine but I am having an issue changing the capture resolution of the input capture.
using setNativeResolution() does not seem to work.
Below is a brief of the code.
#ifndef _CAPTURE_BUFFER_H_
#define _CAPTURE_BUFFER_H_
#include <QMutex>
#include <QWidget>
#include <QImage>
#include <QVideoFrame>
#include <QAbstractVideoSurface>
#include <QVideoSurfaceFormat>
#include <control/qcircularbuffer.h>
class CaptureBuffer: public QAbstractVideoSurface
{
Q_OBJECT
public:
CaptureBuffer(int size = 30);
QList<QVideoFrame::PixelFormat> supportedPixelFormats(QAbstractVideoBuffer::HandleType handleType) const;
bool start(const QVideoSurfaceFormat& format);
void stop();
bool present(const QVideoFrame& frame);
bool isEmpty() const;
void pushBack(const QVideoFrame& new_frame);
void popFront();
bool top(QVideoFrame& frame);
bool back(QVideoFrame& frame);
const QImage::Format& image_format() const {return m_image_format;}
const QSize& image_size() const {return m_image_size;}
protected:
void setNativeResolution(const QSize & resolution);
private:
QSize m_image_size;
QImage::Format m_image_format;
QCircularBuffer<QVideoFrame> m_buffer;
QMutex m_buffer_mutex;
};
#endif
CaptureBuffer::CaptureBuffer(int size) :
m_buffer(QCircularBuffer<QVideoFrame>(size))
{
}
QList<QVideoFrame::PixelFormat> CaptureBuffer::supportedPixelFormats(
QAbstractVideoBuffer::HandleType handleType) const
{
if (handleType == QAbstractVideoBuffer::NoHandle) {
return QList<QVideoFrame::PixelFormat>()
<< QVideoFrame::Format_RGB24
<< QVideoFrame::Format_RGB32
<< QVideoFrame::Format_ARGB32
<< QVideoFrame::Format_ARGB32_Premultiplied
<< QVideoFrame::Format_RGB565
<< QVideoFrame::Format_RGB555;
} else {
return QList<QVideoFrame::PixelFormat>();
}
}
bool CaptureBuffer::start(const QVideoSurfaceFormat& format)
{
const QImage::Format image_format = QVideoFrame::imageFormatFromPixelFormat(format.pixelFormat());
const QSize size = format.frameSize();
if (image_format != QImage::Format_Invalid && !size.isEmpty()) {
m_image_format = image_format;
m_image_size = size;
QAbstractVideoSurface::start(format);
return true;
} else {
return false;
}
}
void CaptureBuffer::stop()
{
QAbstractVideoSurface::stop();
}
bool CaptureBuffer::present(const QVideoFrame& frame)
{
pushBack(frame);
return true;
}
bool CaptureBuffer::isEmpty() const
{
return m_buffer.empty();
}
void CaptureBuffer::pushBack(const QVideoFrame& frame)
{
m_buffer_mutex.lock();
m_buffer.push_back(frame);
m_buffer_mutex.unlock();
}
void CaptureBuffer::popFront()
{
m_buffer_mutex.lock();
m_buffer.pop_front();
m_buffer_mutex.unlock();
}
bool CaptureBuffer::top(QVideoFrame& frame)
{
if(m_buffer.empty())
return false;
m_buffer_mutex.lock();
frame = m_buffer.front();
m_buffer_mutex.unlock();
return true;
}
bool CaptureBuffer::back(QVideoFrame& frame)
{
if(m_buffer.empty())
return false;
m_buffer_mutex.lock();
frame = m_buffer.back();
m_buffer_mutex.unlock();
return true;
}
void CaptureBuffer::setNativeResolution( const QSize & resolution )
{
QAbstractVideoSurface::setNativeResolution(resolution);
}
Here is how the QCamera is used and attached to the capture buffer:
m_camera = camera;
m_camera->setCaptureMode(QCamera::CaptureVideo);
m_camera->setViewfinder(m_capture_buffer);
m_camera->start();
How do I adjust the input capture resolution to say from 640 x 480 to 1280 x 720 etc given the fact that the web camera supports this resolution.
回答1:
As of Qt5.2.1 (from git) looks like Digia did not finish QCamera completely for Windows. However there are more options how to overcome resolution setting problem.
If portability is a must:
You can try gstreamer. As I see the necessary part of the gstreamer plugin is implemented.
I work on Windows and gstreamer uses DirectShow on Windows, so I decided to go with the DirectShow plugin directly.
Qt5.2.1 has a functional DirectShow core plugin, but it is not fully connected to Qt framework itself because DSImageEncoderControl (would be derived from QImageEncoderControl) does not exists in DirectShow plugin.
QAndroidImageEncoderControl and some other mobility implementation exists. It seems Digia decided to push the Qt Mobility business first.
Anyway in the Qt documents they say:
QImageEncoderSettings imageSettings;
imageSettings.setCodec("image/jpeg");
imageSettings.setResolution(1600, 1200);
imageCapture->setEncodingSettings(imageSettings);
However when you call QCameraImageCapture::setEncodingSettings Qt tries to setup the resolution through DSImageEncoderControl, but since it is missing, that part of the code will not run. Most of the controls are not implemented yet in the DirectShow plugin.
For me another problem was that capturing a still image requires to setup surface as well, but I only want to use the image data for further processing with OpenCV for example.
Possible solution:
If you do not need cross platform stuff you can use my borrowed code from Qt's DirectShow plugin and you can set resolution and pixel format as well. In my example I tried to follow Qt's naming convention.
Another problem is at the moment QImage knows only RGB formats, but some camera devices outputs the captured data in YUYV format. Therefore a conversion needed. I also added a simple YUYV to RGB24 converter (thanks to FourCC.org) in my code to test my Laptop's camera, but mainly I use Logitech C920 Pro HD camera which outputs RGB24 as well where no conversion needed.
Download the code from here
来源:https://stackoverflow.com/questions/19583191/change-input-resolution-for-qcamera