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 "qtcamanalysisbin.h"
22 #include <QStringList>
26 #define FACTORY_NAME(x) gst_plugin_feature_get_name(GST_PLUGIN_FEATURE(gst_element_get_factory(x)))
28 static QtCamAnalysisBinPrivate *qt_cam_analysis_bin_create(const QStringList& factories,
30 static QtCamAnalysisBinPrivate *qt_cam_analysis_bin_create(GstElement *child,
33 class QtCamAnalysisBinPrivate {
35 QtCamAnalysisBinPrivate() :
42 static gboolean block_buffers(GstPad *pad, GstMiniObject *o) {
53 QMultiHash<QString, GstElement *> elements;
56 QtCamAnalysisBin::QtCamAnalysisBin(QtCamAnalysisBinPrivate *d) :
58 gst_object_ref(d_ptr->bin);
61 QtCamAnalysisBin::~QtCamAnalysisBin() {
62 d_ptr->elements.clear();
65 gst_object_unref(GST_OBJECT(d_ptr->queuePad));
66 gst_object_unref(d_ptr->bin);
67 delete d_ptr; d_ptr = 0;
70 void QtCamAnalysisBin::setBlocked(bool blocked) {
71 if (blocked == isBlocked()) {
76 d_ptr->probe = gst_pad_add_buffer_probe(d_ptr->queuePad,
77 G_CALLBACK(QtCamAnalysisBinPrivate::block_buffers),
81 gst_pad_remove_data_probe(d_ptr->queuePad, d_ptr->probe);
86 bool QtCamAnalysisBin::isBlocked() const {
87 return d_ptr->probe != 0;
90 GstElement *QtCamAnalysisBin::bin() {
94 QtCamAnalysisBin *QtCamAnalysisBin::create(const QStringList& factories, const char *name) {
95 QList<GstElement *> elements;
96 if (factories.isEmpty()) {
100 QtCamAnalysisBinPrivate *d = qt_cam_analysis_bin_create(factories, name);
105 return new QtCamAnalysisBin(d);
108 QtCamAnalysisBinPrivate *qt_cam_analysis_bin_create(const QStringList& factories,
111 if (factories.isEmpty()) {
116 QHash<QString, GstElement *> elements;
117 QList<GstElement *> added;
119 bin = gst_bin_new("analysis-bin-bin");
121 foreach (const QString& factory, factories) {
122 GstElement *element = gst_element_factory_make(factory.toUtf8().constData(), NULL);
124 qWarning() << "Failed to create element" << factory;
128 if (!gst_bin_add(GST_BIN(bin), element)) {
129 qWarning() << "Failed to add element" << factory << "to bin";
130 gst_object_unref(element);
133 elements.insert(factory, element);
137 if (added.size() > 1) {
138 for (int x = 1; x < added.count(); x++) {
139 GstElement *elem = added[x];
140 GstElement *prev = added[x - 1];
142 if (!gst_element_link(prev, elem)) {
143 qWarning() << "Failed to link" << FACTORY_NAME(prev) << "and" << FACTORY_NAME(elem);
148 GstPad *pad = gst_element_get_static_pad(added.first(), "sink");
149 gst_element_add_pad(bin, gst_ghost_pad_new("sink", pad));
150 gst_object_unref(GST_OBJECT(pad));
152 pad = gst_element_get_static_pad(added.last(), "src");
153 gst_element_add_pad(bin, gst_ghost_pad_new("src", pad));
154 gst_object_unref(GST_OBJECT(pad));
156 QtCamAnalysisBinPrivate *d = qt_cam_analysis_bin_create(bin, name);
161 d->elements = elements;
167 * -- identity -- ghost pad
169 * -- queue -- copy -- filters -- fakesink
171 QtCamAnalysisBinPrivate *qt_cam_analysis_bin_create(GstElement *child, const char *name) {
173 GstPad *queuePad = 0;
174 QtCamAnalysisBinPrivate *d = 0;
176 GstElement *bin = gst_bin_new(name);
178 GstElement *tee = gst_element_factory_make("tee", "analysis-bin-tee");
179 GstElement *queue = gst_element_factory_make("queue", "analysis-bin-queue");
180 GstElement *fakesink = gst_element_factory_make("fakesink", "analysis-bin-fakesink");
181 GstElement *copy = gst_element_factory_make("copy", "analysis-bin-copy");
182 GstElement *identity = gst_element_factory_make("identity", "analysis-bin-identity");
184 if (!bin || !tee || !queue || !fakesink || !copy || !identity) {
185 qWarning() << "Failed to create some elements";
189 gst_bin_add_many(GST_BIN(bin), tee, queue, copy, fakesink, child, identity, NULL);
191 g_object_set(tee, "silent", TRUE, NULL);
192 g_object_set(queue, "silent", TRUE, "leaky", 2, "max-size-buffers", 1, NULL);
193 g_object_set(fakesink, "silent", TRUE, "sync", FALSE, "async", FALSE, NULL);
194 g_object_set(identity, "silent", TRUE, "signal-handoffs", FALSE, NULL);
196 gst_element_link(tee, identity);
197 gst_element_link(tee, queue);
198 gst_element_link(queue, copy);
199 gst_element_link(copy, child);
200 gst_element_link(child, fakesink);
202 pad = gst_element_get_static_pad(tee, "sink");
203 gst_element_add_pad(bin, gst_ghost_pad_new("sink", pad));
204 gst_object_unref(GST_OBJECT(pad));
206 pad = gst_element_get_static_pad(identity, "src");
207 gst_element_add_pad(bin, gst_ghost_pad_new("src", pad));
208 gst_object_unref(GST_OBJECT(pad));
210 pad = gst_element_get_static_pad(tee, "src0");
211 g_object_set(tee, "alloc-pad", pad, NULL);
212 gst_object_unref(GST_OBJECT(pad));
214 queuePad = gst_element_get_static_pad(queue, "src");
216 d = new QtCamAnalysisBinPrivate;
217 d->queuePad = queuePad;
223 gst_object_unref(bin);
226 gst_object_unref(child);
230 gst_object_unref(tee);
234 gst_object_unref(queue);
238 gst_object_unref(copy);
242 gst_object_unref(identity);
246 gst_object_unref(fakesink);
252 QList<GstElement *> QtCamAnalysisBin::lookup(const QString& factory) {
253 if (d_ptr->elements.contains(factory)) {
254 return d_ptr->elements.values(factory);
257 return QList<GstElement *>();