Infrastructure for filters.
authorMohammed Sameer <msameer@foolab.org>
Fri, 21 Dec 2012 23:42:35 +0000 (01:42 +0200)
committerMohammed Sameer <msameer@foolab.org>
Sat, 22 Dec 2012 00:21:14 +0000 (02:21 +0200)
This consists of:
A GStreamer element to duplicate buffers
A wrapper that creates a bin utilizing the above mentioned element.

On some devices like N9, memory is frame buffer memory and access to such
memory is costly since it's not cached by the CPU. What we do is we copy it
to "normal memory" and pass that to any filters that want to inspect the buffer.

lib/gst/gstcopy.cpp [new file with mode: 0644]
lib/gst/gstcopy.h [new file with mode: 0644]
lib/lib.pro
lib/qtcamanalysisbin.cpp [new file with mode: 0644]
lib/qtcamanalysisbin.h [moved from qml/CheckButtonData.qml with 72% similarity]
lib/qtcamdevice.cpp

diff --git a/lib/gst/gstcopy.cpp b/lib/gst/gstcopy.cpp
new file mode 100644 (file)
index 0000000..4bac243
--- /dev/null
@@ -0,0 +1,121 @@
+/*!
+ * 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 "gstcopy.h"
+
+GST_DEBUG_CATEGORY_STATIC (gst_copy_debug);
+#define GST_CAT_DEFAULT gst_copy_debug
+
+#ifndef PACKAGE
+#define PACKAGE "copy"
+#endif
+
+#ifndef VERSION
+#define VERSION "0.1"
+#endif
+
+static GstStaticPadTemplate src_factory = GST_STATIC_PAD_TEMPLATE ("src",
+                                                                  GST_PAD_SRC,
+                                                                  GST_PAD_ALWAYS,
+                                                                  GST_STATIC_CAPS ("ANY")
+                                                                  );
+
+static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ("sink",
+                                                                   GST_PAD_SINK,
+                                                                   GST_PAD_ALWAYS,
+                                                                   GST_STATIC_CAPS ("ANY")
+                                                                   );
+
+GST_BOILERPLATE (GstCopy, gst_copy, GstBaseTransform,
+                GST_TYPE_BASE_TRANSFORM);
+
+static GstFlowReturn gst_copy_transform_ip(GstBaseTransform *trans, GstBuffer *buf);
+static GstFlowReturn gst_copy_prepare_output_buffer(GstBaseTransform *trans, GstBuffer *input,
+                                                   gint size, GstCaps *caps, GstBuffer **buf);
+
+static void
+gst_copy_base_init(gpointer gclass) {
+  GstElementClass *element_class = GST_ELEMENT_CLASS (gclass);
+
+  gst_element_class_set_details_simple(element_class,
+                                      "Copy",
+                                      "Generic",
+                                      "Copy buffers",
+                                      "Mohammed Sameer <msameer@foolab.org>>");
+
+  gst_element_class_add_pad_template(element_class,
+                                    gst_static_pad_template_get(&src_factory));
+  gst_element_class_add_pad_template(element_class,
+                                    gst_static_pad_template_get(&sink_factory));
+}
+
+static void
+gst_copy_class_init(GstCopyClass *klass) {
+  GstBaseTransformClass *gstbasetrans_class = (GstBaseTransformClass *)klass;
+
+  gstbasetrans_class->transform_ip = GST_DEBUG_FUNCPTR(gst_copy_transform_ip);
+  gstbasetrans_class->prepare_output_buffer = GST_DEBUG_FUNCPTR(gst_copy_prepare_output_buffer);
+}
+
+static void
+gst_copy_init(GstCopy *copy, GstCopyClass *) {
+  GstBaseTransform *trans = GST_BASE_TRANSFORM(copy);
+
+  gst_base_transform_set_passthrough(trans, FALSE);
+  gst_base_transform_set_in_place(trans, TRUE);
+}
+
+static GstFlowReturn
+gst_copy_transform_ip(GstBaseTransform *trans, GstBuffer *) {
+  GST_DEBUG_OBJECT(trans, "transform ip");
+
+  return GST_FLOW_OK;
+}
+
+static GstFlowReturn
+gst_copy_prepare_output_buffer(GstBaseTransform *trans, GstBuffer *input,
+                              gint, GstCaps *, GstBuffer **buf) {
+
+  GST_DEBUG_OBJECT(trans, "prepare output buffer");
+
+  *buf = gst_buffer_copy(input);
+
+  return GST_FLOW_OK;
+}
+
+static gboolean
+copy_init(GstPlugin *copy) {
+  GST_DEBUG_CATEGORY_INIT(gst_copy_debug, "copy",
+                         0, "Copy element");
+
+  return gst_element_register(copy, "copy", GST_RANK_NONE,
+                             GST_TYPE_COPY);
+}
+
+
+GST_PLUGIN_DEFINE(GST_VERSION_MAJOR, GST_VERSION_MINOR, "copy", "Copy element",
+                 copy_init, VERSION, "GPL", "", "")
+
+gboolean qt_cam_copy_register() {
+  return gst_plugin_register_static(GST_VERSION_MAJOR, GST_VERSION_MINOR,
+                                 "copy", "Copy element",
+                                 copy_init, VERSION,
+                                 "GPL", "", "", "");
+}
diff --git a/lib/gst/gstcopy.h b/lib/gst/gstcopy.h
new file mode 100644 (file)
index 0000000..e260a79
--- /dev/null
@@ -0,0 +1,63 @@
+// -*- 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 GST_COPY_H
+#define GST_COPY_H
+
+#include <gst/gst.h>
+#include <gst/base/gstbasetransform.h>
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_COPY \
+  (gst_copy_get_type())
+#define GST_COPY(obj) \
+  (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_COPY,GstCopy))
+#define GST_COPY_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_COPY,GstCopyClass))
+#define GST_IS_COPY(obj) \
+  (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_COPY))
+#define GST_IS_COPY_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_COPY))
+
+typedef struct _GstCopy      GstCopy;
+typedef struct _GstCopyClass GstCopyClass;
+
+struct _GstCopy
+{
+  GstBaseTransform element;
+};
+
+struct _GstCopyClass
+{
+  GstBaseTransformClass parent_class;
+};
+
+GType gst_copy_get_type (void);
+
+gboolean gst_zip_src_register();
+
+G_END_DECLS
+
+gboolean qt_cam_copy_register();
+
+#endif /* GST_COPY_H */
index 211f1b8..ad3f7bb 100644 (file)
@@ -18,7 +18,8 @@ HEADERS += qtcamconfig.h qtcamera.h qtcamscanner.h qtcamdevice.h qtcamviewfinder
            qtcamzoom.h qtcamflash.h qtcamscene.h qtcamevcomp.h qtcamvideotorch.h \
            qtcamwhitebalance.h qtcamcolortone.h qtcamflickerreduction.h \
            qtcamnoisereduction.h qtcamiso.h qtcamaperture.h qtcamexposure.h \
