mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-28 19:20:35 +00:00
Remove old camerabin
This commit is contained in:
parent
da001be15a
commit
7d65470c4a
39 changed files with 1315 additions and 15689 deletions
|
@ -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
|
||||
|
|
|
@ -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 \
|
||||
|
|
|
@ -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" />
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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 <multimedia@maemo.org>, Edgard Lima <edgard.lima@indt.org.br></author>
|
||||
<pads>
|
||||
</pads>
|
||||
</element>
|
||||
</elements>
|
||||
</plugin>
|
|
@ -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 <thiago.sousa.santos@collabora.co.uk></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 <thiago.sousa.santos@collabora.com></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 <thiago.sousa.santos@collabora.com></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>
|
2
gst/camerabin/.gitignore
vendored
2
gst/camerabin/.gitignore
vendored
|
@ -1,2 +0,0 @@
|
|||
gstcamerabin-marshal.c
|
||||
gstcamerabin-marshal.h
|
|
@ -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' \
|
||||
> $@
|
|
@ -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
|
|
@ -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_ */
|
|
@ -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;
|
||||
}
|
|
@ -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_ */
|
|
@ -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;
|
||||
}
|
|
@ -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__ */
|
|
@ -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);
|
||||
}
|
|
@ -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__ */
|
|
@ -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;
|
||||
}
|
|
@ -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__ */
|
|
@ -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;
|
||||
}
|
|
@ -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__ */
|
|
@ -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
|
@ -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__ */
|
|
@ -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;
|
||||
}
|
|
@ -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
|
@ -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__ */
|
|
@ -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
|
@ -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
|
||||
|
|
4
tests/examples/camerabin/.gitignore
vendored
4
tests/examples/camerabin/.gitignore
vendored
|
@ -1,4 +0,0 @@
|
|||
gst-camera
|
||||
gst-camera-perf
|
||||
gst-camerabin-test
|
||||
test_*.jpg
|
|
@ -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
|
@ -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
|
@ -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__ */
|
|
@ -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>
|
|
@ -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;
|
||||
}
|
Loading…
Reference in a new issue