2 * This file is part of CameraPlus.
4 * Copyright (C) 2012-2013 Mohammed Sameer <msameer@foolab.org>
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 #include "qtcamviewfinderrenderergeneric.h"
23 #include <gst/video/video.h>
25 #include "qtcamconfig.h"
27 QT_CAM_VIEWFINDER_RENDERER(RENDERER_TYPE_GENERIC, QtCamViewfinderRendererGeneric);
29 #define CAPS "video/x-raw-rgb, bpp = (int) 32, depth = (int) 24, red_mask = (int) 65280, green_mask = (int) 16711680, blue_mask = (int) -16777216"
31 // TODO: this needs to be debugged or rewritten. There are race conditions.
32 QtCamViewfinderRendererGeneric::QtCamViewfinderRendererGeneric(QtCamConfig *config,
34 QtCamViewfinderRenderer(config, parent), m_elem(0), m_sink(0), m_id(0) {
38 QtCamViewfinderRendererGeneric::~QtCamViewfinderRendererGeneric() {
42 g_object_remove_toggle_ref(G_OBJECT(m_elem), (GToggleNotify)sink_notify, this);
45 g_signal_handler_disconnect(m_sink, m_id);
51 void QtCamViewfinderRendererGeneric::paint(QPainter *painter) {
52 // TODO: scale and keep aspect ratio.
55 if (!m_image.isNull()) {
56 painter->drawImage(QRectF(QPointF(0, 0), m_size), m_image);
62 void QtCamViewfinderRendererGeneric::resize(const QSizeF& size) {
66 void QtCamViewfinderRendererGeneric::reset() {
70 GstElement *QtCamViewfinderRendererGeneric::sinkElement() {
72 m_elem = gst_bin_new("QtCamViewfinderRendererGenericBin");
74 qCritical() << "Failed to create sink bin";
78 GstElement *sink = gst_element_factory_make("fakesink", "QtCamViewfinderRendererGenericSink");
80 qCritical() << "Failed to create fakesink";
81 gst_object_unref(m_elem);
86 g_object_set(G_OBJECT(sink), "signal-handoffs", TRUE, "sync", TRUE, NULL);
87 m_id = g_signal_connect(sink, "handoff", G_CALLBACK(on_gst_buffer), this);
89 GstElement *csp = gst_element_factory_make("ffmpegcolorspace",
90 "QtCamViewfinderRendererGenericCsp");
92 qCritical() << "Failed to create ffmpegcolorspace";
93 gst_object_unref(sink);
94 gst_object_unref(m_elem);
99 GstElement *filter = gst_element_factory_make("capsfilter",
100 "QtCamViewfinderRendererGenericCapsFilter");
102 qCritical() << "Failed to create capsfilter";
103 gst_object_unref(sink);
104 gst_object_unref(csp);
105 gst_object_unref(m_elem);
110 GstCaps *caps = gst_caps_from_string(CAPS);
111 g_object_set(filter, "caps", caps, NULL);
112 gst_caps_unref(caps);
114 gst_bin_add_many(GST_BIN(m_elem), csp, filter, sink, NULL);
115 gst_element_link_many(csp, filter, sink, NULL);
117 GstPad *pad = gst_element_get_static_pad(csp, "sink");
118 gst_element_add_pad(m_elem, gst_ghost_pad_new("sink", pad));
119 gst_object_unref(pad);
121 g_object_add_toggle_ref(G_OBJECT(m_elem), (GToggleNotify)sink_notify, this);
129 QRectF QtCamViewfinderRendererGeneric::renderArea() {
130 // TODO: calculate this and emit renderAreaChanged() signal when needed
134 QSizeF QtCamViewfinderRendererGeneric::videoResolution() {
140 void QtCamViewfinderRendererGeneric::on_gst_buffer(GstElement *element,
141 GstBuffer *buf, GstPad *pad,
142 QtCamViewfinderRendererGeneric *q) {
155 if (!gst_video_get_size(pad, &width, &height)) {
159 QImage image(buf->data, width, height, QImage::Format_RGB32);
161 q->m_image = image.copy();
163 QMetaObject::invokeMethod(q, "updateRequested", Qt::QueuedConnection);
168 void QtCamViewfinderRendererGeneric::sink_notify(QtCamViewfinderRendererGeneric *q,
170 gboolean is_last_ref) {
175 g_object_remove_toggle_ref(G_OBJECT(q->m_elem), (GToggleNotify)sink_notify, q);