2 * This file is part of CameraPlus.
4 * Copyright (C) 2012 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>
25 #define FACTORY_NAME(x) gst_plugin_feature_get_name(GST_PLUGIN_FEATURE(gst_element_get_factory(x)))
27 static GstElement *qt_cam_analysis_bin_create(QList<GstElement *>& children,
28 const char *name, GstPad **queuePad);
29 static GstElement *qt_cam_analysis_bin_create(GstElement *child,
30 const char *name, GstPad **queuePad);
32 class QtCamAnalysisBinPrivate {
34 QtCamAnalysisBinPrivate() :
41 static gboolean block_buffers(GstPad *pad, GstMiniObject *o) {
54 QtCamAnalysisBin::QtCamAnalysisBin(QtCamAnalysisBinPrivate *d) :
56 gst_object_ref(d_ptr->bin);
59 QtCamAnalysisBin::~QtCamAnalysisBin() {
61 gst_object_unref(GST_OBJECT(d_ptr->queuePad));
62 gst_object_unref(d_ptr->bin);
63 delete d_ptr; d_ptr = 0;
66 void QtCamAnalysisBin::setBlocked(bool blocked) {
67 if (blocked == isBlocked()) {
72 d_ptr->probe = gst_pad_add_buffer_probe(d_ptr->queuePad,
73 G_CALLBACK(QtCamAnalysisBinPrivate::block_buffers),
77 gst_pad_remove_data_probe(d_ptr->queuePad, d_ptr->probe);
82 bool QtCamAnalysisBin::isBlocked() const {
83 return d_ptr->probe != 0;
86 GstElement *QtCamAnalysisBin::bin() {
90 QtCamAnalysisBin *QtCamAnalysisBin::create(const QStringList& factories, const char *name) {
91 QList<GstElement *> elements;
92 if (factories.isEmpty()) {
96 foreach (const QString& factory, factories) {
97 GstElement *element = gst_element_factory_make(factory.toUtf8().constData(), NULL);
99 qWarning() << "Failed to create element" << factory;
107 GstElement *bin = qt_cam_analysis_bin_create(elements, name, &pad);
112 QtCamAnalysisBinPrivate *d = new QtCamAnalysisBinPrivate;
116 return new QtCamAnalysisBin(d);
119 GstElement *qt_cam_analysis_bin_create(QList<GstElement *>& children,
120 const char *name, GstPad **queuePad) {
123 QList<GstElement *> added;
125 if (children.isEmpty()) {
129 if (children.size() == 1) {
130 return qt_cam_analysis_bin_create(children.takeFirst(), name, queuePad);
133 bin = gst_bin_new("analysis-bin-bin");
135 while (!children.isEmpty()) {
136 GstElement *elem = children.takeFirst();
138 if (!gst_bin_add(GST_BIN(bin), elem)) {
139 qWarning() << "Failed to add element" << FACTORY_NAME(elem) << "to bin";
140 gst_object_unref(elem);
147 for (int x = 1; x < added.count(); x++) {
148 GstElement *elem = added[x];
149 GstElement *prev = added[x - 1];
151 if (!gst_element_link(prev, elem)) {
152 qWarning() << "Failed to link" << FACTORY_NAME(prev) << "and" << FACTORY_NAME(elem);
156 GstPad *pad = gst_element_get_static_pad(added.first(), "sink");
157 gst_element_add_pad(bin, gst_ghost_pad_new("sink", pad));
158 gst_object_unref(GST_OBJECT(pad));
160 pad = gst_element_get_static_pad(added.last(), "src");
161 gst_element_add_pad(bin, gst_ghost_pad_new("src", pad));
162 gst_object_unref(GST_OBJECT(pad));
164 return qt_cam_analysis_bin_create(bin, name, queuePad);
168 * -- identity -- ghost pad
170 * -- queue -- copy -- filters -- fakesink
172 GstElement *qt_cam_analysis_bin_create(GstElement *child, const char *name, GstPad **queuePad) {
175 GstElement *bin = gst_bin_new(name);
177 GstElement *tee = gst_element_factory_make("tee", "analysis-bin-tee");
178 GstElement *queue = gst_element_factory_make("queue", "analysis-bin-queue");
179 GstElement *fakesink = gst_element_factory_make("fakesink", "analysis-bin-fakesink");
180 GstElement *copy = gst_element_factory_make("copy", "analysis-bin-copy");
181 GstElement *identity = gst_element_factory_make("identity", "analysis-bin-identity");
183 if (!bin || !tee || !queue || !fakesink || !copy || !identity) {
184 qWarning() << "Failed to create some elements";
188 gst_bin_add_many(GST_BIN(bin), tee, queue, copy, fakesink, child, identity, NULL);
190 g_object_set(tee, "silent", TRUE, NULL);
191 g_object_set(queue, "silent", TRUE, "leaky", 2, "max-size-buffers", 1, NULL);
192 g_object_set(fakesink, "silent", TRUE, "sync", FALSE, "async", FALSE, NULL);
193 g_object_set(identity, "silent", TRUE, "signal-handoffs", FALSE, NULL);
195 gst_element_link(tee, identity);
196 gst_element_link(tee, queue);
197 gst_element_link(queue, copy);
198 gst_element_link(copy, child);
199 gst_element_link(child, fakesink);
201 pad = gst_element_get_static_pad(tee, "sink");
202 gst_element_add_pad(bin, gst_ghost_pad_new("sink", pad));
203 gst_object_unref(GST_OBJECT(pad));
205 pad = gst_element_get_static_pad(identity, "src");
206 gst_element_add_pad(bin, gst_ghost_pad_new("src", pad));
207 gst_object_unref(GST_OBJECT(pad));
209 pad = gst_element_get_static_pad(tee, "src0");
210 g_object_set(tee, "alloc-pad", pad, NULL);
211 gst_object_unref(GST_OBJECT(pad));
213 *queuePad = gst_element_get_static_pad(queue, "src");
219 gst_object_unref(bin);
222 gst_object_unref(child);
226 gst_object_unref(tee);
230 gst_object_unref(queue);
234 gst_object_unref(copy);
238 gst_object_unref(identity);
242 gst_object_unref(fakesink);