[motiondetect]
use-local-buffer=false
-ratio=1, 2
+ratio=1,2
[facetracking]
use-local-buffer=false
max-num-faces=5
tracking-interval=0
draw-box=false
+event=false
[mp4mux]
dts-method=0
[viewfinder-filters]
elements = facetracking, motiondetect
+
+[roi]
+element=facetracking
+enable=message
+message=regions-of-interest
bool AutoFocus::canFocus(int sceneMode) {
return m_af->canFocus((QtCamScene::SceneMode)sceneMode);
}
-
-void AutoFocus::setRegionOfInterest(const QRectF& roi) {
- return m_af->setRegionOfInterest(roi);
-}
Status status();
Status cafStatus();
-public slots:
- void setRegionOfInterest(const QRectF& roi);
-
signals:
void valueChanged();
void cafValueChanged();
#include "flickerreduction.h"
#include "focus.h"
#include "autofocus.h"
+#include "roi.h"
#include "videomute.h"
#include "videotorch.h"
m_flickerReduction(0),
m_focus(0),
m_autoFocus(0),
+ m_roi(0),
m_videoMute(0),
m_videoTorch(0) {
delete m_flickerReduction;
delete m_focus;
delete m_autoFocus;
+ delete m_roi;
delete m_videoMute;
delete m_videoTorch;
}
m_autoFocus = new AutoFocus(dev, this);
emit autoFocusChanged();
+ delete m_roi;
+ m_roi = new Roi(dev, this);
+ emit roiChanged();
+
delete m_videoMute;
m_videoMute = new VideoMute(dev, this);
emit videoMuteChanged();
return m_autoFocus;
}
+Roi *Camera::roi() const {
+ return m_roi;
+}
+
VideoMute *Camera::videoMute() const {
return m_videoMute;
}
class FlickerReduction;
class Focus;
class AutoFocus;
+class Roi;
class VideoMute;
class VideoTorch;
Q_PROPERTY(FlickerReduction *flickerReduction READ flickerReduction NOTIFY flickerReductionChanged);
Q_PROPERTY(Focus *focus READ focus NOTIFY focusChanged);
Q_PROPERTY(AutoFocus *autoFocus READ autoFocus NOTIFY autoFocusChanged);
+ Q_PROPERTY(Roi *roi READ roi NOTIFY roiChanged);
Q_PROPERTY(VideoMute *videoMute READ videoMute NOTIFY videoMuteChanged);
Q_PROPERTY(VideoTorch *videoTorch READ videoTorch NOTIFY videoTorchChanged);
FlickerReduction *flickerReduction() const;
Focus *focus() const;
AutoFocus *autoFocus() const;
+ Roi *roi() const;
VideoMute *videoMute() const;
VideoTorch *videoTorch() const;
void flickerReductionChanged();
void focusChanged();
void autoFocusChanged();
+ void roiChanged();
void videoMuteChanged();
void videoTorchChanged();
FlickerReduction *m_flickerReduction;
Focus *m_focus;
AutoFocus *m_autoFocus;
+ Roi *m_roi;
VideoMute *m_videoMute;
VideoTorch *m_videoTorch;
colortone.h exposure.h aperture.h iso.h noisereduction.h \
flickerreduction.h videomute.h metadata.h imagesettings.h \
imageresolutionmodel.h videosettings.h videoresolutionmodel.h \
- notifications.h notificationscontainer.h sounds.h focus.h autofocus.h
+ notifications.h notificationscontainer.h sounds.h focus.h autofocus.h \
+ roi.h
SOURCES += plugin.cpp previewprovider.cpp camera.cpp mode.cpp imagemode.cpp videomode.cpp \
zoom.cpp flash.cpp scene.cpp evcomp.cpp videotorch.cpp whitebalance.cpp \
colortone.cpp exposure.cpp aperture.cpp iso.cpp noisereduction.cpp \
flickerreduction.cpp videomute.cpp metadata.cpp imagesettings.cpp \
imageresolutionmodel.cpp videosettings.cpp videoresolutionmodel.cpp \
- notifications.cpp notificationscontainer.cpp sounds.cpp focus.cpp autofocus.cpp
+ notifications.cpp notificationscontainer.cpp sounds.cpp focus.cpp autofocus.cpp \
+ roi.cpp
#include "flickerreduction.h"
#include "focus.h"
#include "autofocus.h"
+#include "roi.h"
#include "videomute.h"
#include "metadata.h"
#include "imagesettings.h"
qmlRegisterUncreatableType<FlickerReduction>(URI, MAJOR, MINOR, "FlickerReduction", QObject::tr("Cannot create separate instance of FlickerReduction"));
qmlRegisterUncreatableType<Focus>(URI, MAJOR, MINOR, "Focus", QObject::tr("Cannot create separate instance of Focus"));
qmlRegisterUncreatableType<AutoFocus>(URI, MAJOR, MINOR, "AutoFocus", QObject::tr("Cannot create separate instance of AutoFocus"));
+ qmlRegisterUncreatableType<Roi>(URI, MAJOR, MINOR, "Roi", QObject::tr("Cannot create separate instance of Roi"));
qmlRegisterUncreatableType<VideoMute>(URI, MAJOR, MINOR, "VideoMute", QObject::tr("Cannot create separate instance of VideoMute"));
qmlRegisterUncreatableType<VideoTorch>(URI, MAJOR, MINOR, "VideoTorch", QObject::tr("Cannot create separate instance of VideoTorch"));
--- /dev/null
+/*!
+ * This file is part of CameraPlus.
+ *
+ * Copyright (C) 2012 Mohammed Sameer <msameer@foolab.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "roi.h"
+#include "qtcamroi.h"
+
+Roi::Roi(QtCamDevice *device, QObject *parent) :
+ QObject(parent),
+ m_roi(new QtCamRoi(device)) {
+
+ QObject::connect(m_roi,
+ SIGNAL(regionsOfInterestUpdated(const QList<QRectF>&, const QRectF&, const QList<QRectF>&)),
+ this,
+ SLOT(handleRegionsChanged(const QList<QRectF>&, const QRectF&, const QList<QRectF>&)));
+}
+
+Roi::~Roi() {
+ delete m_roi; m_roi = 0;
+}
+
+
+void Roi::setEnabled(bool enabled) {
+ if (Roi::isEnabled() != enabled) {
+ m_roi->setEnabled(enabled);
+ emit enabledChanged();
+ }
+}
+
+bool Roi::isEnabled() {
+ return m_roi->isEnabled();
+}
+
+void Roi::setRegionOfInterest(const QRectF& region) {
+ m_roi->setRegionOfInterest(region);
+}
+
+void Roi::resetRegionOfInterest() {
+ m_roi->resetRegionOfInterest();
+}
+
+void Roi::handleRegionsChanged(const QList<QRectF>& regions, const QRectF& primary,
+ const QList<QRectF>& rest) {
+
+ QVariantList regionsList = variantList(regions);
+ QVariantList restList = variantList(rest);
+ QVariant primaryRect = QVariant::fromValue(primary);
+
+ emit regionsChanged(regionsList, primaryRect, restList);
+}
+
+QVariantList Roi::variantList(const QList<QRectF>& rects) {
+ QVariantList list;
+
+ foreach(const QRectF& rect, rects) {
+ list.append(QVariant::fromValue(rect));
+ }
+
+ return list;
+}
--- /dev/null
+// -*- c++ -*-
+
+/*!
+ * This file is part of CameraPlus.
+ *
+ * Copyright (C) 2012 Mohammed Sameer <msameer@foolab.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef ROI_H
+#define ROI_H
+
+#include <QObject>
+#include <QRectF>
+#include <QVariantList>
+
+class QtCamDevice;
+class QtCamRoi;
+
+class Roi : public QObject {
+ Q_OBJECT
+
+ Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled NOTIFY enabledChanged);
+
+public:
+ Roi(QtCamDevice *device, QObject *parent = 0);
+ ~Roi();
+
+ void setEnabled(bool enabled);
+ bool isEnabled();
+
+ QList<QRectF> regions();
+
+public slots:
+ void setRegionOfInterest(const QRectF& region);
+ void resetRegionOfInterest();
+
+signals:
+ void enabledChanged();
+ void regionsChanged(const QVariantList& regions, const QVariant& primary,
+ const QVariantList& rest);
+
+private slots:
+ void handleRegionsChanged(const QList<QRectF>& regions, const QRectF& primary,
+ const QList<QRectF>& rest);
+
+private:
+ QVariantList variantList(const QList<QRectF>& rects);
+
+ QtCamRoi *m_roi;
+};
+
+#endif /* ROI_H */
qtcamwhitebalance.h qtcamcolortone.h qtcamflickerreduction.h \
qtcamnoisereduction.h qtcamiso.h qtcamaperture.h qtcamexposure.h \
qtcamvideomute.h qtcamnotifications.h qtcamfocus.h qtcamautofocus.h \
- qtcamanalysisbin.h qtcampropertysetter.h
+ qtcamanalysisbin.h qtcampropertysetter.h qtcamroi.h
SOURCES += qtcamconfig.cpp qtcamera.cpp qtcamscanner.cpp qtcamdevice.cpp qtcamviewfinder.cpp \
qtcammode.cpp qtcamgstreamermessagehandler.cpp qtcamgstreamermessagelistener.cpp \
qtcamwhitebalance.cpp qtcamcolortone.cpp qtcamflickerreduction.cpp \
qtcamnoisereduction.cpp qtcamiso.cpp qtcamaperture.cpp qtcamexposure.cpp \
qtcamvideomute.cpp qtcamnotifications.cpp qtcamfocus.cpp qtcamautofocus.cpp \
- qtcamanalysisbin.cpp qtcampropertysetter.cpp
+ qtcamanalysisbin.cpp qtcampropertysetter.cpp qtcamroi.cpp
HEADERS += qtcammode_p.h qtcamdevice_p.h qtcamcapability_p.h qtcamautofocus_p.h \
- qtcamnotifications_p.h qtcamflash_p.h
+ qtcamnotifications_p.h qtcamflash_p.h qtcamroi_p.h
LIBS += -lgstphotography-0.10
#include "qtcamanalysisbin.h"
#include <QStringList>
#include <QDebug>
+#include <QHash>
#define FACTORY_NAME(x) gst_plugin_feature_get_name(GST_PLUGIN_FEATURE(gst_element_get_factory(x)))
-static GstElement *qt_cam_analysis_bin_create(QList<GstElement *>& children,
- const char *name, GstPad **queuePad);
-static GstElement *qt_cam_analysis_bin_create(GstElement *child,
- const char *name, GstPad **queuePad);
+static QtCamAnalysisBinPrivate *qt_cam_analysis_bin_create(const QStringList& factories,
+ const char *name);
+static QtCamAnalysisBinPrivate *qt_cam_analysis_bin_create(GstElement *child,
+ const char *name);
class QtCamAnalysisBinPrivate {
public:
GstElement *bin;
gulong probe;
GstPad *queuePad;
+ QMultiHash<QString, GstElement *> elements;
};
QtCamAnalysisBin::QtCamAnalysisBin(QtCamAnalysisBinPrivate *d) :
}
QtCamAnalysisBin::~QtCamAnalysisBin() {
+ d_ptr->elements.clear();
+
setBlocked(false);
gst_object_unref(GST_OBJECT(d_ptr->queuePad));
gst_object_unref(d_ptr->bin);
return 0;
}
- foreach (const QString& factory, factories) {
- GstElement *element = gst_element_factory_make(factory.toUtf8().constData(), NULL);
- if (!element) {
- qWarning() << "Failed to create element" << factory;
- continue;
- }
-
- elements << element;
- }
-
- GstPad *pad = 0;
- GstElement *bin = qt_cam_analysis_bin_create(elements, name, &pad);
- if (!bin) {
+ QtCamAnalysisBinPrivate *d = qt_cam_analysis_bin_create(factories, name);
+ if (!d) {
return 0;
}
- QtCamAnalysisBinPrivate *d = new QtCamAnalysisBinPrivate;
- d->bin = bin;
- d->queuePad = pad;
-
return new QtCamAnalysisBin(d);
}
-GstElement *qt_cam_analysis_bin_create(QList<GstElement *>& children,
- const char *name, GstPad **queuePad) {
- GstElement *bin = 0;
+QtCamAnalysisBinPrivate *qt_cam_analysis_bin_create(const QStringList& factories,
+ const char *name) {
- QList<GstElement *> added;
-
- if (children.isEmpty()) {
+ if (factories.isEmpty()) {
return 0;
}
- if (children.size() == 1) {
- return qt_cam_analysis_bin_create(children.takeFirst(), name, queuePad);
- }
+ GstElement *bin = 0;
+ QHash<QString, GstElement *> elements;
+ QList<GstElement *> added;
bin = gst_bin_new("analysis-bin-bin");
- while (!children.isEmpty()) {
- GstElement *elem = children.takeFirst();
-
- if (!gst_bin_add(GST_BIN(bin), elem)) {
- qWarning() << "Failed to add element" << FACTORY_NAME(elem) << "to bin";
- gst_object_unref(elem);
+ foreach (const QString& factory, factories) {
+ GstElement *element = gst_element_factory_make(factory.toUtf8().constData(), NULL);
+ if (!element) {
+ qWarning() << "Failed to create element" << factory;
+ continue;
}
- else {
- added << elem;
+
+ if (!gst_bin_add(GST_BIN(bin), element)) {
+ qWarning() << "Failed to add element" << factory << "to bin";
+ gst_object_unref(element);
}
+
+ elements.insert(factory, element);
+ added << element;
}
- for (int x = 1; x < added.count(); x++) {
- GstElement *elem = added[x];
- GstElement *prev = added[x - 1];
+ if (added.size() > 1) {
+ for (int x = 1; x < added.count(); x++) {
+ GstElement *elem = added[x];
+ GstElement *prev = added[x - 1];
- if (!gst_element_link(prev, elem)) {
- qWarning() << "Failed to link" << FACTORY_NAME(prev) << "and" << FACTORY_NAME(elem);
+ if (!gst_element_link(prev, elem)) {
+ qWarning() << "Failed to link" << FACTORY_NAME(prev) << "and" << FACTORY_NAME(elem);
+ }
}
}
gst_element_add_pad(bin, gst_ghost_pad_new("src", pad));
gst_object_unref(GST_OBJECT(pad));
- return qt_cam_analysis_bin_create(bin, name, queuePad);
+ QtCamAnalysisBinPrivate *d = qt_cam_analysis_bin_create(bin, name);
+ if (!d) {
+ return 0;
+ }
+
+ d->elements = elements;
+
+ return d;
}
/*
* tee -
* -- queue -- copy -- filters -- fakesink
*/
-GstElement *qt_cam_analysis_bin_create(GstElement *child, const char *name, GstPad **queuePad) {
+QtCamAnalysisBinPrivate *qt_cam_analysis_bin_create(GstElement *child, const char *name) {
GstPad *pad = 0;
+ GstPad *queuePad = 0;
+ QtCamAnalysisBinPrivate *d = 0;
GstElement *bin = gst_bin_new(name);
g_object_set(tee, "alloc-pad", pad, NULL);
gst_object_unref(GST_OBJECT(pad));
- *queuePad = gst_element_get_static_pad(queue, "src");
+ queuePad = gst_element_get_static_pad(queue, "src");
- return bin;
+ d = new QtCamAnalysisBinPrivate;
+ d->queuePad = queuePad;
+ d->bin = bin;
+ return d;
free_and_out:
if (bin) {
return 0;
}
+
+QList<GstElement *> QtCamAnalysisBin::lookup(const QString& factory) {
+ if (d_ptr->elements.contains(factory)) {
+ return d_ptr->elements.values(factory);
+ }
+
+ return QList<GstElement *>();
+}
class QtCamAnalysisBinPrivate;
class QStringList;
+class QString;
class QtCamAnalysisBin {
public:
GstElement *bin();
+ QList<GstElement *> lookup(const QString& factory);
+
private:
QtCamAnalysisBin(QtCamAnalysisBinPrivate *d);
#include "qtcamautofocus.h"
#include "qtcamautofocus_p.h"
-#include <QRectF>
-
-#ifndef G_VALUE_INIT
-#define G_VALUE_INIT { 0, { { 0 } } }
-#endif /* G_VALUE_INIT */
QtCamAutoFocus::QtCamAutoFocus(QtCamDevice *dev, QObject *parent) :
QObject(parent),
return true;
}
-
-void QtCamAutoFocus::setRegionOfInterest(const QRectF& roi) {
- if (!d_ptr->dev || !d_ptr->dev->viewfinder()) {
- return;
- }
-
- QSizeF vf = d_ptr->dev->viewfinder()->videoResolution();
- if (vf.isEmpty()) {
- return;
- }
-
- int frameWidth = vf.width();
- int frameHeight = vf.height();
- int x = roi.x() * frameWidth;
- int y = roi.y() * frameHeight;
- int width = roi.width() * frameWidth;
- int height = roi.height() * frameHeight;
-
- // if we have an empty roi then we reset:
- int priority = roi.isEmpty() ? 0 : 1;
-
- GstStructure *region = gst_structure_new("region0",
- "region-x", G_TYPE_UINT, x,
- "region-y", G_TYPE_UINT, y,
- "region-w", G_TYPE_UINT, width,
- "region-h", G_TYPE_UINT, height,
- "region-priority", G_TYPE_UINT, priority,
- "region-id", G_TYPE_UINT, 0,
- NULL);
-
- GValue regionValue = G_VALUE_INIT;
- GValue regionList = G_VALUE_INIT;
-
- g_value_init(®ionValue, GST_TYPE_STRUCTURE);
- g_value_init(®ionList, GST_TYPE_LIST);
-
- gst_value_set_structure(®ionValue, region);
- gst_value_list_append_value(®ionList, ®ionValue);
-
- GstStructure *s = gst_structure_new("regions-of-interest",
- "frame-width", G_TYPE_UINT, frameWidth,
- "frame-height", G_TYPE_UINT, frameHeight,
- NULL);
- gst_structure_set_value(s, "regions", ®ionList);
-
- GstEvent *event = gst_event_new_custom(GST_EVENT_CUSTOM_UPSTREAM, s);
- gst_structure_free(region);
- g_value_unset(®ionValue);
- g_value_unset(®ionList);
-
- if (!d_ptr->sendEventToSource(event)) {
- qWarning() << "Failed to send ROI event";
- }
-}
class QtCamDevice;
class QtCamAutoFocusPrivate;
-class QRectF;
class QtCamAutoFocus : public QObject {
Q_OBJECT
bool canFocus(const QtCamScene::SceneMode& mode);
- void setRegionOfInterest(const QRectF& roi);
-
signals:
void statusChanged();
void cafStatusChanged();
return false;
}
- bool sendEventToSource(GstEvent *event) {
- if (!dev->d_ptr->videoSource) {
- qWarning() << "No video source";
- gst_event_unref(event);
- return false;
- }
-
- return gst_element_send_event(dev->d_ptr->videoSource, event) == TRUE ? true : false;
- }
-
public slots:
void handleMessage(GstMessage *message) {
if (setStatus(&status, message)) {
QStringList QtCamConfig::viewfinderFilters() const {
return d_ptr->conf->value("viewfinder-filters/elements").toStringList();
}
+
+QString QtCamConfig::roiElement() const {
+ return d_ptr->conf->value("roi/element").toString();
+}
+
+QString QtCamConfig::roiMessageName() const {
+ return d_ptr->conf->value("roi/message").toString();
+}
+
+QString QtCamConfig::roiEnableProperty() const {
+ return d_ptr->conf->value("roi/enable").toString();
+}
+
+QString QtCamConfig::roiMessage() const {
+ return d_ptr->conf->value("roi/message").toString();
+}
QStringList viewfinderFilters() const;
+ QString roiElement() const;
+ QString roiMessageName() const;
+ QString roiEnableProperty() const;
+ QString roiMessage() const;
+
private:
QtCamConfigPrivate *d_ptr;
};
friend class QtCamVideoTorch;
friend class QtCamVideoMute;
friend class QtCamAutoFocusPrivate;
+ friend class QtCamRoiPrivate;
QtCamDevicePrivate *d_ptr;
};
gst_object_unref(elem);
break;
+
case GST_ITERATOR_RESYNC:
gst_iterator_resync(iter);
break;
+
case GST_ITERATOR_ERROR:
- done = TRUE;
- break;
case GST_ITERATOR_DONE:
- done = TRUE;
+ done = true;
break;
}
}
--- /dev/null
+/*!
+ * This file is part of CameraPlus.
+ *
+ * Copyright (C) 2012 Mohammed Sameer <msameer@foolab.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "qtcamroi.h"
+#include "qtcamroi_p.h"
+
+#ifndef G_VALUE_INIT
+#define G_VALUE_INIT { 0, { { 0 } } }
+#endif /* G_VALUE_INIT */
+
+QtCamRoi::QtCamRoi(QtCamDevice *dev, QObject *parent) :
+ QObject(parent),
+ d_ptr(new QtCamRoiPrivate(dev, this, this)) {
+
+ d_ptr->init();
+ d_ptr->installHandler();
+}
+
+QtCamRoi::~QtCamRoi() {
+ delete d_ptr; d_ptr = 0;
+}
+
+void QtCamRoi::setRegionOfInterest(const QRectF& roi) {
+ if (!d_ptr->dev || !d_ptr->dev->viewfinder()) {
+ return;
+ }
+
+ QSizeF vf = d_ptr->dev->viewfinder()->videoResolution();
+ if (vf.isEmpty()) {
+ return;
+ }
+
+ int frameWidth = vf.width();
+ int frameHeight = vf.height();
+ int x = roi.x() * frameWidth;
+ int y = roi.y() * frameHeight;
+ int width = roi.width() * frameWidth;
+ int height = roi.height() * frameHeight;
+
+ // if we have an empty roi then we reset:
+ int priority = roi.isEmpty() ? 0 : 1;
+
+ GstStructure *region = gst_structure_new("region0",
+ "region-x", G_TYPE_UINT, x,
+ "region-y", G_TYPE_UINT, y,
+ "region-w", G_TYPE_UINT, width,
+ "region-h", G_TYPE_UINT, height,
+ "region-priority", G_TYPE_UINT, priority,
+ "region-id", G_TYPE_UINT, 0,
+ NULL);
+
+ GValue regionValue = G_VALUE_INIT;
+ GValue regionList = G_VALUE_INIT;
+
+ g_value_init(®ionValue, GST_TYPE_STRUCTURE);
+ g_value_init(®ionList, GST_TYPE_LIST);
+
+ gst_value_set_structure(®ionValue, region);
+ gst_value_list_append_value(®ionList, ®ionValue);
+
+ GstStructure *s = gst_structure_new("regions-of-interest",
+ "frame-width", G_TYPE_UINT, frameWidth,
+ "frame-height", G_TYPE_UINT, frameHeight,
+ NULL);
+ gst_structure_set_value(s, "regions", ®ionList);
+
+ GstEvent *event = gst_event_new_custom(GST_EVENT_CUSTOM_UPSTREAM, s);
+ gst_structure_free(region);
+ g_value_unset(®ionValue);
+ g_value_unset(®ionList);
+
+ if (!d_ptr->sendEventToSource(event)) {
+ qWarning() << "Failed to send ROI event";
+ }
+}
+
+void QtCamRoi::resetRegionOfInterest() {
+ setRegionOfInterest(QRectF());
+}
+
+void QtCamRoi::setEnabled(bool enabled) {
+ if (enabled == isEnabled()) {
+ return;
+ }
+
+ if (!d_ptr->roi) {
+ return;
+ }
+
+ gboolean val = enabled ? TRUE : FALSE;
+
+ g_object_set(d_ptr->roi, d_ptr->dev->config()->roiEnableProperty().toUtf8().constData(),
+ val, NULL);
+}
+
+bool QtCamRoi::isEnabled() {
+ if (!d_ptr->roi) {
+ return false;
+ }
+
+ gboolean val = FALSE;
+
+ g_object_get(d_ptr->roi, d_ptr->dev->config()->roiEnableProperty().toUtf8().constData(),
+ &val, NULL);
+
+ return val == TRUE;
+}
--- /dev/null
+// -*- c++ -*-
+
+/*!
+ * This file is part of CameraPlus.
+ *
+ * Copyright (C) 2012 Mohammed Sameer <msameer@foolab.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef QT_CAM_ROI_H
+#define QT_CAM_ROI_H
+
+#include <QObject>
+
+class QtCamDevice;
+class QtCamRoiPrivate;
+class QRectF;
+
+class QtCamRoi : public QObject {
+ Q_OBJECT
+ friend class QtCamRoiPrivate;
+
+public:
+ QtCamRoi(QtCamDevice *dev, QObject *parent = 0);
+ ~QtCamRoi();
+
+ void setRegionOfInterest(const QRectF& roi);
+ void resetRegionOfInterest();
+
+ void setEnabled(bool enabled);
+
+ bool isEnabled();
+
+signals:
+ void regionsOfInterestUpdated(const QList<QRectF>& regions,
+ const QRectF& primary,
+ const QList<QRectF>& rest);
+
+private:
+ QtCamRoiPrivate *d_ptr;
+};
+
+#endif /* QT_CAM_ROI_H */
--- /dev/null
+// -*- c++ -*-
+
+/*!
+ * This file is part of CameraPlus.
+ *
+ * Copyright (C) 2012 Mohammed Sameer <msameer@foolab.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef QT_CAM_ROI_P_H
+#define QT_CAM_ROI_P_H
+
+#include "qtcamdevice.h"
+#include "qtcamdevice_p.h"
+#include "qtcamanalysisbin.h"
+#include "qtcamgstreamermessagehandler.h"
+#include "qtcamgstreamermessagelistener.h"
+#include "qtcamroi.h"
+#include <QDebug>
+#include <QPointer>
+#include <cmath>
+
+class QtCamRoiPrivate : public QObject {
+ Q_OBJECT
+
+public:
+ QtCamRoiPrivate(QtCamDevice *device, QtCamRoi *q, QObject *parent = 0) :
+ QObject(parent),
+ q_ptr(q),
+ dev(device),
+ roi(0),
+ msg(0) {
+
+ }
+
+ ~QtCamRoiPrivate() {
+ if (roi) {
+ gst_object_unref(roi);
+ }
+
+ if (handler) {
+ dev->listener()->removeSyncHandler(handler);
+
+ delete handler.data();
+ }
+
+ GstMessage *message = msg.fetchAndStoreOrdered(0);
+ if (message) {
+ gst_message_unref(message);
+ message = 0;
+ }
+ }
+
+ bool sendEventToSource(GstEvent *event) {
+ if (!dev->d_ptr->videoSource) {
+ qWarning() << "No video source";
+ gst_event_unref(event);
+ return false;
+ }
+
+ return gst_element_send_event(dev->d_ptr->videoSource, event) == TRUE ? true : false;
+ }
+
+ void init() {
+ if (!dev->d_ptr->viewfinderFilters) {
+ return;
+ }
+
+ QList<GstElement *> elements =
+ dev->d_ptr->viewfinderFilters->lookup(dev->config()->roiElement());
+ if (elements.isEmpty()) {
+ qWarning() << "Cannot find element" << dev->config()->roiElement();
+ }
+ else if (elements.size() > 1) {
+ qWarning() << "Found multiple element of" << dev->config()->roiElement();
+ }
+ else {
+ roi = GST_ELEMENT(gst_object_ref(elements.at(0)));
+ }
+ }
+
+ void installHandler() {
+
+ if (dev->listener()) {
+ handler = new QtCamGStreamerMessageHandler(dev->config()->roiMessage(), this);
+ dev->listener()->addSyncHandler(handler);
+ QObject::connect(handler, SIGNAL(messageSent(GstMessage *)),
+ this, SLOT(handleMessage(GstMessage *)), Qt::DirectConnection);
+ }
+ }
+
+ int primaryRegion(const QRectF& area, const QList<QRectF>& rects) {
+ int index = -1;
+ qreal distance = 0.0;
+ QPointF center = area.center();
+
+ for (int x = 0; x < rects.size(); x++) {
+ const QRectF& rect = rects.at(x);
+
+ QPointF val = rect.center() - center;
+
+ qreal newDistance = sqrt(pow(val.x(), 2) + pow(val.y(), 2));
+ if (index == -1 || newDistance < distance) {
+ index = x;
+ distance = newDistance;
+ }
+ }
+
+ return -1;
+ }
+
+public slots:
+ void handleMessage(GstMessage *message) {
+ gst_message_ref(message);
+
+ GstMessage *oldMessage = msg.fetchAndStoreOrdered(message);
+
+ if (oldMessage) {
+ gst_message_unref(oldMessage);
+ }
+
+ QMetaObject::invokeMethod(this, "processMessage", Qt::QueuedConnection);
+ }
+
+private slots:
+ void processMessage() {
+ GstMessage *message = msg.fetchAndStoreOrdered(0);
+ if (!message) {
+ return;
+ }
+
+ QList<QRectF> rects;
+ unsigned width = 0, height = 0;
+
+ const GstStructure *s = gst_message_get_structure(message);
+ if (!gst_structure_get_uint(s, "frame-width", &width) ||
+ !gst_structure_get_uint(s, "frame-height", &height)) {
+
+ qWarning() << "Failed to obtain frame dimensions for ROI message";
+ gst_message_unref(message);
+ return;
+ }
+
+ const GValue *regions = gst_structure_get_value(s, "regions");
+ if (!regions) {
+ qWarning() << "No regions in ROI message";
+ gst_message_unref(message);
+ return;
+ }
+
+ guint size = gst_value_list_get_size(regions);
+ for (unsigned i = 0; i < size; i++) {
+ const GValue *region = gst_value_list_get_value(regions, i);
+ const GstStructure *structure = gst_value_get_structure(region);
+
+ unsigned x = 0, y = 0, w = 0, h = 0;
+
+ gst_structure_get_uint(structure, "region-x", &x);
+ gst_structure_get_uint(structure, "region-y", &y);
+ gst_structure_get_uint(structure, "region-w", &w);
+ gst_structure_get_uint(structure, "region-h", &h);
+
+ QRectF rect((qreal)x/width, (qreal)y/height, (qreal)w/width, (qreal)h/height);
+
+ rects << rect;
+ }
+
+ int index = primaryRegion(QRectF(0, 0, width, height), rects);
+
+ QList<QRectF> rest(rects);
+ QRectF primary = index == -1 ? QRectF() : rest.takeAt(index);
+
+ emit q_ptr->regionsOfInterestUpdated(rects, primary, rest);
+
+ gst_message_unref(message);
+ }
+
+public:
+ QtCamRoi *q_ptr;
+ QtCamDevice *dev;
+ GstElement *roi;
+ QPointer<QtCamGStreamerMessageHandler> handler;
+ QAtomicPointer<GstMessage> msg;
+};
+
+#endif /* QT_CAM_ROI_P_H */
// thus we do it here
onModeChanged: {
moveToCenter();
- cam.autoFocus.setRegionOfInterest(Qt.rect(0, 0, 0, 0));
+ cam.roi.resetRegionOfInterest();
}
}
function setRegionOfInterest() {
if (!reticle.touchMode) {
// console.log("resetting ROI");
- cam.autoFocus.setRegionOfInterest(Qt.rect(0, 0, 0, 0));
+ cam.roi.resetRegionOfInterest();
return;
}
height = height / cam.videoResolution.height;
// console.log("Setting ROI to: " + x + " " + y);
- cam.autoFocus.setRegionOfInterest(Qt.rect(x, y, width, height));
+ cam.roi.setRegionOfInterest(Qt.rect(x, y, width, height));
}
onReleased: {
alwaysRunToEnd: true
}
}
+
+ Indicator {
+ id: faceDetectionIndicator
+ visible: settings.faceDetectionEnabled
+ source: "image://theme/icon-m-camera-face-detection-screen"
+ }
+
}
}
}
}
+ Item {
+ width: parent.width
+ height: Math.max(enableFaceDetectionLabel.height, enableFaceDetection.height);
+
+ Label {
+ id: enableFaceDetectionLabel
+ anchors.left: parent.left
+ text: qsTr("Enable face detection");
+ }
+
+ Switch {
+ id: enableFaceDetection
+ anchors.right: parent.right
+ // We have to do it that way because QML complains about a binding
+ // loop for checked if we bind the checked property to the settings value.
+ Component.onCompleted: checked = settings.faceDetectionEnabled;
+ onCheckedChanged: settings.faceDetectionEnabled = checked;
+ }
+ }
+
CameraSettings {
anchors.horizontalCenter: parent.horizontalCenter
}
#define PATH QString("%1%2.config%2/cameraplus.conf").arg(QDir::homePath()).arg(QDir::separator())
-#define DEFAULT_MODE 1
-#define DEFAULT_SCENE_MODE 6 // Auto
-#define DEFAULT_USE_GPS true
-#define DEFAULT_USE_GEOTAGS true
-#define DEFAULT_COLOR_FILTER 0
-#define DEFAULT_WHITE_BALANCE 0
-#define DEFAULT_EV_COMP 0.0
-#define DEFAULT_FLASH_MODE 0
-#define DEFAULT_IMAGE_ISO 0
-#define DEFAULT_IMAGE_RESOLUTION "high"
-#define DEFAULT_IMAGE_ASPECT_RATIO "16:9"
-#define DEFAULT_VIDEO_RESOLUTION "high"
-#define DEFAULT_SOUND_ENABLED true
-#define DEFAULT_VIDEO_TORCH_ON false
-#define DEFAULT_SHOW_TOOL_BAR false
-#define DEFAULT_VIDEO_MUTE false
-#define DEFAULT_GRID_ENABLED false
+#define DEFAULT_MODE 1
+#define DEFAULT_SCENE_MODE 6 // Auto
+#define DEFAULT_USE_GPS true
+#define DEFAULT_USE_GEOTAGS true
+#define DEFAULT_COLOR_FILTER 0
+#define DEFAULT_WHITE_BALANCE 0
+#define DEFAULT_EV_COMP 0.0
+#define DEFAULT_FLASH_MODE 0
+#define DEFAULT_IMAGE_ISO 0
+#define DEFAULT_IMAGE_RESOLUTION "high"
+#define DEFAULT_IMAGE_ASPECT_RATIO "16:9"
+#define DEFAULT_VIDEO_RESOLUTION "high"
+#define DEFAULT_SOUND_ENABLED true
+#define DEFAULT_VIDEO_TORCH_ON false
+#define DEFAULT_SHOW_TOOL_BAR false
+#define DEFAULT_VIDEO_MUTE false
+#define DEFAULT_GRID_ENABLED false
+#define DEFAULT_FACE_DETECTION_ENABLED true
Settings::Settings(QObject *parent) :
QObject(parent),
emit gridEnabledChanged();
}
}
+
+bool Settings::isFaceDetectionEnabled() const {
+ return m_settings->value("image/faceDetectionEnabled", DEFAULT_FACE_DETECTION_ENABLED).toBool();
+}
+
+void Settings::setFaceDetectionEnabled(bool enabled) {
+ if (isFaceDetectionEnabled() != enabled) {
+ m_settings->setValue("image/faceDetectionEnabled", enabled);
+ emit faceDetectionEnabledChanged();
+ }
+}
Q_PROPERTY(bool gridEnabled READ isGridEnabled WRITE setGridEnabled NOTIFY gridEnabledChanged);
+ Q_PROPERTY(bool faceDetectionEnabled READ isFaceDetectionEnabled WRITE setFaceDetectionEnabled NOTIFY faceDetectionEnabledChanged);
+
public:
Settings(QObject *parent = 0);
~Settings();
bool isGridEnabled() const;
void setGridEnabled(bool enabled);
+ bool isFaceDetectionEnabled() const;
+ void setFaceDetectionEnabled(bool enabled);
+
signals:
void modeChanged();
void creatorNameChanged();
void toolBarShownChanged();
void videoMutedChanged();
void gridEnabledChanged();
+ void faceDetectionEnabledChanged();
private:
QSettings *m_settings;