Remove old camerabin

This commit is contained in:
Tim-Philipp Müller 2012-04-30 17:44:34 +01:00
parent da001be15a
commit 7d65470c4a
39 changed files with 1315 additions and 15689 deletions

View file

@ -147,7 +147,6 @@ if test "x$HAVE_UNISTD_H" != "xyes"; then
GST_PLUGINS_SELECTED=`echo $GST_PLUGINS_SELECTED | $SED -e s/festival//`
fi
dnl used by camerabin
AC_CHECK_HEADERS([sys/time.h])
dnl used by ext/dts
@ -301,7 +300,7 @@ dnl *** plug-ins to include ***
dnl Non ported plugins (non-dependant, then dependant)
dnl Make sure you have a space before and after all plugins
GST_PLUGINS_NONPORTED=" aiff \
camerabin cdxaparse \
cdxaparse \
dccp faceoverlay festival \
fieldanalysis freeverb freeze frei0r gaudieffects \
hdvparse id3tag inter interlace ivfparse jpegformat jp2kdecimator \
@ -325,7 +324,6 @@ AG_GST_CHECK_PLUGIN(asfmux)
AG_GST_CHECK_PLUGIN(audiovisualizers)
AG_GST_CHECK_PLUGIN(autoconvert)
AG_GST_CHECK_PLUGIN(bayer)
AG_GST_CHECK_PLUGIN(camerabin)
AG_GST_CHECK_PLUGIN(camerabin2)
AG_GST_CHECK_PLUGIN(cdxaparse)
AG_GST_CHECK_PLUGIN(coloreffects)
@ -2013,7 +2011,6 @@ gst/asfmux/Makefile
gst/audiovisualizers/Makefile
gst/autoconvert/Makefile
gst/bayer/Makefile
gst/camerabin/Makefile
gst/camerabin2/Makefile
gst/cdxaparse/Makefile
gst/coloreffects/Makefile
@ -2113,7 +2110,6 @@ tests/Makefile
tests/check/Makefile
tests/files/Makefile
tests/examples/Makefile
tests/examples/camerabin/Makefile
tests/examples/camerabin2/Makefile
tests/examples/directfb/Makefile
tests/examples/mxf/Makefile

View file

@ -115,7 +115,6 @@ EXTRA_HFILES = \
$(top_srcdir)/gst/audiovisualizers/gstspectrascope.h \
$(top_srcdir)/gst/audiovisualizers/gstsynaescope.h \
$(top_srcdir)/gst/audiovisualizers/gstwavescope.h \
$(top_srcdir)/gst/camerabin/gstcamerabin.h \
$(top_srcdir)/gst/camerabin2/gstcamerabin2.h \
$(top_srcdir)/gst/coloreffects/gstcoloreffects.h \
$(top_srcdir)/gst/dataurisrc/gstdataurisrc.h \

View file

@ -24,7 +24,6 @@
<xi:include href="xml/element-bulge.xml" />
<xi:include href="xml/element-burn.xml" />
<xi:include href="xml/element-camerabin.xml" />
<xi:include href="xml/element-camerabin2.xml" />
<xi:include href="xml/element-celtdec.xml" />
<xi:include href="xml/element-celtenc.xml" />
<xi:include href="xml/element-chromium.xml" />
@ -142,7 +141,6 @@
<xi:include href="xml/plugin-bayer.xml" />
<xi:include href="xml/plugin-bz2.xml" />
<xi:include href="xml/plugin-camerabin.xml" />
<xi:include href="xml/plugin-camerabin2.xml" />
<xi:include href="xml/plugin-cdaudio.xml" />
<xi:include href="xml/plugin-cdxaparse.xml" />
<xi:include href="xml/plugin-celt.xml" />

View file

@ -104,29 +104,14 @@ gst_burn_plugin_init
<FILE>element-camerabin</FILE>
<TITLE>camerabin</TITLE>
GstCameraBin
GstCameraBinMode
<SUBSECTION Standard>
GstCameraBinClass
GST_CAMERABIN
GST_IS_CAMERABIN
GST_TYPE_CAMERABIN
GST_CAMERABIN_CLASS
GST_IS_CAMERABIN_CLASS
gst_camerabin_get_type
</SECTION>
<SECTION>
<FILE>element-camerabin2</FILE>
<TITLE>camerabin2</TITLE>
GstCameraBin2
<SUBSECTION Standard>
GstCameraBin2Class
GST_CAMERA_BIN2
GST_IS_CAMERA_BIN2
GST_TYPE_CAMERA_BIN2
GST_CAMERA_BIN2_CLASS
GST_IS_CAMERA_BIN2_CLASS
gst_camera_bin2_get_type
GST_CAMERA_BIN
GST_IS_CAMERA_BIN
GST_TYPE_CAMERA_BIN
GST_CAMERA_BIN_CLASS
GST_IS_CAMERA_BIN_CLASS
gst_camera_bin_get_type
</SECTION>
<SECTION>

View file

@ -1,22 +0,0 @@
<plugin>
<name>camerabin</name>
<description>High level api for DC (Digital Camera) application</description>
<filename>../../gst/camerabin/.libs/libgstcamerabin.so</filename>
<basename>libgstcamerabin.so</basename>
<version>0.10.23.1</version>
<license>LGPL</license>
<source>gst-plugins-bad</source>
<package>GStreamer Bad Plug-ins git</package>
<origin>Unknown package origin</origin>
<elements>
<element>
<name>camerabin</name>
<longname>Camera Bin</longname>
<class>Generic/Bin/Camera</class>
<description>Handle lot of features present in DSC</description>
<author>Nokia Corporation &lt;multimedia@maemo.org&gt;, Edgard Lima &lt;edgard.lima@indt.org.br&gt;</author>
<pads>
</pads>
</element>
</elements>
</plugin>

View file

@ -1,64 +0,0 @@
<plugin>
<name>camerabin2</name>
<description>camerabin2</description>
<filename>../../gst/camerabin2/.libs/libgstcamerabin2.so</filename>
<basename>libgstcamerabin2.so</basename>
<version>0.11.90</version>
<license>LGPL</license>
<source>gst-plugins-bad</source>
<package>GStreamer Bad Plug-ins source release</package>
<origin>Unknown package origin</origin>
<elements>
<element>
<name>camerabin2</name>
<longname>CameraBin2</longname>
<class>Generic/Bin/Camera</class>
<description>CameraBin2</description>
<author>Thiago Santos &lt;thiago.sousa.santos@collabora.co.uk&gt;</author>
<pads>
</pads>
</element>
<element>
<name>viewfinderbin</name>
<longname>Viewfinder Bin</longname>
<class>Sink/Video</class>
<description>Viewfinder Bin used in camerabin2</description>
<author>Thiago Santos &lt;thiago.sousa.santos@collabora.com&gt;</author>
<pads>
<caps>
<name>sink</name>
<direction>sink</direction>
<presence>always</presence>
<details>video/x-raw</details>
</caps>
</pads>
</element>
<element>
<name>wrappercamerabinsrc</name>
<longname>Wrapper camera src element for camerabin2</longname>
<class>Source/Video</class>
<description>Wrapper camera src element for camerabin2</description>
<author>Thiago Santos &lt;thiago.sousa.santos@collabora.com&gt;</author>
<pads>
<caps>
<name>imgsrc</name>
<direction>source</direction>
<presence>always</presence>
<details>ANY</details>
</caps>
<caps>
<name>vfsrc</name>
<direction>source</direction>
<presence>always</presence>
<details>ANY</details>
</caps>
<caps>
<name>vidsrc</name>
<direction>source</direction>
<presence>always</presence>
<details>ANY</details>
</caps>
</pads>
</element>
</elements>
</plugin>

View file

@ -1,2 +0,0 @@
gstcamerabin-marshal.c
gstcamerabin-marshal.h

View file

@ -1,63 +0,0 @@
glib_gen_prefix = __gst_camerabin
glib_gen_basename = gstcamerabin
include $(top_srcdir)/common/gst-glib-gen.mak
built_sources = gstcamerabin-marshal.c
built_headers = gstcamerabin-marshal.h
BUILT_SOURCES = $(built_sources) $(built_headers)
CLEANFILES = $(BUILT_SOURCES)
EXTRA_DIST = gstcamerabin-marshal.list
plugin_LTLIBRARIES = libgstcamerabin.la
libgstcamerabin_la_SOURCES = gstcamerabin.c \
gstcamerabincolorbalance.c \
gstinputselector.c \
camerabinimage.c \
camerabinvideo.c \
camerabingeneral.c \
camerabinpreview.c \
gstcamerabin-enum.c
nodist_libgstcamerabin_la_SOURCES = $(built_sources)
libgstcamerabin_la_CFLAGS = \
$(GST_PLUGINS_BAD_CFLAGS) \
$(GST_CFLAGS) $(GST_BASE_CFLAGS) $(GST_PLUGINS_BASE_CFLAGS) \
-DGST_USE_UNSTABLE_API
libgstcamerabin_la_LIBADD = \
$(top_builddir)/gst-libs/gst/interfaces/libgstphotography-$(GST_API_VERSION).la \
$(GST_LIBS) $(GST_BASE_LIBS) $(GST_PLUGINS_BASE_LIBS) \
-lgstinterfaces-$(GST_API_VERSION) -lgsttag-$(GST_API_VERSION)
libgstcamerabin_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
libgstcamerabin_la_LIBTOOLFLAGS = --tag=disable-static
noinst_HEADERS = gstcamerabin.h \
gstcamerabincolorbalance.h \
gstinputselector.h \
camerabinimage.h \
camerabinvideo.h \
camerabindebug.h \
camerabingeneral.h \
camerabinpreview.h \
gstcamerabin-enum.h
Android.mk: Makefile.am $(BUILT_SOURCES)
androgenizer \
-:PROJECT libgstcamerabin -:SHARED libgstcamerabin \
-:TAGS eng debug \
-:REL_TOP $(top_srcdir) -:ABS_TOP $(abs_top_srcdir) \
-:SOURCES $(libgstcamerabin_la_SOURCES) \
-:CFLAGS $(DEFS) $(DEFAULT_INCLUDES) $(libgstcamerabin_la_CFLAGS) \
-:LDFLAGS $(libgstcamerabin_la_LDFLAGS) \
$(libgstcamerabin_la_LIBADD) \
-ldl \
-:LIBFILTER_STATIC gstphotography-@GST_API_VERSION@ \
gstbasecamerabinsrc-@GST_API_VERSION@ \
-:PASSTHROUGH LOCAL_ARM_MODE:=arm \
LOCAL_MODULE_PATH:='$$(TARGET_OUT)/lib/gstreamer-0.10' \
> $@

View file

