From 83fe4eb456a36bc964710d7781b545d7fe209f75 Mon Sep 17 00:00:00 2001 From: Jeongmo Yang Date: Fri, 30 Mar 2018 17:54:45 +0900 Subject: [PATCH] Add tizencamerasrc plugin, but disabled now. - It's a reference plugin to use tizen camera HAL interface. [Version] 1.0.0-54 [Profile] Common [Issue Type] Add [Dependency module] N/A Change-Id: Ia572295a8819b136de7a30af4c54b3148e0aae1a Signed-off-by: Jeongmo Yang --- Makefile.am | 4 + configure.ac | 20 + packaging/gst-plugins-tizen.spec | 8 +- tizencamerasrc/Makefile.am | 1 + tizencamerasrc/src/Makefile.am | 32 + tizencamerasrc/src/camera_hal_interface.c | 570 ++++++ tizencamerasrc/src/gsttizencamerasrc.c | 2049 ++++++++++++++++++++ tizencamerasrc/src/gsttizencamerasrccolorbalance.c | 92 + tizencamerasrc/src/gsttizencamerasrccontrol.c | 727 +++++++ tizencamerasrc/src/include/camera_hal_interface.h | 54 + tizencamerasrc/src/include/gsttizencamerasrc.h | 126 ++ .../src/include/gsttizencamerasrccolorbalance.h | 91 + .../src/include/gsttizencamerasrccontrol.h | 364 ++++ 13 files changed, 4136 insertions(+), 2 deletions(-) create mode 100644 tizencamerasrc/Makefile.am create mode 100644 tizencamerasrc/src/Makefile.am create mode 100644 tizencamerasrc/src/camera_hal_interface.c create mode 100644 tizencamerasrc/src/gsttizencamerasrc.c create mode 100644 tizencamerasrc/src/gsttizencamerasrccolorbalance.c create mode 100644 tizencamerasrc/src/gsttizencamerasrccontrol.c create mode 100644 tizencamerasrc/src/include/camera_hal_interface.h create mode 100644 tizencamerasrc/src/include/gsttizencamerasrc.h create mode 100644 tizencamerasrc/src/include/gsttizencamerasrccolorbalance.h create mode 100644 tizencamerasrc/src/include/gsttizencamerasrccontrol.h diff --git a/Makefile.am b/Makefile.am index 7dfb351..44500b4 100755 --- a/Makefile.am +++ b/Makefile.am @@ -65,6 +65,10 @@ if GST_TIZEN_USE_WAYLANDSINK SUBDIRS += tizenwlsink endif +if GST_TIZEN_USE_TIZENCAMERASRC +SUBDIRS += tizencamerasrc +endif + DIST_SUBDIRS = common if GST_TIZEN_USE_ENCODEBIN diff --git a/configure.ac b/configure.ac index a738fab..17703ba 100644 --- a/configure.ac +++ b/configure.ac @@ -169,6 +169,7 @@ AC_SUBST(TBM_LIBS) PKG_CHECK_MODULES(MMCOMMON,mm-common) AC_SUBST(MMCOMMON_CFLAGS) +AC_SUBST(MMCOMMON_LIBS) dnl belows are related to wfdtsdemux AG_GST_ARG_WITH_PACKAGE_NAME @@ -438,6 +439,23 @@ AC_SUBST(WAYLAND_CFLAGS) AC_SUBST(WAYLAND_LIBS) fi +dnl use tizencamerasrc -------------------------------------------------------------------------- +AC_ARG_ENABLE(tizencamerasrc, AC_HELP_STRING([--enable-tizencamerasrc], [using tizencamerasrc]), +[ + case "${enableval}" in + yes) GST_TIZEN_USE_TIZENCAMERASRC=yes ;; + no) GST_TIZEN_USE_TIZENCAMERASRC=no ;; + *) AC_MSG_ERROR(bad value ${enableval} for --enable-tizencamerasrc) ;; + esac + ], + [GST_TIZEN_USE_TIZENCAMERASRC=yes]) +AM_CONDITIONAL([GST_TIZEN_USE_TIZENCAMERASRC], [test "x$GST_TIZEN_USE_TIZENCAMERASRC" = "xyes"]) +if test "x$GST_TIZEN_USE_TIZENCAMERASRC" = "xyes"; then +PKG_CHECK_MODULES(DLOG, dlog) +AC_SUBST(DLOG_CFLAGS) +AC_SUBST(DLOG_LIBS) +fi + AC_OUTPUT( Makefile common/Makefile @@ -469,4 +487,6 @@ video360/Makefile video360/src/Makefile tizenwlsink/Makefile tizenwlsink/src/Makefile +tizencamerasrc/Makefile +tizencamerasrc/src/Makefile ) diff --git a/packaging/gst-plugins-tizen.spec b/packaging/gst-plugins-tizen.spec index 4439c5d..69474d2 100644 --- a/packaging/gst-plugins-tizen.spec +++ b/packaging/gst-plugins-tizen.spec @@ -9,13 +9,12 @@ Name: gst-plugins-tizen Version: 1.0.0 Summary: GStreamer tizen plugins (common) -Release: 53 +Release: 54 Group: Multimedia/Framework Url: http://gstreamer.freedesktop.org/ License: LGPL-2.1+ Source0: %{name}-%{version}.tar.gz -#BuildRequires: pkgconfig(camsrcjpegenc) BuildRequires: pkgconfig(gstreamer-audio-1.0) BuildRequires: pkgconfig(gstreamer-video-1.0) BuildRequires: pkgconfig(gstreamer-plugins-base-1.0) @@ -44,6 +43,9 @@ BuildRequires: pkgconfig(wayland-client) >= 1.0.0 BuildRequires: pkgconfig(wayland-tbm-client) BuildRequires: pkgconfig(tizen-extension-client) %endif +# for tizencamerasrc +#BuildRequires: pkgconfig(dlog) +#BuildRequires: mm-hal-interface %description GStreamer tizen plugins (common) @@ -83,6 +85,7 @@ export CFLAGS="$CFLAGS_DEFAULT -DTIZEN_FEATURE_PRODUCT_TM1" --enable-ext-wfdtizenmanager\ --enable-ext-alfec\ --disable-tizenipc\ + --disable-tizencamerasrc\ --disable-static\ --with-tizen-platform \ --with-native-formats \ @@ -107,6 +110,7 @@ export CFLAGS="$CFLAGS_DEFAULT" --enable-ext-wfdtizenmanager\ --enable-ext-alfec\ --disable-tizenipc\ + --disable-tizencamerasrc\ --disable-static\ --with-tizen-platform \ --with-native-formats \ diff --git a/tizencamerasrc/Makefile.am b/tizencamerasrc/Makefile.am new file mode 100644 index 0000000..af437a6 --- /dev/null +++ b/tizencamerasrc/Makefile.am @@ -0,0 +1 @@ +SUBDIRS = src diff --git a/tizencamerasrc/src/Makefile.am b/tizencamerasrc/src/Makefile.am new file mode 100644 index 0000000..4396a7d --- /dev/null +++ b/tizencamerasrc/src/Makefile.am @@ -0,0 +1,32 @@ +# plugindir is set in configure + +plugin_LTLIBRARIES = libgsttizencamerasrc.la + +# sources used to compile this plug-in +libgsttizencamerasrc_la_SOURCES = gsttizencamerasrc.c \ + gsttizencamerasrccontrol.c \ + gsttizencamerasrccolorbalance.c \ + camera_hal_interface.c + +libgsttizencamerasrc_la_CFLAGS = -I$(srcdir)/include \ + $(GST_CFLAGS) \ + $(GST_BASE_CFLAGS) \ + $(GST_VIDEO_FLAGS) \ + $(MMCOMMON_CFLAGS) \ + $(MMUTIL_JPEG_CFLAGS) \ + $(DLOG_CFLAGS) \ + $(TBM_CFLAGS) + +libgsttizencamerasrc_la_LIBADD = -ldl -lpthread -lrt -lm \ + $(GST_LIBS) \ + $(GST_BASE_LIBS) \ + $(GST_VIDEO_LIBS) \ + $(MMCOMMON_LIBS) \ + $(MMUTIL_JPEG_LIBS) \ + $(DLOG_LIBS) \ + $(TBM_LIBS) + +libgsttizencamerasrc_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) + +libgsttizencamerasrc_la_CPPFLAGS = -I$(srcdir)/include + diff --git a/tizencamerasrc/src/camera_hal_interface.c b/tizencamerasrc/src/camera_hal_interface.c new file mode 100644 index 0000000..65f13de --- /dev/null +++ b/tizencamerasrc/src/camera_hal_interface.c @@ -0,0 +1,570 @@ +/* + * camera_hal_interface.c + * + * Copyright (c) 2018 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Jeongmo Yang + * + * This library is free software; you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License as published by the + * Free Software Foundation; either version 2.1 of the License, or (at your option) + * any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, Inc., 51 + * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include "camera_hal_interface.h" + +#ifdef LOG_TAG +#undef LOG_TAG +#endif /* LOG_TAG */ +#define LOG_TAG "CAMERA_HAL_INTF" + +#define LIB_TIZEN_CAMERA "libtizen-camera.so" + +struct _camera_hal_interface { + void *dl_handle; + void *hal_handle; + camera_interface_t intf; +}; + +int camera_hal_interface_init(camera_hal_interface **h) +{ + int ret = CAMERA_ERROR_NONE; + camera_hal_interface *tmp_h = NULL; + + if (h == NULL) { + LOGE("invalid parameter for camera_hal_interface"); + return CAMERA_ERROR_INVALID_PARAMETER; + } + + tmp_h = g_new0(camera_hal_interface, 1); + if (tmp_h == NULL) { + LOGE("failed to allocate hal interface"); + return CAMERA_ERROR_OUT_OF_MEMORY; + } + + tmp_h->dl_handle = dlopen(LIB_TIZEN_CAMERA, RTLD_NOW); + if (tmp_h->dl_handle) { + tmp_h->intf.init = dlsym(tmp_h->dl_handle, "camera_init"); + tmp_h->intf.deinit = dlsym(tmp_h->dl_handle, "camera_deinit"); + tmp_h->intf.get_device_list = dlsym(tmp_h->dl_handle, "camera_get_device_list"); + tmp_h->intf.open_device = dlsym(tmp_h->dl_handle, "camera_open_device"); + tmp_h->intf.close_device = dlsym(tmp_h->dl_handle, "camera_close_device"); + tmp_h->intf.add_message_callback = dlsym(tmp_h->dl_handle, "camera_add_message_callback"); + tmp_h->intf.remove_message_callback = dlsym(tmp_h->dl_handle, "camera_remove_message_callback"); + tmp_h->intf.set_preview_stream_format = dlsym(tmp_h->dl_handle, "camera_set_preview_stream_format"); + tmp_h->intf.get_preview_stream_format = dlsym(tmp_h->dl_handle, "camera_get_preview_stream_format"); + tmp_h->intf.start_preview = dlsym(tmp_h->dl_handle, "camera_start_preview"); + tmp_h->intf.release_preview_buffer = dlsym(tmp_h->dl_handle, "camera_release_preview_buffer"); + tmp_h->intf.stop_preview = dlsym(tmp_h->dl_handle, "camera_stop_preview"); + tmp_h->intf.start_auto_focus = dlsym(tmp_h->dl_handle, "camera_start_auto_focus"); + tmp_h->intf.stop_auto_focus = dlsym(tmp_h->dl_handle, "camera_stop_auto_focus"); + tmp_h->intf.start_capture = dlsym(tmp_h->dl_handle, "camera_start_capture"); + tmp_h->intf.stop_capture = dlsym(tmp_h->dl_handle, "camera_stop_capture"); + tmp_h->intf.set_video_stream_format = dlsym(tmp_h->dl_handle, "camera_set_video_stream_format"); + tmp_h->intf.get_video_stream_format = dlsym(tmp_h->dl_handle, "camera_get_video_stream_format"); + tmp_h->intf.start_record = dlsym(tmp_h->dl_handle, "camera_start_record"); + tmp_h->intf.release_video_buffer = dlsym(tmp_h->dl_handle, "camera_release_video_buffer"); + tmp_h->intf.stop_record = dlsym(tmp_h->dl_handle, "camera_stop_record"); + tmp_h->intf.set_command = dlsym(tmp_h->dl_handle, "camera_set_command"); + tmp_h->intf.get_command = dlsym(tmp_h->dl_handle, "camera_get_command"); + tmp_h->intf.set_batch_command = dlsym(tmp_h->dl_handle, "camera_set_batch_command"); + + if (tmp_h->intf.init == NULL || tmp_h->intf.deinit == NULL) { + LOGE("could not get mandatory function. %p %1p", tmp_h->intf.init, tmp_h->intf.deinit); + ret = CAMERA_ERROR_INTERNAL; + goto _CAMERA_HAL_INTERFACE_GET_FAILED; + } + + if (tmp_h->intf.init) { + ret = tmp_h->intf.init(&tmp_h->hal_handle); + if (ret != CAMERA_ERROR_NONE) { + LOGE("camera_init failed 0x%x", ret); + goto _CAMERA_HAL_INTERFACE_GET_FAILED; + } + } else { + LOGE("no camera_init function"); + ret = CAMERA_ERROR_INTERNAL; + goto _CAMERA_HAL_INTERFACE_GET_FAILED; + } + } else { + LOGE("dlopen failed [%s]", LIB_TIZEN_CAMERA); + ret = CAMERA_ERROR_INTERNAL; + goto _CAMERA_HAL_INTERFACE_GET_FAILED; + } + + *h = tmp_h; + + return ret; + +_CAMERA_HAL_INTERFACE_GET_FAILED: + if (tmp_h) { + if (tmp_h->dl_handle) + dlclose(tmp_h->dl_handle); + + g_free(tmp_h); + } + + return ret; +} + +int camera_hal_interface_deinit(camera_hal_interface *h) +{ + int ret = CAMERA_ERROR_NONE; + + if (h == NULL) { + LOGE("NULL interface"); + return CAMERA_ERROR_INVALID_PARAMETER; + } + + if (h->dl_handle) { + ret = h->intf.deinit(h->hal_handle); + if (ret != CAMERA_ERROR_NONE) { + LOGE("camera_deinit failed 0x%x", ret); + return ret; + } + + h->hal_handle = NULL; + + dlclose(h->dl_handle); + h->dl_handle = NULL; + } + + g_free(h); + + return CAMERA_ERROR_NONE; +} + +int camera_hal_interface_get_device_list(camera_hal_interface *h, camera_device_list_t *device_list) +{ + int ret = CAMERA_ERROR_NONE; + + if (h == NULL) { + LOGE("NULL interface"); + return CAMERA_ERROR_INVALID_PARAMETER; + } + + if (h->intf.get_device_list) { + ret = h->intf.get_device_list(h->hal_handle, device_list); + } else { + LOGE("camera_get_device_list not implemented"); + ret = CAMERA_ERROR_NOT_IMPLEMENTED; + } + + return ret; +} + +int camera_hal_interface_open_device(camera_hal_interface *h, int device_index) +{ + int ret = CAMERA_ERROR_NONE; + + if (h == NULL) { + LOGE("NULL interface"); + return CAMERA_ERROR_INVALID_PARAMETER; + } + + if (h->intf.open_device) { + ret = h->intf.open_device(h->hal_handle, device_index); + } else { + LOGE("camera_open_device not implemented"); + ret = CAMERA_ERROR_NOT_IMPLEMENTED; + } + + return ret; +} + +int camera_hal_interface_close_device(camera_hal_interface *h) +{ + int ret = CAMERA_ERROR_NONE; + + if (h == NULL) { + LOGE("NULL interface"); + return CAMERA_ERROR_INVALID_PARAMETER; + } + + if (h->intf.close_device) { + ret = h->intf.close_device(h->hal_handle); + } else { + LOGE("camera_close_device not implemented"); + ret = CAMERA_ERROR_NOT_IMPLEMENTED; + } + + return ret; +} + +int camera_hal_interface_add_message_callback(camera_hal_interface *h, camera_message_cb callback, void *user_data, uint32_t *cb_id) +{ + int ret = CAMERA_ERROR_NONE; + + if (h == NULL) { + LOGE("NULL interface"); + return CAMERA_ERROR_INVALID_PARAMETER; + } + + if (h->intf.add_message_callback) { + ret = h->intf.add_message_callback(h->hal_handle, callback, user_data, cb_id); + } else { + LOGE("camera_add_message_callback not implemented"); + ret = CAMERA_ERROR_NOT_IMPLEMENTED; + } + + return ret; +} + +int camera_hal_interface_remove_message_callback(camera_hal_interface *h, uint32_t cb_id) +{ + int ret = CAMERA_ERROR_NONE; + + if (h == NULL) { + LOGE("NULL interface"); + return CAMERA_ERROR_INVALID_PARAMETER; + } + + if (h->intf.remove_message_callback) { + ret = h->intf.remove_message_callback(h->hal_handle, cb_id); + } else { + LOGE("camera_remove_message_callback not implemented"); + ret = CAMERA_ERROR_NOT_IMPLEMENTED; + } + + return ret; +} + +int camera_hal_interface_set_preview_stream_format(camera_hal_interface *h, camera_format_t *format) +{ + int ret = CAMERA_ERROR_NONE; + + if (h == NULL) { + LOGE("NULL interface"); + return CAMERA_ERROR_INVALID_PARAMETER; + } + + if (h->intf.set_preview_stream_format) { + ret = h->intf.set_preview_stream_format(h->hal_handle, format); + } else { + LOGE("camera_set_preview_stream_format not implemented"); + ret = CAMERA_ERROR_NOT_IMPLEMENTED; + } + + return ret; +} + +int camera_hal_interface_get_preview_stream_format(camera_hal_interface *h, camera_format_t *format) +{ + int ret = CAMERA_ERROR_NONE; + + if (h == NULL) { + LOGE("NULL interface"); + return CAMERA_ERROR_INVALID_PARAMETER; + } + + if (h->intf.get_preview_stream_format) { + ret = h->intf.get_preview_stream_format(h->hal_handle, format); + } else { + LOGE("camera_get_preview_stream_format not implemented"); + ret = CAMERA_ERROR_NOT_IMPLEMENTED; + } + + return ret; +} + +int camera_hal_interface_start_preview(camera_hal_interface *h, camera_preview_frame_cb callback, void *user_data) +{ + int ret = CAMERA_ERROR_NONE; + + if (h == NULL) { + LOGE("NULL interface"); + return CAMERA_ERROR_INVALID_PARAMETER; + } + + if (h->intf.start_preview) { + ret = h->intf.start_preview(h->hal_handle, callback, user_data); + } else { + LOGE("camera_start_preview not implemented"); + ret = CAMERA_ERROR_NOT_IMPLEMENTED; + } + + return ret; +} + +int camera_hal_interface_release_preview_buffer(camera_hal_interface *h, int buffer_index) +{ + int ret = CAMERA_ERROR_NONE; + + if (h == NULL) { + LOGE("NULL interface"); + return CAMERA_ERROR_INVALID_PARAMETER; + } + + if (h->intf.release_preview_buffer) { + ret = h->intf.release_preview_buffer(h->hal_handle, buffer_index); + } else { + LOGE("camera_release_preview_buffer not implemented"); + ret = CAMERA_ERROR_NOT_IMPLEMENTED; + } + + return ret; +} + +int camera_hal_interface_stop_preview(camera_hal_interface *h) +{ + int ret = CAMERA_ERROR_NONE; + + if (h == NULL) { + LOGE("NULL interface"); + return CAMERA_ERROR_INVALID_PARAMETER; + } + + if (h->intf.stop_preview) { + ret = h->intf.stop_preview(h->hal_handle); + } else { + LOGE("camera_stop_preview not implemented"); + ret = CAMERA_ERROR_NOT_IMPLEMENTED; + } + + return ret; +} + +int camera_hal_interface_start_auto_focus(camera_hal_interface *h) +{ + int ret = CAMERA_ERROR_NONE; + + if (h == NULL) { + LOGE("NULL interface"); + return CAMERA_ERROR_INVALID_PARAMETER; + } + + if (h->intf.start_auto_focus) { + ret = h->intf.start_auto_focus(h->hal_handle); + } else { + LOGE("camera_start_auto_focus not implemented"); + ret = CAMERA_ERROR_NOT_IMPLEMENTED; + } + + return ret; +} + +int camera_hal_interface_stop_auto_focus(camera_hal_interface *h) +{ + int ret = CAMERA_ERROR_NONE; + + if (h == NULL) { + LOGE("NULL interface"); + return CAMERA_ERROR_INVALID_PARAMETER; + } + + if (h->intf.stop_auto_focus) { + ret = h->intf.stop_auto_focus(h->hal_handle); + } else { + LOGE("camera_stop_auto_focus not implemented"); + ret = CAMERA_ERROR_NOT_IMPLEMENTED; + } + + return ret; +} + +int camera_hal_interface_start_capture(camera_hal_interface *h, camera_capture_cb callback, void *user_data) +{ + int ret = CAMERA_ERROR_NONE; + + if (h == NULL) { + LOGE("NULL interface"); + return CAMERA_ERROR_INVALID_PARAMETER; + } + + if (h->intf.start_capture) { + ret = h->intf.start_capture(h->hal_handle, callback, user_data); + } else { + LOGE("camera_start_capture not implemented"); + ret = CAMERA_ERROR_NOT_IMPLEMENTED; + } + + return ret; +} + +int camera_hal_interface_stop_capture(camera_hal_interface *h) +{ + int ret = CAMERA_ERROR_NONE; + + if (h == NULL) { + LOGE("NULL interface"); + return CAMERA_ERROR_INVALID_PARAMETER; + } + + if (h->intf.stop_capture) { + ret = h->intf.stop_capture(h->hal_handle); + } else { + LOGE("camera_stop_capture not implemented"); + ret = CAMERA_ERROR_NOT_IMPLEMENTED; + } + + return ret; +} + +int camera_hal_interface_set_video_stream_format(camera_hal_interface *h, camera_format_t *format) +{ + int ret = CAMERA_ERROR_NONE; + + if (h == NULL) { + LOGE("NULL interface"); + return CAMERA_ERROR_INVALID_PARAMETER; + } + + if (h->intf.set_video_stream_format) { + ret = h->intf.set_video_stream_format(h->hal_handle, format); + } else { + LOGE("camera_set_video_stream_format not implemented"); + ret = CAMERA_ERROR_NOT_IMPLEMENTED; + } + + return ret; +} + +int camera_hal_interface_get_video_stream_format(camera_hal_interface *h, camera_format_t *format) +{ + int ret = CAMERA_ERROR_NONE; + + if (h == NULL) { + LOGE("NULL interface"); + return CAMERA_ERROR_INVALID_PARAMETER; + } + + if (h->intf.get_video_stream_format) { + ret = h->intf.get_video_stream_format(h->hal_handle, format); + } else { + LOGE("camera_get_video_stream_format not implemented"); + ret = CAMERA_ERROR_NOT_IMPLEMENTED; + } + + return ret; +} + +int camera_hal_interface_start_record(camera_hal_interface *h, camera_video_frame_cb callback, void *user_data) +{ + int ret = CAMERA_ERROR_NONE; + + if (h == NULL) { + LOGE("NULL interface"); + return CAMERA_ERROR_INVALID_PARAMETER; + } + + if (h->intf.start_record) { + ret = h->intf.start_record(h->hal_handle, callback, user_data); + } else { + LOGE("camera_start_record not implemented"); + ret = CAMERA_ERROR_NOT_IMPLEMENTED; + } + + return ret; +} + +int camera_hal_interface_release_video_buffer(camera_hal_interface *h, int buffer_index) +{ + int ret = CAMERA_ERROR_NONE; + + if (h == NULL) { + LOGE("NULL interface"); + return CAMERA_ERROR_INVALID_PARAMETER; + } + + if (h->intf.release_video_buffer) { + ret = h->intf.release_video_buffer(h->hal_handle, buffer_index); + } else { + LOGE("camera_release_video_buffer not implemented"); + ret = CAMERA_ERROR_NOT_IMPLEMENTED; + } + + return ret; +} + +int camera_hal_interface_stop_record(camera_hal_interface *h) +{ + int ret = CAMERA_ERROR_NONE; + + if (h == NULL) { + LOGE("NULL interface"); + return CAMERA_ERROR_INVALID_PARAMETER; + } + + if (h->intf.stop_record) { + ret = h->intf.stop_record(h->hal_handle); + } else { + LOGE("camera_stop_record not implemented"); + ret = CAMERA_ERROR_NOT_IMPLEMENTED; + } + + return ret; +} + +int camera_hal_interface_set_command(camera_hal_interface *h, int64_t command, void *value) +{ + int ret = CAMERA_ERROR_NONE; + + if (h == NULL) { + LOGE("NULL interface"); + return CAMERA_ERROR_INVALID_PARAMETER; + } + + if (h->intf.set_command) { + ret = h->intf.set_command(h->hal_handle, command, value); + } else { + LOGE("camera_set_command not implemented"); + ret = CAMERA_ERROR_NOT_IMPLEMENTED; + } + + return ret; +} + +int camera_hal_interface_get_command(camera_hal_interface *h, int64_t command, void *value) +{ + int ret = CAMERA_ERROR_NONE; + + if (h == NULL) { + LOGE("NULL interface"); + return CAMERA_ERROR_INVALID_PARAMETER; + } + + if (h->intf.get_command) { + ret = h->intf.get_command(h->hal_handle, command, value); + } else { + LOGE("camera_get_command not implemented"); + ret = CAMERA_ERROR_NOT_IMPLEMENTED; + } + + return ret; +} + +int camera_hal_interface_set_batch_command(camera_hal_interface *h, camera_batch_command_control_t *batch_command, int64_t *error_command) +{ + int ret = CAMERA_ERROR_NONE; + + if (h == NULL) { + LOGE("NULL interface"); + return CAMERA_ERROR_INVALID_PARAMETER; + } + + if (h->intf.set_batch_command) { + ret = h->intf.set_batch_command(h->hal_handle, batch_command, error_command); + } else { + LOGE("camera_set_batch_command not implemented"); + ret = CAMERA_ERROR_NOT_IMPLEMENTED; + } + + return ret; +} diff --git a/tizencamerasrc/src/gsttizencamerasrc.c b/tizencamerasrc/src/gsttizencamerasrc.c new file mode 100644 index 0000000..bb4bf78 --- /dev/null +++ b/tizencamerasrc/src/gsttizencamerasrc.c @@ -0,0 +1,2049 @@ +/* + * gsttizencamerasrc.c + * + * Copyright (c) 2018 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Jeongmo Yang + * + * This library is free software; you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License as published by the + * Free Software Foundation; either version 2.1 of the License, or (at your option) + * any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, Inc., 51 + * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "gsttizencamerasrc.h" +#include "gsttizencamerasrccontrol.h" +#include "gsttizencamerasrccolorbalance.h" + + +/****************************************************************************** + * Definitions + *******************************************************************************/ +GST_DEBUG_CATEGORY (camerasrc_debug); +#define GST_CAT_DEFAULT camerasrc_debug + + +#define CAMERASRC_ALIGN(addr,size) (((addr)+((size)-1))&(~((size)-1))) + +#if !defined (CLEAR) + #define CLEAR(x) memset(&(x), 0, sizeof(x)) +#endif + +/* Enables */ +#define _ENABLE_CAMERASRC_DEBUG 0 + +/* Local definitions */ +#define _DEFAULT_FPS 15 +#define _DEFAULT_HIGH_SPEED_FPS 0 +#define _DEFAULT_FPS_AUTO FALSE +#define _DEFAULT_PIX_FORMAT CAMERA_PIXEL_FORMAT_NV12 +#define _DEFAULT_PIX_FORMAT_NAME "NV12" +#define _DEFAULT_CAPTURE_FORMAT_NAME "JPEG" +#define _DEFAULT_CAMERA_ID 0 + +#define _CAMERA_ID_MIN 0 +#define _CAMERA_ID_MAX 1 + +#define _DEFAULT_CAP_JPG_QUALITY 95 +#define _DEFAULT_CAP_WIDTH 640 +#define _DEFAULT_CAP_HEIGHT 480 +#define _DEFAULT_CAP_COUNT 1 +#define _DEFAULT_CAP_INTERVAL 0 +#define _DEFAULT_CAP_PROVIDE_EXIF FALSE +#define _PREVIEW_BUFFER_WAIT_TIMEOUT 5000000 /* usec */ + +enum { + CAMERA_COLOR_BALANCE_BRIGHTNESS = 0, + CAMERA_COLOR_BALANCE_CONTRAST, + CAMERA_COLOR_BALANCE_WHITE_BALANCE, + CAMERA_COLOR_BALANCE_COLOR_TONE, + CAMERA_COLOR_BALANCE_SATURATION, + CAMERA_COLOR_BALANCE_HUE, + CAMERA_COLOR_BALANCE_SHARPNESS, + CAMERA_COLOR_BALANCE_NUM +}; + +#define SAFE_FREE_GQUEUE(gqueue) \ + if (gqueue) { \ + g_queue_free(gqueue); \ + gqueue = NULL; \ + } + +#define MAKE_FOURCC_FROM_STRING(string) ((guint32)(string[0] | (string[1] << 8) | (string[2] << 16) | (string[3] << 24))) + + +/* Enumerations */ +enum { + /*signal*/ + SIGNAL_STILL_CAPTURE, + + /*SIGNAL_REGISTER_TROUBLE,*/ + LAST_SIGNAL +}; + +enum { + ARG_0, + /* camera */ + ARG_CAMERA_HIGH_SPEED_FPS, + ARG_CAMERA_AUTO_FPS, + ARG_CAMERA_ID, + + /* capture */ + ARG_CAMERA_CAPTURE_FOURCC, + ARG_CAMERA_CAPTURE_WIDTH, + ARG_CAMERA_CAPTURE_HEIGHT, + ARG_CAMERA_CAPTURE_INTERVAL, + ARG_CAMERA_CAPTURE_COUNT, + ARG_CAMERA_CAPTURE_JPG_QUALITY, + ARG_CAMERA_CAPTURE_PROVIDE_EXIF, + + /* etc */ + ARG_VFLIP, + ARG_HFLIP, + ARG_NUM, +}; + +enum { + VIDEO_IN_MODE_NONE, + VIDEO_IN_MODE_PREVIEW, + VIDEO_IN_MODE_VIDEO, + VIDEO_IN_MODE_CAPTURE, +}; + + +static void gst_tizencamerasrc_uri_handler_init (gpointer g_iface, gpointer iface_data); + +static guint gst_tizencamerasrc_signals[LAST_SIGNAL] = { 0 }; + +/* Element template variables */ +static GstStaticPadTemplate src_factory = + GST_STATIC_PAD_TEMPLATE("src", + GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_STATIC_CAPS("video/x-raw," + "format = (string) { NV12 }, " + "width = (int) [ 1, 4096 ], " + "height = (int) [ 1, 4096 ]; ")); + +/* Local static functions */ +static void gst_tizencamerasrc_set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec); +static void gst_tizencamerasrc_get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec); +static gboolean gst_tizencamerasrc_negotiate(GstBaseSrc *basesrc); +static gboolean gst_tizencamerasrc_src_start(GstBaseSrc *src); +static gboolean gst_tizencamerasrc_src_stop(GstBaseSrc *src); +static gboolean gst_tizencamerasrc_start(GstTizenCameraSrc *camerasrc); +static GstFlowReturn gst_tizencamerasrc_src_create(GstPushSrc *src, GstBuffer **buffer); +static GstFlowReturn gst_tizencamerasrc_read_preview(GstTizenCameraSrc *camerasrc, GstBuffer **buffer); +static GstStateChangeReturn gst_tizencamerasrc_change_state(GstElement *element, GstStateChange transition); +static GstCaps *gst_tizencamerasrc_get_caps(GstBaseSrc *src, GstCaps *filter); +static gboolean gst_tizencamerasrc_set_caps(GstBaseSrc *src, GstCaps *caps); +static gboolean gst_tizencamerasrc_get_caps_info(GstTizenCameraSrc *camerasrc, GstCaps *caps, guint *size); +static gboolean gst_tizencamerasrc_fill_ctrl_list(GstTizenCameraSrc *camerasrc); +static gboolean gst_tizencamerasrc_empty_ctrl_list(GstTizenCameraSrc *camerasrc); +static void gst_tizencamerasrc_finalize(GObject *object); +static gboolean gst_tizencamerasrc_get_timeinfo(GstTizenCameraSrc *camerasrc, GstBuffer *buffer); +static gboolean gst_tizencamerasrc_capture_start(GstTizenCameraSrc *camerasrc); +static gboolean gst_tizencamerasrc_capture_stop(GstTizenCameraSrc *camerasrc); +static void gst_tizencamerasrc_error_handler(GstTizenCameraSrc *camerasrc, int ret); + +/* Util functions */ +#if 0 +static unsigned long _get_current_time(void); +#endif +static gboolean _gst_tizencamerasrc_get_frame_size(int fourcc, int width, int height, unsigned int *outsize); +static gboolean _gst_tizencamerasrc_get_raw_pixel_info(int fourcc, int *pix_format); +static void _gst_tizencamerasrc_post_message_int(GstTizenCameraSrc *camerasrc, const char *msg_name, const char *field_name, int value); + +#if _ENABLE_CAMERASRC_DEBUG +static int __util_write_file(char *filename, void *data, int size); +#endif /* _ENABLE_CAMERASRC_DEBUG */ + +GST_IMPLEMENT_TIZENCAMERASRC_COLOR_BALANCE_METHODS(GstTizenCameraSrc, gst_tizencamera_src); +GST_IMPLEMENT_TIZENCAMERASRC_CONTROL_METHODS(GstTizenCameraSrc, gst_tizencamera_src); + + +/****************************************************************************** + * Implementations + *******************************************************************************/ +static void gst_tizencamerasrc_error_handler(GstTizenCameraSrc *camerasrc, int ret) +{ + if (!camerasrc) { + GST_ERROR_OBJECT(camerasrc, "NULL camerasrc"); + return; + } + + switch (ret) { + case CAMERA_ERROR_NONE: + GST_WARNING_OBJECT(camerasrc, "NO ERROR"); + break; + case CAMERA_ERROR_INTERNAL: + GST_ELEMENT_ERROR(camerasrc, RESOURCE, FAILED, ("IO control error"), GST_ERROR_SYSTEM); + break; + case CAMERA_ERROR_DEVICE_OPEN: + GST_ELEMENT_ERROR(camerasrc, RESOURCE, OPEN_READ_WRITE, ("camera open failed"), GST_ERROR_SYSTEM); + break; + case CAMERA_ERROR_DEVICE_BUSY: + GST_ELEMENT_ERROR(camerasrc, RESOURCE, BUSY, ("camera device busy"), GST_ERROR_SYSTEM); + break; + case CAMERA_ERROR_DEVICE_NOT_FOUND: + GST_ELEMENT_ERROR(camerasrc, RESOURCE, NOT_FOUND, ("camera device not found"), GST_ERROR_SYSTEM); + break; + case CAMERA_ERROR_DEVICE_UNAVAILABLE: + GST_ELEMENT_ERROR(camerasrc, RESOURCE, OPEN_READ, ("camera device unavailable"), GST_ERROR_SYSTEM); + break; + case CAMERA_ERROR_DEVICE_TIME_OUT: + GST_ELEMENT_ERROR(camerasrc, RESOURCE, TOO_LAZY, ("Time Out"), GST_ERROR_SYSTEM); + break; + case CAMERA_ERROR_DEVICE_NOT_SUPPORTED: + GST_ELEMENT_ERROR(camerasrc, RESOURCE, SETTINGS, ("Not supported"), GST_ERROR_SYSTEM); + break; + case CAMERA_ERROR_OUT_OF_MEMORY: + GST_ELEMENT_ERROR(camerasrc, RESOURCE, SETTINGS, ("memory allocation failed"), GST_ERROR_SYSTEM); + break; + case CAMERA_ERROR_PERMISSION_DENIED: + GST_ELEMENT_ERROR(camerasrc, RESOURCE, FAILED, ("Security service failed"), GST_ERROR_SYSTEM); + break; + case CAMERA_ERROR_DEVICE_READ: + GST_ELEMENT_ERROR(camerasrc, RESOURCE, READ, ("camera read failed"), GST_ERROR_SYSTEM); + break; + case CAMERA_ERROR_DEVICE_WRITE: + GST_ELEMENT_ERROR(camerasrc, RESOURCE, WRITE, ("camera write failed"), GST_ERROR_SYSTEM); + break; + default: + GST_ELEMENT_ERROR(camerasrc, RESOURCE, SEEK, (("General video device error[ret=%x]"), ret), GST_ERROR_SYSTEM); + break; + } + + return; +} + + +/* VOID:OBJECT,OBJECT,OBJECT (generated by 'glib-genmarshal') */ +#define g_marshal_value_peek_pointer(v) (v)->data[0].v_pointer +#define g_marshal_value_peek_object(v) (v)->data[0].v_pointer +static void +g_cclosure_user_marshal_VOID__OBJECT_OBJECT_OBJECT(GClosure *closure, + GValue *return_value G_GNUC_UNUSED, + guint n_param_values, + const GValue *param_values, + gpointer invocation_hint G_GNUC_UNUSED, + gpointer marshal_data) +{ + typedef void (*GMarshalFunc_VOID__OBJECT_OBJECT_OBJECT)(gpointer data1, + gpointer arg_1, + gpointer arg_2, + gpointer arg_3, + gpointer data2); + + register GMarshalFunc_VOID__OBJECT_OBJECT_OBJECT callback; + register GCClosure *cc = (GCClosure *)closure; + register gpointer data1; + register gpointer data2; + + g_return_if_fail(n_param_values == 4); + + if (G_CCLOSURE_SWAP_DATA(closure)) { + data1 = closure->data; + data2 = g_value_peek_pointer(param_values + 0); + } else { + data1 = g_value_peek_pointer(param_values + 0); + data2 = closure->data; + } + + callback = (GMarshalFunc_VOID__OBJECT_OBJECT_OBJECT)(marshal_data ? marshal_data : cc->callback); + + callback(data1, + g_marshal_value_peek_object (param_values + 1), + g_marshal_value_peek_object (param_values + 2), + g_marshal_value_peek_object (param_values + 3), + data2); + + return; +} + +/* use following BOILERPLATE MACRO as _get_type entry */ +G_DEFINE_TYPE_WITH_CODE(GstTizenCameraSrc, gst_tizencamerasrc, GST_TYPE_PUSH_SRC, + G_IMPLEMENT_INTERFACE(GST_TYPE_URI_HANDLER, gst_tizencamerasrc_uri_handler_init) + G_IMPLEMENT_INTERFACE(GST_TYPE_CAMERA_CONTROL, gst_tizencamera_src_control_interface_init) + G_IMPLEMENT_INTERFACE(GST_TYPE_COLOR_BALANCE, gst_tizencamera_src_color_balance_interface_init)); + +static int _camera_hal_message_callback(camera_message_t *message, void *user_data) +{ + GstTizenCameraSrc *camerasrc = NULL; + + if (message == NULL || user_data == NULL) { + GST_ERROR("message callback error %p %p", message, user_data); + return FALSE; + } + + camerasrc = (GstTizenCameraSrc *)user_data; + + switch (message->type) { + case CAMERA_MESSAGE_TYPE_FOCUS_CHANGED: + GST_INFO_OBJECT(camerasrc, "focus state %d", message->focus_state); + _gst_tizencamerasrc_post_message_int(camerasrc, "camerasrc-AF", "focus-state", message->focus_state); + break; + case CAMERA_MESSAGE_TYPE_CAPTURED: + GST_INFO_OBJECT(camerasrc, "CAPTURED"); + break; + case CAMERA_MESSAGE_TYPE_HDR_PROGRESS: + GST_INFO_OBJECT(camerasrc, "HDR progress %d", message->hdr_progress); + break; + case CAMERA_MESSAGE_TYPE_ERROR: + GST_ERROR_OBJECT(camerasrc, "error from camera HAL 0x%x", message->error_code); + break; + default: + GST_ERROR_OBJECT(camerasrc, "unknown type message %d", message->type); + return FALSE; + } + + return TRUE; +} + + +static int _camera_preview_frame_cb(camera_buffer_t *buffer, camera_metadata_t *meta, void *user_data) +{ + int i = 0; + int copied_size = 0; + GstTizenCameraSrc *camerasrc = NULL; + GstBuffer *gst_buffer = NULL; + GstMapInfo map_info; + + if (!buffer || !user_data) { + GST_ERROR("preview callback error %p %p", buffer, user_data); + return FALSE; + } + + camerasrc = (GstTizenCameraSrc *)user_data; + + g_mutex_lock(&camerasrc->buffer_lock); + if (!camerasrc->buffer_running) { + GST_WARNING_OBJECT(camerasrc, "buffer is NOT running"); + g_mutex_unlock(&camerasrc->buffer_lock); + return FALSE; + } + + /* create new buffer */ + gst_buffer = gst_buffer_new_and_alloc(buffer->total_size); + if (!gst_buffer) { + GST_ERROR_OBJECT(camerasrc, "new buffer allocation failed. size %u", buffer->total_size); + g_mutex_unlock(&camerasrc->buffer_lock); + return FALSE; + } + + if (!gst_buffer_map(gst_buffer, &map_info, GST_MAP_WRITE)) { + GST_ERROR_OBJECT(camerasrc, "failed to map gst buffer %p", gst_buffer); + gst_buffer_unref(gst_buffer); + g_mutex_unlock(&camerasrc->buffer_lock); + return FALSE; + } + + /* copy buffer data */ + for (i = 0 ; i < buffer->num_planes ; i++) { + memcpy(map_info.data + copied_size, buffer->planes[i].data, buffer->planes[i].size); + copied_size += buffer->planes[i].size; + } + + gst_buffer_unmap(gst_buffer, &map_info); + + /* add new buffer to preview buffer list */ + g_queue_push_tail(camerasrc->preview_buffer_list, gst_buffer); + + GST_DEBUG_OBJECT(camerasrc, "buffer index %d - gst buffer %p", buffer->index, gst_buffer); + + g_cond_signal(&camerasrc->buffer_cond); + + g_mutex_unlock(&camerasrc->buffer_lock); + + /* release preview buffer from camera HAL */ + camera_hal_interface_release_preview_buffer(camerasrc->hal_intf_handle, buffer->index); + + return TRUE; +} + + +static GstVideoFormat __get_gst_video_format(camera_pixel_format_t pixel_format) +{ + switch (pixel_format) { + case CAMERA_PIXEL_FORMAT_NV12: + return GST_VIDEO_FORMAT_NV12; + case CAMERA_PIXEL_FORMAT_NV21: + return GST_VIDEO_FORMAT_NV21; + case CAMERA_PIXEL_FORMAT_I420: + return GST_VIDEO_FORMAT_I420; + case CAMERA_PIXEL_FORMAT_YV12: + return GST_VIDEO_FORMAT_YV12; + case CAMERA_PIXEL_FORMAT_YUYV: + return GST_VIDEO_FORMAT_YUY2; + case CAMERA_PIXEL_FORMAT_UYVY: + return GST_VIDEO_FORMAT_UYVY; + default: + GST_ERROR("unknown pixel format %d", pixel_format); + return -1; + } +} + +static GstSample *__create_buffer_sample(GstTizenCameraSrc *camerasrc, camera_buffer_t *cam_buffer) +{ + GstBuffer *gst_buffer = NULL; + GstCaps *caps = NULL; + GstSample *sample = NULL; + const gchar *string_fourcc = NULL; + + if (!camerasrc) { + GST_ERROR("NULL handle"); + return NULL; + } + + if (!cam_buffer) { + GST_ERROR_OBJECT(camerasrc, "NULL buffer"); + return NULL; + } + + gst_buffer = gst_buffer_new_wrapped_full(0, + cam_buffer->planes[0].data, + cam_buffer->planes[0].size, + 0, + cam_buffer->planes[0].size, + NULL, NULL); + if (!gst_buffer) { + GST_ERROR_OBJECT(camerasrc, "failed to allocate gst buffer for %p", cam_buffer); + return NULL; + } + + if (cam_buffer->format == CAMERA_PIXEL_FORMAT_ENCODED_JPEG) { + caps = gst_caps_new_simple("image/jpeg", + "width", G_TYPE_INT, cam_buffer->resolution.width, + "height", G_TYPE_INT, cam_buffer->resolution.height, + NULL); + } else { + string_fourcc = gst_video_format_to_string(__get_gst_video_format(cam_buffer->format)); + if (string_fourcc) { + caps = gst_caps_new_simple("image/jpeg", + "format", G_TYPE_STRING, string_fourcc, + "width", G_TYPE_INT, cam_buffer->resolution.width, + "height", G_TYPE_INT, cam_buffer->resolution.height, + NULL); + } else { + GST_ERROR_OBJECT(camerasrc, "failed to get string_fourcc"); + } + } + + if (!caps) { + GST_ERROR_OBJECT(camerasrc, "sample caps creation failed for %p", cam_buffer); + goto _CREATE_BUFFER_SAMPLE_DONE; + } + + sample = gst_sample_new(gst_buffer, caps, NULL, NULL); + if (!sample) { + GST_ERROR_OBJECT(camerasrc, "buffer sample1 creation failed"); + goto _CREATE_BUFFER_SAMPLE_DONE; + } + +_CREATE_BUFFER_SAMPLE_DONE: + if (gst_buffer) + gst_buffer_unref(gst_buffer); + if (caps) + gst_caps_unref(caps); + + GST_INFO_OBJECT(camerasrc, "sample %p - format %d, %dx%d", + sample, cam_buffer->format, cam_buffer->resolution.width, cam_buffer->resolution.height); + + return sample; +} + + +static int _camera_capture_cb(camera_buffer_t *main, camera_buffer_t *postview, camera_buffer_t *thumbnail, void *user_data) +{ + GstTizenCameraSrc *camerasrc = NULL; + GstSample *buf_sample1 = NULL; + GstSample *buf_sample2 = NULL; + GstSample *buf_sample3 = NULL; + + if (!main || !user_data) { + GST_ERROR("capture callback error %p %p", main, user_data); + return FALSE; + } + + camerasrc = (GstTizenCameraSrc *)user_data; + + buf_sample1 = __create_buffer_sample(camerasrc, main); + if (!buf_sample1) { + GST_ERROR_OBJECT(camerasrc, "buffer sample1 creation failed"); + return FALSE; + } + + buf_sample2 = __create_buffer_sample(camerasrc, postview); + if (!buf_sample2) + GST_WARNING_OBJECT(camerasrc, "No sample for postview"); + + buf_sample3 = __create_buffer_sample(camerasrc, thumbnail); + if (!buf_sample3) + GST_WARNING_OBJECT(camerasrc, "No sample for thumbnail"); + + GST_INFO_OBJECT(camerasrc, "CALL: capture callback"); + + g_signal_emit(G_OBJECT(camerasrc), + gst_tizencamerasrc_signals[SIGNAL_STILL_CAPTURE], + 0, + buf_sample1, + buf_sample2, + buf_sample3); + + GST_INFO_OBJECT(camerasrc, "RETURN: capture callback"); + + return TRUE; +} + + +static gboolean gst_tizencamerasrc_create(GstTizenCameraSrc *camerasrc) +{ + int ret = 0; + + /* camera interface handle init */ + GST_INFO("camera_hal_interface init"); + + ret = camera_hal_interface_init(&camerasrc->hal_intf_handle); + if (ret != CAMERA_ERROR_NONE) { + GST_ERROR("camera_hal_interface_init() failed. errcode = 0x%08X", ret); + goto _ERROR; + } + + GST_INFO("camera_hal_interface_init() done"); + + ret = camera_hal_interface_open_device(camerasrc->hal_intf_handle, 0); + if (ret != CAMERA_ERROR_NONE) { + GST_ERROR("camera_hal_interface_open_device() failed. errcode = 0x%08X", ret); + camera_hal_interface_deinit(camerasrc->hal_intf_handle); + camerasrc->hal_intf_handle = NULL; + goto _ERROR; + } + + if (!gst_tizencamerasrc_fill_ctrl_list(camerasrc)) { + GST_WARNING("Can't fill v4l2 control list."); + } + + return TRUE; + + _ERROR: + gst_tizencamerasrc_error_handler(camerasrc, ret); + return FALSE; +} + + +static gboolean gst_tizencamerasrc_destroy(GstTizenCameraSrc *camerasrc) +{ + int ret = CAMERA_ERROR_NONE; + + GST_INFO_OBJECT(camerasrc, "ENTERED"); + + if (camerasrc->hal_intf_handle == NULL) { + GST_ERROR_OBJECT(camerasrc, "not initialized"); + return FALSE; + } + + if (camerasrc->hal_intf_handle) { + /* camera hal interface deinit */ + GST_INFO_OBJECT(camerasrc, "camerasrc_destroy() calling..."); + + camera_hal_interface_close_device(camerasrc->hal_intf_handle); + + ret = camera_hal_interface_deinit(camerasrc->hal_intf_handle); + if (ret != CAMERA_ERROR_NONE) { + GST_ERROR_OBJECT(camerasrc, "camera_hal_interface_deinit failed 0x%x", ret); + return FALSE; + } + + camerasrc->hal_intf_handle = NULL; + + /* Empty control list */ + gst_tizencamerasrc_empty_ctrl_list(camerasrc); + } + + GST_INFO_OBJECT(camerasrc, "LEAVED"); + + return TRUE; +} + + +static gboolean gst_tizencamerasrc_fill_ctrl_list(GstTizenCameraSrc *camerasrc) +{ + int n = 0; + + char *camerasrc_ctrl_label[CAMERA_COLOR_BALANCE_NUM] = { + "brightness", + "contrast", + "white balance", + "color tone", + "saturation", + "hue", + "sharpness", + }; + + uint64_t camerasrc_ctrl_cmd[CAMERA_COLOR_BALANCE_NUM] = { + CAMERA_COMMAND_EXPOSURE, + CAMERA_COMMAND_CONTRAST, + CAMERA_COMMAND_WHITE_BALANCE, + CAMERA_COMMAND_EFFECT, + CAMERA_COMMAND_SATURATION, + CAMERA_COMMAND_HUE, + CAMERA_COMMAND_SHARPNESS + }; + + g_return_val_if_fail(camerasrc, FALSE); + + GST_DEBUG_OBJECT(camerasrc, "ENTERED"); + + for (n = CAMERA_COMMAND_EXPOSURE ; n < CAMERA_COLOR_BALANCE_NUM ; n++) { + GstTizenCameraSrcColorBalanceChannel *camerasrc_color_channel = NULL; + GstColorBalanceChannel *color_channel = NULL; + + GstTizenCamerasrcControlChannel *camerasrc_control_channel = NULL; + GstCameraControlChannel *control_channel = NULL; + + gint channel_type; + + switch (n) { + case CAMERA_COLOR_BALANCE_BRIGHTNESS: + case CAMERA_COLOR_BALANCE_CONTRAST: + case CAMERA_COLOR_BALANCE_WHITE_BALANCE: + case CAMERA_COLOR_BALANCE_COLOR_TONE: + case CAMERA_COLOR_BALANCE_SATURATION: + case CAMERA_COLOR_BALANCE_HUE: + case CAMERA_COLOR_BALANCE_SHARPNESS: + channel_type = INTERFACE_COLOR_BALANCE; + break; + default: + channel_type = INTERFACE_CAMERA_CONTROL; + continue; + } + + if (channel_type == INTERFACE_COLOR_BALANCE) { + camerasrc_color_channel = g_object_new(GST_TYPE_TIZENCAMERASRC_COLOR_BALANCE_CHANNEL, NULL); + color_channel = GST_COLOR_BALANCE_CHANNEL(camerasrc_color_channel); + + color_channel->label = g_strdup((const gchar *)camerasrc_ctrl_label[n]); + camerasrc_color_channel->id = camerasrc_ctrl_cmd[n]; + color_channel->min_value = 0; + color_channel->max_value = 0; + + camerasrc->colors = g_list_append(camerasrc->colors, (gpointer)color_channel); + GST_INFO_OBJECT(camerasrc, "Adding Color Balance Channel %s [%"PRIx64"]", + color_channel->label, camerasrc_color_channel->id); + } else { /* if( channel_type == INTERFACE_CAMERA_CONTROL ) */ + camerasrc_control_channel = g_object_new(GST_TYPE_TIZENCAMERASRC_CONTROL_CHANNEL, NULL); + control_channel = GST_CAMERA_CONTROL_CHANNEL(camerasrc_control_channel); + + control_channel->label = g_strdup((const gchar *)camerasrc_ctrl_label[n]); + camerasrc_control_channel->id = camerasrc_ctrl_cmd[n]; + control_channel->min_value = 0; + control_channel->max_value = 0; + + camerasrc->camera_controls = g_list_append(camerasrc->camera_controls, (gpointer)control_channel); + GST_INFO_OBJECT(camerasrc, "Adding Camera Control Channel %s [%"PRIx64"]", + control_channel->label, camerasrc_control_channel->id); + } + } + + GST_DEBUG_OBJECT(camerasrc, "LEAVED"); + + return TRUE; +} + + +static gboolean gst_tizencamerasrc_empty_ctrl_list(GstTizenCameraSrc *camerasrc) +{ + g_return_val_if_fail(camerasrc, FALSE); + + GST_DEBUG_OBJECT (camerasrc, "ENTERED"); + + g_list_foreach(camerasrc->colors, (GFunc)g_object_unref, NULL); + g_list_free(camerasrc->colors); + camerasrc->colors = NULL; + + g_list_foreach(camerasrc->camera_controls, (GFunc)g_object_unref, NULL); + g_list_free(camerasrc->camera_controls); + camerasrc->camera_controls = NULL; + + GST_DEBUG_OBJECT(camerasrc, "LEAVED"); + + return TRUE; +} + + +static gboolean gst_tizencamerasrc_start(GstTizenCameraSrc *camerasrc) +{ + int ret = 0; + + camera_flip_t set_flip; + camera_format_t set_format; + + GST_DEBUG_OBJECT(camerasrc, "ENTERED"); + + /* set message callback */ + camera_hal_interface_add_message_callback(camerasrc->hal_intf_handle, _camera_hal_message_callback, camerasrc, &camerasrc->msg_cb_id); + + CLEAR(set_format); + + /* set preview stream format */ + set_format.stream_format = camerasrc->pix_format; + set_format.stream_resolution.width = camerasrc->width; + set_format.stream_resolution.height = camerasrc->height; + switch (camerasrc->rotate) { + case 90: + set_format.stream_rotation = CAMERA_ROTATION_90; + break; + case 180: + set_format.stream_rotation = CAMERA_ROTATION_180; + break; + case 270: + set_format.stream_rotation = CAMERA_ROTATION_270; + break; + case 0: + default: + set_format.stream_rotation = CAMERA_ROTATION_0; + break; + } + if (camerasrc->fps_auto) { + /*if fps is zero, auto fps mode*/ + set_format.stream_fps = 0; + + GST_INFO_OBJECT (camerasrc, "AUTO FPS mode"); + } else if (camerasrc->high_speed_fps <= 0) { + if (camerasrc->fps <= 0) { + /*if fps is zero, auto fps mode*/ + set_format.stream_fps = 0; + } else { + set_format.stream_fps = camerasrc->fps; + } + } else { + GST_INFO_OBJECT(camerasrc, "high speed fps %d", camerasrc->high_speed_fps); + set_format.stream_fps = camerasrc->high_speed_fps; + } + + set_format.capture_format = CAMERA_PIXEL_FORMAT_ENCODED_JPEG; + set_format.capture_resolution.width = camerasrc->cap_width; + set_format.capture_resolution.height = camerasrc->cap_height; + set_format.capture_quality = (uint32_t)camerasrc->cap_jpg_quality; + + GST_INFO_OBJECT(camerasrc, "resolution [%dx%d] fps %d, format %d, rotation %d", + camerasrc->width, camerasrc->height, set_format.stream_fps, + camerasrc->pix_format, camerasrc->rotate); + + ret = camera_hal_interface_set_preview_stream_format(camerasrc->hal_intf_handle, &set_format); + if (ret != CAMERA_ERROR_NONE) { + GST_ERROR_OBJECT(camerasrc, "camera_hal_interface_set_preview_stream_format() failed 0x%x", ret); + goto _ERROR; + } + + /* set flip */ + if (camerasrc->vflip) { + if (camerasrc->hflip) + set_flip = CAMERA_FLIP_BOTH; + else + set_flip = CAMERA_FLIP_VERTICAL; + } else { + if (camerasrc->hflip) + set_flip = CAMERA_FLIP_HORIZONTAL; + else + set_flip = CAMERA_FLIP_NONE; + } + + camera_hal_interface_set_command(camerasrc->hal_intf_handle, CAMERA_COMMAND_FLIP, (void *)&set_flip); + + GST_INFO("VFLIP : %d, HFLIP : %d", camerasrc->vflip, camerasrc->hflip); + + /* start preview stream */ + ret = camera_hal_interface_start_preview(camerasrc->hal_intf_handle, _camera_preview_frame_cb, camerasrc); + if (ret != CAMERA_ERROR_NONE) { + GST_ERROR_OBJECT(camerasrc, "camera_hal_interface_start_preview() failed 0x%x", ret); + camerasrc->buffer_running = FALSE; + goto _ERROR; + } + + GST_INFO_OBJECT(camerasrc, "camerasrc_start_preview_stream() done"); + + camerasrc->mode = VIDEO_IN_MODE_PREVIEW; + camerasrc->buffer_running = TRUE; + + GST_INFO_OBJECT(camerasrc, "LEAVED"); + + return TRUE; + +_ERROR: + gst_tizencamerasrc_error_handler(camerasrc, ret); + GST_ERROR_OBJECT(camerasrc, "LEAVED 0x%x", ret); + + return FALSE; +} + + +static gboolean gst_tizencamerasrc_stop(GstTizenCameraSrc *camerasrc) +{ + int ret = CAMERA_ERROR_NONE; + + GST_INFO_OBJECT (camerasrc, "ENTERED"); + + if (camerasrc->hal_intf_handle) { + GstBuffer *buffer = NULL; + + /* Stop preview stream */ + g_mutex_lock(&camerasrc->buffer_lock); + if (camerasrc->buffer_running) { + camerasrc->buffer_running = FALSE; + } else { + GST_ERROR_OBJECT(camerasrc, "buffer NOT running"); + g_mutex_unlock(&camerasrc->buffer_lock); + return FALSE; + } + g_mutex_unlock(&camerasrc->buffer_lock); + + GST_INFO_OBJECT(camerasrc, "stop preview stream"); + + ret = camera_hal_interface_stop_preview(camerasrc->hal_intf_handle); + if (ret != CAMERA_ERROR_NONE) { + GST_ERROR_OBJECT(camerasrc, "camera_hal_interface_stop_preview failed 0x%x", ret); + camerasrc->buffer_running = TRUE; + return FALSE; + } + + camerasrc->mode = VIDEO_IN_MODE_NONE; + + while (!g_queue_is_empty(camerasrc->preview_buffer_list)) { + buffer = g_queue_pop_head(camerasrc->preview_buffer_list); + if (buffer) { + GST_INFO_OBJECT(camerasrc, "unref buffer %p", buffer); + gst_buffer_unref(buffer); + buffer = NULL; + } + } + } + + GST_INFO_OBJECT(camerasrc, "LEAVED"); + + return TRUE; +} + + +static gboolean gst_tizencamerasrc_capture_start(GstTizenCameraSrc *camerasrc) +{ + int ret = CAMERA_ERROR_NONE; + + GST_INFO_OBJECT(camerasrc, "ENTERED - mode %d", camerasrc->mode); + + if (camerasrc->mode == VIDEO_IN_MODE_PREVIEW) { + /* set preview buffer running flag to FALSE to release preview buffer immediately */ + g_mutex_lock(&camerasrc->buffer_lock); + + if (camerasrc->buffer_running) { + camerasrc->buffer_running = FALSE; + } else { + GST_ERROR_OBJECT(camerasrc, "buffer NOT running"); + g_mutex_unlock(&camerasrc->buffer_lock); + return FALSE; + } + + g_mutex_unlock(&camerasrc->buffer_lock); + + GST_INFO_OBJECT(camerasrc, "start capture"); + + ret = camera_hal_interface_start_capture(camerasrc->hal_intf_handle, _camera_capture_cb, camerasrc); + if (ret != CAMERA_ERROR_NONE) { + GST_ERROR_OBJECT(camerasrc, "camera_hal_interface_start_capture failed 0x%x", ret); + camerasrc->buffer_running = TRUE; + return FALSE; + } + + camerasrc->mode = VIDEO_IN_MODE_CAPTURE; + + g_mutex_lock(&camerasrc->buffer_lock); + + camerasrc->buffer_running = TRUE; + + g_cond_signal(&camerasrc->buffer_cond); + + g_mutex_unlock(&camerasrc->buffer_lock); + + GST_INFO_OBJECT(camerasrc, "CAPTURE STARTED!"); + + return TRUE; + } else { + GST_WARNING_OBJECT(camerasrc, "Wrong state[%d]!", camerasrc->mode); + return FALSE; + } +} + + +static gboolean gst_tizencamerasrc_capture_stop(GstTizenCameraSrc *camerasrc) +{ + int ret = CAMERA_ERROR_NONE; + + GST_INFO_OBJECT(camerasrc, "ENTERED - mode %d", camerasrc->mode); + + if (camerasrc->mode == VIDEO_IN_MODE_CAPTURE) { + ret = camera_hal_interface_stop_capture(camerasrc->hal_intf_handle); + if (ret != CAMERA_ERROR_NONE) { + GST_ERROR_OBJECT(camerasrc, "camera_hal_interface_stop_capture failed 0x%x", ret); + return FALSE; + } + + g_mutex_lock(&camerasrc->buffer_lock); + + camerasrc->mode = VIDEO_IN_MODE_PREVIEW; + + g_cond_signal(&camerasrc->buffer_cond); + + g_mutex_unlock(&camerasrc->buffer_lock); + + GST_INFO_OBJECT(camerasrc, "CAPTURE STOPPED!"); + + return TRUE; + } else { + GST_WARNING_OBJECT(camerasrc, "Wrong state[%d]!", camerasrc->mode); + return FALSE; + } +} + + +static GstFlowReturn gst_tizencamerasrc_read_preview(GstTizenCameraSrc *camerasrc, GstBuffer **buffer) +{ + int preview_check_count = 0; + gint64 end_time = 0; + + GST_DEBUG_OBJECT(camerasrc, "check preview buffer list"); + + g_mutex_lock(&camerasrc->buffer_lock); + + while (g_queue_is_empty(camerasrc->preview_buffer_list)) { + GST_DEBUG_OBJECT(camerasrc, "Preview buffer list is empty. waiting..."); + + if (camerasrc->mode == VIDEO_IN_MODE_PREVIEW) { + end_time = g_get_monotonic_time () + _PREVIEW_BUFFER_WAIT_TIMEOUT; + if (!g_cond_wait_until(&camerasrc->buffer_cond, &camerasrc->buffer_lock, end_time)) { + GST_ERROR_OBJECT(camerasrc, "Buffer wait timeout[%d usec]. Return ERROR", _PREVIEW_BUFFER_WAIT_TIMEOUT); + g_mutex_unlock(&camerasrc->buffer_lock); + gst_tizencamerasrc_error_handler(camerasrc, CAMERA_ERROR_DEVICE_READ); + return GST_FLOW_ERROR; + } else { + preview_check_count++; + GST_DEBUG_OBJECT(camerasrc, "Signal received. Retry...[count %d]", preview_check_count); + } + } else if (camerasrc->mode == VIDEO_IN_MODE_CAPTURE) { + GST_INFO_OBJECT(camerasrc, "now capture mode. wait..."); + g_cond_wait(&camerasrc->buffer_cond, &camerasrc->buffer_lock); + GST_INFO_OBJECT(camerasrc, "capture mode - signal received, check preview buffer again."); + preview_check_count = 0; + } else if (preview_check_count > 5) { + GST_ERROR_OBJECT(camerasrc, "preview buffer check failed"); + g_mutex_unlock(&camerasrc->buffer_lock); + gst_tizencamerasrc_error_handler(camerasrc, CAMERA_ERROR_DEVICE_READ); + return GST_FLOW_ERROR; + } + } + + *buffer = g_queue_pop_head(camerasrc->preview_buffer_list); + + g_mutex_unlock(&camerasrc->buffer_lock); + + if (*buffer == NULL) { + GST_ERROR_OBJECT(camerasrc, "popped buffer is NULL"); + + gst_tizencamerasrc_error_handler(camerasrc, CAMERA_ERROR_DEVICE_READ); + + return GST_FLOW_ERROR; + } + + /* set timestamp and duration */ + gst_tizencamerasrc_get_timeinfo(camerasrc, *buffer); + + if (camerasrc->firsttime) { + camerasrc->firsttime = FALSE; + } + + GST_DEBUG_OBJECT(camerasrc, "preview buffer %p", *buffer); + + return GST_FLOW_OK; +} + + +static GstFlowReturn gst_tizencamerasrc_read(GstTizenCameraSrc *camerasrc, GstBuffer **buffer) +{ + GstFlowReturn ret = GST_FLOW_OK; + + switch (camerasrc->mode) { + case VIDEO_IN_MODE_PREVIEW: + case VIDEO_IN_MODE_CAPTURE: + case VIDEO_IN_MODE_VIDEO: + GST_DEBUG_OBJECT(camerasrc, "gst_tizencamerasrc_read_preview"); + ret = gst_tizencamerasrc_read_preview(camerasrc, buffer); + break; + case VIDEO_IN_MODE_NONE: + default: + ret = GST_FLOW_ERROR; + GST_ERROR_OBJECT (camerasrc, "can't reach statement.[camerasrc->mode=%d]", camerasrc->mode); + break; + } + + if (!buffer || !(*buffer) || !GST_IS_BUFFER(*buffer)) { + /* To avoid seg fault, make dummy buffer. */ + GST_WARNING_OBJECT (camerasrc, "Make a dummy buffer"); + *buffer = gst_buffer_new(); + } + + return ret; +} + + +static gboolean gst_tizencamerasrc_get_timeinfo(GstTizenCameraSrc *camerasrc, GstBuffer *buffer) +{ + int fps_nu = 0; + int fps_de = 0; + GstClock *clock = NULL; + GstClockTime timestamp = GST_CLOCK_TIME_NONE; + GstClockTime duration = GST_CLOCK_TIME_NONE; + + if (!camerasrc || !buffer) { + GST_WARNING_OBJECT (camerasrc, "Invalid pointer [hadle:%p, buffer:%p]", camerasrc, buffer); + return FALSE; + } + + /* timestamps, LOCK to get clock and base time. */ + clock = GST_ELEMENT_CLOCK(camerasrc); + if (clock) { + /* the time now is the time of the clock minus the base time */ + gst_object_ref(clock); + timestamp = gst_clock_get_time(clock) - GST_ELEMENT(camerasrc)->base_time; + gst_object_unref(clock); + + /* if we have a framerate adjust timestamp for frame latency */ + if (camerasrc->fps_auto) { + /* auto fps mode */ + duration = GST_CLOCK_TIME_NONE; + } else { + if (camerasrc->fps <= 0) { + /*if fps is zero, auto fps mode*/ + fps_nu = 0; + fps_de = 1; + } else { + fps_nu = 1; + fps_de = camerasrc->fps; + } + + if (fps_nu > 0 && fps_de > 0) { + duration = gst_util_uint64_scale_int(GST_SECOND, fps_nu, fps_de); + } + } + + /* set default duration if duration is NONE : 30 fps */ + if (duration == GST_CLOCK_TIME_NONE) { + duration = gst_util_uint64_scale_int(GST_SECOND, 1, 30); + } + } else { + /* no clock, can't set timestamps */ + timestamp = GST_CLOCK_TIME_NONE; + } + + GST_BUFFER_TIMESTAMP(buffer) = timestamp; + GST_BUFFER_DURATION(buffer) = duration; + + GST_LOG_OBJECT(camerasrc, "timestamp [%"GST_TIME_FORMAT" dur %" GST_TIME_FORMAT "]", + GST_TIME_ARGS(GST_BUFFER_TIMESTAMP(buffer)), + GST_TIME_ARGS(GST_BUFFER_DURATION(buffer))); + + return TRUE; +} + + +/* Gstreamer general functions */ +static gboolean gst_tizencamerasrc_src_start(GstBaseSrc *src) +{ + int ret = TRUE; + GstTizenCameraSrc *camerasrc = GST_TIZENCAMERA_SRC (src); + + GST_DEBUG_OBJECT(camerasrc, "ENTERED"); + + camerasrc->firsttime = TRUE; + /* 'gst_tizencamerasrc_set_caps' will call gst_tizencamerasrc_start(). So skip to call it. */ + /*ret = gst_tizencamerasrc_start(camerasrc);*/ + + GST_DEBUG_OBJECT(camerasrc, "LEAVED"); + + return ret; +} + + +static gboolean gst_tizencamerasrc_src_stop(GstBaseSrc *src) +{ + int ret = 0; + GstTizenCameraSrc *camerasrc = GST_TIZENCAMERA_SRC(src); + + GST_DEBUG_OBJECT (camerasrc, "ENTERED"); + + ret = gst_tizencamerasrc_stop(camerasrc); + + GST_DEBUG_OBJECT(camerasrc, "LEAVED"); + + return ret; +} + + +static GstFlowReturn gst_tizencamerasrc_src_create(GstPushSrc *src, GstBuffer **buffer) +{ + GstTizenCameraSrc *camerasrc = GST_TIZENCAMERA_SRC (src); + GstFlowReturn ret; + + GST_LOG_OBJECT(camerasrc, "ENTERED"); + + ret = gst_tizencamerasrc_read(camerasrc, buffer); + + GST_LOG_OBJECT (camerasrc, "LEAVED"); + + return ret; +} + + +static void gst_tizencamerasrc_set_property(GObject *object, guint prop_id, + const GValue *value, GParamSpec *pspec) +{ + int tmp = 0; + GstTizenCameraSrc *camerasrc = NULL; + + g_return_if_fail(GST_IS_TIZENCAMERA_SRC(object)); + camerasrc = GST_TIZENCAMERA_SRC(object); + + switch (prop_id) { + case ARG_CAMERA_HIGH_SPEED_FPS: + camerasrc->high_speed_fps = g_value_get_int(value); + GST_INFO_OBJECT(camerasrc, "Set HIGH SPEED FPS: %d", camerasrc->high_speed_fps); + break; + case ARG_CAMERA_AUTO_FPS: + camerasrc->fps_auto = g_value_get_boolean(value); + GST_INFO_OBJECT(camerasrc, "Set AUTO_FPS: %d", camerasrc->fps_auto); + break; + case ARG_CAMERA_ID: + camerasrc->camera_id = g_value_get_int(value); + break; + case ARG_CAMERA_CAPTURE_FOURCC: + camerasrc->cap_fourcc = g_value_get_uint(value); + break; + case ARG_CAMERA_CAPTURE_WIDTH: + camerasrc->cap_width = g_value_get_int(value); + GST_INFO_OBJECT(camerasrc, "Set capture width: %d", camerasrc->cap_width); + break; + case ARG_CAMERA_CAPTURE_HEIGHT: + camerasrc->cap_height = g_value_get_int(value); + GST_INFO_OBJECT(camerasrc, "Set capture height: %d", camerasrc->cap_height); + break; + case ARG_CAMERA_CAPTURE_INTERVAL: + camerasrc->cap_interval = g_value_get_int(value); + GST_INFO_OBJECT(camerasrc, "Set capture interval: %d", camerasrc->cap_interval); + break; + case ARG_CAMERA_CAPTURE_COUNT: + tmp = g_value_get_int(value); + camerasrc->cap_count = tmp; + camerasrc->cap_count_reverse = tmp; + GST_INFO_OBJECT(camerasrc, "Set capture count: %d", camerasrc->cap_count_reverse); + break; + case ARG_CAMERA_CAPTURE_JPG_QUALITY: + { + camerasrc->cap_jpg_quality = g_value_get_int(value); + GST_INFO_OBJECT(camerasrc, "Set jpeg quality : %d", camerasrc->cap_jpg_quality); + break; + } + case ARG_VFLIP: + camerasrc->vflip = g_value_get_boolean(value); + GST_INFO_OBJECT(camerasrc, "Set VFLIP : %d", camerasrc->vflip); + break; + case ARG_HFLIP: + camerasrc->hflip = g_value_get_boolean(value); + GST_INFO_OBJECT(camerasrc, "Set HFLIP : %d", camerasrc->hflip); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } + + return; +} + + +static void gst_tizencamerasrc_get_property(GObject *object, guint prop_id, + GValue *value, GParamSpec *pspec) +{ + GstTizenCameraSrc *camerasrc; + + g_return_if_fail(GST_IS_TIZENCAMERA_SRC(object)); + camerasrc = GST_TIZENCAMERA_SRC(object); + + switch (prop_id) { + case ARG_CAMERA_HIGH_SPEED_FPS: + g_value_set_int(value, camerasrc->high_speed_fps); + break; + case ARG_CAMERA_AUTO_FPS: + g_value_set_boolean(value, camerasrc->fps_auto); + break; + case ARG_CAMERA_ID: + g_value_set_int(value, camerasrc->camera_id); + break; + case ARG_CAMERA_CAPTURE_FOURCC: + g_value_set_uint(value, camerasrc->cap_fourcc); + break; + case ARG_CAMERA_CAPTURE_WIDTH: + g_value_set_int(value, camerasrc->cap_width); + break; + case ARG_CAMERA_CAPTURE_HEIGHT: + g_value_set_int(value, camerasrc->cap_height); + break; + case ARG_CAMERA_CAPTURE_INTERVAL: + g_value_set_int(value, camerasrc->cap_interval); + break; + case ARG_CAMERA_CAPTURE_COUNT: + g_value_set_int(value, camerasrc->cap_count); + break; + case ARG_CAMERA_CAPTURE_JPG_QUALITY: + g_value_set_int(value, camerasrc->cap_jpg_quality); + GST_INFO("GET jpeg compress ratio : %d", camerasrc->cap_jpg_quality); + break; + case ARG_CAMERA_CAPTURE_PROVIDE_EXIF: + g_value_set_boolean(value, camerasrc->cap_provide_exif); + GST_INFO("Is Exif provided? : %d", camerasrc->cap_provide_exif); + break; + case ARG_VFLIP: + g_value_set_boolean(value, camerasrc->vflip); + break; + case ARG_HFLIP: + g_value_set_boolean(value, camerasrc->hflip); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } + + return; +} + + +static GstStateChangeReturn gst_tizencamerasrc_change_state(GstElement *element, GstStateChange transition) +{ + GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS; + GstTizenCameraSrc *camerasrc; + camerasrc = GST_TIZENCAMERA_SRC (element); + + switch (transition) { + case GST_STATE_CHANGE_NULL_TO_READY: + GST_INFO_OBJECT(camerasrc, "GST CAMERA SRC: NULL -> READY"); + GST_INFO(" gst_tizencamerasrc_create"); + if (!gst_tizencamerasrc_create(camerasrc)){ + goto statechange_failed; + } + break; + case GST_STATE_CHANGE_READY_TO_PAUSED: + GST_INFO_OBJECT(camerasrc, "GST CAMERA SRC: READY -> PAUSED"); + ret = GST_STATE_CHANGE_NO_PREROLL; + break; + case GST_STATE_CHANGE_PAUSED_TO_PLAYING: + GST_INFO_OBJECT(camerasrc, "GST CAMERA SRC: PAUSED -> PLAYING"); + break; + default: + break; + } + + ret = GST_ELEMENT_CLASS(gst_tizencamerasrc_parent_class)->change_state(element, transition); + if (ret == GST_STATE_CHANGE_FAILURE){ + return ret; + } + + switch (transition) { + case GST_STATE_CHANGE_PLAYING_TO_PAUSED: + GST_INFO_OBJECT(camerasrc, "GST CAMERA SRC: PLAYING -> PAUSED"); + ret = GST_STATE_CHANGE_NO_PREROLL; + break; + case GST_STATE_CHANGE_PAUSED_TO_READY: + GST_INFO_OBJECT(camerasrc, "GST CAMERA SRC: PAUSED -> READY"); + break; + case GST_STATE_CHANGE_READY_TO_NULL: + GST_INFO_OBJECT(camerasrc, "GST CAMERA SRC: READY -> NULL"); + GST_INFO(" gst_tizencamerasrc_destroy"); + if (!gst_tizencamerasrc_destroy(camerasrc)){ + goto statechange_failed; + } + break; + default: + break; + } + + return ret; + + statechange_failed: + /* subclass must post a meaningful error message */ + GST_ERROR_OBJECT(camerasrc, "state change failed"); + + return GST_STATE_CHANGE_FAILURE; +} + + +static void gst_tizencamerasrc_finalize(GObject *object) +{ + GstTizenCameraSrc *camerasrc = GST_TIZENCAMERA_SRC(object); + + GST_INFO("ENTERED"); + + g_cond_clear(&camerasrc->buffer_cond); + g_mutex_clear(&camerasrc->buffer_lock); + SAFE_FREE_GQUEUE(camerasrc->preview_buffer_list); + + if (G_OBJECT_CLASS (gst_tizencamerasrc_parent_class)->finalize) + G_OBJECT_CLASS(gst_tizencamerasrc_parent_class)->finalize(object); + + GST_INFO("LEAVED"); + + return; +} + + +void gst_tizencamerasrc_set_capture_command(GstTizenCameraSrc *camerasrc, GstCameraControlCaptureCommand cmd) +{ + if (camerasrc == NULL) { + GST_ERROR_OBJECT(camerasrc, "camerasrc is NULL"); + return; + } + + GST_INFO_OBJECT(camerasrc, "ENTERED"); + + if (cmd == GST_CAMERA_CONTROL_CAPTURE_COMMAND_START) + gst_tizencamerasrc_capture_start(camerasrc); + else if (cmd == GST_CAMERA_CONTROL_CAPTURE_COMMAND_STOP) + gst_tizencamerasrc_capture_stop(camerasrc); + else + GST_WARNING_OBJECT(camerasrc, "not supported command %d", cmd); + + GST_INFO_OBJECT(camerasrc, "LEAVE"); + + return; +} + + +static gboolean +gst_tizencamerasrc_negotiate (GstBaseSrc * basesrc) +{ + GstCaps *thiscaps; + GstCaps *caps = NULL; + GstCaps *peercaps = NULL; + gboolean result = FALSE; + GstStructure *s; + GstTizenCameraSrc *camerasrc = GST_TIZENCAMERA_SRC(basesrc); + + GST_INFO_OBJECT(camerasrc, "ENTERED"); + /* first see what is possible on our source pad */ + thiscaps = gst_pad_query_caps (GST_BASE_SRC_PAD (basesrc), NULL); + GST_DEBUG_OBJECT (basesrc, "caps of src: %" GST_PTR_FORMAT, thiscaps); + + /* nothing or anything is allowed, we're done */ + if (thiscaps == NULL || gst_caps_is_any (thiscaps)) + goto no_nego_needed; + + /* get the peer caps */ + peercaps = gst_pad_peer_query_caps (GST_BASE_SRC_PAD (basesrc), NULL); + GST_DEBUG_OBJECT (basesrc, "caps of peer: %" GST_PTR_FORMAT, peercaps); + //LOG_CAPS (basesrc, peercaps); + if (peercaps && !gst_caps_is_any (peercaps)) { + GstCaps *icaps = NULL; + int i; + + /* Prefer the first caps we are compatible with that the peer proposed */ + for (i = 0; i < gst_caps_get_size (peercaps); i++) { + /* get intersection */ + GstCaps *ipcaps = gst_caps_copy_nth (peercaps, i); + + GST_DEBUG_OBJECT (basesrc, "peer: %" GST_PTR_FORMAT, ipcaps); + icaps = gst_caps_intersect (thiscaps, ipcaps); + gst_caps_unref (ipcaps); + + /*s = gst_caps_get_structure (icaps, 0); + gst_structure_get_fourcc(s, "format", &camerasrc->fourcc); + if ((camerasrc->fourcc == GST_MAKE_FOURCC('S','N','1','2')) || + (camerasrc->fourcc == GST_MAKE_FOURCC('S','T','1','2'))) { + break; + }*/ + if (!gst_caps_is_empty (icaps)) + break; + + gst_caps_unref (icaps); + icaps = NULL; + } + + GST_DEBUG_OBJECT (basesrc, "intersect: %" GST_PTR_FORMAT, icaps); + if (icaps) { + /* If there are multiple intersections pick the one with the smallest + * resolution strictly bigger then the first peer caps */ + if (gst_caps_get_size (icaps) > 1) { + s = gst_caps_get_structure (peercaps, 0); + int best = 0; + int twidth, theight; + int width = G_MAXINT, height = G_MAXINT; + + if (gst_structure_get_int (s, "width", &twidth) + && gst_structure_get_int (s, "height", &theight)) { + + /* Walk the structure backwards to get the first entry of the + * smallest resolution bigger (or equal to) the preferred resolution) + */ + for (i = gst_caps_get_size (icaps) - 1; i >= 0; i--) { + GstStructure *is = gst_caps_get_structure (icaps, i); + int w, h; + + if (gst_structure_get_int (is, "width", &w) + && gst_structure_get_int (is, "height", &h)) { + if (w >= twidth && w <= width && h >= theight && h <= height) { + width = w; + height = h; + best = i; + } + } + } + } + + caps = gst_caps_copy_nth (icaps, best); + gst_caps_unref (icaps); + } else { + caps = icaps; + } + } + gst_caps_unref (thiscaps); + gst_caps_unref (peercaps); + } else { + /* no peer or peer have ANY caps, work with our own caps then */ + caps = thiscaps; + } + if (caps) { + caps = gst_caps_fixate(caps); + + /* now fixate */ + if (!gst_caps_is_empty (caps)) { + GST_DEBUG_OBJECT (basesrc, "fixated to: %" GST_PTR_FORMAT, caps); + + if (gst_caps_is_any (caps)) { + /* hmm, still anything, so element can do anything and + * nego is not needed */ + result = TRUE; + } else if (gst_caps_is_fixed (caps)) { + /* yay, fixed caps, use those then */ + result = gst_tizencamerasrc_set_caps(basesrc, caps); + } + } + gst_caps_unref (caps); + } + return result; + +no_nego_needed: + { + GST_DEBUG_OBJECT (basesrc, "no negotiation needed"); + if (thiscaps) + gst_caps_unref (thiscaps); + return TRUE; + } +} + + +static GstCaps *gst_tizencamerasrc_get_caps(GstBaseSrc *src, GstCaps *filter) +{ + GstTizenCameraSrc *camerasrc = GST_TIZENCAMERA_SRC(src); + GstCaps *ret = NULL; + + GST_DEBUG_OBJECT(camerasrc, "ENTERED"); + + if (camerasrc->mode == VIDEO_IN_MODE_NONE) { + GST_INFO_OBJECT(camerasrc, "Just return template caps."); + GST_DEBUG_OBJECT(camerasrc, "LEAVED"); + + ret = gst_pad_get_pad_template_caps(GST_BASE_SRC_PAD(camerasrc)); + return filter ? gst_caps_intersect(ret, filter) : gst_caps_copy(ret); + } + + /*FIXME: Using "VIDIOC_ENUM_FMT".*/ + ret = gst_caps_copy(gst_pad_get_pad_template_caps(GST_BASE_SRC_PAD(camerasrc))); + + if (filter != NULL) { + gst_caps_take(&ret, gst_caps_intersect(ret, filter)); + } + + GST_INFO_OBJECT(camerasrc, "probed caps: %p", ret); + GST_DEBUG_OBJECT(camerasrc, "LEAVED"); + + return ret; +} + + +static gboolean _gst_tizencamerasrc_get_raw_pixel_info(int fourcc, int *pix_format) +{ + if (pix_format == NULL) { + GST_ERROR("NULL pointer"); + return FALSE; + } + + switch (fourcc) { + case GST_MAKE_FOURCC('I','4','2','0'): + case GST_MAKE_FOURCC('S','4','2','0'): + *pix_format = CAMERA_PIXEL_FORMAT_I420;; + break; + case GST_MAKE_FOURCC('Y','V','1','2'): + *pix_format = CAMERA_PIXEL_FORMAT_YV12; + break; + case GST_MAKE_FOURCC('Y','U','Y','V'): + case GST_MAKE_FOURCC('Y','U','Y','2'): + case GST_MAKE_FOURCC('S','U','Y','V'): + case GST_MAKE_FOURCC('S','U','Y','2'): + *pix_format = CAMERA_PIXEL_FORMAT_YUYV; + break; + case GST_MAKE_FOURCC('U','Y','V','Y'): + case GST_MAKE_FOURCC('S','Y','V','Y'): + *pix_format = CAMERA_PIXEL_FORMAT_UYVY; + break; + case GST_MAKE_FOURCC('N','V','1','2'): + case GST_MAKE_FOURCC('S','N','1','2'): + *pix_format = CAMERA_PIXEL_FORMAT_NV12; + break; + default: + GST_ERROR("unknown fourcc %c%c%c%c", + fourcc, fourcc >> 8, fourcc >> 16, fourcc >> 24); + return FALSE; + } + + return TRUE; +} + + +static gboolean _gst_tizencamerasrc_get_frame_size(int fourcc, int width, int height, unsigned int *outsize) +{ + switch (fourcc) { + case GST_MAKE_FOURCC('I','4','2','0'): /* V4L2_PIX_FMT_YUV420 */ + case GST_MAKE_FOURCC('I','Y','U','V'): + case GST_MAKE_FOURCC('Y','U','1','2'): + case GST_MAKE_FOURCC('Y','V','1','2'): + case GST_MAKE_FOURCC('S','4','2','0'): /* V4L2_PIX_FMT_NV12 tiled non-linear */ + *outsize = GST_ROUND_UP_4 (width) * GST_ROUND_UP_2 (height); + *outsize += 2 * ((GST_ROUND_UP_8 (width) / 2) * (GST_ROUND_UP_2 (height) / 2)); + break; + case GST_MAKE_FOURCC('Y','U','Y','V'): /* V4L2_PIX_FMT_YUYV */ + case GST_MAKE_FOURCC('Y','U','Y','2'): /* V4L2_PIX_FMT_YUYV */ + case GST_MAKE_FOURCC('S','U','Y','V'): + case GST_MAKE_FOURCC('S','U','Y','2'): + case GST_MAKE_FOURCC('U','Y','V','Y'): /* V4L2_PIX_FMT_UYVY */ + case GST_MAKE_FOURCC('S','Y','V','Y'): /* V4L2_PIX_FMT_UYVY */ + case GST_MAKE_FOURCC('4','2','2','P'): /* V4L2_PIX_FMT_YUV422P */ + case GST_MAKE_FOURCC('Y','4','2','B'): /* V4L2_PIX_FMT_YUV422P */ + case GST_MAKE_FOURCC('Y','4','1','P'): /* V4L2_PIX_FMT_Y41P */ + *outsize = (GST_ROUND_UP_2 (width) * 2) * height; + break; + case GST_MAKE_FOURCC('Y','4','1','B'): /* V4L2_PIX_FMT_YUV411P */ + *outsize = GST_ROUND_UP_4 (width) * height; + *outsize += 2 * ((GST_ROUND_UP_8 (width) / 4) * height); + break; + case GST_MAKE_FOURCC('N','V','1','2'): /* V4L2_PIX_FMT_NV12 */ + case GST_MAKE_FOURCC('N','V','2','1'): /* V4L2_PIX_FMT_NV21 */ + case GST_MAKE_FOURCC('S','N','1','2'): /* V4L2_PIX_FMT_NV12 non-linear */ + case GST_MAKE_FOURCC('S','N','2','1'): /* V4L2_PIX_FMT_NV21 non-linear */ + *outsize = GST_ROUND_UP_4 (width) * GST_ROUND_UP_2 (height); + *outsize += (GST_ROUND_UP_4 (width) * height) / 2; + break; + case GST_MAKE_FOURCC('J','P','E','G'): + case GST_MAKE_FOURCC('j','p','e','g'): + /* jpeg size can't be calculated here. */ + *outsize = 0; + break; + default: + /* unknown format!! */ + *outsize = 0; + break; + } + + return TRUE; +} + + +static gboolean gst_tizencamerasrc_get_caps_info(GstTizenCameraSrc *camerasrc, GstCaps *caps, guint *size) +{ + gint fps_n = 0; + gint fps_d = 0; + gint width = 0; + gint height = 0; + gint rotate = 0; + gchar *caps_string = NULL; + const gchar *mimetype; + GstVideoInfo caps_info; + const gchar *caps_format_name = NULL; + guint32 caps_fourcc = 0; + const GValue *framerate; + GstStructure *structure = NULL; + + GST_INFO_OBJECT(camerasrc, "ENTERED Collect data for given caps.(caps:%p)", caps); + + structure = gst_caps_get_structure(caps, 0); + + if (!gst_structure_get_int(structure, "width", &width)) { + goto _caps_info_failed; + } + + if (!gst_structure_get_int(structure, "height", &height)) { + goto _caps_info_failed; + } + + if (!gst_structure_get_int(structure, "rotate", &rotate)) { + GST_WARNING_OBJECT(camerasrc, "Failed to get rotate info in caps. set default 0."); + camerasrc->use_rotate_caps = FALSE; + } else { + GST_INFO_OBJECT(camerasrc, "Succeed to get rotate [%d] info in caps", rotate); + camerasrc->use_rotate_caps = TRUE; + } + + camerasrc->width = width; + camerasrc->height = height; + camerasrc->rotate = rotate; + + framerate = gst_structure_get_value(structure, "framerate"); + if (!framerate) { + GST_INFO("Set FPS as default(30/1)"); + + /* set default fps if framerate is not existed in caps */ + fps_n = _DEFAULT_FPS; + fps_d = 1; + } else { + fps_n = gst_value_get_fraction_numerator(framerate); + fps_d = gst_value_get_fraction_denominator(framerate); + + /* numerator and denominator should be bigger than zero */ + if (fps_n <= 0) { + GST_WARNING("numerator of FPS is %d. make it default(15).", fps_n); + fps_n = _DEFAULT_FPS; + } + + if (fps_d <= 0) { + GST_WARNING("denominator of FPS is %d. make it 1.", fps_d); + fps_d = 1; + } + } + + camerasrc->fps = (int)((float)fps_n / (float)fps_d); + + mimetype = gst_structure_get_name (structure); + + *size = 0; + + if (!strcmp(mimetype, "video/x-raw")) { + gst_video_info_init(&caps_info); + if (gst_video_info_from_caps(&caps_info, caps) && + GST_VIDEO_INFO_IS_YUV(&caps_info)) { + caps_format_name = gst_structure_get_string(structure, "format"); + if (caps_format_name == NULL) { + GST_ERROR_OBJECT(camerasrc, "Getting format name is NULL."); + goto _caps_info_failed; + } + + strncpy(camerasrc->format_name, caps_format_name, sizeof(camerasrc->format_name)); + caps_fourcc = MAKE_FOURCC_FROM_STRING(camerasrc->format_name); + + _gst_tizencamerasrc_get_frame_size(caps_fourcc, width, height, size); + _gst_tizencamerasrc_get_raw_pixel_info(caps_fourcc, &camerasrc->pix_format); + } else { + GST_ERROR_OBJECT(camerasrc, "video/x-raw, but NOT YUV"); + goto _caps_info_failed; + } + } else { + GST_ERROR_OBJECT(camerasrc, "NOT video/x-raw"); + goto _caps_info_failed; + } + + GST_INFO_OBJECT(camerasrc, "pixformat %d, size %d", camerasrc->pix_format, *size); + + caps_string = gst_caps_to_string(caps); + if (caps_string) { + GST_INFO_OBJECT(camerasrc, "caps : [%s]", caps_string); + g_free(caps_string); + caps_string = NULL; + } + + return TRUE; + +_caps_info_failed: + GST_INFO_OBJECT(camerasrc, "Failed to get caps info."); + GST_DEBUG_OBJECT(camerasrc, "LEAVED"); + return FALSE; +} + + +static void _gst_tizencamerasrc_post_message_int(GstTizenCameraSrc *camerasrc, const char *msg_name, const char *field_name, int value) +{ + GstMessage *m = NULL; + GstStructure *s = NULL; + + if (!camerasrc || !msg_name || !field_name) { + GST_ERROR("pointer is NULL %p, %p, %p", camerasrc, msg_name, field_name); + return; + } + + GST_INFO("post message [%s] %s %d", msg_name, field_name, value); + + s = gst_structure_new(msg_name, field_name, G_TYPE_INT, value, NULL); + if (s == NULL) { + GST_ERROR("gst_structure_new failed"); + gst_tizencamerasrc_error_handler(camerasrc, CAMERA_ERROR_OUT_OF_MEMORY); + return; + } + + m = gst_message_new_element(GST_OBJECT(camerasrc), s); + if (m == NULL) { + GST_ERROR("gst_message_new_element failed"); + gst_tizencamerasrc_error_handler(camerasrc, CAMERA_ERROR_OUT_OF_MEMORY); + return; + } + + gst_element_post_message(GST_ELEMENT(camerasrc), m); + + return; +} + + +static gboolean gst_tizencamerasrc_set_caps(GstBaseSrc *src, GstCaps *caps) +{ + guint size; + GstTizenCameraSrc *camerasrc = NULL; + gboolean res = FALSE; + + camerasrc = GST_TIZENCAMERA_SRC(src); + + GST_INFO_OBJECT(camerasrc, "ENTERED"); + + if (camerasrc->mode == VIDEO_IN_MODE_PREVIEW || + camerasrc->mode == VIDEO_IN_MODE_VIDEO) { + GST_INFO_OBJECT(camerasrc, "Proceed set_caps"); + GST_INFO(" gst_tizencamerasrc_stop"); + if (!gst_tizencamerasrc_stop(camerasrc)) { + GST_INFO_OBJECT(camerasrc, "Cam sensor stop failed."); + } + } else if (camerasrc->mode == VIDEO_IN_MODE_CAPTURE) { + GST_ERROR_OBJECT(camerasrc, "A mode of avsystem camera is capture. Not to proceed set_caps."); + GST_DEBUG_OBJECT(camerasrc, "LEAVED"); + return FALSE; + } else { + GST_INFO_OBJECT(camerasrc, "A mode of avsystem camera is unknown[%d]. Proceed set_caps.", camerasrc->mode); + } + + /* we want our own v4l2 type of fourcc codes */ + if (!gst_tizencamerasrc_get_caps_info(camerasrc, caps, &size)) { + GST_INFO_OBJECT(camerasrc, "can't get capture information from caps %p", caps); + return FALSE; + } + + GST_INFO(" gst_tizencamerasrc_start"); + if (!gst_tizencamerasrc_start(camerasrc)) { + GST_INFO_OBJECT (camerasrc, "Cam sensor start failed."); + } + + res = gst_pad_push_event (GST_BASE_SRC_PAD (src), gst_event_new_caps (caps)); + + GST_INFO_OBJECT (camerasrc, "LEAVED"); + + return res; +} + + +static void gst_tizencamerasrc_class_init(GstTizenCameraSrcClass *klass) +{ + GST_DEBUG_CATEGORY_INIT(camerasrc_debug, "camerasrc", 0, "camerasrc element"); + + GObjectClass *gobject_class; + GstElementClass *element_class; + GstBaseSrcClass *basesrc_class; + GstPushSrcClass *pushsrc_class; + + GST_DEBUG("ENTERED"); + + gobject_class = G_OBJECT_CLASS(klass); + element_class = GST_ELEMENT_CLASS(klass); + basesrc_class = GST_BASE_SRC_CLASS(klass); + pushsrc_class = GST_PUSH_SRC_CLASS(klass); + + gobject_class->set_property = gst_tizencamerasrc_set_property; + gobject_class->get_property = gst_tizencamerasrc_get_property; + gobject_class->finalize = gst_tizencamerasrc_finalize; + element_class->change_state = gst_tizencamerasrc_change_state; + gst_element_class_add_pad_template(element_class, gst_static_pad_template_get (&src_factory)); + gst_element_class_set_static_metadata(element_class, + "Camera Source GStreamer Plug-in", + "Source/Video", + "camera src for videosrc based GStreamer Plug-in", + "Jeongmo Yang "); + basesrc_class->start = gst_tizencamerasrc_src_start; + basesrc_class->stop = gst_tizencamerasrc_src_stop; + basesrc_class->get_caps = gst_tizencamerasrc_get_caps; + basesrc_class->set_caps = gst_tizencamerasrc_set_caps; + basesrc_class->negotiate = gst_tizencamerasrc_negotiate; + pushsrc_class->create = gst_tizencamerasrc_src_create; + + g_object_class_install_property(gobject_class, ARG_CAMERA_HIGH_SPEED_FPS, + g_param_spec_int("high-speed-fps", "Fps for high speed recording", + "If this value is 0, the element doesn't activate high speed recording.", + 0, G_MAXINT, _DEFAULT_HIGH_SPEED_FPS, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property(gobject_class, ARG_CAMERA_AUTO_FPS, + g_param_spec_boolean("fps-auto", "FPS Auto", + "Field for auto fps setting", + _DEFAULT_FPS_AUTO, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property(gobject_class, ARG_CAMERA_ID, + g_param_spec_int("camera-id", "index number of camera to activate", + "index number of camera to activate", + _CAMERA_ID_MIN, _CAMERA_ID_MAX, 0, + G_PARAM_READWRITE)); + + /*Capture*/ + g_object_class_install_property(gobject_class, ARG_CAMERA_CAPTURE_FOURCC, + g_param_spec_uint("capture-fourcc", "Capture format", + "Fourcc value for capture format", + 0, G_MAXUINT, 0, + G_PARAM_READWRITE)); + + g_object_class_install_property(gobject_class, ARG_CAMERA_CAPTURE_WIDTH, + g_param_spec_int("capture-width", "Capture width", + "Width for camera size to capture", + 0, G_MAXINT, _DEFAULT_CAP_WIDTH, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property(gobject_class, ARG_CAMERA_CAPTURE_HEIGHT, + g_param_spec_int("capture-height", "Capture height", + "Height for camera size to capture", + 0, G_MAXINT, _DEFAULT_CAP_HEIGHT, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property(gobject_class, ARG_CAMERA_CAPTURE_INTERVAL, + g_param_spec_int("capture-interval", "Capture interval", + "Interval time to capture (millisecond)", + 0, G_MAXINT, _DEFAULT_CAP_INTERVAL, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property(gobject_class, ARG_CAMERA_CAPTURE_COUNT, + g_param_spec_int("capture-count", "Capture count", + "Capture count for multishot", + 1, G_MAXINT, _DEFAULT_CAP_COUNT, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property(gobject_class, ARG_CAMERA_CAPTURE_JPG_QUALITY, + g_param_spec_int("capture-jpg-quality", "JPEG Capture compress ratio", + "Quality of capture image compress ratio", + 1, 100, _DEFAULT_CAP_JPG_QUALITY, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property(gobject_class, ARG_CAMERA_CAPTURE_PROVIDE_EXIF, + g_param_spec_boolean("provide-exif", "Whether EXIF is provided", + "Does capture provide EXIF?", + _DEFAULT_CAP_PROVIDE_EXIF, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property(gobject_class, ARG_VFLIP, + g_param_spec_boolean("vflip", "Flip vertically", + "Flip camera input vertically", + 0, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property(gobject_class, ARG_HFLIP, + g_param_spec_boolean("hflip", "Flip horizontally", + "Flip camera input horizontally", + 0, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + /** + * GstTizenCameraSrc::still-capture: + * @camerasrc: the camerasrc instance + * @buffer: the buffer that will be pushed - Main + * @buffer: the buffer that will be pushed - Thumbnail + * @buffer: the buffer that will be pushed - Screennail + * + * This signal gets emitted before sending the buffer. + */ + gst_tizencamerasrc_signals[SIGNAL_STILL_CAPTURE] = + g_signal_new("still-capture", + G_TYPE_FROM_CLASS(klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET(GstTizenCameraSrcClass, still_capture), + NULL, + NULL, + g_cclosure_user_marshal_VOID__OBJECT_OBJECT_OBJECT, + G_TYPE_NONE, + 3, /* Number of parameter */ + GST_TYPE_SAMPLE, /* Main image buffer */ + GST_TYPE_SAMPLE, /* Thumbnail image buffer */ + GST_TYPE_SAMPLE); /* Screennail image buffer */ + + GST_DEBUG("LEAVED"); + + return; +} + + +static void gst_tizencamerasrc_init(GstTizenCameraSrc *camerasrc) +{ + GST_INFO("ENTERED"); + + camerasrc->hal_intf_handle = NULL; + camerasrc->mode = VIDEO_IN_MODE_NONE; + camerasrc->firsttime = TRUE; + camerasrc->cap_count_current = -1; + camerasrc->cap_count_reverse = _DEFAULT_CAP_COUNT; + + /*camera*/ + camerasrc->fps = _DEFAULT_FPS; + camerasrc->rotate = 0; + camerasrc->use_rotate_caps = FALSE; + camerasrc->high_speed_fps = _DEFAULT_HIGH_SPEED_FPS; + camerasrc->fps_auto = _DEFAULT_FPS_AUTO; + camerasrc->pix_format = _DEFAULT_PIX_FORMAT; + strcpy(camerasrc->format_name, _DEFAULT_PIX_FORMAT_NAME); + camerasrc->buffer_running = FALSE; + camerasrc->vflip = FALSE; + camerasrc->hflip = FALSE; + camerasrc->camera_id = _DEFAULT_CAMERA_ID; + camerasrc->preview_buffer_list = g_queue_new (); + + /*capture*/ + camerasrc->cap_fourcc = MAKE_FOURCC_FROM_STRING(_DEFAULT_CAPTURE_FORMAT_NAME); + camerasrc->cap_width = _DEFAULT_CAP_WIDTH; + camerasrc->cap_height = _DEFAULT_CAP_HEIGHT; + camerasrc->cap_interval = _DEFAULT_CAP_INTERVAL; + camerasrc->cap_count = _DEFAULT_CAP_COUNT; + camerasrc->cap_jpg_quality = _DEFAULT_CAP_JPG_QUALITY; + camerasrc->cap_provide_exif = _DEFAULT_CAP_PROVIDE_EXIF; + + g_mutex_init(&camerasrc->buffer_lock); + g_cond_init(&camerasrc->buffer_cond); + + /* we operate in time */ + gst_base_src_set_format(GST_BASE_SRC(camerasrc), GST_FORMAT_TIME); + gst_base_src_set_live(GST_BASE_SRC(camerasrc), TRUE); + gst_base_src_set_do_timestamp(GST_BASE_SRC(camerasrc), TRUE); + + GST_INFO("LEAVED"); + + return; +} + +#if 0 +static unsigned long _get_current_time(void) +{ + struct timeval lc_time; + gettimeofday(&lc_time, NULL); + return ((unsigned long)(lc_time.tv_sec * 1000L) + (unsigned long)(lc_time.tv_usec / 1000L)); +} +#endif + + +#if _ENABLE_CAMERASRC_DEBUG +#include +static int __util_write_file(char *filename, void *data, int size) +{ + FILE *fp = NULL; + + fp = fopen(filename, "wb"); + if (!fp) { + return FALSE; + } + + fwrite(data, 1, size, fp); + fclose(fp); + + return TRUE; +} +#endif + + +static gboolean plugin_init(GstPlugin *plugin) +{ + gboolean error; + + error = gst_element_register(plugin, "tizencamerasrc", GST_RANK_PRIMARY + 100, GST_TYPE_TIZENCAMERA_SRC); + + return error; +} + + +GST_PLUGIN_DEFINE(GST_VERSION_MAJOR, + GST_VERSION_MINOR, + tizencamerasrc, + "Tizen reference camera source plug-in", + plugin_init, + PACKAGE_VERSION, + "LGPL", + "Samsung Electronics Co", + "http://www.samsung.com") + +/* GstURIHandler interface */ +static GstURIType +gst_tizencamerasrc_uri_get_type (GType type) +{ + return GST_URI_SRC; +} + +static const gchar * const* +gst_tizencamerasrc_uri_get_protocols (GType type) +{ + static const gchar *protocols[] = { "camera", NULL }; + return protocols; +} + +static gchar * +gst_tizencamerasrc_uri_get_uri (GstURIHandler * handler) +{ + return strdup("camera://0"); +} + +static gboolean +gst_tizencamerasrc_uri_set_uri (GstURIHandler * handler, const gchar * uri, GError **error) +{ + GstTizenCameraSrc *camerasrc = GST_TIZENCAMERA_SRC (handler); + const gchar *device = "0"; + if (strcmp (uri, "camera://") != 0) { + device = uri + 9; + } + g_object_set (camerasrc, "camera-id", atoi(device), NULL); + + return TRUE; +} + + +static void +gst_tizencamerasrc_uri_handler_init (gpointer g_iface, gpointer iface_data) +{ + GstURIHandlerInterface *iface = (GstURIHandlerInterface *) g_iface; + + iface->get_type = gst_tizencamerasrc_uri_get_type; + iface->get_protocols = gst_tizencamerasrc_uri_get_protocols; + iface->get_uri = gst_tizencamerasrc_uri_get_uri; + iface->set_uri = gst_tizencamerasrc_uri_set_uri; +} +/* EOF */ diff --git a/tizencamerasrc/src/gsttizencamerasrccolorbalance.c b/tizencamerasrc/src/gsttizencamerasrccolorbalance.c new file mode 100644 index 0000000..3dcc761 --- /dev/null +++ b/tizencamerasrc/src/gsttizencamerasrccolorbalance.c @@ -0,0 +1,92 @@ +/* + * gsttizencamerasrccolorbalance.c + * + * Copyright (c) 2018 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Jeongmo Yang + * + * This library is free software; you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License as published by the + * Free Software Foundation; either version 2.1 of the License, or (at your option) + * any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, Inc., 51 + * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include "gsttizencamerasrccolorbalance.h" + +G_DEFINE_TYPE(GstTizenCameraSrcColorBalanceChannel, + gst_tizencamerasrc_color_balance_channel, + GST_TYPE_COLOR_BALANCE_CHANNEL); + +#ifndef GST_CAT_DEFAULT +GST_DEBUG_CATEGORY_EXTERN(camerasrc_debug); +#define GST_CAT_DEFAULT camerasrc_debug +#endif /* GST_CAT_DEFAULT */ + + +static void gst_tizencamerasrc_color_balance_channel_class_init(GstTizenCameraSrcColorBalanceChannelClass *klass) +{ +} + +static void gst_tizencamerasrc_color_balance_channel_init(GstTizenCameraSrcColorBalanceChannel *camerasrc_color_channel) +{ + camerasrc_color_channel->id = (guint32) - 1; +} + +static G_GNUC_UNUSED gboolean gst_tizencamerasrc_color_balance_contains_channel(GstTizenCameraSrc *camerasrc, GstTizenCameraSrcColorBalanceChannel *camerasrc_color_channel) +{ + const GList *item = NULL; + + for (item = camerasrc->colors ; item != NULL ; item = item->next) { + if (item->data == camerasrc_color_channel) + return TRUE; + } + + return FALSE; +} + +const GList *gst_tizencamerasrc_color_balance_list_channels(GstTizenCameraSrc *camerasrc) +{ + return camerasrc->colors; +} + +void gst_tizencamerasrc_color_balance_set_value(GstTizenCameraSrc *camerasrc, GstColorBalanceChannel *color_channel, gint value) +{ + GstTizenCameraSrcColorBalanceChannel *camerasrc_color_channel = GST_TIZENCAMERASRC_COLOR_BALANCE_CHANNEL(color_channel); + + /* assert that we're opened and that we're using a known item */ + g_return_if_fail(camerasrc); + g_return_if_fail(gst_tizencamerasrc_color_balance_contains_channel(camerasrc, camerasrc_color_channel)); + + /* TODO */ + + return; +} + +gint gst_tizencamerasrc_color_balance_get_value(GstTizenCameraSrc *camerasrc, GstColorBalanceChannel *color_channel) +{ + int value = 0; + GstTizenCameraSrcColorBalanceChannel *camerasrc_color_channel = GST_TIZENCAMERASRC_COLOR_BALANCE_CHANNEL(color_channel); + + /* assert that we're opened and that we're using a known item */ + g_return_val_if_fail(camerasrc, FALSE); + g_return_val_if_fail(gst_tizencamerasrc_color_balance_contains_channel(camerasrc, camerasrc_color_channel), FALSE); + + /* TODO */ + + return value; +} diff --git a/tizencamerasrc/src/gsttizencamerasrccontrol.c b/tizencamerasrc/src/gsttizencamerasrccontrol.c new file mode 100644 index 0000000..1f2140f --- /dev/null +++ b/tizencamerasrc/src/gsttizencamerasrccontrol.c @@ -0,0 +1,727 @@ +/* + * gsttizencamerasrccontrol.c + * + * Copyright (c) 2018 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Jeongmo Yang + * + * This library is free software; you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License as published by the + * Free Software Foundation; either version 2.1 of the License, or (at your option) + * any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, Inc., 51 + * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include "gsttizencamerasrccontrol.h" +#include "camera_hal_interface.h" + +#define gst_tizencamerasrc_debug(fmt, args...) GST_INFO(fmt, ##args) + +#define CAMERA_CONTROL_AF_STOP_TOTALTIME 2000000 +#define CAMERA_CONTROL_AF_STOP_INTERVAL 20000 + +/** + * Enumeration of Wide Dynamic Range + */ +enum { + CAMERA_CONTROL_WDR_OFF = 1, + CAMERA_CONTROL_WDR_ON, + CAMERA_CONTROL_WDR_AUTO, +}; + +G_DEFINE_TYPE(GstTizenCamerasrcControlChannel, + gst_tizencamerasrc_control_channel, + GST_TYPE_CAMERA_CONTROL_CHANNEL); + +static void gst_tizencamerasrc_control_channel_class_init(GstTizenCamerasrcControlChannelClass *klass) +{ + gst_tizencamerasrc_debug("class init"); +} + +static void gst_tizencamerasrc_control_channel_init(GstTizenCamerasrcControlChannel *control_channel) +{ + gst_tizencamerasrc_debug("channel init"); + control_channel->id = (guint32) - 1; +} + +static G_GNUC_UNUSED gboolean gst_tizencamerasrc_control_contains_channel(GstTizenCameraSrc *camerasrc, GstTizenCamerasrcControlChannel *camerasrc_control_channel) +{ + gst_tizencamerasrc_debug("contains channel"); + + const GList *item = NULL; + + for (item = camerasrc->camera_controls ; item != NULL ; item = item->next) { + if (item->data == camerasrc_control_channel) { + return TRUE; + } + } + + return FALSE; +} + +const GList *gst_tizencamerasrc_control_list_channels(GstTizenCameraSrc *camerasrc) +{ + gst_tizencamerasrc_debug("list channels"); + return camerasrc->camera_controls; +} + +gboolean gst_tizencamerasrc_control_set_value(GstTizenCameraSrc *camerasrc, GstCameraControlChannel *control_channel, gint value) +{ + gst_tizencamerasrc_debug("set value : %d", value); + + GstTizenCamerasrcControlChannel *camerasrc_control_channel = GST_TIZENCAMERASRC_CONTROL_CHANNEL(control_channel); + + g_return_val_if_fail(camerasrc, FALSE); + g_return_val_if_fail(gst_tizencamerasrc_control_contains_channel(camerasrc, camerasrc_control_channel), FALSE); + + return TRUE; +} + +gboolean gst_tizencamerasrc_control_get_value(GstTizenCameraSrc *camerasrc, GstCameraControlChannel *control_channel, gint *value) +{ + gst_tizencamerasrc_debug("get value"); + + GstTizenCamerasrcControlChannel *camerasrc_control_channel = GST_TIZENCAMERASRC_CONTROL_CHANNEL(control_channel); + + g_return_val_if_fail(camerasrc, FALSE); + g_return_val_if_fail(gst_tizencamerasrc_control_contains_channel(camerasrc, camerasrc_control_channel), FALSE); + + return TRUE; +} + +gboolean gst_tizencamerasrc_control_set_exposure(GstTizenCameraSrc *camerasrc, gint type, gint value1, gint value2) +{ + int ret = CAMERA_ERROR_NONE; + camera_fraction_t frac; + + g_return_val_if_fail(camerasrc, FALSE); + + gst_tizencamerasrc_debug("set exposure"); + + /* TODO : F number */ + switch (type) { + case GST_CAMERA_CONTROL_F_NUMBER: + ret = CAMERA_ERROR_NONE; + break; + case GST_CAMERA_CONTROL_SHUTTER_SPEED: + frac.numerator = value1; + frac.denominator = value2; + gst_tizencamerasrc_debug(" camerasrc_set_shutter_speed"); + ret = camera_hal_interface_set_command(camerasrc->hal_intf_handle, CAMERA_COMMAND_SHUTTER_SPEED, &frac); + break; + case GST_CAMERA_CONTROL_ISO: + gst_tizencamerasrc_debug(" camerasrc_set_iso_value"); + ret = camera_hal_interface_set_command(camerasrc->hal_intf_handle, CAMERA_COMMAND_ISO, &value1); + break; + case GST_CAMERA_CONTROL_PROGRAM_MODE: + gst_tizencamerasrc_debug(" camerasrc_set_control"); + ret = camera_hal_interface_set_command(camerasrc->hal_intf_handle, CAMERA_COMMAND_SCENE_MODE, &value1); + break; + case GST_CAMERA_CONTROL_EXPOSURE_MODE: + gst_tizencamerasrc_debug(" camerasrc_set_exposure_mode"); + ret = camera_hal_interface_set_command(camerasrc->hal_intf_handle, CAMERA_COMMAND_EXPOSURE_MODE, &value1); + break; + case GST_CAMERA_CONTROL_EXPOSURE_VALUE: + frac.numerator = value1; + frac.denominator = value2; + gst_tizencamerasrc_debug(" camerasrc_set_exposure_value"); + ret = camera_hal_interface_set_command(camerasrc->hal_intf_handle, CAMERA_COMMAND_EXPOSURE, &frac); + break; + default: + gst_tizencamerasrc_debug("Not supported type."); + return FALSE; + } + + if (ret != CAMERA_ERROR_NONE) { + gst_tizencamerasrc_debug("Failed to set exposure 0x%x Type[%d] value1[%d] value2[%d]", ret, type, value1, value2); + return FALSE; + } + + return TRUE; +} + +gboolean gst_tizencamerasrc_control_get_exposure(GstTizenCameraSrc *camerasrc, gint type, gint *value1, gint *value2) +{ + int ret = CAMERA_ERROR_NONE; + camera_fraction_t frac; + + g_return_val_if_fail(camerasrc, FALSE); + g_return_val_if_fail(value1, FALSE); + + gst_tizencamerasrc_debug("get exposure"); + + /* TODO : F number */ + switch (type) { + case GST_CAMERA_CONTROL_F_NUMBER: + break; + case GST_CAMERA_CONTROL_SHUTTER_SPEED: + g_return_val_if_fail(value2, FALSE); + ret = camera_hal_interface_get_command(camerasrc->hal_intf_handle, CAMERA_COMMAND_SHUTTER_SPEED, &frac); + if (ret == CAMERA_ERROR_NONE) { + *value1 = frac.numerator; + *value2 = frac.denominator; + } + break; + case GST_CAMERA_CONTROL_ISO: + ret = camera_hal_interface_get_command(camerasrc->hal_intf_handle, CAMERA_COMMAND_ISO, value1); + break; + case GST_CAMERA_CONTROL_PROGRAM_MODE: + ret = camera_hal_interface_get_command(camerasrc->hal_intf_handle, CAMERA_COMMAND_SCENE_MODE, value1); + break; + case GST_CAMERA_CONTROL_EXPOSURE_MODE: + ret = camera_hal_interface_get_command(camerasrc->hal_intf_handle, CAMERA_COMMAND_EXPOSURE_MODE, value1); + break; + case GST_CAMERA_CONTROL_EXPOSURE_VALUE: + g_return_val_if_fail(value2, FALSE); + ret = camera_hal_interface_get_command(camerasrc->hal_intf_handle, CAMERA_COMMAND_EXPOSURE, &frac); + if (ret == CAMERA_ERROR_NONE) { + *value1 = frac.numerator; + *value2 = frac.denominator; + } + break; + default: + gst_tizencamerasrc_debug("Not supported type."); + return FALSE; + } + + if (ret != CAMERA_ERROR_NONE) { + gst_tizencamerasrc_debug("Failed to get exposure 0x%x Type[%d]", ret, type); + return FALSE; + } + + return TRUE; +} + +gboolean gst_tizencamerasrc_control_set_capture_mode(GstTizenCameraSrc *camerasrc, gint type, gint value) +{ + int ret = CAMERA_ERROR_NONE; + + g_return_val_if_fail(camerasrc, FALSE); + + gst_tizencamerasrc_debug("set capture mode"); + + switch (type) { + case GST_CAMERA_CONTROL_CAPTURE_MODE: + break; + case GST_CAMERA_CONTROL_OUTPUT_MODE: + break; + case GST_CAMERA_CONTROL_FRAME_COUNT: + break; + case GST_CAMERA_CONTROL_JPEG_QUALITY: + break; + default: + gst_tizencamerasrc_debug("Not supported type."); + return FALSE; + } + + if (ret != CAMERA_ERROR_NONE) { + gst_tizencamerasrc_debug("Failed to set capture mode. Type[%d],value[%d],err code[%x]", type, value, ret); + return FALSE; + } + + return TRUE; +} + +gboolean gst_tizencamerasrc_control_get_capture_mode(GstTizenCameraSrc *camerasrc, gint type, gint *value) +{ + int ret = CAMERA_ERROR_NONE; + + g_return_val_if_fail(camerasrc, FALSE); + + gst_tizencamerasrc_debug("get capture mode"); + + switch (type) { + case GST_CAMERA_CONTROL_CAPTURE_MODE: + break; + case GST_CAMERA_CONTROL_OUTPUT_MODE: + break; + case GST_CAMERA_CONTROL_FRAME_COUNT: + break; + case GST_CAMERA_CONTROL_JPEG_QUALITY: + break; + default: + gst_tizencamerasrc_debug("Not supported type."); + return FALSE; + } + + if (ret != CAMERA_ERROR_NONE) { + gst_tizencamerasrc_debug("Failed to set capture mode. Type[%d],err code[%x]", type, ret); + return FALSE; + } + + return TRUE; +} + +gboolean gst_tizencamerasrc_control_set_strobe(GstTizenCameraSrc *camerasrc, gint type, gint value) +{ + int ret = CAMERA_ERROR_NONE; + + g_return_val_if_fail(camerasrc, FALSE); + + gst_tizencamerasrc_debug("set strobe"); + + switch (type) { + case GST_CAMERA_CONTROL_STROBE_MODE: + ret = camera_hal_interface_set_command(camerasrc->hal_intf_handle, CAMERA_COMMAND_FLASH_MODE, &value); + break; + case GST_CAMERA_CONTROL_STROBE_CONTROL: + case GST_CAMERA_CONTROL_STROBE_CAPABILITIES: + case GST_CAMERA_CONTROL_STROBE_STATUS: + case GST_CAMERA_CONTROL_STROBE_EV: + default: + gst_tizencamerasrc_debug("Not supported type[%d], return CAMERASRC_ERR_DEVICE_NOT_SUPPORT.", type); + ret = CAMERA_ERROR_DEVICE_NOT_SUPPORTED; + break; + } + + if (ret != CAMERA_ERROR_NONE) { + gst_tizencamerasrc_debug("Failed to set strobe. Type[%d],value[%d],err code[%x]", type, value, ret); + return FALSE; + } + + gst_tizencamerasrc_debug("Succeed to set strobe. Type[%d],value[%d]", type, value); + + return TRUE; +} + +gboolean gst_tizencamerasrc_control_get_strobe(GstTizenCameraSrc *camerasrc, gint type, gint *value) +{ + int ret = CAMERA_ERROR_NONE; + + g_return_val_if_fail(camerasrc, FALSE); + + gst_tizencamerasrc_debug("get strobe"); + + switch (type) { + case GST_CAMERA_CONTROL_STROBE_MODE: + ret = camera_hal_interface_get_command(camerasrc->hal_intf_handle, CAMERA_COMMAND_FLASH_MODE, value); + break; + case GST_CAMERA_CONTROL_STROBE_CONTROL: + case GST_CAMERA_CONTROL_STROBE_CAPABILITIES: + case GST_CAMERA_CONTROL_STROBE_STATUS: + case GST_CAMERA_CONTROL_STROBE_EV: + default: + gst_tizencamerasrc_debug("Not supported type[%d].", type); + ret = CAMERA_ERROR_DEVICE_NOT_SUPPORTED; + break; + } + + if (ret != CAMERA_ERROR_NONE) { + gst_tizencamerasrc_debug("Failed to get strobe. Type[%d],err code[%x]", type, ret); + return FALSE; + } + + return TRUE; +} + +gboolean gst_tizencamerasrc_control_set_detect(GstTizenCameraSrc *camerasrc, gint type, gint value) +{ + int ret = CAMERA_ERROR_NONE; + + g_return_val_if_fail(camerasrc, FALSE); + + gst_tizencamerasrc_debug("set detect"); + + /* TODO */ + switch (type) { + case GST_CAMERA_CONTROL_FACE_DETECT_MODE: + ret = camera_hal_interface_set_command(camerasrc->hal_intf_handle, CAMERA_COMMAND_FACE_DETECTION, &value); + break; + case GST_CAMERA_CONTROL_FACE_DETECT_NUMBER: + break; + case GST_CAMERA_CONTROL_FACE_FOCUS_SELECT: + break; + case GST_CAMERA_CONTROL_FACE_SELECT_NUMBER: + break; + case GST_CAMERA_CONTROL_FACE_DETECT_STATUS: + break; + default: + gst_tizencamerasrc_debug("Not supported type."); + return FALSE; + } + + if (ret != CAMERA_ERROR_NONE) { + gst_tizencamerasrc_debug("Failed to set detect. Type[%d],value[%d],err code[%x]", type, value, ret); + return FALSE; + } + + return TRUE; +} + +gboolean gst_tizencamerasrc_control_get_detect(GstTizenCameraSrc *camerasrc, gint type, gint *value) +{ + int ret = CAMERA_ERROR_NONE; + + g_return_val_if_fail(camerasrc, FALSE); + + gst_tizencamerasrc_debug("get detect"); + + /* TODO : detection number, focus select, select number, detect status */ + switch (type) { + case GST_CAMERA_CONTROL_FACE_DETECT_MODE: + ret = camera_hal_interface_get_command(camerasrc->hal_intf_handle, CAMERA_COMMAND_FACE_DETECTION, value); + break; + case GST_CAMERA_CONTROL_FACE_DETECT_NUMBER: + break; + case GST_CAMERA_CONTROL_FACE_FOCUS_SELECT: + break; + case GST_CAMERA_CONTROL_FACE_SELECT_NUMBER: + break; + case GST_CAMERA_CONTROL_FACE_DETECT_STATUS: + break; + default: + gst_tizencamerasrc_debug("Not supported type."); + return FALSE; + } + + if (ret != CAMERA_ERROR_NONE) { + gst_tizencamerasrc_debug("Failed to get detect. Type[%d],err code[%x]", type, ret); + return FALSE; + } + + return TRUE; +} + +gboolean gst_tizencamerasrc_control_set_zoom(GstTizenCameraSrc *camerasrc, gint type, gint value) +{ + int ret = CAMERA_ERROR_NONE; + + g_return_val_if_fail(camerasrc, FALSE); + + gst_tizencamerasrc_debug("set zoom"); + + switch (type) { + case GST_CAMERA_CONTROL_DIGITAL_ZOOM: + ret = camera_hal_interface_set_command(camerasrc->hal_intf_handle, CAMERA_COMMAND_DIGITAL_ZOOM, &value); + break; + case GST_CAMERA_CONTROL_OPTICAL_ZOOM: + ret = camera_hal_interface_set_command(camerasrc->hal_intf_handle, CAMERA_COMMAND_OPTICAL_ZOOM, &value); + break; + default: + gst_tizencamerasrc_debug("Not supported type."); + return FALSE; + } + + if (ret != CAMERA_ERROR_NONE) { + gst_tizencamerasrc_debug("Failed to set zoom. Type[%d],value[%d],err code[%x]", type, value, ret); + return FALSE; + } + + return TRUE; +} + +gboolean gst_tizencamerasrc_control_get_zoom(GstTizenCameraSrc *camerasrc, gint type, gint *value) +{ + int ret = CAMERA_ERROR_NONE; + + g_return_val_if_fail(camerasrc, FALSE); + + gst_tizencamerasrc_debug("get zoom"); + + switch (type) { + case GST_CAMERA_CONTROL_DIGITAL_ZOOM: + ret = camera_hal_interface_get_command(camerasrc->hal_intf_handle, CAMERA_COMMAND_DIGITAL_ZOOM, value); + break; + case GST_CAMERA_CONTROL_OPTICAL_ZOOM: + ret = camera_hal_interface_get_command(camerasrc->hal_intf_handle, CAMERA_COMMAND_OPTICAL_ZOOM, value); + break; + default: + gst_tizencamerasrc_debug("Not supported type."); + return FALSE; + } + + if (ret != CAMERA_ERROR_NONE) { + gst_tizencamerasrc_debug("Failed to get zoom. Type[%d],err code[%x]", type, ret); + return FALSE; + } + + return TRUE; +} + +gboolean gst_tizencamerasrc_control_set_focus(GstTizenCameraSrc *camerasrc, gint focus_mode, gint focus_range) +{ + int ret = CAMERA_ERROR_NONE; + int64_t error_cmd = 0; + + g_return_val_if_fail(camerasrc, FALSE); + + gst_tizencamerasrc_debug("set focus"); + + camera_batch_command_control_t batch_cmd; + + memset(&batch_cmd, 0x0, sizeof(camera_batch_command_control_t)); + + batch_cmd.focus_mode = focus_mode; + batch_cmd.command_set_flag |= CAMERA_COMMAND_FOCUS_MODE; + batch_cmd.focus_range = focus_range; + batch_cmd.command_set_flag |= CAMERA_COMMAND_FOCUS_RANGE; + + ret = camera_hal_interface_set_batch_command(camerasrc->hal_intf_handle, &batch_cmd, &error_cmd); + if (ret != CAMERA_ERROR_NONE) { + gst_tizencamerasrc_debug("Failed to set AF mode. error cmd %lld", error_cmd); + return FALSE; + } + + return TRUE; +} + +gboolean gst_tizencamerasrc_control_get_focus(GstTizenCameraSrc *camerasrc, gint *focus_mode, gint *focus_range) +{ + int ret = CAMERA_ERROR_NONE; + + g_return_val_if_fail(camerasrc, FALSE); + + gst_tizencamerasrc_debug("get focus"); + + ret = camera_hal_interface_get_command(camerasrc->hal_intf_handle, CAMERA_COMMAND_FOCUS_MODE, focus_mode); + ret |= camera_hal_interface_get_command(camerasrc->hal_intf_handle, CAMERA_COMMAND_FOCUS_RANGE, focus_range); + if (ret != CAMERA_ERROR_NONE) { + gst_tizencamerasrc_debug("Failed to get AF mode."); + return FALSE; + } + + return TRUE; +} + +gboolean gst_tizencamerasrc_control_start_auto_focus(GstTizenCameraSrc *camerasrc) +{ + int ret = CAMERA_ERROR_NONE; + + g_return_val_if_fail(camerasrc, FALSE); + + gst_tizencamerasrc_debug("start auto focus"); + + ret = camera_hal_interface_start_auto_focus(camerasrc->hal_intf_handle); + if (ret != CAMERA_ERROR_NONE) { + gst_tizencamerasrc_debug("Failed to start AF. error[0x%x]", ret); + return FALSE; + } else { + gst_tizencamerasrc_debug("Succeeded to start AF."); + return TRUE; + } +} + +gboolean gst_tizencamerasrc_control_stop_auto_focus(GstTizenCameraSrc *camerasrc) +{ + int ret = CAMERA_ERROR_NONE; + + g_return_val_if_fail(camerasrc, FALSE); + + gst_tizencamerasrc_debug("stop auto focus"); + + ret = camera_hal_interface_stop_auto_focus(camerasrc->hal_intf_handle); + if (ret != CAMERA_ERROR_NONE) { + gst_tizencamerasrc_debug("Failed to stop autofocus."); + return FALSE; + } + + return TRUE; +} + +gboolean gst_tizencamerasrc_control_set_focus_level(GstTizenCameraSrc *camerasrc, gint focus_level) +{ + /* TODO : */ + + gst_tizencamerasrc_debug("Not support"); + return FALSE; +} + +gboolean gst_tizencamerasrc_control_get_focus_level(GstTizenCameraSrc *camerasrc, gint *focus_level) +{ + /* TODO : */ + + gst_tizencamerasrc_debug("Not support"); + return FALSE; +} + +gboolean gst_tizencamerasrc_control_set_auto_focus_area(GstTizenCameraSrc *camerasrc, GstCameraControlRectType rect) +{ + int ret = CAMERA_ERROR_NONE; + camera_rectangle_t set_rect; + + g_return_val_if_fail(camerasrc, FALSE); + + gst_tizencamerasrc_debug("set auto focus area"); + + set_rect.x = rect.x; + set_rect.y = rect.y; + set_rect.width = rect.width; + set_rect.height = rect.height; + + GST_INFO_OBJECT(camerasrc, "Set AF area %d,%d,%dx%d", + set_rect.x, set_rect.y, + set_rect.width, set_rect.height); + + ret = camera_hal_interface_set_command(camerasrc->hal_intf_handle, CAMERA_COMMAND_FOCUS_AREA, &set_rect); + if (ret != CAMERA_ERROR_NONE) { + GST_ERROR_OBJECT(camerasrc, "Failed to set auto focus area 0x%x", ret); + return FALSE; + } + + return TRUE; +} + +gboolean gst_tizencamerasrc_control_get_auto_focus_area(GstTizenCameraSrc *camerasrc, GstCameraControlRectType *rect) +{ + int ret = CAMERA_ERROR_NONE; + camera_rectangle_t get_rect; + + g_return_val_if_fail(camerasrc, FALSE); + g_return_val_if_fail(rect, FALSE); + + gst_tizencamerasrc_debug("get auto focus area"); + + ret = camera_hal_interface_get_command(camerasrc->hal_intf_handle, CAMERA_COMMAND_FOCUS_AREA, &get_rect); + if (ret != CAMERA_ERROR_NONE) { + gst_tizencamerasrc_debug("Failed to get auto focus area."); + return FALSE; + } + + rect->x = get_rect.x; + rect->y = get_rect.y; + rect->width = get_rect.width; + rect->height = get_rect.height; + + return TRUE; +} + +gboolean gst_tizencamerasrc_control_set_wdr(GstTizenCameraSrc *camerasrc, gint value) +{ + int ret = CAMERA_ERROR_NONE; + + g_return_val_if_fail(camerasrc, FALSE); + + gst_tizencamerasrc_debug("set wdr"); + + ret = camera_hal_interface_set_command(camerasrc->hal_intf_handle, CAMERA_COMMAND_WDR, &value); + if (ret != CAMERA_ERROR_NONE) { + gst_tizencamerasrc_debug("Failed to set wdr. value[%d],err code[%x]", value, ret); + return FALSE; + } + + return TRUE; +} + +gboolean gst_tizencamerasrc_control_get_wdr(GstTizenCameraSrc *camerasrc, gint *value) +{ + int ret = CAMERA_ERROR_NONE; + + g_return_val_if_fail(camerasrc, FALSE); + + gst_tizencamerasrc_debug("get wdr"); + + ret = camera_hal_interface_get_command(camerasrc->hal_intf_handle, CAMERA_COMMAND_WDR, value); + if (ret != CAMERA_ERROR_NONE) { + gst_tizencamerasrc_debug("Failed to get wdr. err code[%x]", ret); + return FALSE; + } + + return TRUE; +} + +gboolean gst_tizencamerasrc_control_set_ahs(GstTizenCameraSrc *camerasrc, gint value) +{ + int ret = CAMERA_ERROR_NONE; + + g_return_val_if_fail(camerasrc, FALSE); + + gst_tizencamerasrc_debug("set ahs"); + + ret = camera_hal_interface_set_command(camerasrc->hal_intf_handle, CAMERA_COMMAND_ANTI_SHAKE, &value); + if (ret != CAMERA_ERROR_NONE) { + gst_tizencamerasrc_debug("Failed to set ahs. value[%d],err code[%x]", value, ret); + return FALSE; + } + + return TRUE; +} + +gboolean gst_tizencamerasrc_control_get_ahs(GstTizenCameraSrc *camerasrc, gint *value) +{ + int ret = CAMERA_ERROR_NONE; + + g_return_val_if_fail(camerasrc, FALSE); + + gst_tizencamerasrc_debug("get ahs"); + + ret = camera_hal_interface_get_command(camerasrc->hal_intf_handle, CAMERA_COMMAND_ANTI_SHAKE, value); + if (ret != CAMERA_ERROR_NONE) { + gst_tizencamerasrc_debug("Failed to get ahs. err code[%x]", ret); + return FALSE; + } + + return TRUE; +} + + +gboolean gst_tizencamerasrc_control_get_exif_info(GstTizenCameraSrc *camerasrc, GstCameraControlExifInfo *info) +{ + g_return_val_if_fail(camerasrc, FALSE); + + gst_tizencamerasrc_debug("get exif info"); + + /* TODO */ + + return TRUE; +} + +gboolean gst_tizencamerasrc_control_get_basic_dev_info (GstTizenCameraSrc *camerasrc, gint dev_id, GstCameraControlCapsInfoType *info) +{ + g_return_val_if_fail(camerasrc, FALSE); + + gst_tizencamerasrc_debug("get basic dev info"); + + /* TODO */ + + return TRUE; +} + +gboolean gst_tizencamerasrc_control_get_misc_dev_info(GstTizenCameraSrc *camerasrc, gint dev_id, GstCameraControlCtrlListInfoType *info) +{ + g_return_val_if_fail(camerasrc, FALSE); + + gst_tizencamerasrc_debug("get misc dev info"); + + /* TODO */ + + return TRUE; +} + +gboolean gst_tizencamerasrc_control_get_extra_dev_info(GstTizenCameraSrc *camerasrc, gint dev_id, GstCameraControlExtraInfoType *info) +{ + g_return_val_if_fail(camerasrc, FALSE); + + gst_tizencamerasrc_debug("get extra dev info"); + + /* TODO */ + + return TRUE; +} + +void gst_tizencamerasrc_control_set_capture_command(GstTizenCameraSrc *camerasrc, GstCameraControlCaptureCommand cmd) +{ + gst_tizencamerasrc_debug("set capture command"); + + if (camerasrc == NULL) { + gst_tizencamerasrc_debug("camerasrc is NULL"); + return; + } + + gst_tizencamerasrc_set_capture_command(camerasrc, cmd); + + return; +} diff --git a/tizencamerasrc/src/include/camera_hal_interface.h b/tizencamerasrc/src/include/camera_hal_interface.h new file mode 100644 index 0000000..3ab6179 --- /dev/null +++ b/tizencamerasrc/src/include/camera_hal_interface.h @@ -0,0 +1,54 @@ +/* + * camera_hal_interface.h + * + * Copyright (c) 2018 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Jeongmo Yang + * + * This library is free software; you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License as published by the + * Free Software Foundation; either version 2.1 of the License, or (at your option) + * any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, Inc., 51 + * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + + +#include + + + +typedef struct _camera_hal_interface camera_hal_interface; + +int camera_hal_interface_init(camera_hal_interface **h); +int camera_hal_interface_deinit(camera_hal_interface *h); +int camera_hal_interface_get_device_list(camera_hal_interface *h, camera_device_list_t *device_list); +int camera_hal_interface_open_device(camera_hal_interface *h, int device_index); +int camera_hal_interface_close_device(camera_hal_interface *h); +int camera_hal_interface_add_message_callback(camera_hal_interface *h, camera_message_cb callback, void *user_data, uint32_t *cb_id); +int camera_hal_interface_remove_message_callback(camera_hal_interface *h, uint32_t cb_id); +int camera_hal_interface_set_preview_stream_format(camera_hal_interface *h, camera_format_t *format); +int camera_hal_interface_get_preview_stream_format(camera_hal_interface *h, camera_format_t *format); +int camera_hal_interface_start_preview(camera_hal_interface *h, camera_preview_frame_cb callback, void *user_data); +int camera_hal_interface_release_preview_buffer(camera_hal_interface *h, int buffer_index); +int camera_hal_interface_stop_preview(camera_hal_interface *h); +int camera_hal_interface_start_auto_focus(camera_hal_interface *h); +int camera_hal_interface_stop_auto_focus(camera_hal_interface *h); +int camera_hal_interface_start_capture(camera_hal_interface *h, camera_capture_cb callback, void *user_data); +int camera_hal_interface_stop_capture(camera_hal_interface *h); +int camera_hal_interface_set_video_stream_format(camera_hal_interface *h, camera_format_t *format); +int camera_hal_interface_get_video_stream_format(camera_hal_interface *h, camera_format_t *format); +int camera_hal_interface_start_record(camera_hal_interface *h, camera_video_frame_cb callback, void *user_data); +int camera_hal_interface_release_video_buffer(camera_hal_interface *h, int buffer_index); +int camera_hal_interface_stop_record(camera_hal_interface *h); +int camera_hal_interface_set_command(camera_hal_interface *h, int64_t command, void *value); +int camera_hal_interface_get_command(camera_hal_interface *h, int64_t command, void *value); +int camera_hal_interface_set_batch_command(camera_hal_interface *h, camera_batch_command_control_t *batch_command, int64_t *error_command); diff --git a/tizencamerasrc/src/include/gsttizencamerasrc.h b/tizencamerasrc/src/include/gsttizencamerasrc.h new file mode 100644 index 0000000..f7845dc --- /dev/null +++ b/tizencamerasrc/src/include/gsttizencamerasrc.h @@ -0,0 +1,126 @@ +/* + * gsttizencamerasrc.h + * + * Copyright (c) 2018 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Jeongmo Yang + * + * This library is free software; you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License as published by the + * Free Software Foundation; either version 2.1 of the License, or (at your option) + * any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, Inc., 51 + * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifndef __GST_TIZENCAMERASRC_H__ +#define __GST_TIZENCAMERASRC_H__ + +#include +#include + +#include +#include +#include +#include + +#include +#include +#include + +#include "camera_hal_interface.h" + + +G_BEGIN_DECLS +#define GST_TYPE_TIZENCAMERA_SRC (gst_tizencamerasrc_get_type()) +#define GST_TIZENCAMERA_SRC(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_TIZENCAMERA_SRC,GstTizenCameraSrc)) +#define GST_TIZENCAMERA_SRC_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_TIZENCAMERA_SRC,GstTizenCameraSrcClass)) +#define GST_IS_TIZENCAMERA_SRC(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_TIZENCAMERA_SRC)) +#define GST_IS_TIZENCAMERA_SRC_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_TIZENCAMERA_SRC)) + + +#define FORMAT_NAME_LENGTH 10 + + +typedef struct _GstTizenCameraSrc GstTizenCameraSrc; +typedef struct _GstTizenCameraSrcClass GstTizenCameraSrcClass; + +struct _GstTizenCameraSrc +{ + GstPushSrc element; + + /*private*/ + camera_hal_interface *hal_intf_handle; /**< Camera HAL interface handle */ + int mode; + gboolean vflip; /**< flip camera input vertically */ + gboolean hflip; /**< flip camera input horizontally */ + gboolean firsttime; + + int cap_count_current; /**< current capture count */ + int cap_count_reverse; /**< current capture count (reverse counting) */ + GQueue *preview_buffer_list; + uint32_t msg_cb_id; + + /*camera property*/ + int width; /**< Width */ + int height; /**< Height */ + int fps; /**< Video source fps */ + + gchar format_name[FORMAT_NAME_LENGTH]; /**< Format name */ + int pix_format; /**< Image format of video source */ + int high_speed_fps; /**< Video source fps for high speed recording */ + gboolean fps_auto; /**< Auto Video source fps */ + + int camera_id; + int rotate; /**< Video source rotate */ + gboolean use_rotate_caps; /**< Use or not rotate value in caps */ + + GCond buffer_cond; /**< condition for buffer control */ + GMutex buffer_lock; /**< lock for buffer control */ + gboolean buffer_running; /**< with lock */ + + /* Colorbalance , CameraControl interface */ + GList *colors; + GList *camera_controls; + + /*capture property*/ + guint32 cap_fourcc; /**< gstreamer fourcc value(GST_MAKE_FOURCC format) for raw capturing */ + int cap_width; /**< Capture width */ + int cap_height; /**< Capture height */ + int cap_interval; /**< Capture interval */ + int cap_count; /**< Capture count */ + int cap_jpg_quality; /**< Capture quality for jpg compress ratio */ + gboolean cap_provide_exif; /**< Is exif provided? */ +}; + +struct _GstTizenCameraSrcClass { + GstPushSrcClass parent_class; + /* signals */ + void (*still_capture) (GstElement *element, GstBuffer *main, GstBuffer *sub, GstBuffer *scrnl); + void (*nego_complete) (GstElement *element); + void (*register_trouble) (GstElement *element); +}; + +typedef enum { + INTERFACE_NONE, + INTERFACE_COLOR_BALANCE, + INTERFACE_CAMERA_CONTROL, +} GstInterfaceType; + + +void gst_tizencamerasrc_set_capture_command(GstTizenCameraSrc* camerasrc, GstCameraControlCaptureCommand cmd); + + +GType gst_tizencamerasrc_get_type(void); + +G_END_DECLS + +#endif /* __GST_TIZENCAMERASRC_H__ */ diff --git a/tizencamerasrc/src/include/gsttizencamerasrccolorbalance.h b/tizencamerasrc/src/include/gsttizencamerasrccolorbalance.h new file mode 100644 index 0000000..d6ed7fa --- /dev/null +++ b/tizencamerasrc/src/include/gsttizencamerasrccolorbalance.h @@ -0,0 +1,91 @@ +/* + * gsttizencamerasrccolorbalance.h + * + * Copyright (c) 2018 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Jeongmo Yang + * + * This library is free software; you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License as published by the + * Free Software Foundation; either version 2.1 of the License, or (at your option) + * any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, Inc., 51 + * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifndef __GST_TIZENCAMERASRC_COLOR_BALANCE_H__ +#define __GST_TIZENCAMERASRC_COLOR_BALANCE_H__ + +#include +#include +#include "gsttizencamerasrc.h" + +G_BEGIN_DECLS + +#define GST_TYPE_TIZENCAMERASRC_COLOR_BALANCE_CHANNEL (gst_tizencamerasrc_color_balance_channel_get_type ()) +#define GST_TIZENCAMERASRC_COLOR_BALANCE_CHANNEL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_TIZENCAMERASRC_COLOR_BALANCE_CHANNEL, GstTizenCameraSrcColorBalanceChannel)) +#define GST_TIZENCAMERASRC_COLOR_BALANCE_CHANNEL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_TIZENCAMERASRC_COLOR_BALANCE_CHANNEL, GstTizenCameraSrcColorBalanceChannelClass)) +#define GST_IS_CAMERASRC_COLOR_BALANCE_CHANNEL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_TIZENCAMERASRC_COLOR_BALANCE_CHANNEL)) +#define GST_IS_CAMERASRC_COLOR_BALANCE_CHANNEL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_TIZENCAMERASRC_COLOR_BALANCE_CHANNEL)) + +typedef struct _GstTizenCameraSrcColorBalanceChannel { + GstColorBalanceChannel parent; + + int64_t id; +} GstTizenCameraSrcColorBalanceChannel; + +typedef struct _GstTizenCameraSrcColorBalanceChannelClass { + GstColorBalanceChannelClass parent; +} GstTizenCameraSrcColorBalanceChannelClass; + +GType gst_tizencamerasrc_color_balance_channel_get_type( void ); + +const GList *gst_tizencamerasrc_color_balance_list_channels( GstTizenCameraSrc *camerasrc ); +void gst_tizencamerasrc_color_balance_set_value( GstTizenCameraSrc *camerasrc, GstColorBalanceChannel *color_channel, gint value ); +gint gst_tizencamerasrc_color_balance_get_value( GstTizenCameraSrc *camerasrc, GstColorBalanceChannel *color_channel ); + +#define GST_IMPLEMENT_TIZENCAMERASRC_COLOR_BALANCE_METHODS( Type, interface_as_function ) \ + \ +static const GList* \ +interface_as_function ## _color_balance_list_channels( GstColorBalance *balance ) \ +{ \ + Type *this = (Type*) balance; \ + return gst_tizencamerasrc_color_balance_list_channels( this ); \ +} \ + \ +static void \ +interface_as_function ## _color_balance_set_value( GstColorBalance *balance, \ + GstColorBalanceChannel *color_channel, \ + gint value ) \ +{ \ + Type *this = (Type*) balance; \ + return gst_tizencamerasrc_color_balance_set_value( this, color_channel, value ); \ +} \ + \ +static gint \ +interface_as_function ## _color_balance_get_value( GstColorBalance *balance, \ + GstColorBalanceChannel *color_channel )\ +{ \ + Type *this = (Type*) balance; \ + return gst_tizencamerasrc_color_balance_get_value( this, color_channel ); \ +} \ + \ +void \ +interface_as_function ## _color_balance_interface_init( GstColorBalanceInterface *klass ) \ +{ \ + /* default virtual functions */ \ + klass->list_channels = interface_as_function ## _color_balance_list_channels; \ + klass->set_value = interface_as_function ## _color_balance_set_value; \ + klass->get_value = interface_as_function ## _color_balance_get_value; \ +} + +#endif /* __GST_TIZENCAMERASRC_COLOR_BALANCE_H__ */ + diff --git a/tizencamerasrc/src/include/gsttizencamerasrccontrol.h b/tizencamerasrc/src/include/gsttizencamerasrccontrol.h new file mode 100644 index 0000000..f5afe10 --- /dev/null +++ b/tizencamerasrc/src/include/gsttizencamerasrccontrol.h @@ -0,0 +1,364 @@ +/* + * gsttizencamerasrccontrol.h + * + * Copyright (c) 2018 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Jeongmo Yang + * + * This library is free software; you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License as published by the + * Free Software Foundation; either version 2.1 of the License, or (at your option) + * any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, Inc., 51 + * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifndef __GST_TIZENCAMERASRC_CONTROL_H__ +#define __GST_TIZENCAMERASRC_CONTROL_H__ + +#include +#include +#include "gsttizencamerasrc.h" + +G_BEGIN_DECLS + +#define GST_TYPE_TIZENCAMERASRC_CONTROL_CHANNEL (gst_tizencamerasrc_control_channel_get_type ()) +#define GST_TIZENCAMERASRC_CONTROL_CHANNEL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_TIZENCAMERASRC_CONTROL_CHANNEL, GstTizenCamerasrcControlChannel)) +#define GST_TIZENCAMERASRC_CONTROL_CHANNEL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_TIZENCAMERASRC_CONTROL_CHANNEL, GstTizenCamerasrcControlChannelClass)) +#define GST_IS_TIZENCAMERASRC_CONTROL_CHANNEL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_TIZENCAMERASRC_CONTROL_CHANNEL)) +#define GST_IS_TIZENCAMERASRC_CONTROL_CHANNEL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_TIZENCAMERASRC_CONTROL_CHANNEL)) + +typedef struct _GstTizenCamerasrcControlChannel { + GstCameraControlChannel parent; + int64_t id; +} GstTizenCamerasrcControlChannel; + +typedef struct _GstTizenCamerasrcControlChannelClass { + GstCameraControlChannelClass parent; +} GstTizenCamerasrcControlChannelClass; + +GType gst_tizencamerasrc_control_channel_get_type(void); + +const GList *gst_tizencamerasrc_control_list_channels(GstTizenCameraSrc *camera_src); + +gboolean gst_tizencamerasrc_control_set_value (GstTizenCameraSrc *camera_src, GstCameraControlChannel *control_channel, gint value); +gboolean gst_tizencamerasrc_control_get_value (GstTizenCameraSrc *camera_src, GstCameraControlChannel *control_channel, gint *value); +gboolean gst_tizencamerasrc_control_set_exposure (GstTizenCameraSrc *camera_src, gint type, gint value1, gint value2); +gboolean gst_tizencamerasrc_control_get_exposure (GstTizenCameraSrc *camera_src, gint type, gint *value1, gint *value2); +gboolean gst_tizencamerasrc_control_set_capture_mode (GstTizenCameraSrc *camera_src, gint type, gint value); +gboolean gst_tizencamerasrc_control_get_capture_mode (GstTizenCameraSrc *camera_src, gint type, gint *value); +gboolean gst_tizencamerasrc_control_set_strobe (GstTizenCameraSrc *camera_src, gint type, gint value); +gboolean gst_tizencamerasrc_control_get_strobe (GstTizenCameraSrc *camera_src, gint type, gint *value); +gboolean gst_tizencamerasrc_control_set_detect (GstTizenCameraSrc *camera_src, gint type, gint value); +gboolean gst_tizencamerasrc_control_get_detect (GstTizenCameraSrc *camera_src, gint type, gint *value); +gboolean gst_tizencamerasrc_control_set_zoom (GstTizenCameraSrc *camera_src, gint type, gint value); +gboolean gst_tizencamerasrc_control_get_zoom (GstTizenCameraSrc *camera_src, gint type, gint *value); +gboolean gst_tizencamerasrc_control_set_focus (GstTizenCameraSrc *camera_src, gint mode, gint range); +gboolean gst_tizencamerasrc_control_get_focus (GstTizenCameraSrc *camera_src, gint *mode, gint *range); +gboolean gst_tizencamerasrc_control_start_auto_focus (GstTizenCameraSrc *camera_src); +gboolean gst_tizencamerasrc_control_stop_auto_focus (GstTizenCameraSrc *camera_src); +gboolean gst_tizencamerasrc_control_set_focus_level (GstTizenCameraSrc *camera_src, gint manual_level); +gboolean gst_tizencamerasrc_control_get_focus_level (GstTizenCameraSrc *camera_src, gint *manual_level); +gboolean gst_tizencamerasrc_control_set_auto_focus_area(GstTizenCameraSrc *camera_src, GstCameraControlRectType rect); +gboolean gst_tizencamerasrc_control_get_auto_focus_area(GstTizenCameraSrc *camera_src, GstCameraControlRectType *rect); +gboolean gst_tizencamerasrc_control_set_wdr (GstTizenCameraSrc *camera_src, gint value); +gboolean gst_tizencamerasrc_control_get_wdr (GstTizenCameraSrc *camera_src, gint *value); +gboolean gst_tizencamerasrc_control_set_ahs (GstTizenCameraSrc *camera_src, gint value); +gboolean gst_tizencamerasrc_control_get_ahs (GstTizenCameraSrc *camera_src, gint *value); +gboolean gst_tizencamerasrc_control_get_exif_info (GstTizenCameraSrc *camera_src, GstCameraControlExifInfo *info); +gboolean gst_tizencamerasrc_control_get_basic_dev_info (GstTizenCameraSrc *camera_src, gint dev_id, GstCameraControlCapsInfoType *info); +gboolean gst_tizencamerasrc_control_get_misc_dev_info (GstTizenCameraSrc *camera_src, gint dev_id, GstCameraControlCtrlListInfoType *info); +gboolean gst_tizencamerasrc_control_get_extra_dev_info (GstTizenCameraSrc *camera_src, gint dev_id, GstCameraControlExtraInfoType *info); +void gst_tizencamerasrc_control_set_capture_command(GstTizenCameraSrc *camera_src, GstCameraControlCaptureCommand cmd); + +#define GST_IMPLEMENT_TIZENCAMERASRC_CONTROL_METHODS(Type, interface_as_function) \ + \ +static const GList* \ +interface_as_function ## _control_list_channels(GstCameraControl *control) \ +{ \ + Type *this = (Type *) control; \ + return gst_tizencamerasrc_control_list_channels(this); \ +} \ + \ +static gboolean \ +interface_as_function ## _control_set_value(GstCameraControl *control, \ + GstCameraControlChannel *control_channel, int value) \ +{ \ + Type *this = (Type *)control; \ + return gst_tizencamerasrc_control_set_value(this, control_channel, value); \ +} \ + \ +static gboolean \ +interface_as_function ## _control_get_value(GstCameraControl *control, \ + GstCameraControlChannel *control_channel, int *value) \ +{ \ + Type *this = (Type *)control; \ + return gst_tizencamerasrc_control_get_value(this, control_channel, value); \ +} \ + \ +static gboolean \ +interface_as_function ## _control_set_exposure(GstCameraControl *control, \ + gint type, gint value1, gint value2) \ +{ \ + Type *this = (Type *)control; \ + return gst_tizencamerasrc_control_set_exposure(this, type, value1, value2); \ +} \ + \ +static gboolean \ +interface_as_function ## _control_get_exposure(GstCameraControl *control, \ + gint type, gint *value1, gint *value2) \ +{ \ + Type *this = (Type *)control; \ + return gst_tizencamerasrc_control_get_exposure(this, type, value1, value2); \ +} \ + \ +static gboolean \ +interface_as_function ## _control_set_capture_mode(GstCameraControl *control, \ + gint type, gint value) \ +{ \ + Type *this = (Type *)control; \ + return gst_tizencamerasrc_control_set_capture_mode(this, type, value); \ +} \ + \ +static gboolean \ +interface_as_function ## _control_get_capture_mode(GstCameraControl *control, \ + gint type, gint *value) \ +{ \ + Type *this = (Type *)control; \ + return gst_tizencamerasrc_control_get_capture_mode(this, type, value); \ +} \ + \ +static gboolean \ +interface_as_function ## _control_set_strobe(GstCameraControl *control, \ + gint type, gint value) \ +{ \ + Type *this = (Type *)control; \ + return gst_tizencamerasrc_control_set_strobe(this, type, value); \ +} \ + \ +static gboolean \ +interface_as_function ## _control_get_strobe(GstCameraControl *control, \ + gint type, gint *value) \ +{ \ + Type *this = (Type *)control; \ + return gst_tizencamerasrc_control_get_strobe(this, type, value); \ +} \ + \ +static gboolean \ +interface_as_function ## _control_set_detect(GstCameraControl *control, \ + gint type, gint value) \ +{ \ + Type *this = (Type *)control; \ + return gst_tizencamerasrc_control_set_detect(this, type, value); \ +} \ + \ +static gboolean \ +interface_as_function ## _control_get_detect(GstCameraControl *control, \ + gint type, gint *value) \ +{ \ + Type *this = (Type *)control; \ + return gst_tizencamerasrc_control_get_detect(this, type, value); \ +} \ + \ +static gboolean \ +interface_as_function ## _control_set_zoom(GstCameraControl *control, \ + gint type, gint value) \ +{ \ + Type *this = (Type *)control; \ + return gst_tizencamerasrc_control_set_zoom(this, type, value); \ +} \ + \ +static gboolean \ +interface_as_function ## _control_get_zoom(GstCameraControl *control, \ + gint type, gint *value) \ +{ \ + Type *this = (Type *)control; \ + return gst_tizencamerasrc_control_get_zoom(this, type, value); \ +} \ + \ +static gboolean \ +interface_as_function ## _control_set_focus(GstCameraControl *control, \ + gint focus_mode, gint focus_range) \ +{ \ + Type *this = (Type *)control; \ + return gst_tizencamerasrc_control_set_focus(this, focus_mode, focus_range); \ +} \ + \ +static gboolean \ +interface_as_function ## _control_get_focus(GstCameraControl *control, \ + gint *focus_mode, gint *focus_range) \ +{ \ + Type *this = (Type *)control; \ + return gst_tizencamerasrc_control_get_focus(this, focus_mode, focus_range); \ +} \ + \ +static gboolean \ +interface_as_function ## _control_start_auto_focus(GstCameraControl *control) \ +{ \ + Type *this = (Type *)control; \ + return gst_tizencamerasrc_control_start_auto_focus(this); \ +} \ + \ +static gboolean \ +interface_as_function ## _control_stop_auto_focus(GstCameraControl *control) \ +{ \ + Type *this = (Type *)control; \ + return gst_tizencamerasrc_control_stop_auto_focus(this); \ +} \ + \ +static gboolean \ +interface_as_function ## _control_set_focus_level(GstCameraControl *control, \ + gint focus_level) \ +{ \ + Type *this = (Type *)control; \ + return gst_tizencamerasrc_control_set_focus_level(this, focus_level); \ +} \ + \ +static gboolean \ +interface_as_function ## _control_get_focus_level(GstCameraControl *control, \ + gint *focus_level) \ +{ \ + Type *this = (Type *)control; \ + return gst_tizencamerasrc_control_get_focus_level(this, focus_level); \ +} \ + \ +static gboolean \ +interface_as_function ## _control_set_auto_focus_area(GstCameraControl *control, \ + GstCameraControlRectType rect) \ +{ \ + Type *this = (Type *)control; \ + return gst_tizencamerasrc_control_set_auto_focus_area(this, rect); \ +} \ + \ +static gboolean \ +interface_as_function ## _control_get_auto_focus_area(GstCameraControl *control, \ + GstCameraControlRectType *rect) \ +{ \ + Type *this = (Type *)control; \ + return gst_tizencamerasrc_control_get_auto_focus_area(this, rect); \ +} \ + \ +static gboolean \ +interface_as_function ## _control_set_wdr(GstCameraControl *control, \ + gint value) \ +{ \ + Type *this = (Type *)control; \ + return gst_tizencamerasrc_control_set_wdr(this, value); \ +} \ + \ +static gboolean \ +interface_as_function ## _control_get_wdr(GstCameraControl *control, \ + gint *value) \ +{ \ + Type *this = (Type *)control; \ + return gst_tizencamerasrc_control_get_wdr(this, value); \ +} \ + \ +static gboolean \ +interface_as_function ## _control_set_ahs(GstCameraControl *control, \ + gint value) \ +{ \ + Type *this = (Type *)control; \ + return gst_tizencamerasrc_control_set_ahs(this, value); \ +} \ + \ +static gboolean \ +interface_as_function ## _control_get_ahs(GstCameraControl *control, \ + gint *value) \ +{ \ + Type *this = (Type *)control; \ + return gst_tizencamerasrc_control_get_ahs(this, value); \ +} \ + \ +static gboolean \ +interface_as_function ## _control_get_exif_info(GstCameraControl *control, \ + GstCameraControlExifInfo *info) \ +{ \ + Type *this = (Type *)control; \ + return gst_tizencamerasrc_control_get_exif_info(this, info); \ +} \ + \ +static gboolean \ +interface_as_function ## _control_get_basic_dev_info(GstCameraControl *control, \ + gint dev_id, \ + GstCameraControlCapsInfoType *info) \ +{ \ + Type *this = (Type *)control; \ + return gst_tizencamerasrc_control_get_basic_dev_info(this, dev_id, info); \ +} \ + \ +static gboolean \ +interface_as_function ## _control_get_misc_dev_info(GstCameraControl *control, \ + gint dev_id, \ + GstCameraControlCtrlListInfoType *info) \ +{ \ + Type *this = (Type *)control; \ + return gst_tizencamerasrc_control_get_misc_dev_info(this, dev_id, info); \ +} \ + \ +static gboolean \ +interface_as_function ## _control_get_extra_dev_info(GstCameraControl *control, \ + gint dev_id, \ + GstCameraControlExtraInfoType *info) \ +{ \ + Type *this = (Type *)control; \ + return gst_tizencamerasrc_control_get_extra_dev_info(this, dev_id, info); \ +} \ + \ +static void \ +interface_as_function ## _control_set_capture_command(GstCameraControl *control, \ + GstCameraControlCaptureCommand cmd) \ +{ \ + Type *this = (Type *)control; \ + gst_tizencamerasrc_control_set_capture_command(this, cmd); \ + return; \ +} \ + \ +void \ +interface_as_function ## _control_interface_init(GstCameraControlClass *klass) \ +{ \ + GST_CAMERA_CONTROL_TYPE(klass) = GST_CAMERA_CONTROL_HARDWARE; \ + \ + /* default virtual functions */ \ + klass->list_channels = interface_as_function ## _control_list_channels; \ + klass->set_value = interface_as_function ## _control_set_value; \ + klass->get_value = interface_as_function ## _control_get_value; \ + klass->set_exposure = interface_as_function ## _control_set_exposure; \ + klass->get_exposure = interface_as_function ## _control_get_exposure; \ + klass->set_capture_mode = interface_as_function ## _control_set_capture_mode; \ + klass->get_capture_mode = interface_as_function ## _control_get_capture_mode; \ + klass->set_strobe = interface_as_function ## _control_set_strobe; \ + klass->get_strobe = interface_as_function ## _control_get_strobe; \ + klass->set_detect = interface_as_function ## _control_set_detect; \ + klass->get_detect = interface_as_function ## _control_get_detect; \ + klass->set_zoom = interface_as_function ## _control_set_zoom; \ + klass->get_zoom = interface_as_function ## _control_get_zoom; \ + klass->set_focus = interface_as_function ## _control_set_focus; \ + klass->get_focus = interface_as_function ## _control_get_focus; \ + klass->start_auto_focus = interface_as_function ## _control_start_auto_focus; \ + klass->stop_auto_focus = interface_as_function ## _control_stop_auto_focus; \ + klass->set_focus_level = interface_as_function ## _control_set_focus_level; \ + klass->get_focus_level = interface_as_function ## _control_get_focus_level; \ + klass->set_auto_focus_area = interface_as_function ## _control_set_auto_focus_area; \ + klass->get_auto_focus_area = interface_as_function ## _control_get_auto_focus_area; \ + klass->set_wdr = interface_as_function ## _control_set_wdr; \ + klass->get_wdr = interface_as_function ## _control_get_wdr; \ + klass->set_ahs = interface_as_function ## _control_set_ahs; \ + klass->get_ahs = interface_as_function ## _control_get_ahs; \ + klass->get_exif_info = interface_as_function ## _control_get_exif_info; \ + klass->get_basic_dev_info = interface_as_function ## _control_get_basic_dev_info; \ + klass->get_misc_dev_info = interface_as_function ## _control_get_misc_dev_info; \ + klass->get_extra_dev_info = interface_as_function ## _control_get_extra_dev_info; \ + klass->set_capture_command = interface_as_function ## _control_set_capture_command; \ + \ +} + +#endif /* __GST_TIZENCAMERASRC_CONTROL_H__ */ -- 2.7.4