4 * This file is part of CameraPlus.
6 * Copyright (C) 2012-2013 Mohammed Sameer <msameer@foolab.org>
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23 #ifndef QT_CAM_ROI_P_H
24 #define QT_CAM_ROI_P_H
26 #include "qtcamdevice.h"
27 #include "qtcamdevice_p.h"
28 #include "qtcamanalysisbin.h"
29 #include "qtcamgstreamermessagehandler.h"
30 #include "qtcamgstreamermessagelistener.h"
36 class QtCamRoiPrivate : public QObject {
40 QtCamRoiPrivate(QtCamDevice *device, QtCamRoi *q, QObject *parent = 0) :
51 gst_object_unref(roi);
55 dev->listener()->removeSyncHandler(handler);
57 delete handler.data();
60 GstMessage *message = msg.fetchAndStoreOrdered(0);
62 gst_message_unref(message);
67 bool sendEventToSource(GstEvent *event) {
68 if (!dev->d_ptr->videoSource) {
69 qWarning() << "No video source";
70 gst_event_unref(event);
74 return gst_element_send_event(dev->d_ptr->videoSource, event) == TRUE ? true : false;
78 if (!dev->d_ptr->viewfinderFilters) {
82 QList<GstElement *> elements =
83 dev->d_ptr->viewfinderFilters->lookup(dev->config()->roiElement());
84 if (elements.isEmpty()) {
85 qWarning() << "Cannot find element" << dev->config()->roiElement();
87 else if (elements.size() > 1) {
88 qWarning() << "Found multiple element of" << dev->config()->roiElement();
91 roi = GST_ELEMENT(gst_object_ref(elements.at(0)));
95 void installHandler() {
97 if (dev->listener()) {
98 handler = new QtCamGStreamerMessageHandler(dev->config()->roiMessage(), this);
99 dev->listener()->addSyncHandler(handler);
100 QObject::connect(handler, SIGNAL(messageSent(GstMessage *)),
101 this, SLOT(handleMessage(GstMessage *)), Qt::DirectConnection);
105 int primaryRegion(const QRectF& area, const QList<QRectF>& rects) {
107 qreal distance = 0.0;
108 QPointF center = area.center();
110 for (int x = 0; x < rects.size(); x++) {
111 const QRectF& rect = rects.at(x);
113 QPointF val = rect.center() - center;
115 qreal newDistance = sqrt(pow(val.x(), 2) + pow(val.y(), 2));
116 if (index == -1 || newDistance < distance) {
118 distance = newDistance;
126 void handleMessage(GstMessage *message) {
127 gst_message_ref(message);
129 GstMessage *oldMessage = msg.fetchAndStoreOrdered(message);
132 gst_message_unref(oldMessage);
135 QMetaObject::invokeMethod(this, "processMessage", Qt::QueuedConnection);
139 void processMessage() {
140 GstMessage *message = msg.fetchAndStoreOrdered(0);
146 unsigned width = 0, height = 0;
148 const GstStructure *s = gst_message_get_structure(message);
149 if (!gst_structure_get_uint(s, "frame-width", &width) ||
150 !gst_structure_get_uint(s, "frame-height", &height)) {
152 qWarning() << "Failed to obtain frame dimensions for ROI message";
153 gst_message_unref(message);
157 const GValue *regions = gst_structure_get_value(s, "regions");
159 qWarning() << "No regions in ROI message";
160 gst_message_unref(message);
164 guint size = gst_value_list_get_size(regions);
165 for (unsigned i = 0; i < size; i++) {
166 const GValue *region = gst_value_list_get_value(regions, i);
167 const GstStructure *structure = gst_value_get_structure(region);
169 unsigned x = 0, y = 0, w = 0, h = 0;
171 gst_structure_get_uint(structure, "region-x", &x);
172 gst_structure_get_uint(structure, "region-y", &y);
173 gst_structure_get_uint(structure, "region-w", &w);
174 gst_structure_get_uint(structure, "region-h", &h);
176 QRectF rect((qreal)x/width, (qreal)y/height, (qreal)w/width, (qreal)h/height);
181 int index = primaryRegion(QRectF(0, 0, 1, 1), rects);
183 QList<QRectF> rest(rects);
184 QRectF primary = index == -1 ? QRectF() : rest.takeAt(index);
186 emit q_ptr->regionsOfInterestUpdated(rects, primary, rest);
188 gst_message_unref(message);
195 QPointer<QtCamGStreamerMessageHandler> handler;
196 QAtomicPointer<GstMessage> msg;
199 #endif /* QT_CAM_ROI_P_H */