GStreamer: port to 1.0.
0.10 is still used by default. To enable GStreamer 1.0, pass GST_VERSION=1.0 to qmake for qtmultimedia.pro. Contributions from: Andrew den Exter <andrew.den.exter@qinetic.com.au> Ilya Smelykh <ilya@videoexpertsgroup.com> Jim Hodapp <jim.hodapp@canonical.com> Sergio Schvezov <sergio.schvezov@canonical.com> Change-Id: I72a46d1170a8794a149bdb5e20767afcc5b7587c Reviewed-by: Andrew den Exter <andrew.den.exter@qinetic.com.au>
This commit is contained in:
committed by
Andrew den Exter
parent
7e3d69668e
commit
108dda7a90
@@ -79,7 +79,7 @@ config_gstreamer_photography {
|
||||
$$PWD/camerabinlocks.cpp \
|
||||
$$PWD/camerabinzoom.cpp
|
||||
|
||||
LIBS += -lgstphotography-0.10
|
||||
LIBS += -lgstphotography-$$GST_VERSION
|
||||
DEFINES += GST_USE_UNSTABLE_API #prevents warnings because of unstable photography API
|
||||
}
|
||||
|
||||
|
||||
@@ -96,7 +96,7 @@ GstEncodingContainerProfile *CameraBinContainer::createProfile()
|
||||
GstCaps *caps;
|
||||
|
||||
if (m_actualFormat.isEmpty()) {
|
||||
caps = gst_caps_new_any();
|
||||
return 0;
|
||||
} else {
|
||||
QString format = m_actualFormat;
|
||||
QStringList supportedFormats = m_supportedContainers.supportedCodecs();
|
||||
|
||||
@@ -95,11 +95,6 @@ void CameraBinControl::setCaptureMode(QCamera::CaptureModes mode)
|
||||
captureMode() == QCamera::CaptureStillImage ?
|
||||
CamerabinResourcePolicy::ImageCaptureResources :
|
||||
CamerabinResourcePolicy::VideoCaptureResources);
|
||||
#if (GST_VERSION_MAJOR == 0) && ((GST_VERSION_MINOR < 10) || (GST_VERSION_MICRO < 23))
|
||||
//due to bug in v4l2src, it's necessary to reload camera on video caps changes
|
||||
//https://bugzilla.gnome.org/show_bug.cgi?id=649832
|
||||
reloadLater();
|
||||
#endif
|
||||
}
|
||||
emit captureModeChanged(mode);
|
||||
}
|
||||
@@ -299,6 +294,8 @@ bool CameraBinControl::canChangeProperty(PropertyChangeType changeType, QCamera:
|
||||
|
||||
switch (changeType) {
|
||||
case QCameraControl::CaptureMode:
|
||||
return status != QCamera::ActiveStatus;
|
||||
break;
|
||||
case QCameraControl::ImageEncodingSettings:
|
||||
case QCameraControl::VideoEncodingSettings:
|
||||
case QCameraControl::Viewfinder:
|
||||
|
||||
@@ -37,6 +37,10 @@
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
#if !GST_CHECK_VERSION(1,0,0)
|
||||
typedef GstSceneMode GstPhotographySceneMode;
|
||||
#endif
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
CameraBinExposure::CameraBinExposure(CameraBinSession *session)
|
||||
@@ -119,7 +123,7 @@ QVariant CameraBinExposure::actualValue(ExposureParameter parameter) const
|
||||
}
|
||||
case QCameraExposureControl::ExposureMode:
|
||||
{
|
||||
GstSceneMode sceneMode;
|
||||
GstPhotographySceneMode sceneMode;
|
||||
gst_photography_get_scene_mode(m_session->photography(), &sceneMode);
|
||||
|
||||
switch (sceneMode) {
|
||||
@@ -167,7 +171,7 @@ bool CameraBinExposure::setValue(ExposureParameter parameter, const QVariant& va
|
||||
case QCameraExposureControl::ExposureMode:
|
||||
{
|
||||
QCameraExposure::ExposureMode mode = QCameraExposure::ExposureMode(value.toInt());
|
||||
GstSceneMode sceneMode;
|
||||
GstPhotographySceneMode sceneMode;
|
||||
gst_photography_get_scene_mode(m_session->photography(), &sceneMode);
|
||||
|
||||
switch (mode) {
|
||||
|
||||
@@ -37,6 +37,10 @@
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
#if !GST_CHECK_VERSION(1,0,0)
|
||||
typedef GstFlashMode GstPhotographyFlashMode;
|
||||
#endif
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
CameraBinFlash::CameraBinFlash(CameraBinSession *session)
|
||||
@@ -51,7 +55,7 @@ CameraBinFlash::~CameraBinFlash()
|
||||
|
||||
QCameraExposure::FlashModes CameraBinFlash::flashMode() const
|
||||
{
|
||||
GstFlashMode flashMode;
|
||||
GstPhotographyFlashMode flashMode;
|
||||
gst_photography_get_flash_mode(m_session->photography(), &flashMode);
|
||||
|
||||
QCameraExposure::FlashModes modes;
|
||||
@@ -70,7 +74,7 @@ QCameraExposure::FlashModes CameraBinFlash::flashMode() const
|
||||
|
||||
void CameraBinFlash::setFlashMode(QCameraExposure::FlashModes mode)
|
||||
{
|
||||
GstFlashMode flashMode;
|
||||
GstPhotographyFlashMode flashMode;
|
||||
gst_photography_get_flash_mode(m_session->photography(), &flashMode);
|
||||
|
||||
if (mode.testFlag(QCameraExposure::FlashAuto)) flashMode = GST_PHOTOGRAPHY_FLASH_MODE_AUTO;
|
||||
|
||||
@@ -39,6 +39,12 @@
|
||||
#include <QDebug>
|
||||
#include <QtCore/qmetaobject.h>
|
||||
|
||||
#include <private/qgstutils_p.h>
|
||||
|
||||
#if !GST_CHECK_VERSION(1,0,0)
|
||||
typedef GstFocusMode GstPhotographyFocusMode;
|
||||
#endif
|
||||
|
||||
//#define CAMERABIN_DEBUG 1
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
@@ -73,7 +79,7 @@ QCameraFocus::FocusModes CameraBinFocus::focusMode() const
|
||||
|
||||
void CameraBinFocus::setFocusMode(QCameraFocus::FocusModes mode)
|
||||
{
|
||||
GstFocusMode photographyMode;
|
||||
GstPhotographyFocusMode photographyMode;
|
||||
|
||||
switch (mode) {
|
||||
case QCameraFocus::AutoFocus:
|
||||
@@ -181,9 +187,10 @@ QCameraFocusZoneList CameraBinFocus::focusZones() const
|
||||
void CameraBinFocus::handleFocusMessage(GstMessage *gm)
|
||||
{
|
||||
//it's a sync message, so it's called from non main thread
|
||||
if (gst_structure_has_name(gm->structure, GST_PHOTOGRAPHY_AUTOFOCUS_DONE)) {
|
||||
const GstStructure *structure = gst_message_get_structure(gm);
|
||||
if (gst_structure_has_name(structure, GST_PHOTOGRAPHY_AUTOFOCUS_DONE)) {
|
||||
gint status = GST_PHOTOGRAPHY_FOCUS_STATUS_NONE;
|
||||
gst_structure_get_int (gm->structure, "status", &status);
|
||||
gst_structure_get_int (structure, "status", &status);
|
||||
QCamera::LockStatus focusStatus = m_focusStatus;
|
||||
QCamera::LockChangeReason reason = QCamera::UserRequest;
|
||||
|
||||
@@ -243,7 +250,7 @@ void CameraBinFocus::_q_handleCameraStateChange(QCamera::State state)
|
||||
m_cameraState = state;
|
||||
if (state == QCamera::ActiveState) {
|
||||
if (GstPad *pad = gst_element_get_static_pad(m_session->cameraSource(), "vfsrc")) {
|
||||
if (GstCaps *caps = gst_pad_get_negotiated_caps(pad)) {
|
||||
if (GstCaps *caps = qt_gst_pad_get_current_caps(pad)) {
|
||||
if (GstStructure *structure = gst_caps_get_structure(caps, 0)) {
|
||||
int width = 0;
|
||||
int height = 0;
|
||||
|
||||
@@ -53,11 +53,13 @@ QT_BEGIN_NAMESPACE
|
||||
|
||||
CameraBinImageCapture::CameraBinImageCapture(CameraBinSession *session)
|
||||
:QCameraImageCaptureControl(session)
|
||||
, m_encoderProbe(this)
|
||||
, m_muxerProbe(this)
|
||||
, m_session(session)
|
||||
, m_ready(false)
|
||||
, m_requestId(0)
|
||||
, m_jpegEncoderElement(0)
|
||||
, m_metadataMuxerElement(0)
|
||||
, m_requestId(0)
|
||||
, m_ready(false)
|
||||
{
|
||||
connect(m_session, SIGNAL(stateChanged(QCamera::State)), SLOT(updateState()));
|
||||
connect(m_session, SIGNAL(imageExposed(int)), this, SIGNAL(imageExposed(int)));
|
||||
@@ -108,11 +110,18 @@ void CameraBinImageCapture::updateState()
|
||||
}
|
||||
}
|
||||
|
||||
gboolean CameraBinImageCapture::metadataEventProbe(GstPad *pad, GstEvent *event, CameraBinImageCapture *self)
|
||||
#if GST_CHECK_VERSION(1,0,0)
|
||||
GstPadProbeReturn CameraBinImageCapture::encoderEventProbe(
|
||||
GstPad *, GstPadProbeInfo *info, gpointer user_data)
|
||||
{
|
||||
Q_UNUSED(pad);
|
||||
|
||||
if (GST_EVENT_TYPE(event) == GST_EVENT_TAG) {
|
||||
GstEvent * const event = gst_pad_probe_info_get_event(info);
|
||||
#else
|
||||
gboolean CameraBinImageCapture::encoderEventProbe(
|
||||
GstElement *, GstEvent *event, gpointer user_data)
|
||||
{
|
||||
#endif
|
||||
CameraBinImageCapture * const self = static_cast<CameraBinImageCapture *>(user_data);
|
||||
if (event && GST_EVENT_TYPE(event) == GST_EVENT_TAG) {
|
||||
GstTagList *gstTags;
|
||||
gst_event_parse_tag(event, &gstTags);
|
||||
QMap<QByteArray, QVariant> extendedTags = QGstUtils::gstTagListToMap(gstTags);
|
||||
@@ -146,17 +155,31 @@ gboolean CameraBinImageCapture::metadataEventProbe(GstPad *pad, GstEvent *event,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
#if GST_CHECK_VERSION(1,0,0)
|
||||
return GST_PAD_PROBE_OK;
|
||||
#else
|
||||
return TRUE;
|
||||
#endif
|
||||
}
|
||||
|
||||
gboolean CameraBinImageCapture::uncompressedBufferProbe(GstPad *pad, GstBuffer *buffer, CameraBinImageCapture *self)
|
||||
void CameraBinImageCapture::EncoderProbe::probeCaps(GstCaps *caps)
|
||||
{
|
||||
Q_UNUSED(pad);
|
||||
CameraBinSession *session = self->m_session;
|
||||
#if GST_CHECK_VERSION(1,0,0)
|
||||
capture->m_bufferFormat = QGstUtils::formatForCaps(caps, &capture->m_videoInfo);
|
||||
#else
|
||||
int bytesPerLine = 0;
|
||||
QVideoSurfaceFormat format = QGstUtils::formatForCaps(caps, &bytesPerLine);
|
||||
capture->m_bytesPerLine = bytesPerLine;
|
||||
capture->m_bufferFormat = format;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool CameraBinImageCapture::EncoderProbe::probeBuffer(GstBuffer *buffer)
|
||||
{
|
||||
CameraBinSession * const session = capture->m_session;
|
||||
|
||||
#ifdef DEBUG_CAPTURE
|
||||
qDebug() << "Uncompressed buffer probe" << gst_caps_to_string(GST_BUFFER_CAPS(buffer));
|
||||
qDebug() << "Uncompressed buffer probe";
|
||||
#endif
|
||||
|
||||
QCameraImageCapture::CaptureDestinations destination =
|
||||
@@ -165,21 +188,23 @@ gboolean CameraBinImageCapture::uncompressedBufferProbe(GstPad *pad, GstBuffer *
|
||||
|
||||
if (destination & QCameraImageCapture::CaptureToBuffer) {
|
||||
if (format != QVideoFrame::Format_Jpeg) {
|
||||
GstCaps *caps = GST_BUFFER_CAPS(buffer);
|
||||
int bytesPerLine = -1;
|
||||
QVideoSurfaceFormat format = QVideoSurfaceGstSink::formatForCaps(caps, &bytesPerLine);
|
||||
#ifdef DEBUG_CAPTURE
|
||||
qDebug() << "imageAvailable(uncompressed):" << format;
|
||||
#endif
|
||||
QGstVideoBuffer *videoBuffer = new QGstVideoBuffer(buffer, bytesPerLine);
|
||||
#if GST_CHECK_VERSION(1,0,0)
|
||||
QGstVideoBuffer *videoBuffer = new QGstVideoBuffer(buffer, capture->m_videoInfo);
|
||||
#else
|
||||
QGstVideoBuffer *videoBuffer = new QGstVideoBuffer(buffer, capture->m_bytesPerLine);
|
||||
#endif
|
||||
|
||||
QVideoFrame frame(videoBuffer,
|
||||
format.frameSize(),
|
||||
format.pixelFormat());
|
||||
QVideoFrame frame(
|
||||
videoBuffer,
|
||||
capture->m_bufferFormat.frameSize(),
|
||||
capture->m_bufferFormat.pixelFormat());
|
||||
|
||||
QMetaObject::invokeMethod(self, "imageAvailable",
|
||||
QMetaObject::invokeMethod(capture, "imageAvailable",
|
||||
Qt::QueuedConnection,
|
||||
Q_ARG(int, self->m_requestId),
|
||||
Q_ARG(int, capture->m_requestId),
|
||||
Q_ARG(QVideoFrame, frame));
|
||||
}
|
||||
}
|
||||
@@ -192,25 +217,40 @@ gboolean CameraBinImageCapture::uncompressedBufferProbe(GstPad *pad, GstBuffer *
|
||||
return keepBuffer;
|
||||
}
|
||||
|
||||
gboolean CameraBinImageCapture::jpegBufferProbe(GstPad *pad, GstBuffer *buffer, CameraBinImageCapture *self)
|
||||
void CameraBinImageCapture::MuxerProbe::probeCaps(GstCaps *caps)
|
||||
{
|
||||
Q_UNUSED(pad);
|
||||
CameraBinSession *session = self->m_session;
|
||||
capture->m_jpegResolution = QGstUtils::capsCorrectedResolution(caps);
|
||||
}
|
||||
|
||||
#ifdef DEBUG_CAPTURE
|
||||
qDebug() << "Jpeg buffer probe" << gst_caps_to_string(GST_BUFFER_CAPS(buffer));
|
||||
#endif
|
||||
bool CameraBinImageCapture::MuxerProbe::probeBuffer(GstBuffer *buffer)
|
||||
{
|
||||
CameraBinSession * const session = capture->m_session;
|
||||
|
||||
QCameraImageCapture::CaptureDestinations destination =
|
||||
session->captureDestinationControl()->captureDestination();
|
||||
|
||||
if ((destination & QCameraImageCapture::CaptureToBuffer) &&
|
||||
session->captureBufferFormatControl()->bufferFormat() == QVideoFrame::Format_Jpeg) {
|
||||
QGstVideoBuffer *videoBuffer = new QGstVideoBuffer(buffer,
|
||||
-1); //bytesPerLine is not available for jpegs
|
||||
|
||||
QSize resolution = QGstUtils::capsCorrectedResolution(GST_BUFFER_CAPS(buffer));
|
||||
QSize resolution = capture->m_jpegResolution;
|
||||
//if resolution is not presented in caps, try to find it from encoded jpeg data:
|
||||
#if GST_CHECK_VERSION(1,0,0)
|
||||
GstMapInfo mapInfo;
|
||||
if (resolution.isEmpty() && gst_buffer_map(buffer, &mapInfo, GST_MAP_READ)) {
|
||||
QBuffer data;
|
||||
data.setData(reinterpret_cast<const char*>(mapInfo.data), mapInfo.size);
|
||||
|
||||
QImageReader reader(&data, "JPEG");
|
||||
resolution = reader.size();
|
||||
|
||||
gst_buffer_unmap(buffer, &mapInfo);
|
||||
}
|
||||
|
||||
GstVideoInfo info;
|
||||
gst_video_info_set_format(
|
||||
&info, GST_VIDEO_FORMAT_ENCODED, resolution.width(), resolution.height());
|
||||
QGstVideoBuffer *videoBuffer = new QGstVideoBuffer(buffer, info);
|
||||
#else
|
||||
if (resolution.isEmpty()) {
|
||||
QBuffer data;
|
||||
data.setData(reinterpret_cast<const char*>(GST_BUFFER_DATA(buffer)), GST_BUFFER_SIZE(buffer));
|
||||
@@ -218,20 +258,28 @@ gboolean CameraBinImageCapture::jpegBufferProbe(GstPad *pad, GstBuffer *buffer,
|
||||
resolution = reader.size();
|
||||
}
|
||||
|
||||
QGstVideoBuffer *videoBuffer = new QGstVideoBuffer(buffer,
|
||||
-1); //bytesPerLine is not available for jpegs
|
||||
#endif
|
||||
|
||||
|
||||
QVideoFrame frame(videoBuffer,
|
||||
resolution,
|
||||
QVideoFrame::Format_Jpeg);
|
||||
|
||||
QMetaObject::invokeMethod(self, "imageAvailable",
|
||||
QMetaObject::invokeMethod(capture, "imageAvailable",
|
||||
Qt::QueuedConnection,
|
||||
Q_ARG(int, self->m_requestId),
|
||||
Q_ARG(int, capture->m_requestId),
|
||||
Q_ARG(QVideoFrame, frame));
|
||||
}
|
||||
|
||||
//drop the buffer if capture to file was disabled
|
||||
return destination & QCameraImageCapture::CaptureToFile;
|
||||
|
||||
// Theoretically we could drop the buffer here when don't want to capture to file but that
|
||||
// prevents camerabin from recognizing that capture has been completed and returning
|
||||
// to its idle state.
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool CameraBinImageCapture::processBusMessage(const QGstreamerMessage &message)
|
||||
{
|
||||
//Install metadata event and buffer probes
|
||||
@@ -252,9 +300,10 @@ bool CameraBinImageCapture::processBusMessage(const QGstreamerMessage &message)
|
||||
return false;
|
||||
|
||||
QString elementName = QString::fromLatin1(gst_element_get_name(element));
|
||||
#if !GST_CHECK_VERSION(1,0,0)
|
||||
GstElementClass *elementClass = GST_ELEMENT_GET_CLASS(element);
|
||||
QString elementLongName = elementClass->details.longname;
|
||||
|
||||
#endif
|
||||
if (elementName.contains("jpegenc") && element != m_jpegEncoderElement) {
|
||||
m_jpegEncoderElement = element;
|
||||
GstPad *sinkpad = gst_element_get_static_pad(element, "sink");
|
||||
@@ -264,21 +313,23 @@ bool CameraBinImageCapture::processBusMessage(const QGstreamerMessage &message)
|
||||
#ifdef DEBUG_CAPTURE
|
||||
qDebug() << "install metadata probe";
|
||||
#endif
|
||||
gst_pad_add_event_probe(sinkpad,
|
||||
G_CALLBACK(CameraBinImageCapture::metadataEventProbe),
|
||||
this);
|
||||
|
||||
#if GST_CHECK_VERSION(1,0,0)
|
||||
gst_pad_add_probe(
|
||||
sinkpad, GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM, encoderEventProbe, this, NULL);
|
||||
#else
|
||||
gst_pad_add_event_probe(sinkpad, G_CALLBACK(encoderEventProbe), this);
|
||||
#endif
|
||||
#ifdef DEBUG_CAPTURE
|
||||
qDebug() << "install uncompressed buffer probe";
|
||||
#endif
|
||||
gst_pad_add_buffer_probe(sinkpad,
|
||||
G_CALLBACK(CameraBinImageCapture::uncompressedBufferProbe),
|
||||
this);
|
||||
m_encoderProbe.addProbeToPad(sinkpad, true);
|
||||
|
||||
gst_object_unref(sinkpad);
|
||||
} else if ((elementName.contains("jifmux") ||
|
||||
elementName.startsWith("metadatamux") ||
|
||||
elementLongName == QLatin1String("JPEG stream muxer"))
|
||||
} else if ((elementName.contains("jifmux")
|
||||
#if !GST_CHECK_VERSION(1,0,0)
|
||||
|| elementLongName == QLatin1String("JPEG stream muxer")
|
||||
#endif
|
||||
|| elementName.startsWith("metadatamux"))
|
||||
&& element != m_metadataMuxerElement) {
|
||||
//Jpeg encoded buffer probe is added after jifmux/metadatamux
|
||||
//element to ensure the resulting jpeg buffer contains capture metadata
|
||||
@@ -288,9 +339,8 @@ bool CameraBinImageCapture::processBusMessage(const QGstreamerMessage &message)
|
||||
#ifdef DEBUG_CAPTURE
|
||||
qDebug() << "install jpeg buffer probe";
|
||||
#endif
|
||||
gst_pad_add_buffer_probe(srcpad,
|
||||
G_CALLBACK(CameraBinImageCapture::jpegBufferProbe),
|
||||
this);
|
||||
m_muxerProbe.addProbeToPad(srcpad);
|
||||
|
||||
gst_object_unref(srcpad);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,6 +38,14 @@
|
||||
#include <qcameraimagecapturecontrol.h>
|
||||
#include "camerabinsession.h"
|
||||
|
||||
#include <qvideosurfaceformat.h>
|
||||
|
||||
#include <private/qgstreamerbufferprobe_p.h>
|
||||
|
||||
#if GST_CHECK_VERSION(1,0,0)
|
||||
#include <gst/video/video.h>
|
||||
#endif
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
class CameraBinImageCapture : public QCameraImageCaptureControl, public QGstreamerBusMessageFilter
|
||||
@@ -61,15 +69,47 @@ private slots:
|
||||
void updateState();
|
||||
|
||||
private:
|
||||
static gboolean metadataEventProbe(GstPad *pad, GstEvent *event, CameraBinImageCapture *);
|
||||
static gboolean uncompressedBufferProbe(GstPad *pad, GstBuffer *buffer, CameraBinImageCapture *);
|
||||
static gboolean jpegBufferProbe(GstPad *pad, GstBuffer *buffer, CameraBinImageCapture *);
|
||||
#if GST_CHECK_VERSION(1,0,0)
|
||||
static GstPadProbeReturn encoderEventProbe(GstPad *, GstPadProbeInfo *info, gpointer user_data);
|
||||
#else
|
||||
static gboolean encoderEventProbe(GstElement *, GstEvent *event, gpointer user_data);
|
||||
#endif
|
||||
|
||||
class EncoderProbe : public QGstreamerBufferProbe
|
||||
{
|
||||
public:
|
||||
EncoderProbe(CameraBinImageCapture *capture) : capture(capture) {}
|
||||
void probeCaps(GstCaps *caps);
|
||||
bool probeBuffer(GstBuffer *buffer);
|
||||
|
||||
private:
|
||||
CameraBinImageCapture * const capture;
|
||||
} m_encoderProbe;
|
||||
|
||||
class MuxerProbe : public QGstreamerBufferProbe
|
||||
{
|
||||
public:
|
||||
MuxerProbe(CameraBinImageCapture *capture) : capture(capture) {}
|
||||
void probeCaps(GstCaps *caps);
|
||||
bool probeBuffer(GstBuffer *buffer);
|
||||
|
||||
private:
|
||||
CameraBinImageCapture * const capture;
|
||||
|
||||
} m_muxerProbe;
|
||||
|
||||
QVideoSurfaceFormat m_bufferFormat;
|
||||
QSize m_jpegResolution;
|
||||
CameraBinSession *m_session;
|
||||
bool m_ready;
|
||||
int m_requestId;
|
||||
GstElement *m_jpegEncoderElement;
|
||||
GstElement *m_metadataMuxerElement;
|
||||
#if GST_CHECK_VERSION(1,0,0)
|
||||
GstVideoInfo m_videoInfo;
|
||||
#else
|
||||
int m_bytesPerLine;
|
||||
#endif
|
||||
int m_requestId;
|
||||
bool m_ready;
|
||||
};
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
@@ -49,7 +49,6 @@ CameraBinImageEncoder::~CameraBinImageEncoder()
|
||||
|
||||
QList<QSize> CameraBinImageEncoder::supportedResolutions(const QImageEncoderSettings &, bool *continuous) const
|
||||
{
|
||||
qDebug() << "CameraBinImageEncoder::supportedResolutions()";
|
||||
if (continuous)
|
||||
*continuous = false;
|
||||
|
||||
|
||||
@@ -34,7 +34,11 @@
|
||||
#include "camerabinimageprocessing.h"
|
||||
#include "camerabinsession.h"
|
||||
|
||||
#include <gst/interfaces/colorbalance.h>
|
||||
#if GST_CHECK_VERSION(1,0,0)
|
||||
# include <gst/video/colorbalance.h>
|
||||
#else
|
||||
# include <gst/interfaces/colorbalance.h>
|
||||
#endif
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
@@ -126,7 +130,7 @@ bool CameraBinImageProcessing::setColorBalanceValue(const QString& channel, qrea
|
||||
QCameraImageProcessing::WhiteBalanceMode CameraBinImageProcessing::whiteBalanceMode() const
|
||||
{
|
||||
#ifdef HAVE_GST_PHOTOGRAPHY
|
||||
GstWhiteBalanceMode wbMode;
|
||||
GstPhotographyWhiteBalanceMode wbMode;
|
||||
gst_photography_get_white_balance_mode(m_session->photography(), &wbMode);
|
||||
return m_mappedWbValues[wbMode];
|
||||
#else
|
||||
|
||||
@@ -41,7 +41,10 @@
|
||||
#include <glib.h>
|
||||
|
||||
#ifdef HAVE_GST_PHOTOGRAPHY
|
||||
#include <gst/interfaces/photography.h>
|
||||
# include <gst/interfaces/photography.h>
|
||||
# if !GST_CHECK_VERSION(1,0,0)
|
||||
typedef GstWhiteBalanceMode GstPhotographyWhiteBalanceMode;
|
||||
# endif
|
||||
#endif
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
@@ -73,7 +76,7 @@ private:
|
||||
CameraBinSession *m_session;
|
||||
QMap<QCameraImageProcessingControl::ProcessingParameter, int> m_values;
|
||||
#ifdef HAVE_GST_PHOTOGRAPHY
|
||||
QMap<GstWhiteBalanceMode, QCameraImageProcessing::WhiteBalanceMode> m_mappedWbValues;
|
||||
QMap<GstPhotographyWhiteBalanceMode, QCameraImageProcessing::WhiteBalanceMode> m_mappedWbValues;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
@@ -126,7 +126,7 @@ static const QGStreamerMetaDataKeys *qt_gstreamerMetaDataKeys()
|
||||
metadataKeys->append(QGStreamerMetaDataKey(QMediaMetaData::AlbumTitle, GST_TAG_ALBUM, QVariant::String));
|
||||
metadataKeys->append(QGStreamerMetaDataKey(QMediaMetaData::AlbumArtist, GST_TAG_ARTIST, QVariant::String));
|
||||
metadataKeys->append(QGStreamerMetaDataKey(QMediaMetaData::ContributingArtist, GST_TAG_PERFORMER, QVariant::String));
|
||||
#if (GST_VERSION_MAJOR >= 0) && (GST_VERSION_MINOR >= 10) && (GST_VERSION_MICRO >= 19)
|
||||
#if GST_CHECK_VERSION(0,10,19)
|
||||
metadataKeys->append(QGStreamerMetaDataKey(QMediaMetaData::Composer, GST_TAG_COMPOSER, QVariant::String));
|
||||
#endif
|
||||
//metadataKeys->append(QGStreamerMetaDataKey(QMediaMetaData::Conductor, 0, QVariant::String));
|
||||
@@ -153,8 +153,7 @@ static const QGStreamerMetaDataKeys *qt_gstreamerMetaDataKeys()
|
||||
//metadataKeys->append(QGStreamerMetaDataKey(QMediaMetaData::Director, 0, QVariant::String));
|
||||
metadataKeys->append(QGStreamerMetaDataKey(QMediaMetaData::LeadPerformer, GST_TAG_PERFORMER, QVariant::String));
|
||||
//metadataKeys->append(QGStreamerMetaDataKey(QMediaMetaData::Writer, 0, QVariant::String));
|
||||
|
||||
#if (GST_VERSION_MAJOR >= 0) && (GST_VERSION_MINOR >= 10) && (GST_VERSION_MICRO >= 30)
|
||||
#if GST_CHECK_VERSION(0,10,30)
|
||||
// Photos
|
||||
metadataKeys->append(QGStreamerMetaDataKey(QMediaMetaData::CameraManufacturer, GST_TAG_DEVICE_MANUFACTURER, QVariant::String));
|
||||
metadataKeys->append(QGStreamerMetaDataKey(QMediaMetaData::CameraModel, GST_TAG_DEVICE_MODEL, QVariant::String));
|
||||
|
||||
@@ -110,9 +110,10 @@ void CameraBinRecorder::updateStatus()
|
||||
m_state = QMediaRecorder::StoppedState;
|
||||
m_session->stopVideoRecording();
|
||||
}
|
||||
m_status = m_session->pendingState() == QCamera::ActiveState ?
|
||||
QMediaRecorder::LoadingStatus :
|
||||
QMediaRecorder::UnloadedStatus;
|
||||
m_status = m_session->pendingState() == QCamera::ActiveState
|
||||
&& m_session->captureMode().testFlag(QCamera::CaptureVideo)
|
||||
? QMediaRecorder::LoadingStatus
|
||||
: QMediaRecorder::UnloadedStatus;
|
||||
}
|
||||
|
||||
if (m_state != oldState)
|
||||
@@ -161,8 +162,6 @@ void CameraBinRecorder::applySettings()
|
||||
|
||||
QVideoEncoderSettings videoSettings = videoEncoderControl->videoSettings();
|
||||
videoSettings.setCodec(candidate[1]);
|
||||
if (videoSettings.resolution().isEmpty())
|
||||
videoSettings.setResolution(640, 480);
|
||||
videoEncoderControl->setActualVideoSettings(videoSettings);
|
||||
|
||||
QAudioEncoderSettings audioSettings = audioEncoderControl->audioSettings();
|
||||
|
||||
@@ -56,11 +56,11 @@
|
||||
#include "camerabincapturedestination.h"
|
||||
#include "camerabinviewfindersettings.h"
|
||||
#include <private/qgstreamerbushelper_p.h>
|
||||
#include <private/qgstutils_p.h>
|
||||
|
||||
#include <private/qgstreameraudioinputselector_p.h>
|
||||
#include <private/qgstreamervideoinputdevicecontrol_p.h>
|
||||
|
||||
|
||||
#if defined(HAVE_WIDGETS)
|
||||
#include <private/qgstreamervideowidget_p.h>
|
||||
#endif
|
||||
@@ -121,7 +121,6 @@ CameraBinService::CameraBinService(GstElementFactory *sourceFactory, QObject *pa
|
||||
#else
|
||||
m_videoWindow = new QGstreamerVideoWindow(this);
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_WIDGETS)
|
||||
m_videoWidgetControl = new QGstreamerVideoWidgetControl(this);
|
||||
#endif
|
||||
@@ -150,8 +149,6 @@ QMediaControl *CameraBinService::requestControl(const char *name)
|
||||
if (!m_captureSession)
|
||||
return 0;
|
||||
|
||||
//qDebug() << "Request control" << name;
|
||||
|
||||
if (!m_videoOutput) {
|
||||
if (qstrcmp(name, QVideoRendererControl_iid) == 0) {
|
||||
m_videoOutput = m_videoRenderer;
|
||||
@@ -249,7 +246,7 @@ void CameraBinService::releaseControl(QMediaControl *control)
|
||||
|
||||
bool CameraBinService::isCameraBinAvailable()
|
||||
{
|
||||
GstElementFactory *factory = gst_element_factory_find("camerabin2");
|
||||
GstElementFactory *factory = gst_element_factory_find(QT_GSTREAMER_CAMERABIN_ELEMENT_NAME);
|
||||
if (factory) {
|
||||
gst_object_unref(GST_OBJECT(factory));
|
||||
return true;
|
||||
|
||||
@@ -140,8 +140,8 @@ CameraBinSession::CameraBinSession(GstElementFactory *sourceFactory, QObject *pa
|
||||
{
|
||||
if (m_sourceFactory)
|
||||
gst_object_ref(GST_OBJECT(m_sourceFactory));
|
||||
m_camerabin = gst_element_factory_make(QT_GSTREAMER_CAMERABIN_ELEMENT_NAME, "camerabin");
|
||||
|
||||
m_camerabin = gst_element_factory_make("camerabin2", "camerabin2");
|
||||
g_signal_connect(G_OBJECT(m_camerabin), "notify::idle", G_CALLBACK(updateBusyStatus), this);
|
||||
g_signal_connect(G_OBJECT(m_camerabin), "element-added", G_CALLBACK(elementAdded), this);
|
||||
g_signal_connect(G_OBJECT(m_camerabin), "element-removed", G_CALLBACK(elementRemoved), this);
|
||||
@@ -178,7 +178,15 @@ CameraBinSession::CameraBinSession(GstElementFactory *sourceFactory, QObject *pa
|
||||
//post image preview in RGB format
|
||||
g_object_set(G_OBJECT(m_camerabin), POST_PREVIEWS_PROPERTY, TRUE, NULL);
|
||||
|
||||
#if GST_CHECK_VERSION(1,0,0)
|
||||
GstCaps *previewCaps = gst_caps_new_simple(
|
||||
"video/x-raw",
|
||||
"format", G_TYPE_STRING, "RGBx",
|
||||
NULL);
|
||||
#else
|
||||
GstCaps *previewCaps = gst_caps_from_string("video/x-raw-rgb");
|
||||
#endif
|
||||
|
||||
g_object_set(G_OBJECT(m_camerabin), PREVIEW_CAPS_PROPERTY, previewCaps, NULL);
|
||||
gst_caps_unref(previewCaps);
|
||||
}
|
||||
@@ -243,6 +251,7 @@ bool CameraBinSession::setupCameraBin()
|
||||
qWarning() << "Staring camera without viewfinder available";
|
||||
m_viewfinderElement = gst_element_factory_make("fakesink", NULL);
|
||||
}
|
||||
g_object_set(G_OBJECT(m_viewfinderElement), "sync", FALSE, NULL);
|
||||
qt_gst_object_ref_sink(GST_OBJECT(m_viewfinderElement));
|
||||
gst_element_set_state(m_camerabin, GST_STATE_NULL);
|
||||
g_object_set(G_OBJECT(m_camerabin), VIEWFINDER_SINK_PROPERTY, m_viewfinderElement, NULL);
|
||||
@@ -251,61 +260,27 @@ bool CameraBinSession::setupCameraBin()
|
||||
return true;
|
||||
}
|
||||
|
||||
static GstCaps *resolutionToCaps(const QSize &resolution, const QPair<int, int> &rate = qMakePair<int,int>(0,0))
|
||||
static GstCaps *resolutionToCaps(const QSize &resolution, qreal frameRate = 0.0)
|
||||
{
|
||||
if (resolution.isEmpty())
|
||||
return gst_caps_new_any();
|
||||
GstCaps *caps = QGstUtils::videoFilterCaps();
|
||||
|
||||
GstCaps *caps = 0;
|
||||
if (rate.second > 0) {
|
||||
caps = gst_caps_new_full(gst_structure_new("video/x-raw-yuv",
|
||||
"width", G_TYPE_INT, resolution.width(),
|
||||
"height", G_TYPE_INT, resolution.height(),
|
||||
"framerate", GST_TYPE_FRACTION, rate.first, rate.second,
|
||||
NULL),
|
||||
gst_structure_new("video/x-raw-rgb",
|
||||
"width", G_TYPE_INT, resolution.width(),
|
||||
"height", G_TYPE_INT, resolution.height(),
|
||||
"framerate", GST_TYPE_FRACTION, rate.first, rate.second,
|
||||
NULL),
|
||||
gst_structure_new("video/x-raw-data",
|
||||
"width", G_TYPE_INT, resolution.width(),
|
||||
"height", G_TYPE_INT, resolution.height(),
|
||||
"framerate", GST_TYPE_FRACTION, rate.first, rate.second,
|
||||
NULL),
|
||||
gst_structure_new("video/x-android-buffer",
|
||||
"width", G_TYPE_INT, resolution.width(),
|
||||
"height", G_TYPE_INT, resolution.height(),
|
||||
"framerate", GST_TYPE_FRACTION, rate.first, rate.second,
|
||||
NULL),
|
||||
gst_structure_new("image/jpeg",
|
||||
"width", G_TYPE_INT, resolution.width(),
|
||||
"height", G_TYPE_INT, resolution.height(),
|
||||
"framerate", GST_TYPE_FRACTION, rate.first, rate.second,
|
||||
NULL),
|
||||
NULL);
|
||||
} else {
|
||||
caps = gst_caps_new_full (gst_structure_new ("video/x-raw-yuv",
|
||||
"width", G_TYPE_INT, resolution.width(),
|
||||
"height", G_TYPE_INT, resolution.height(),
|
||||
NULL),
|
||||
gst_structure_new ("video/x-raw-rgb",
|
||||
"width", G_TYPE_INT, resolution.width(),
|
||||
"height", G_TYPE_INT, resolution.height(),
|
||||
NULL),
|
||||
gst_structure_new("video/x-raw-data",
|
||||
"width", G_TYPE_INT, resolution.width(),
|
||||
"height", G_TYPE_INT, resolution.height(),
|
||||
NULL),
|
||||
gst_structure_new ("video/x-android-buffer",
|
||||
"width", G_TYPE_INT, resolution.width(),
|
||||
"height", G_TYPE_INT, resolution.height(),
|
||||
NULL),
|
||||
gst_structure_new ("image/jpeg",
|
||||
"width", G_TYPE_INT, resolution.width(),
|
||||
"height", G_TYPE_INT, resolution.height(),
|
||||
NULL),
|
||||
NULL);
|
||||
if (!resolution.isEmpty()) {
|
||||
gst_caps_set_simple(
|
||||
caps,
|
||||
"width", G_TYPE_INT, resolution.width(),
|
||||
"height", G_TYPE_INT, resolution.height(),
|
||||
NULL);
|
||||
}
|
||||
|
||||
if (frameRate > 0.0) {
|
||||
gint numerator;
|
||||
gint denominator;
|
||||
gst_util_double_to_fraction(frameRate, &numerator, &denominator);
|
||||
|
||||
gst_caps_set_simple(
|
||||
caps,
|
||||
"framerate", GST_TYPE_FRACTION, numerator, denominator,
|
||||
NULL);
|
||||
}
|
||||
|
||||
return caps;
|
||||
@@ -314,40 +289,40 @@ static GstCaps *resolutionToCaps(const QSize &resolution, const QPair<int, int>
|
||||
void CameraBinSession::setupCaptureResolution()
|
||||
{
|
||||
QSize resolution = m_imageEncodeControl->imageSettings().resolution();
|
||||
if (!resolution.isEmpty()) {
|
||||
{
|
||||
GstCaps *caps = resolutionToCaps(resolution);
|
||||
#if CAMERABIN_DEBUG
|
||||
qDebug() << Q_FUNC_INFO << "set image resolution" << resolution << gst_caps_to_string(caps);
|
||||
qDebug() << Q_FUNC_INFO << "set image resolution" << resolution << caps;
|
||||
#endif
|
||||
g_object_set(m_camerabin, IMAGE_CAPTURE_CAPS_PROPERTY, caps, NULL);
|
||||
gst_caps_unref(caps);
|
||||
} else {
|
||||
g_object_set(m_camerabin, IMAGE_CAPTURE_CAPS_PROPERTY, NULL, NULL);
|
||||
if (caps)
|
||||
gst_caps_unref(caps);
|
||||
}
|
||||
|
||||
const QSize viewfinderResolution = m_viewfinderSettingsControl->resolution();
|
||||
resolution = m_videoEncodeControl->actualVideoSettings().resolution();
|
||||
//qreal framerate = m_videoEncodeControl->videoSettings().frameRate();
|
||||
if (!resolution.isEmpty()) {
|
||||
GstCaps *caps = resolutionToCaps(resolution /*, framerate*/); //convert to rational
|
||||
qreal framerate = m_videoEncodeControl->videoSettings().frameRate();
|
||||
{
|
||||
GstCaps *caps = resolutionToCaps(
|
||||
!resolution.isEmpty() ? resolution : viewfinderResolution, framerate);
|
||||
#if CAMERABIN_DEBUG
|
||||
qDebug() << Q_FUNC_INFO << "set video resolution" << resolution << gst_caps_to_string(caps);
|
||||
qDebug() << Q_FUNC_INFO << "set video resolution" << resolution << caps;
|
||||
#endif
|
||||
g_object_set(m_camerabin, VIDEO_CAPTURE_CAPS_PROPERTY, caps, NULL);
|
||||
gst_caps_unref(caps);
|
||||
} else {
|
||||
g_object_set(m_camerabin, VIDEO_CAPTURE_CAPS_PROPERTY, NULL, NULL);
|
||||
if (caps)
|
||||
gst_caps_unref(caps);
|
||||
}
|
||||
|
||||
resolution = m_viewfinderSettingsControl->resolution();
|
||||
if (!resolution.isEmpty()) {
|
||||
if (!viewfinderResolution.isEmpty())
|
||||
resolution = viewfinderResolution;
|
||||
{
|
||||
GstCaps *caps = resolutionToCaps(resolution);
|
||||
#if CAMERABIN_DEBUG
|
||||
qDebug() << Q_FUNC_INFO << "set viewfinder resolution" << resolution << gst_caps_to_string(caps);
|
||||
qDebug() << Q_FUNC_INFO << "set viewfinder resolution" << resolution << caps;
|
||||
#endif
|
||||
g_object_set(m_camerabin, VIEWFINDER_CAPS_PROPERTY, caps, NULL);
|
||||
gst_caps_unref(caps);
|
||||
} else {
|
||||
g_object_set(m_camerabin, VIEWFINDER_CAPS_PROPERTY, NULL, NULL);
|
||||
if (caps)
|
||||
gst_caps_unref(caps);
|
||||
}
|
||||
|
||||
if (m_videoEncoder)
|
||||
@@ -363,13 +338,17 @@ void CameraBinSession::setAudioCaptureCaps()
|
||||
if (sampleRate == -1 && channelCount == -1)
|
||||
return;
|
||||
|
||||
#if GST_CHECK_VERSION(1,0,0)
|
||||
GstStructure *structure = gst_structure_new_empty(QT_GSTREAMER_RAW_AUDIO_MIME);
|
||||
#else
|
||||
GstStructure *structure = gst_structure_new(
|
||||
"audio/x-raw-int",
|
||||
QT_GSTREAMER_RAW_AUDIO_MIME,
|
||||
"endianness", G_TYPE_INT, 1234,
|
||||
"signed", G_TYPE_BOOLEAN, TRUE,
|
||||
"width", G_TYPE_INT, 16,
|
||||
"depth", G_TYPE_INT, 16,
|
||||
NULL);
|
||||
#endif
|
||||
if (sampleRate != -1)
|
||||
gst_structure_set(structure, "rate", G_TYPE_INT, sampleRate, NULL);
|
||||
if (channelCount != -1)
|
||||
@@ -760,7 +739,7 @@ qint64 CameraBinSession::duration() const
|
||||
if (fileSink) {
|
||||
GstFormat format = GST_FORMAT_TIME;
|
||||
gint64 duration = 0;
|
||||
bool ret = gst_element_query_position(fileSink, &format, &duration);
|
||||
bool ret = qt_gst_element_query_position(fileSink, format, &duration);
|
||||
gst_object_unref(GST_OBJECT(fileSink));
|
||||
if (ret)
|
||||
return duration / 1000000;
|
||||
@@ -795,129 +774,57 @@ void CameraBinSession::setMetaData(const QMap<QByteArray, QVariant> &data)
|
||||
{
|
||||
m_metaData = data;
|
||||
|
||||
if (m_camerabin) {
|
||||
GstIterator *elements = gst_bin_iterate_all_by_interface(GST_BIN(m_camerabin), GST_TYPE_TAG_SETTER);
|
||||
GstElement *element = 0;
|
||||
while (gst_iterator_next(elements, (void**)&element) == GST_ITERATOR_OK) {
|
||||
gst_tag_setter_reset_tags(GST_TAG_SETTER(element));
|
||||
|
||||
QMapIterator<QByteArray, QVariant> it(data);
|
||||
while (it.hasNext()) {
|
||||
it.next();
|
||||
const QString tagName = it.key();
|
||||
const QVariant tagValue = it.value();
|
||||
|
||||
switch(tagValue.type()) {
|
||||
case QVariant::String:
|
||||
gst_tag_setter_add_tags(GST_TAG_SETTER(element),
|
||||
GST_TAG_MERGE_REPLACE,
|
||||
tagName.toUtf8().constData(),
|
||||
tagValue.toString().toUtf8().constData(),
|
||||
NULL);
|
||||
break;
|
||||
case QVariant::Int:
|
||||
case QVariant::LongLong:
|
||||
gst_tag_setter_add_tags(GST_TAG_SETTER(element),
|
||||
GST_TAG_MERGE_REPLACE,
|
||||
tagName.toUtf8().constData(),
|
||||
tagValue.toInt(),
|
||||
NULL);
|
||||
break;
|
||||
case QVariant::Double:
|
||||
gst_tag_setter_add_tags(GST_TAG_SETTER(element),
|
||||
GST_TAG_MERGE_REPLACE,
|
||||
tagName.toUtf8().constData(),
|
||||
tagValue.toDouble(),
|
||||
NULL);
|
||||
break;
|
||||
case QVariant::DateTime: {
|
||||
QDateTime date = tagValue.toDateTime().toLocalTime();
|
||||
gst_tag_setter_add_tags(GST_TAG_SETTER(element),
|
||||
GST_TAG_MERGE_REPLACE,
|
||||
tagName.toUtf8().constData(),
|
||||
gst_date_time_new_local_time(
|
||||
date.date().year(), date.date().month(), date.date().day(),
|
||||
date.time().hour(), date.time().minute(), date.time().second()),
|
||||
NULL);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
gst_iterator_free(elements);
|
||||
}
|
||||
if (m_camerabin)
|
||||
QGstUtils::setMetaData(m_camerabin, data);
|
||||
}
|
||||
|
||||
bool CameraBinSession::processSyncMessage(const QGstreamerMessage &message)
|
||||
{
|
||||
GstMessage* gm = message.rawMessage();
|
||||
const GstStructure *st;
|
||||
const GValue *image;
|
||||
GstBuffer *buffer = NULL;
|
||||
|
||||
if (gm && GST_MESSAGE_TYPE(gm) == GST_MESSAGE_ELEMENT) {
|
||||
if (m_captureMode == QCamera::CaptureStillImage &&
|
||||
gst_structure_has_name(gm->structure, "preview-image")) {
|
||||
st = gst_message_get_structure(gm);
|
||||
|
||||
if (gst_structure_has_field_typed(st, "buffer", GST_TYPE_BUFFER)) {
|
||||
image = gst_structure_get_value(st, "buffer");
|
||||
if (image) {
|
||||
buffer = gst_value_get_buffer(image);
|
||||
|
||||
QImage img;
|
||||
|
||||
GstCaps *caps = gst_buffer_get_caps(buffer);
|
||||
if (caps) {
|
||||
GstStructure *structure = gst_caps_get_structure(caps, 0);
|
||||
gint width = 0;
|
||||
gint height = 0;
|
||||
#if CAMERABIN_DEBUG
|
||||
qDebug() << "Preview caps:" << gst_structure_to_string(structure);
|
||||
const GstStructure *st = gst_message_get_structure(gm);
|
||||
const GValue *sampleValue = 0;
|
||||
if (m_captureMode == QCamera::CaptureStillImage
|
||||
&& gst_structure_has_name(st, "preview-image")
|
||||
#if GST_CHECK_VERSION(1,0,0)
|
||||
&& gst_structure_has_field_typed(st, "sample", GST_TYPE_SAMPLE)
|
||||
&& (sampleValue = gst_structure_get_value(st, "sample"))) {
|
||||
GstSample * const sample = gst_value_get_sample(sampleValue);
|
||||
GstCaps * const previewCaps = gst_sample_get_caps(sample);
|
||||
GstBuffer * const buffer = gst_sample_get_buffer(sample);
|
||||
#else
|
||||
&& gst_structure_has_field_typed(st, "buffer", GST_TYPE_BUFFER)
|
||||
&& (sampleValue = gst_structure_get_value(st, "buffer"))) {
|
||||
GstBuffer * const buffer = gst_value_get_buffer(sampleValue);
|
||||
#endif
|
||||
|
||||
if (structure &&
|
||||
gst_structure_get_int(structure, "width", &width) &&
|
||||
gst_structure_get_int(structure, "height", &height) &&
|
||||
width > 0 && height > 0) {
|
||||
if (qstrcmp(gst_structure_get_name(structure), "video/x-raw-rgb") == 0) {
|
||||
QImage::Format format = QImage::Format_Invalid;
|
||||
int bpp = 0;
|
||||
gst_structure_get_int(structure, "bpp", &bpp);
|
||||
QImage image;
|
||||
#if GST_CHECK_VERSION(1,0,0)
|
||||
GstVideoInfo previewInfo;
|
||||
if (gst_video_info_from_caps(&previewInfo, previewCaps))
|
||||
image = QGstUtils::bufferToImage(buffer, previewInfo);
|
||||
gst_sample_unref(sample);
|
||||
#else
|
||||
image = QGstUtils::bufferToImage(buffer);
|
||||
gst_buffer_unref(buffer);
|
||||
#endif
|
||||
if (!image.isNull()) {
|
||||
static QMetaMethod exposedSignal = QMetaMethod::fromSignal(&CameraBinSession::imageExposed);
|
||||
exposedSignal.invoke(this,
|
||||
Qt::QueuedConnection,
|
||||
Q_ARG(int,m_requestId));
|
||||
|
||||
if (bpp == 24)
|
||||
format = QImage::Format_RGB888;
|
||||
else if (bpp == 32)
|
||||
format = QImage::Format_RGB32;
|
||||
|
||||
if (format != QImage::Format_Invalid) {
|
||||
img = QImage((const uchar *)buffer->data, width, height, format);
|
||||
img.bits(); //detach
|
||||
}
|
||||
}
|
||||
}
|
||||
gst_caps_unref(caps);
|
||||
|
||||
static QMetaMethod exposedSignal = QMetaMethod::fromSignal(&CameraBinSession::imageExposed);
|
||||
exposedSignal.invoke(this,
|
||||
Qt::QueuedConnection,
|
||||
Q_ARG(int,m_requestId));
|
||||
|
||||
static QMetaMethod capturedSignal = QMetaMethod::fromSignal(&CameraBinSession::imageCaptured);
|
||||
capturedSignal.invoke(this,
|
||||
Qt::QueuedConnection,
|
||||
Q_ARG(int,m_requestId),
|
||||
Q_ARG(QImage,img));
|
||||
}
|
||||
|
||||
}
|
||||
return true;
|
||||
static QMetaMethod capturedSignal = QMetaMethod::fromSignal(&CameraBinSession::imageCaptured);
|
||||
capturedSignal.invoke(this,
|
||||
Qt::QueuedConnection,
|
||||
Q_ARG(int,m_requestId),
|
||||
Q_ARG(QImage,image));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
#ifdef HAVE_GST_PHOTOGRAPHY
|
||||
if (gst_structure_has_name(gm->structure, GST_PHOTOGRAPHY_AUTOFOCUS_DONE))
|
||||
if (gst_structure_has_name(st, GST_PHOTOGRAPHY_AUTOFOCUS_DONE))
|
||||
m_cameraFocusControl->handleFocusMessage(gm);
|
||||
#endif
|
||||
}
|
||||
@@ -1109,20 +1016,12 @@ QList< QPair<int,int> > CameraBinSession::supportedFrameRates(const QSize &frame
|
||||
if (frameSize.isEmpty()) {
|
||||
caps = gst_caps_copy(supportedCaps);
|
||||
} else {
|
||||
GstCaps *filter = gst_caps_new_full(
|
||||
gst_structure_new(
|
||||
"video/x-raw-rgb",
|
||||
"width" , G_TYPE_INT , frameSize.width(),
|
||||
"height" , G_TYPE_INT, frameSize.height(), NULL),
|
||||
gst_structure_new(
|
||||
"video/x-raw-yuv",
|
||||
"width" , G_TYPE_INT, frameSize.width(),
|
||||
"height" , G_TYPE_INT, frameSize.height(), NULL),
|
||||
gst_structure_new(
|
||||
"image/jpeg",
|
||||
"width" , G_TYPE_INT, frameSize.width(),
|
||||
"height" , G_TYPE_INT, frameSize.height(), NULL),
|
||||
NULL);
|
||||
GstCaps *filter = QGstUtils::videoFilterCaps();
|
||||
gst_caps_set_simple(
|
||||
filter,
|
||||
"width", G_TYPE_INT, frameSize.width(),
|
||||
"height", G_TYPE_INT, frameSize.height(),
|
||||
NULL);
|
||||
|
||||
caps = gst_caps_intersect(supportedCaps, filter);
|
||||
gst_caps_unref(filter);
|
||||
@@ -1133,7 +1032,7 @@ QList< QPair<int,int> > CameraBinSession::supportedFrameRates(const QSize &frame
|
||||
caps = gst_caps_make_writable(caps);
|
||||
for (uint i=0; i<gst_caps_get_size(caps); i++) {
|
||||
GstStructure *structure = gst_caps_get_structure(caps, i);
|
||||
gst_structure_set_name(structure, "video/x-raw-yuv");
|
||||
gst_structure_set_name(structure, "video/x-raw");
|
||||
const GValue *oldRate = gst_structure_get_value(structure, "framerate");
|
||||
GValue rate;
|
||||
memset(&rate, 0, sizeof(rate));
|
||||
@@ -1142,8 +1041,11 @@ QList< QPair<int,int> > CameraBinSession::supportedFrameRates(const QSize &frame
|
||||
gst_structure_remove_all_fields(structure);
|
||||
gst_structure_set_value(structure, "framerate", &rate);
|
||||
}
|
||||
#if GST_CHECK_VERSION(1,0,0)
|
||||
caps = gst_caps_simplify(caps);
|
||||
#else
|
||||
gst_caps_do_simplify(caps);
|
||||
|
||||
#endif
|
||||
|
||||
for (uint i=0; i<gst_caps_get_size(caps); i++) {
|
||||
GstStructure *structure = gst_caps_get_structure(caps, i);
|
||||
@@ -1154,7 +1056,7 @@ QList< QPair<int,int> > CameraBinSession::supportedFrameRates(const QSize &frame
|
||||
qSort(res.begin(), res.end(), rateLessThan);
|
||||
|
||||
#if CAMERABIN_DEBUG
|
||||
qDebug() << "Supported rates:" << gst_caps_to_string(caps);
|
||||
qDebug() << "Supported rates:" << caps;
|
||||
qDebug() << res;
|
||||
#endif
|
||||
|
||||
@@ -1213,31 +1115,24 @@ QList<QSize> CameraBinSession::supportedResolutions(QPair<int,int> rate,
|
||||
SUPPORTED_IMAGE_CAPTURE_CAPS_PROPERTY : SUPPORTED_VIDEO_CAPTURE_CAPS_PROPERTY,
|
||||
&supportedCaps, NULL);
|
||||
|
||||
#if CAMERABIN_DEBUG
|
||||
qDebug() << "Source caps:" << supportedCaps;
|
||||
#endif
|
||||
|
||||
if (!supportedCaps)
|
||||
return res;
|
||||
|
||||
#if CAMERABIN_DEBUG
|
||||
qDebug() << "Source caps:" << gst_caps_to_string(supportedCaps);
|
||||
#endif
|
||||
|
||||
GstCaps *caps = 0;
|
||||
bool isContinuous = false;
|
||||
|
||||
if (rate.first <= 0 || rate.second <= 0) {
|
||||
caps = gst_caps_copy(supportedCaps);
|
||||
} else {
|
||||
GstCaps *filter = gst_caps_new_full(
|
||||
gst_structure_new(
|
||||
"video/x-raw-rgb",
|
||||
"framerate" , GST_TYPE_FRACTION , rate.first, rate.second, NULL),
|
||||
gst_structure_new(
|
||||
"video/x-raw-yuv",
|
||||
"framerate" , GST_TYPE_FRACTION , rate.first, rate.second, NULL),
|
||||
gst_structure_new(
|
||||
"image/jpeg",
|
||||
"framerate" , GST_TYPE_FRACTION , rate.first, rate.second, NULL),
|
||||
NULL);
|
||||
|
||||
GstCaps *filter = QGstUtils::videoFilterCaps();
|
||||
gst_caps_set_simple(
|
||||
filter,
|
||||
"framerate" , GST_TYPE_FRACTION , rate.first, rate.second,
|
||||
NULL);
|
||||
caps = gst_caps_intersect(supportedCaps, filter);
|
||||
gst_caps_unref(filter);
|
||||
}
|
||||
@@ -1247,7 +1142,7 @@ QList<QSize> CameraBinSession::supportedResolutions(QPair<int,int> rate,
|
||||
caps = gst_caps_make_writable(caps);
|
||||
for (uint i=0; i<gst_caps_get_size(caps); i++) {
|
||||
GstStructure *structure = gst_caps_get_structure(caps, i);
|
||||
gst_structure_set_name(structure, "video/x-raw-yuv");
|
||||
gst_structure_set_name(structure, "video/x-raw");
|
||||
const GValue *oldW = gst_structure_get_value(structure, "width");
|
||||
const GValue *oldH = gst_structure_get_value(structure, "height");
|
||||
GValue w;
|
||||
@@ -1262,7 +1157,13 @@ QList<QSize> CameraBinSession::supportedResolutions(QPair<int,int> rate,
|
||||
gst_structure_set_value(structure, "width", &w);
|
||||
gst_structure_set_value(structure, "height", &h);
|
||||
}
|
||||
|
||||
#if GST_CHECK_VERSION(1,0,0)
|
||||
caps = gst_caps_simplify(caps);
|
||||
#else
|
||||
gst_caps_do_simplify(caps);
|
||||
#endif
|
||||
|
||||
|
||||
for (uint i=0; i<gst_caps_get_size(caps); i++) {
|
||||
GstStructure *structure = gst_caps_get_structure(caps, i);
|
||||
|
||||
Reference in New Issue
Block a user