-           qtcamvideomute.h qtcamnotifications.h qtcamfocus.h qtcamautofocus.h
+           qtcamvideomute.h qtcamnotifications.h qtcamfocus.h qtcamautofocus.h \
+           qtcamanalysisbin.h
 
 SOURCES += qtcamconfig.cpp qtcamera.cpp qtcamscanner.cpp qtcamdevice.cpp qtcamviewfinder.cpp \
            qtcammode.cpp qtcamgstreamermessagehandler.cpp qtcamgstreamermessagelistener.cpp \
@@ -28,13 +29,17 @@ SOURCES += qtcamconfig.cpp qtcamera.cpp qtcamscanner.cpp qtcamdevice.cpp qtcamvi
            qtcamzoom.cpp qtcamflash.cpp qtcamscene.cpp qtcamevcomp.cpp qtcamvideotorch.cpp \
            qtcamwhitebalance.cpp qtcamcolortone.cpp qtcamflickerreduction.cpp \
            qtcamnoisereduction.cpp qtcamiso.cpp qtcamaperture.cpp qtcamexposure.cpp \
-           qtcamvideomute.cpp qtcamnotifications.cpp qtcamfocus.cpp qtcamautofocus.cpp
+           qtcamvideomute.cpp qtcamnotifications.cpp qtcamfocus.cpp qtcamautofocus.cpp \
+           qtcamanalysisbin.cpp
 
 HEADERS += qtcammode_p.h qtcamdevice_p.h qtcamcapability_p.h qtcamautofocus_p.h \
            qtcamnotifications_p.h qtcamflash_p.h
 
 LIBS += -lgstphotography-0.10
 
