mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-24 02:31:03 +00:00
camerabin: add flags property. Fixes #573370 (partially)
Adds flags property to enable runtime configuration of conversion and scaling elements. Also adds flag for disabling audio completely.
This commit is contained in:
parent
7d65643656
commit
7dac3659c6
9 changed files with 400 additions and 182 deletions
|
@ -20,7 +20,8 @@ libgstcamerabin_la_SOURCES = gstcamerabin.c \
|
|||
camerabinvideo.c \
|
||||
camerabingeneral.c \
|
||||
camerabinpreview.c \
|
||||
gstcamerabinphotography.c
|
||||
gstcamerabinphotography.c \
|
||||
gstcamerabin-enum.c
|
||||
|
||||
nodist_libgstcamerabin_la_SOURCES = $(built_sources)
|
||||
libgstcamerabin_la_CFLAGS = \
|
||||
|
@ -41,4 +42,5 @@ noinst_HEADERS = gstcamerabin.h \
|
|||
camerabinvideo.h \
|
||||
camerabingeneral.h \
|
||||
camerabinpreview.h \
|
||||
gstcamerabinphotography.h
|
||||
gstcamerabinphotography.h \
|
||||
gstcamerabin-enum.h
|
||||
|
|
|
@ -52,6 +52,7 @@
|
|||
|
||||
#include "camerabinimage.h"
|
||||
#include "camerabingeneral.h"
|
||||
#include "gstcamerabin-enum.h"
|
||||
|
||||
#include "string.h"
|
||||
|
||||
|
@ -60,6 +61,7 @@
|
|||
#define DEFAULT_SINK "filesink"
|
||||
#define DEFAULT_ENC "jpegenc"
|
||||
#define DEFAULT_META_MUX "metadatamux"
|
||||
#define DEFAULT_FLAGS GST_CAMERABIN_FLAG_IMAGE_COLOR_CONVERSION
|
||||
|
||||
enum
|
||||
{
|
||||
|
@ -157,6 +159,7 @@ gst_camerabin_image_init (GstCameraBinImage * img,
|
|||
gst_element_add_pad (GST_ELEMENT (img), img->sinkpad);
|
||||
|
||||
img->elements_created = FALSE;
|
||||
img->flags = DEFAULT_FLAGS;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -425,17 +428,15 @@ gst_camerabin_image_create_elements (GstCameraBinImage * img)
|
|||
img_sinkpad = gst_element_get_static_pad (img->post, "sink");
|
||||
}
|
||||
|
||||
/* Add colorspace converter */
|
||||
if (!(csp =
|
||||
gst_camerabin_create_and_add_element (imgbin, "ffmpegcolorspace"))) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Set up sink ghost pad for img bin */
|
||||
if (!img_sinkpad) {
|
||||
if (img->flags & GST_CAMERABIN_FLAG_IMAGE_COLOR_CONVERSION) {
|
||||
/* Add colorspace converter */
|
||||
if (!(csp =
|
||||
gst_camerabin_create_and_add_element (imgbin,
|
||||
"ffmpegcolorspace"))) {
|
||||
goto done;
|
||||
}
|
||||
img_sinkpad = gst_element_get_static_pad (csp, "sink");
|
||||
}
|
||||
gst_ghost_pad_set_target (GST_GHOST_PAD (img->sinkpad), img_sinkpad);
|
||||
|
||||
/* Create image encoder */
|
||||
if (img->user_enc) {
|
||||
|
@ -471,6 +472,12 @@ gst_camerabin_image_create_elements (GstCameraBinImage * img)
|
|||
g_object_set (G_OBJECT (img->sink), "location", img->filename->str, "async", FALSE, "buffer-mode", 2, /* non buffered io */
|
||||
NULL);
|
||||
|
||||
/* Set up sink ghost pad for image bin */
|
||||
if (!img_sinkpad) {
|
||||
img_sinkpad = gst_element_get_static_pad (img->enc, "sink");
|
||||
}
|
||||
gst_ghost_pad_set_target (GST_GHOST_PAD (img->sinkpad), img_sinkpad);
|
||||
|
||||
ret = TRUE;
|
||||
|
||||
done:
|
||||
|
@ -535,6 +542,13 @@ gst_camerabin_image_set_postproc (GstCameraBinImage * img,
|
|||
img->post = postproc;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
|
|
|
@ -23,6 +23,8 @@
|
|||
|
||||
#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))
|
||||
|
@ -53,6 +55,7 @@ struct _GstCameraBinImage
|
|||
GstElement *sink;
|
||||
|
||||
gboolean elements_created;
|
||||
GstCameraBinFlags flags;
|
||||
};
|
||||
|
||||
struct _GstCameraBinImageClass
|
||||
|
@ -69,6 +72,10 @@ void
|
|||
gst_camerabin_image_set_postproc (GstCameraBinImage * img,
|
||||
GstElement * postproc);
|
||||
|
||||
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);
|
||||
|
|
|
@ -71,7 +71,7 @@
|
|||
#define DEFAULT_MUX "oggmux"
|
||||
#define DEFAULT_SINK "filesink"
|
||||
|
||||
#define USE_AUDIO_CONVERSION 1
|
||||
#define DEFAULT_FLAGS 0
|
||||
|
||||
enum
|
||||
{
|
||||
|
@ -187,6 +187,7 @@ gst_camerabin_video_init (GstCameraBinVideo * vid,
|
|||
vid->pending_eos = NULL;
|
||||
|
||||
vid->mute = ARG_DEFAULT_MUTE;
|
||||
vid->flags = DEFAULT_FLAGS;
|
||||
|
||||
vid->aud_src_probe_id = 0;
|
||||
vid->vid_src_probe_id = 0;
|
||||
|
@ -571,6 +572,7 @@ gst_camerabin_video_create_elements (GstCameraBinVideo * vid)
|
|||
|
||||
/* Add queue element for video */
|
||||
vid->tee_video_srcpad = gst_element_get_request_pad (vid->tee, "src%d");
|
||||
|
||||
if (!(vid->video_queue =
|
||||
gst_camerabin_create_and_add_element (vidbin, "queue"))) {
|
||||
goto error;
|
||||
|
@ -610,57 +612,59 @@ gst_camerabin_video_create_elements (GstCameraBinVideo * vid)
|
|||
g_object_set (G_OBJECT (vid->sink), "location", vid->filename->str, "buffer-mode", 2, /* non buffered io */
|
||||
NULL);
|
||||
|
||||
/* Add user set or default audio source element */
|
||||
if (!(vid->aud_src = gst_camerabin_setup_default_element (vidbin,
|
||||
vid->user_aud_src, "autoaudiosrc", DEFAULT_AUDIOSRC))) {
|
||||
vid->aud_src = NULL;
|
||||
goto error;
|
||||
} else {
|
||||
if (!gst_camerabin_add_element (vidbin, vid->aud_src))
|
||||
if (!(vid->flags & GST_CAMERABIN_FLAG_DISABLE_AUDIO)) {
|
||||
/* Add user set or default audio source element */
|
||||
if (!(vid->aud_src = gst_camerabin_setup_default_element (vidbin,
|
||||
vid->user_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 */
|
||||
if (!(gst_camerabin_create_and_add_element (vidbin, "queue"))) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* Add optional audio conversion and volume elements and
|
||||
raise no errors if adding them fails */
|
||||
#ifdef USE_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 */
|
||||
}
|
||||
#endif
|
||||
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 user set or default audio encoder element */
|
||||
if (vid->user_aud_enc) {
|
||||
vid->aud_enc = vid->user_aud_enc;
|
||||
if (!gst_camerabin_add_element (vidbin, vid->aud_enc)) {
|
||||
/* Add queue element for audio */
|
||||
if (!(gst_camerabin_create_and_add_element (vidbin, "queue"))) {
|
||||
goto error;
|
||||
}
|
||||
} else if (!(vid->aud_enc =
|
||||
gst_camerabin_create_and_add_element (vidbin, DEFAULT_AUD_ENC))) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* Link audio part to the muxer */
|
||||
if (!gst_element_link (vid->aud_enc, vid->muxer)) {
|
||||
GST_ELEMENT_ERROR (vid, CORE, NEGOTIATION, (NULL),
|
||||
("linking audio encoder and muxer failed"));
|
||||
goto error;
|
||||
}
|
||||
/* 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 user set or default audio encoder element */
|
||||
if (vid->user_aud_enc) {
|
||||
vid->aud_enc = vid->user_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))) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* Link audio part to the muxer */
|
||||
if (!gst_element_link (vid->aud_enc, vid->muxer)) {
|
||||
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%d");
|
||||
if (!(queue = gst_camerabin_create_and_add_element (vidbin, "queue"))) {
|
||||
|
@ -678,11 +682,12 @@ gst_camerabin_video_create_elements (GstCameraBinVideo * vid)
|
|||
G_CALLBACK (gst_camerabin_drop_eos_probe), vid);
|
||||
gst_object_unref (vid_srcpad);
|
||||
|
||||
pad = gst_element_get_static_pad (vid->aud_src, "src");
|
||||
vid->aud_src_probe_id = gst_pad_add_buffer_probe (pad,
|
||||
G_CALLBACK (camerabin_video_pad_aud_src_have_buffer), vid);
|
||||
gst_object_unref (pad);
|
||||
|
||||
if (!(vid->flags & GST_CAMERABIN_FLAG_DISABLE_AUDIO)) {
|
||||
pad = gst_element_get_static_pad (vid->aud_src, "src");
|
||||
vid->aud_src_probe_id = gst_pad_add_buffer_probe (pad,
|
||||
G_CALLBACK (camerabin_video_pad_aud_src_have_buffer), vid);
|
||||
gst_object_unref (pad);
|
||||
}
|
||||
GST_DEBUG ("created video elements");
|
||||
|
||||
return TRUE;
|
||||
|
@ -841,6 +846,16 @@ gst_camerabin_video_set_audio_src (GstCameraBinVideo * vid,
|
|||
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)
|
||||
{
|
||||
|
|
|
@ -23,6 +23,8 @@
|
|||
|
||||
#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())
|
||||
|
@ -88,6 +90,7 @@ struct _GstCameraBinVideo
|
|||
gulong vid_sink_probe_id;
|
||||
|
||||
gboolean mute;
|
||||
GstCameraBinFlags flags;
|
||||
};
|
||||
|
||||
struct _GstCameraBinVideoClass
|
||||
|
@ -120,6 +123,10 @@ 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);
|
||||
|
||||
|
|
59
gst/camerabin/gstcamerabin-enum.c
Normal file
59
gst/camerabin/gstcamerabin-enum.c
Normal file
|
@ -0,0 +1,59 @@
|
|||
/*
|
||||
* 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"},
|
||||
{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;
|
||||
}
|
60
gst/camerabin/gstcamerabin-enum.h
Normal file
60
gst/camerabin/gstcamerabin-enum.h
Normal file
|
@ -0,0 +1,60 @@
|
|||
/*
|
||||
* 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
|
||||
/**
|
||||
* 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
|
||||
*
|
||||
* 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)
|
||||
} 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__ */
|
|
@ -190,6 +190,7 @@ enum
|
|||
ARG_0,
|
||||
ARG_FILENAME,
|
||||
ARG_MODE,
|
||||
ARG_FLAGS,
|
||||
ARG_MUTE,
|
||||
ARG_ZOOM,
|
||||
ARG_IMAGE_POST,
|
||||
|
@ -229,6 +230,10 @@ static guint camerabin_signals[LAST_SIGNAL];
|
|||
#define CAMERABIN_MAX_VF_WIDTH 848
|
||||
#define CAMERABIN_MAX_VF_HEIGHT 848
|
||||
|
||||
#define DEFAULT_FLAGS GST_CAMERABIN_FLAG_SOURCE_RESIZE | \
|
||||
GST_CAMERABIN_FLAG_VIEWFINDER_SCALE | \
|
||||
GST_CAMERABIN_FLAG_IMAGE_COLOR_CONVERSION
|
||||
|
||||
/* Using "bilinear" as default zoom method */
|
||||
#define CAMERABIN_DEFAULT_ZOOM_METHOD 1
|
||||
|
||||
|
@ -239,10 +244,6 @@ static guint camerabin_signals[LAST_SIGNAL];
|
|||
/* FIXME: this is v4l2camsrc specific */
|
||||
#define DEFAULT_V4L2CAMSRC_DRIVER_NAME "omap3cam"
|
||||
|
||||
/* pipeline configuration */
|
||||
//#define USE_VIEWFINDER_COLOR_CONVERTER 1
|
||||
//#define USE_VIEWFINDER_SCALE 1
|
||||
|
||||
/* message names */
|
||||
#define PREVIEW_MESSAGE_NAME "preview-image"
|
||||
#define IMG_CAPTURED_MESSAGE_NAME "image-captured"
|
||||
|
@ -267,6 +268,9 @@ static void camerabin_dispose_elements (GstCameraBin * camera);
|
|||
|
||||
static void gst_camerabin_change_mode (GstCameraBin * camera, gint mode);
|
||||
|
||||
static void
|
||||
gst_camerabin_set_flags (GstCameraBin * camera, GstCameraBinFlags flags);
|
||||
|
||||
static void
|
||||
gst_camerabin_change_filename (GstCameraBin * camera, const gchar * name);
|
||||
|
||||
|
@ -393,6 +397,7 @@ gst_camerabin_mode_get_type (void)
|
|||
return gtype;
|
||||
}
|
||||
|
||||
|
||||
static gboolean
|
||||
gst_camerabin_iface_supported (GstImplementsInterface * iface, GType iface_type)
|
||||
{
|
||||
|
@ -542,9 +547,10 @@ camerabin_setup_src_elements (GstCameraBin * camera)
|
|||
}
|
||||
|
||||
/* Set default zoom method */
|
||||
g_object_set (camera->src_zoom_scale, "method",
|
||||
CAMERABIN_DEFAULT_ZOOM_METHOD, NULL);
|
||||
|
||||
if (camera->src_zoom_scale) {
|
||||
g_object_set (camera->src_zoom_scale, "method",
|
||||
CAMERABIN_DEFAULT_ZOOM_METHOD, NULL);
|
||||
}
|
||||
/* we create new caps in any way and they take ownership of the structure st */
|
||||
gst_caps_replace (&camera->view_finder_caps, new_caps);
|
||||
gst_caps_unref (new_caps);
|
||||
|
@ -578,22 +584,24 @@ camerabin_create_src_elements (GstCameraBin * camera)
|
|||
if (!gst_camerabin_add_element (cbin, camera->src_vid_src))
|
||||
goto done;
|
||||
}
|
||||
#ifdef USE_COLOR_CONVERTER
|
||||
if (!gst_camerabin_create_and_add_element (cbin, "ffmpegcolorspace"))
|
||||
goto done;
|
||||
#endif
|
||||
if (camera->flags & GST_CAMERABIN_FLAG_SOURCE_COLOR_CONVERSION) {
|
||||
if (!gst_camerabin_create_and_add_element (cbin, "ffmpegcolorspace"))
|
||||
goto done;
|
||||
}
|
||||
if (!(camera->src_filter =
|
||||
gst_camerabin_create_and_add_element (cbin, "capsfilter")))
|
||||
goto done;
|
||||
if (!(camera->src_zoom_crop =
|
||||
gst_camerabin_create_and_add_element (cbin, "videocrop")))
|
||||
goto done;
|
||||
if (!(camera->src_zoom_scale =
|
||||
gst_camerabin_create_and_add_element (cbin, "videoscale")))
|
||||
goto done;
|
||||
if (!(camera->src_zoom_filter =
|
||||
gst_camerabin_create_and_add_element (cbin, "capsfilter")))
|
||||
goto done;
|
||||
if (camera->flags & GST_CAMERABIN_FLAG_SOURCE_RESIZE) {
|
||||
if (!(camera->src_zoom_crop =
|
||||
gst_camerabin_create_and_add_element (cbin, "videocrop")))
|
||||
goto done;
|
||||
if (!(camera->src_zoom_scale =
|
||||
gst_camerabin_create_and_add_element (cbin, "videoscale")))
|
||||
goto done;
|
||||
if (!(camera->src_zoom_filter =
|
||||
gst_camerabin_create_and_add_element (cbin, "capsfilter")))
|
||||
goto done;
|
||||
}
|
||||
if (!(camera->src_out_sel =
|
||||
gst_camerabin_create_and_add_element (cbin, "output-selector")))
|
||||
goto done;
|
||||
|
@ -671,24 +679,24 @@ camerabin_create_view_elements (GstCameraBin * camera)
|
|||
}
|
||||
camera->pad_view_src = GST_PAD (pads->data);
|
||||
|
||||
#ifdef USE_VIEWFINDER_CONVERTERS
|
||||
/* Add videoscale in case we need to downscale frame for view finder */
|
||||
if (!(camera->view_scale =
|
||||
gst_camerabin_create_and_add_element (cbin, "videoscale"))) {
|
||||
goto error;
|
||||
}
|
||||
if (camera->flags & GST_CAMERABIN_FLAG_VIEWFINDER_SCALE) {
|
||||
if (!(camera->view_scale =
|
||||
gst_camerabin_create_and_add_element (cbin, "videoscale"))) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* Add capsfilter to maintain aspect ratio while scaling */
|
||||
if (!(camera->aspect_filter =
|
||||
gst_camerabin_create_and_add_element (cbin, "capsfilter"))) {
|
||||
goto error;
|
||||
/* Add capsfilter to maintain aspect ratio while scaling */
|
||||
if (!(camera->aspect_filter =
|
||||
gst_camerabin_create_and_add_element (cbin, "capsfilter"))) {
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_VIEWFINDER_COLOR_CONVERTER
|
||||
if (!gst_camerabin_create_and_add_element (cbin, "ffmpegcolorspace")) {
|
||||
goto error;
|
||||
if (camera->flags & GST_CAMERABIN_FLAG_VIEWFINDER_COLOR_CONVERSION) {
|
||||
if (!gst_camerabin_create_and_add_element (cbin, "ffmpegcolorspace")) {
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
/* Add user set or default video sink element */
|
||||
if (!(camera->view_sink = gst_camerabin_setup_default_element (cbin,
|
||||
camera->user_vf_sink, "autovideosink", DEFAULT_VIDEOSINK))) {
|
||||
|
@ -982,6 +990,28 @@ gst_camerabin_change_mode (GstCameraBin * camera, gint mode)
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* gst_camerabin_set_flags:
|
||||
* @camera: camerabin object
|
||||
* @flags: flags for camerabin, videobin and imagebin
|
||||
*
|
||||
* Change camerabin capture flags.
|
||||
*/
|
||||
static void
|
||||
gst_camerabin_set_flags (GstCameraBin * camera, GstCameraBinFlags flags)
|
||||
{
|
||||
g_return_if_fail (camera != NULL);
|
||||
|
||||
GST_DEBUG_OBJECT (camera, "setting flags: %d", flags);
|
||||
|
||||
GST_OBJECT_LOCK (camera);
|
||||
camera->flags = flags;
|
||||
GST_OBJECT_UNLOCK (camera);
|
||||
|
||||
gst_camerabin_video_set_flags (GST_CAMERABIN_VIDEO (camera->vidbin), flags);
|
||||
gst_camerabin_image_set_flags (GST_CAMERABIN_IMAGE (camera->imgbin), flags);
|
||||
}
|
||||
|
||||
/*
|
||||
* gst_camerabin_change_filename:
|
||||
* @camera: camerabin object
|
||||
|
@ -1407,7 +1437,8 @@ gst_camerabin_set_capsfilter_caps (GstCameraBin * camera, GstCaps * new_caps)
|
|||
|
||||
/* Update capsfilters */
|
||||
g_object_set (G_OBJECT (camera->src_filter), "caps", new_caps, NULL);
|
||||
g_object_set (G_OBJECT (camera->src_zoom_filter), "caps", new_caps, NULL);
|
||||
if (camera->src_zoom_filter)
|
||||
g_object_set (G_OBJECT (camera->src_zoom_filter), "caps", new_caps, NULL);
|
||||
gst_camerabin_update_aspect_filter (camera, new_caps);
|
||||
}
|
||||
|
||||
|
@ -1456,27 +1487,29 @@ gst_camerabin_adapt_video_resolution (GstCameraBin * camera, GstCaps * caps)
|
|||
/* Crop if requested aspect ratio differs from incoming frame aspect ratio */
|
||||
|
||||
/* Don't override original crop values in case we have zoom applied */
|
||||
g_object_get (G_OBJECT (camera->src_zoom_crop), "top", &top, "bottom",
|
||||
&bottom, "left", &left, "right", &right, NULL);
|
||||
if (camera->src_zoom_crop) {
|
||||
g_object_get (G_OBJECT (camera->src_zoom_crop), "top", &top, "bottom",
|
||||
&bottom, "left", &left, "right", &right, NULL);
|
||||
|
||||
ratio_w = (gdouble) width / camera->width;
|
||||
ratio_h = (gdouble) height / camera->height;
|
||||
ratio_w = (gdouble) width / camera->width;
|
||||
ratio_h = (gdouble) height / camera->height;
|
||||
|
||||
if (ratio_w < ratio_h) {
|
||||
crop = height - (camera->height * ratio_w);
|
||||
top += crop / 2;
|
||||
bottom += crop / 2;
|
||||
} else {
|
||||
crop = width - (camera->width * ratio_h);
|
||||
left += crop / 2;
|
||||
right += crop / 2;
|
||||
if (ratio_w < ratio_h) {
|
||||
crop = height - (camera->height * ratio_w);
|
||||
top += crop / 2;
|
||||
bottom += crop / 2;
|
||||
} else {
|
||||
crop = width - (camera->width * ratio_h);
|
||||
left += crop / 2;
|
||||
right += crop / 2;
|
||||
}
|
||||
|
||||
GST_INFO_OBJECT (camera,
|
||||
"updating crop: left:%d, right:%d, top:%d, bottom:%d", left, right, top,
|
||||
bottom);
|
||||
g_object_set (G_OBJECT (camera->src_zoom_crop), "top", top, "bottom",
|
||||
bottom, "left", left, "right", right, NULL);
|
||||
}
|
||||
|
||||
GST_INFO_OBJECT (camera,
|
||||
"updating crop: left:%d, right:%d, top:%d, bottom:%d", left, right, top,
|
||||
bottom);
|
||||
g_object_set (G_OBJECT (camera->src_zoom_crop), "top", top, "bottom", bottom,
|
||||
"left", left, "right", right, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -2227,79 +2260,79 @@ gst_camerabin_find_better_framerate (GstCameraBin * camera, GstStructure * st,
|
|||
static void
|
||||
gst_camerabin_update_aspect_filter (GstCameraBin * camera, GstCaps * new_caps)
|
||||
{
|
||||
#ifdef USE_VIEWFINDER_SCALE
|
||||
GstCaps *sink_caps, *ar_caps;
|
||||
GstStructure *st;
|
||||
gint in_w = 0, in_h = 0, sink_w = 0, sink_h = 0, target_w = 0, target_h = 0;
|
||||
gdouble ratio_w, ratio_h;
|
||||
GstPad *sink_pad;
|
||||
const GValue *range;
|
||||
if (camera->flags & GST_CAMERABIN_FLAG_VIEWFINDER_SCALE) {
|
||||
GstCaps *sink_caps, *ar_caps;
|
||||
GstStructure *st;
|
||||
gint in_w = 0, in_h = 0, sink_w = 0, sink_h = 0, target_w = 0, target_h = 0;
|
||||
gdouble ratio_w, ratio_h;
|
||||
GstPad *sink_pad;
|
||||
const GValue *range;
|
||||
|
||||
sink_pad = gst_element_get_static_pad (camera->view_sink, "sink");
|
||||
sink_pad = gst_element_get_static_pad (camera->view_sink, "sink");
|
||||
|
||||
if (sink_pad) {
|
||||
sink_caps = gst_pad_get_caps (sink_pad);
|
||||
gst_object_unref (sink_pad);
|
||||
if (sink_caps) {
|
||||
if (!gst_caps_is_any (sink_caps)) {
|
||||
GST_DEBUG_OBJECT (camera, "sink element caps %" GST_PTR_FORMAT,
|
||||
sink_caps);
|
||||
/* Get maximum resolution that view finder sink accepts */
|
||||
st = gst_caps_get_structure (sink_caps, 0);
|
||||
if (gst_structure_has_field_typed (st, "width", GST_TYPE_INT_RANGE)) {
|
||||
range = gst_structure_get_value (st, "width");
|
||||
sink_w = gst_value_get_int_range_max (range);
|
||||
}
|
||||
if (gst_structure_has_field_typed (st, "height", GST_TYPE_INT_RANGE)) {
|
||||
range = gst_structure_get_value (st, "height");
|
||||
sink_h = gst_value_get_int_range_max (range);
|
||||
}
|
||||
GST_DEBUG_OBJECT (camera, "sink element accepts max %dx%d", sink_w,
|
||||
sink_h);
|
||||
if (sink_pad) {
|
||||
sink_caps = gst_pad_get_caps (sink_pad);
|
||||
gst_object_unref (sink_pad);
|
||||
if (sink_caps) {
|
||||
if (!gst_caps_is_any (sink_caps)) {
|
||||
GST_DEBUG_OBJECT (camera, "sink element caps %" GST_PTR_FORMAT,
|
||||
sink_caps);
|
||||
/* Get maximum resolution that view finder sink accepts */
|
||||
st = gst_caps_get_structure (sink_caps, 0);
|
||||
if (gst_structure_has_field_typed (st, "width", GST_TYPE_INT_RANGE)) {
|
||||
range = gst_structure_get_value (st, "width");
|
||||
sink_w = gst_value_get_int_range_max (range);
|
||||
}
|
||||
if (gst_structure_has_field_typed (st, "height", GST_TYPE_INT_RANGE)) {
|
||||
range = gst_structure_get_value (st, "height");
|
||||
sink_h = gst_value_get_int_range_max (range);
|
||||
}
|
||||
GST_DEBUG_OBJECT (camera, "sink element accepts max %dx%d", sink_w,
|
||||
sink_h);
|
||||
|
||||
/* Get incoming frames' resolution */
|
||||
if (sink_h && sink_w) {
|
||||
st = gst_caps_get_structure (new_caps, 0);
|
||||
gst_structure_get_int (st, "width", &in_w);
|
||||
gst_structure_get_int (st, "height", &in_h);
|
||||
GST_DEBUG_OBJECT (camera, "new caps with %dx%d", in_w, in_h);
|
||||
/* Get incoming frames' resolution */
|
||||
if (sink_h && sink_w) {
|
||||
st = gst_caps_get_structure (new_caps, 0);
|
||||
gst_structure_get_int (st, "width", &in_w);
|
||||
gst_structure_get_int (st, "height", &in_h);
|
||||
GST_DEBUG_OBJECT (camera, "new caps with %dx%d", in_w, in_h);
|
||||
}
|
||||
}
|
||||
gst_caps_unref (sink_caps);
|
||||
}
|
||||
gst_caps_unref (sink_caps);
|
||||
}
|
||||
}
|
||||
|
||||
/* If we get bigger frames than view finder sink accepts, then we scale.
|
||||
If we scale we need to adjust aspect ratio capsfilter caps in order
|
||||
to maintain aspect ratio while scaling. */
|
||||
if (in_w && in_h && (in_w > sink_w || in_h > sink_h)) {
|
||||
ratio_w = (gdouble) sink_w / in_w;
|
||||
ratio_h = (gdouble) sink_h / in_h;
|
||||
/* If we get bigger frames than view finder sink accepts, then we scale.
|
||||
If we scale we need to adjust aspect ratio capsfilter caps in order
|
||||
to maintain aspect ratio while scaling. */
|
||||
if (in_w && in_h && (in_w > sink_w || in_h > sink_h)) {
|
||||
ratio_w = (gdouble) sink_w / in_w;
|
||||
ratio_h = (gdouble) sink_h / in_h;
|
||||
|
||||
if (ratio_w < ratio_h) {
|
||||
target_w = sink_w;
|
||||
target_h = (gint) (ratio_w * in_h);
|
||||
if (ratio_w < ratio_h) {
|
||||
target_w = sink_w;
|
||||
target_h = (gint) (ratio_w * in_h);
|
||||
} else {
|
||||
target_w = (gint) (ratio_h * in_w);
|
||||
target_h = sink_h;
|
||||
}
|
||||
|
||||
GST_DEBUG_OBJECT (camera, "setting %dx%d filter to maintain aspect ratio",
|
||||
target_w, target_h);
|
||||
ar_caps = gst_caps_copy (new_caps);
|
||||
gst_caps_set_simple (ar_caps, "width", G_TYPE_INT, target_w, "height",
|
||||
G_TYPE_INT, target_h, NULL);
|
||||
} else {
|
||||
target_w = (gint) (ratio_h * in_w);
|
||||
target_h = sink_h;
|
||||
GST_DEBUG_OBJECT (camera, "no scaling");
|
||||
ar_caps = new_caps;
|
||||
}
|
||||
|
||||
GST_DEBUG_OBJECT (camera, "setting %dx%d filter to maintain aspect ratio",
|
||||
target_w, target_h);
|
||||
ar_caps = gst_caps_copy (new_caps);
|
||||
gst_caps_set_simple (ar_caps, "width", G_TYPE_INT, target_w, "height",
|
||||
G_TYPE_INT, target_h, NULL);
|
||||
} else {
|
||||
GST_DEBUG_OBJECT (camera, "no scaling");
|
||||
ar_caps = new_caps;
|
||||
GST_DEBUG_OBJECT (camera, "aspect ratio filter caps %" GST_PTR_FORMAT,
|
||||
ar_caps);
|
||||
g_object_set (G_OBJECT (camera->aspect_filter), "caps", ar_caps, NULL);
|
||||
if (ar_caps != new_caps)
|
||||
gst_caps_unref (ar_caps);
|
||||
}
|
||||
|
||||
GST_DEBUG_OBJECT (camera, "aspect ratio filter caps %" GST_PTR_FORMAT,
|
||||
ar_caps);
|
||||
g_object_set (G_OBJECT (camera->aspect_filter), "caps", ar_caps, NULL);
|
||||
if (ar_caps != new_caps)
|
||||
gst_caps_unref (ar_caps);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -2315,9 +2348,11 @@ gst_camerabin_finish_image_capture (GstCameraBin * camera)
|
|||
if (camera->image_capture_caps) {
|
||||
/* If we used specific caps for image capture we need to
|
||||
restore the caps and zoom/crop for view finder mode */
|
||||
GST_DEBUG_OBJECT (camera, "resetting crop in camerabin");
|
||||
g_object_set (camera->src_zoom_crop, "left", 0, "right", 0,
|
||||
"top", 0, "bottom", 0, NULL);
|
||||
if (camera->src_zoom_crop) {
|
||||
GST_DEBUG_OBJECT (camera, "resetting crop in camerabin");
|
||||
g_object_set (camera->src_zoom_crop, "left", 0, "right", 0,
|
||||
"top", 0, "bottom", 0, NULL);
|
||||
}
|
||||
gst_camerabin_set_capsfilter_caps (camera, camera->view_finder_caps);
|
||||
}
|
||||
}
|
||||
|
@ -2385,6 +2420,16 @@ gst_camerabin_class_init (GstCameraBinClass * klass)
|
|||
GST_TYPE_CAMERABIN_MODE, DEFAULT_MODE, G_PARAM_READWRITE));
|
||||
|
||||
/**
|
||||
* GstCameraBin:flags
|
||||
*
|
||||
* Control the behaviour of camerabin.
|
||||
*/
|
||||
g_object_class_install_property (gobject_class, ARG_FLAGS,
|
||||
g_param_spec_flags ("flags", "Flags", "Flags to control behaviour",
|
||||
GST_TYPE_CAMERABIN_FLAGS, DEFAULT_FLAGS,
|
||||
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||
|
||||
/**
|
||||
* GstCameraBin:mute:
|
||||
*
|
||||
* Mute audio in video recording mode.
|
||||
|
@ -2708,6 +2753,7 @@ gst_camerabin_init (GstCameraBin * camera, GstCameraBinClass * gclass)
|
|||
|
||||
camera->filename = g_string_new ("");
|
||||
camera->mode = DEFAULT_MODE;
|
||||
camera->flags = DEFAULT_FLAGS;
|
||||
camera->stop_requested = FALSE;
|
||||
camera->paused = FALSE;
|
||||
camera->capturing = FALSE;
|
||||
|
@ -2828,6 +2874,9 @@ gst_camerabin_set_property (GObject * object, guint prop_id,
|
|||
case ARG_MODE:
|
||||
gst_camerabin_change_mode (camera, g_value_get_enum (value));
|
||||
break;
|
||||
case ARG_FLAGS:
|
||||
gst_camerabin_set_flags (camera, g_value_get_flags (value));
|
||||
break;
|
||||
case ARG_FILENAME:
|
||||
gst_camerabin_change_filename (camera, g_value_get_string (value));
|
||||
break;
|
||||
|
@ -2973,6 +3022,9 @@ gst_camerabin_get_property (GObject * object, guint prop_id,
|
|||
case ARG_MODE:
|
||||
g_value_set_enum (value, camera->mode);
|
||||
break;
|
||||
case ARG_FLAGS:
|
||||
g_value_set_flags (value, camera->flags);
|
||||
break;
|
||||
case ARG_MUTE:
|
||||
g_value_set_boolean (value,
|
||||
gst_camerabin_video_get_mute (GST_CAMERABIN_VIDEO (camera->vidbin)));
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#include <gst/gstbin.h>
|
||||
#include <gst/interfaces/photography.h>
|
||||
|
||||
#include "gstcamerabin-enum.h"
|
||||
#include "camerabinimage.h"
|
||||
#include "camerabinvideo.h"
|
||||
|
||||
|
@ -58,9 +59,10 @@ struct _GstCameraBin
|
|||
|
||||
/* private */
|
||||
GString *filename;
|
||||
gint mode; /* MODE_IMAGE or MODE_VIDEO */
|
||||
gboolean stop_requested; /* TRUE if capturing stop needed */
|
||||
gboolean paused; /* TRUE if capturing paused */
|
||||
gint mode; /* MODE_IMAGE or MODE_VIDEO */
|
||||
GstCameraBinFlags flags;
|
||||
gboolean stop_requested; /* TRUE if capturing stop needed */
|
||||
gboolean paused; /* TRUE if capturing paused */
|
||||
|
||||
/* resolution and frames per second of image captured by v4l2 device */
|
||||
gint width;
|
||||
|
|
Loading…
Reference in a new issue