@ -1,31 +0,0 @@
= Cleanups =
* often two g_object_set for same object one after the other
* use GST_*_OBJECT () more often
* there are two gst_element_set_state() one after each other
= Renaming =
* internal use of img->image, vid->video
= Refactorisation =
* gstcamerabin:gst_camerabin_rewrite_tags
- sounds fishy, should use normal tagsetter method
- gst_camerabin_rewrite_tags_to_bin(9 why don't we just send a tag-event?
* file-name property
- supplying an already opened filedeskriptor would be more safe
- need to check what filesink does if the file exists and cannot be overwritten
* imagbin
- we want async operation here (especialy for burst mode capture)
- right now, its a bit fragile as we muck with locked_state
- main problem is that the location for filesink can only be set in NULL/READY
and we need to do that sync'ed with the dataflow. we can't use multifilesink
as it does a file per pad_push
- one problem of the current approach is that we can't have an image in e.g,
postprocessing while anotherone is beeing saved
- we could use a pool of imagebins:
- configure one (set filename)
- push_buffer
- on eos, put it back to the pool
- for this we need to check that we can have multiple instances of e.g.
dsp jpeg encoders

View file

@ -1,30 +0,0 @@
/*
* GStreamer
* Copyright (C) 2010 Nokia Corporation <multimedia@maemo.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 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
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#ifndef __CAMERABIN_DEBUG_H_
#define __CAMERABIN_DEBUG_H_
#include <gst/gst.h>
/* debug logging category */
GST_DEBUG_CATEGORY_EXTERN (gst_camerabin_debug);
#define GST_CAT_DEFAULT gst_camerabin_debug
#endif /* #ifndef __CAMERABIN_DEBUG_H_ */

View file

@ -1,263 +0,0 @@
/*
* GStreamer
* Copyright (C) 2008 Nokia Corporation <multimedia@maemo.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 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
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
/**
* SECTION:camerabingeneral
* @short_description: helper functions for #GstCameraBin and it's modules
*
* Common helper functions for #GstCameraBin, #GstCameraBinImage and
* #GstCameraBinVideo.
*
*/
#include <string.h>
#include <glib.h>
#include "camerabingeneral.h"
#include "gstinputselector.h"
GST_DEBUG_CATEGORY (gst_camerabin_debug);
/**
* gst_camerabin_add_element:
* @bin: add an element to this bin
* @new_elem: new element to be added
*
* Adds given element to given @bin. Looks for an unconnected src pad
* from the @bin and links the element to it. Raises an error if adding
* or linking failed. Unrefs the element in the case of an error.
*
* Returns: %TRUE if adding and linking succeeded, %FALSE otherwise.
*/
gboolean
gst_camerabin_add_element (GstBin * bin, GstElement * new_elem)
{
gboolean ret;
g_return_val_if_fail (bin, FALSE);
g_return_val_if_fail (new_elem, FALSE);
ret = gst_camerabin_try_add_element (bin, new_elem);
if (!ret) {
gchar *elem_name = gst_element_get_name (new_elem);
GST_ELEMENT_ERROR (bin, CORE, NEGOTIATION, (NULL),
("linking %s failed", elem_name));
g_free (elem_name);
gst_object_unref (new_elem);
}
return ret;
}
/**
* gst_camerabin_try_add_element:
* @bin: tries adding an element to this bin
* @new_elem: new element to be added
*
* Adds given element to given @bin. Looks for an unconnected src pad
* from the @bin and links the element to it.
*
* Returns: %TRUE if adding and linking succeeded, %FALSE otherwise.
*/
gboolean
gst_camerabin_try_add_element (GstBin * bin, GstElement * new_elem)
{
GstPad *bin_pad;
GstElement *bin_elem;
gboolean ret = TRUE;
g_return_val_if_fail (bin, FALSE);
g_return_val_if_fail (new_elem, FALSE);
/* Get pads for linking */
bin_pad = gst_bin_find_unlinked_pad (bin, GST_PAD_SRC);
/* Add to bin */
gst_bin_add (GST_BIN (bin), new_elem);
/* Link, if unconnected pad was found, otherwise just add it to bin */
if (bin_pad) {
GST_DEBUG_OBJECT (bin, "linking %s to %s:%s", GST_OBJECT_NAME (new_elem),
GST_DEBUG_PAD_NAME (bin_pad));
bin_elem = gst_pad_get_parent_element (bin_pad);
gst_object_unref (bin_pad);
if (!gst_element_link_pads_full (bin_elem, NULL, new_elem, NULL,
GST_PAD_LINK_CHECK_CAPS)) {
gst_object_ref (new_elem);
gst_bin_remove (bin, new_elem);
ret = FALSE;
}
gst_object_unref (bin_elem);
} else {
GST_INFO_OBJECT (bin, "no unlinked source pad in bin");
}
return ret;
}
/**
* gst_camerabin_create_and_add_element:
* @bin: tries adding an element to this bin
* @elem_name: name of the element to be created
* @instance_name: name of the instance of the element to be created
*
* Creates an element according to given name and
* adds it to given @bin. Looks for an unconnected src pad
* from the @bin and links the element to it.
*
* Returns: pointer to the new element if successful, NULL otherwise.
*/
GstElement *
gst_camerabin_create_and_add_element (GstBin * bin, const gchar * elem_name,
const gchar * instance_name)
{
GstElement *new_elem;
g_return_val_if_fail (bin, FALSE);
g_return_val_if_fail (elem_name, FALSE);
if (strcmp (elem_name, "input-selector") == 0) {
/* we ship our own copy of input-selector because we still use the
* "select-all" property which was removed when input-selector was
* moved to core */
new_elem = g_object_new (GST_TYPE_INPUT_SELECTOR, NULL);
} else {
new_elem = gst_element_factory_make (elem_name, NULL);
}
if (!new_elem) {
GST_ELEMENT_ERROR (bin, CORE, MISSING_PLUGIN, (NULL),
("could not create \"%s\" element.", elem_name));
} else if (!gst_camerabin_add_element (bin, new_elem)) {
new_elem = NULL;
}
return new_elem;
}
/* try to change the state of an element. This function returns the element when
* the state change could be performed. When this function returns NULL an error
* occured and the element is unreffed if @unref is TRUE. */
static GstElement *
try_element (GstElement * bin, GstElement * element, gboolean unref)
{
GstStateChangeReturn ret;
if (element) {
ret = gst_element_set_state (element, GST_STATE_READY);
if (ret == GST_STATE_CHANGE_FAILURE) {
GST_DEBUG_OBJECT (bin, "failed state change..");
gst_element_set_state (element, GST_STATE_NULL);
if (unref)
gst_object_unref (element);
element = NULL;
}
}
return element;
}
GstElement *
gst_camerabin_setup_default_element (GstBin * bin, GstElement * user_elem,
const gchar * auto_elem_name, const gchar * default_elem_name)
{
GstElement *elem;
if (user_elem) {
GST_DEBUG_OBJECT (bin, "trying configured element");
elem = try_element (GST_ELEMENT_CAST (bin), user_elem, FALSE);
} else {
/* only try fallback if no specific sink was chosen */
GST_DEBUG_OBJECT (bin, "trying %s", auto_elem_name);
elem = gst_element_factory_make (auto_elem_name, NULL);
elem = try_element (GST_ELEMENT_CAST (bin), elem, TRUE);
if (elem == NULL) {
/* if default sink from config.h is different then try it too */
if (strcmp (default_elem_name, auto_elem_name)) {
GST_DEBUG_OBJECT (bin, "trying %s", default_elem_name);
elem = gst_element_factory_make (default_elem_name, NULL);
elem = try_element (GST_ELEMENT_CAST (bin), elem, TRUE);
}
}
}
return elem;
}
/**
* gst_camerabin_remove_elements_from_bin:
* @bin: removes all elements from this bin
*
* Removes all elements from this @bin.
*/
void
gst_camerabin_remove_elements_from_bin (GstBin * bin)
{
GstIterator *iter = NULL;
gpointer data = NULL;
GstElement *elem = NULL;
gboolean done = FALSE;
iter = gst_bin_iterate_elements (bin);
while (!done) {
switch (gst_iterator_next (iter, &data)) {
case GST_ITERATOR_OK:
elem = GST_ELEMENT (data);
gst_bin_remove (bin, elem);
gst_element_set_state (GST_ELEMENT (elem), GST_STATE_NULL);
/* Iterator increased the element refcount, so unref */
gst_object_unref (elem);
break;
case GST_ITERATOR_RESYNC:
gst_iterator_resync (iter);
break;
case GST_ITERATOR_ERROR:
GST_WARNING_OBJECT (bin, "error in iterating elements");
done = TRUE;
break;
case GST_ITERATOR_DONE:
done = TRUE;
break;
}
}
gst_iterator_free (iter);
}
/**
* gst_camerabin_drop_eos_probe:
* @pad: pad receiving the event
* @event: received event
* @u_data: not used
*
* Event probe that drop all eos events.
*
* Returns: FALSE to drop the event, TRUE otherwise
*/
gboolean
gst_camerabin_drop_eos_probe (GstPad * pad, GstEvent * event, gpointer u_data)
{
gboolean ret = TRUE;
switch (GST_EVENT_TYPE (event)) {
case GST_EVENT_EOS:
GST_DEBUG ("dropping eos in %s:%s", GST_DEBUG_PAD_NAME (pad));
ret = FALSE;
break;
default:
break;
}
return ret;
}

View file

@ -1,36 +0,0 @@
/*
* GStreamer
* Copyright (C) 2008 Nokia Corporation <multimedia@maemo.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 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
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#ifndef __CAMERABIN_GENERAL_H_
#define __CAMERABIN_GENERAL_H_
#include <gst/gst.h>
gboolean gst_camerabin_try_add_element (GstBin * bin, GstElement * new_elem);
gboolean gst_camerabin_add_element (GstBin * bin, GstElement * new_elem);
GstElement *gst_camerabin_create_and_add_element (GstBin * bin, const gchar * elem_name, const gchar * instance_name);
GstElement * gst_camerabin_setup_default_element (GstBin * bin, GstElement *user_elem, const gchar *auto_elem_name, const gchar *default_elem_name);
void gst_camerabin_remove_elements_from_bin (GstBin * bin);
gboolean gst_camerabin_drop_eos_probe (GstPad * pad, GstEvent * event, gpointer u_data);
#endif /* #ifndef __CAMERABIN_GENERAL_H_ */

View file

@ -1,777 +0,0 @@
/*
* GStreamer
* Copyright (C) 2008 Nokia Corporation <multimedia@maemo.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 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
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
/**
* SECTION:camerabinimage
* @short_description: image capturing module of #GstCameraBin
*
* <refsect2>
* <para>
*
* The pipeline for this module is:
*
* <informalexample>
* <programlisting>
*-----------------------------------------------------------------------------
*
* -> [post proc] -> csp -> imageenc -> metadatamuxer -> filesink
*
*-----------------------------------------------------------------------------
* </programlisting>
* </informalexample>
*
* The image bin opens file for image writing in READY to PAUSED state change.
* The image bin closes the file in PAUSED to READY state change.
*
* </para>
* </refsect2>
*/
/*
* includes
*/
#include <gst/gst.h>
#include "camerabinimage.h"
#include "camerabindebug.h"
#include "camerabingeneral.h"
#include "gstcamerabin-enum.h"
#include "string.h"
/* default internal element names */
#define DEFAULT_SINK "filesink"
#define DEFAULT_ENC "jpegenc"
#define DEFAULT_FORMATTER "jifmux"
#define DEFAULT_FLAGS GST_CAMERABIN_FLAG_IMAGE_COLOR_CONVERSION
enum
{
PROP_0,
PROP_FILENAME
};
static gboolean gst_camerabin_image_create_elements (GstCameraBinImage * img);
static void gst_camerabin_image_destroy_elements (GstCameraBinImage * img);
static void gst_camerabin_image_dispose (GstCameraBinImage * sink);
static GstStateChangeReturn
gst_camerabin_image_change_state (GstElement * element,
GstStateChange transition);
static gboolean gst_camerabin_image_send_event (GstElement * element,
GstEvent * event);
static void gst_camerabin_image_set_property (GObject * object, guint prop_id,
const GValue * value, GParamSpec * pspec);
static void gst_camerabin_image_get_property (GObject * object, guint prop_id,
GValue * value, GParamSpec * pspec);
static gboolean metadata_write_probe (GstPad * pad, GstBuffer * buffer,
gpointer u_data);
static gboolean prepare_element (GList ** result,
const gchar * default_element_name, GstElement * app_elem,
GstElement ** res_elem);
GST_BOILERPLATE (GstCameraBinImage, gst_camerabin_image, GstBin, GST_TYPE_BIN);
static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("sink",
GST_PAD_SINK,
GST_PAD_ALWAYS,
GST_STATIC_CAPS_ANY);
static void
gst_camerabin_image_base_init (gpointer klass)
{
GstElementClass *eklass = GST_ELEMENT_CLASS (klass);
gst_element_class_add_pad_template (eklass,
gst_static_pad_template_get (&sink_template));
gst_element_class_set_details_simple (eklass,
"Image capture bin for camerabin", "Bin/Image",
"Process and store image data",
"Edgard Lima <edgard.lima@indt.org.br>, "
"Nokia Corporation <multimedia@maemo.org>");
}
static void
gst_camerabin_image_class_init (GstCameraBinImageClass * klass)
{
GObjectClass *gobject_class;
GstElementClass *eklass = GST_ELEMENT_CLASS (klass);
gobject_class = G_OBJECT_CLASS (klass);
gobject_class->dispose =
(GObjectFinalizeFunc) GST_DEBUG_FUNCPTR (gst_camerabin_image_dispose);
eklass->change_state = GST_DEBUG_FUNCPTR (gst_camerabin_image_change_state);
eklass->send_event = GST_DEBUG_FUNCPTR (gst_camerabin_image_send_event);
gobject_class->set_property =
GST_DEBUG_FUNCPTR (gst_camerabin_image_set_property);
gobject_class->get_property =
GST_DEBUG_FUNCPTR (gst_camerabin_image_get_property);
/**
* GstCameraBinImage:filename
*
* This property can be used to specify the filename of the image.
*
**/
g_object_class_install_property (gobject_class, PROP_FILENAME,
g_param_spec_string ("filename", "Filename",
"Filename of the image to save", NULL,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
}
static void
gst_camerabin_image_init (GstCameraBinImage * img,
GstCameraBinImageClass * g_class)
{
img->filename = g_string_new ("");
img->post = NULL;
img->csp = NULL;
img->enc = NULL;
img->app_enc = NULL;
img->formatter = NULL;
img->app_formatter = NULL;
img->sink = NULL;
/* Create src and sink ghost pads */
img->sinkpad = gst_ghost_pad_new_no_target ("sink", GST_PAD_SINK);
gst_element_add_pad (GST_ELEMENT (img), img->sinkpad);
img->flags = DEFAULT_FLAGS;
}
static void
gst_camerabin_image_dispose (GstCameraBinImage * img)
{
GST_DEBUG_OBJECT (img, "disposing");
g_string_free (img->filename, TRUE);
img->filename = NULL;
if (img->elements) {
g_list_free (img->elements);
img->elements = NULL;
}
if (img->sink) {
GST_LOG_OBJECT (img, "disposing %s with refcount %d",
GST_ELEMENT_NAME (img->sink), GST_OBJECT_REFCOUNT_VALUE (img->sink));
gst_object_unref (img->sink);
img->sink = NULL;
}
if (img->formatter) {
GST_LOG_OBJECT (img, "disposing %s with refcount %d",
GST_ELEMENT_NAME (img->formatter),
GST_OBJECT_REFCOUNT_VALUE (img->formatter));
gst_object_unref (img->formatter);
img->formatter = NULL;
}
if (img->app_formatter) {
gst_object_sink (img->app_formatter);
GST_LOG_OBJECT (img, "disposing %s with refcount %d",
GST_ELEMENT_NAME (img->app_formatter),
GST_OBJECT_REFCOUNT_VALUE (img->app_formatter));
gst_object_unref (img->app_formatter);
img->app_formatter = NULL;
}
if (img->enc) {
GST_LOG_OBJECT (img, "disposing %s with refcount %d",
GST_ELEMENT_NAME (img->enc), GST_OBJECT_REFCOUNT_VALUE (img->enc));
gst_object_unref (img->enc);
img->enc = NULL;
}
if (img->csp) {
GST_LOG_OBJECT (img, "disposing %s with refcount %d",
GST_ELEMENT_NAME (img->csp), GST_OBJECT_REFCOUNT_VALUE (img->csp));
gst_object_unref (img->csp);
img->csp = NULL;
}
/* Note: if imagebin was never set to READY state the
ownership of elements created by application were never
taken by bin and therefore gst_object_sink is called for
these elements (they may still be in floating state
and not unreffed properly without sinking first)
FIXME, something else is wrong if you have to sink here
*/
if (img->app_enc) {
//gst_object_ref_sink (img->app_enc);
GST_LOG_OBJECT (img, "disposing %s with refcount %d",
GST_ELEMENT_NAME (img->app_enc),
GST_OBJECT_REFCOUNT_VALUE (img->app_enc));
gst_object_unref (img->app_enc);
img->app_enc = NULL;
}
if (img->post) {
//gst_object_ref_sink (img->post);
GST_LOG_OBJECT (img, "disposing %s with refcount %d",
GST_ELEMENT_NAME (img->post), GST_OBJECT_REFCOUNT_VALUE (img->post));
gst_object_unref (img->post);
img->post = NULL;
}
G_OBJECT_CLASS (parent_class)->dispose ((GObject *) img);
}
static GstStateChangeReturn
gst_camerabin_image_change_state (GstElement * element,
GstStateChange transition)
{
GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
GstCameraBinImage *img = GST_CAMERABIN_IMAGE (element);
GST_DEBUG_OBJECT (element, "changing state: %s -> %s",
gst_element_state_get_name (GST_STATE_TRANSITION_CURRENT (transition)),
gst_element_state_get_name (GST_STATE_TRANSITION_NEXT (transition)));
switch (transition) {
case GST_STATE_CHANGE_NULL_TO_READY:
if (!gst_camerabin_image_create_elements (img)) {
return GST_STATE_CHANGE_FAILURE;
}
/* Allow setting filename when image bin in READY state */
gst_element_set_locked_state (img->sink, TRUE);
GST_INFO_OBJECT (img, "locking imagebin->sink state to %s",
gst_element_state_get_name (GST_STATE (img->sink)));
break;
case GST_STATE_CHANGE_READY_TO_PAUSED:
if (!g_str_equal (img->filename->str, "")) {
GST_INFO_OBJECT (img, "preparing image with filename: %s",
img->filename->str);
gst_element_set_locked_state (img->sink, FALSE);
} else {
GST_INFO_OBJECT (img, "keep sink locked, we have no filename yet");
}
break;
case GST_STATE_CHANGE_PAUSED_TO_READY:
/* Set sink to NULL in order to write the file _now_ */
GST_INFO_OBJECT (img, "write image with filename: %s",
img->filename->str);
gst_element_set_locked_state (img->sink, TRUE);
gst_element_set_state (img->sink, GST_STATE_NULL);
g_string_assign (img->filename, "");
break;
default:
break;
}
ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
switch (transition) {
case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
/* Write debug graph to file */
GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS (GST_BIN (GST_ELEMENT_PARENT (img)),
GST_DEBUG_GRAPH_SHOW_MEDIA_TYPE |
GST_DEBUG_GRAPH_SHOW_NON_DEFAULT_PARAMS, "imagebin.playing");
break;
case GST_STATE_CHANGE_READY_TO_NULL:
gst_camerabin_image_destroy_elements (img);
break;
default:
break;
}
GST_DEBUG_OBJECT (element, "changed state: %s -> %s = %s",
gst_element_state_get_name (GST_STATE_TRANSITION_CURRENT (transition)),
gst_element_state_get_name (GST_STATE_TRANSITION_NEXT (transition)),
gst_element_state_change_return_get_name (ret));
return ret;
}
gboolean
gst_camerabin_image_send_event (GstElement * element, GstEvent * event)
{
GstCameraBinImage *bin = GST_CAMERABIN_IMAGE (element);
gboolean ret = FALSE;
GST_INFO ("got %s event", GST_EVENT_TYPE_NAME (event));
if (GST_EVENT_IS_DOWNSTREAM (event)) {
ret = gst_pad_send_event (bin->sinkpad, event);
} else {
if (bin->sink) {
ret = gst_element_send_event (bin->sink, event);
} else {
GST_WARNING ("upstream event handling failed");
}
}
return ret;
}
static void
gst_camerabin_image_set_property (GObject * object, guint prop_id,
const GValue * value, GParamSpec * pspec)
{
GstCameraBinImage *bin = GST_CAMERABIN_IMAGE (object);
switch (prop_id) {
case PROP_FILENAME:
g_string_assign (bin->filename, g_value_get_string (value));
GST_INFO_OBJECT (bin, "received filename: '%s'", bin->filename->str);
if (bin->sink) {
if (!g_str_equal (bin->filename->str, "")) {
g_object_set (G_OBJECT (bin->sink), "location", bin->filename->str,
NULL);
gst_element_set_locked_state (bin->sink, FALSE);
gst_element_sync_state_with_parent (bin->sink);
} else {
GST_INFO_OBJECT (bin, "empty filename");
}
} else {
GST_INFO_OBJECT (bin, "no sink, not setting name yet");
}
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
gst_camerabin_image_get_property (GObject * object, guint prop_id,
GValue * value, GParamSpec * pspec)
{
GstCameraBinImage *bin = GST_CAMERABIN_IMAGE (object);
switch (prop_id) {
case PROP_FILENAME:
g_value_set_string (value, bin->filename->str);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
/*
* gst_camerabin_image_prepare_elements:
* @imagebin: a pointer to #GstCameraBinImage object
*
* This function creates an ordered list of elements configured for imagebin
* pipeline and creates the elements if necessary. It also stores pointers
* to created elements for re-using them.
*
* Image bin:
* img->sinkpad ! [ post process !] [ csp !] encoder ! metadata ! filesink
*
* Returns: %FALSE if there was error creating element, %TRUE otherwise
*/
gboolean
gst_camerabin_image_prepare_elements (GstCameraBinImage * imagebin)
{
gboolean ret = FALSE;
GstPad *sinkpad = NULL;
g_return_val_if_fail (imagebin != NULL, FALSE);
GST_DEBUG_OBJECT (imagebin, "preparing image capture elements");
if (imagebin->elements != NULL) {
g_list_free (imagebin->elements);
imagebin->elements = NULL;
}
/* Create file sink element */
if (!prepare_element (&imagebin->elements, DEFAULT_SINK, NULL,
&imagebin->sink)) {
goto done;
} else {
g_object_set (G_OBJECT (imagebin->sink), "location",
imagebin->filename->str, "async", FALSE, "buffer-mode", 2,
/* non buffered io */ NULL);
}
/* Create metadata muxer element */
if (!prepare_element (&imagebin->elements, DEFAULT_FORMATTER,
imagebin->app_formatter, &imagebin->formatter)) {
goto done;
} else if (!imagebin->metadata_probe_id) {
/* Add probe for default XMP metadata writing */
sinkpad = gst_element_get_static_pad (imagebin->formatter, "sink");
imagebin->metadata_probe_id =
gst_pad_add_buffer_probe (sinkpad, G_CALLBACK (metadata_write_probe),
imagebin);
gst_object_unref (sinkpad);
}
/* Create image encoder element */
if (!prepare_element (&imagebin->elements, DEFAULT_ENC, imagebin->app_enc,
&imagebin->enc)) {
goto done;
}
/* Create optional colorspace conversion element */
if (imagebin->flags & GST_CAMERABIN_FLAG_IMAGE_COLOR_CONVERSION) {
if (!prepare_element (&imagebin->elements, "ffmpegcolorspace", NULL,
&imagebin->csp)) {
goto done;
}
}
/* Add optional image post processing element */
if (!prepare_element (&imagebin->elements, NULL, imagebin->post,
&imagebin->post)) {
goto done;
}
ret = TRUE;
done:
GST_DEBUG_OBJECT (imagebin, "preparing finished %s", ret ? "OK" : "NOK");
return ret;
}
/*
* static helper functions implementation
*/
/*
* metadata_write_probe:
* @pad: sink pad of metadata muxer
* @buffer: received buffer
* @u_data: image bin object
*
* Buffer probe that sets Xmp.dc.type and Xmp.dc.format tags
* to metadata muxer based on preceding element src pad caps.
*
* Returns: TRUE always
*/
static gboolean
metadata_write_probe (GstPad * pad, GstBuffer * buffer, gpointer u_data)
{
/* Add XMP tags */
GstCameraBinImage *img = NULL;
GstTagSetter *setter = NULL;
GstPad *srcpad = NULL;
GstCaps *caps = NULL;
GstStructure *st = NULL;
img = GST_CAMERABIN_IMAGE (u_data);
g_return_val_if_fail (img != NULL, TRUE);
if (GST_IS_TAG_SETTER (img->formatter)) {
setter = GST_TAG_SETTER (img->formatter);
}
if (!setter) {
GST_WARNING_OBJECT (img, "setting tags failed");
goto done;
}
/* Xmp.dc.type tag */
gst_tag_setter_add_tags (setter, GST_TAG_MERGE_REPLACE,
GST_TAG_CODEC, "Image", NULL);
/* Xmp.dc.format tag */
if (img->enc) {
srcpad = gst_element_get_static_pad (img->enc, "src");
}
GST_LOG_OBJECT (img, "srcpad:%" GST_PTR_FORMAT, srcpad);
if (srcpad) {
caps = gst_pad_get_negotiated_caps (srcpad);
GST_LOG_OBJECT (img, "caps:%" GST_PTR_FORMAT, caps);
if (caps) {
/* If there are many structures, we can't know which one to use */
if (gst_caps_get_size (caps) != 1) {
GST_WARNING_OBJECT (img, "can't decide structure for format tag");
goto done;
}
st = gst_caps_get_structure (caps, 0);
if (st) {
GST_DEBUG_OBJECT (img, "Xmp.dc.format:%s", gst_structure_get_name (st));
gst_tag_setter_add_tags (setter, GST_TAG_MERGE_REPLACE,
GST_TAG_VIDEO_CODEC, gst_structure_get_name (st), NULL);
}
}
}
done:
if (caps)
gst_caps_unref (caps);
if (srcpad)
gst_object_unref (srcpad);
return TRUE;
}
/*
* prepare_element:
* @result: result list address
* @default_element_name: name of default element to be created
* @app_elem: pointer to application set element
* @res_elem: pointer to current element to be replaced if needed
*
* This function chooses given image capture element or creates a new one and
* and prepends it to @result list.
*
* Returns: %FALSE if there was error creating new element, %TRUE otherwise
*/
static gboolean
prepare_element (GList ** result, const gchar * default_element_name,
GstElement * app_elem, GstElement ** res_elem)
{
GstElement *elem = NULL;
gboolean ret = TRUE;
if (app_elem) {
/* Prefer application set element */
elem = app_elem;
} else if (*res_elem) {
/* Use existing element if any */
elem = *res_elem;
} else if (default_element_name) {
/* Create new element */
if (!(elem = gst_element_factory_make (default_element_name, NULL))) {
GST_WARNING ("creating %s failed", default_element_name);
ret = FALSE;
}
}
if (*res_elem != elem) {
/* Keep reference and store pointer to chosen element, which can be re-used
until imagebin is disposed or new image capture element is chosen. */
gst_object_replace ((GstObject **) res_elem, (GstObject *) elem);
}
if (elem) {
*result = g_list_prepend (*result, elem);
}
return ret;
}
/*
* gst_camerabin_image_link_first_element:
* @img: a pointer to #GstCameraBinImage object
* @elem: first element to be linked on imagebin
*
* Adds given element to imagebin and links it to imagebin's ghost sink pad.
*
* Returns: %TRUE if adding and linking succeeded, %FALSE otherwise
*/
static gboolean
gst_camerabin_image_link_first_element (GstCameraBinImage * imagebin,
GstElement * elem)
{
GstPad *first_sinkpad = NULL;
gboolean ret = FALSE;
g_return_val_if_fail (imagebin != NULL, FALSE);
/* Link given element to imagebin ghost sink pad */
if (gst_bin_add (GST_BIN (imagebin), elem)) {
first_sinkpad = gst_element_get_static_pad (elem, "sink");
if (first_sinkpad) {
if (gst_ghost_pad_set_target (GST_GHOST_PAD (imagebin->sinkpad),
first_sinkpad)) {
ret = TRUE;
} else {
GST_WARNING ("linking first element failed");
}
gst_object_unref (first_sinkpad);
} else {
GST_WARNING ("no sink pad in first element");
}
} else {
GST_WARNING ("adding element failed");
}
return ret;
}
/*
* gst_camerabin_image_link_elements:
* @imagebin: a pointer to #GstCameraBinImage object
*
* Link elements configured to imagebin elements list.
*
* Returns %TRUE if linking succeeded, %FALSE otherwise.
*/
static gboolean
gst_camerabin_image_link_elements (GstCameraBinImage * imagebin)
{
GList *prev = NULL;
GList *next = NULL;
gboolean ret = FALSE;
GST_DEBUG_OBJECT (imagebin, "linking image elements");
if (!imagebin->elements) {
GST_WARNING ("no elements to link");
goto done;
}
/* Link the elements in list */
prev = imagebin->elements;
next = g_list_next (imagebin->elements);
for (; next != NULL; next = g_list_next (next)) {
/* Link first element in list to imagebin ghost sink pad */
if (prev == imagebin->elements
&& !gst_camerabin_image_link_first_element (imagebin,
GST_ELEMENT (prev->data))) {
goto done;
}
if (!gst_bin_add (GST_BIN (imagebin), GST_ELEMENT (next->data))) {
GST_WARNING_OBJECT (imagebin, "adding element failed");
goto done;
}
GST_LOG_OBJECT (imagebin, "linking %s - %s",
GST_ELEMENT_NAME (GST_ELEMENT (prev->data)),
GST_ELEMENT_NAME (GST_ELEMENT (next->data)));
if (!gst_element_link (GST_ELEMENT (prev->data), GST_ELEMENT (next->data))) {
GST_WARNING_OBJECT (imagebin, "linking element failed");
goto done;
}
prev = next;
}
ret = TRUE;
done:
if (!ret) {
gst_camerabin_remove_elements_from_bin (GST_BIN (imagebin));
}
GST_DEBUG_OBJECT (imagebin, "linking finished %s", ret ? "OK" : "NOK");
return ret;
}
/*
* gst_camerabin_image_create_elements:
* @img: a pointer to #GstCameraBinImage object
*
* This function creates needed elements, adds them to
* imagebin and links them.
*
* Returns %TRUE if success, %FALSE otherwise.
*/
static gboolean
gst_camerabin_image_create_elements (GstCameraBinImage * img)
{
gboolean ret = FALSE;
g_return_val_if_fail (img != NULL, FALSE);
if (gst_camerabin_image_prepare_elements (img)) {
ret = gst_camerabin_image_link_elements (img);
}
return ret;
}
/*
* gst_camerabin_image_destroy_elements:
* @img: a pointer to #GstCameraBinImage object
*
* This function releases resources allocated in
* gst_camerabin_image_create_elements.
*
*/
static void
gst_camerabin_image_destroy_elements (GstCameraBinImage * img)
{
GST_LOG ("destroying image elements");
gst_ghost_pad_set_target (GST_GHOST_PAD (img->sinkpad), NULL);
gst_camerabin_remove_elements_from_bin (GST_BIN (img));
}
void
gst_camerabin_image_set_encoder (GstCameraBinImage * img, GstElement * encoder)
{
GST_DEBUG ("setting image encoder %" GST_PTR_FORMAT, encoder);
if (img->app_enc)
gst_object_unref (img->app_enc);
if (encoder)
gst_object_ref (encoder);
img->app_enc = encoder;
}
void
gst_camerabin_image_set_postproc (GstCameraBinImage * img,
GstElement * postproc)
{
GST_DEBUG ("setting image postprocessing element %" GST_PTR_FORMAT, postproc);
if (img->post)
gst_object_unref (img->post);
if (postproc)
gst_object_ref (postproc);
img->post = postproc;
}
void
gst_camerabin_image_set_formatter (GstCameraBinImage * img,
GstElement * formatter)
{
GstElement **app_formatter;
GST_DEBUG ("setting image formatter %" GST_PTR_FORMAT, formatter);
app_formatter = &img->app_formatter;
GST_OBJECT_LOCK (img);
gst_object_replace ((GstObject **) app_formatter, GST_OBJECT (formatter));
GST_OBJECT_UNLOCK (img);
}
void
gst_camerabin_image_set_flags (GstCameraBinImage * img, GstCameraBinFlags flags)
{
GST_DEBUG_OBJECT (img, "setting image flags: %d", flags);
img->flags = flags;
}
GstElement *
gst_camerabin_image_get_encoder (GstCameraBinImage * img)
{
GstElement *enc;
if (img->app_enc) {
enc = img->app_enc;
} else {
enc = img->enc;
}
return enc;
}
GstElement *
gst_camerabin_image_get_formatter (GstCameraBinImage * img)
{
/* Prefer formatter that is currently in use */
return img->formatter ? img->formatter : img->app_formatter;
}
GstElement *
gst_camerabin_image_get_postproc (GstCameraBinImage * img)
{
return img->post;
}

View file

@ -1,96 +0,0 @@
/*
* GStreamer
* Copyright (C) 2008 Nokia Corporation <multimedia@maemo.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 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
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#ifndef __CAMERABIN_IMAGE_H__
#define __CAMERABIN_IMAGE_H__
#include <gst/gstbin.h>
#include "gstcamerabin-enum.h"
G_BEGIN_DECLS
#define GST_TYPE_CAMERABIN_IMAGE (gst_camerabin_image_get_type())
#define GST_CAMERABIN_IMAGE_CAST(obj) ((GstCameraBinImage*)(obj))
#define GST_CAMERABIN_IMAGE(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_CAMERABIN_IMAGE,GstCameraBinImage))
#define GST_CAMERABIN_IMAGE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_CAMERABIN_IMAGE,GstCameraBinImageClass))
#define GST_IS_CAMERABIN_IMAGE(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_CAMERABIN_IMAGE))
#define GST_IS_CAMERABIN_IMAGE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_CAMERABIN_IMAGE))
/**
* GstCameraBinImage:
*
* The opaque #GstCameraBinImage structure.
*/
typedef struct _GstCameraBinImage GstCameraBinImage;
typedef struct _GstCameraBinImageClass GstCameraBinImageClass;
struct _GstCameraBinImage
{
GstBin parent;
GString *filename;
/* Ghost pads of image bin */
GstPad *sinkpad;
/* Ordered list of elements configured to imagebin */
GList *elements;
/* Imagebin elements */
GstElement *post;
GstElement *csp;
GstElement *enc;
GstElement *app_enc;
GstElement *formatter;
GstElement *app_formatter;
GstElement *sink;
GstCameraBinFlags flags;
gulong metadata_probe_id;
};
struct _GstCameraBinImageClass
{
GstBinClass parent_class;
};
GType gst_camerabin_image_get_type (void);
void
gst_camerabin_image_set_encoder (GstCameraBinImage * img, GstElement * encoder);
void
gst_camerabin_image_set_postproc (GstCameraBinImage * img,
GstElement * postproc);
void
gst_camerabin_image_set_formatter (GstCameraBinImage * img, GstElement * formatter);
void
gst_camerabin_image_set_flags (GstCameraBinImage * img,
GstCameraBinFlags flags);
GstElement *gst_camerabin_image_get_encoder (GstCameraBinImage * img);
GstElement *gst_camerabin_image_get_postproc (GstCameraBinImage * img);
GstElement *gst_camerabin_image_get_formatter (GstCameraBinImage * img);
gboolean gst_camerabin_image_prepare_elements (GstCameraBinImage * imagebin);
G_END_DECLS
#endif /* #ifndef __CAMERABIN_IMAGE_H__ */

View file

@ -1,364 +0,0 @@
/*
* GStreamer
* Copyright (C) 2009 Nokia Corporation <multimedia@maemo.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 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
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <gst/gst.h>
#include <string.h>
#include "camerabindebug.h"
#include "camerabingeneral.h"
#include "camerabinpreview.h"
static void
save_result (GstElement * sink, GstBuffer * buf, GstPad * pad, gpointer data)
{
GstBuffer **p_buf = (GstBuffer **) data;
*p_buf = gst_buffer_ref (buf);
GST_DEBUG ("received converted buffer %p with caps %" GST_PTR_FORMAT,
*p_buf, GST_BUFFER_CAPS (*p_buf));
}
static gboolean
create_element (const gchar * factory_name, const gchar * elem_name,
GstElement ** element, GError ** err)
{
*element = gst_element_factory_make (factory_name, elem_name);
if (*element)
return TRUE;
if (err && *err == NULL) {
*err = g_error_new (GST_CORE_ERROR, GST_CORE_ERROR_MISSING_PLUGIN,
"cannot create element '%s' - please check your GStreamer installation",
factory_name);
}
return FALSE;
}
/**
* gst_camerabin_preview_create_pipeline:
* @element: #GstCameraBin element
* @caps: pointer to the caps used in pipeline
* @src_filter: source filter element
*
* Create a preview converter pipeline that outputs the format defined in
* @caps parameter.
*
* Returns: New pipeline data structure, or NULL if error occured.
*/
GstCameraBinPreviewPipelineData *
gst_camerabin_preview_create_pipeline (GstElement * element, GstCaps * caps,
GstElement * src_filter)
{
GstElement *csp = NULL, *vscale = NULL;
GError *error = NULL;
GstCameraBinPreviewPipelineData *data;
g_return_val_if_fail (caps != NULL, NULL);
GST_DEBUG ("creating elements");
data = g_new (GstCameraBinPreviewPipelineData, 1);
/* We have multiple pipelines created by using this function, so we can't
* give a name to them. Another way would to ensure the uniqueness of the
* name here*/
data->pipeline = gst_pipeline_new (NULL);
if (!data->pipeline)
goto create_error;
if (!create_element ("appsrc", "prev_src", &data->appsrc, &error) ||
!create_element ("videoscale", NULL, &vscale, &error) ||
!create_element ("ffmpegcolorspace", NULL, &csp, &error) ||
!create_element ("capsfilter", NULL, &data->capsfilter, &error) ||
!create_element ("fakesink", "prev_sink", &data->appsink, &error))
goto create_error;
GST_DEBUG ("adding elements");
gst_bin_add_many (GST_BIN (data->pipeline), data->appsrc, csp,
data->capsfilter, vscale, data->appsink, NULL);
if (src_filter) {
gst_bin_add (GST_BIN (data->pipeline), src_filter);
}
data->element = element;
GST_DEBUG ("preview format is: %" GST_PTR_FORMAT, caps);
g_object_set (data->capsfilter, "caps", caps, NULL);
g_object_set (data->appsink, "preroll-queue-len", 1, "signal-handoffs", TRUE,
NULL);
g_object_set (vscale, "method", 0, NULL);
GST_DEBUG ("linking src->vscale");
if (!gst_element_link_pads (data->appsrc, "src", vscale, "sink"))
goto link_error;
if (src_filter) {
GST_DEBUG ("linking vscale->src_filter");
if (!gst_element_link_pads (vscale, "src", src_filter, "sink")) {
goto link_error;
}
GST_DEBUG ("linking filter->csp");
if (!gst_element_link_pads (src_filter, "src", csp, "sink")) {
goto link_error;
}
} else {
GST_DEBUG ("linking vscale->csp");
if (!gst_element_link_pads (vscale, "src", csp, "sink"))
goto link_error;
}
GST_DEBUG ("linking csp->capsfilter");
if (!gst_element_link_pads (csp, "src", data->capsfilter, "sink"))
goto link_error;
GST_DEBUG ("linking capsfilter->sink");
if (!gst_element_link_pads (data->capsfilter, "src", data->appsink, "sink"))
goto link_error;
return data;
create_error:
if (error) {
GST_WARNING ("Preview pipeline element creation failed: %s",
error->message);
g_error_free (error);
}
if (csp)
gst_object_unref (csp);
if (vscale)
gst_object_unref (vscale);
if (data->appsrc)
gst_object_unref (data->appsrc);
if (data->capsfilter)
gst_object_unref (data->capsfilter);
if (data->appsink)
gst_object_unref (data->appsink);
link_error:
GST_WARNING ("Could not create preview pipeline");
gst_camerabin_preview_destroy_pipeline (data);
return NULL;
}
/**
* gst_camerabin_preview_destroy_pipeline:
* @data: the pipeline data to be destroyed
*
* Destroy preview converter pipeline.
*/
void
gst_camerabin_preview_destroy_pipeline (GstCameraBinPreviewPipelineData * data)
{
if (data->pipeline) {
gst_element_set_state (data->pipeline, GST_STATE_NULL);
gst_object_unref (data->pipeline);
}
g_free (data);
}
/**
* gst_camerabin_preview_convert:
* @data: preview pipeline data to use
* @buf: #GstBuffer that contains the frame to be converted
*
* Create a preview image of the given frame.
*
* Returns: converted preview image, or NULL if operation failed.
*/
GstBuffer *
gst_camerabin_preview_convert (GstCameraBinPreviewPipelineData * data,
GstBuffer * buf)
{
GstMessage *msg;
GstBuffer *result = NULL;
GError *error = NULL;
GstBus *bus;
GstElement *src, *sink;
GstBufferFlag bflags;
GstFlowReturn fret;
g_return_val_if_fail (GST_BUFFER_CAPS (buf) != NULL, NULL);
g_return_val_if_fail (data != NULL, NULL);
if (data->pipeline == NULL) {
GST_WARNING ("pipeline is NULL");
goto no_pipeline;
}
src = gst_bin_get_by_name (GST_BIN (data->pipeline), "prev_src");
sink = gst_bin_get_by_name (GST_BIN (data->pipeline), "prev_sink");
if (!src || !sink) {
GST_WARNING ("pipeline doesn't have src / sink elements");
goto missing_elements;
}
g_object_set (src, "size", (gint64) GST_BUFFER_SIZE (buf),
"blocksize", (guint32) GST_BUFFER_SIZE (buf),
"caps", GST_BUFFER_CAPS (buf), "num-buffers", 1, NULL);
g_signal_connect (sink, "handoff", G_CALLBACK (save_result), &result);
bflags = GST_BUFFER_FLAGS (buf);
GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_READONLY);
GST_DEBUG ("running conversion pipeline, source is: %" GST_PTR_FORMAT,
GST_BUFFER_CAPS (buf));
gst_element_set_state (data->pipeline, GST_STATE_PLAYING);
g_signal_emit_by_name (src, "push-buffer", buf, &fret);
bus = gst_element_get_bus (data->pipeline);
msg = gst_bus_timed_pop_filtered (bus, (25 * GST_SECOND),
GST_MESSAGE_ERROR | GST_MESSAGE_EOS);
gst_object_unref (bus);
if (msg) {
switch (GST_MESSAGE_TYPE (msg)) {
case GST_MESSAGE_EOS:{
if (result) {
GST_DEBUG ("preview image successful: result = %p", result);
} else {
GST_WARNING ("EOS but no result frame?!");
}
break;
}
case GST_MESSAGE_ERROR:{
gchar *dbg = NULL;
gst_message_parse_error (msg, &error, &dbg);
if (error) {
g_warning ("Could not make preview image: %s", error->message);
GST_DEBUG ("%s [debug: %s]", error->message, GST_STR_NULL (dbg));
g_error_free (error);
} else {
g_warning ("Could not make preview image (and NULL error!)");
}
g_free (dbg);
result = NULL;
break;
}
default:{
g_return_val_if_reached (NULL);
}
}
gst_message_unref (msg);
} else {
g_warning ("Could not make preview image: %s", "timeout during conversion");
result = NULL;
}
g_signal_handlers_disconnect_by_func (sink, G_CALLBACK (save_result),
&result);
gst_element_set_state (data->pipeline, GST_STATE_READY);
GST_BUFFER_FLAGS (buf) = bflags;
done:
if (src)
gst_object_unref (src);
if (sink)
gst_object_unref (sink);
return result;
/* ERRORS */
missing_elements:
{
g_warning ("Could not make preview image: %s",
"missing elements in pipeline (unknown error)");
goto done;
}
no_pipeline:
{
g_warning ("Could not make preview image: %s",
"no pipeline (unknown error)");
return NULL;
}
}
/**
* gst_camerabin_preview_send_event:
* @data: preview pipeline data to use
* @evt: The #GstEvent to be pushed, takes ownership
*
* Pushes an event to the preview pipeline.
*
* Returns: True if the event was handled
*/
gboolean
gst_camerabin_preview_send_event (GstCameraBinPreviewPipelineData * data,
GstEvent * evt)
{
GstElement *src;
src = gst_bin_get_by_name (GST_BIN (data->pipeline), "prev_src");
if (!src) {
GST_WARNING ("Preview pipeline doesn't have src element, can't push event");
gst_event_unref (evt);
return FALSE;
}
GST_DEBUG_OBJECT (data->element, "Pushing event %p to preview pipeline", evt);
return gst_element_send_event (src, evt);
}
/**
* gst_camerabin_preview_set_caps:
* @data: preview pipeline data to use
* @caps: New #GstCaps to be set for the pipeline
*
* Sets new caps for the preview pipeline
*/
void
gst_camerabin_preview_set_caps (GstCameraBinPreviewPipelineData * data,
GstCaps * caps)
{
GstState state, pending;
GstStateChangeReturn ret;
g_return_if_fail (data->pipeline != NULL);
g_return_if_fail (caps != NULL);
ret = gst_element_get_state (data->pipeline, &state, &pending, 0);
if (ret == GST_STATE_CHANGE_FAILURE) {
/* make it try again */
state = GST_STATE_PLAYING;
pending = GST_STATE_VOID_PENDING;
}
gst_element_set_state (data->pipeline, GST_STATE_NULL);
g_object_set (data->capsfilter, "caps", caps, NULL);
if (pending != GST_STATE_VOID_PENDING)
state = pending;
gst_element_set_state (data->pipeline, state);
}

View file

@ -1,57 +0,0 @@
/*
* GStreamer
* Copyright (C) 2009 Nokia Corporation <multimedia@maemo.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 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
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#ifndef __CAMERABINPREVIEW_H__
#define __CAMERABINPREVIEW_H__
#include <gst/gst.h>
G_BEGIN_DECLS
typedef struct
{
GstElement *pipeline;
GstElement *appsrc;
GstElement *capsfilter;
GstElement *appsink;
GstElement *element;
} GstCameraBinPreviewPipelineData;
GstCameraBinPreviewPipelineData * gst_camerabin_preview_create_pipeline (
GstElement *element, GstCaps *caps, GstElement *src_filter);
void gst_camerabin_preview_destroy_pipeline (
GstCameraBinPreviewPipelineData *data);
GstBuffer *gst_camerabin_preview_convert (
GstCameraBinPreviewPipelineData *data, GstBuffer *buf);
gboolean gst_camerabin_preview_send_event (
GstCameraBinPreviewPipelineData *pipeline, GstEvent *event);
void gst_camerabin_preview_set_caps (
GstCameraBinPreviewPipelineData *pipeline, GstCaps *caps);
G_END_DECLS
#endif /* __CAMERABINPREVIEW_H__ */

View file

@ -1,846 +0,0 @@
/*
* GStreamer
* Copyright (C) 2008 Nokia Corporation <multimedia@maemo.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 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
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
/**
* SECTION:camerabinvideo
* @short_description: video recording module of #GstCameraBin
*
* <refsect2>
* <para>
*
* The pipeline for this module is:
*
* <informalexample>
* <programlisting>
*-----------------------------------------------------------------------------
* audiosrc -> audio_queue -> audioconvert -> volume -> audioenc
* > videomux -> filesink
* video_queue -> [timeoverlay] -> [csp] -> videoenc -> queue
* -> [post proc] -> tee <
* queue ->
*-----------------------------------------------------------------------------
* </programlisting>
* </informalexample>
*
* The properties of elements are:
*
* queue - "leaky", 2 (Leaky on downstream (old buffers))
*
* </para>
* </refsect2>
*/
/*
* includes
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <gst/gst.h>
#include "camerabindebug.h"
#include "camerabingeneral.h"
#include "camerabinvideo.h"
/*
* defines and static global vars
*/
/* internal element names */
#define DEFAULT_AUD_ENC "vorbisenc"
#define DEFAULT_VID_ENC "theoraenc"
#define DEFAULT_MUX "oggmux"
#define DEFAULT_SINK "filesink"
#define DEFAULT_FLAGS 0
enum
{
PROP_0,
PROP_FILENAME
};
static void gst_camerabin_video_dispose (GstCameraBinVideo * sink);
static void gst_camerabin_video_set_property (GObject * object, guint prop_id,
const GValue * value, GParamSpec * pspec);
static void gst_camerabin_video_get_property (GObject * object, guint prop_id,
GValue * value, GParamSpec * pspec);
static GstStateChangeReturn
gst_camerabin_video_change_state (GstElement * element,
GstStateChange transition);
static
gboolean camerabin_video_pad_tee_src0_have_buffer (GstPad * pad,
GstBuffer * buffer, gpointer u_data);
static gboolean camerabin_video_sink_have_event (GstPad * pad, GstEvent * event,
gpointer u_data);
static gboolean gst_camerabin_video_create_elements (GstCameraBinVideo * vid);
static void gst_camerabin_video_destroy_elements (GstCameraBinVideo * vid);
GST_BOILERPLATE (GstCameraBinVideo, gst_camerabin_video, GstBin, GST_TYPE_BIN);
static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("sink",
GST_PAD_SINK,
GST_PAD_ALWAYS,
GST_STATIC_CAPS_ANY);
static GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE ("src",
GST_PAD_SRC,
GST_PAD_ALWAYS,
GST_STATIC_CAPS_ANY);
/* GObject methods implementation */
static void
gst_camerabin_video_base_init (gpointer klass)
{
GstElementClass *eklass = GST_ELEMENT_CLASS (klass);
gst_element_class_add_pad_template (eklass,
gst_static_pad_template_get (&sink_template));
gst_element_class_add_pad_template (eklass,
gst_static_pad_template_get (&src_template));
gst_element_class_set_details_simple (eklass,
"Video capture bin for camerabin", "Bin/Video",
"Process and store video data",
"Edgard Lima <edgard.lima@indt.org.br>, "
"Nokia Corporation <multimedia@maemo.org>");
}
static void
gst_camerabin_video_class_init (GstCameraBinVideoClass * klass)
{
GObjectClass *gobject_class;
GstElementClass *eklass = GST_ELEMENT_CLASS (klass);
gobject_class = G_OBJECT_CLASS (klass);
gobject_class->dispose =
(GObjectFinalizeFunc) GST_DEBUG_FUNCPTR (gst_camerabin_video_dispose);
eklass->change_state = GST_DEBUG_FUNCPTR (gst_camerabin_video_change_state);
gobject_class->set_property =
GST_DEBUG_FUNCPTR (gst_camerabin_video_set_property);
gobject_class->get_property =
GST_DEBUG_FUNCPTR (gst_camerabin_video_get_property);
/**
* GstCameraBinVideo:filename:
*
* This property can be used to specify the filename of the video.
*
**/
g_object_class_install_property (gobject_class, PROP_FILENAME,
g_param_spec_string ("filename", "Filename",
"Filename of the video to save", NULL,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
}
static void
gst_camerabin_video_init (GstCameraBinVideo * vid,
GstCameraBinVideoClass * g_class)
{
vid->filename = g_string_new ("");
vid->app_post = NULL;
vid->app_vid_enc = NULL;
vid->app_aud_enc = NULL;
vid->app_aud_src = NULL;
vid->app_mux = NULL;
vid->aud_src = NULL;
vid->sink = NULL;
vid->tee = NULL;
vid->volume = NULL;
vid->video_queue = NULL;
vid->tee_video_srcpad = NULL;
vid->tee_vf_srcpad = NULL;
vid->pending_eos = NULL;
vid->mute = ARG_DEFAULT_MUTE;
vid->flags = DEFAULT_FLAGS;
vid->vid_src_probe_id = 0;
vid->vid_tee_probe_id = 0;
vid->vid_sink_probe_id = 0;
/* Create src and sink ghost pads */
vid->sinkpad = gst_ghost_pad_new_no_target ("sink", GST_PAD_SINK);
gst_element_add_pad (GST_ELEMENT (vid), vid->sinkpad);
vid->srcpad = gst_ghost_pad_new_no_target ("src", GST_PAD_SRC);
gst_element_add_pad (GST_ELEMENT (vid), vid->srcpad);
/* Add probe for handling eos when stopping recording */
vid->vid_sink_probe_id = gst_pad_add_event_probe (vid->sinkpad,
G_CALLBACK (camerabin_video_sink_have_event), vid);
}
static void
gst_camerabin_video_dispose (GstCameraBinVideo * vid)
{
GST_DEBUG_OBJECT (vid, "disposing");
g_string_free (vid->filename, TRUE);
vid->filename = NULL;
if (vid->vid_sink_probe_id) {
gst_pad_remove_event_probe (vid->sinkpad, vid->vid_sink_probe_id);
vid->vid_sink_probe_id = 0;
}
/* Note: if videobin was never set to READY state the
ownership of elements created by application were never
taken by bin and therefore gst_object_sink is called for
these elements (they may still be in floating state
and not unreffed properly without sinking first)
FIXME, something else is wrong when you have to sink here
*/
if (vid->app_post) {
//gst_object_sink (vid->app_post);
gst_object_unref (vid->app_post);
vid->app_post = NULL;
}
if (vid->app_vid_enc) {
//gst_object_sink (vid->app_vid_enc);
gst_object_unref (vid->app_vid_enc);
vid->app_vid_enc = NULL;
}
if (vid->app_aud_enc) {
//gst_object_sink (vid->app_aud_enc);
gst_object_unref (vid->app_aud_enc);
vid->app_aud_enc = NULL;
}
if (vid->app_aud_src) {
//gst_object_sink (vid->app_aud_src);
gst_object_unref (vid->app_aud_src);
vid->app_aud_src = NULL;
}
if (vid->app_mux) {
//gst_object_sink (vid->app_mux);
gst_object_unref (vid->app_mux);
vid->app_mux = NULL;
}
G_OBJECT_CLASS (parent_class)->dispose ((GObject *) vid);
}
static void
gst_camerabin_video_set_property (GObject * object, guint prop_id,
const GValue * value, GParamSpec * pspec)
{
GstCameraBinVideo *bin = GST_CAMERABIN_VIDEO (object);
switch (prop_id) {
case PROP_FILENAME:
g_string_assign (bin->filename, g_value_get_string (value));
GST_INFO_OBJECT (bin, "received filename: '%s'", bin->filename->str);
if (bin->sink) {
g_object_set (G_OBJECT (bin->sink), "location", bin->filename->str,
NULL);
} else {
GST_INFO_OBJECT (bin, "no sink, not setting name yet");
}
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
gst_camerabin_video_get_property (GObject * object, guint prop_id,
GValue * value, GParamSpec * pspec)
{
GstCameraBinVideo *bin = GST_CAMERABIN_VIDEO (object);
switch (prop_id) {
case PROP_FILENAME:
g_value_set_string (value, bin->filename->str);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static GstStateChangeReturn
gst_camerabin_video_change_state (GstElement * element,
GstStateChange transition)
{
GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
GstCameraBinVideo *vid = GST_CAMERABIN_VIDEO (element);
GST_DEBUG_OBJECT (element, "changing state: %s -> %s",
gst_element_state_get_name (GST_STATE_TRANSITION_CURRENT (transition)),
gst_element_state_get_name (GST_STATE_TRANSITION_NEXT (transition)));
switch (transition) {
case GST_STATE_CHANGE_NULL_TO_READY:
if (!gst_camerabin_video_create_elements (vid)) {
return GST_STATE_CHANGE_FAILURE;
}
/* Don't change sink to READY yet to allow changing the
filename in READY state. */
gst_element_set_locked_state (vid->sink, TRUE);
break;
case GST_STATE_CHANGE_READY_TO_PAUSED:
vid->calculate_adjust_ts_video = TRUE;
g_object_set (G_OBJECT (vid->sink), "async", FALSE, NULL);
gst_element_set_locked_state (vid->sink, FALSE);
break;
case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
vid->calculate_adjust_ts_video = TRUE;
break;
case GST_STATE_CHANGE_PAUSED_TO_READY:
/* Set sink to NULL in order to write the file _now_ */
GST_INFO ("write video file: %s", vid->filename->str);
gst_element_set_locked_state (vid->sink, TRUE);
gst_element_set_state (vid->sink, GST_STATE_NULL);
break;
default:
break;
}
ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
switch (transition) {
case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
/* Write debug graph to file */
GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS (GST_BIN (GST_ELEMENT_PARENT (vid)),
GST_DEBUG_GRAPH_SHOW_MEDIA_TYPE |
GST_DEBUG_GRAPH_SHOW_NON_DEFAULT_PARAMS, "videobin.playing");
if (vid->pending_eos) {
/* Video bin is still paused, so push eos directly to video queue */
GST_DEBUG_OBJECT (vid, "pushing pending eos");
gst_pad_push_event (vid->tee_video_srcpad, vid->pending_eos);
vid->pending_eos = NULL;
}
break;
case GST_STATE_CHANGE_PAUSED_TO_READY:
/* Reset counters related to timestamp rewriting */
vid->adjust_ts_video = 0;
vid->last_ts_video = 0;
if (vid->pending_eos) {
gst_event_unref (vid->pending_eos);
vid->pending_eos = NULL;
}
break;
case GST_STATE_CHANGE_READY_TO_NULL:
gst_camerabin_video_destroy_elements (vid);
break;
default:
break;
}
GST_DEBUG_OBJECT (element, "changed state: %s -> %s = %s",
gst_element_state_get_name (GST_STATE_TRANSITION_CURRENT (transition)),
gst_element_state_get_name (GST_STATE_TRANSITION_NEXT (transition)),
gst_element_state_change_return_get_name (ret));
return ret;
}
/*
* static helper functions implementation
*/
/*
* camerabin_video_pad_tee_src0_have_buffer:
* @pad: tee src pad leading to video encoding
* @event: received buffer
* @u_data: video bin object
*
* Buffer probe for rewriting video buffer timestamps.
*
* Returns: TRUE always
*/
static gboolean
camerabin_video_pad_tee_src0_have_buffer (GstPad * pad, GstBuffer * buffer,
gpointer u_data)
{
GstCameraBinVideo *vid = (GstCameraBinVideo *) u_data;
GST_LOG ("buffer in with size %d ts %" GST_TIME_FORMAT,
GST_BUFFER_SIZE (buffer), GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer)));
if (G_UNLIKELY (vid->calculate_adjust_ts_video)) {
GstEvent *event;
GstObject *tee;
GstPad *sinkpad;
vid->adjust_ts_video = GST_BUFFER_TIMESTAMP (buffer) - vid->last_ts_video;
vid->calculate_adjust_ts_video = FALSE;
event = gst_event_new_new_segment (FALSE, 1.0, GST_FORMAT_TIME,
0, GST_CLOCK_TIME_NONE, vid->last_ts_video);
/* Send the newsegment to both view finder and video bin */
tee = gst_pad_get_parent (pad);
sinkpad = gst_element_get_static_pad (GST_ELEMENT (tee), "sink");
gst_pad_send_event (sinkpad, event);
gst_object_unref (tee);
gst_object_unref (sinkpad);
GST_LOG_OBJECT (vid, "vid ts adjustment: %" GST_TIME_FORMAT,
GST_TIME_ARGS (vid->adjust_ts_video));
GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DISCONT);
}
GST_BUFFER_TIMESTAMP (buffer) -= vid->adjust_ts_video;
vid->last_ts_video = GST_BUFFER_TIMESTAMP (buffer);
if (GST_BUFFER_DURATION_IS_VALID (buffer))
vid->last_ts_video += GST_BUFFER_DURATION (buffer);
GST_LOG ("buffer out with size %d ts %" GST_TIME_FORMAT,
GST_BUFFER_SIZE (buffer), GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer)));
return TRUE;
}
/*
* camerabin_video_sink_have_event:
* @pad: video bin sink pad
* @event: received event
* @u_data: video bin object
*
* Event probe for video bin eos handling.
* Copies the eos event to audio branch of video bin.
*
* Returns: FALSE to drop the event, TRUE otherwise
*/
static gboolean
camerabin_video_sink_have_event (GstPad * pad, GstEvent * event,
gpointer u_data)
{
GstCameraBinVideo *vid = (GstCameraBinVideo *) u_data;
gboolean ret = TRUE;
GST_DEBUG_OBJECT (vid, "got videobin sink event: %s",
GST_EVENT_TYPE_NAME (event));
switch (GST_EVENT_TYPE (event)) {
case GST_EVENT_EOS:
if (vid->aud_src) {
GST_DEBUG_OBJECT (vid, "copying %s to audio branch",
GST_EVENT_TYPE_NAME (event));
gst_element_send_event (vid->aud_src, gst_event_copy (event));
}
/* If we're paused, we can't pass eos to video now to avoid blocking.
Instead send eos when changing to playing next time. */
if (GST_STATE (GST_ELEMENT (vid)) == GST_STATE_PAUSED) {
GST_DEBUG_OBJECT (vid, "paused, delay eos sending");
vid->pending_eos = gst_event_ref (event);
ret = FALSE; /* Drop the event */
}
break;
default:
break;
}
return ret;
}
/*
* gst_camerabin_video_create_elements:
* @vid: a pointer to #GstCameraBinVideo
*
* This function creates the needed #GstElements and resources to record videos.
* Use gst_camerabin_video_destroy_elements() to free these resources.
*
* Returns: %TRUE if succeeded or FALSE if failed
*/
static gboolean
gst_camerabin_video_create_elements (GstCameraBinVideo * vid)
{
GstPad *vid_sinkpad = NULL, *vid_srcpad = NULL;
GstBin *vidbin = GST_BIN (vid);
GstElement *queue = NULL;
vid->adjust_ts_video = 0;
vid->last_ts_video = 0;
vid->calculate_adjust_ts_video = FALSE;
/* Add video post processing element if any */
if (vid->app_post) {
if (!gst_camerabin_add_element (vidbin, vid->app_post)) {
goto error;
}
vid_sinkpad = gst_element_get_static_pad (vid->app_post, "sink");
}
/* Add tee element */
if (!(vid->tee =
gst_camerabin_create_and_add_element (vidbin, "tee", "video-tee"))) {
goto error;
}
/* Set up sink ghost pad for video bin */
if (!vid_sinkpad) {
vid_sinkpad = gst_element_get_static_pad (vid->tee, "sink");
}
gst_ghost_pad_set_target (GST_GHOST_PAD (vid->sinkpad), vid_sinkpad);
gst_object_unref (vid_sinkpad);
/* Add queue element for video */
vid->tee_video_srcpad = gst_element_get_request_pad (vid->tee, "src_%u");
vid->video_queue = gst_element_factory_make ("queue", "video-queue");
if (!gst_camerabin_add_element (vidbin, vid->video_queue)) {
goto error;
}
g_object_set (vid->video_queue, "silent", TRUE, NULL);
/* Add probe for rewriting video timestamps */
vid->vid_tee_probe_id = gst_pad_add_buffer_probe (vid->tee_video_srcpad,
G_CALLBACK (camerabin_video_pad_tee_src0_have_buffer), vid);
if (vid->flags & GST_CAMERABIN_FLAG_VIDEO_COLOR_CONVERSION) {
/* Add colorspace converter */
if (gst_camerabin_create_and_add_element (vidbin,
"ffmpegcolorspace", "video-ffmpegcolorspace") == NULL) {
goto error;
}
}
/* Add user set or default video encoder element */
if (vid->app_vid_enc) {
vid->vid_enc = vid->app_vid_enc;
if (!gst_camerabin_add_element (vidbin, vid->vid_enc)) {
goto error;
}
} else if (!(vid->vid_enc =
gst_camerabin_create_and_add_element (vidbin, DEFAULT_VID_ENC,
"video-encoder"))) {
goto error;
}
/* Add application set or default muxer element */
if (vid->app_mux) {
vid->muxer = vid->app_mux;
if (!gst_camerabin_add_element (vidbin, vid->muxer)) {
goto error;
}
} else if (!(vid->muxer =
gst_camerabin_create_and_add_element (vidbin, DEFAULT_MUX,
"video-muxer"))) {
goto error;
}
/* Add sink element for storing the video */
if (!(vid->sink =
gst_camerabin_create_and_add_element (vidbin, DEFAULT_SINK,
"video-sink"))) {
goto error;
}
g_object_set (G_OBJECT (vid->sink), "location", vid->filename->str, "buffer-mode", 2, /* non buffered io */
NULL);
if (!(vid->flags & GST_CAMERABIN_FLAG_DISABLE_AUDIO)) {
/* Add application set or default audio source element */
if (!(vid->aud_src = gst_camerabin_setup_default_element (vidbin,
vid->app_aud_src, "autoaudiosrc", DEFAULT_AUDIOSRC))) {
vid->aud_src = NULL;
goto error;
} else {
if (!gst_camerabin_add_element (vidbin, vid->aud_src))
goto error;
}
/* Add queue element for audio */
queue = gst_element_factory_make ("queue", "audio-queue");
if (!gst_camerabin_add_element (vidbin, queue)) {
goto error;
}
g_object_set (queue, "silent", TRUE, NULL);
/* Add optional audio conversion and volume elements and
raise no errors if adding them fails */
if (vid->flags & GST_CAMERABIN_FLAG_AUDIO_CONVERSION) {
if (!gst_camerabin_try_add_element (vidbin,
gst_element_factory_make ("audioconvert", NULL))) {
GST_WARNING_OBJECT (vid, "unable to add audio conversion element");
/* gst_camerabin_try_add_element() destroyed the element */
}
}
vid->volume = gst_element_factory_make ("volume", NULL);
if (!gst_camerabin_try_add_element (vidbin, vid->volume)) {
GST_WARNING_OBJECT (vid, "unable to add volume element");
/* gst_camerabin_try_add_element() destroyed the element */
vid->volume = NULL;
} else {
g_object_set (vid->volume, "mute", vid->mute, NULL);
}
/* Add application set or default audio encoder element */
if (vid->app_aud_enc) {
vid->aud_enc = vid->app_aud_enc;
if (!gst_camerabin_add_element (vidbin, vid->aud_enc)) {
goto error;
}
} else if (!(vid->aud_enc =
gst_camerabin_create_and_add_element (vidbin, DEFAULT_AUD_ENC,
"audio-encoder"))) {
goto error;
}
/* Link audio part to the muxer */
if (!gst_element_link_pads_full (vid->aud_enc, NULL, vid->muxer, NULL,
GST_PAD_LINK_CHECK_CAPS)) {
GST_ELEMENT_ERROR (vid, CORE, NEGOTIATION, (NULL),
("linking audio encoder and muxer failed"));
goto error;
}
}
/* Add queue leading out of the video bin and to view finder */
vid->tee_vf_srcpad = gst_element_get_request_pad (vid->tee, "src_%u");
queue = gst_element_factory_make ("queue", "viewfinder-queue");
if (!gst_camerabin_add_element (vidbin, queue)) {
goto error;
}
/* Set queue leaky, we don't want to block video encoder feed, but
prefer leaking view finder buffers instead. */
g_object_set (G_OBJECT (queue), "leaky", 2, "max-size-buffers", 1, "silent",
TRUE, NULL);
/* Set up src ghost pad for video bin */
vid_srcpad = gst_element_get_static_pad (queue, "src");
gst_ghost_pad_set_target (GST_GHOST_PAD (vid->srcpad), vid_srcpad);
/* Never let video bin eos events reach view finder */
vid->vid_src_probe_id = gst_pad_add_event_probe (vid_srcpad,
G_CALLBACK (gst_camerabin_drop_eos_probe), vid);
gst_object_unref (vid_srcpad);
/* audio source is not always present and might be set to NULL during operation */
if (vid->aud_src
&& g_object_class_find_property (G_OBJECT_GET_CLASS (vid->aud_src),
"provide-clock")) {
g_object_set (vid->aud_src, "provide-clock", FALSE, NULL);
}
GST_DEBUG ("created video elements");
return TRUE;
error:
gst_camerabin_video_destroy_elements (vid);
return FALSE;
}
/*
* gst_camerabin_video_destroy_elements:
* @vid: a pointer to #GstCameraBinVideo
*
* This function destroys all the elements created by
* gst_camerabin_video_create_elements().
*
*/
static void
gst_camerabin_video_destroy_elements (GstCameraBinVideo * vid)
{
GST_DEBUG ("destroying video elements");
/* Remove EOS event probe from videobin srcpad (queue's srcpad) */
if (vid->vid_src_probe_id) {
GstPad *pad = gst_ghost_pad_get_target (GST_GHOST_PAD (vid->srcpad));
if (pad) {
gst_pad_remove_event_probe (pad, vid->vid_src_probe_id);
gst_object_unref (pad);
}
vid->vid_src_probe_id = 0;
}
/* Remove buffer probe from video tee srcpad */
if (vid->vid_tee_probe_id) {
gst_pad_remove_buffer_probe (vid->tee_video_srcpad, vid->vid_tee_probe_id);
vid->vid_tee_probe_id = 0;
}
/* Release tee request pads */
if (vid->tee_video_srcpad) {
gst_element_release_request_pad (vid->tee, vid->tee_video_srcpad);
gst_object_unref (vid->tee_video_srcpad);
vid->tee_video_srcpad = NULL;
}
if (vid->tee_vf_srcpad) {
gst_element_release_request_pad (vid->tee, vid->tee_vf_srcpad);
gst_object_unref (vid->tee_vf_srcpad);
vid->tee_vf_srcpad = NULL;
}
gst_ghost_pad_set_target (GST_GHOST_PAD (vid->sinkpad), NULL);
gst_ghost_pad_set_target (GST_GHOST_PAD (vid->srcpad), NULL);
gst_camerabin_remove_elements_from_bin (GST_BIN (vid));
vid->aud_src = NULL;
vid->sink = NULL;
vid->tee = NULL;
vid->volume = NULL;
vid->video_queue = NULL;
vid->vid_enc = NULL;
vid->aud_enc = NULL;
vid->muxer = NULL;
if (vid->pending_eos) {
gst_event_unref (vid->pending_eos);
vid->pending_eos = NULL;
}
}
/*
* Set & get mute and video capture elements
*/
void
gst_camerabin_video_set_mute (GstCameraBinVideo * vid, gboolean mute)
{
g_return_if_fail (vid != NULL);
GST_DEBUG_OBJECT (vid, "setting mute %s", mute ? "on" : "off");
vid->mute = mute;
if (vid->volume) {
g_object_set (vid->volume, "mute", mute, NULL);
}
}
void
gst_camerabin_video_set_post (GstCameraBinVideo * vid, GstElement * post)
{
GstElement **app_post;
GST_DEBUG_OBJECT (vid, "setting video post processing: %" GST_PTR_FORMAT,
post);
GST_OBJECT_LOCK (vid);
app_post = &vid->app_post;
gst_object_replace ((GstObject **) app_post, GST_OBJECT (post));
GST_OBJECT_UNLOCK (vid);
}
void
gst_camerabin_video_set_video_enc (GstCameraBinVideo * vid,
GstElement * video_enc)
{
GstElement **app_vid_enc;
GST_DEBUG_OBJECT (vid, "setting video encoder: %" GST_PTR_FORMAT, video_enc);
GST_OBJECT_LOCK (vid);
app_vid_enc = &vid->app_vid_enc;
gst_object_replace ((GstObject **) app_vid_enc, GST_OBJECT (video_enc));
GST_OBJECT_UNLOCK (vid);
}
void
gst_camerabin_video_set_audio_enc (GstCameraBinVideo * vid,
GstElement * audio_enc)
{
GstElement **app_aud_enc;
GST_DEBUG_OBJECT (vid, "setting audio encoder: %" GST_PTR_FORMAT, audio_enc);
GST_OBJECT_LOCK (vid);
app_aud_enc = &vid->app_aud_enc;
gst_object_replace ((GstObject **) app_aud_enc, GST_OBJECT (audio_enc));
GST_OBJECT_UNLOCK (vid);
}
void
gst_camerabin_video_set_muxer (GstCameraBinVideo * vid, GstElement * muxer)
{
GstElement **app_mux;
GST_DEBUG_OBJECT (vid, "setting muxer: %" GST_PTR_FORMAT, muxer);
GST_OBJECT_LOCK (vid);
app_mux = &vid->app_mux;
gst_object_replace ((GstObject **) app_mux, GST_OBJECT (muxer));
GST_OBJECT_UNLOCK (vid);
}
void
gst_camerabin_video_set_audio_src (GstCameraBinVideo * vid,
GstElement * audio_src)
{
GstElement **app_aud_src;
GST_DEBUG_OBJECT (vid, "setting audio source: %" GST_PTR_FORMAT, audio_src);
GST_OBJECT_LOCK (vid);
app_aud_src = &vid->app_aud_src;
gst_object_replace ((GstObject **) app_aud_src, GST_OBJECT (audio_src));
GST_OBJECT_UNLOCK (vid);
}
void
gst_camerabin_video_set_flags (GstCameraBinVideo * vid, GstCameraBinFlags flags)
{
GST_DEBUG_OBJECT (vid, "setting video flags: %d", flags);
GST_OBJECT_LOCK (vid);
vid->flags = flags;
GST_OBJECT_UNLOCK (vid);
}
gboolean
gst_camerabin_video_get_mute (GstCameraBinVideo * vid)
{
g_return_val_if_fail (vid != NULL, FALSE);
if (vid->volume) {
g_object_get (vid->volume, "mute", &vid->mute, NULL);
}
return vid->mute;
}
GstElement *
gst_camerabin_video_get_post (GstCameraBinVideo * vid)
{
return vid->app_post;
}
GstElement *
gst_camerabin_video_get_video_enc (GstCameraBinVideo * vid)
{
return vid->vid_enc ? vid->vid_enc : vid->app_vid_enc;
}
GstElement *
gst_camerabin_video_get_audio_enc (GstCameraBinVideo * vid)
{
return vid->aud_enc ? vid->aud_enc : vid->app_aud_enc;
}
GstElement *
gst_camerabin_video_get_muxer (GstCameraBinVideo * vid)
{
return vid->muxer ? vid->muxer : vid->app_mux;
}
GstElement *
gst_camerabin_video_get_audio_src (GstCameraBinVideo * vid)
{
return vid->aud_src ? vid->aud_src : vid->app_aud_src;
}

View file

@ -1,139 +0,0 @@
/*
* GStreamer
* Copyright (C) 2008 Nokia Corporation <multimedia@maemo.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 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
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#ifndef __CAMERABIN_VIDEO_H__
#define __CAMERABIN_VIDEO_H__
#include <gst/gstbin.h>
#include "gstcamerabin-enum.h"
G_BEGIN_DECLS
#define ARG_DEFAULT_MUTE FALSE
#define GST_TYPE_CAMERABIN_VIDEO (gst_camerabin_video_get_type())
#define GST_CAMERABIN_VIDEO_CAST(obj) ((GstCameraBinVideo*)(obj))
#define GST_CAMERABIN_VIDEO(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_CAMERABIN_VIDEO,GstCameraBinVideo))
#define GST_CAMERABIN_VIDEO_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_CAMERABIN_VIDEO,GstCameraBinVideoClass))
#define GST_IS_CAMERABIN_VIDEO(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_CAMERABIN_VIDEO))
#define GST_IS_CAMERABIN_VIDEO_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_CAMERABIN_VIDEO))
/**
* GstCameraBinVideo:
*
* The opaque #GstCameraBinVideo structure.
*/
typedef struct _GstCameraBinVideo GstCameraBinVideo;
typedef struct _GstCameraBinVideoClass GstCameraBinVideoClass;
struct _GstCameraBinVideo
{
GstBin parent;
GString *filename;
/* A/V timestamp rewriting */
guint64 adjust_ts_video;
guint64 last_ts_video;
gboolean calculate_adjust_ts_video;
/* Sink and src pads of video bin */
GstPad *sinkpad;
GstPad *srcpad;
/* Tee src pads leading to video encoder and view finder */
GstPad *tee_video_srcpad;
GstPad *tee_vf_srcpad;
/* Application set elements */
GstElement *app_post; /* Video post processing */
GstElement *app_vid_enc;
GstElement *app_aud_enc;
GstElement *app_aud_src;
GstElement *app_mux;
/* Other elements */
GstElement *aud_src; /* Audio source */
GstElement *sink; /* Sink for recorded video */
GstElement *tee; /* Split output to view finder and recording sink */
GstElement *volume; /* Volume for muting */
GstElement *video_queue; /* Buffer for raw video frames */
GstElement *vid_enc; /* Video encoder */
GstElement *aud_enc; /* Audio encoder */
GstElement *muxer; /* Muxer */
GstEvent *pending_eos;
/* Probe IDs */
gulong vid_src_probe_id;
gulong vid_tee_probe_id;
gulong vid_sink_probe_id;
gboolean mute;
GstCameraBinFlags flags;
};
struct _GstCameraBinVideoClass
{
GstBinClass parent_class;
};
GType gst_camerabin_video_get_type (void);
/*
* external function prototypes
*/
void gst_camerabin_video_set_mute (GstCameraBinVideo * vid, gboolean mute);
void gst_camerabin_video_set_post (GstCameraBinVideo * vid, GstElement * post);
void
gst_camerabin_video_set_video_enc (GstCameraBinVideo * vid,
GstElement * video_enc);
void
gst_camerabin_video_set_audio_enc (GstCameraBinVideo * vid,
GstElement * audio_enc);
void
gst_camerabin_video_set_muxer (GstCameraBinVideo * vid, GstElement * muxer);
void
gst_camerabin_video_set_audio_src (GstCameraBinVideo * vid,
GstElement * audio_src);
void
gst_camerabin_video_set_flags (GstCameraBinVideo * vid,
GstCameraBinFlags flags);
gboolean gst_camerabin_video_get_mute (GstCameraBinVideo * vid);
GstElement *gst_camerabin_video_get_post (GstCameraBinVideo * vid);
GstElement *gst_camerabin_video_get_video_enc (GstCameraBinVideo * vid);
GstElement *gst_camerabin_video_get_audio_enc (GstCameraBinVideo * vid);
GstElement *gst_camerabin_video_get_muxer (GstCameraBinVideo * vid);
GstElement *gst_camerabin_video_get_audio_src (GstCameraBinVideo * vid);
G_END_DECLS
#endif /* #ifndef __CAMERABIN_VIDEO_H__ */

View file

@ -1,62 +0,0 @@
/*
* GStreamer
* Copyright (C) 2009 Nokia Corporation <multimedia@maemo.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 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
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#include "gstcamerabin-enum.h"
#define C_FLAGS(v) ((guint) v)
static void
register_gst_camerabin_flags (GType * id)
{
static const GFlagsValue values[] = {
{C_FLAGS (GST_CAMERABIN_FLAG_SOURCE_RESIZE),
"Enable source crop and scale", "source-resize"},
{C_FLAGS (GST_CAMERABIN_FLAG_SOURCE_COLOR_CONVERSION),
"Enable colorspace conversion for video source",
"source-colorspace-conversion"},
{C_FLAGS (GST_CAMERABIN_FLAG_VIEWFINDER_COLOR_CONVERSION),
"Enable colorspace conversion for viewfinder",
"viewfinder-colorspace-conversion"},
{C_FLAGS (GST_CAMERABIN_FLAG_VIEWFINDER_SCALE),
"Enable scale for viewfinder", "viewfinder-scale"},
{C_FLAGS (GST_CAMERABIN_FLAG_AUDIO_CONVERSION),
"Enable audio conversion for video capture", "audio-conversion"},
{C_FLAGS (GST_CAMERABIN_FLAG_DISABLE_AUDIO),
"Disable audio elements for video capture", "disable-audio"},
{C_FLAGS (GST_CAMERABIN_FLAG_IMAGE_COLOR_CONVERSION),
"Enable colorspace conversion for still image",
"image-colorspace-conversion"},
{C_FLAGS (GST_CAMERABIN_FLAG_VIDEO_COLOR_CONVERSION),
"Enable colorspace conversion for video capture",
"video-colorspace-conversion"},
{0, NULL, NULL}
};
*id = g_flags_register_static ("GstCameraBinFlags", values);
}
GType
gst_camerabin_flags_get_type (void)
{
static GType id;
static GOnce once = G_ONCE_INIT;
g_once (&once, (GThreadFunc) register_gst_camerabin_flags, &id);
return id;
}

View file

@ -1,112 +0,0 @@
/*
* GStreamer
* Copyright (C) 2009 Nokia Corporation <multimedia@maemo.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 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
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#ifndef __GST_CAMERABIN_ENUM_H__
#define __GST_CAMERABIN_ENUM_H__
#include <gst/gst.h>
G_BEGIN_DECLS
enum
{
ARG_0,
ARG_FILENAME,
ARG_MODE,
ARG_FLAGS,
ARG_MUTE,
ARG_ZOOM,
ARG_IMAGE_POST,
ARG_IMAGE_ENC,
ARG_IMAGE_FORMATTER,
ARG_VIDEO_POST,
ARG_VIDEO_ENC,
ARG_AUDIO_ENC,
ARG_VIDEO_MUX,
ARG_VF_SINK,
ARG_VIDEO_SRC,
ARG_AUDIO_SRC,
ARG_INPUT_CAPS,
ARG_FILTER_CAPS,
ARG_PREVIEW_CAPS,
ARG_WB_MODE,
ARG_COLOUR_TONE,
ARG_SCENE_MODE,
ARG_FLASH_MODE,
ARG_FOCUS_STATUS,
ARG_CAPABILITIES,
ARG_SHAKE_RISK,
ARG_EV_COMP,
ARG_ISO_SPEED,
ARG_APERTURE,
ARG_EXPOSURE,
ARG_VIDEO_SOURCE_FILTER,
ARG_IMAGE_CAPTURE_SUPPORTED_CAPS,
ARG_VIEWFINDER_FILTER,
ARG_FLICKER_MODE,
ARG_FOCUS_MODE,
ARG_BLOCK_VIEWFINDER,
ARG_IMAGE_CAPTURE_WIDTH,
ARG_IMAGE_CAPTURE_HEIGHT,
ARG_VIDEO_CAPTURE_WIDTH,
ARG_VIDEO_CAPTURE_HEIGHT,
ARG_VIDEO_CAPTURE_FRAMERATE,
ARG_PREVIEW_SOURCE_FILTER,
ARG_READY_FOR_CAPTURE,
ARG_IDLE
};
/**
* GstCameraBinFlags:
* @GST_CAMERABIN_FLAG_SOURCE_RESIZE: enable video crop and scale
* after capture
* @GST_CAMERABIN_FLAG_SOURCE_COLOR_CONVERSION: enable conversion
* of native video format by enabling ffmpegcolorspace
* @GST_CAMERABIN_FLAG_VIEWFINDER_COLOR_CONVERSION: enable color
* conversion for viewfinder element
* @GST_CAMERABIN_FLAG_VIEWFINDER_SCALE: enable scaling in
* viewfinder element retaining aspect ratio
* @GST_CAMERABIN_FLAG_AUDIO_CONVERSION: enable audioconvert and
* audioresample elements
* @GST_CAMERABIN_FLAG_DISABLE_AUDIO: disable audio elements
* @GST_CAMERABIN_FLAG_IMAGE_COLOR_CONVERSION: enable color
* conversion for image output element
* @GST_CAMERABIN_FLAG_VIDEO_COLOR_CONVERSION: enable color
* conversion for video encoder element
*
* Extra flags to configure the behaviour of the sinks.
*/
typedef enum {
GST_CAMERABIN_FLAG_SOURCE_RESIZE = (1 << 0),
GST_CAMERABIN_FLAG_SOURCE_COLOR_CONVERSION = (1 << 1),
GST_CAMERABIN_FLAG_VIEWFINDER_COLOR_CONVERSION = (1 << 2),
GST_CAMERABIN_FLAG_VIEWFINDER_SCALE = (1 << 3),
GST_CAMERABIN_FLAG_AUDIO_CONVERSION = (1 << 4),
GST_CAMERABIN_FLAG_DISABLE_AUDIO = (1 << 5),
GST_CAMERABIN_FLAG_IMAGE_COLOR_CONVERSION = (1 << 6),
GST_CAMERABIN_FLAG_VIDEO_COLOR_CONVERSION = (1 << 7)
} GstCameraBinFlags;
#define GST_TYPE_CAMERABIN_FLAGS (gst_camerabin_flags_get_type())
GType gst_camerabin_flags_get_type (void);
G_END_DECLS
#endif /* #ifndef __GST_CAMERABIN_ENUM_H__ */

View file

@ -1,8 +0,0 @@
# glib-genmarshal --header --prefix=gst_camerabin camerabin_marshal.marshal > camerabin_marshal.h
# glib-genmarshal --body --prefix=gst_camerabin camerabin_marshal.marshal > camerabin_marshal.c
VOID:INT,INT,INT,INT
VOID:INT,INT
BOOLEAN:STRING
INT64:VOID
VOID:OBJECT,INT64,INT64

File diff suppressed because it is too large Load diff

View file

@ -1,236 +0,0 @@
/*
* GStreamer
* Copyright (C) 2008 Nokia Corporation <multimedia@maemo.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 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
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#ifndef __GST_CAMERABIN_H__
#define __GST_CAMERABIN_H__
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <gst/gstbin.h>
#include <gst/interfaces/photography.h>
#include "gstcamerabin-enum.h"
#include "camerabinimage.h"
#include "camerabinvideo.h"
#include "camerabinpreview.h"
G_BEGIN_DECLS
/* #defines don't like whitespacey bits */
#define GST_TYPE_CAMERABIN \
(gst_camerabin_get_type())
#define GST_CAMERABIN(obj) \
(G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_CAMERABIN,GstCameraBin))
#define GST_CAMERABIN_CLASS(klass) \
(G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_CAMERABIN,GstCameraBinClass))
#define GST_IS_CAMERABIN(obj) \
(G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_CAMERABIN))
#define GST_IS_CAMERABIN_CLASS(klass) \
(G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_CAMERABIN))
typedef struct _GstCameraBin GstCameraBin;
typedef struct _GstCameraBinClass GstCameraBinClass;
/**
* GstCameraBin:
*
* The opaque #GstCameraBin structure.
*/
struct _GstCameraBin
{
GstPipeline parent;
/* private */
GString *filename;
gint mode; /* MODE_IMAGE or MODE_VIDEO */
GstCameraBinFlags flags;
gboolean stop_requested; /* TRUE if capturing stop needed */
gboolean paused; /* TRUE if capturing paused */
/*
* Those 2 booleans work together.
*
* 'block_viewfinder_prop' is the property, 'block_viewfinder_trigger'
* is the flag that actually makes the viewfinder block after capture.
* We need both to avoid blocking the viewfinder if the application resets
* the flag after issuing the 'capture-start', but before the actual
* blocking happens. This causes the viewfinder to block even though
* the application resetted the flag to keep it running already.
*
* Here's how this should work:
* When a capture is started, the property is checked, if it is TRUE, the
* trigger is set to TRUE. The blocking will only happen if
* the trigger is TRUE after image capture finishes, ff the property
* is reset before the blocking happens, the trigger goes to
* FALSE and no blocking happens.
*/
gboolean block_viewfinder_prop; /* TRUE if viewfinder blocks after capture */
gboolean block_viewfinder_trigger;
/* Resolution of the buffers configured to camerabin */
gint width;
gint height;
/* Frames per second configured to camerabin */
gint fps_n;
gint fps_d;
/* app configured resolution/framerate */
gint app_width;
gint app_height;
gint app_fps_n;
gint app_fps_d;
gboolean video_capture_caps_update;
/* Image capture resolution */
gint image_capture_width;
gint image_capture_height;
/* Image tags are collected here first before sending to imgbin */
GstTagList *event_tags;
/* Caps applied to capsfilters when taking still image */
GstCaps *image_capture_caps;
gboolean image_capture_caps_update;
/* Caps applied to capsfilters when in view finder mode */
GstCaps *view_finder_caps;
/* Caps that videosrc supports */
GstCaps *allowed_caps;
/* Caps used to create preview image */
GstCaps *preview_caps;
/* Caps used to create video preview image */
GstCaps *video_preview_caps;
/* The digital zoom (from 1.0 to 10.0) */
gfloat zoom;
/* concurrency control */
GMutex *capture_mutex;
GCond *cond;
GCond *idle_cond;
gboolean capturing;
gboolean eos_handled;
/* everytime a new capture is started this is incremented, when it is
* finished/fails it is decremented. Used to know if camerabin is idle */
gint processing_counter;
/* pad names for output and input selectors */
GstPad *pad_src_view;
GstPad *pad_view_src;
GstPad *pad_src_img;
GstPad *pad_src_vid;
GstPad *pad_view_vid;
GstPad *pad_src_queue;
GstElement *img_queue; /* queue for decoupling capture from
image-postprocessing and saving */
GstElement *imgbin; /* bin that holds image capturing elements */
GstElement *vidbin; /* bin that holds video capturing elements */
GstElement *active_bin; /* image or video bin that is currently in use */
/* pipeline for creating preview images */
GstCameraBinPreviewPipelineData *preview_pipeline;
/* pipeline for creating video preview image */
GstCameraBinPreviewPipelineData *video_preview_pipeline;
GstBuffer *video_preview_buffer; /* buffer for storing video preview */
/* source elements */
GstElement *src_vid_src;
GstElement *src_filter;
GstElement *src_zoom_crop;
GstElement *src_zoom_scale;
GstElement *src_zoom_filter;
GstElement *src_out_sel;
/* view finder elements */
GstElement *view_in_sel;
GstElement *aspect_filter;
GstElement *view_scale;
GstElement *view_sink;
/* Application configurable elements */
GstElement *app_vid_src;
GstElement *app_vf_sink;
GstElement *app_video_filter;
GstElement *app_viewfinder_filter;
GstElement *app_preview_source_filter;
GstElement *app_video_preview_source_filter;
/* Night mode handling */
gboolean night_mode;
gint pre_night_fps_n;
gint pre_night_fps_d;
/* Buffer probe id for captured image handling */
gulong image_captured_id;
/* Optional base crop for frames. Used to crop frames e.g.
due to wrong aspect ratio, before the crop related to zooming. */
gint base_crop_top;
gint base_crop_bottom;
gint base_crop_left;
gint base_crop_right;
};
/**
* GstCameraBinClass:
*
* The #GstCameraBin class structure.
*/
struct _GstCameraBinClass
{
GstPipelineClass parent_class;
/* action signals */
void (*capture_start) (GstCameraBin * camera);
void (*capture_stop) (GstCameraBin * camera);
void (*capture_pause) (GstCameraBin * camera);
void (*set_video_resolution_fps) (GstCameraBin * camera, gint width,
gint height, gint fps_n, gint fps_d);
void (*set_image_resolution) (GstCameraBin * camera, gint width, gint height);
/* signals (callback) */
gboolean (*img_done) (GstCameraBin * camera, const gchar * filename);
};
/**
* GstCameraBinMode:
* @MODE_IMAGE: image capture
* @MODE_VIDEO: video capture
*
* Capture mode to use.
*/
typedef enum
{
MODE_IMAGE = 0,
MODE_VIDEO
} GstCameraBinMode;
GType gst_camerabin_get_type (void);
G_END_DECLS
#endif /* #ifndef __GST_CAMERABIN_H__ */

View file

@ -1,81 +0,0 @@
/*
* GStreamer
* Copyright (C) 2008 Nokia Corporation <multimedia@maemo.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 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
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
/*
* Includes
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include "gstcamerabincolorbalance.h"
#include "gstcamerabin.h"
/*
* static functions implementation
*/
static const GList *
gst_camerabin_color_balance_list_channels (GstColorBalance * cb)
{
if (cb && GST_CAMERABIN (cb)->src_vid_src) {
GstColorBalance *cbl = GST_COLOR_BALANCE (GST_CAMERABIN (cb)->src_vid_src);
return gst_color_balance_list_channels (cbl);
} else {
return NULL;
}
}
static void
gst_camerabin_color_balance_set_value (GstColorBalance * cb,
GstColorBalanceChannel * channel, gint value)
{
if (cb && GST_CAMERABIN (cb)->src_vid_src) {
GstColorBalance *cbl = GST_COLOR_BALANCE (GST_CAMERABIN (cb)->src_vid_src);
gst_color_balance_set_value (cbl, channel, value);
}
}
static gint
gst_camerabin_color_balance_get_value (GstColorBalance * cb,
GstColorBalanceChannel * channel)
{
if (cb && GST_CAMERABIN (cb)->src_vid_src) {
GstColorBalance *cbl = GST_COLOR_BALANCE (GST_CAMERABIN (cb)->src_vid_src);
return gst_color_balance_get_value (cbl, channel);
} else {
return 0;
}
}
/*
* extern functions implementation
*/
void
gst_camerabin_color_balance_init (GstColorBalanceInterface * iface)
{
/* FIXME: to get the same type as v4l2src */
GST_COLOR_BALANCE_TYPE (iface) = GST_COLOR_BALANCE_HARDWARE;
iface->list_channels = gst_camerabin_color_balance_list_channels;
iface->set_value = gst_camerabin_color_balance_set_value;
iface->get_value = gst_camerabin_color_balance_get_value;
}

View file

@ -1,28 +0,0 @@
/*
* GStreamer
* Copyright (C) 2008 Nokia Corporation <multimedia@maemo.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 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
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#ifndef __GST_CAMERA_COLOR_BALANCE_H__
#define __GST_CAMERA_COLOR_BALANCE_H__
#include <gst/interfaces/colorbalance.h>
extern void gst_camerabin_color_balance_init (GstColorBalanceInterface * iface);
#endif /* #ifndef __GST_CAMERA_COLOR_BALANCE_H__ */

File diff suppressed because it is too large Load diff

View file

@ -1,84 +0,0 @@
/* GStreamer
* Copyright (C) 2003 Julien Moutte <julien@moutte.net>
* Copyright (C) 2005 Ronald S. Bultje <rbultje@ronald.bitfreak.net>
* Copyright (C) 2008 Nokia Corporation. (contact <stefan.kost@nokia.com>)
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 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
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#ifndef __GST_INPUT_SELECTOR_H__
#define __GST_INPUT_SELECTOR_H__
#include <gst/gst.h>
G_BEGIN_DECLS
#define GST_TYPE_INPUT_SELECTOR \
(gst_input_selector_get_type())
#define GST_INPUT_SELECTOR(obj) \
(G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_INPUT_SELECTOR, GstInputSelector))
#define GST_INPUT_SELECTOR_CLASS(klass) \
(G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_INPUT_SELECTOR, GstInputSelectorClass))
#define GST_IS_INPUT_SELECTOR(obj) \
(G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_INPUT_SELECTOR))
#define GST_IS_INPUT_SELECTOR_CLASS(klass) \
(G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_INPUT_SELECTOR))
typedef struct _GstInputSelector GstInputSelector;
typedef struct _GstInputSelectorClass GstInputSelectorClass;
#define GST_INPUT_SELECTOR_GET_LOCK(sel) (((GstInputSelector*)(sel))->lock)
#define GST_INPUT_SELECTOR_GET_COND(sel) (((GstInputSelector*)(sel))->cond)
#define GST_INPUT_SELECTOR_LOCK(sel) (g_mutex_lock (GST_INPUT_SELECTOR_GET_LOCK(sel)))
#define GST_INPUT_SELECTOR_UNLOCK(sel) (g_mutex_unlock (GST_INPUT_SELECTOR_GET_LOCK(sel)))
#define GST_INPUT_SELECTOR_WAIT(sel) (g_cond_wait (GST_INPUT_SELECTOR_GET_COND(sel), \
GST_INPUT_SELECTOR_GET_LOCK(sel)))
#define GST_INPUT_SELECTOR_BROADCAST(sel) (g_cond_broadcast (GST_INPUT_SELECTOR_GET_COND(sel)))
struct _GstInputSelector {
GstElement element;
GstPad *srcpad;
GstPad *active_sinkpad;
guint n_pads;
guint padcount;
GstSegment segment; /* the output segment */
gboolean pending_close; /* if we should push a close first */
GMutex *lock;
GCond *cond;
gboolean blocked;
gboolean flushing;
/* select all mode, send data from all input pads forward */
gboolean select_all;
};
struct _GstInputSelectorClass {
GstElementClass parent_class;
gint64 (*block) (GstInputSelector *self);
void (*switch_) (GstInputSelector *self, GstPad *pad,
gint64 stop_time, gint64 start_time);
};
GType gst_input_selector_get_type (void);
G_END_DECLS
#endif /* __GST_INPUT_SELECTOR_H__ */

View file

@ -14,7 +14,7 @@ TESTS_ENVIRONMENT = \
GST_PLUGIN_SYSTEM_PATH= \
GST_PLUGIN_PATH=$(top_builddir)/gst:$(top_builddir)/sys:$(top_builddir)/ext:$(GST_PLUGINS_FFMPEG_DIR):$(GST_PLUGINS_UGLY_DIR):$(GST_PLUGINS_GOOD_DIR):$(GST_PLUGINS_BASE_DIR):$(GST_PLUGINS_DIR) \
GST_PLUGIN_LOADING_WHITELIST="gstreamer@$(GST_PLUGINS_DIR):gst-plugins-base@$(GSTPB_PLUGINS_DIR):gst-plugins-good:gst-plugins-ugly:gst-ffmpeg:gst-plugins-bad@$(top_builddir)" \
GST_STATE_IGNORE_ELEMENTS="apexsink camerabin camerabin2 cdaudio dc1394src \
GST_STATE_IGNORE_ELEMENTS="apexsink camerabin cdaudio dc1394src \
dccpclientsrc dccpclientsink dccpserversrc dccpserversink decklinksrc \
decklinksink dvbsrc dvbbasebin dfbvideosink festival gsettingsvideosrc \
gsettingsvideosink gsettingsaudiosrc gsettingsaudiosink linsyssdisrc linsyssdisink nassink \
@ -182,7 +182,6 @@ check_PROGRAMS = \
elements/asfmux \
elements/baseaudiovisualizer \
elements/camerabin \
elements/camerabin2 \
elements/dataurisrc \
elements/legacyresample \
$(check_jifmux) \
@ -306,21 +305,11 @@ elements_camerabin_CFLAGS = \
$(GST_PLUGINS_BAD_CFLAGS) $(GST_PLUGINS_BASE_CFLAGS) \
$(GST_BASE_CFLAGS) $(GST_CFLAGS) $(AM_CFLAGS) -DGST_USE_UNSTABLE_API
elements_camerabin_LDADD = \
$(top_builddir)/gst-libs/gst/interfaces/libgstphotography-@GST_API_VERSION@.la \
$(GST_PLUGINS_BASE_LIBS) \
$(GST_BASE_LIBS) $(GST_LIBS) $(LDADD)
elements_camerabin_SOURCES = elements/camerabin.c
elements_camerabin2_CFLAGS = \
$(GST_PLUGINS_BAD_CFLAGS) $(GST_PLUGINS_BASE_CFLAGS) \
$(GST_BASE_CFLAGS) $(GST_CFLAGS) $(AM_CFLAGS) -DGST_USE_UNSTABLE_API
elements_camerabin2_LDADD = \
$(top_builddir)/gst-libs/gst/interfaces/libgstphotography-@GST_API_VERSION@.la \
$(top_builddir)/gst-libs/gst/basecamerabinsrc/libgstbasecamerabinsrc-@GST_API_VERSION@.la \
-lgstpbutils-$(GST_API_VERSION) \
$(GST_PLUGINS_BASE_LIBS) $(GST_BASE_LIBS) $(GST_LIBS) $(LDADD)
elements_camerabin2_SOURCES = elements/camerabin2.c
elements_camerabin_SOURCES = elements/camerabin.c
elements_jifmux_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(EXIF_CFLAGS) $(AM_CFLAGS)
elements_jifmux_LDADD = $(GST_PLUGINS_BASE_LIBS) -lgsttag-$(GST_API_VERSION) $(GST_CHECK_LIBS) $(EXIF_LIBS) $(LDADD)

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,5 +1,5 @@
if HAVE_GTK
GTK_EXAMPLES=camerabin mxf scaletempo camerabin2
GTK_EXAMPLES=mxf scaletempo camerabin2
else
GTK_EXAMPLES=
endif
@ -13,6 +13,6 @@ endif
OPENCV_EXAMPLES=opencv
SUBDIRS= $(DIRECTFB_DIR) $(GTK_EXAMPLES) $(OPENCV_EXAMPLES)
DIST_SUBDIRS= camerabin camerabin2 directfb mxf scaletempo opencv
DIST_SUBDIRS= camerabin2 directfb mxf scaletempo opencv
include $(top_srcdir)/common/parallel-subdirs.mak

View file

@ -1,4 +0,0 @@
gst-camera
gst-camera-perf
gst-camerabin-test
test_*.jpg

View file

@ -1,54 +0,0 @@
GST_CAMERABIN_UI_FILES = gst-camera.ui
if HAVE_GTK
GST_CAMERABIN_GTK_EXAMPLES = gst-camera
gst_camera_SOURCES = gst-camera.h gst-camera.c
gst_camera_CFLAGS = \
$(GST_PLUGINS_BAD_CFLAGS) \
$(GST_PLUGINS_BASE_CFLAGS) $(GST_CFLAGS) \
$(GTK_CFLAGS) \
$(GMODULE_EXPORT_CFLAGS) \
-DGST_USE_UNSTABLE_API
gst_camera_LDADD = \
$(top_builddir)/gst-libs/gst/interfaces/libgstphotography-@GST_API_VERSION@.la \
$(GST_PLUGINS_BASE_LIBS) \
-lgstvideo-@GST_API_VERSION@ \
$(GST_LIBS) \
$(GTK_LIBS) \
$(GMODULE_EXPORT_LIBS)
noinst_DATA = $(GST_CAMERABIN_UI_FILES)
INCLUDES = -DCAMERA_APPS_UIDIR=\""$(srcdir)"\"
else
GST_CAMERABIN_GTK_EXAMPLES =
endif
gst_camera_perf_SOURCES = gst-camera-perf.c
gst_camera_perf_CFLAGS = $(GST_CFLAGS)
gst_camera_perf_LDADD = $(GST_LIBS)
if HAVE_X11
GST_CAMERABIN_X11_EXAMPLES = gst-camerabin-test
gst_camerabin_test_SOURCES = gst-camerabin-test.c
gst_camerabin_test_CFLAGS = $(GST_CFLAGS) $(GST_PLUGINS_BASE_CFLAGS) $(GST_PLUGINS_BAD_CFLAGS)
gst_camerabin_test_LDADD = \
$(top_builddir)/gst-libs/gst/interfaces/libgstphotography-@GST_API_VERSION@.la \
-lgstvideo-@GST_API_VERSION@ \
$(GST_LIBS) \
$(GST_PLUGINS_BASE_LIBS) \
$(X11_LIBS)
else
GST_CAMERABIN_X11_EXAMPLES =
endif
noinst_PROGRAMS = gst-camera-perf $(GST_CAMERABIN_X11_EXAMPLES) $(GST_CAMERABIN_GTK_EXAMPLES)
EXTRA_DIST = $(GST_CAMERABIN_UI_FILES)

File diff suppressed because it is too large Load diff

View file

@ -1,80 +0,0 @@
<?xml version="1.0"?>
<interface>
<!-- interface-requires gtk+ 2.8 -->
<!-- interface-naming-policy project-wide -->
<object class="GtkWindow" id="wndMain">
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<property name="default_width">400</property>
<property name="default_height">600</property>
<signal name="delete_event" handler="on_wndMain_delete_event"/>
<child>
<object class="GtkVPaned" id="vpnMain">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="position">200</property>
<child>
<object class="GtkDrawingArea" id="daMain">
<property name="height_request">100</property>
<property name="visible">True</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
</object>
<packing>
<property name="resize">False</property>
<property name="shrink">True</property>
</packing>
</child>
<child>
<object class="GtkVBox" id="vboxMain">
<property name="visible">True</property>
<child>
<object class="GtkButton" id="btnStart">
<property name="label" translatable="yes">start</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="use_underline">True</property>
<signal name="clicked" handler="on_btnStart_clicked"/>
</object>
<packing>
<property name="expand">False</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkScrolledWindow" id="scrwndMain">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="hscrollbar_policy">never</property>
<property name="vscrollbar_policy">automatic</property>
<child>
<object class="GtkViewport" id="vpMain">
<property name="visible">True</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<child>
<object class="GtkLabel" id="lbMain">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="yalign">0</property>
<property name="label" translatable="yes">== Please wait few seconds after press start ==</property>
<property name="use_markup">True</property>
<property name="wrap">True</property>
<property name="selectable">True</property>
</object>
</child>
</object>
</child>
</object>
<packing>
<property name="position">1</property>
</packing>
</child>
</object>
<packing>
<property name="resize">True</property>
<property name="shrink">True</property>
</packing>
</child>
</object>
</child>
</object>
</interface>

File diff suppressed because it is too large Load diff

View file

@ -1,102 +0,0 @@
/*
* GStreamer
* Copyright (C) 2008 Nokia Corporation <multimedia@maemo.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 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
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
/*
* This is a demo application to test the camerabin element.
* If you have question don't hesitate in contact me edgard.lima@indt.org.br
*/
#ifndef __GST_CAMERA_BIN_H__
#define __GST_CAMERA_BIN_H__
#include <gtk/gtk.h>
void
on_windowMain_delete_event (GtkWidget * widget, GdkEvent * event, gpointer data);
void
on_buttonShot_clicked (GtkButton * button, gpointer user_data);
void
on_buttonPause_clicked (GtkButton * button, gpointer user_data);
void
on_drawingareaView_realize (GtkWidget * widget, gpointer data);
gboolean
on_drawingareaView_configure_event (GtkWidget * widget,
GdkEventConfigure * event, gpointer data);
void
on_comboboxResolution_changed (GtkComboBox * widget, gpointer user_data);
void
on_radiobuttonImageCapture_toggled (GtkToggleButton * togglebutton,
gpointer user_data);
void
on_radiobuttonVideoCapture_toggled (GtkToggleButton * togglebutton,
gpointer user_data);
void
on_rbBntVidEffNone_toggled (GtkToggleButton * togglebutton, gpointer data);
void
on_rbBntVidEffEdge_toggled (GtkToggleButton * togglebutton, gpointer data);
void
on_rbBntVidEffAging_toggled (GtkToggleButton * togglebutton, gpointer user_data);
void
on_rbBntVidEffDice_toggled (GtkToggleButton * togglebutton, gpointer user_data);
void
on_rbBntVidEffWarp_toggled (GtkToggleButton * togglebutton, gpointer data);
void
on_rbBntVidEffShagadelic_toggled (GtkToggleButton * togglebutton, gpointer data);
void
on_rbBntVidEffVertigo_toggled (GtkToggleButton * togglebutton, gpointer data);
void
on_rbBntVidEffRev_toggled (GtkToggleButton * togglebutton, gpointer data);
void
on_rbBntVidEffQuark_toggled (GtkToggleButton * togglebutton, gpointer data);
void
on_chkbntMute_toggled (GtkToggleButton * togglebutton, gpointer data);
void
on_chkbtnRawMsg_toggled (GtkToggleButton * togglebutton, gpointer data);
void
on_hscaleZoom_value_changed (GtkRange * range, gpointer user_data);
void
on_color_control_value_changed (GtkRange * range, gpointer user_data);
gboolean
on_key_released (GtkWidget * widget, GdkEventKey * event, gpointer user_data);
gboolean
on_key_pressed (GtkWidget * widget, GdkEventKey * event, gpointer user_data);
#endif /* __GST_CAMERA_BIN_H__ */

View file

@ -1,424 +0,0 @@
<?xml version="1.0"?>
<interface>
<requires lib="gtk+" version="2.16"/>
<!-- interface-naming-policy project-wide -->
<object class="GtkWindow" id="windowMain">
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<property name="title" translatable="yes">gst-camera</property>
<signal name="delete_event" handler="on_windowMain_delete_event"/>
<child>
<object class="GtkVBox" id="vboxMain">
<property name="visible">True</property>
<child>
<object class="GtkHBox" id="hbox2">
<property name="visible">True</property>
<child>
<object class="GtkMenuBar" id="menubar1">
<property name="visible">True</property>
<child>
<object class="GtkMenuItem" id="menuitemPhotography">
<property name="visible">True</property>
<property name="label" translatable="yes">Photography</property>
<property name="use_underline">True</property>
<child type="submenu">
<object class="GtkMenu" id="menu1">
<property name="visible">True</property>
</object>
</child>
</object>
</child>
<child>
<object class="GtkMenuItem" id="menuitemCapture">
<property name="visible">True</property>
<property name="label" translatable="yes">Capture</property>
<property name="use_underline">True</property>
</object>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkComboBox" id="comboboxResolution">
<property name="visible">True</property>
<property name="model">liststore1</property>
<signal name="changed" handler="on_comboboxResolution_changed"/>
<child>
<object class="GtkCellRendererText" id="cellrenderertext1"/>
<attributes>
<attribute name="text">0</attribute>
</attributes>
</child>
</object>
<packing>
<property name="position">1</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkHBox" id="hboxMode">
<property name="visible">True</property>
<child>
<object class="GtkRadioButton" id="radiobuttonImageCapture">
<property name="label" translatable="yes">Image capture</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="use_underline">True</property>
<property name="active">True</property>
<property name="draw_indicator">True</property>
<signal name="toggled" handler="on_radiobuttonImageCapture_toggled"/>
</object>
<packing>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkRadioButton" id="radiobuttonVideoCapture">
<property name="label" translatable="yes">Video rec</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="use_underline">True</property>
<property name="active">True</property>
<property name="draw_indicator">True</property>
<property name="group">radiobuttonImageCapture</property>
<signal name="toggled" handler="on_radiobuttonVideoCapture_toggled"/>
</object>
<packing>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkButton" id="buttonShot">
<property name="label" translatable="yes">Shot</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="use_underline">True</property>
<signal name="clicked" handler="on_buttonShot_clicked"/>
</object>
<packing>
<property name="position">2</property>
</packing>
</child>
<child>
<object class="GtkButton" id="buttonPause">
<property name="label" translatable="yes">Pause</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="use_underline">True</property>
<signal name="clicked" handler="on_buttonPause_clicked"/>
</object>
<packing>
<property name="position">3</property>
</packing>
</child>
<child>
<object class="GtkCheckButton" id="chkbntMute">
<property name="label" translatable="yes">mute</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="use_underline">True</property>
<property name="draw_indicator">True</property>
<signal name="toggled" handler="on_chkbntMute_toggled"/>
</object>
<packing>
<property name="position">4</property>
</packing>
</child>
<child>
<object class="GtkCheckButton" id="chkbntContinous">
<property name="label" translatable="yes">continous</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="use_underline">True</property>
<property name="draw_indicator">True</property>
</object>
<packing>
<property name="position">5</property>
</packing>
</child>
<child>
<object class="GtkCheckButton" id="chkbtnRawMsg">
<property name="label" translatable="yes">raw msg</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="tooltip_text" translatable="yes">Send raw image after still image capture as gstreamer message</property>
<property name="use_underline">True</property>
<property name="draw_indicator">True</property>
<signal name="toggled" handler="on_chkbtnRawMsg_toggled"/>
</object>
<packing>
<property name="position">6</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkTable" id="tableOptions">
<property name="visible">True</property>
<property name="n_columns">3</property>
<child>
<object class="GtkVBox" id="vboxVidEffect">
<property name="visible">True</property>
<child>
<object class="GtkLabel" id="labelVidEff">
<property name="visible">True</property>
<property name="label" translatable="yes">video effects:</property>
</object>
<packing>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkRadioButton" id="rbBntVidEffNone">
<property name="label" translatable="yes">none</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="use_underline">True</property>
<property name="active">True</property>
<property name="draw_indicator">True</property>
<signal name="toggled" handler="on_rbBntVidEffNone_toggled"/>
</object>
<packing>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkRadioButton" id="rbBntVidEffEdge">
<property name="label" translatable="yes">edged</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="use_underline">True</property>
<property name="active">True</property>
<property name="draw_indicator">True</property>
<property name="group">rbBntVidEffNone</property>
<signal name="toggled" handler="on_rbBntVidEffEdge_toggled"/>
</object>
<packing>
<property name="position">2</property>
</packing>
</child>
<child>
<object class="GtkRadioButton" id="rbBntVidEffAging">
<property name="label" translatable="yes">aging</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="use_underline">True</property>
<property name="active">True</property>
<property name="draw_indicator">True</property>
<property name="group">rbBntVidEffNone</property>
<signal name="toggled" handler="on_rbBntVidEffAging_toggled"/>
</object>
<packing>
<property name="position">3</property>
</packing>
</child>
<child>
<object class="GtkRadioButton" id="rbBntVidEffDice">
<property name="label" translatable="yes">dice</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="use_underline">True</property>
<property name="active">True</property>
<property name="draw_indicator">True</property>
<property name="group">rbBntVidEffNone</property>
<signal name="toggled" handler="on_rbBntVidEffDice_toggled"/>
</object>
<packing>
<property name="position">4</property>
</packing>
</child>
<child>
<object class="GtkRadioButton" id="rbBntVidEffWarp">
<property name="label" translatable="yes">warp</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="use_underline">True</property>
<property name="active">True</property>
<property name="draw_indicator">True</property>
<property name="group">rbBntVidEffNone</property>
<signal name="toggled" handler="on_rbBntVidEffWarp_toggled"/>
</object>
<packing>
<property name="position">5</property>
</packing>
</child>
<child>
<object class="GtkRadioButton" id="rbBntVidEffShaga">
<property name="label" translatable="yes">shagadelic</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="use_underline">True</property>
<property name="active">True</property>
<property name="draw_indicator">True</property>
<property name="group">rbBntVidEffNone</property>
<signal name="toggled" handler="on_rbBntVidEffShagadelic_toggled"/>
</object>
<packing>
<property name="position">6</property>
</packing>
</child>
<child>
<object class="GtkRadioButton" id="rbBntVidEffVertigo">
<property name="label" translatable="yes">vertigo</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="use_underline">True</property>
<property name="active">True</property>
<property name="draw_indicator">True</property>
<property name="group">rbBntVidEffNone</property>
<signal name="toggled" handler="on_rbBntVidEffVertigo_toggled"/>
</object>
<packing>
<property name="position">7</property>
</packing>
</child>
<child>
<object class="GtkRadioButton" id="rbBntVidEffRev">
<property name="label" translatable="yes">rev</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="use_underline">True</property>
<property name="active">True</property>
<property name="draw_indicator">True</property>
<property name="group">rbBntVidEffNone</property>
<signal name="toggled" handler="on_rbBntVidEffRev_toggled"/>
</object>
<packing>
<property name="position">8</property>
</packing>
</child>
<child>
<object class="GtkRadioButton" id="rbBntVidEffQuark">
<property name="label" translatable="yes">quark</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="use_underline">True</property>
<property name="active">True</property>
<property name="draw_indicator">True</property>
<property name="group">rbBntVidEffNone</property>
<signal name="toggled" handler="on_rbBntVidEffQuark_toggled"/>
</object>
<packing>
<property name="position">9</property>
</packing>
</child>
</object>
<packing>
<property name="x_options"></property>
</packing>
</child>
<child>
<object class="GtkScrolledWindow" id="scrlWndColorControls">
<property name="width_request">200</property>
<property name="height_request">200</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="hscrollbar_policy">automatic</property>
<property name="vscrollbar_policy">automatic</property>
<child>
<object class="GtkViewport" id="viewportColorControls">
<property name="visible">True</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<child>
<object class="GtkVBox" id="vboxColorControls">
<property name="visible">True</property>
</object>
</child>
</object>
</child>
</object>
<packing>
<property name="left_attach">2</property>
<property name="right_attach">3</property>
<property name="x_options"></property>
</packing>
</child>
<child>
<object class="GtkAspectFrame" id="drawingareaFrame">
<property name="visible">True</property>
<property name="label_xalign">0</property>
<property name="shadow_type">none</property>
<property name="obey_child">False</property>
<child>
<object class="GtkAlignment" id="alignment1">
<property name="visible">True</property>
<child>
<object class="GtkDrawingArea" id="drawingareaView">
<property name="visible">True</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
<signal name="configure_event" handler="on_drawingareaView_configure_event"/>
<signal name="realize" handler="on_drawingareaView_realize"/>
</object>
</child>
</object>
</child>
</object>
<packing>
<property name="left_attach">1</property>
<property name="right_attach">2</property>
</packing>
</child>
</object>
<packing>
<property name="position">2</property>
</packing>
</child>
<child>
<object class="GtkHScale" id="hscaleZoom">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="adjustment">adjustment1</property>
<property name="digits">0</property>
<property name="value_pos">left</property>
<signal name="value_changed" handler="on_hscaleZoom_value_changed"/>
</object>
<packing>
<property name="expand">False</property>
<property name="position">3</property>
</packing>
</child>
</object>
</child>
</object>
<object class="GtkAdjustment" id="adjustment1">
<property name="lower">100</property>
<property name="upper">1100</property>
<property name="value">100</property>
<property name="step_increment">10</property>
<property name="page_increment">100</property>
<property name="page_size">100</property>
</object>
<object class="GtkListStore" id="liststore1">
<columns>
<!-- column-name item text -->
<column type="gchararray"/>
</columns>
</object>
</interface>

View file

@ -1,845 +0,0 @@
/*
* GStreamer
* Copyright (C) 2010 Nokia Corporation <multimedia@maemo.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 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
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
/*
Examples:
./gst-camerabin-test --image-width=2048 --image-height=1536 --image-enc=dspjpegenc
./gst-camerabin-test --mode=1 --capture-time=10 --image-width=848 --image-height=480 --view-framerate-num=2825 \
--view-framerate-den=100 --audio-src=pulsesrc --audio-enc=nokiaaacenc --video-enc=dspmp4venc \
--video-mux=mp4mux --src-colorspace=UYVY
gst-camerabin-test --help
Usage:
gst-camerabin-test [OPTION...]
camerabin command line test application.
Help Options:
-h, --help Show help options
--help-all Show all help options
--help-gst Show GStreamer Options
Application Options:
--ev-compensation EV compensation (-2.5..2.5, default = 0)
--aperture Aperture (size of lens opening, default = 0 (auto))
--flash-mode Flash mode (default = 0 (auto))
--scene-mode Scene mode (default = 6 (auto))
--exposure Exposure (default = 0 (auto))
--iso-speed ISO speed (default = 0 (auto))
--white-balance-mode White balance mode (default = 0 (auto))
--colour-tone-mode Colour tone mode (default = 0 (auto))
--directory Directory for capture file(s) (default is current directory)
--mode Capture mode (default = 0 (image), 1 = video)
--capture-time Time to capture video in seconds (default = 10)
--capture-total Total number of captures to be done (default = 1)
--flags Flags for camerabin, (default = 0x9)
--mute Mute audio
--zoom Zoom (100 = 1x (default), 200 = 2x etc.)
--audio-src Audio source used in video recording
--audio-bitrate Audio bitrate (default 128000)
--audio-samplerate Audio samplerate (default 48000)
--audio-channels Audio channels (default 1)
--video-src Video source used in still capture and video recording
--audio-enc Audio encoder used in video recording
--video-enc Video encoder used in video recording
--image-enc Image encoder used in still capture
--image-pp Image post-processing element
--image-formatter Image metadata formatter element
--video-mux Muxer used in video recording
--viewfinder-sink Viewfinder sink (default = fakesink)
--image-width Width for image capture
--image-height Height for image capture
--view-framerate-num Framerate numerator for viewfinder
--view-framerate-den Framerate denominator for viewfinder
--src-colorspace Colorspace format for video source (e.g. YUY2, UYVY)
--src-format Video format for video source
--preview-caps Preview caps (e.g. video/x-raw-rgb,width=320,height=240)
--video-source-filter Video filter to process all frames from video source
--viewfinder-filter Filter to process all frames going to viewfinder sink
--x-width X window width (default = 320)
--x-height X window height (default = 240)
--no-xwindow Do not create XWindow
*/
/*
* Includes
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#define GST_USE_UNSTABLE_API 1
#include <gst/gst.h>
#include <gst/video/videooverlay.h>
#include <gst/interfaces/photography.h>
#include <string.h>
#include <sys/time.h>
#include <time.h>
#include <unistd.h>
#include <stdlib.h>
#include <glib.h>
#include <glib/gstdio.h>
#include <X11/Xlib.h>
#include <X11/Xatom.h>
/*
* debug logging
*/
GST_DEBUG_CATEGORY_STATIC (camerabin_test);
#define GST_CAT_DEFAULT camerabin_test
typedef struct _ResultType
{
GstClockTime avg;
GstClockTime min;
GstClockTime max;
guint32 times;
} ResultType;
/*
* Global vars
*/
static GstElement *camera_bin = NULL;
static GMainLoop *loop = NULL;
/* commandline options */
static gchar *audiosrc_name = NULL;
static gchar *videosrc_name = NULL;
static gchar *audioenc_name = NULL;
static gchar *videoenc_name = NULL;
static gchar *imageenc_name = NULL;
static gchar *imagepp_name = NULL;
static gchar *imageformatter_name = NULL;
static gchar *videomux_name = NULL;
static gchar *vfsink_name = NULL;
static gchar *src_csp = NULL;
static gchar *src_format = NULL;
static gint image_width = 1280;
static gint image_height = 720;
static gint view_framerate_num = 2825;
static gint view_framerate_den = 100;
static gboolean no_xwindow = FALSE;
static gint mode = 1;
static gint flags = 0x4f;
static gboolean mute = FALSE;
static gint zoom = 100;
static gint capture_time = 10;
static gint capture_count = 0;
static gint capture_total = 1;
/* photography interface command line options */
#define EV_COMPENSATION_NONE -G_MAXFLOAT
#define APERTURE_NONE -G_MAXINT
#define FLASH_MODE_NONE -G_MAXINT
#define SCENE_MODE_NONE -G_MAXINT
#define EXPOSURE_NONE -G_MAXINT64
#define ISO_SPEED_NONE -G_MAXINT
#define WHITE_BALANCE_MODE_NONE -G_MAXINT
#define COLOR_TONE_MODE_NONE -G_MAXINT
static gfloat ev_compensation = EV_COMPENSATION_NONE;
static gint aperture = APERTURE_NONE;
static gint flash_mode = FLASH_MODE_NONE;
static gint scene_mode = SCENE_MODE_NONE;
static gint64 exposure = EXPOSURE_NONE;
static gint iso_speed = ISO_SPEED_NONE;
static gint wb_mode = WHITE_BALANCE_MODE_NONE;
static gint color_mode = COLOR_TONE_MODE_NONE;
/* audio capsfilter options */
static gint audio_bitrate = 128000;
static gint audio_samplerate = 48000;
static gint audio_channels = 1;
static gchar *video_src_filter = NULL;
static gchar *viewfinder_filter = NULL;
static int x_width = 320;
static int x_height = 240;
/* test configuration for common callbacks */
static GString *filename = NULL;
static gchar *preview_caps_name = NULL;
/* X window variables */
static Display *display = NULL;
static Window window = 0;
GTimer *timer = NULL;
/*
* Prototypes
*/
static gboolean run_pipeline (gpointer user_data);
static void set_metadata (GstElement * camera);
static void
create_host_window (void)
{
unsigned long valuemask;
XSetWindowAttributes attributes;
display = XOpenDisplay (NULL);
if (display) {
window =
XCreateSimpleWindow (display, DefaultRootWindow (display), 0, 0,
x_width, x_height, 0, 0, 0);
if (window) {
valuemask = CWOverrideRedirect;
attributes.override_redirect = True;
XChangeWindowAttributes (display, window, valuemask, &attributes);
XSetWindowBackgroundPixmap (display, window, None);
XMapRaised (display, window);
XSync (display, FALSE);
} else {
GST_DEBUG ("could not create X window!");
}
} else {
GST_DEBUG ("could not open display!");
}
}
static gboolean
img_capture_done (GstElement * camera, const gchar * fname, gpointer user_data)
{
gboolean ret = FALSE;
GST_DEBUG ("image done: %s", fname);
if (capture_count < capture_total) {
g_idle_add ((GSourceFunc) run_pipeline, NULL);
} else {
g_main_loop_quit (loop);
}
return ret;
}
static GstBusSyncReply
sync_bus_callback (GstBus * bus, GstMessage * message, gpointer data)
{
const GstStructure *st;
const GValue *image;
GstBuffer *buf = NULL;
gchar *preview_filename = NULL;
FILE *f = NULL;
size_t written;
switch (GST_MESSAGE_TYPE (message)) {
case GST_MESSAGE_ELEMENT:{
st = gst_message_get_structure (message);
if (st) {
if (gst_structure_has_name (st, "prepare-xwindow-id")) {
if (!no_xwindow && window) {
gst_video_overlay_set_window_handle (GST_VIDEO_OVERLAY
(GST_MESSAGE_SRC (message)), window);
gst_message_unref (message);
message = NULL;
return GST_BUS_DROP;
}
} else if (gst_structure_has_name (st, "image-captured")) {
GST_DEBUG ("image-captured");
} else if (gst_structure_has_name (st, "preview-image")) {
GST_DEBUG ("preview-image");
//extract preview-image from msg
image = gst_structure_get_value (st, "buffer");
if (image) {
GstMapInfo map;
buf = gst_value_get_buffer (image);
gst_buffer_map (buf, &map, GST_MAP_READ);
preview_filename = g_strdup_printf ("test_vga.rgb");
g_print ("writing buffer to %s, elapsed: %.2fs\n",
preview_filename, g_timer_elapsed (timer, NULL));
f = g_fopen (preview_filename, "w");
if (f) {
written = fwrite (map.data, map.size, 1, f);
if (!written) {
g_print ("error writing file\n");
}
fclose (f);
} else {
g_print ("error opening file for raw image writing\n");
}
g_free (preview_filename);
gst_buffer_unmap (buf, &map);
}
}
}
break;
}
default:
/* unhandled message */
break;
}
return GST_BUS_PASS;
}
static gboolean
bus_callback (GstBus * bus, GstMessage * message, gpointer data)
{
switch (GST_MESSAGE_TYPE (message)) {
case GST_MESSAGE_ERROR:{
GError *err;
gchar *debug;
gst_message_parse_error (message, &err, &debug);
g_print ("Error: %s\n", err->message);
g_error_free (err);
g_free (debug);
/* Write debug graph to file */
GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS (GST_BIN (camera_bin),
GST_DEBUG_GRAPH_SHOW_ALL, "camerabin.error");
g_main_loop_quit (loop);
break;
}
case GST_MESSAGE_STATE_CHANGED:
if (GST_IS_BIN (GST_MESSAGE_SRC (message))) {
GstState oldstate, newstate;
gst_message_parse_state_changed (message, &oldstate, &newstate, NULL);
GST_DEBUG_OBJECT (GST_MESSAGE_SRC (message), "state-changed: %s -> %s",
gst_element_state_get_name (oldstate),
gst_element_state_get_name (newstate));
}
break;
case GST_MESSAGE_EOS:
/* end-of-stream */
GST_INFO ("got eos() - should not happen");
g_main_loop_quit (loop);
break;
default:
/* unhandled message */
break;
}
return TRUE;
}
/*
* Helpers
*/
static void
cleanup_pipeline (void)
{
if (camera_bin) {
GST_INFO_OBJECT (camera_bin, "stopping and destroying");
gst_element_set_state (camera_bin, GST_STATE_NULL);
gst_object_unref (camera_bin);
camera_bin = NULL;
}
}
static gboolean
setup_pipeline_element (const gchar * property_name, const gchar * element_name,
GstElement ** res_elem)
{
gboolean res = TRUE;
GstElement *elem = NULL;
if (element_name) {
elem = gst_element_factory_make (element_name, NULL);
if (elem) {
g_object_set (camera_bin, property_name, elem, NULL);
} else {
GST_WARNING ("can't create element '%s' for property '%s'", element_name,
property_name);
res = FALSE;
}
} else {
GST_DEBUG ("no element for property '%s' given", property_name);
}
if (res_elem)
*res_elem = elem;
return res;
}
static GstElement *
create_audioencoder_bin (void)
{
GstElement *bin, *aenc, *filter;
GstPad *pad;
GstCaps *audio_caps;
bin = gst_bin_new ("aebin");
filter = gst_element_factory_make ("capsfilter", "aefilter");
aenc = gst_element_factory_make (audioenc_name, "aenc");
if (!g_ascii_strcasecmp (audioenc_name, "pulsesrc")) {
g_object_set (G_OBJECT (aenc),
"bitrate", audio_bitrate, "profile", 2, NULL);
}
audio_caps = gst_caps_new_simple ("audio/x-raw-int",
"channels", G_TYPE_INT, audio_channels,
"rate", G_TYPE_INT, audio_samplerate, NULL);
if (!audio_caps) {
g_warning ("error generating caps");
}
g_object_set (G_OBJECT (filter), "caps", audio_caps, NULL);
gst_caps_unref (audio_caps);
gst_bin_add_many (GST_BIN (bin), filter, aenc, NULL);
gst_element_link (filter, aenc);
pad = gst_element_get_static_pad (filter, "sink");
gst_element_add_pad (bin, gst_ghost_pad_new ("sink", pad));
gst_object_unref (GST_OBJECT (pad));
pad = gst_element_get_static_pad (aenc, "src");
gst_element_add_pad (bin, gst_ghost_pad_new ("src", pad));
gst_object_unref (GST_OBJECT (pad));
return bin;
}
static GstElement *
create_ipp_bin (void)
{
GstElement *bin = NULL, *element = NULL;
GstPad *pad = NULL;
gchar **elements;
GList *element_list = NULL, *current = NULL, *next = NULL;
int i;
bin = gst_bin_new ("ippbin");
elements = g_strsplit (imagepp_name, ",", 0);
for (i = 0; elements[i] != NULL; i++) {
element = gst_element_factory_make (elements[i], NULL);
if (element) {
element_list = g_list_append (element_list, element);
gst_bin_add (GST_BIN (bin), element);
} else
GST_WARNING ("Could create element %s for ippbin", elements[i]);
}
for (i = 1; i < g_list_length (element_list); i++) {
current = g_list_nth (element_list, i - 1);
next = g_list_nth (element_list, i);
gst_element_link (current->data, next->data);
}
current = g_list_first (element_list);
pad = gst_element_get_static_pad (current->data, "sink");
gst_element_add_pad (bin, gst_ghost_pad_new ("sink", pad));
gst_object_unref (GST_OBJECT (pad));
current = g_list_last (element_list);
pad = gst_element_get_static_pad (current->data, "src");
gst_element_add_pad (bin, gst_ghost_pad_new ("src", pad));
gst_object_unref (GST_OBJECT (pad));
g_list_free (element_list);
g_strfreev (elements);
return bin;
}
static gboolean
setup_pipeline (void)
{
GstBus *bus;
gboolean res = TRUE;
GstElement *vmux = NULL, *ienc = NULL, *sink = NULL, *aenc = NULL, *ipp =
NULL;
GstCaps *filter_caps = NULL;
camera_bin = gst_element_factory_make ("camerabin", NULL);
if (NULL == camera_bin) {
g_warning ("can't create camerabin element\n");
goto error;
}
g_object_set (camera_bin, "flags", flags, NULL);
g_signal_connect (camera_bin, "image-done", (GCallback) img_capture_done,
NULL);
bus = gst_pipeline_get_bus (GST_PIPELINE (camera_bin));
/* Add sync handler for time critical messages that need to be handled fast */
gst_bus_set_sync_handler (bus, sync_bus_callback, NULL);
/* Handle normal messages asynchronously */
gst_bus_add_watch (bus, bus_callback, NULL);
gst_object_unref (bus);
GST_INFO_OBJECT (camera_bin, "camerabin created");
/* configure used elements */
res &= setup_pipeline_element ("viewfinder-sink", vfsink_name, &sink);
res &= setup_pipeline_element ("audio-source", audiosrc_name, NULL);
res &= setup_pipeline_element ("video-source", videosrc_name, NULL);
res &= setup_pipeline_element ("video-source-filter", video_src_filter, NULL);
res &= setup_pipeline_element ("viewfinder-filter", viewfinder_filter, NULL);
if (audioenc_name) {
aenc = create_audioencoder_bin ();
if (aenc)
g_object_set (camera_bin, "audio-encoder", aenc, NULL);
else
GST_WARNING ("Could not make audio encoder element");
}
if (imagepp_name) {
ipp = create_ipp_bin ();
if (ipp)
g_object_set (camera_bin, "image-post-processing", ipp, NULL);
else
GST_WARNING ("Could not create ipp elements");
}
res &= setup_pipeline_element ("video-encoder", videoenc_name, NULL);
res &= setup_pipeline_element ("image-encoder", imageenc_name, &ienc);
res &= setup_pipeline_element ("image-formatter", imageformatter_name, NULL);
res &= setup_pipeline_element ("video-muxer", videomux_name, &vmux);
if (!res) {
goto error;
}
GST_INFO_OBJECT (camera_bin, "elements created");
/* set properties */
if (src_format) {
filter_caps = gst_caps_from_string (src_format);
} else if (src_csp) {
/* Set requested colorspace format, this is needed if the default
colorspace negotiated for viewfinder doesn't match with e.g. encoders. */
filter_caps = gst_caps_new_simple ("video/x-raw",
"format", G_TYPE_STRING, src_csp, NULL);
}
if (filter_caps) {
g_object_set (camera_bin, "filter-caps", filter_caps, NULL);
gst_caps_unref (filter_caps);
}
g_object_set (sink, "sync", TRUE, NULL);
GST_INFO_OBJECT (camera_bin, "elements configured");
/* configure a resolution and framerate */
if (mode == 1) {
g_signal_emit_by_name (camera_bin, "set-video-resolution-fps", image_width,
image_height, view_framerate_num, view_framerate_den, NULL);
} else {
g_signal_emit_by_name (camera_bin, "set-image-resolution", image_width,
image_height, NULL);
}
if (GST_STATE_CHANGE_FAILURE ==
gst_element_set_state (camera_bin, GST_STATE_READY)) {
g_warning ("can't set camerabin to ready\n");
goto error;
}
GST_INFO_OBJECT (camera_bin, "camera ready");
if (GST_STATE_CHANGE_FAILURE ==
gst_element_set_state (camera_bin, GST_STATE_PLAYING)) {
g_warning ("can't set camerabin to playing\n");
goto error;
}
GST_INFO_OBJECT (camera_bin, "camera started");
return TRUE;
error:
cleanup_pipeline ();
return FALSE;
}
static gboolean
stop_capture (gpointer user_data)
{
g_signal_emit_by_name (camera_bin, "capture-stop", 0);
if (capture_count < capture_total) {
g_idle_add ((GSourceFunc) run_pipeline, NULL);
} else {
g_main_loop_quit (loop);
}
return FALSE;
}
static void
set_metadata (GstElement * camera)
{
GstTagSetter *setter = GST_TAG_SETTER (camera);
GTimeVal time = { 0, 0 };
gchar *desc_str;
GDate *date = g_date_new ();
g_get_current_time (&time);
g_date_set_time_val (date, &time);
desc_str = g_strdup_printf ("captured by %s", g_get_real_name ());
gst_tag_setter_add_tags (setter, GST_TAG_MERGE_REPLACE,
GST_TAG_DATE, date,
GST_TAG_DESCRIPTION, desc_str,
GST_TAG_TITLE, "gst-camerabin-test capture",
GST_TAG_GEO_LOCATION_LONGITUDE, 1.0,
GST_TAG_GEO_LOCATION_LATITUDE, 2.0,
GST_TAG_GEO_LOCATION_ELEVATION, 3.0,
GST_TAG_DEVICE_MANUFACTURER, "gst-camerabin-test manufacturer",
GST_TAG_DEVICE_MODEL, "gst-camerabin-test model", NULL);
g_free (desc_str);
g_date_free (date);
}
static gboolean
run_pipeline (gpointer user_data)
{
GstCaps *preview_caps = NULL;
gchar *filename_str = NULL;
GstElement *video_source = NULL;
const gchar *filename_suffix;
g_object_set (camera_bin, "mode", mode, NULL);
if (preview_caps_name != NULL) {
preview_caps = gst_caps_from_string (preview_caps_name);
if (preview_caps) {
g_object_set (camera_bin, "preview-caps", preview_caps, NULL);
GST_DEBUG ("Preview caps set");
} else
GST_DEBUG ("Preview caps set but could not create caps from string");
}
set_metadata (camera_bin);
/* Construct filename */
if (mode == 1)
filename_suffix = ".mp4";
else
filename_suffix = ".jpg";
filename_str =
g_strdup_printf ("%s/test_%04u%s", filename->str, capture_count,
filename_suffix);
GST_DEBUG ("Setting filename: %s", filename_str);
g_object_set (camera_bin, "filename", filename_str, NULL);
g_free (filename_str);
g_object_get (camera_bin, "video-source", &video_source, NULL);
if (video_source) {
if (GST_IS_ELEMENT (video_source) && GST_IS_PHOTOGRAPHY (video_source)) {
/* Set GstPhotography interface options. If option not given as
command-line parameter use default of the source element. */
if (scene_mode != SCENE_MODE_NONE)
g_object_set (video_source, "scene-mode", scene_mode, NULL);
if (ev_compensation != EV_COMPENSATION_NONE)
g_object_set (video_source, "ev-compensation", ev_compensation, NULL);
if (aperture != APERTURE_NONE)
g_object_set (video_source, "aperture", aperture, NULL);
if (flash_mode != FLASH_MODE_NONE)
g_object_set (video_source, "flash-mode", flash_mode, NULL);
if (exposure != EXPOSURE_NONE)
g_object_set (video_source, "exposure", exposure, NULL);
if (iso_speed != ISO_SPEED_NONE)
g_object_set (video_source, "iso-speed", iso_speed, NULL);
if (wb_mode != WHITE_BALANCE_MODE_NONE)
g_object_set (video_source, "white-balance-mode", wb_mode, NULL);
if (color_mode != COLOR_TONE_MODE_NONE)
g_object_set (video_source, "colour-tone-mode", color_mode, NULL);
}
g_object_unref (video_source);
}
g_object_set (camera_bin, "mute", mute, NULL);
g_object_set (camera_bin, "zoom", zoom / 100.0f, NULL);
capture_count++;
g_timer_start (timer);
g_signal_emit_by_name (camera_bin, "capture-start", 0);
if (mode == 1) {
g_timeout_add ((capture_time * 1000), (GSourceFunc) stop_capture, NULL);
}
return FALSE;
}
int
main (int argc, char *argv[])
{
gchar *target_times = NULL;
gchar *ev_option = NULL;
gchar *fn_option = NULL;
GOptionEntry options[] = {
{"ev-compensation", '\0', G_OPTION_FLAG_OPTIONAL_ARG, G_OPTION_ARG_STRING,
&ev_option,
"EV compensation for source element GstPhotography interface", NULL},
{"aperture", '\0', G_OPTION_FLAG_OPTIONAL_ARG, G_OPTION_ARG_INT, &aperture,
"Aperture (size of lens opening) for source element GstPhotography interface",
NULL},
{"flash-mode", '\0', G_OPTION_FLAG_OPTIONAL_ARG, G_OPTION_ARG_INT,
&flash_mode,
"Flash mode for source element GstPhotography interface", NULL},
{"scene-mode", '\0', G_OPTION_FLAG_OPTIONAL_ARG, G_OPTION_ARG_INT,
&scene_mode,
"Scene mode for source element GstPhotography interface", NULL},
{"exposure", '\0', G_OPTION_FLAG_OPTIONAL_ARG, G_OPTION_ARG_INT64,
&exposure,
"Exposure time (in ms) for source element GstPhotography interface",
NULL},
{"iso-speed", '\0', G_OPTION_FLAG_OPTIONAL_ARG, G_OPTION_ARG_INT,
&iso_speed,
"ISO speed for source element GstPhotography interface", NULL},
{"white-balance-mode", '\0', G_OPTION_FLAG_OPTIONAL_ARG, G_OPTION_ARG_INT,
&wb_mode,
"White balance mode for source element GstPhotography interface", NULL},
{"colour-tone-mode", '\0', G_OPTION_FLAG_OPTIONAL_ARG, G_OPTION_ARG_INT,
&color_mode,
"Colour tone mode for source element GstPhotography interface", NULL},
{"directory", '\0', 0, G_OPTION_ARG_STRING, &fn_option,
"Directory for capture file(s) (default is current directory)", NULL},
{"mode", '\0', G_OPTION_FLAG_OPTIONAL_ARG, G_OPTION_ARG_INT, &mode,
"Capture mode (default = 0 (image), 1 = video)", NULL},
{"capture-time", '\0', G_OPTION_FLAG_OPTIONAL_ARG, G_OPTION_ARG_INT,
&capture_time,
"Time to capture video in seconds (default = 10)", NULL},
{"capture-total", '\0', 0, G_OPTION_ARG_INT, &capture_total,
"Total number of captures to be done (default = 1)", NULL},
{"flags", '\0', G_OPTION_FLAG_OPTIONAL_ARG, G_OPTION_ARG_INT, &flags,
"Flags for camerabin, (default = 0x9)", NULL},
{"mute", '\0', G_OPTION_FLAG_OPTIONAL_ARG, G_OPTION_ARG_NONE, &mute,
"Mute audio", NULL},
{"zoom", '\0', G_OPTION_FLAG_OPTIONAL_ARG, G_OPTION_ARG_INT, &zoom,
"Zoom (100 = 1x (default), 200 = 2x etc.)", NULL},
{"audio-src", '\0', 0, G_OPTION_ARG_STRING, &audiosrc_name,
"Audio source used in video recording", NULL},
{"audio-bitrate", '\0', 0, G_OPTION_ARG_INT, &audio_bitrate,
"Audio bitrate (default 128000)", NULL},
{"audio-samplerate", '\0', 0, G_OPTION_ARG_INT, &audio_samplerate,
"Audio samplerate (default 48000)", NULL},
{"audio-channels", '\0', 0, G_OPTION_ARG_INT, &audio_channels,
"Audio channels (default 1)", NULL},
{"video-src", '\0', 0, G_OPTION_ARG_STRING, &videosrc_name,
"Video source used in still capture and video recording", NULL},
{"audio-enc", '\0', 0, G_OPTION_ARG_STRING, &audioenc_name,
"Audio encoder used in video recording", NULL},
{"video-enc", '\0', 0, G_OPTION_ARG_STRING, &videoenc_name,
"Video encoder used in video recording", NULL},
{"image-enc", '\0', 0, G_OPTION_ARG_STRING, &imageenc_name,
"Image encoder used in still capture", NULL},
{"image-pp", '\0', 0, G_OPTION_ARG_STRING, &imagepp_name,
"List of image post-processing elements separated with comma", NULL},
{"image-formatter", '\0', 0, G_OPTION_ARG_STRING, &imageformatter_name,
"Image metadata formatter used in still image capture", NULL},
{"video-mux", '\0', 0, G_OPTION_ARG_STRING, &videomux_name,
"Muxer used in video recording", NULL},
{"viewfinder-sink", '\0', 0, G_OPTION_ARG_STRING, &vfsink_name,
"Viewfinder sink (default = fakesink)", NULL},
{"image-width", '\0', 0, G_OPTION_ARG_INT, &image_width,
"Width for image capture", NULL},
{"image-height", '\0', 0, G_OPTION_ARG_INT, &image_height,
"Height for image capture", NULL},
{"view-framerate-num", '\0', 0, G_OPTION_ARG_INT, &view_framerate_num,
"Framerate numerator for viewfinder", NULL},
{"view-framerate-den", '\0', 0, G_OPTION_ARG_INT, &view_framerate_den,
"Framerate denominator for viewfinder", NULL},
{"src-colorspace", '\0', 0, G_OPTION_ARG_STRING, &src_csp,
"Colorspace format for video source (e.g. YUY2, UYVY)", NULL},
{"src-format", '\0', 0, G_OPTION_ARG_STRING, &src_format,
"Video format for video source", NULL},
{"preview-caps", '\0', 0, G_OPTION_ARG_STRING, &preview_caps_name,
"Preview caps (e.g. video/x-raw-rgb,width=320,height=240)", NULL},
{"video-source-filter", '\0', 0, G_OPTION_ARG_STRING, &video_src_filter,
"Video filter to process all frames from video source", NULL},
{"viewfinder-filter", '\0', 0, G_OPTION_ARG_STRING, &viewfinder_filter,
"Filter to process all frames going to viewfinder sink", NULL},
{"x-width", '\0', 0, G_OPTION_ARG_INT, &x_width,
"X window width (default = 320)", NULL},
{"x-height", '\0', 0, G_OPTION_ARG_INT, &x_height,
"X window height (default = 240)", NULL},
{"no-xwindow", '\0', 0, G_OPTION_ARG_NONE, &no_xwindow,
"Do not create XWindow", NULL},
{NULL}
};
GOptionContext *ctx;
GError *err = NULL;
ctx = g_option_context_new ("\n\ncamerabin command line test application.");
g_option_context_add_main_entries (ctx, options, NULL);
g_option_context_add_group (ctx, gst_init_get_option_group ());
if (!g_option_context_parse (ctx, &argc, &argv, &err)) {
g_print ("Error initializing: %s\n", err->message);
exit (1);
}
g_option_context_free (ctx);
/* if we fail to create xwindow should we care? */
if (!no_xwindow)
create_host_window ();
GST_DEBUG_CATEGORY_INIT (camerabin_test, "camerabin-test", 0,
"camerabin test");
/* FIXME: error handling */
if (ev_option != NULL)
ev_compensation = strtod (ev_option, (char **) NULL);
if (vfsink_name == NULL)
vfsink_name = g_strdup ("fakesink");
filename = g_string_new (fn_option);
if (filename->len == 0)
filename = g_string_append (filename, ".");
timer = g_timer_new ();
/* init */
if (setup_pipeline ()) {
loop = g_main_loop_new (NULL, FALSE);
g_idle_add ((GSourceFunc) run_pipeline, NULL);
g_main_loop_run (loop);
cleanup_pipeline ();
g_main_loop_unref (loop);
}
/* free */
g_string_free (filename, TRUE);
g_free (ev_option);
g_free (audiosrc_name);
g_free (videosrc_name);
g_free (audioenc_name);
g_free (videoenc_name);
g_free (imageenc_name);
g_free (imageformatter_name);
g_free (imagepp_name);
g_free (videomux_name);
g_free (vfsink_name);
g_free (src_csp);
g_free (src_format);
g_free (target_times);
g_timer_destroy (timer);
if (window)
XDestroyWindow (display, window);
if (display)
XCloseDisplay (display);
return 0;
}