+HEADERS += gst/gstcopy.h
+SOURCES += gst/gstcopy.cpp
+
 isEqual(MEEGO_EDITION, harmattan) {
 SOURCES += qtcamviewfinderrenderermeego.cpp
 HEADERS += qtcamviewfinderrenderermeego.h
diff --git a/lib/qtcamanalysisbin.cpp b/lib/qtcamanalysisbin.cpp
new file mode 100644 (file)
index 0000000..ef81a2c
--- /dev/null
@@ -0,0 +1,150 @@
+/*!
+ * 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 "qtcamanalysisbin.h"
+#include <QDebug>
+
+#define FACTORY_NAME(x) gst_plugin_feature_get_name(GST_PLUGIN_FEATURE(gst_element_get_factory(x)))
+
+GstElement *qt_cam_analysis_bin_create(QList<GstElement *>& children, const char *name) {
+  GstElement *bin = 0;
+
+  QList<GstElement *> added;
+
+  if (children.isEmpty()) {
+    return 0;
+  }
+
+  if (children.size() == 1) {
+    return qt_cam_analysis_bin_create(children.takeFirst(), name);
+  }
+
+  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);
+    }
+    else {
+      added << elem;
+    }
+  }
+
+  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);
+    }
+  }
+
+  GstPad *pad = gst_element_get_static_pad(added.first(), "sink");
+  gst_element_add_pad(bin, gst_ghost_pad_new("sink", pad));
+  gst_object_unref(GST_OBJECT(pad));
+
+  pad = gst_element_get_static_pad(added.last(), "src");
+  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);
+}
+
+/*
+ *       -- identity -- ghost pad
+ * tee -
+ *       -- queue -- copy -- filters -- fakesink
+ */
+GstElement *qt_cam_analysis_bin_create(GstElement *child, const char *name) {
+  GstPad *pad = 0;
+
+  GstElement *bin = gst_bin_new(name);
+
+  GstElement *tee = gst_element_factory_make("tee", "analysis-bin-tee");
+  GstElement *queue = gst_element_factory_make("queue", "analysis-bin-queue");
+  GstElement *fakesink = gst_element_factory_make("fakesink", "analysis-bin-fakesink");
+  GstElement *copy = gst_element_factory_make("copy", "analysis-bin-copy");
+  GstElement *identity = gst_element_factory_make("identity", "analysis-bin-identity");
+
+  if (!bin || !tee || !queue || !fakesink || !copy || !identity) {
+    qWarning() << "Failed to create some elements";
+    goto free_and_out;
+  }
+
+  gst_bin_add_many(GST_BIN(bin), tee, queue, copy, fakesink, child, identity, NULL);
+
+  g_object_set(tee, "silent", TRUE, NULL);
+  g_object_set(queue, "silent", TRUE, "leaky", 2, "max-size-buffers", 1, NULL);
+  g_object_set(fakesink, "silent", TRUE, "sync", FALSE, "async", FALSE, NULL);
+  g_object_set(identity, "silent", TRUE, "signal-handoffs", FALSE, NULL);
+
+  gst_element_link(tee, identity);
+  gst_element_link(tee, queue);
+  gst_element_link(queue, copy);
+  gst_element_link(copy, child);
+  gst_element_link(child, fakesink);
+
+  pad = gst_element_get_static_pad(tee, "sink");
+  gst_element_add_pad(bin, gst_ghost_pad_new("sink", pad));
+  gst_object_unref(GST_OBJECT(pad));
+
+  pad = gst_element_get_static_pad(identity, "src");
+  gst_element_add_pad(bin, gst_ghost_pad_new("src", pad));
+  gst_object_unref(GST_OBJECT(pad));
+
+  pad = gst_element_get_static_pad(tee, "src0");
+  g_object_set(tee, "alloc-pad", pad, NULL);
+  gst_object_unref(GST_OBJECT(pad));
+
+  return bin;
+
+ free_and_out:
+  if (bin) {
+    gst_object_unref(bin);
+  }
+  else {
+    gst_object_unref(child);
+  }
+
+  if (tee) {
+    gst_object_unref(tee);
+  }
+
+  if (queue) {
+    gst_object_unref(queue);
+  }
+
+  if (copy) {
+    gst_object_unref(copy);
+  }
+
+  if (identity) {
+    gst_object_unref(identity);
+  }
+
+  if (fakesink) {
+    gst_object_unref(fakesink);
+  }
+
+  return 0;
+}
similarity index 72%
rename from qml/CheckButtonData.qml
rename to lib/qtcamanalysisbin.h
index 72420e7..8a797a1 100644 (file)
@@ -1,4 +1,4 @@
-// -*- qml -*-
+// -*- c++ -*-
 
 /*!
  * This file is part of CameraPlus.
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  */
 
-import QtQuick 1.1
+#ifndef QT_CAM_ANALYSIS_BIN_H
+#define QT_CAM_ANALYSIS_BIN_H
 
-QtObject {
-        property string normalIcon: ""
-        property string checkedIcon: ""
-        property int value: -1
-}
+#include <gst/gst.h>
+#include <QList>
+
+GstElement *qt_cam_analysis_bin_create(QList<GstElement *>& children, const char *name);
+GstElement *qt_cam_analysis_bin_create(GstElement *child, const char *name);
+
+#endif /* QT_CAM_ANALYSIS_BIN_H */
index c9cce2b..4aa1c19 100644 (file)
 #include "qtcamimagemode.h"
 #include "qtcamvideomode.h"
 #include "qtcamnotifications.h"
+#include "gst/gstcopy.h"
 
 QtCamDevice::QtCamDevice(QtCamConfig *config, const QString& name,
                         const QVariant& id, QObject *parent) :
   QObject(parent), d_ptr(new QtCamDevicePrivate) {
 
+  static gboolean register_copy = TRUE;
+  if (register_copy) {
+    qt_cam_copy_register();
+    register_copy = FALSE;
+  }
+
   d_ptr->q_ptr = this;
   d_ptr->name = name;
   d_ptr->id = id;