From 15101ed729eda53e949eb354873f1fc224cfcdf5 Mon Sep 17 00:00:00 2001 From: "jk7744.park" Date: Sat, 24 Oct 2015 16:51:27 +0900 Subject: [PATCH] tizen 2.4 release --- configure.ac | 40 +- libmm-camcorder.manifest | 2 +- mm-camcorder.pc.in | 4 +- packaging/libmm-camcorder.spec | 26 +- src/Makefile.am | 21 +- src/include/mm_camcorder.h | 95 +++- src/include/mm_camcorder_attribute.h | 14 +- src/include/mm_camcorder_exifinfo.h | 2 +- src/include/mm_camcorder_gstcommon.h | 4 +- src/include/mm_camcorder_internal.h | 169 +++--- src/include/mm_camcorder_platform.h | 5 +- src/include/mm_camcorder_stillshot.h | 17 +- src/include/mm_camcorder_util.h | 120 ++-- src/include/mm_camcorder_videorec.h | 5 +- src/mm_camcorder.c | 31 +- src/mm_camcorder_attribute.c | 777 ++++++++++++++++++++----- src/mm_camcorder_audiorec.c | 252 ++++----- src/mm_camcorder_configure.c | 206 ++++--- src/mm_camcorder_exifinfo.c | 32 +- src/mm_camcorder_gstcommon.c | 920 ++++++++++++++++++++---------- src/mm_camcorder_internal.c | 674 ++++++++++++++-------- src/mm_camcorder_platform.c | 144 +++-- src/mm_camcorder_sound.c | 6 +- src/mm_camcorder_stillshot.c | 299 +++++----- src/mm_camcorder_util.c | 1038 ++++++++++++++++++++++++---------- src/mm_camcorder_videorec.c | 579 +++++++++++-------- test/Makefile.am | 4 +- test/mm_camcorder_testsuite.c | 107 +++- 28 files changed, 3729 insertions(+), 1864 deletions(-) mode change 100755 => 100644 mm-camcorder.pc.in mode change 100755 => 100644 test/Makefile.am diff --git a/configure.ac b/configure.ac index abed85f..f21f9e8 100644 --- a/configure.ac +++ b/configure.ac @@ -6,6 +6,8 @@ AC_CONFIG_HEADERS([config.h:config.hin]) AC_CONFIG_MACRO_DIR([m4]) # Checks for programs. +m4_pattern_allow([AM_PROG_AR]) +AM_PROG_AR AC_PROG_CC AC_C_CONST dnl AC_FUNC_MALLOC @@ -21,19 +23,19 @@ AC_PROG_GCC_TRADITIONAL AC_PROG_LIBTOOL # Checks for libraries. -PKG_CHECK_MODULES(GST, gstreamer-0.10 >= 0.10) +PKG_CHECK_MODULES(GST, gstreamer-1.0 >= 1.2.0) AC_SUBST(GST_CFLAGS) AC_SUBST(GST_LIBS) -PKG_CHECK_MODULES(GST_PLUGIN_BASE, gstreamer-base-0.10 >= 0.10) +PKG_CHECK_MODULES(GST_PLUGIN_BASE, gstreamer-base-1.0 >= 1.2.0) AC_SUBST(GST_PLUGIN_BASE_CFLAGS) AC_SUBST(GST_PLUGIN_BASE_LIBS) -PKG_CHECK_MODULES(GST_INTERFACES, gstreamer-interfaces-0.10 >= 0.10) -AC_SUBST(GST_INTERFACES_CFLAGS) -AC_SUBST(GST_INTERFACES_LIBS) +PKG_CHECK_MODULES(GST_VIDEO, gstreamer-video-1.0 >= 1.2.0) +AC_SUBST(GST_VIDEO_CFLAGS) +AC_SUBST(GST_VIDEO_LIBS) -PKG_CHECK_MODULES(GST_APP, gstreamer-app-0.10) +PKG_CHECK_MODULES(GST_APP, gstreamer-app-1.0 >= 1.2.0) AC_SUBST(GST_APP_CFLAGS) AC_SUBST(GST_APP_LIBS) @@ -53,6 +55,10 @@ PKG_CHECK_MODULES(GLIB, glib-2.0) AC_SUBST(GLIB_CFLAGS) AC_SUBST(GLIB_LIBS) +PKG_CHECK_MODULES(GIO, gio-2.0) +AC_SUBST(GIO_CFLAGS) +AC_SUBST(GIO_LIBS) + PKG_CHECK_MODULES(MMSESSION, mm-session) AC_SUBST(MMSESSION_CFLAGS) AC_SUBST(MMSESSION_LIBS) @@ -69,14 +75,14 @@ PKG_CHECK_MODULES(MMUTIL_IMGP, mmutil-imgp) AC_SUBST(MMUTIL_IMGP_CFLAGS) AC_SUBST(MMUTIL_IMGP_LIBS) +PKG_CHECK_MODULES(MMUTIL_JPEG, mmutil-jpeg) +AC_SUBST(MMUTIL_JPEG_CFLAGS) +AC_SUBST(MMUTIL_JPEG_LIBS) + PKG_CHECK_MODULES(SNDFILE, sndfile) AC_SUBST(SNDFILE_CFLAGS) AC_SUBST(SNDFILE_LIBS) -PKG_CHECK_MODULES(CAMSRCJPEGENC, camsrcjpegenc) -AC_SUBST(CAMSRCJPEGENC_CFLAGS) -AC_SUBST(CAMSRCJPEGENC_LIBS) - PKG_CHECK_MODULES(VCONF, vconf) AC_SUBST(VCONF_CFLAGS) AC_SUBST(VCONF_LIBS) @@ -85,9 +91,17 @@ PKG_CHECK_MODULES(SYSTEMINFO, capi-system-info) AC_SUBST(SYSTEMINFO_CFLAGS) AC_SUBST(SYSTEMINFO_LIBS) -PKG_CHECK_MODULES(DBUS, dbus-1) -AC_SUBST(DBUS_CFLAGS) -AC_SUBST(DBUS_LIBS) +PKG_CHECK_MODULES(TTRACE, ttrace) +AC_SUBST(TTRACE_CFLAGS) +AC_SUBST(TTRACE_LIBS) + +PKG_CHECK_MODULES(TBM, libtbm) +AC_SUBST(TBM_CFLAGS) +AC_SUBST(TBM_LIBS) + +PKG_CHECK_MODULES(STORAGE, storage) +AC_SUBST(STORAGE_CFLAGS) +AC_SUBST(STORAGE_LIBS) # Checks for header files. AC_HEADER_STDC diff --git a/libmm-camcorder.manifest b/libmm-camcorder.manifest index 692624d..1852d08 100644 --- a/libmm-camcorder.manifest +++ b/libmm-camcorder.manifest @@ -3,6 +3,6 @@ - + diff --git a/mm-camcorder.pc.in b/mm-camcorder.pc.in old mode 100755 new mode 100644 index 7994653..eb5870c --- a/mm-camcorder.pc.in +++ b/mm-camcorder.pc.in @@ -5,7 +5,7 @@ includedir=@includedir@ Name: mm-camcorder Description: Multimedia Framework Camcorder Library -Requires: gstreamer-0.10 gstreamer-base-0.10 mm-common libexif +Requires: gstreamer-1.0 gstreamer-base-1.0 mm-common mm-log libexif Version: $VERSION -Libs: -L${libdir} -lmmfcamcorder +Libs: -L${libdir} -lmmfcamcorder Cflags: -I${includedir}/ -I${includedir}/mmf diff --git a/packaging/libmm-camcorder.spec b/packaging/libmm-camcorder.spec index fe90ad9..800687b 100644 --- a/packaging/libmm-camcorder.spec +++ b/packaging/libmm-camcorder.spec @@ -1,6 +1,6 @@ Name: libmm-camcorder Summary: Camera and recorder library -Version: 0.9.64 +Version: 0.9.125 Release: 0 Group: libdevel License: Apache-2.0 @@ -8,21 +8,26 @@ Source0: %{name}-%{version}.tar.gz Requires(post): /usr/bin/vconftool Requires(post): /sbin/ldconfig Requires(postun): /sbin/ldconfig +BuildRequires: pkgconfig(glib-2.0) +BuildRequires: pkgconfig(gio-2.0) BuildRequires: pkgconfig(capi-system-info) BuildRequires: pkgconfig(mm-common) BuildRequires: pkgconfig(mm-sound) BuildRequires: pkgconfig(libexif) BuildRequires: pkgconfig(mmutil-imgp) -BuildRequires: pkgconfig(gstreamer-plugins-base-0.10) -BuildRequires: pkgconfig(gstreamer-app-0.10) +BuildRequires: pkgconfig(mmutil-jpeg) +BuildRequires: pkgconfig(gstreamer-base-1.0) +BuildRequires: pkgconfig(gstreamer-video-1.0) +BuildRequires: pkgconfig(gstreamer-app-1.0) BuildRequires: pkgconfig(sndfile) BuildRequires: pkgconfig(mm-session) BuildRequires: pkgconfig(audio-session-mgr) -BuildRequires: pkgconfig(camsrcjpegenc) BuildRequires: pkgconfig(libpulse) BuildRequires: pkgconfig(vconf) -BuildRequires: gst-plugins-base-devel -BuildRequires: pkgconfig(dbus-1) +BuildRequires: gstreamer1.0-devel +BuildRequires: pkgconfig(ttrace) +BuildRequires: pkgconfig(libtbm) +BuildRequires: pkgconfig(storage) %description Camera and recorder library. @@ -34,19 +39,19 @@ Group: libdevel Version: %{version} Requires: %{name} = %{version}-%{release} -%description devel +%description devel Camera and recorder development library. %prep -%setup -q +%setup -q %build %if 0%{?sec_build_binary_debug_enable} export CFLAGS+=" -DTIZEN_DEBUG_ENABLE" %endif -export CFLAGS+=" -Wall -Wcast-qual -Wextra -Wno-array-bounds -Wno-empty-body -Wno-ignored-qualifiers -Wno-unused-parameter -Wshadow -Wwrite-strings -Wswitch-default -Wno-unused-but-set-parameter -Wno-unused-but-set-variable" +export CFLAGS+=" -Wall -Wextra -Wno-array-bounds -Wno-empty-body -Wno-ignored-qualifiers -Wno-unused-parameter -Wshadow -Wwrite-strings -Wswitch-default -Wno-unused-but-set-parameter -Wno-unused-but-set-variable -D_LARGEFILE64_SOURCE" #export CFLAGS+=" -Werror" ./autogen.sh %configure \ @@ -63,9 +68,6 @@ cp LICENSE.APLv2 %{buildroot}/usr/share/license/%{name} %post /sbin/ldconfig -vconftool set -t int memory/camera/state 0 -i -u 5000 -s system::vconf_multimedia -vconftool set -t int memory/recorder/state 0 -i -u 5000 -s system::vconf_multimedia -vconftool set -t int file/camera/shutter_sound_policy 0 -u 5000 -s system::vconf_inhouse chsmack -a "device::camera" /usr/share/sounds/mm-camcorder/camera_resource chsmack -a "pulseaudio::record" /usr/share/sounds/mm-camcorder/recorder_resource diff --git a/src/Makefile.am b/src/Makefile.am index 50744c1..fa04693 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -35,38 +35,47 @@ libmmfcamcorder_la_SOURCES = mm_camcorder.c \ libmmfcamcorder_la_CFLAGS = -I$(srcdir)/include \ $(GST_CFLAGS) \ $(GST_PLUGIN_BASE_CFLAGS) \ - $(GST_INTERFACES_CFLAGS) \ + $(GST_VIDEO_CFLAGS) \ $(GST_APP_CFLAGS) \ $(EXIF_CFLAGS) \ $(MM_COMMON_CFLAGS) \ $(MMSESSION_CFLAGS) \ $(MMSOUND_CFLAGS) \ $(SNDFILE_CFLAGS) \ - $(CAMSRCJPEGENC_CFLAGS) \ $(VCONF_CFLAGS) \ $(MMUTIL_IMGP_CFLAGS) \ + $(MMUTIL_JPEG_CFLAGS) \ $(AUDIOSESSIONMGR_CFLAGS) \ $(DBUS_CFLAGS) \ + $(TTRACE_CFLAGS) \ + $(TBM_CFLAGS) \ + $(STORAGE_CFLAGS) \ $(SYSTEMINFO_CFLAGS) libmmfcamcorder_la_LIBADD = \ + $(GLIB_LIBS) \ + $(GIO_LIBS) \ $(GST_LIBS) \ $(GST_PLUGIN_BASE_LIBS) \ - $(GST_INTERFACES_LIBS) \ + $(GST_VIDEO_LIBS) \ $(GST_APP_LIBS) \ $(MM_COMMON_LIBS) \ $(EXIF_LIBS) \ $(MMSESSION_LIBS) \ $(MMSOUND_LIBS) \ $(SNDFILE_LIBS) \ - $(CAMSRCJPEGENC_LIBS) \ $(VCONF_LIBS) \ $(MMUTIL_IMGP_LIBS) \ - $(DBUS_LIBS) \ + $(MMUTIL_JPEG_LIBS) \ + $(TBM_LIBS) \ + $(STORAGE_LIBS) \ + $(TTRACE_LIBS) \ $(AUDIOSESSIONMGR_LIBS) libmmfcamcorder_la_CFLAGS += -DMMF_LOG_OWNER=0x010 -D_INTERNAL_SESSION_MANAGER_ -D_FILE_OFFSET_BITS=64 -libmmfcamcorder_la_CFLAGS += -fdata-sections -ffunction-sections -Wl,--gc-sections +libmmfcamcorder_la_CFLAGS += -fdata-sections -ffunction-sections +libmmfcamcorder_la_LDFLAGS = -Wl,--gc-sections \ + -Wl,-init,_mmcamcorder_constructor libmmfcamcorder_la_LIBADD += $(SYSTEMINFO_LIBS) install-exec-hook: diff --git a/src/include/mm_camcorder.h b/src/include/mm_camcorder.h index 7474fcd..71cd5b3 100644 --- a/src/include/mm_camcorder.h +++ b/src/include/mm_camcorder.h @@ -727,7 +727,7 @@ extern "C" { /** * Frames per second. This is an integer field - * + * */ #define MMCAM_CAMERA_FPS "camera-fps" @@ -757,6 +757,16 @@ extern "C" { #define MMCAM_CAMERA_DIGITAL_ZOOM "camera-digital-zoom" /** + * Digital pan level. + */ +#define MMCAM_CAMERA_PAN "camera-pan" + +/** + * Digital tilt level. + */ +#define MMCAM_CAMERA_TILT "camera-tilt" + +/** * Optical zoom level. */ #define MMCAM_CAMERA_OPTICAL_ZOOM "camera-optical-zoom" @@ -1228,11 +1238,30 @@ extern "C" { #define MMCAM_SUPPORT_MEDIA_PACKET_PREVIEW_CB "support-media-packet-preview-cb" /** + * Display scaler + */ +#define MMCAM_DISPLAY_SCALER "display-scaler" + +/** + * Bitrate for encoded preview stream + */ +#define MMCAM_ENCODED_PREVIEW_BITRATE "encoded-preview-bitrate" + +/** + * I-frame interval for encoded preview stream + */ +#define MMCAM_ENCODED_PREVIEW_IFRAME_INTERVAL "encoded-preview-iframe-interval" + +/** + * Name of usb audio device id + */ +#define MMCAM_USB_AUDIO_UDEV_ID "usb-audio-device-id" + +/** * Enable to write tags for recorded file */ #define MMCAM_RECORDER_TAG_ENABLE "recorder-tag-enable" - /*======================================================================================= | ENUM DEFINITIONS | ========================================================================================*/ @@ -1317,10 +1346,10 @@ enum MMCamcorderColorToneType { /** * An enumeration for white balance. White Balance is the control that adjusts - * the camcorder's color sensitivity to match the prevailing color of white - * outdoor light, yellower indoor light, or (sometimes) greenish fluorescent - * light. White balance may be set either automatically or manually. White balance - * may be set "incorrectly" on purpose to achieve special effects. + * the camcorder's color sensitivity to match the prevailing color of white + * outdoor light, yellower indoor light, or (sometimes) greenish fluorescent + * light. White balance may be set either automatically or manually. White balance + * may be set "incorrectly" on purpose to achieve special effects. */ enum MMCamcorderWhiteBalanceType { MM_CAMCORDER_WHITE_BALANCE_NONE = 0, /**< None */ @@ -1333,13 +1362,12 @@ enum MMCamcorderWhiteBalanceType { MM_CAMCORDER_WHITE_BALANCE_HORIZON, /**< Horizon */ MM_CAMCORDER_WHITE_BALANCE_FLASH, /**< Flash */ MM_CAMCORDER_WHITE_BALANCE_CUSTOM, /**< Custom */ - }; /** * An enumeration for scene mode. Scene mode gives the environment condition - * for operating camcorder. The mode of operation can be in daylight, night and + * for operating camcorder. The mode of operation can be in daylight, night and * backlight. It can be an automatic setting also. */ enum MMCamcorderSceneModeType { @@ -1367,8 +1395,8 @@ enum MMCamcorderSceneModeType { */ enum MMCamcorderFocusMode { MM_CAMCORDER_FOCUS_MODE_NONE = 0, /**< Focus mode is None */ - MM_CAMCORDER_FOCUS_MODE_PAN, /**< Pan focus mode*/ - MM_CAMCORDER_FOCUS_MODE_AUTO, /**< Autofocus mode*/ + MM_CAMCORDER_FOCUS_MODE_PAN, /**< Pan focus mode*/ + MM_CAMCORDER_FOCUS_MODE_AUTO, /**< Autofocus mode*/ MM_CAMCORDER_FOCUS_MODE_MANUAL, /**< Manual focus mode*/ MM_CAMCORDER_FOCUS_MODE_TOUCH_AUTO, /**< Touch Autofocus mode*/ MM_CAMCORDER_FOCUS_MODE_CONTINUOUS, /**< Continuous Autofocus mode*/ @@ -1607,6 +1635,7 @@ typedef enum { MM_CAM_STREAM_DATA_YUV420SP, /**< YUV420 SemiPlannar type - 2 planes */ MM_CAM_STREAM_DATA_YUV420P, /**< YUV420 Plannar type - 3 planes */ MM_CAM_STREAM_DATA_YUV422P, /**< YUV422 Plannar type - 3 planes */ + MM_CAM_STREAM_DATA_ENCODED /**< Encoded data type - 1 plane */ } MMCamStreamData; @@ -1705,6 +1734,10 @@ typedef struct { unsigned char *v; unsigned int length_v; } yuv420p, yuv422p; + struct { + unsigned char *data; + unsigned int length_data; + } encoded; } data; /**< pointer of captured stream */ MMCamStreamData data_type; /**< data type */ unsigned int length_total; /**< total length of stream buffer (in byte)*/ @@ -3051,6 +3084,48 @@ int mm_camcorder_get_attribute_info(MMHandleType camcorder, const char *attribut /** + * mm_camcorder_get_fps_list_by_resolution:\n + * Get detail information of the fps configure. To manager fps, an user may want to know the supported fps list by the current preview resolution, + * Gives attribute information structure, from the configure data. + * Depending on the 'validity_type', validity union would be different. To know about the type of union, please refer 'MMCamAttrsInfo'. + * + * @param[in] camcorder Specifies the camcorder handle. + * @param[in] width width value of the current Preview resolution. + * @param[in] height height value of the current Preview resolution. + * @param[out] fps_info a structure that holds information related with the attribute. + * @return This function returns zero(MM_ERROR_NONE) on success, or negative value with error code.\n + * Please refer 'mm_error.h' to know the exact meaning of the error. + * @pre None + * @post None + * @remarks If the function succeeds, 'info' holds detail information about the attribute, such as type, + * flag, validity_type, validity_values, and default values. + * @see mm_camcorder_get_attributes, mm_camcorder_set_attributes + * @par example + * @code + +#include + +gboolean getting_info_from_attribute() +{ + MMCamAttrsInfo info; + int err; + + err = mm_camcorder_get_fps_list_by_resolution(handle, width, height, &info); + if (err < 0) { + printf("Fail to call mm_camcorder_get_attribute_info()"); + return FALSE; + } + + //Now 'info' has many information about 'MMCAM_CAPTURE_HEIGHT' + + return TRUE; +} + * @endcode + */ +int mm_camcorder_get_fps_list_by_resolution(MMHandleType camcorder, int width, int height, MMCamAttrsInfo *fps_info); + + +/** * mm_camcorder_init_focusing:\n * Initialize focusing. \n * This function stops focusing action and adjust the camera lens to initial position. diff --git a/src/include/mm_camcorder_attribute.h b/src/include/mm_camcorder_attribute.h index c072f64..61fcdbc 100644 --- a/src/include/mm_camcorder_attribute.h +++ b/src/include/mm_camcorder_attribute.h @@ -25,6 +25,7 @@ /*======================================================================================= | INCLUDE FILES | ========================================================================================*/ +#include #include #include @@ -165,12 +166,18 @@ typedef enum MM_CAM_DISPLAY_FLIP, MM_CAM_CAMERA_VIDEO_STABILIZATION, MM_CAM_TAG_VIDEO_ORIENTATION, - MM_CAM_VIDEO_WIDTH, /* 110 */ + MM_CAM_CAMERA_PAN, /* 110 */ + MM_CAM_CAMERA_TILT, + MM_CAM_VIDEO_WIDTH, MM_CAM_VIDEO_HEIGHT, MM_CAM_SUPPORT_ZSL_CAPTURE, MM_CAM_DISPLAY_HANDLE_USER_DATA, MM_CAM_SUPPORT_ZERO_COPY_FORMAT, MM_CAM_SUPPORT_MEDIA_PACKET_PREVIEW_CB, + MM_CAM_DISPLAY_SCALER, + MM_CAM_ENCODED_PREVIEW_BITRATE, + MM_CAM_ENCODED_PREVIEW_IFRAME_INTERVAL, /* 120 */ + MM_CAM_USB_AUDIO_UDEV_ID, MM_CAM_RECORDER_TAG_ENABLE, MM_CAM_NUM }MMCamcorderAttrsID; @@ -350,10 +357,15 @@ bool _mmcamcorder_commit_display_geometry_method(MMHandleType handle, int attr_i bool _mmcamcorder_commit_display_rect(MMHandleType handle, int attr_idx, const mmf_value_t *value); bool _mmcamcorder_commit_display_scale(MMHandleType handle, int attr_idx, const mmf_value_t *value); bool _mmcamcorder_commit_display_evas_do_scaling(MMHandleType handle, int attr_idx, const mmf_value_t *value); +bool _mmcamcorder_commit_display_scaler(MMHandleType handle, int attr_idx, const mmf_value_t *value); bool _mmcamcorder_commit_strobe(MMHandleType handle, int attr_idx, const mmf_value_t *value); bool _mmcamcorder_commit_detect(MMHandleType handle, int attr_idx, const mmf_value_t *value); bool _mmcamcorder_commit_camera_flip(MMHandleType handle, int attr_idx, const mmf_value_t *value); bool _mmcamcorder_commit_camera_hdr_capture(MMHandleType handle, int attr_idx, const mmf_value_t *value); +bool _mmcamcorder_commit_camera_pan(MMHandleType handle, int attr_idx, const mmf_value_t *value); +bool _mmcamcorder_commit_camera_tilt(MMHandleType handle, int attr_idx, const mmf_value_t *value); +bool _mmcamcorder_commit_encoded_preview_bitrate(MMHandleType handle, int attr_idx, const mmf_value_t *value); +bool _mmcamcorder_commit_encoded_preview_iframe_interval(MMHandleType handle, int attr_idx, const mmf_value_t *value); /** * This function initialize effect setting. diff --git a/src/include/mm_camcorder_exifinfo.h b/src/include/mm_camcorder_exifinfo.h index 1032e9a..efbdc97 100644 --- a/src/include/mm_camcorder_exifinfo.h +++ b/src/include/mm_camcorder_exifinfo.h @@ -87,7 +87,7 @@ ExifData *mm_exif_get_exif_from_info(mm_exif_info_t *info); int mm_exif_set_exif_to_info(mm_exif_info_t *info, ExifData *exif); /** - * add one tag information into exif + * add one tag information into exif * @param[in] info exif info. * @param[in] Exif tag . * @param[in] tag content category. diff --git a/src/include/mm_camcorder_gstcommon.h b/src/include/mm_camcorder_gstcommon.h index cb025b2..68e0230 100644 --- a/src/include/mm_camcorder_gstcommon.h +++ b/src/include/mm_camcorder_gstcommon.h @@ -149,8 +149,8 @@ int _mmcamcorder_create_encodesink_bin(MMHandleType handle, MMCamcorderEncodebin int _mmcamcorder_create_preview_pipeline(MMHandleType handle); /* plug-in related */ -void _mmcamcorder_negosig_handler(GstElement *videosrc, MMHandleType handle); void _mmcamcorder_ready_to_encode_callback(GstElement *element, guint size, gpointer handle); +bool _mmcamcorder_recreate_decoder_for_encoded_preview(MMHandleType handle); /* etc */ int _mmcamcorder_videosink_window_set(MMHandleType handle, type_element *VideosinkElement); @@ -168,6 +168,8 @@ bool _mmcamcorder_set_videosrc_flip(MMHandleType handle, int viderosrc_flip); bool _mmcamcorder_set_videosrc_anti_shake(MMHandleType handle, int anti_shake); bool _mmcamcorder_set_videosrc_stabilization(MMHandleType handle, int stabilization); bool _mmcamcorder_set_camera_resolution(MMHandleType handle, int width, int height); +bool _mmcamcorder_set_encoded_preview_bitrate(MMHandleType handle, int bitrate); +bool _mmcamcorder_set_encoded_preview_iframe_interval(MMHandleType handle, int interval); #ifdef __cplusplus } diff --git a/src/include/mm_camcorder_internal.h b/src/include/mm_camcorder_internal.h index 84d14da..e0e09ef 100644 --- a/src/include/mm_camcorder_internal.h +++ b/src/include/mm_camcorder_internal.h @@ -37,6 +37,7 @@ #include #include #include +#include #include "mm_camcorder.h" #include "mm_debug.h" @@ -131,7 +132,9 @@ extern "C" { _mmcam_dbg_err("The element is existed. element_id=[%d], name=[%s]", eid, name); \ gst_object_unref(element[eid].gst); \ } \ + traceBegin(TTRACE_TAG_CAMERA, "MMCAMCORDER:ELEMENT_MAKE:%s", name); \ element[eid].gst = gst_element_factory_make(name, nickname); \ + traceEnd(TTRACE_TAG_CAMERA); \ if (element[eid].gst == NULL) { \ _mmcam_dbg_err("Element creation fail. element_id=[%d], name=[%s]", eid, name); \ err = MM_ERROR_CAMCORDER_RESOURCE_CREATION; \ @@ -204,7 +207,24 @@ extern "C" { #define _MM_GST_PAD_LINK_UNREF(srcpad, sinkpad, err, if_fail_goto)\ {\ - GstPadLinkReturn ret = _MM_GST_PAD_LINK(srcpad, sinkpad);\ + GstPadLinkReturn ret = GST_PAD_LINK_OK;\ + if (srcpad == NULL || sinkpad == NULL) {\ + if (srcpad == NULL) {\ + _mmcam_dbg_err("srcpad is NULL");\ + } else {\ + gst_object_unref(srcpad);\ + srcpad = NULL;\ + }\ + if (sinkpad == NULL) {\ + _mmcam_dbg_err("sinkpad is NULL");\ + } else {\ + gst_object_unref(sinkpad);\ + sinkpad = NULL;\ + }\ + err = MM_ERROR_CAMCORDER_GST_LINK;\ + goto if_fail_goto;\ + }\ + ret = _MM_GST_PAD_LINK(srcpad, sinkpad);\ if (ret != GST_PAD_LINK_OK) {\ GstObject *src_parent = gst_pad_get_parent(srcpad);\ GstObject *sink_parent = gst_pad_get_parent(sinkpad);\ @@ -245,7 +265,13 @@ extern "C" { #define _MMCAMCORDER_STATE_SET_COUNT 3 /* checking interval */ #define _MMCAMCORDER_STATE_CHECK_TOTALTIME 5000000L /* total wating time for state change */ -#define _MMCAMCORDER_STATE_CHECK_INTERVAL 5000 /* checking interval */ +#define _MMCAMCORDER_STATE_CHECK_INTERVAL (50*1000) /* checking interval - 50ms*/ + +/** + * Error message size + */ +#define MAX_ERROR_MESSAGE_LEN 128 + /** * Default videosink type @@ -294,69 +320,75 @@ extern "C" { /** * Functions related with LOCK and WAIT */ -#define _MMCAMCORDER_CAST_MTSAFE(handle) (((mmf_camcorder_t*)handle)->mtsafe) - -#define _MMCAMCORDER_GET_LOCK(handle) (_MMCAMCORDER_CAST_MTSAFE(handle).lock) -#define _MMCAMCORDER_LOCK(handle) g_mutex_lock(_MMCAMCORDER_GET_LOCK(handle)) -#define _MMCAMCORDER_TRYLOCK(handle) g_mutex_trylock(_MMCAMCORDER_GET_LOCK(handle)) -#define _MMCAMCORDER_UNLOCK(handle) g_mutex_unlock(_MMCAMCORDER_GET_LOCK(handle)) - -#define _MMCAMCORDER_GET_COND(handle) (_MMCAMCORDER_CAST_MTSAFE(handle).cond) -#define _MMCAMCORDER_WAIT(handle) g_cond_wait (_MMCAMCORDER_GET_COND(handle), _MMCAMCORDER_GET_LOCK(handle)) -#define _MMCAMCORDER_TIMED_WAIT(handle, timeval) g_cond_timed_wait (_MMCAMCORDER_GET_COND(handle), _MMCAMCORDER_GET_LOCK(handle),timeval) - -#define _MMCAMCORDER_SIGNAL(handle) g_cond_signal (_MMCAMCORDER_GET_COND(handle)); -#define _MMCAMCORDER_BROADCAST(handle) g_cond_broadcast (_MMCAMCORDER_GET_COND(handle)); +#define _MMCAMCORDER_CAST_MTSAFE(handle) (((mmf_camcorder_t*)handle)->mtsafe) +#define _MMCAMCORDER_LOCK_FUNC(mutex) pthread_mutex_lock(&mutex) +#define _MMCAMCORDER_TRYLOCK_FUNC(mutex) (!pthread_mutex_trylock(&mutex)) +#define _MMCAMCORDER_UNLOCK_FUNC(mutex) pthread_mutex_unlock(&mutex) + +#define _MMCAMCORDER_GET_LOCK(handle) (_MMCAMCORDER_CAST_MTSAFE(handle).lock) +#define _MMCAMCORDER_LOCK(handle) _MMCAMCORDER_LOCK_FUNC(_MMCAMCORDER_GET_LOCK(handle)) +#define _MMCAMCORDER_TRYLOCK(handle) _MMCAMCORDER_TRYLOCK_FUNC(_MMCAMCORDER_GET_LOCK(handle)) +#define _MMCAMCORDER_UNLOCK(handle) _MMCAMCORDER_UNLOCK_FUNC(_MMCAMCORDER_GET_LOCK(handle)) + +#define _MMCAMCORDER_GET_COND(handle) (_MMCAMCORDER_CAST_MTSAFE(handle).cond) +#define _MMCAMCORDER_WAIT(handle) pthread_cond_wait(&_MMCAMCORDER_GET_COND(handle), &_MMCAMCORDER_GET_LOCK(handle)) +#define _MMCAMCORDER_TIMED_WAIT(handle, timeout) pthread_cond_timedwait(&_MMCAMCORDER_GET_COND(handle), &_MMCAMCORDER_GET_LOCK(handle), &timeout) +#define _MMCAMCORDER_SIGNAL(handle) pthread_cond_signal(&_MMCAMCORDER_GET_COND(handle)); +#define _MMCAMCORDER_BROADCAST(handle) pthread_cond_broadcast(&_MMCAMCORDER_GET_COND(handle)); /* for command */ -#define _MMCAMCORDER_GET_CMD_LOCK(handle) (_MMCAMCORDER_CAST_MTSAFE(handle).cmd_lock) -#define _MMCAMCORDER_LOCK_CMD(handle) g_mutex_lock(_MMCAMCORDER_GET_CMD_LOCK(handle)) -#define _MMCAMCORDER_TRYLOCK_CMD(handle) g_mutex_trylock(_MMCAMCORDER_GET_CMD_LOCK(handle)) -#define _MMCAMCORDER_UNLOCK_CMD(handle) g_mutex_unlock(_MMCAMCORDER_GET_CMD_LOCK(handle)) +#define _MMCAMCORDER_GET_CMD_LOCK(handle) (_MMCAMCORDER_CAST_MTSAFE(handle).cmd_lock) +#define _MMCAMCORDER_GET_CMD_COND(handle) (_MMCAMCORDER_CAST_MTSAFE(handle).cmd_cond) +#define _MMCAMCORDER_LOCK_CMD(handle) _MMCAMCORDER_LOCK_FUNC(_MMCAMCORDER_GET_CMD_LOCK(handle)) +#define _MMCAMCORDER_TRYLOCK_CMD(handle) _MMCAMCORDER_TRYLOCK_FUNC(_MMCAMCORDER_GET_CMD_LOCK(handle)) +#define _MMCAMCORDER_UNLOCK_CMD(handle) _MMCAMCORDER_UNLOCK_FUNC(_MMCAMCORDER_GET_CMD_LOCK(handle)) +#define _MMCAMCORDER_CMD_WAIT(handle) pthread_cond_wait(&_MMCAMCORDER_GET_CMD_COND(handle), &_MMCAMCORDER_GET_CMD_LOCK(handle)) +#define _MMCAMCORDER_CMD_TIMED_WAIT(handle, timeout) pthread_cond_timedwait(&_MMCAMCORDER_GET_CMD_COND(handle), &_MMCAMCORDER_GET_CMD_LOCK(handle), &timeout) +#define _MMCAMCORDER_CMD_SIGNAL(handle) pthread_cond_signal(&_MMCAMCORDER_GET_CMD_COND(handle)); /* for ASM */ -#define _MMCAMCORDER_GET_ASM_LOCK(handle) (_MMCAMCORDER_CAST_MTSAFE(handle).asm_lock) -#define _MMCAMCORDER_LOCK_ASM(handle) g_mutex_lock(_MMCAMCORDER_GET_ASM_LOCK(handle)) -#define _MMCAMCORDER_TRYLOCK_ASM(handle) g_mutex_trylock(_MMCAMCORDER_GET_ASM_LOCK(handle)) -#define _MMCAMCORDER_UNLOCK_ASM(handle) g_mutex_unlock(_MMCAMCORDER_GET_ASM_LOCK(handle)) +#define _MMCAMCORDER_GET_ASM_LOCK(handle) (_MMCAMCORDER_CAST_MTSAFE(handle).asm_lock) +#define _MMCAMCORDER_LOCK_ASM(handle) _MMCAMCORDER_LOCK_FUNC(_MMCAMCORDER_GET_ASM_LOCK(handle)) +#define _MMCAMCORDER_TRYLOCK_ASM(handle) _MMCAMCORDER_TRYLOCK_FUNC(_MMCAMCORDER_GET_ASM_LOCK(handle)) +#define _MMCAMCORDER_UNLOCK_ASM(handle) _MMCAMCORDER_UNLOCK_FUNC(_MMCAMCORDER_GET_ASM_LOCK(handle)) /* for state change */ -#define _MMCAMCORDER_GET_STATE_LOCK(handle) (_MMCAMCORDER_CAST_MTSAFE(handle).state_lock) -#define _MMCAMCORDER_LOCK_STATE(handle) g_mutex_lock(_MMCAMCORDER_GET_STATE_LOCK(handle)) -#define _MMCAMCORDER_TRYLOCK_STATE(handle) g_mutex_trylock(_MMCAMCORDER_GET_STATE_LOCK(handle)) -#define _MMCAMCORDER_UNLOCK_STATE(handle) g_mutex_unlock(_MMCAMCORDER_GET_STATE_LOCK(handle)) +#define _MMCAMCORDER_GET_STATE_LOCK(handle) (_MMCAMCORDER_CAST_MTSAFE(handle).state_lock) +#define _MMCAMCORDER_LOCK_STATE(handle) _MMCAMCORDER_LOCK_FUNC(_MMCAMCORDER_GET_STATE_LOCK(handle)) +#define _MMCAMCORDER_TRYLOCK_STATE(handle) _MMCAMCORDER_TRYLOCK_FUNC(_MMCAMCORDER_GET_STATE_LOCK(handle)) +#define _MMCAMCORDER_UNLOCK_STATE(handle) _MMCAMCORDER_UNLOCK_FUNC(_MMCAMCORDER_GET_STATE_LOCK(handle)) /* for gstreamer state change */ -#define _MMCAMCORDER_GET_GST_STATE_LOCK(handle) (_MMCAMCORDER_CAST_MTSAFE(handle).gst_state_lock) -#define _MMCAMCORDER_LOCK_GST_STATE(handle) g_mutex_lock(_MMCAMCORDER_GET_GST_STATE_LOCK(handle)) -#define _MMCAMCORDER_TRYLOCK_GST_STATE(handle) g_mutex_trylock(_MMCAMCORDER_GET_GST_STATE_LOCK(handle)) -#define _MMCAMCORDER_UNLOCK_GST_STATE(handle) g_mutex_unlock(_MMCAMCORDER_GET_GST_STATE_LOCK(handle)) +#define _MMCAMCORDER_GET_GST_STATE_LOCK(handle) (_MMCAMCORDER_CAST_MTSAFE(handle).gst_state_lock) +#define _MMCAMCORDER_LOCK_GST_STATE(handle) _MMCAMCORDER_LOCK_FUNC(_MMCAMCORDER_GET_GST_STATE_LOCK(handle)) +#define _MMCAMCORDER_TRYLOCK_GST_STATE(handle) _MMCAMCORDER_TRYLOCK_FUNC(_MMCAMCORDER_GET_GST_STATE_LOCK(handle)) +#define _MMCAMCORDER_UNLOCK_GST_STATE(handle) _MMCAMCORDER_UNLOCK_FUNC(_MMCAMCORDER_GET_GST_STATE_LOCK(handle)) -#define _MMCAMCORDER_GET_GST_ENCODE_STATE_LOCK(handle) (_MMCAMCORDER_CAST_MTSAFE(handle).gst_encode_state_lock) -#define _MMCAMCORDER_LOCK_GST_ENCODE_STATE(handle) g_mutex_lock(_MMCAMCORDER_GET_GST_ENCODE_STATE_LOCK(handle)) -#define _MMCAMCORDER_TRYLOCK_GST_ENCODE_STATE(handle) g_mutex_trylock(_MMCAMCORDER_GET_GST_ENCODE_STATE_LOCK(handle)) -#define _MMCAMCORDER_UNLOCK_GST_ENCODE_STATE(handle) g_mutex_unlock(_MMCAMCORDER_GET_GST_ENCODE_STATE_LOCK(handle)) +#define _MMCAMCORDER_GET_GST_ENCODE_STATE_LOCK(handle) (_MMCAMCORDER_CAST_MTSAFE(handle).gst_encode_state_lock) +#define _MMCAMCORDER_LOCK_GST_ENCODE_STATE(handle) _MMCAMCORDER_LOCK_FUNC(_MMCAMCORDER_GET_GST_ENCODE_STATE_LOCK(handle)) +#define _MMCAMCORDER_TRYLOCK_GST_ENCODE_STATE(handle) _MMCAMCORDER_TRYLOCK_FUNC(_MMCAMCORDER_GET_GST_ENCODE_STATE_LOCK(handle)) +#define _MMCAMCORDER_UNLOCK_GST_ENCODE_STATE(handle) _MMCAMCORDER_UNLOCK_FUNC(_MMCAMCORDER_GET_GST_ENCODE_STATE_LOCK(handle)) /* for setting/calling callback */ #define _MMCAMCORDER_GET_MESSAGE_CALLBACK_LOCK(handle) (_MMCAMCORDER_CAST_MTSAFE(handle).message_cb_lock) -#define _MMCAMCORDER_LOCK_MESSAGE_CALLBACK(handle) g_mutex_lock(_MMCAMCORDER_GET_MESSAGE_CALLBACK_LOCK(handle)) -#define _MMCAMCORDER_TRYLOCK_MESSAGE_CALLBACK(handle) g_mutex_trylock(_MMCAMCORDER_GET_MESSAGE_CALLBACK_LOCK(handle)) -#define _MMCAMCORDER_UNLOCK_MESSAGE_CALLBACK(handle) g_mutex_unlock(_MMCAMCORDER_GET_MESSAGE_CALLBACK_LOCK(handle)) +#define _MMCAMCORDER_LOCK_MESSAGE_CALLBACK(handle) _MMCAMCORDER_LOCK_FUNC(_MMCAMCORDER_GET_MESSAGE_CALLBACK_LOCK(handle)) +#define _MMCAMCORDER_TRYLOCK_MESSAGE_CALLBACK(handle) _MMCAMCORDER_TRYLOCK_FUNC(_MMCAMCORDER_GET_MESSAGE_CALLBACK_LOCK(handle)) +#define _MMCAMCORDER_UNLOCK_MESSAGE_CALLBACK(handle) _MMCAMCORDER_UNLOCK_FUNC(_MMCAMCORDER_GET_MESSAGE_CALLBACK_LOCK(handle)) #define _MMCAMCORDER_GET_VCAPTURE_CALLBACK_LOCK(handle) (_MMCAMCORDER_CAST_MTSAFE(handle).vcapture_cb_lock) -#define _MMCAMCORDER_LOCK_VCAPTURE_CALLBACK(handle) g_mutex_lock(_MMCAMCORDER_GET_VCAPTURE_CALLBACK_LOCK(handle)) -#define _MMCAMCORDER_TRYLOCK_VCAPTURE_CALLBACK(handle) g_mutex_trylock(_MMCAMCORDER_GET_VCAPTURE_CALLBACK_LOCK(handle)) -#define _MMCAMCORDER_UNLOCK_VCAPTURE_CALLBACK(handle) g_mutex_unlock(_MMCAMCORDER_GET_VCAPTURE_CALLBACK_LOCK(handle)) +#define _MMCAMCORDER_LOCK_VCAPTURE_CALLBACK(handle) _MMCAMCORDER_LOCK_FUNC(_MMCAMCORDER_GET_VCAPTURE_CALLBACK_LOCK(handle)) +#define _MMCAMCORDER_TRYLOCK_VCAPTURE_CALLBACK(handle) _MMCAMCORDER_TRYLOCK_FUNC(_MMCAMCORDER_GET_VCAPTURE_CALLBACK_LOCK(handle)) +#define _MMCAMCORDER_UNLOCK_VCAPTURE_CALLBACK(handle) _MMCAMCORDER_UNLOCK_FUNC(_MMCAMCORDER_GET_VCAPTURE_CALLBACK_LOCK(handle)) #define _MMCAMCORDER_GET_VSTREAM_CALLBACK_LOCK(handle) (_MMCAMCORDER_CAST_MTSAFE(handle).vstream_cb_lock) -#define _MMCAMCORDER_LOCK_VSTREAM_CALLBACK(handle) g_mutex_lock(_MMCAMCORDER_GET_VSTREAM_CALLBACK_LOCK(handle)) -#define _MMCAMCORDER_TRYLOCK_VSTREAM_CALLBACK(handle) g_mutex_trylock(_MMCAMCORDER_GET_VSTREAM_CALLBACK_LOCK(handle)) -#define _MMCAMCORDER_UNLOCK_VSTREAM_CALLBACK(handle) g_mutex_unlock(_MMCAMCORDER_GET_VSTREAM_CALLBACK_LOCK(handle)) +#define _MMCAMCORDER_LOCK_VSTREAM_CALLBACK(handle) _MMCAMCORDER_LOCK_FUNC(_MMCAMCORDER_GET_VSTREAM_CALLBACK_LOCK(handle)) +#define _MMCAMCORDER_TRYLOCK_VSTREAM_CALLBACK(handle) _MMCAMCORDER_TRYLOCK_FUNC(_MMCAMCORDER_GET_VSTREAM_CALLBACK_LOCK(handle)) +#define _MMCAMCORDER_UNLOCK_VSTREAM_CALLBACK(handle) _MMCAMCORDER_UNLOCK_FUNC(_MMCAMCORDER_GET_VSTREAM_CALLBACK_LOCK(handle)) #define _MMCAMCORDER_GET_ASTREAM_CALLBACK_LOCK(handle) (_MMCAMCORDER_CAST_MTSAFE(handle).astream_cb_lock) -#define _MMCAMCORDER_LOCK_ASTREAM_CALLBACK(handle) g_mutex_lock(_MMCAMCORDER_GET_ASTREAM_CALLBACK_LOCK(handle)) -#define _MMCAMCORDER_TRYLOCK_ASTREAM_CALLBACK(handle) g_mutex_trylock(_MMCAMCORDER_GET_ASTREAM_CALLBACK_LOCK(handle)) -#define _MMCAMCORDER_UNLOCK_ASTREAM_CALLBACK(handle) g_mutex_unlock(_MMCAMCORDER_GET_ASTREAM_CALLBACK_LOCK(handle)) +#define _MMCAMCORDER_LOCK_ASTREAM_CALLBACK(handle) _MMCAMCORDER_LOCK_FUNC(_MMCAMCORDER_GET_ASTREAM_CALLBACK_LOCK(handle)) +#define _MMCAMCORDER_TRYLOCK_ASTREAM_CALLBACK(handle) _MMCAMCORDER_TRYLOCK_FUNC(_MMCAMCORDER_GET_ASTREAM_CALLBACK_LOCK(handle)) +#define _MMCAMCORDER_UNLOCK_ASTREAM_CALLBACK(handle) _MMCAMCORDER_UNLOCK_FUNC(_MMCAMCORDER_GET_ASTREAM_CALLBACK_LOCK(handle)) /** * Caster of main handle (camcorder) @@ -460,6 +492,7 @@ typedef enum { _MMCAMCORDER_VIDEOSRC_CLS, _MMCAMCORDER_VIDEOSRC_CLS_FILT, _MMCAMCORDER_VIDEOSRC_QUE, + _MMCAMCORDER_VIDEOSRC_DECODE, /* Pipeline element of Video output */ _MMCAMCORDER_VIDEOSINK_QUE, @@ -515,7 +548,9 @@ typedef enum { typedef enum { _MMCAMCORDER_TASK_THREAD_STATE_NONE, _MMCAMCORDER_TASK_THREAD_STATE_SOUND_PLAY_START, + _MMCAMCORDER_TASK_THREAD_STATE_SOUND_SOLO_PLAY_START, _MMCAMCORDER_TASK_THREAD_STATE_ENCODE_PIPE_CREATE, + _MMCAMCORDER_TASK_THREAD_STATE_CHECK_CAPTURE_IN_RECORDING, _MMCAMCORDER_TASK_THREAD_STATE_EXIT, } _MMCamcorderTaskThreadState; @@ -555,17 +590,18 @@ typedef struct { * MMCamcorder information for Multi-Thread Safe */ typedef struct { - GMutex *lock; /**< Mutex (for general use) */ - GCond *cond; /**< Condition (for general use) */ - GMutex *cmd_lock; /**< Mutex (for command) */ - GMutex *asm_lock; /**< Mutex (for ASM) */ - GMutex *state_lock; /**< Mutex (for state change) */ - GMutex *gst_state_lock; /**< Mutex (for gst pipeline state change) */ - GMutex *gst_encode_state_lock; /**< Mutex (for gst encode pipeline state change) */ - GMutex *message_cb_lock; /**< Mutex (for message callback) */ - GMutex *vcapture_cb_lock; /**< Mutex (for video capture callback) */ - GMutex *vstream_cb_lock; /**< Mutex (for video stream callback) */ - GMutex *astream_cb_lock; /**< Mutex (for audio stream callback) */ + pthread_mutex_t lock; /**< Mutex (for general use) */ + pthread_cond_t cond; /**< Condition (for general use) */ + pthread_mutex_t cmd_lock; /**< Mutex (for command) */ + pthread_cond_t cmd_cond; /**< Condition (for command) */ + pthread_mutex_t asm_lock; /**< Mutex (for ASM) */ + pthread_mutex_t state_lock; /**< Mutex (for state change) */ + pthread_mutex_t gst_state_lock; /**< Mutex (for gst pipeline state change) */ + pthread_mutex_t gst_encode_state_lock; /**< Mutex (for gst encode pipeline state change) */ + pthread_mutex_t message_cb_lock; /**< Mutex (for message callback) */ + pthread_mutex_t vcapture_cb_lock; /**< Mutex (for video capture callback) */ + pthread_mutex_t vstream_cb_lock; /**< Mutex (for video stream callback) */ + pthread_mutex_t astream_cb_lock; /**< Mutex (for audio stream callback) */ } _MMCamcorderMTSafe; @@ -582,8 +618,6 @@ typedef struct { GstClockTime pause_time; /**< amount of time while pipeline is in PAUSE state.*/ GstClockTime stillshot_time; /**< pipeline time of capturing moment*/ gboolean is_modified_rate; /**< whether recording motion rate is modified or not */ - gboolean error_occurs; /**< flag for error */ - int error_code; /**< error code for internal gstreamer error */ gboolean ferror_send; /**< file write/seek error **/ guint ferror_count; /**< file write/seek error count **/ GstClockTime previous_slot_time; @@ -674,13 +708,16 @@ typedef struct mmf_camcorder { int asm_event_type; /**< Event type of ASM */ int asm_session_type; /**< Session type of ASM */ int asm_session_options; /**< Session option of ASM */ + char *root_directory; /**< Root directory for device */ + int resolution_changed; /**< Flag for preview resolution change */ _MMCamcorderInfoConverting caminfo_convert[CAMINFO_CONVERT_NUM]; /**< converting structure of camera info */ _MMCamcorderEnumConvert enum_conv[ENUM_CONVERT_NUM]; /**< enum converting list that is modified by ini info */ gboolean capture_in_recording; /**< Flag for capture while recording */ - guint64 system_memory; /* system memory size, do not use this size for recording*/ + gboolean error_occurs; /**< flag for error */ + int error_code; /**< error code for internal gstreamer error */ /* task thread */ pthread_t task_thread; /**< thread for task */ @@ -713,7 +750,7 @@ typedef struct mmf_camcorder { int _mmcamcorder_create(MMHandleType *handle, MMCamPreset *info); /** - * This function destroys instance of camcorder. + * This function destroys instance of camcorder. * * @param[in] hcamcorder Specifies the camcorder handle * @return This function returns zero on success, or negative value with error code. @@ -1018,7 +1055,7 @@ int _mmcamcorder_get_state(MMHandleType handle); void _mmcamcorder_set_state(MMHandleType handle, int state); /** - * This function gets asynchronous status of MSL Camcroder. + * This function gets asynchronous status of MSL Camcroder. * * @param[in] handle Handle of camcorder context. * @param[in] target_state setting target_state value of camcorder. @@ -1137,7 +1174,7 @@ int _mmcamcorder_create_pipeline(MMHandleType handle, int type); void _mmcamcorder_destroy_pipeline(MMHandleType handle, int type); /** - * This function sets gstreamer element status. + * This function sets gstreamer element status. * If the gstreamer fails to set status or returns asynchronous mode, * this function waits for state changed until timeout expired. * @@ -1151,14 +1188,14 @@ void _mmcamcorder_destroy_pipeline(MMHandleType handle, int type); int _mmcamcorder_gst_set_state(MMHandleType handle, GstElement *pipeline, GstState target_state); /** - * This function sets gstreamer element status, asynchronously. + * This function sets gstreamer element status, asynchronously. * Regardless of processing, it returns immediately. * * @param[in] pipeline Pointer of pipeline * @param[in] target_state newly setting status * @return This function returns zero on success, or negative value with error code. * @remarks - * @see + * @see * */ int _mmcamcorder_gst_set_state_async(MMHandleType handle, GstElement *pipeline, GstState target_state); diff --git a/src/include/mm_camcorder_platform.h b/src/include/mm_camcorder_platform.h index 9d64d0b..c2196e6 100644 --- a/src/include/mm_camcorder_platform.h +++ b/src/include/mm_camcorder_platform.h @@ -143,7 +143,7 @@ extern "C" { #define _MMCAMCORDER_SENSOR_ENUM_NONE -255 /* camera information related */ -#define CAMINFO_CONVERT_NUM 41 +#define CAMINFO_CONVERT_NUM 40 /*======================================================================================= @@ -226,10 +226,11 @@ typedef struct { ========================================================================================*/ int _mmcamcorder_convert_msl_to_sensor(MMHandleType handle, int attr_idx, int mslval); int _mmcamcorder_convert_sensor_to_msl(MMHandleType handle, int attr_idx, int sensval); +int _mmcamcorder_get_fps_array_by_resolution(MMHandleType handle, int width, int height, MMCamAttrsInfo* fps_info); int _mmcamcorder_set_converted_value(MMHandleType handle, _MMCamcorderEnumConvert *convert); int _mmcamcorder_init_convert_table(MMHandleType handle); -int _mmcamcorder_init_attr_from_configure(MMHandleType handle); +int _mmcamcorder_init_attr_from_configure(MMHandleType handle, int type); int _mmcamcorder_convert_brightness(int mslVal); int _mmcamcorder_convert_whitebalance(int mslVal); diff --git a/src/include/mm_camcorder_stillshot.h b/src/include/mm_camcorder_stillshot.h index e68c7f8..5fe834c 100644 --- a/src/include/mm_camcorder_stillshot.h +++ b/src/include/mm_camcorder_stillshot.h @@ -40,10 +40,11 @@ extern "C" { /*======================================================================================= | MACRO DEFINITIONS | ========================================================================================*/ -#define _MMCAMCORDER_CAPTURE_STOP_CHECK_INTERVAL 5000 -#define _MMCAMCORDER_CAPTURE_STOP_CHECK_COUNT 600 +#define _MMCAMCORDER_CAPTURE_STOP_CHECK_INTERVAL (50*1000) +#define _MMCAMCORDER_CAPTURE_STOP_CHECK_COUNT 60 + #define _MNOTE_VALUE_NONE 0 -#define _SOUND_STATUS_INIT -1 +#define _SOUND_STATUS_INIT -1 /*======================================================================================= | ENUM DEFINITIONS | @@ -71,7 +72,6 @@ typedef struct { int preview_format; /**< Preview format */ int hdr_capture_mode; /**< HDR Capture mode */ gboolean sound_status; /**< sound status of system */ - unsigned int volume_level; /**< media volume level of system */ gboolean played_capture_sound; /**< whether play capture sound when capture starts */ } _MMCamcorderImageInfo; @@ -137,10 +137,11 @@ int _mmcamcorder_video_capture_command(MMHandleType handle, int command); int __mmcamcorder_set_exif_basic_info(MMHandleType handle, int image_width, int image_height); int __mmcamcorder_update_exif_info(MMHandleType handle,void* imagedata, int imgln); void __mmcamcorder_init_stillshot_info(MMHandleType handle); -void __mmcamcorder_get_capture_data_from_buffer(MMCamcorderCaptureDataType *capture_data, int pixtype, GstBuffer *buffer); -void __mmcamcorder_release_jpeg_data(MMHandleType handle, MMCamcorderCaptureDataType *dest); -int __mmcamcorder_capture_save_exifinfo(MMHandleType handle, MMCamcorderCaptureDataType *original, MMCamcorderCaptureDataType *thumbnail); -int __mmcamcorder_set_jpeg_data(MMHandleType handle, MMCamcorderCaptureDataType *dest, MMCamcorderCaptureDataType *thumbnail); +void __mmcamcorder_get_capture_data_from_buffer(MMCamcorderCaptureDataType *capture_data, int pixtype, GstSample *sample); +void __mmcamcorder_release_jpeg_data(MMHandleType handle, MMCamcorderCaptureDataType *dest, int tag_enable, int provide_exif); +int __mmcamcorder_capture_save_exifinfo(MMHandleType handle, MMCamcorderCaptureDataType *original, MMCamcorderCaptureDataType *thumbnail, int provide_exif); +int __mmcamcorder_set_jpeg_data(MMHandleType handle, MMCamcorderCaptureDataType *dest, MMCamcorderCaptureDataType *thumbnail, int provide_exif); +gboolean __mmcamcorder_handoff_callback(GstElement *fakesink, GstBuffer *buffer, GstPad *pad, gpointer u_data); #ifdef __cplusplus } diff --git a/src/include/mm_camcorder_util.h b/src/include/mm_camcorder_util.h index 9283dad..f1ea0ec 100644 --- a/src/include/mm_camcorder_util.h +++ b/src/include/mm_camcorder_util.h @@ -25,7 +25,6 @@ /*======================================================================================= | INCLUDE FILES | ========================================================================================*/ -#include #include @@ -55,7 +54,7 @@ do { \ } else { \ item->object = G_OBJECT(x_pad); \ item->category = x_category; \ - item->handler_id = gst_pad_add_buffer_probe(x_pad, G_CALLBACK(x_callback), x_hcamcorder); \ + item->handler_id = gst_pad_add_probe(x_pad, GST_PAD_PROBE_TYPE_BUFFER, x_callback, x_hcamcorder, NULL); \ x_hcamcorder->buffer_probes = g_list_append(x_hcamcorder->buffer_probes, item); \ _mmcam_dbg_log("Adding buffer probe on [%s:%s] - [ID : %lu], [Category : %x] ", GST_DEBUG_PAD_NAME(item->object), item->handler_id, item->category); \ } \ @@ -73,7 +72,7 @@ do { \ } else { \ item->object =G_OBJECT(x_pad); \ item->category = x_category; \ - item->handler_id = gst_pad_add_event_probe(x_pad, G_CALLBACK(x_callback), x_hcamcorder); \ + item->handler_id = gst_pad_add_probe(x_pad, GST_PAD_PROBE_TYPE_EVENT_BOTH, x_callback, x_hcamcorder, NULL); \ x_hcamcorder->event_probes = g_list_append(x_hcamcorder->event_probes, item); \ _mmcam_dbg_log("Adding event probe on [%s:%s] - [ID : %lu], [Category : %x] ", GST_DEBUG_PAD_NAME(item->object), item->handler_id, item->category); \ } \ @@ -93,7 +92,7 @@ do { \ item->handler_id = g_signal_connect(G_OBJECT(x_object), x_signal,\ G_CALLBACK(x_callback), x_hcamcorder ); \ x_hcamcorder->signals = g_list_append(x_hcamcorder->signals, item); \ - _mmcam_dbg_log("Connecting signal on [%s] - [ID : %lu], [Category : %x] ", GST_OBJECT_NAME(item->object), item->handler_id, item->category); \ + _mmcam_dbg_log("Connecting signal on [%s][%p] - [ID : %lu], [Category : %x] ", GST_OBJECT_NAME(item->object), item->object, item->handler_id, item->category); \ } \ } while (0); @@ -113,7 +112,32 @@ do { \ #define MMCAMCORDER_G_OBJECT_SET(obj, name, value) \ do { \ if (obj) { \ - if(g_object_class_find_property(G_OBJECT_GET_CLASS(G_OBJECT(obj)), name)) { \ + GParamSpec *spec = g_object_class_find_property(G_OBJECT_GET_CLASS(G_OBJECT(obj)), name);\ + if(spec) { \ + if (spec->value_type == G_TYPE_INT64) {\ + g_object_set(G_OBJECT(obj), name, (gint64)value, NULL); \ + } else if (spec->value_type == G_TYPE_UINT64) { \ + g_object_set(G_OBJECT(obj), name, (guint64)value, NULL); \ + } else if (spec->value_type == G_TYPE_FLOAT) { \ + g_object_set(G_OBJECT(obj), name, (float)value, NULL); \ + } else if (spec->value_type == G_TYPE_DOUBLE) { \ + g_object_set(G_OBJECT(obj), name, (double)value, NULL); \ + } else { \ + g_object_set(G_OBJECT(obj), name, value, NULL); \ + } \ + } else { \ + _mmcam_dbg_warn ("The object doesn't have a property named(%s)", name); \ + } \ + } else { \ + _mmcam_dbg_err("Null object"); \ + } \ +} while(0); + +#define MMCAMCORDER_G_OBJECT_SET_POINTER(obj, name, value) \ +do { \ + if (obj) { \ + GParamSpec *spec = g_object_class_find_property(G_OBJECT_GET_CLASS(G_OBJECT(obj)), name);\ + if(spec) { \ g_object_set(G_OBJECT(obj), name, value, NULL); \ } else { \ _mmcam_dbg_warn ("The object doesn't have a property named(%s)", name); \ @@ -136,7 +160,7 @@ do { \ msg.id = msg_id;\ msg.param.code = msg_code;\ _mmcam_dbg_log("msg id : %x, code : %x", msg_id, msg_code);\ - _mmcamcroder_send_message((MMHandleType)handle, &msg);\ + _mmcamcorder_send_message((MMHandleType)handle, &msg);\ } @@ -185,68 +209,6 @@ typedef struct { GMutex lock; /**< mutex for item */ } _MMCamcorderMsgItem; -/** - * Structure of zero copy image buffer - */ -#define SCMN_IMGB_MAX_PLANE (4) - -/* image buffer definition *************************************************** - - +------------------------------------------+ --- - | | ^ - | a[], p[] | | - | +---------------------------+ --- | | - | | | ^ | | - | |<---------- w[] ---------->| | | | - | | | | | | - | | | | - | | | h[] | e[] - | | | | - | | | | | | - | | | | | | - | | | v | | - | +---------------------------+ --- | | - | | v - +------------------------------------------+ --- - - |<----------------- s[] ------------------>| -*/ - -typedef struct -{ - /* width of each image plane */ - int w[SCMN_IMGB_MAX_PLANE]; - /* height of each image plane */ - int h[SCMN_IMGB_MAX_PLANE]; - /* stride of each image plane */ - int s[SCMN_IMGB_MAX_PLANE]; - /* elevation of each image plane */ - int e[SCMN_IMGB_MAX_PLANE]; - /* user space address of each image plane */ - void *a[SCMN_IMGB_MAX_PLANE]; - /* physical address of each image plane, if needs */ - void *p[SCMN_IMGB_MAX_PLANE]; - /* color space type of image */ - int cs; - /* left postion, if needs */ - int x; - /* top position, if needs */ - int y; - /* to align memory */ - int __dummy2; - /* arbitrary data */ - int data[16]; - /* dmabuf or ion fd */ - int fd[SCMN_IMGB_MAX_PLANE]; - /* flag for buffer share */ - int buf_share_method; - /* Y plane size */ - int y_size; - /* UV plane size */ - int uv_size; - /* Tizen buffer object of each image plane */ - void *bo[SCMN_IMGB_MAX_PLANE]; -} SCMN_IMGB; /*======================================================================================= | CONSTANT DEFINITIONS | @@ -255,6 +217,7 @@ typedef struct #define NANO_SEC_PER_MILI_SEC 1000000 #define _MMCAMCORDER_HANDLER_CATEGORY_ALL \ (_MMCAMCORDER_HANDLER_PREVIEW | _MMCAMCORDER_HANDLER_VIDEOREC |_MMCAMCORDER_HANDLER_STILLSHOT | _MMCAMCORDER_HANDLER_AUDIOREC) +#define G_DBUS_REPLY_TIMEOUT (120 * 1000) /*======================================================================================= | GLOBAL FUNCTION PROTOTYPES | @@ -270,19 +233,19 @@ gboolean _mmcamcorder_add_elements_to_bin(GstBin *bin, GList *element_list); gboolean _mmcamcorder_link_elements(GList *element_list); /* Message */ -gboolean _mmcamcroder_msg_callback(void *data); -gboolean _mmcamcroder_send_message(MMHandleType handle, _MMCamcorderMsgItem *data); -void _mmcamcroder_remove_message_all(MMHandleType handle); +gboolean _mmcamcorder_msg_callback(void *data); +gboolean _mmcamcorder_send_message(MMHandleType handle, _MMCamcorderMsgItem *data); +void _mmcamcorder_remove_message_all(MMHandleType handle); /* Pixel format */ -int _mmcamcorder_get_pixel_format(GstBuffer *buffer); +int _mmcamcorder_get_pixel_format(GstCaps *pad); int _mmcamcorder_get_pixtype(unsigned int fourcc); unsigned int _mmcamcorder_get_fourcc(int pixtype, int codectype, int use_zero_copy_format); /* JPEG encode */ gboolean _mmcamcorder_encode_jpeg(void *src_data, unsigned int src_width, unsigned int src_height, int src_format, unsigned int src_length, unsigned int jpeg_quality, - void **result_data, unsigned int *result_length, int enc_type); + void **result_data, unsigned int *result_length); /* resize */ gboolean _mmcamcorder_resize_frame(unsigned char *src_data, unsigned int src_width, unsigned int src_height, unsigned int src_length, int src_format, unsigned char **dst_data, unsigned int *dst_width, unsigned int *dst_height, unsigned int *dst_length); @@ -300,17 +263,20 @@ gboolean _mmcamcorder_write_loci(FILE *f, _MMCamcorderLocationInfo info); gboolean _mmcamcorder_write_geodata(FILE *f,_MMCamcorderLocationInfo info); gboolean _mmcamcorder_write_udta(FILE *f, int gps_enable, _MMCamcorderLocationInfo info, _MMCamcorderLocationInfo geotag); guint64 _mmcamcorder_get_container_size(const guchar *size); +guint64 _mmcamcorder_get_container_size64(const guchar *size); gboolean _mmcamcorder_update_composition_matrix(FILE *f, int orientation); /* File system */ -int _mmcamcorder_get_freespace(const gchar *path, guint64 *free_space); -int _mmcamcorder_get_freespace_except_system(guint64 *free_space); +int _mmcamcorder_get_freespace(const gchar *path, const gchar *root_directory, guint64 *free_space); int _mmcamcorder_get_file_size(const char *filename, guint64 *size); int _mmcamcorder_get_file_system_type(const gchar *path, int *file_system_type); -gboolean _mmcamcorder_check_file_path(const gchar *path); +int _mmcamcorder_get_root_directory(char **root_directory); /* Task */ -void *_mmcamcorder_util_task_thread_func(void *data); +void *_mmcamcorder_task_thread_func(void *data); + +/* device */ +int _mmcamcorder_get_device_flash_brightness(int *brightness); #ifdef __cplusplus } diff --git a/src/include/mm_camcorder_videorec.h b/src/include/mm_camcorder_videorec.h index 5267d9d..f15a12f 100644 --- a/src/include/mm_camcorder_videorec.h +++ b/src/include/mm_camcorder_videorec.h @@ -60,7 +60,7 @@ typedef struct { double record_timestamp_ratio; /**< timestamp ratio of video recording for slow/fast motion recording */ double record_motion_rate; /**< motion rate of video recording for slow/fast motion recording */ GstClockTime prev_preview_ts; /**< previous preview frame timestamp */ - GstClockTime prev_video_ts; /**< previous video frame timestamp */ + GstClockTime base_video_ts; /**< base video frame timestamp */ guint record_drop_count; /**< drop count of video recording for slow/fast motion recording */ guint64 video_frame_count; /**< current video frame */ guint64 audio_frame_count; /**< current audio frame */ @@ -74,7 +74,8 @@ typedef struct { int video_width; /**< video width */ int video_height; /**< video height */ int fps; /**< fps in videosrc caps */ - int is_firstframe; + gboolean is_firstframe; + gboolean get_first_I_frame; /**< start flag for H.264 preview recording */ gboolean support_dual_stream; /**< support dual stream flag */ gboolean record_dual_stream; /**< record with dual stream flag */ gboolean restart_preview; /**< flag for whether restart preview or not when start recording */ diff --git a/src/mm_camcorder.c b/src/mm_camcorder.c index c40fe51..d764e39 100644 --- a/src/mm_camcorder.c +++ b/src/mm_camcorder.c @@ -47,8 +47,12 @@ int mm_camcorder_create(MMHandleType *camcorder, MMCamPreset *info) _mmcam_dbg_err(""); + traceBegin(TTRACE_TAG_CAMERA, "MMCAMCORDER:CREATE"); + error = _mmcamcorder_create(camcorder, info); + traceEnd(TTRACE_TAG_CAMERA); + _mmcam_dbg_err("END"); return error; @@ -63,8 +67,12 @@ int mm_camcorder_destroy(MMHandleType camcorder) _mmcam_dbg_err(""); + traceBegin(TTRACE_TAG_CAMERA, "MMCAMCORDER:DESTROY"); + error = _mmcamcorder_destroy(camcorder); + traceEnd(TTRACE_TAG_CAMERA); + _mmcam_dbg_err("END!!!"); return error; @@ -81,8 +89,12 @@ int mm_camcorder_realize(MMHandleType camcorder) _MMCAMCORDER_LOCK_ASM(camcorder); + traceBegin(TTRACE_TAG_CAMERA, "MMCAMCORDER:REALIZE"); + error = _mmcamcorder_realize(camcorder); + traceEnd(TTRACE_TAG_CAMERA); + _MMCAMCORDER_UNLOCK_ASM(camcorder); _mmcam_dbg_err("END"); @@ -101,8 +113,12 @@ int mm_camcorder_unrealize(MMHandleType camcorder) _MMCAMCORDER_LOCK_ASM(camcorder); + traceBegin(TTRACE_TAG_CAMERA, "MMCAMCORDER:UNREALIZE"); + error = _mmcamcorder_unrealize(camcorder); + traceEnd(TTRACE_TAG_CAMERA); + _MMCAMCORDER_UNLOCK_ASM(camcorder); _mmcam_dbg_err("END"); @@ -121,8 +137,12 @@ int mm_camcorder_start(MMHandleType camcorder) _MMCAMCORDER_LOCK_ASM(camcorder); + traceBegin(TTRACE_TAG_CAMERA, "MMCAMCORDER:START"); + error = _mmcamcorder_start(camcorder); + traceEnd(TTRACE_TAG_CAMERA); + _MMCAMCORDER_UNLOCK_ASM(camcorder); _mmcam_dbg_err("END"); @@ -141,8 +161,12 @@ int mm_camcorder_stop(MMHandleType camcorder) _MMCAMCORDER_LOCK_ASM(camcorder); + traceBegin(TTRACE_TAG_CAMERA, "MMCAMCORDER:STOP"); + error = _mmcamcorder_stop(camcorder); + traceEnd(TTRACE_TAG_CAMERA); + _MMCAMCORDER_UNLOCK_ASM(camcorder); _mmcam_dbg_err("END"); @@ -352,7 +376,7 @@ int mm_camcorder_set_attributes(MMHandleType camcorder, char **err_attr_name, c va_start (var_args, attribute_name); ret = _mmcamcorder_set_attributes(camcorder, err_attr_name, attribute_name, var_args); va_end (var_args); - + return ret; } @@ -362,6 +386,11 @@ int mm_camcorder_get_attribute_info(MMHandleType camcorder, const char *attribut return _mmcamcorder_get_attribute_info(camcorder, attribute_name, info); } +int mm_camcorder_get_fps_list_by_resolution(MMHandleType camcorder, int width, int height, MMCamAttrsInfo *fps_info) +{ + return _mmcamcorder_get_fps_array_by_resolution(camcorder, width, height, fps_info); +} + int mm_camcorder_init_focusing(MMHandleType camcorder) { diff --git a/src/mm_camcorder_attribute.c b/src/mm_camcorder_attribute.c index d016d4b..b668e0f 100644 --- a/src/mm_camcorder_attribute.c +++ b/src/mm_camcorder_attribute.c @@ -26,15 +26,17 @@ #include "mm_camcorder_internal.h" #include "mm_camcorder_gstcommon.h" -#include -#include -#include +#include +#include +#include /*----------------------------------------------------------------------- | MACRO DEFINITIONS: | -----------------------------------------------------------------------*/ #define MMCAMCORDER_DEFAULT_CAMERA_WIDTH 640 #define MMCAMCORDER_DEFAULT_CAMERA_HEIGHT 480 +#define MMCAMCORDER_DEFAULT_ENCODER_PREVIEW_BITRATE (1024*1024*10) +#define MMCAMCORDER_DEFAULT_ENCODER_PREVIEW_IFRAME_INTERVAL 1000 /*--------------------------------------------------------------------------------------- | GLOBAL VARIABLE DEFINITIONS for internal | @@ -81,9 +83,9 @@ mm_cam_attr_construct_info cam_attrs_const_info[] ={ MMF_VALUE_TYPE_INT, MM_ATTRS_FLAG_RW, {(void*)MM_AUDIO_DEVICE_MIC}, - MM_ATTRS_VALID_TYPE_INT_RANGE, + MM_ATTRS_VALID_TYPE_INT_ARRAY, + (int)NULL, 0, - MM_AUDIO_DEVICE_NUM-1, NULL, }, { @@ -325,9 +327,9 @@ mm_cam_attr_construct_info cam_attrs_const_info[] ={ MMF_VALUE_TYPE_INT, MM_ATTRS_FLAG_RW, {(void*)30}, - MM_ATTRS_VALID_TYPE_INT_ARRAY, - 0, + MM_ATTRS_VALID_TYPE_INT_RANGE, 0, + 1024, _mmcamcorder_commit_camera_fps, }, { @@ -1285,6 +1287,28 @@ mm_cam_attr_construct_info cam_attrs_const_info[] ={ }, //110 { + MM_CAM_CAMERA_PAN, + "camera-pan", + MMF_VALUE_TYPE_INT, + MM_ATTRS_FLAG_RW, + {(void*)0}, + MM_ATTRS_VALID_TYPE_INT_RANGE, + -10, + 10, + _mmcamcorder_commit_camera_pan, + }, + { + MM_CAM_CAMERA_TILT, + "camera-tilt", + MMF_VALUE_TYPE_INT, + MM_ATTRS_FLAG_RW, + {(void*)0}, + MM_ATTRS_VALID_TYPE_INT_RANGE, + -10, + 10, + _mmcamcorder_commit_camera_tilt, + }, + { MM_CAM_VIDEO_WIDTH, "video-width", MMF_VALUE_TYPE_INT, @@ -1351,6 +1375,51 @@ mm_cam_attr_construct_info cam_attrs_const_info[] ={ NULL, }, { + MM_CAM_DISPLAY_SCALER, + "display-scaler", + MMF_VALUE_TYPE_INT, + MM_ATTRS_FLAG_RW, + {(void*)0}, + MM_ATTRS_VALID_TYPE_INT_RANGE, + 0, + 1, + _mmcamcorder_commit_display_scaler, + }, + { + MM_CAM_ENCODED_PREVIEW_BITRATE, + "encoded-preview-bitrate", + MMF_VALUE_TYPE_INT, + MM_ATTRS_FLAG_RW, + {(void*)MMCAMCORDER_DEFAULT_ENCODER_PREVIEW_BITRATE}, + MM_ATTRS_VALID_TYPE_INT_RANGE, + 0, + _MMCAMCORDER_MAX_INT, + _mmcamcorder_commit_encoded_preview_bitrate, + }, + //120 + { + MM_CAM_ENCODED_PREVIEW_IFRAME_INTERVAL, + "encoded-preview-iframe-interval", + MMF_VALUE_TYPE_INT, + MM_ATTRS_FLAG_RW, + {(void*)MMCAMCORDER_DEFAULT_ENCODER_PREVIEW_IFRAME_INTERVAL}, + MM_ATTRS_VALID_TYPE_INT_RANGE, + 0, + _MMCAMCORDER_MAX_INT, + _mmcamcorder_commit_encoded_preview_iframe_interval, + }, + { + MM_CAM_USB_AUDIO_UDEV_ID, + "usb-audio-device-id", + MMF_VALUE_TYPE_STRING, + MM_ATTRS_FLAG_RW, + {(void*)NULL}, + MM_ATTRS_VALID_TYPE_NONE, + 0, + 0, + NULL, + }, + { MM_CAM_RECORDER_TAG_ENABLE, "recorder-tag-enable", MMF_VALUE_TYPE_INT, @@ -1549,6 +1618,7 @@ _mmcamcorder_set_attributes(MMHandleType handle, char **err_attr_name, const cha { MMHandleType attrs = 0; int ret = MM_ERROR_NONE; + mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle); mmf_return_val_if_fail( handle, MM_ERROR_CAMCORDER_INVALID_ARGUMENT ); // mmf_return_val_if_fail( err_attr_name, MM_ERROR_CAMCORDER_INVALID_ARGUMENT ); @@ -1567,12 +1637,19 @@ _mmcamcorder_set_attributes(MMHandleType handle, char **err_attr_name, const cha } if (ret == MM_ERROR_NONE) { + hcamcorder->error_code = MM_ERROR_NONE; ret = mm_attrs_set_valist(attrs, err_attr_name, attribute_name, var_args); } _MMCAMCORDER_UNLOCK_CMD(handle); if (ret != MM_ERROR_NONE) { + if (hcamcorder->error_code != MM_ERROR_NONE) { + _mmcam_dbg_err("error_code is not NONE. origin 0x%x, modified 0x%x", ret, hcamcorder->error_code); + ret = hcamcorder->error_code; + hcamcorder->error_code = MM_ERROR_NONE; + } + _mmcam_dbg_err("failed error code 0x%x - handle %p", ret, (mmf_camcorder_t *)handle); } @@ -1822,7 +1899,7 @@ bool _mmcamcorder_commit_capture_break_cont_shot (MMHandleType handle, int attr_ return TRUE; } - control = GST_CAMERA_CONTROL( sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst ); + control = GST_CAMERA_CONTROL(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst); if (control) { gst_camera_control_set_capture_command(control, GST_CAMERA_CONTROL_CAPTURE_COMMAND_STOP_MULTISHOT); _mmcam_dbg_warn("Commit Break continuous shot : Set command OK. current state[%d]", current_state); @@ -1922,8 +1999,39 @@ bool _mmcamcorder_commit_audio_volume (MMHandleType handle, int attr_idx, const bool _mmcamcorder_commit_camera_fps (MMHandleType handle, int attr_idx, const mmf_value_t *value) { + MMCamAttrsInfo fps_info; + int resolution_width = 0; + int resolution_height = 0; + int i; + int ret; + _mmcam_dbg_log("FPS(%d)", value->value.i_val); - return TRUE; + + ret = mm_camcorder_get_attributes(handle, NULL, + MMCAM_CAMERA_WIDTH, &resolution_width, + MMCAM_CAMERA_HEIGHT, &resolution_height, + NULL); + + if(ret != MM_ERROR_NONE) { + _mmcam_dbg_err("FAILED : coult not get resolution values."); + return FALSE; + } + + ret = mm_camcorder_get_fps_list_by_resolution(handle, resolution_width, resolution_height, &fps_info); + + if(ret != MM_ERROR_NONE) { + _mmcam_dbg_err("FAILED : coult not get FPS values by resolution."); + return FALSE; + } + + for(i=0; ivalue.i_val == fps_info.int_array.array[i]) { + return TRUE; + } + } + + _mmcam_dbg_err("FAILED : %d is not supported FPS", value->value.i_val); + return FALSE; } @@ -1964,7 +2072,7 @@ bool _mmcamcorder_commit_camera_recording_motion_rate(MMHandleType handle, int a } -bool _mmcamcorder_commit_camera_width (MMHandleType handle, int attr_idx, const mmf_value_t *value) +bool _mmcamcorder_commit_camera_width(MMHandleType handle, int attr_idx, const mmf_value_t *value) { MMHandleType attr = 0; int current_state = MM_CAMCORDER_STATE_NONE; @@ -2008,6 +2116,13 @@ bool _mmcamcorder_commit_camera_width (MMHandleType handle, int attr_idx, const NULL); if (current_state == MM_CAMCORDER_STATE_PREPARE) { + if (hcamcorder->resolution_changed == FALSE) { + _mmcam_dbg_log("no need to restart preview"); + return TRUE; + } + + hcamcorder->resolution_changed = FALSE; + if (!pthread_mutex_trylock(&(hcamcorder->restart_preview_lock))) { _mmcam_dbg_log("restart preview"); @@ -2016,6 +2131,13 @@ bool _mmcamcorder_commit_camera_width (MMHandleType handle, int attr_idx, const _mmcamcorder_gst_set_state(handle, sc->element[_MMCAMCORDER_MAIN_PIPE].gst, GST_STATE_READY); + if (sc->info_image->preview_format == MM_PIXEL_FORMAT_ENCODED_H264) { + if (!_mmcamcorder_recreate_decoder_for_encoded_preview(handle)) { + pthread_mutex_unlock(&(hcamcorder->restart_preview_lock)); + return FALSE; + } + } + /* get preview format */ sc->info_image->preview_format = preview_format; sc->fourcc = _mmcamcorder_get_fourcc(sc->info_image->preview_format, codec_type, hcamcorder->use_zero_copy_format); @@ -2047,7 +2169,7 @@ bool _mmcamcorder_commit_camera_width (MMHandleType handle, int attr_idx, const } -bool _mmcamcorder_commit_camera_height (MMHandleType handle, int attr_idx, const mmf_value_t *value) +bool _mmcamcorder_commit_camera_height(MMHandleType handle, int attr_idx, const mmf_value_t *value) { int ret = 0; int current_state = MM_CAMCORDER_STATE_NONE; @@ -2066,7 +2188,7 @@ bool _mmcamcorder_commit_camera_height (MMHandleType handle, int attr_idx, const mmf_return_val_if_fail(attr, FALSE); _mmcam_dbg_log("Height(%d)", value->value.i_val); - current_state = _mmcamcorder_get_state( handle); + current_state = _mmcamcorder_get_state(handle); if (current_state > MM_CAMCORDER_STATE_PREPARE) { _mmcam_dbg_log("Resolution can't be changed.(state=%d)", current_state); @@ -2089,6 +2211,13 @@ bool _mmcamcorder_commit_camera_height (MMHandleType handle, int attr_idx, const sc->info_video->preview_height = height; if (current_state == MM_CAMCORDER_STATE_PREPARE) { + if (hcamcorder->resolution_changed == FALSE) { + _mmcam_dbg_log("no need to restart preview"); + return TRUE; + } + + hcamcorder->resolution_changed = FALSE; + if (!pthread_mutex_trylock(&(hcamcorder->restart_preview_lock))) { _mmcam_dbg_log("restart preview"); @@ -2099,6 +2228,13 @@ bool _mmcamcorder_commit_camera_height (MMHandleType handle, int attr_idx, const _mmcamcorder_gst_set_state(handle, sc->element[_MMCAMCORDER_MAIN_PIPE].gst, GST_STATE_READY); + if (sc->info_image->preview_format == MM_PIXEL_FORMAT_ENCODED_H264) { + if (!_mmcamcorder_recreate_decoder_for_encoded_preview(handle)) { + pthread_mutex_unlock(&(hcamcorder->restart_preview_lock)); + return FALSE; + } + } + /* get preview format */ sc->info_image->preview_format = preview_format; sc->fourcc = _mmcamcorder_get_fourcc(sc->info_image->preview_format, codec_type, hcamcorder->use_zero_copy_format); @@ -2205,6 +2341,103 @@ bool _mmcamcorder_commit_camera_zoom (MMHandleType handle, int attr_idx, const m return FALSE; } +bool _mmcamcorder_commit_camera_pan(MMHandleType handle, int attr_idx, const mmf_value_t *value) +{ + _MMCamcorderSubContext *sc = NULL; + int current_state = MM_CAMCORDER_STATE_NONE; + + GstCameraControl *CameraControl = NULL; + GstCameraControlChannel *CameraControlChannel = NULL; + const GList *controls = NULL; + const GList *item = NULL; + + sc = MMF_CAMCORDER_SUBCONTEXT(handle); + mmf_return_val_if_fail(sc, TRUE); + + _mmcam_dbg_log("pan : %d", value->value.i_val); + + current_state = _mmcamcorder_get_state(handle); + if (current_state < MM_CAMCORDER_STATE_PREPARE || + current_state == MM_CAMCORDER_STATE_CAPTURING) { + _mmcam_dbg_err("invalid state[%d]", current_state); + return FALSE; + } + + if (sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst) { + CameraControl = GST_CAMERA_CONTROL(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst); + controls = gst_camera_control_list_channels(CameraControl); + if (controls != NULL) { + for (item = controls ; item && item->data ; item = item->next) { + CameraControlChannel = item->data; + _mmcam_dbg_log("CameraControlChannel->label %s", CameraControlChannel->label); + if (!strcmp(CameraControlChannel->label, "pan")) { + if (gst_camera_control_set_value(CameraControl, CameraControlChannel, value->value.i_val)) { + _mmcam_dbg_warn("set pan %d done", value->value.i_val); + return TRUE; + } else { + _mmcam_dbg_err("failed to set pan %d", value->value.i_val); + return FALSE; + } + } + } + + if (item == NULL) { + _mmcam_dbg_warn("failed to find pan control channel"); + } + } + } + + return FALSE; +} + +bool _mmcamcorder_commit_camera_tilt(MMHandleType handle, int attr_idx, const mmf_value_t *value) +{ + _MMCamcorderSubContext *sc = NULL; + int current_state = MM_CAMCORDER_STATE_NONE; + + GstCameraControl *CameraControl = NULL; + GstCameraControlChannel *CameraControlChannel = NULL; + const GList *controls = NULL; + const GList *item = NULL; + + sc = MMF_CAMCORDER_SUBCONTEXT(handle); + mmf_return_val_if_fail(sc, TRUE); + + _mmcam_dbg_log("tilt : %d", value->value.i_val); + + current_state = _mmcamcorder_get_state(handle); + if (current_state < MM_CAMCORDER_STATE_PREPARE || + current_state == MM_CAMCORDER_STATE_CAPTURING) { + _mmcam_dbg_err("invalid state[%d]", current_state); + return FALSE; + } + + if (sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst) { + CameraControl = GST_CAMERA_CONTROL(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst); + controls = gst_camera_control_list_channels(CameraControl); + if (controls != NULL) { + for (item = controls ; item && item->data ; item = item->next) { + CameraControlChannel = item->data; + _mmcam_dbg_log("CameraControlChannel->label %s", CameraControlChannel->label); + if (!strcmp(CameraControlChannel->label, "tilt")) { + if (gst_camera_control_set_value(CameraControl, CameraControlChannel, value->value.i_val)) { + _mmcam_dbg_warn("set tilt %d done", value->value.i_val); + return TRUE; + } else { + _mmcam_dbg_err("failed to set tilt %d", value->value.i_val); + return FALSE; + } + } + } + + if (item == NULL) { + _mmcam_dbg_warn("failed to find tilt control channel"); + } + } + } + + return FALSE; +} bool _mmcamcorder_commit_camera_focus_mode (MMHandleType handle, int attr_idx, const mmf_value_t *value) { @@ -2289,7 +2522,8 @@ bool _mmcamcorder_commit_camera_af_scan_range (MMHandleType handle, int attr_idx _MMCamcorderSubContext *sc = NULL; GstCameraControl *control = NULL; int current_state = MM_CAMCORDER_STATE_NONE; - int mslVal, newVal; + int mslVal = 0; + int newVal = 0; int cur_focus_mode = 0; int cur_focus_range = 0; int msl_mode = MM_CAMCORDER_FOCUS_MODE_NONE; @@ -2355,164 +2589,205 @@ bool _mmcamcorder_commit_camera_af_scan_range (MMHandleType handle, int attr_idx bool _mmcamcorder_commit_camera_af_touch_area (MMHandleType handle, int attr_idx, const mmf_value_t *value) { + mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle); _MMCamcorderSubContext *sc = NULL; GstCameraControl *control = NULL; - GstCameraControlRectType set_area = { 0, 0, 0, 0 }, get_area = { 0, 0, 0, 0 }; + GstCameraControlRectType set_area = { 0, 0, 0, 0 }; + GstCameraControlRectType get_area = { 0, 0, 0, 0 }; int current_state = MM_CAMCORDER_STATE_NONE; int ret = FALSE; - int focus_mode = MM_CAMCORDER_FOCUS_MODE_NONE; + int i = 0; + gboolean is_supported = FALSE; + MMCamAttrsInfo focus_mode; gboolean do_set = FALSE; - MMCamAttrsInfo info_y, info_w, info_h; + MMCamAttrsInfo info_y; + MMCamAttrsInfo info_w; + MMCamAttrsInfo info_h; + + if (hcamcorder == NULL) { + _mmcam_dbg_log("handle is NULL"); + return FALSE; + } sc = MMF_CAMCORDER_SUBCONTEXT(handle); - if (!sc) + if (!sc) { return TRUE; + } _mmcam_dbg_log("(%d)", attr_idx); - current_state = _mmcamcorder_get_state( handle); + ret = mm_camcorder_get_attribute_info(handle, MMCAM_CAMERA_FOCUS_MODE, &focus_mode); + if (ret != MM_ERROR_NONE) { + _mmcam_dbg_err("failed to get attribute info for FOCUS_MODE"); + return FALSE; + } - if( current_state < MM_CAMCORDER_STATE_PREPARE ) - { - _mmcam_dbg_log("It doesn't need to change dynamically.(state=%d)", current_state); - return TRUE; + for (i = 0 ; i < focus_mode.int_array.count ; i++) { + if (focus_mode.int_array.array[i] == MM_CAMCORDER_FOCUS_MODE_TOUCH_AUTO || + focus_mode.int_array.array[i] == MM_CAMCORDER_FOCUS_MODE_CONTINUOUS) { + is_supported = TRUE; + break; + } } - ret = mm_camcorder_get_attributes(handle, NULL, - MMCAM_CAMERA_FOCUS_MODE, &focus_mode, - NULL); - if( ret != MM_ERROR_NONE ) - { - _mmcam_dbg_warn( "Failed to get FOCUS MODE.[%x]", ret ); + if (is_supported == FALSE) { + _mmcam_dbg_err("TOUCH_AF/CONTINUOUS not supported"); + hcamcorder->error_code = MM_ERROR_CAMCORDER_NOT_SUPPORTED; return FALSE; } - if ((focus_mode != MM_CAMCORDER_FOCUS_MODE_TOUCH_AUTO ) && (focus_mode != MM_CAMCORDER_FOCUS_MODE_CONTINUOUS)) - { - _mmcam_dbg_warn( "Focus mode is NOT TOUCH AUTO or CONTINUOUS(current[%d]). return FALSE", focus_mode ); - return FALSE; + current_state = _mmcamcorder_get_state(handle); + if (current_state < MM_CAMCORDER_STATE_PREPARE) { + _mmcam_dbg_log("It doesn't need to change dynamically.(state=%d)", current_state); + return TRUE; } - if( sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst ) - { - if (!GST_IS_CAMERA_CONTROL(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst)) - { + if (sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst) { + if (!GST_IS_CAMERA_CONTROL(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst)) { _mmcam_dbg_log("Can't cast Video source into camera control."); return TRUE; } - switch( attr_idx ) - { - case MM_CAM_CAMERA_AF_TOUCH_X: - mm_camcorder_get_attribute_info(handle, MMCAM_CAMERA_AF_TOUCH_Y, &info_y); - mm_camcorder_get_attribute_info(handle, MMCAM_CAMERA_AF_TOUCH_WIDTH, &info_w); - mm_camcorder_get_attribute_info(handle, MMCAM_CAMERA_AF_TOUCH_HEIGHT, &info_h); - if( !( (info_y.flag|info_w.flag|info_h.flag) & MM_ATTRS_FLAG_MODIFIED) ) - { - set_area.x = value->value.i_val; - mm_camcorder_get_attributes(handle, NULL, - MMCAM_CAMERA_AF_TOUCH_Y, &set_area.y, - MMCAM_CAMERA_AF_TOUCH_WIDTH, &set_area.width, - MMCAM_CAMERA_AF_TOUCH_HEIGHT, &set_area.height, - NULL); - do_set = TRUE; - } - else - { - _mmcam_dbg_log( "Just store AF area[x:%d]", value->value.i_val ); - return TRUE; - } - break; - case MM_CAM_CAMERA_AF_TOUCH_Y: - mm_camcorder_get_attribute_info(handle, MMCAM_CAMERA_AF_TOUCH_WIDTH, &info_w); - mm_camcorder_get_attribute_info(handle, MMCAM_CAMERA_AF_TOUCH_HEIGHT, &info_h); - if( !( (info_w.flag|info_h.flag) & MM_ATTRS_FLAG_MODIFIED) ) - { - set_area.y = value->value.i_val; - mm_camcorder_get_attributes(handle, NULL, - MMCAM_CAMERA_AF_TOUCH_X, &set_area.x, - MMCAM_CAMERA_AF_TOUCH_WIDTH, &set_area.width, - MMCAM_CAMERA_AF_TOUCH_HEIGHT, &set_area.height, - NULL); - do_set = TRUE; - } - else - { - _mmcam_dbg_log( "Just store AF area[y:%d]", value->value.i_val ); - return TRUE; - } - break; - case MM_CAM_CAMERA_AF_TOUCH_WIDTH: - mm_camcorder_get_attribute_info(handle, MMCAM_CAMERA_AF_TOUCH_HEIGHT, &info_h); - if( !( info_h.flag & MM_ATTRS_FLAG_MODIFIED) ) - { - set_area.width = value->value.i_val; - mm_camcorder_get_attributes(handle, NULL, - MMCAM_CAMERA_AF_TOUCH_X, &set_area.x, - MMCAM_CAMERA_AF_TOUCH_Y, &set_area.y, - MMCAM_CAMERA_AF_TOUCH_HEIGHT, &set_area.height, - NULL); - do_set = TRUE; - } - else - { - _mmcam_dbg_log( "Just store AF area[width:%d]", value->value.i_val ); - return TRUE; - } - break; - case MM_CAM_CAMERA_AF_TOUCH_HEIGHT: - set_area.height = value->value.i_val; + memset(&info_y, 0x0, sizeof(MMCamAttrsInfo)); + memset(&info_w, 0x0, sizeof(MMCamAttrsInfo)); + memset(&info_h, 0x0, sizeof(MMCamAttrsInfo)); + + switch (attr_idx) { + case MM_CAM_CAMERA_AF_TOUCH_X: + mm_camcorder_get_attribute_info(handle, MMCAM_CAMERA_AF_TOUCH_Y, &info_y); + mm_camcorder_get_attribute_info(handle, MMCAM_CAMERA_AF_TOUCH_WIDTH, &info_w); + mm_camcorder_get_attribute_info(handle, MMCAM_CAMERA_AF_TOUCH_HEIGHT, &info_h); + if (!((info_y.flag|info_w.flag|info_h.flag) & MM_ATTRS_FLAG_MODIFIED)) { + set_area.x = value->value.i_val; mm_camcorder_get_attributes(handle, NULL, - MMCAM_CAMERA_AF_TOUCH_X, &set_area.x, - MMCAM_CAMERA_AF_TOUCH_Y, &set_area.y, - MMCAM_CAMERA_AF_TOUCH_WIDTH, &set_area.width, - NULL); + MMCAM_CAMERA_AF_TOUCH_Y, &set_area.y, + MMCAM_CAMERA_AF_TOUCH_WIDTH, &set_area.width, + MMCAM_CAMERA_AF_TOUCH_HEIGHT, &set_area.height, + NULL); do_set = TRUE; - break; - default: - break; + } else { + _mmcam_dbg_log("Just store AF area[x:%d]", value->value.i_val); + return TRUE; + } + break; + case MM_CAM_CAMERA_AF_TOUCH_Y: + mm_camcorder_get_attribute_info(handle, MMCAM_CAMERA_AF_TOUCH_WIDTH, &info_w); + mm_camcorder_get_attribute_info(handle, MMCAM_CAMERA_AF_TOUCH_HEIGHT, &info_h); + if (!((info_w.flag|info_h.flag) & MM_ATTRS_FLAG_MODIFIED)) { + set_area.y = value->value.i_val; + mm_camcorder_get_attributes(handle, NULL, + MMCAM_CAMERA_AF_TOUCH_X, &set_area.x, + MMCAM_CAMERA_AF_TOUCH_WIDTH, &set_area.width, + MMCAM_CAMERA_AF_TOUCH_HEIGHT, &set_area.height, + NULL); + do_set = TRUE; + } else { + _mmcam_dbg_log( "Just store AF area[y:%d]", value->value.i_val ); + return TRUE; + } + break; + case MM_CAM_CAMERA_AF_TOUCH_WIDTH: + mm_camcorder_get_attribute_info(handle, MMCAM_CAMERA_AF_TOUCH_HEIGHT, &info_h); + if (!(info_h.flag & MM_ATTRS_FLAG_MODIFIED)) { + set_area.width = value->value.i_val; + mm_camcorder_get_attributes(handle, NULL, + MMCAM_CAMERA_AF_TOUCH_X, &set_area.x, + MMCAM_CAMERA_AF_TOUCH_Y, &set_area.y, + MMCAM_CAMERA_AF_TOUCH_HEIGHT, &set_area.height, + NULL); + do_set = TRUE; + } else { + _mmcam_dbg_log("Just store AF area[width:%d]", value->value.i_val); + return TRUE; + } + break; + case MM_CAM_CAMERA_AF_TOUCH_HEIGHT: + set_area.height = value->value.i_val; + mm_camcorder_get_attributes(handle, NULL, + MMCAM_CAMERA_AF_TOUCH_X, &set_area.x, + MMCAM_CAMERA_AF_TOUCH_Y, &set_area.y, + MMCAM_CAMERA_AF_TOUCH_WIDTH, &set_area.width, + NULL); + do_set = TRUE; + break; + default: + break; } - if( do_set ) - { + if (do_set) { + _MMCamcorderVideoInfo *info = sc->info_video; + + if (info == NULL) { + _mmcam_dbg_err("video info is NULL"); + return FALSE; + } + control = GST_CAMERA_CONTROL (sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst); if (control == NULL) { _mmcam_dbg_err("cast CAMERA_CONTROL failed"); return FALSE; } - ret = gst_camera_control_get_auto_focus_area( control, &get_area ); - if( !ret ) - { + /* convert area */ + if (current_state >= MM_CAMCORDER_STATE_RECORDING && info->support_dual_stream == FALSE && + (info->preview_width != info->video_width || info->preview_height != info->video_height)) { + float ratio_width = 0.0; + float ratio_height = 0.0; + + if (info->preview_width != 0 && info->preview_height != 0) { + ratio_width = (float)info->video_width / (float)info->preview_width; + ratio_height = (float)info->video_height / (float)info->preview_height; + + _mmcam_dbg_log("original area %d,%d,%dx%d, resolution ratio : width %f, height %f", + set_area.x, set_area.y, set_area.width, set_area.height, ratio_width, ratio_height); + + set_area.x = (int)((float)set_area.x * ratio_width); + set_area.y = (int)((float)set_area.y * ratio_height); + set_area.width = (int)((float)set_area.width * ratio_width); + set_area.height = (int)((float)set_area.height * ratio_height); + + if (set_area.width <= 0) { + set_area.width = 1; + } + if (set_area.height <= 0) { + set_area.height = 1; + } + + _mmcam_dbg_log("converted area %d,%d,%dx%d", + set_area.x, set_area.y, set_area.width, set_area.height); + } else { + _mmcam_dbg_warn("invalid preview size %dx%d, skip AF area converting", + info->preview_width, info->preview_height); + } + } + + ret = gst_camera_control_get_auto_focus_area(control, &get_area); + if (!ret) { _mmcam_dbg_warn( "Failed to get AF area" ); return FALSE; } - if( get_area.x == set_area.x && get_area.y == set_area.y ) - // width and height are not supported now. - // get_area.width == set_area.width && get_area.height == set_area.height - { - _mmcam_dbg_log( "No need to set AF area[x,y:%d,%d]", get_area.x, get_area.y ); + /* width and height are not supported now */ + if (get_area.x == set_area.x && get_area.y == set_area.y) { + _mmcam_dbg_log("No need to set AF area[x,y:%d,%d]", + get_area.x, get_area.y); return TRUE; } - ret = gst_camera_control_set_auto_focus_area( control, set_area ); - if( ret ) - { - _mmcam_dbg_log( "Succeed to set AF area[%d,%d,%dx%d]", set_area.x, set_area.y, set_area.width, set_area.height ); + ret = gst_camera_control_set_auto_focus_area(control, set_area); + if (ret) { + _mmcam_dbg_log("Succeed to set AF area[%d,%d,%dx%d]", + set_area.x, set_area.y, set_area.width, set_area.height); return TRUE; - } - else - { - _mmcam_dbg_warn( "Failed to set AF area[%d,%d,%dx%d]", set_area.x, set_area.y, set_area.width, set_area.height ); + } else { + _mmcam_dbg_warn("Failed to set AF area[%d,%d,%dx%d]", + set_area.x, set_area.y, set_area.width, set_area.height); } } - } - else - { + } else { _mmcam_dbg_log("pointer of video src is null"); } @@ -2804,7 +3079,7 @@ bool _mmcamcorder_commit_target_filename(MMHandleType handle, int attr_idx, cons if (sc->encode_element && sc->encode_element[_MMCAMCORDER_ENCSINK_SINK].gst) { _mmcam_dbg_log("new file location set.[%s] filesink %p", filename, sc->encode_element[_MMCAMCORDER_ENCSINK_SINK].gst); - MMCAMCORDER_G_OBJECT_SET(sc->encode_element[_MMCAMCORDER_ENCSINK_SINK].gst, "location", filename); + MMCAMCORDER_G_OBJECT_SET_POINTER(sc->encode_element[_MMCAMCORDER_ENCSINK_SINK].gst, "location", filename); _mmcam_dbg_log("new file location set.(%s)", filename); } else { _mmcam_dbg_log("element is not created yet. [%s] will be set later...", filename); @@ -3061,7 +3336,7 @@ bool _mmcamcorder_commit_display_handle(MMHandleType handle, int attr_idx, const int current_state = MM_CAMCORDER_STATE_NONE; int display_surface_type = MM_DISPLAY_SURFACE_X; const char *videosink_name = NULL; - void *p_data = NULL; + void *p_handle = NULL; mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle); _MMCamcorderSubContext *sc = NULL; @@ -3089,34 +3364,39 @@ bool _mmcamcorder_commit_display_handle(MMHandleType handle, int attr_idx, const /* get videosink name */ _mmcamcorder_conf_get_value_element_name(sc->VideosinkElement, &videosink_name); - + if (videosink_name == NULL) { + _mmcam_dbg_err("Please check videosink element in configuration file"); + return FALSE; + } _mmcam_dbg_log("Commit : videosinkname[%s], surface type[%d]", videosink_name, display_surface_type); - p_data = value->value.p_val; + p_handle = value->value.p_val; if (display_surface_type == MM_DISPLAY_SURFACE_X_EXT) { - _mmcam_dbg_log("Commit : Set pixmap-id-callback %p", p_data); - MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_SINK].gst, "pixmap-id-callback", p_data); + _mmcam_dbg_log("Commit : Set pixmap-id-callback %p", p_handle); + MMCAMCORDER_G_OBJECT_SET_POINTER(sc->element[_MMCAMCORDER_VIDEOSINK_SINK].gst, "pixmap-id-callback", p_handle); } else { - if (p_data) { + if (p_handle) { if (!strcmp(videosink_name, "xvimagesink") || !strcmp(videosink_name, "ximagesink")) { - _mmcam_dbg_log("Commit : Set XID[%x]", *(int*)(p_data)); - gst_x_overlay_set_xwindow_id(GST_X_OVERLAY(sc->element[_MMCAMCORDER_VIDEOSINK_SINK].gst), *(int*)(p_data)); + _mmcam_dbg_log("Commit : Set XID[%x]", *(int*)(p_handle)); + gst_video_overlay_set_window_handle(GST_VIDEO_OVERLAY(sc->element[_MMCAMCORDER_VIDEOSINK_SINK].gst), *(int*)(p_handle)); } else if (!strcmp(videosink_name, "evasimagesink") || !strcmp(videosink_name, "evaspixmapsink")) { - _mmcam_dbg_log("Commit : Set evas object [%p]", p_data); - MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_SINK].gst, "evas-object", p_data); + _mmcam_dbg_log("Commit : Set evas object [%p]", p_handle); + MMCAMCORDER_G_OBJECT_SET_POINTER(sc->element[_MMCAMCORDER_VIDEOSINK_SINK].gst, "evas-object", p_handle); } else { _mmcam_dbg_warn("Commit : Nothing to commit with this element[%s]", videosink_name); return FALSE; } + } else { _mmcam_dbg_warn("Display handle is NULL"); return FALSE; } } + return TRUE; } @@ -3151,11 +3431,15 @@ bool _mmcamcorder_commit_display_handle_user_data(MMHandleType handle, int attr_ /* get videosink name */ _mmcamcorder_conf_get_value_element_name(sc->VideosinkElement, &videosink_name); + if (videosink_name == NULL) { + _mmcam_dbg_err("Please check videosink element in configuration file"); + return FALSE; + } _mmcam_dbg_log("Commit : videosinkname[%s]", videosink_name); if (!strcmp(videosink_name, "xvimagesink")) { _mmcam_dbg_log("Commit : Set pixmap-id-callback-userdata %p", p_userdata); - MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_SINK].gst, "pixmap-id-callback-userdata", p_userdata); + MMCAMCORDER_G_OBJECT_SET_POINTER(sc->element[_MMCAMCORDER_VIDEOSINK_SINK].gst, "pixmap-id-callback-userdata", p_userdata); } else { _mmcam_dbg_warn("Commit : Nothing to commit with this element[%s]", videosink_name); return FALSE; @@ -3191,6 +3475,10 @@ bool _mmcamcorder_commit_display_mode(MMHandleType handle, int attr_idx, const m sc = MMF_CAMCORDER_SUBCONTEXT(handle); _mmcamcorder_conf_get_value_element_name(sc->VideosinkElement, &videosink_name); + if (videosink_name == NULL) { + _mmcam_dbg_err("Please check videosink element in configuration file"); + return FALSE; + } _mmcam_dbg_log("Commit : videosinkname[%s]", videosink_name); if (!strcmp(videosink_name, "xvimagesink")) { @@ -3281,6 +3569,10 @@ bool _mmcamcorder_commit_display_visible(MMHandleType handle, int attr_idx, cons /* Get videosink name */ _mmcamcorder_conf_get_value_element_name(sc->VideosinkElement, &videosink_name); + if (videosink_name == NULL) { + _mmcam_dbg_err("Please check videosink element in configuration file"); + return FALSE; + } if (!strcmp(videosink_name, "xvimagesink") || !strcmp(videosink_name, "evasimagesink") || !strcmp(videosink_name, "evaspixmapsink")) { MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_SINK].gst, "visible", value->value.i_val); @@ -3321,6 +3613,10 @@ bool _mmcamcorder_commit_display_geometry_method (MMHandleType handle, int attr_ /* Get videosink name */ _mmcamcorder_conf_get_value_element_name(sc->VideosinkElement, &videosink_name); + if (videosink_name == NULL) { + _mmcam_dbg_err("Please check videosink element in configuration file"); + return FALSE; + } if (!strcmp(videosink_name, "xvimagesink") || !strcmp(videosink_name, "evasimagesink") || !strcmp(videosink_name, "evaspixmapsink")) { method = value->value.i_val; @@ -3370,6 +3666,10 @@ bool _mmcamcorder_commit_display_rect(MMHandleType handle, int attr_idx, const m /* Get videosink name */ _mmcamcorder_conf_get_value_element_name(sc->VideosinkElement, &videosink_name); + if (videosink_name == NULL) { + _mmcam_dbg_err("Please check videosink element in configuration file"); + return FALSE; + } if (!strcmp(videosink_name, "xvimagesink") || !strcmp(videosink_name, "evaspixmapsink")) { int rect_x = 0; @@ -3469,6 +3769,10 @@ bool _mmcamcorder_commit_display_scale(MMHandleType handle, int attr_idx, const /* Get videosink name */ _mmcamcorder_conf_get_value_element_name(sc->VideosinkElement, &videosink_name); + if (videosink_name == NULL) { + _mmcam_dbg_err("Please check videosink element in configuration file"); + return FALSE; + } zoom = value->value.i_val; if (!strcmp(videosink_name, "xvimagesink")) { vs_element = sc->element[_MMCAMCORDER_VIDEOSINK_SINK].gst; @@ -3514,6 +3818,10 @@ bool _mmcamcorder_commit_display_evas_do_scaling(MMHandleType handle, int attr_i /* Get videosink name */ _mmcamcorder_conf_get_value_element_name(sc->VideosinkElement, &videosink_name); + if (videosink_name == NULL) { + _mmcam_dbg_err("Please check videosink element in configuration file"); + return FALSE; + } if (!strcmp(videosink_name, "evaspixmapsink")) { MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_SINK].gst, "origin-size", !do_scaling); _mmcam_dbg_log("Set origin-size to %d", !(value->value.i_val)); @@ -3524,13 +3832,66 @@ bool _mmcamcorder_commit_display_evas_do_scaling(MMHandleType handle, int attr_i } } +bool _mmcamcorder_commit_display_scaler(MMHandleType handle, int attr_idx, const mmf_value_t *value) +{ + int current_state = MM_CAMCORDER_STATE_NONE; + GstElement *vs_element = NULL; + int vplane = 0; + const char *videosink_name = NULL; + + mmf_camcorder_t *hcamcorder= MMF_CAMCORDER( handle); + _MMCamcorderSubContext *sc = NULL; + + mmf_return_val_if_fail(handle, FALSE); + + /* check type */ + if (hcamcorder->type == MM_CAMCORDER_MODE_AUDIO) { + _mmcam_dbg_err("invalid mode %d", hcamcorder->type); + return FALSE; + } + + /* check current state */ + current_state = _mmcamcorder_get_state(handle); + if (current_state < MM_CAMCORDER_STATE_READY) { + _mmcam_dbg_log("NOT initialized. this will be applied later"); + return TRUE; + } + + sc = MMF_CAMCORDER_SUBCONTEXT(handle); + mmf_return_val_if_fail(sc, TRUE); + + vplane = value->value.i_val; + + /* Get videosink name */ + _mmcamcorder_conf_get_value_element_name(sc->VideosinkElement, &videosink_name); + if (videosink_name == NULL) { + _mmcam_dbg_err("Please check videosink element in configuration file"); + return FALSE; + } + if (!strcmp(videosink_name, "xvimagesink")) { + vs_element = sc->element[_MMCAMCORDER_VIDEOSINK_SINK].gst; + MMCAMCORDER_G_OBJECT_SET(vs_element, "device-scaler", vplane); + _mmcam_dbg_log("Set device-scaler %d",vplane ); + return TRUE; + } else { + _mmcam_dbg_warn("videosink[%s] does not support video plane selection", videosink_name); + return FALSE; + } +} bool _mmcamcorder_commit_strobe (MMHandleType handle, int attr_idx, const mmf_value_t *value) { bool bret = FALSE; _MMCamcorderSubContext *sc = NULL; + mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle); int strobe_type, mslVal, newVal, cur_value; int current_state = MM_CAMCORDER_STATE_NONE; + int set_flash_state = -1; + + if (hcamcorder == NULL) { + _mmcam_dbg_err("NULL handle"); + return FALSE; + } sc = MMF_CAMCORDER_SUBCONTEXT(handle); if (!sc) @@ -3538,19 +3899,57 @@ bool _mmcamcorder_commit_strobe (MMHandleType handle, int attr_idx, const mmf_va /*_mmcam_dbg_log( "Commit : strobe attribute(%d)", attr_idx );*/ - //status check - current_state = _mmcamcorder_get_state( handle); + mslVal = value->value.i_val; + + /* check flash state */ + if (attr_idx == MM_CAM_STROBE_MODE) { + int flash_brightness = 0; + + /* get current flash brightness */ + if (_mmcamcorder_get_device_flash_brightness(&flash_brightness) != MM_ERROR_NONE) { + _mmcam_dbg_err("_mmcamcorder_get_device_flash_brightness failed"); + hcamcorder->error_code = MM_ERROR_COMMON_INVALID_PERMISSION; + return FALSE; + } + + _mmcam_dbg_log("flash brightness %d", flash_brightness); + if (flash_brightness > 0 && + mslVal != MM_CAMCORDER_STROBE_MODE_OFF) { + /* other module already turned on flash */ + hcamcorder->error_code = MM_ERROR_CAMCORDER_DEVICE_BUSY; + _mmcam_dbg_err("other module already turned on flash. avoid to set flash mode here."); + return FALSE; + } else { + /* flash is OFF state, this case will set flash state key */ + if (mslVal == MM_CAMCORDER_STROBE_MODE_OFF) { + set_flash_state = VCONFKEY_CAMERA_FLASH_STATE_OFF; + } else { + set_flash_state = VCONFKEY_CAMERA_FLASH_STATE_ON; + } + + _mmcam_dbg_log("keep going, and will set flash state key %d", set_flash_state); + } + } + + /* check state */ + current_state = _mmcamcorder_get_state(handle); if (current_state < MM_CAMCORDER_STATE_READY) { _mmcam_dbg_log("It doesn't need to change dynamically.(state=%d)", current_state); + + if (set_flash_state != -1) { + _mmcam_dbg_log("set VCONFKEY_CAMERA_FLASH_STATE : %d", set_flash_state); + vconf_set_int(VCONFKEY_CAMERA_FLASH_STATE, set_flash_state); + vconf_set_int(VCONFKEY_CAMERA_PID, (int)getpid()); + } + return TRUE; } else if (current_state == MM_CAMCORDER_STATE_CAPTURING) { _mmcam_dbg_warn("invalid state[capturing]"); + hcamcorder->error_code = MM_ERROR_CAMCORDER_INVALID_STATE; return FALSE; } - mslVal = value->value.i_val; - switch (attr_idx) { case MM_CAM_STROBE_CONTROL: strobe_type = GST_CAMERA_CONTROL_STROBE_CONTROL; @@ -3605,6 +4004,12 @@ bool _mmcamcorder_commit_strobe (MMHandleType handle, int attr_idx, const mmf_va } } + if (bret == TRUE && set_flash_state != -1) { + _mmcam_dbg_log("set VCONFKEY_CAMERA_FLASH_STATE : %d", set_flash_state); + vconf_set_int(VCONFKEY_CAMERA_FLASH_STATE, set_flash_state); + vconf_set_int(VCONFKEY_CAMERA_PID, (int)getpid()); + } + return bret; } @@ -3685,6 +4090,11 @@ bool _mmcamcorder_commit_camera_hdr_capture(MMHandleType handle, int attr_idx, c MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_QUE].gst, "empty-buffers", TRUE); _mmcamcorder_gst_set_state(handle, sc->element[_MMCAMCORDER_MAIN_PIPE].gst, GST_STATE_READY); + if (sc->info_image->preview_format == MM_PIXEL_FORMAT_ENCODED_H264) { + if (!_mmcamcorder_recreate_decoder_for_encoded_preview(handle)) { + return FALSE; + } + } MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_QUE].gst, "empty-buffers", FALSE); MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_QUE].gst, "empty-buffers", FALSE); @@ -3800,6 +4210,64 @@ bool _mmcamcorder_commit_detect(MMHandleType handle, int attr_idx, const mmf_val return bret; } +bool _mmcamcorder_commit_encoded_preview_bitrate(MMHandleType handle, int attr_idx, const mmf_value_t *value) +{ + int current_state = MM_CAMCORDER_STATE_NONE; + int preview_format = MM_PIXEL_FORMAT_NV12; + + if ((void *)handle == NULL) { + _mmcam_dbg_warn("handle is NULL"); + return FALSE; + } + + _mmcam_dbg_log("Commit : encoded preview bitrate - %d", value->value.i_val); + + /* check preview format */ + mm_camcorder_get_attributes(handle, NULL, MMCAM_CAMERA_FORMAT, &preview_format, NULL); + if (preview_format != MM_PIXEL_FORMAT_ENCODED_H264) { + _mmcam_dbg_err("current preview format[%d] is not encoded format", preview_format); + return FALSE; + } + + /* check state */ + current_state = _mmcamcorder_get_state(handle); + if (current_state < MM_CAMCORDER_STATE_READY) { + _mmcam_dbg_log("will be applied when preview starts"); + return TRUE; + } + + return _mmcamcorder_set_encoded_preview_bitrate(handle, value->value.i_val); +} + + +bool _mmcamcorder_commit_encoded_preview_iframe_interval(MMHandleType handle, int attr_idx, const mmf_value_t *value) +{ + int current_state = MM_CAMCORDER_STATE_NONE; + int preview_format = MM_PIXEL_FORMAT_NV12; + + if ((void *)handle == NULL) { + _mmcam_dbg_warn("handle is NULL"); + return FALSE; + } + + _mmcam_dbg_log("Commit : encoded preview I-frame interval - %d", value->value.i_val); + + /* check preview format */ + mm_camcorder_get_attributes(handle, NULL, MMCAM_CAMERA_FORMAT, &preview_format, NULL); + if (preview_format != MM_PIXEL_FORMAT_ENCODED_H264) { + _mmcam_dbg_err("current preview format[%d] is not encoded format", preview_format); + return FALSE; + } + + /* check state */ + current_state = _mmcamcorder_get_state(handle); + if (current_state < MM_CAMCORDER_STATE_READY) { + _mmcam_dbg_log("will be applied when preview starts"); + return TRUE; + } + + return _mmcamcorder_set_encoded_preview_iframe_interval(handle, value->value.i_val); +} static bool __mmcamcorder_attrs_is_supported(MMHandleType handle, int idx) @@ -4014,17 +4482,17 @@ static bool __mmcamcorder_set_capture_resolution(MMHandleType handle, int width, } -static int -__mmcamcorder_check_valid_pair( MMHandleType handle, char **err_attr_name, const char *attribute_name, va_list var_args ) +static int __mmcamcorder_check_valid_pair(MMHandleType handle, char **err_attr_name, const char *attribute_name, va_list var_args) { #define INIT_VALUE -1 #define CHECK_COUNT 3 - mmf_camcorder_t *hcamcorder= MMF_CAMCORDER(handle); + mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle); MMHandleType attrs = 0; int ret = MM_ERROR_NONE; - int i = 0, j = 0; + int i = 0; + int j = 0; const char *name = NULL; const char *check_pair_name[CHECK_COUNT][3] = { {MMCAM_CAMERA_WIDTH, MMCAM_CAMERA_HEIGHT, "MMCAM_CAMERA_WIDTH and HEIGHT"}, @@ -4174,6 +4642,25 @@ __mmcamcorder_check_valid_pair( MMHandleType handle, char **err_attr_name, const return MM_ERROR_CAMCORDER_INVALID_ARGUMENT; } + if (!strcmp(check_pair_name[i][0], MMCAM_CAMERA_WIDTH)) { + int current_width = 0; + int current_height = 0; + + mm_camcorder_get_attributes(handle, NULL, + MMCAM_CAMERA_WIDTH, ¤t_width, + MMCAM_CAMERA_HEIGHT, ¤t_height, + NULL); + + if (current_width != check_pair_value[i][0] || + current_height != check_pair_value[i][1]) { + hcamcorder->resolution_changed = TRUE; + } else { + hcamcorder->resolution_changed = FALSE; + } + + _mmcam_dbg_log("resolution changed : %d", hcamcorder->resolution_changed); + } + if (err_name) { free(err_name); err_name = NULL; diff --git a/src/mm_camcorder_audiorec.c b/src/mm_camcorder_audiorec.c index c3d59a9..eed549b 100644 --- a/src/mm_camcorder_audiorec.c +++ b/src/mm_camcorder_audiorec.c @@ -39,17 +39,16 @@ #define _MMCAMCORDER_AUDIO_MINIMUM_SPACE (100*1024) #define _MMCAMCORDER_AUDIO_MARGIN_SPACE (1*1024) #define _MMCAMCORDER_RETRIAL_COUNT 10 -#define _MMCAMCORDER_FRAME_WAIT_TIME 20000 /* micro second */ +#define _MMCAMCORDER_FRAME_WAIT_TIME 200000 /* micro second */ #define _MMCAMCORDER_FREE_SPACE_CHECK_INTERVAL 10 /*--------------------------------------------------------------------------------------- | LOCAL FUNCTION PROTOTYPES: | ---------------------------------------------------------------------------------------*/ /* STATIC INTERNAL FUNCTION */ -static gboolean __mmcamcorder_audio_dataprobe_voicerecorder(GstPad *pad, GstBuffer *buffer, gpointer u_data); -static gboolean __mmcamcorder_audio_dataprobe_record(GstPad *pad, GstBuffer *buffer, gpointer u_data); +static GstPadProbeReturn __mmcamcorder_audio_dataprobe_voicerecorder(GstPad *pad, GstPadProbeInfo *info, gpointer u_data); +static GstPadProbeReturn __mmcamcorder_audio_dataprobe_record(GstPad *pad, GstPadProbeInfo *info, gpointer u_data); static int __mmcamcorder_create_audiop_with_encodebin(MMHandleType handle); -static void __mmcamcorder_audiorec_pad_added_cb(GstElement *element, GstPad *pad, MMHandleType handle); static gboolean __mmcamcorder_audio_add_metadata_info_m4a(MMHandleType handle); /*======================================================================================= @@ -198,19 +197,11 @@ static int __mmcamcorder_create_audiop_with_encodebin(MMHandleType handle) gst_object_unref(srcpad); srcpad = NULL; - if (info->bMuxing) { - MMCAMCORDER_SIGNAL_CONNECT(sc->encode_element[_MMCAMCORDER_ENCSINK_MUX].gst, - _MMCAMCORDER_HANDLER_AUDIOREC, - "pad-added", - __mmcamcorder_audiorec_pad_added_cb, - hcamcorder); - } else { - srcpad = gst_element_get_static_pad(sc->encode_element[_MMCAMCORDER_ENCSINK_AENC].gst, "src"); - MMCAMCORDER_ADD_BUFFER_PROBE(srcpad, _MMCAMCORDER_HANDLER_AUDIOREC, - __mmcamcorder_audio_dataprobe_record, hcamcorder); - gst_object_unref(srcpad); - srcpad = NULL; - } + srcpad = gst_element_get_static_pad(sc->encode_element[_MMCAMCORDER_ENCSINK_AENC].gst, "src"); + MMCAMCORDER_ADD_BUFFER_PROBE(srcpad, _MMCAMCORDER_HANDLER_AUDIOREC, + __mmcamcorder_audio_dataprobe_record, hcamcorder); + gst_object_unref(srcpad); + srcpad = NULL; bus = gst_pipeline_get_bus(GST_PIPELINE(sc->encode_element[_MMCAMCORDER_ENCODE_MAIN_PIPE].gst)); @@ -218,7 +209,7 @@ static int __mmcamcorder_create_audiop_with_encodebin(MMHandleType handle) hcamcorder->pipeline_cb_event_id = gst_bus_add_watch(bus, (GstBusFunc)_mmcamcorder_pipeline_cb_message, hcamcorder); /* set sync callback */ - gst_bus_set_sync_handler(bus, _mmcamcorder_audio_pipeline_bus_sync_callback, hcamcorder); + gst_bus_set_sync_handler(bus, _mmcamcorder_audio_pipeline_bus_sync_callback, hcamcorder, NULL); gst_object_unref(bus); bus = NULL; @@ -360,7 +351,6 @@ _mmcamcorder_audio_command(MMHandleType handle, int command) int err = 0; int size=0; guint64 free_space = 0; - guint64 free_space_exceptsystem=0; char *dir_name = NULL; char *err_attr_name = NULL; @@ -394,7 +384,7 @@ _mmcamcorder_audio_command(MMHandleType handle, int command) int file_system_type = 0; if(sc->pipeline_time) { - gst_pipeline_set_new_stream_time(GST_PIPELINE(pipeline), sc->pipeline_time); + gst_element_set_start_time(pipeline, sc->pipeline_time); } sc->pipeline_time = RESET_PAUSE_TIME; @@ -424,7 +414,7 @@ _mmcamcorder_audio_command(MMHandleType handle, int command) _mmcam_dbg_log("Record start : set file name using attribute - %s\n ",info->filename); - MMCAMCORDER_G_OBJECT_SET(sc->encode_element[_MMCAMCORDER_ENCSINK_SINK].gst, "location", info->filename); + MMCAMCORDER_G_OBJECT_SET_POINTER(sc->encode_element[_MMCAMCORDER_ENCSINK_SINK].gst, "location", info->filename); sc->ferror_send = FALSE; sc->ferror_count = 0; @@ -445,18 +435,12 @@ _mmcamcorder_audio_command(MMHandleType handle, int command) info->max_time = ((guint64)imax_time) * 1000; /* to millisecond */ } - /* TODO : check free space before recording start, need to more discussion */ + /* TODO : check free space before recording start */ dir_name = g_path_get_dirname(info->filename); if (dir_name) { - err = _mmcamcorder_get_freespace(dir_name, &free_space); - if(_mmcamcorder_check_file_path(dir_name)) { - err = _mmcamcorder_get_freespace_except_system(&free_space_exceptsystem); - hcamcorder->system_memory = free_space - free_space_exceptsystem; - free_space = free_space - hcamcorder->system_memory; - } + err = _mmcamcorder_get_freespace(dir_name, hcamcorder->root_directory, &free_space); - _mmcam_dbg_warn("current space - %s [%" G_GUINT64_FORMAT "], system [%" G_GUINT64_FORMAT "]", - dir_name, free_space, hcamcorder->system_memory); + _mmcam_dbg_warn("current space - %s [%" G_GUINT64_FORMAT "]", dir_name, free_space); if (_mmcamcorder_get_file_system_type(dir_name, &file_system_type) == 0) { /* MSDOS_SUPER_MAGIC : 0x4d44 */ @@ -589,7 +573,15 @@ _mmcamcorder_audio_command(MMHandleType handle, int command) } if (audioSrc) { - ret = gst_element_send_event(audioSrc, gst_event_new_eos()); + if (gst_element_send_event(audioSrc, gst_event_new_eos()) == FALSE) { + _mmcam_dbg_err("send EOS failed"); + info->b_commiting = FALSE; + ret = MM_ERROR_CAMCORDER_INTERNAL; + goto _ERR_CAMCORDER_AUDIO_COMMAND; + } + + _mmcam_dbg_log("send EOS done"); + /* for pause -> commit case */ if (_mmcamcorder_get_state((MMHandleType)hcamcorder) == MM_CAMCORDER_STATE_PAUSED) { ret = _mmcamcorder_gst_set_state(handle, pipeline, GST_STATE_PLAYING); @@ -598,6 +590,11 @@ _mmcamcorder_audio_command(MMHandleType handle, int command) goto _ERR_CAMCORDER_AUDIO_COMMAND; } } + } else { + _mmcam_dbg_err("No audio stream source"); + info->b_commiting = FALSE; + ret = MM_ERROR_CAMCORDER_INTERNAL; + goto _ERR_CAMCORDER_AUDIO_COMMAND; } /* wait until finishing EOS */ @@ -672,7 +669,7 @@ int _mmcamcorder_audio_handle_eos(MMHandleType handle) report->recording_filename = strdup(info->filename); msg.param.data= report; - _mmcamcroder_send_message(handle, &msg); + _mmcamcorder_send_message(handle, &msg); if (info->bMuxing) { MMCAMCORDER_G_OBJECT_SET(sc->encode_element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "block", FALSE); @@ -755,8 +752,7 @@ __mmcamcorder_get_decibel(unsigned char* raw, int size, MMCamcorderAudioFormat f } -static gboolean -__mmcamcorder_audio_dataprobe_voicerecorder(GstPad *pad, GstBuffer *buffer, gpointer u_data) +static GstPadProbeReturn __mmcamcorder_audio_dataprobe_voicerecorder(GstPad *pad, GstPadProbeInfo *info, gpointer u_data) { mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(u_data); double volume = 0.0; @@ -766,8 +762,12 @@ __mmcamcorder_audio_dataprobe_voicerecorder(GstPad *pad, GstBuffer *buffer, gpoi _MMCamcorderMsgItem msg; int err = MM_ERROR_UNKNOWN; char *err_name = NULL; + GstBuffer *buffer = GST_PAD_PROBE_INFO_BUFFER(info); + GstMapInfo mapinfo; - mmf_return_val_if_fail(hcamcorder, FALSE); + mmf_return_val_if_fail(hcamcorder, GST_PAD_PROBE_OK); + + memset(&mapinfo, 0x0, sizeof(GstMapInfo)); /* Set volume to audio input */ err = mm_camcorder_get_attributes((MMHandleType)hcamcorder, &err_name, @@ -775,32 +775,35 @@ __mmcamcorder_audio_dataprobe_voicerecorder(GstPad *pad, GstBuffer *buffer, gpoi MMCAM_AUDIO_FORMAT, &format, MMCAM_AUDIO_CHANNEL, &channel, NULL); - if (err < 0) - { + if (err < 0) { _mmcam_dbg_warn("Get attrs fail. (%s:%x)", err_name, err); - SAFE_FREE (err_name); + SAFE_FREE(err_name); return err; } - if(volume == 0) //mute - memset (GST_BUFFER_DATA(buffer), 0, GST_BUFFER_SIZE(buffer)); + gst_buffer_map(buffer, &mapinfo, GST_MAP_READWRITE); + + if(volume == 0){ + memset(mapinfo.data, 0, mapinfo.size); + } /* Get current volume level of real input stream */ - curdcb = __mmcamcorder_get_decibel(GST_BUFFER_DATA(buffer), GST_BUFFER_SIZE(buffer), format); + curdcb = __mmcamcorder_get_decibel(mapinfo.data, mapinfo.size, format); msg.id = MM_MESSAGE_CAMCORDER_CURRENT_VOLUME; msg.param.rec_volume_dB = curdcb; - _mmcamcroder_send_message((MMHandleType)hcamcorder, &msg); + _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg); /* CALL audio stream callback */ - if ((hcamcorder->astream_cb) && buffer && GST_BUFFER_DATA(buffer)) + if ((hcamcorder->astream_cb) && buffer && mapinfo.data && mapinfo.size > 0) { MMCamcorderAudioStreamDataType stream; if (_mmcamcorder_get_state((MMHandleType)hcamcorder) < MM_CAMCORDER_STATE_PREPARE) { _mmcam_dbg_warn("Not ready for stream callback"); - return TRUE; + gst_buffer_unmap(buffer, &mapinfo); + return GST_PAD_PROBE_OK; } /* @@ -808,11 +811,11 @@ __mmcamcorder_audio_dataprobe_voicerecorder(GstPad *pad, GstBuffer *buffer, gpoi GST_BUFFER_DATA(buffer), format, channel, GST_BUFFER_SIZE(buffer), curdcb); */ - stream.data = (void *)GST_BUFFER_DATA(buffer); + stream.data = (void *)mapinfo.data; stream.format = format; stream.channel = channel; - stream.length = GST_BUFFER_SIZE(buffer); - stream.timestamp = (unsigned int)(GST_BUFFER_TIMESTAMP(buffer)/1000000); //nano -> msecond + stream.length = mapinfo.size; + stream.timestamp = (unsigned int)(GST_BUFFER_PTS(buffer)/1000000); //nano -> msecond stream.volume_dB = curdcb; _MMCAMCORDER_LOCK_ASTREAM_CALLBACK( hcamcorder ); @@ -825,32 +828,12 @@ __mmcamcorder_audio_dataprobe_voicerecorder(GstPad *pad, GstBuffer *buffer, gpoi _MMCAMCORDER_UNLOCK_ASTREAM_CALLBACK( hcamcorder ); } - return TRUE; -} - - -static void -__mmcamcorder_audiorec_pad_added_cb(GstElement *element, GstPad *pad, MMHandleType handle) -{ - mmf_camcorder_t *hcamcorder= MMF_CAMCORDER(handle); - - _mmcam_dbg_log("ENTER(%s)", GST_PAD_NAME(pad)); - //FIXME : the name of audio sink pad of wavparse, oggmux doesn't have 'audio'. How could I handle the name? - if((strstr(GST_PAD_NAME(pad), "audio")) || (strstr(GST_PAD_NAME(pad), "sink"))) - { - MMCAMCORDER_ADD_BUFFER_PROBE(pad, _MMCAMCORDER_HANDLER_AUDIOREC, - __mmcamcorder_audio_dataprobe_record, hcamcorder); - } - else - { - _mmcam_dbg_warn("Unknow pad is added, check it : [%s]", GST_PAD_NAME(pad)); - } - - return; + gst_buffer_unmap(buffer, &mapinfo); + return GST_PAD_PROBE_OK; } -static gboolean __mmcamcorder_audio_dataprobe_record(GstPad *pad, GstBuffer *buffer, gpointer u_data) +static GstPadProbeReturn __mmcamcorder_audio_dataprobe_record(GstPad *pad, GstPadProbeInfo *info, gpointer u_data) { static int count = 0; guint64 rec_pipe_time = 0; @@ -862,59 +845,66 @@ static gboolean __mmcamcorder_audio_dataprobe_record(GstPad *pad, GstBuffer *buf _MMCamcorderSubContext *sc = NULL; mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(u_data); - _MMCamcorderAudioInfo *info = NULL; + _MMCamcorderAudioInfo *audioinfo = NULL; _MMCamcorderMsgItem msg; + GstBuffer *buffer = GST_PAD_PROBE_INFO_BUFFER(info); - mmf_return_val_if_fail(hcamcorder, FALSE); - mmf_return_val_if_fail(buffer, FALSE); + mmf_return_val_if_fail(hcamcorder, GST_PAD_PROBE_DROP); + mmf_return_val_if_fail(buffer, GST_PAD_PROBE_DROP); sc = MMF_CAMCORDER_SUBCONTEXT(hcamcorder); - mmf_return_val_if_fail(sc && sc->info_audio, FALSE); - info = sc->info_audio; + mmf_return_val_if_fail(sc && sc->info_audio, GST_PAD_PROBE_DROP); + audioinfo = sc->info_audio; if (sc->isMaxtimePausing || sc->isMaxsizePausing) { _mmcam_dbg_warn("isMaxtimePausing[%d],isMaxsizePausing[%d]", sc->isMaxtimePausing, sc->isMaxsizePausing); - return FALSE; + return GST_PAD_PROBE_DROP; } - buffer_size = (guint64)GST_BUFFER_SIZE(buffer); + buffer_size = gst_buffer_get_size(buffer); - if (info->filesize == 0) { - if (info->fileformat == MM_FILE_FORMAT_WAV) { - info->filesize += 44; /* wave header size */ - } else if (info->fileformat == MM_FILE_FORMAT_AMR) { - info->filesize += 6; /* amr header size */ + if (audioinfo->filesize == 0) { + if (audioinfo->fileformat == MM_FILE_FORMAT_WAV) { + audioinfo->filesize += 44; /* wave header size */ + } else if (audioinfo->fileformat == MM_FILE_FORMAT_AMR) { + audioinfo->filesize += 6; /* amr header size */ } - info->filesize += buffer_size; - return TRUE; + audioinfo->filesize += buffer_size; + return GST_PAD_PROBE_OK; } if (sc->ferror_send) { _mmcam_dbg_warn("file write error, drop frames"); - return FALSE; + return GST_PAD_PROBE_DROP; } /* get trailer size */ - if (info->fileformat == MM_FILE_FORMAT_3GP || - info->fileformat == MM_FILE_FORMAT_MP4 || - info->fileformat == MM_FILE_FORMAT_AAC) { + if (audioinfo->fileformat == MM_FILE_FORMAT_3GP || + audioinfo->fileformat == MM_FILE_FORMAT_MP4 || + audioinfo->fileformat == MM_FILE_FORMAT_AAC) { MMCAMCORDER_G_OBJECT_GET(sc->encode_element[_MMCAMCORDER_ENCSINK_MUX].gst, "expected-trailer-size", &trailer_size); /*_mmcam_dbg_log("trailer_size %d", trailer_size);*/ } else { trailer_size = 0; /* no trailer */ } - filename = info->filename; + filename = audioinfo->filename; /* to minimizing free space check overhead */ count = count % _MMCAMCORDER_FREE_SPACE_CHECK_INTERVAL; if (count++ == 0) { - gint free_space_ret = _mmcamcorder_get_freespace(filename, &free_space); + char *dir_name = g_path_get_dirname(filename); + gint free_space_ret = 0; - if(_mmcamcorder_check_file_path(filename) && hcamcorder->system_memory) { - free_space = free_space - hcamcorder->system_memory; + if (dir_name) { + free_space_ret = _mmcamcorder_get_freespace(dir_name, hcamcorder->root_directory, &free_space); + g_free(dir_name); + dir_name = NULL; + } else { + _mmcam_dbg_err("failed to get dir name from [%s]", filename); + free_space_ret = -1; } /*_mmcam_dbg_log("check free space for recording");*/ @@ -931,21 +921,21 @@ static gboolean __mmcamcorder_audio_dataprobe_record(GstPad *pad, GstBuffer *buf } else { msg.param.code = MM_ERROR_FILE_READ; } - _mmcamcroder_send_message((MMHandleType)hcamcorder, &msg); + _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg); } else { sc->ferror_count++; } - return FALSE; /* skip this buffer */ + return GST_PAD_PROBE_DROP; /* skip this buffer */ default: /* succeeded to get free space */ /* check free space for recording */ if (free_space < (guint64)(_MMCAMCORDER_AUDIO_MINIMUM_SPACE + buffer_size + trailer_size)) { _mmcam_dbg_warn("No more space for recording!!!"); _mmcam_dbg_warn("Free Space : [%" G_GUINT64_FORMAT "], file size : [%" G_GUINT64_FORMAT "]", - free_space, info->filesize); + free_space, audioinfo->filesize); - if (info->bMuxing) { + if (audioinfo->bMuxing) { MMCAMCORDER_G_OBJECT_SET(sc->encode_element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "block", TRUE); } else { MMCAMCORDER_G_OBJECT_SET(sc->encode_element[_MMCAMCORDER_ENCSINK_AQUE].gst, "empty-buffers", TRUE); @@ -953,27 +943,27 @@ static gboolean __mmcamcorder_audio_dataprobe_record(GstPad *pad, GstBuffer *buf sc->isMaxsizePausing = TRUE; msg.id = MM_MESSAGE_CAMCORDER_NO_FREE_SPACE; - _mmcamcroder_send_message((MMHandleType)hcamcorder, &msg); + _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg); - return FALSE; /* skip this buffer */ + return GST_PAD_PROBE_DROP; /* skip this buffer */ } break; } } - if (!GST_CLOCK_TIME_IS_VALID(GST_BUFFER_TIMESTAMP(buffer))) { + if (!GST_CLOCK_TIME_IS_VALID(GST_BUFFER_PTS(buffer))) { _mmcam_dbg_err("Buffer timestamp is invalid, check it"); - return FALSE; + return GST_PAD_PROBE_DROP; } - rec_pipe_time = GST_TIME_AS_MSECONDS(GST_BUFFER_TIMESTAMP(buffer)); + rec_pipe_time = GST_TIME_AS_MSECONDS(GST_BUFFER_PTS(buffer)); /* calculate remained time can be recorded */ - if (info->max_time > 0 && info->max_time < (remained_time + rec_pipe_time)) { - remained_time = info->max_time - rec_pipe_time; - } else if (info->max_size > 0) { - long double max_size = (long double)info->max_size; - long double current_size = (long double)(info->filesize + buffer_size + trailer_size); + if (audioinfo->max_time > 0 && audioinfo->max_time < (remained_time + rec_pipe_time)) { + remained_time = audioinfo->max_time - rec_pipe_time; + } else if (audioinfo->max_size > 0) { + long double max_size = (long double)audioinfo->max_size; + long double current_size = (long double)(audioinfo->filesize + buffer_size + trailer_size); remained_time = (unsigned long long)((long double)rec_pipe_time * (max_size/current_size)) - rec_pipe_time; } @@ -981,14 +971,14 @@ static gboolean __mmcamcorder_audio_dataprobe_record(GstPad *pad, GstBuffer *buf /*_mmcam_dbg_log("remained time : %u", remained_time);*/ /* check max size of recorded file */ - if (info->max_size > 0 && - info->max_size < info->filesize + buffer_size + trailer_size + _MMCAMCORDER_MMS_MARGIN_SPACE) { + if (audioinfo->max_size > 0 && + audioinfo->max_size < audioinfo->filesize + buffer_size + trailer_size + _MMCAMCORDER_MMS_MARGIN_SPACE) { _mmcam_dbg_warn("Max size!!! Recording is paused."); _mmcam_dbg_warn("Max [%" G_GUINT64_FORMAT "], file [%" G_GUINT64_FORMAT "], trailer : [%" G_GUINT64_FORMAT "]", \ - info->max_size, info->filesize, trailer_size); + audioinfo->max_size, audioinfo->filesize, trailer_size); /* just same as pause status. After blocking two queue, this function will not call again. */ - if (info->bMuxing) { + if (audioinfo->bMuxing) { MMCAMCORDER_G_OBJECT_SET(sc->encode_element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "block", TRUE); } else { MMCAMCORDER_G_OBJECT_SET(sc->encode_element[_MMCAMCORDER_ENCSINK_AQUE].gst, "empty-buffers", TRUE); @@ -996,26 +986,26 @@ static gboolean __mmcamcorder_audio_dataprobe_record(GstPad *pad, GstBuffer *buf msg.id = MM_MESSAGE_CAMCORDER_RECORDING_STATUS; msg.param.recording_status.elapsed = (unsigned long long)rec_pipe_time; - msg.param.recording_status.filesize = (unsigned long long)((info->filesize + trailer_size) >> 10); + msg.param.recording_status.filesize = (unsigned long long)((audioinfo->filesize + trailer_size) >> 10); msg.param.recording_status.remained_time = 0; - _mmcamcroder_send_message((MMHandleType)hcamcorder, &msg); + _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg); - _mmcam_dbg_warn("Last filesize sent by message : %d", info->filesize + trailer_size); + _mmcam_dbg_warn("Last filesize sent by message : %llu", audioinfo->filesize + trailer_size); sc->isMaxsizePausing = TRUE; msg.id = MM_MESSAGE_CAMCORDER_MAX_SIZE; - _mmcamcroder_send_message((MMHandleType)hcamcorder, &msg); + _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg); /* skip this buffer */ - return FALSE; + return GST_PAD_PROBE_DROP; } /* check recording time limit and send recording status message */ - if (info->max_time > 0 && rec_pipe_time > info->max_time) { + if (audioinfo->max_time > 0 && rec_pipe_time > audioinfo->max_time) { _mmcam_dbg_warn("Current time : [%" G_GUINT64_FORMAT "], Maximum time : [%" G_GUINT64_FORMAT "]", \ - rec_pipe_time, info->max_time); + rec_pipe_time, audioinfo->max_time); - if (info->bMuxing) { + if (audioinfo->bMuxing) { MMCAMCORDER_G_OBJECT_SET(sc->encode_element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "block", TRUE); } else { MMCAMCORDER_G_OBJECT_SET(sc->encode_element[_MMCAMCORDER_ENCSINK_AQUE].gst, "empty-buffers", TRUE); @@ -1023,26 +1013,26 @@ static gboolean __mmcamcorder_audio_dataprobe_record(GstPad *pad, GstBuffer *buf sc->isMaxtimePausing = TRUE; msg.id = MM_MESSAGE_CAMCORDER_TIME_LIMIT; - _mmcamcroder_send_message((MMHandleType)hcamcorder, &msg); + _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg); /* skip this buffer */ - return FALSE; + return GST_PAD_PROBE_DROP; } /* send message for recording time and recorded file size */ - if (info->b_commiting == FALSE) { - info->filesize += buffer_size; + if (audioinfo->b_commiting == FALSE) { + audioinfo->filesize += buffer_size; msg.id = MM_MESSAGE_CAMCORDER_RECORDING_STATUS; msg.param.recording_status.elapsed = (unsigned long long)rec_pipe_time; - msg.param.recording_status.filesize = (unsigned long long)((info->filesize + trailer_size) >> 10); + msg.param.recording_status.filesize = (unsigned long long)((audioinfo->filesize + trailer_size) >> 10); msg.param.recording_status.remained_time = remained_time; - _mmcamcroder_send_message((MMHandleType)hcamcorder, &msg); + _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg); - return TRUE; + return GST_PAD_PROBE_OK; } else { /* skip this buffer if commit process has been started */ - return FALSE; + return GST_PAD_PROBE_DROP; } } @@ -1095,7 +1085,7 @@ static gboolean __mmcamcorder_audio_add_metadata_info_m4a(MMHandleType handle) geo_info.altitude = altitude *10000; } - f = fopen(info->filename, "rb+"); + f = fopen64(info->filename, "rb+"); if (f == NULL) { strerror_r(errno, err_msg, 128); _mmcam_dbg_err("file open failed [%s]", err_msg); @@ -1119,7 +1109,7 @@ static gboolean __mmcamcorder_audio_add_metadata_info_m4a(MMHandleType handle) goto fail; } - udta_pos = ftell(f); + udta_pos = ftello(f); if (udta_pos < 0) { goto ftell_fail; } @@ -1145,7 +1135,7 @@ static gboolean __mmcamcorder_audio_add_metadata_info_m4a(MMHandleType handle) } } - current_pos = ftell(f); + current_pos = ftello(f); if (current_pos < 0) { goto ftell_fail; } @@ -1166,7 +1156,7 @@ static gboolean __mmcamcorder_audio_add_metadata_info_m4a(MMHandleType handle) /* find moov container. update moov container size. */ - if((current_pos = ftell(f))<0) + if((current_pos = ftello(f))<0) goto ftell_fail; if (_mmcamcorder_find_fourcc(f, MMCAM_FOURCC('m','o','o','v'), TRUE)) { @@ -1176,7 +1166,7 @@ static gboolean __mmcamcorder_audio_add_metadata_info_m4a(MMHandleType handle) goto fail; } - moov_pos = ftell(f); + moov_pos = ftello(f); if (moov_pos < 0) { goto ftell_fail; } diff --git a/src/mm_camcorder_configure.c b/src/mm_camcorder_configure.c index 9604a3b..5ba80a6 100644 --- a/src/mm_camcorder_configure.c +++ b/src/mm_camcorder_configure.c @@ -165,7 +165,7 @@ static type_element _videoscale_element_default = { */ static type_element _videoconvert_element_default = { "VideoconvertElement", - "ffmpegcolorspace", + "videoconvert", NULL, 0, NULL, @@ -674,6 +674,18 @@ static type_element _matroska_element_default = { }; /* + * M2TS element default value + */ +static type_element _m2ts_element_default = { + "M2TS", + "mpegtsmux", + NULL, + 0, + NULL, + 0, +}; + +/* * [General] matching table */ static conf_info_table conf_main_general_table[] = { @@ -702,6 +714,7 @@ static conf_info_table conf_main_video_input_table[] = { * [AudioInput] matching table */ static conf_info_table conf_main_audio_input_table[] = { + { "AudioDevice", CONFIGURE_VALUE_INT_ARRAY, {(int)NULL} }, { "AudiosrcElement", CONFIGURE_VALUE_ELEMENT, {(int)&_audiosrc_element_default} }, { "AudiomodemsrcElement", CONFIGURE_VALUE_ELEMENT, {(int)&_audiomodemsrc_element_default} }, }; @@ -820,6 +833,7 @@ static conf_info_table conf_main_mux_table[] = { { "MID", CONFIGURE_VALUE_ELEMENT, {(int)&_mid_element_default} }, { "MMF", CONFIGURE_VALUE_ELEMENT, {(int)&_mmfmux_element_default} }, { "MATROSKA", CONFIGURE_VALUE_ELEMENT, {(int)&_matroska_element_default} }, + { "M2TS", CONFIGURE_VALUE_ELEMENT, {(int)&_m2ts_element_default} }, }; @@ -836,7 +850,16 @@ static conf_info_table conf_ctrl_camera_table[] = { { "PreviewResolution", CONFIGURE_VALUE_INT_PAIR_ARRAY, {(int)NULL} }, { "CaptureResolution", CONFIGURE_VALUE_INT_PAIR_ARRAY, {(int)NULL} }, { "VideoResolution", CONFIGURE_VALUE_INT_PAIR_ARRAY, {(int)NULL} }, - { "FPS", CONFIGURE_VALUE_INT_ARRAY, {(int)NULL} }, + { "FPS0", CONFIGURE_VALUE_INT_ARRAY, {(int)NULL} }, + { "FPS1", CONFIGURE_VALUE_INT_ARRAY, {(int)NULL} }, + { "FPS2", CONFIGURE_VALUE_INT_ARRAY, {(int)NULL} }, + { "FPS3", CONFIGURE_VALUE_INT_ARRAY, {(int)NULL} }, + { "FPS4", CONFIGURE_VALUE_INT_ARRAY, {(int)NULL} }, + { "FPS5", CONFIGURE_VALUE_INT_ARRAY, {(int)NULL} }, + { "FPS6", CONFIGURE_VALUE_INT_ARRAY, {(int)NULL} }, + { "FPS7", CONFIGURE_VALUE_INT_ARRAY, {(int)NULL} }, + { "FPS8", CONFIGURE_VALUE_INT_ARRAY, {(int)NULL} }, + { "FPS9", CONFIGURE_VALUE_INT_ARRAY, {(int)NULL} }, { "PictureFormat", CONFIGURE_VALUE_INT_ARRAY, {(int)NULL} }, { "Overlay", CONFIGURE_VALUE_INT_RANGE, {(int)NULL} }, { "RecommendDisplayRotation", CONFIGURE_VALUE_INT, {3} }, @@ -1072,12 +1095,13 @@ _mmcamcorder_conf_parse_info( int type, FILE* fd, camera_conf** configure_info ) camera_conf* new_conf = (camera_conf *)g_malloc0(sizeof(camera_conf)); if (new_conf == NULL) { _mmcam_dbg_err("new_conf alloc failed : %d", sizeof(camera_conf)); + *configure_info = NULL; return MM_ERROR_CAMCORDER_LOW_MEMORY; } - buffer_string = (char *)g_malloc0(sizeof(char) * BUFFER_LENGTH_STRING); + buffer_string = (char*)g_malloc0(sizeof(char) * BUFFER_LENGTH_STRING); if (buffer_string == NULL) { - _mmcam_dbg_err("buffer_string alloc failed : %d", sizeof(char)*BUFFER_LENGTH_STRING); + _mmcam_dbg_err("buffer_string alloc failed : %d", sizeof(char) * BUFFER_LENGTH_STRING); *configure_info = NULL; g_free(new_conf); return MM_ERROR_CAMCORDER_LOW_MEMORY; @@ -1095,7 +1119,7 @@ _mmcamcorder_conf_parse_info( int type, FILE* fd, camera_conf** configure_info ) g_free(new_conf); return MM_ERROR_CAMCORDER_INVALID_ARGUMENT; } - + read_main = 0; count_main_category = 0; @@ -1138,12 +1162,12 @@ _mmcamcorder_conf_parse_info( int type, FILE* fd, camera_conf** configure_info ) } /* Main Category */ else if( *buffer_token[0] == '[' ) - { + { category_name = get_new_string( buffer_token[0] ); count_main_category++; count_details = 0; - + while( !feof( fd ) ) { length_read = getline( &buffer_string, &BUFFER_LENGTH_STRING, fd ); @@ -1185,7 +1209,7 @@ _mmcamcorder_conf_parse_info( int type, FILE* fd, camera_conf** configure_info ) /* Details */ if( type == CONFIGURE_TYPE_MAIN ) - { + { if( !strcmp( "[General]", category_name ) ) { category = CONFIGURE_CATEGORY_MAIN_GENERAL; @@ -1257,7 +1281,7 @@ _mmcamcorder_conf_parse_info( int type, FILE* fd, camera_conf** configure_info ) if( category != -1 ) { - _mmcamcorder_conf_add_info( type, &(new_conf->info[category]), + _mmcamcorder_conf_add_info( type, &(new_conf->info[category]), buffer_details, category, count_details ); } else @@ -1289,8 +1313,7 @@ _mmcamcorder_conf_parse_info( int type, FILE* fd, camera_conf** configure_info ) } -void -_mmcamcorder_conf_release_info( camera_conf** configure_info ) +void _mmcamcorder_conf_release_info(camera_conf **configure_info) { int i = 0; int j = 0; @@ -1412,6 +1435,7 @@ _mmcamcorder_conf_release_info( camera_conf** configure_info ) _mmcam_dbg_log("Done."); } + int _mmcamcorder_conf_get_value_type( int type, int category, const char* name, int* value_type ) { @@ -1425,7 +1449,7 @@ _mmcamcorder_conf_get_value_type( int type, int category, const char* name, int* if( !_mmcamcorder_conf_get_category_size( type, category, &count_value ) ) { _mmcam_dbg_warn( "No matched category... check it... categoty[%d]", category ); - return FALSE; + return FALSE; } /*_mmcam_dbg_log( "Number of value : [%d]", count_value );*/ @@ -1463,7 +1487,7 @@ int _mmcamcorder_conf_add_info( int type, conf_detail** info, char** buffer_details, int category, int count_details ) { const int BUFFER_NUM_TOKEN = 256; - + int i = 0; int j = 0; int count_token; @@ -1582,8 +1606,8 @@ _mmcamcorder_conf_add_info( int type, conf_detail** info, char** buffer_details, (*info)->detail_info[i] = (void*)new_int_range; /* _mmcam_dbg_log("INT RANGE - name[%s],min[%d],max[%d],default[%d]", - new_int_range->name, - new_int_range->min, + new_int_range->name, + new_int_range->min, new_int_range->max, new_int_range->default_value); */ @@ -1621,7 +1645,7 @@ _mmcamcorder_conf_add_info( int type, conf_detail** info, char** buffer_details, new_int_array->default_value = atoi( buffer_token[count_token-1] ); /*_mmcam_dbg_log(" default value[%d]", new_int_array->default_value);*/ - + (*info)->detail_info[i] = (void*)new_int_array; break; } @@ -1686,7 +1710,7 @@ _mmcamcorder_conf_add_info( int type, conf_detail** info, char** buffer_details, case CONFIGURE_VALUE_STRING: { type_string2* new_string; - + new_string = (type_string2*)g_malloc0( sizeof(type_string2) ); if (new_string == NULL) { _mmcam_dbg_err("allocation failed"); @@ -1695,7 +1719,7 @@ _mmcamcorder_conf_add_info( int type, conf_detail** info, char** buffer_details, new_string->name = get_new_string( buffer_token[0] ); new_string->value = get_new_string( buffer_token[1] ); (*info)->detail_info[i] = (void*)new_string; - + /*_mmcam_dbg_log("STRING - name[%s],value[%s]", new_string->name, new_string->value);*/ break; } @@ -1703,7 +1727,7 @@ _mmcamcorder_conf_add_info( int type, conf_detail** info, char** buffer_details, { int count_value = count_token - 2; type_string_array* new_string_array; - + new_string_array = (type_string_array*)g_malloc0( sizeof(type_string_array) ); if ( new_string_array == NULL ) { break; @@ -1735,7 +1759,7 @@ _mmcamcorder_conf_add_info( int type, conf_detail** info, char** buffer_details, case CONFIGURE_VALUE_ELEMENT: { type_element2* new_element; - + new_element = (type_element2*)g_malloc0( sizeof(type_element2) ); if ( new_element == NULL ) { _mmcam_dbg_err("allocation failed"); @@ -1827,16 +1851,16 @@ _mmcamcorder_conf_get_value_int( camera_conf* configure_info, int category, cons if( configure_info->info[category] ) { - count = configure_info->info[category]->count; - info = configure_info->info[category]; - + count = configure_info->info[category]->count; + info = configure_info->info[category]; + for( i = 0 ; i < count ; i++ ) { if( info->detail_info[i] == NULL ) { continue; } - + if( !strcmp( ((type_int*)(info->detail_info[i]))->name , name ) ) { *value = ((type_int*)(info->detail_info[i]))->value; @@ -1870,21 +1894,21 @@ _mmcamcorder_conf_get_value_int_range( camera_conf* configure_info, int category if( configure_info->info[category] ) { - count = configure_info->info[category]->count; - info = configure_info->info[category]; - + count = configure_info->info[category]->count; + info = configure_info->info[category]; + for( i = 0 ; i < count ; i++ ) { if( info->detail_info[i] == NULL ) { continue; } - + if( !strcmp( ((type_int_range*)(info->detail_info[i]))->name , name ) ) { *value = (type_int_range*)(info->detail_info[i]); /* - _mmcam_dbg_log( "Get[%s] int range - min[%d],max[%d],default[%d]", + _mmcam_dbg_log( "Get[%s] int range - min[%d],max[%d],default[%d]", name, (*value)->min, (*value)->max, (*value)->default_value ); */ return TRUE; @@ -1921,12 +1945,12 @@ _mmcamcorder_conf_get_value_int_array( camera_conf* configure_info, int category { continue; } - + if( !strcmp( ((type_int_array*)(info->detail_info[i]))->name , name ) ) { *value = (type_int_array*)(info->detail_info[i]); /* - _mmcam_dbg_log( "Get[%s] int array - [%x],count[%d],default[%d]", + _mmcam_dbg_log( "Get[%s] int array - [%x],count[%d],default[%d]", name, (*value)->value, (*value)->count, (*value)->default_value ); */ return TRUE; @@ -1954,22 +1978,22 @@ _mmcamcorder_conf_get_value_int_pair_array( camera_conf* configure_info, int cat if( configure_info->info[category] ) { - count = configure_info->info[category]->count; - info = configure_info->info[category]; - + count = configure_info->info[category]->count; + info = configure_info->info[category]; + for( i = 0 ; i < count ; i++ ) { if( info->detail_info[i] == NULL ) { continue; } - + if( !strcmp( ((type_int_pair_array*)(info->detail_info[i]))->name , name ) ) { *value = (type_int_pair_array*)(info->detail_info[i]); /* - _mmcam_dbg_log( "Get[%s] int pair array - [%x][%x],count[%d],default[%d][%d]", - name, (*value)->value[0], (*value)->value[1], (*value)->count, + _mmcam_dbg_log( "Get[%s] int pair array - [%x][%x],count[%d],default[%d][%d]", + name, (*value)->value[0], (*value)->value[1], (*value)->count, (*value)->default_value[0], (*value)->default_value[1] ); */ return TRUE; @@ -1989,24 +2013,24 @@ _mmcamcorder_conf_get_value_string( camera_conf* configure_info, int category, c { int i, count; conf_detail* info; - + //_mmcam_dbg_log( "Entered... category[%d],name[%s]", category, name ); mmf_return_val_if_fail( configure_info, FALSE ); mmf_return_val_if_fail( name, FALSE ); - + if( configure_info->info[category] ) { - count = configure_info->info[category]->count; - info = configure_info->info[category]; - + count = configure_info->info[category]->count; + info = configure_info->info[category]; + for( i = 0 ; i < count ; i++ ) { if( info->detail_info[i] == NULL ) { continue; } - + if( !strcmp( ((type_string*)(info->detail_info[i]))->name , name ) ) { *value = ((type_string*)(info->detail_info[i]))->value; @@ -2040,8 +2064,8 @@ _mmcamcorder_conf_get_value_string_array( camera_conf* configure_info, int categ if( configure_info->info[category] ) { - count = configure_info->info[category]->count; - info = configure_info->info[category]; + count = configure_info->info[category]->count; + info = configure_info->info[category]; for( i = 0 ; i < count ; i++ ) { @@ -2049,12 +2073,12 @@ _mmcamcorder_conf_get_value_string_array( camera_conf* configure_info, int categ { continue; } - + if( !strcmp( ((type_string_array*)(info->detail_info[i]))->name , name ) ) { *value = (type_string_array*)(info->detail_info[i]); /* - _mmcam_dbg_log( "Get[%s] string array - [%x],count[%d],default[%s]", + _mmcam_dbg_log( "Get[%s] string array - [%x],count[%d],default[%s]", name, (*value)->value, (*value)->count, (*value)->default_value ); */ return TRUE; @@ -2074,7 +2098,7 @@ _mmcamcorder_conf_get_element( camera_conf* configure_info, int category, const { int i, count; conf_detail* info; - + //_mmcam_dbg_log( "Entered... category[%d],name[%s]", category, name ); mmf_return_val_if_fail( configure_info, FALSE ); @@ -2082,16 +2106,16 @@ _mmcamcorder_conf_get_element( camera_conf* configure_info, int category, const if( configure_info->info[category] ) { - count = configure_info->info[category]->count; - info = configure_info->info[category]; - + count = configure_info->info[category]->count; + info = configure_info->info[category]; + for( i = 0 ; i < count ; i++ ) { if( info->detail_info[i] == NULL ) { continue; } - + if( !strcmp( ((type_element*)(info->detail_info[i]))->name , name ) ) { *element = (type_element*)(info->detail_info[i]); @@ -2130,9 +2154,9 @@ int _mmcamcorder_conf_get_value_element_int( type_element* element, const char* name, int* value ) { int i; - + //_mmcam_dbg_log( "Entered..." ); - + mmf_return_val_if_fail( element, FALSE ); mmf_return_val_if_fail( name, FALSE ); @@ -2146,7 +2170,7 @@ _mmcamcorder_conf_get_value_element_int( type_element* element, const char* name } } - _mmcam_dbg_warn( "Faild to get int in element... ElementName[%p],Name[%s],Count[%d]", + _mmcam_dbg_warn( "Faild to get int in element... ElementName[%p],Name[%s],Count[%d]", element->name, name, element->count_int ); return FALSE; @@ -2156,9 +2180,9 @@ int _mmcamcorder_conf_get_value_element_string( type_element* element, const char* name, const char** value ) { int i; - + //_mmcam_dbg_log( "Entered..." ); - + mmf_return_val_if_fail( element, FALSE ); mmf_return_val_if_fail( name, FALSE ); @@ -2172,7 +2196,7 @@ _mmcamcorder_conf_get_value_element_string( type_element* element, const char* n } } - _mmcam_dbg_warn( "Faild to get int in element... ElementName[%p],Name[%s],Count[%d]", + _mmcam_dbg_warn( "Faild to get int in element... ElementName[%p],Name[%s],Count[%d]", element->name, name, element->count_string ); return FALSE; @@ -2227,7 +2251,7 @@ _mmcamcorder_conf_set_value_element_property( GstElement* gst, type_element* ele for( i = 0 ; i < element->count_string ; i++ ) { - MMCAMCORDER_G_OBJECT_SET( gst, element->value_string[i]->name, element->value_string[i]->value ); + MMCAMCORDER_G_OBJECT_SET_POINTER( gst, element->value_string[i]->name, element->value_string[i]->value ); _mmcam_dbg_log( "Element[%s] Set[%s] -> string[%s]", element->element_name, @@ -2248,13 +2272,13 @@ _mmcamcorder_conf_get_default_value_int( int type, int category, const char* nam int count_value = 0; //_mmcam_dbg_log( "Entered..." ); - + mmf_return_val_if_fail( name, FALSE ); if( !_mmcamcorder_conf_get_category_size( type, category, &count_value ) ) { _mmcam_dbg_warn( "No matched category... check it... categoty[%d]", category ); - return FALSE; + return FALSE; } if( type == CONFIGURE_TYPE_MAIN ) @@ -2277,7 +2301,7 @@ _mmcamcorder_conf_get_default_value_int( int type, int category, const char* nam *value = conf_ctrl_info_table[category][i].value_int; return TRUE; } - } + } } _mmcam_dbg_warn( "Failed to get default int... check it... Type[%d],Category[%d],Name[%s]", type, category, name ); @@ -2292,13 +2316,13 @@ _mmcamcorder_conf_get_default_value_string( int type, int category, const char* int count_value = 0; //_mmcam_dbg_log( "Entered..." ); - + mmf_return_val_if_fail( name, FALSE ); if( !_mmcamcorder_conf_get_category_size( type, category, &count_value ) ) { _mmcam_dbg_warn( "No matched category... check it... categoty[%d]", category ); - return FALSE; + return FALSE; } if( type == CONFIGURE_TYPE_MAIN ) @@ -2328,7 +2352,7 @@ _mmcamcorder_conf_get_default_value_string( int type, int category, const char* _mmcam_dbg_warn( "Failed to get default string... check it... Type[%d],Category[%d],Name[%s]", type, category, name ); - return FALSE; + return FALSE; } int @@ -2338,13 +2362,13 @@ _mmcamcorder_conf_get_default_element( int type, int category, const char* name, int count_value = 0; //_mmcam_dbg_log( "Entered..." ); - + mmf_return_val_if_fail( name, FALSE ); if( !_mmcamcorder_conf_get_category_size( type, category, &count_value ) ) { _mmcam_dbg_warn( "No matched category... check it... categoty[%d]", category ); - return FALSE; + return FALSE; } if( type == CONFIGURE_TYPE_MAIN ) @@ -2396,7 +2420,7 @@ _mmcamcorder_conf_get_category_size( int type, int category, int* size ) *size = (int)conf_ctrl_category_size[category]; } - return TRUE; + return TRUE; } void @@ -2478,7 +2502,7 @@ _mmcamcorder_conf_print_info( camera_conf** configure_info ) for( k = 0 ; k < temp_element->count_string ; k++ ) { g_print( " - STRING[%d] Name[%s],Value[%s]\n", k, temp_element->value_string[k]->name, temp_element->value_string[k]->value ); - } + } break; default: g_print( "[ConfigureInfo] : Not matched value type... So can not print data... check it... Name[%s],type[%d]\n", ((type_int*)((*configure_info)->info[i]->detail_info[j]))->name, type ); @@ -2489,7 +2513,7 @@ _mmcamcorder_conf_print_info( camera_conf** configure_info ) { g_print( "[ConfigureInfo] : Failed to get value type." ); } - } + } } } @@ -2505,12 +2529,12 @@ __mmcamcorder_get_audio_codec_element(MMHandleType handle) int codec_type = MM_AUDIO_CODEC_INVALID; mmf_camcorder_t *hcamcorder= MMF_CAMCORDER(handle); _MMCamcorderSubContext *sc = NULL; - + mmf_return_val_if_fail(hcamcorder, NULL); sc = MMF_CAMCORDER_SUBCONTEXT(handle); mmf_return_val_if_fail(sc, NULL); - + _mmcam_dbg_log(""); /* Check element availability */ @@ -2520,7 +2544,7 @@ __mmcamcorder_get_audio_codec_element(MMHandleType handle) { case MM_AUDIO_CODEC_AMR: codec_type_str = "AMR"; - break; + break; case MM_AUDIO_CODEC_G723_1: codec_type_str = "G723_1"; break; @@ -2553,9 +2577,9 @@ __mmcamcorder_get_audio_codec_element(MMHandleType handle) return NULL; } - _mmcamcorder_conf_get_element( hcamcorder->conf_main, + _mmcamcorder_conf_get_element( hcamcorder->conf_main, CONFIGURE_CATEGORY_MAIN_AUDIO_ENCODER, - codec_type_str, + codec_type_str, &telement ); return telement; @@ -2570,7 +2594,7 @@ __mmcamcorder_get_video_codec_element(MMHandleType handle) int codec_type = MM_VIDEO_CODEC_INVALID; mmf_camcorder_t *hcamcorder= MMF_CAMCORDER(handle); _MMCamcorderSubContext *sc = NULL; - + mmf_return_val_if_fail(hcamcorder, NULL); sc = MMF_CAMCORDER_SUBCONTEXT(handle); @@ -2598,7 +2622,7 @@ __mmcamcorder_get_video_codec_element(MMHandleType handle) case MM_VIDEO_CODEC_MPEG1: codec_type_str = "MPEG1"; break; - case MM_VIDEO_CODEC_THEORA: // OGG + case MM_VIDEO_CODEC_THEORA: codec_type_str = "THEORA"; break; default: @@ -2606,9 +2630,9 @@ __mmcamcorder_get_video_codec_element(MMHandleType handle) return NULL; } - _mmcamcorder_conf_get_element( hcamcorder->conf_main, + _mmcamcorder_conf_get_element( hcamcorder->conf_main, CONFIGURE_CATEGORY_MAIN_VIDEO_ENCODER, - codec_type_str, + codec_type_str, &telement ); return telement; @@ -2623,12 +2647,12 @@ __mmcamcorder_get_image_codec_element(MMHandleType handle) int codec_type = MM_IMAGE_CODEC_INVALID; mmf_camcorder_t *hcamcorder= MMF_CAMCORDER(handle); _MMCamcorderSubContext *sc = NULL; - + mmf_return_val_if_fail(hcamcorder, NULL); sc = MMF_CAMCORDER_SUBCONTEXT(handle); mmf_return_val_if_fail(sc, NULL); - + _mmcam_dbg_log(""); /* Check element availability */ @@ -2683,9 +2707,9 @@ __mmcamcorder_get_image_codec_element(MMHandleType handle) return NULL; } - _mmcamcorder_conf_get_element( hcamcorder->conf_main, + _mmcamcorder_conf_get_element( hcamcorder->conf_main, CONFIGURE_CATEGORY_MAIN_IMAGE_ENCODER, - codec_type_str, + codec_type_str, &telement ); return telement; @@ -2700,12 +2724,12 @@ __mmcamcorder_get_file_format_element(MMHandleType handle) int file_type = MM_FILE_FORMAT_INVALID; mmf_camcorder_t *hcamcorder= MMF_CAMCORDER(handle); _MMCamcorderSubContext *sc = NULL; - + mmf_return_val_if_fail(hcamcorder, NULL); sc = MMF_CAMCORDER_SUBCONTEXT(handle); mmf_return_val_if_fail(sc, NULL); - + _mmcam_dbg_log(""); /* Check element availability */ @@ -2752,14 +2776,17 @@ __mmcamcorder_get_file_format_element(MMHandleType handle) case MM_FILE_FORMAT_MATROSKA: mux_type_str = "MATROSKA"; break; + case MM_FILE_FORMAT_M2TS: + mux_type_str = "M2TS"; + break; default: _mmcam_dbg_err( "Not supported file format[%d]", file_type ); return NULL; } - _mmcamcorder_conf_get_element( hcamcorder->conf_main, + _mmcamcorder_conf_get_element( hcamcorder->conf_main, CONFIGURE_CATEGORY_MAIN_MUX, - mux_type_str, + mux_type_str, &telement ); return telement; @@ -2772,7 +2799,7 @@ _mmcamcorder_get_type_element(MMHandleType handle, int type) type_element *telement = NULL; _mmcam_dbg_log("type:%d", type); - + switch(type) { case MM_CAM_AUDIO_ENCODER: @@ -2939,6 +2966,9 @@ int _mmcamcorder_get_mux_format(MMHandleType handle, const char *name) mux_index = MM_FILE_FORMAT_MMF; } else if (!strcmp(name, "MATROSKA")) { mux_index = MM_FILE_FORMAT_MATROSKA; + } else if (!strcmp(name, "M2TS")) { + mux_index = MM_FILE_FORMAT_M2TS; + } /*_mmcam_dbg_log("mux index %d", mux_index);*/ diff --git a/src/mm_camcorder_exifinfo.c b/src/mm_camcorder_exifinfo.c index f271199..a2f7e60 100644 --- a/src/mm_camcorder_exifinfo.c +++ b/src/mm_camcorder_exifinfo.c @@ -110,28 +110,28 @@ _exif_get_jpeg_marker_offset (void *jpeg, int jpeg_size, unsigned short marker) _mmcam_dbg_log("marker: 0x%02X 0x%02X", m[0], m[1]); - if (*src == 0xff && *(src + 1) == 0xd8) + if (*src == 0xff && *(src + 1) == 0xd8) { p = src + 2; /* SOI(start of image) */ - } - else + } + else { _mmcam_dbg_log("invalid JPEG file."); return 0UL; } - for (i = 0; i < src_sz - (1 + 2); i++, p++) + for (i = 0; i < src_sz - (1 + 2); i++, p++) { - if (*p == 0xff) + if (*p == 0xff) { /*marker is 0xFFxx*/ - if (*(p + 1) == m[1]) + if (*(p + 1) == m[1]) { ret = p - src; _mmcam_dbg_log("marker offset: %lu %p %p.",ret, (p+1), src); return ret; } - } + } } _mmcam_dbg_log("Marker not found."); return 0UL; @@ -162,7 +162,7 @@ mm_exif_get_exif_from_info (mm_exif_info_t *info) unsigned char size[2]; unsigned int i; - + /*get ExifData from info*/ loader = exif_loader_new (); @@ -194,9 +194,9 @@ mm_exif_set_exif_to_info (mm_exif_info_t *info, ExifData *exif) if(info->data) { - free (info->data); - info->data = NULL; - info->size = 0; + free (info->data); + info->data = NULL; + info->size = 0; } exif_data_save_data (exif, &eb, &ebs); @@ -339,13 +339,13 @@ mm_exif_destory_exif_info (mm_exif_info_t *info) #if MM_EXIFINFO_USE_BINARY_EXIFDATA if (info) { - if (info->data) + if (info->data) free (info->data); free (info); } #else if (info) { - if (info->data) + if (info->data) exif_mem_free (info->data); free (info); } @@ -413,7 +413,7 @@ mm_exif_add_thumbnail_info (mm_exif_info_t *info, void *thumbnail, int width, in ed->data = NULL; ed->size = 0; - exif_data_unref (ed); + exif_data_unref (ed); exit : if(p_compressed != NULL) @@ -492,7 +492,7 @@ mm_exif_write_exif_jpeg_to_memory (void **mem, unsigned int *length, mm_exif_inf if(jpeg_len>JPEG_MAX_SIZE) { _mmcam_dbg_err( "jpeg_len is worng jpeg_len=%d",jpeg_len); - return MM_ERROR_CAMCORDER_DEVICE_WRONG_JPEG; + return MM_ERROR_CAMCORDER_DEVICE_WRONG_JPEG; } eb = info->data; @@ -522,7 +522,7 @@ mm_exif_write_exif_jpeg_to_memory (void **mem, unsigned int *length, mm_exif_inf m = malloc (m_len); if (!m) { _mmcam_dbg_err( "malloc() failed."); - return MM_ERROR_CAMCORDER_LOW_MEMORY; + return MM_ERROR_CAMCORDER_LOW_MEMORY; } /*set SOI, APP1*/ diff --git a/src/mm_camcorder_gstcommon.c b/src/mm_camcorder_gstcommon.c index 3b9864a..691459b 100644 --- a/src/mm_camcorder_gstcommon.c +++ b/src/mm_camcorder_gstcommon.c @@ -22,10 +22,12 @@ /*======================================================================================= | INCLUDE FILES | =======================================================================================*/ -#include -#include +#include +#include +#include #include #include +#include #include "mm_camcorder_internal.h" #include "mm_camcorder_gstcommon.h" @@ -35,84 +37,84 @@ -----------------------------------------------------------------------*/ /* Table for compatibility between audio codec and file format */ gboolean audiocodec_fileformat_compatibility_table[MM_AUDIO_CODEC_NUM][MM_FILE_FORMAT_NUM] = -{ /* 3GP ASF AVI MATROSKA MP4 OGG NUT QT REAL AMR AAC MP3 AIFF AU WAV MID MMF DIVX FLV VOB IMELODY WMA WMV JPG */ -/*AMR*/ { 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, -/*G723.1*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, -/*MP3*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, -/*OGG*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, -/*AAC*/ { 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, -/*WMA*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, -/*MMF*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, -/*ADPCM*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, -/*WAVE*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, -/*WAVE_NEW*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, -/*MIDI*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, -/*IMELODY*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, -/*MXMF*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, -/*MPA*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, -/*MP2*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, -/*G711*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, -/*G722*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, -/*G722.1*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, -/*G722.2*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, -/*G723*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, -/*G726*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, -/*G728*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, -/*G729*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, -/*G729A*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, -/*G729.1*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, -/*REAL*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, -/*AAC_LC*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, -/*AAC_MAIN*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, -/*AAC_SRS*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, -/*AAC_LTP*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, -/*AAC_HE_V1*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, -/*AAC_HE_V2*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, -/*AC3*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, -/*ALAC*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, -/*ATRAC*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, -/*SPEEX*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, -/*VORBIS*/ { 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, -/*AIFF*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, -/*AU*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, -/*NONE*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, -/*PCM*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, -/*ALAW*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, -/*MULAW*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, -/*MS_ADPCM*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, +{ /* 3GP ASF AVI MATROSKA MP4 OGG NUT QT REAL AMR AAC MP3 AIFF AU WAV MID MMF DIVX FLV VOB IMELODY WMA WMV JPG FLAC M2TS*/ +/*AMR*/ { 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +/*G723.1*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +/*MP3*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +/*OGG*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +/*AAC*/ { 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}, +/*WMA*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +/*MMF*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +/*ADPCM*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +/*WAVE*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +/*WAVE_NEW*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +/*MIDI*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +/*IMELODY*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +/*MXMF*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +/*MPA*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +/*MP2*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +/*G711*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +/*G722*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +/*G722.1*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +/*G722.2*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +/*G723*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +/*G726*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +/*G728*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +/*G729*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +/*G729A*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +/*G729.1*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +/*REAL*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +/*AAC_LC*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +/*AAC_MAIN*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +/*AAC_SRS*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +/*AAC_LTP*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +/*AAC_HE_V1*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +/*AAC_HE_V2*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +/*AC3*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}, +/*ALAC*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +/*ATRAC*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +/*SPEEX*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +/*VORBIS*/ { 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +/*AIFF*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +/*AU*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +/*NONE*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +/*PCM*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +/*ALAW*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +/*MULAW*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +/*MS_ADPCM*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, }; /* Table for compatibility between video codec and file format */ gboolean videocodec_fileformat_compatibility_table[MM_VIDEO_CODEC_NUM][MM_FILE_FORMAT_NUM] = -{ /* 3GP ASF AVI MATROSKA MP4 OGG NUT QT REAL AMR AAC MP3 AIFF AU WAV MID MMF DIVX FLV VOB IMELODY WMA WMV JPG */ -/*NONE*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, -/*H263*/ { 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, -/*H264*/ { 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, -/*H26L*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, -/*MPEG4*/ { 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, -/*MPEG1*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, -/*WMV*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, -/*DIVX*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, -/*XVID*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, -/*H261*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, -/*H262*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, -/*H263V2*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, -/*H263V3*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, -/*MJPEG*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, -/*MPEG2*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, -/*MPEG4_SIMPLE*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, -/*MPEG4_ADV*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, -/*MPEG4_MAIN*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, -/*MPEG4_CORE*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, -/*MPEG4_ACE*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, -/*MPEG4_ARTS*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, -/*MPEG4_AVC*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, -/*REAL*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, -/*VC1*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, -/*AVS*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, -/*CINEPAK*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, -/*INDEO*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, -/*THEORA*/ { 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, +{ /* 3GP ASF AVI MATROSKA MP4 OGG NUT QT REAL AMR AAC MP3 AIFF AU WAV MID MMF DIVX FLV VOB IMELODY WMA WMV JPG FLAC M2TS*/ +/*NONE*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +/*H263*/ { 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +/*H264*/ { 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}, +/*H26L*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +/*MPEG4*/ { 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}, +/*MPEG1*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +/*WMV*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +/*DIVX*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +/*XVID*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +/*H261*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +/*H262*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +/*H263V2*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +/*H263V3*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +/*MJPEG*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +/*MPEG2*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +/*MPEG4_SIMPLE*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +/*MPEG4_ADV*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +/*MPEG4_MAIN*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +/*MPEG4_CORE*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +/*MPEG4_ACE*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +/*MPEG4_ARTS*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +/*MPEG4_AVC*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +/*REAL*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +/*VC1*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +/*AVS*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +/*CINEPAK*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +/*INDEO*/ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, +/*THEORA*/ { 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, }; @@ -123,7 +125,9 @@ gboolean videocodec_fileformat_compatibility_table[MM_VIDEO_CODEC_NUM][MM_FILE_F #define _MMCAMCORDER_CONVERT_OUTPUT_BUFFER_NUM 6 #define _MMCAMCORDER_MIN_TIME_TO_PASS_FRAME 30000000 /* ns */ #define _MMCAMCORDER_FRAME_PASS_MIN_FPS 30 - +#define _MMCAMCORDER_NANOSEC_PER_1SEC 1000000000 +#define _MMCAMCORDER_NANOSEC_PER_1MILISEC 1000 +#define _MMCAMCORDER_VIDEO_DECODER_NAME_PREFIX "avdec_h264" /*----------------------------------------------------------------------- | LOCAL FUNCTION PROTOTYPES: | @@ -141,11 +145,11 @@ gboolean videocodec_fileformat_compatibility_table[MM_VIDEO_CODEC_NUM][MM_FILE_F * @remarks * @see __mmcamcorder_create_preview_pipeline() */ -static gboolean __mmcamcorder_video_dataprobe_preview(GstPad *pad, GstBuffer *buffer, gpointer u_data); -static gboolean __mmcamcorder_video_dataprobe_push_buffer_to_record(GstPad *pad, GstBuffer *buffer, gpointer u_data); +static GstPadProbeReturn __mmcamcorder_video_dataprobe_preview(GstPad *pad, GstPadProbeInfo *info, gpointer u_data); +static GstPadProbeReturn __mmcamcorder_video_dataprobe_push_buffer_to_record(GstPad *pad, GstPadProbeInfo *info, gpointer u_data); static void __mmcamcorder_videoframe_render_error_cb(GstElement *element, void *error_id, gpointer u_data); - static int __mmcamcorder_get_amrnb_bitrate_mode(int bitrate); +static guint32 _mmcamcorder_convert_fourcc_string_to_value(const gchar* format_name); /*======================================================================================= | FUNCTION DEFINITIONS | @@ -283,18 +287,47 @@ int _mmcamcorder_create_preview_elements(MMHandleType handle) /* Set basic infomation of videosrc element */ _mmcamcorder_conf_set_value_element_property(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst, VideosrcElement); + /* make demux and decoder for H264 stream from videosrc */ + if (sc->info_image->preview_format == MM_PIXEL_FORMAT_ENCODED_H264) { + int preview_bitrate = 0; + int iframe_interval = 0; + char decoder_name[20] = {'\0',}; + + /* set encoded preview bitrate and iframe interval */ + mm_camcorder_get_attributes(handle, NULL, + MMCAM_ENCODED_PREVIEW_BITRATE, &preview_bitrate, + MMCAM_ENCODED_PREVIEW_IFRAME_INTERVAL, &iframe_interval, + NULL); + + snprintf(decoder_name, sizeof(decoder_name)-1, "%s", _MMCAMCORDER_VIDEO_DECODER_NAME_PREFIX); + + _mmcam_dbg_log("encoded preview bitrate %d, iframe_interval %d, decoder_name %s", + preview_bitrate, iframe_interval, decoder_name); + + if (!_mmcamcorder_set_encoded_preview_bitrate(handle, preview_bitrate)) { + _mmcam_dbg_warn("_mmcamcorder_set_encoded_preview_bitrate failed"); + } + + if (!_mmcamcorder_set_encoded_preview_iframe_interval(handle, iframe_interval)) { + _mmcam_dbg_warn("_mmcamcorder_set_encoded_preview_iframe_interval failed"); + } + + /* create decoder element */ + _MMCAMCORDER_ELEMENT_MAKE(sc, sc->element, _MMCAMCORDER_VIDEOSRC_DECODE, decoder_name, "videosrc_decode", element_list, err); + } + _mmcam_dbg_log("Current mode[%d]", hcamcorder->type); /* Get videosink name */ _mmcamcorder_conf_get_value_element_name(sc->VideosinkElement, &videosink_name); + _MMCAMCORDER_ELEMENT_MAKE(sc, sc->element, _MMCAMCORDER_VIDEOSINK_QUE, "queue", "videosink_queue", element_list, err); + /* Add color converting element */ - if (!strcmp(videosink_name, "evasimagesink") || - !strcmp(videosink_name, "ximagesink")) { - _MMCAMCORDER_ELEMENT_MAKE(sc, sc->element, _MMCAMCORDER_VIDEOSINK_CLS, "ffmpegcolorspace", "videosrc_convert", element_list, err); + if (!strcmp(videosink_name, "evasimagesink") || !strcmp(videosink_name, "ximagesink")) { + _MMCAMCORDER_ELEMENT_MAKE(sc, sc->element, _MMCAMCORDER_VIDEOSINK_CLS, "videoconvert", "videosrc_convert", element_list, err); } - _MMCAMCORDER_ELEMENT_MAKE(sc, sc->element, _MMCAMCORDER_VIDEOSINK_QUE, "queue", "videosink_queue", element_list, err); _MMCAMCORDER_ELEMENT_MAKE(sc, sc->element, _MMCAMCORDER_VIDEOSINK_SINK, videosink_name, "videosink_sink", element_list, err); if (strcmp(videosink_name, "fakesink") != 0) { @@ -338,6 +371,7 @@ pipeline_creation_error: _MMCAMCORDER_ELEMENT_REMOVE(sc->element, _MMCAMCORDER_VIDEOSRC_CLS); _MMCAMCORDER_ELEMENT_REMOVE(sc->element, _MMCAMCORDER_VIDEOSRC_CLS_FILT); _MMCAMCORDER_ELEMENT_REMOVE(sc->element, _MMCAMCORDER_VIDEOSRC_QUE); + _MMCAMCORDER_ELEMENT_REMOVE(sc->element, _MMCAMCORDER_VIDEOSRC_DECODE); _MMCAMCORDER_ELEMENT_REMOVE(sc->element, _MMCAMCORDER_VIDEOSINK_QUE); _MMCAMCORDER_ELEMENT_REMOVE(sc->element, _MMCAMCORDER_VIDEOSINK_CLS); _MMCAMCORDER_ELEMENT_REMOVE(sc->element, _MMCAMCORDER_VIDEOSINK_SINK); @@ -368,6 +402,8 @@ int _mmcamcorder_create_audiosrc_bin(MMHandleType handle) GstCaps *caps = NULL; GstPad *pad = NULL; GList *element_list = NULL; + int size = 0; + char *device_id = NULL; mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle); _MMCamcorderSubContext *sc = NULL; @@ -395,6 +431,7 @@ int _mmcamcorder_create_audiosrc_bin(MMHandleType handle) MMCAM_AUDIO_FORMAT, &format, MMCAM_AUDIO_CHANNEL, &channel, MMCAM_AUDIO_VOLUME, &volume, + MMCAM_USB_AUDIO_UDEV_ID, &device_id, &size, NULL); if (err != MM_ERROR_NONE) { _mmcam_dbg_warn("Get attrs fail. (%s:%x)", err_name, err); @@ -441,12 +478,15 @@ int _mmcamcorder_create_audiosrc_bin(MMHandleType handle) _mmcamcorder_conf_set_value_element_property(sc->encode_element[_MMCAMCORDER_AUDIOSRC_SRC].gst, AudiosrcElement); + if(device_id != NULL) + MMCAMCORDER_G_OBJECT_SET_POINTER(sc->encode_element[_MMCAMCORDER_AUDIOSRC_SRC].gst, "device-id", device_id); + _MMCAMCORDER_ELEMENT_MAKE(sc, sc->encode_element, _MMCAMCORDER_AUDIOSRC_FILT, "capsfilter", "audiosrc_capsfilter", element_list, err); _MMCAMCORDER_ELEMENT_MAKE(sc, sc->encode_element, _MMCAMCORDER_AUDIOSRC_QUE, "queue", "audiosrc_queue", element_list, err); MMCAMCORDER_G_OBJECT_SET(sc->encode_element[_MMCAMCORDER_AUDIOSRC_QUE].gst, "max-size-buffers", 0); MMCAMCORDER_G_OBJECT_SET(sc->encode_element[_MMCAMCORDER_AUDIOSRC_QUE].gst, "max-size-bytes", 0); - MMCAMCORDER_G_OBJECT_SET(sc->encode_element[_MMCAMCORDER_AUDIOSRC_QUE].gst, "max-size-time", (int64_t)0); + MMCAMCORDER_G_OBJECT_SET(sc->encode_element[_MMCAMCORDER_AUDIOSRC_QUE].gst, "max-size-time", 0); if (a_enc != MM_AUDIO_CODEC_VORBIS) { _MMCAMCORDER_ELEMENT_MAKE(sc, sc->encode_element, _MMCAMCORDER_AUDIOSRC_VOL, "volume", "audiosrc_volume", element_list, err); @@ -455,6 +495,7 @@ int _mmcamcorder_create_audiosrc_bin(MMHandleType handle) /* Set basic infomation */ if (a_enc != MM_AUDIO_CODEC_VORBIS) { int depth = 0; + const gchar* format_name = NULL; if (volume == 0.0) { /* Because data probe of audio src do the same job, it doesn't need to set "mute" here. Already null raw data. */ @@ -466,31 +507,32 @@ int _mmcamcorder_create_audiosrc_bin(MMHandleType handle) if (format == MM_CAMCORDER_AUDIO_FORMAT_PCM_S16_LE) { depth = 16; + format_name = "S16LE"; } else { /* MM_CAMCORDER_AUDIO_FORMAT_PCM_U8 */ depth = 8; + format_name = "U8"; } - caps = gst_caps_new_simple("audio/x-raw-int", - "rate", G_TYPE_INT, rate, - "channels", G_TYPE_INT, channel, - "depth", G_TYPE_INT, depth, - NULL); - _mmcam_dbg_log("caps [x-raw-int, rate:%d, channel:%d, depth:%d], volume %lf", + caps = gst_caps_new_simple("audio/x-raw", + "rate", G_TYPE_INT, rate, + "channels", G_TYPE_INT, channel, + "format", G_TYPE_STRING, format_name, + NULL); + _mmcam_dbg_log("caps [x-raw, rate:%d, channel:%d, depth:%d], volume %lf", rate, channel, depth, volume); } else { /* what are the audio encoder which should get audio/x-raw-float? */ - caps = gst_caps_new_simple("audio/x-raw-float", - "rate", G_TYPE_INT, rate, - "channels", G_TYPE_INT, channel, - "endianness", G_TYPE_INT, BYTE_ORDER, - "width", G_TYPE_INT, 32, - NULL); - _mmcam_dbg_log("caps [x-raw-float, rate:%d, channel:%d, endianness:%d, width:32]", + caps = gst_caps_new_simple("audio/x-raw", + "rate", G_TYPE_INT, rate, + "channels", G_TYPE_INT, channel, + "format", G_TYPE_STRING, GST_AUDIO_NE(F32), + NULL); + _mmcam_dbg_log("caps [x-raw (F32), rate:%d, channel:%d, endianness:%d, width:32]", rate, channel, BYTE_ORDER); } if (caps) { - MMCAMCORDER_G_OBJECT_SET((sc->encode_element[_MMCAMCORDER_AUDIOSRC_FILT].gst), "caps", caps); + MMCAMCORDER_G_OBJECT_SET_POINTER((sc->encode_element[_MMCAMCORDER_AUDIOSRC_FILT].gst), "caps", caps); gst_caps_unref(caps); caps = NULL; } else { @@ -513,7 +555,7 @@ int _mmcamcorder_create_audiosrc_bin(MMHandleType handle) last_element = (_MMCamcorderGstElement*)(g_list_last(element_list)->data); pad = gst_element_get_static_pad(last_element->gst, "src"); - if ((gst_element_add_pad(sc->encode_element[_MMCAMCORDER_AUDIOSRC_BIN].gst, gst_ghost_pad_new("src", pad) )) < 0) { + if (!gst_element_add_pad(sc->encode_element[_MMCAMCORDER_AUDIOSRC_BIN].gst, gst_ghost_pad_new("src", pad))) { gst_object_unref(pad); pad = NULL; _mmcam_dbg_err("failed to create ghost pad on _MMCAMCORDER_AUDIOSRC_BIN."); @@ -534,6 +576,7 @@ int _mmcamcorder_create_audiosrc_bin(MMHandleType handle) pipeline_creation_error: _MMCAMCORDER_ELEMENT_REMOVE(sc->encode_element, _MMCAMCORDER_AUDIOSRC_SRC); _MMCAMCORDER_ELEMENT_REMOVE(sc->encode_element, _MMCAMCORDER_AUDIOSRC_FILT); + _MMCAMCORDER_ELEMENT_REMOVE(sc->encode_element, _MMCAMCORDER_AUDIOSRC_QUE); _MMCAMCORDER_ELEMENT_REMOVE(sc->encode_element, _MMCAMCORDER_AUDIOSRC_VOL); _MMCAMCORDER_ELEMENT_REMOVE(sc->encode_element, _MMCAMCORDER_AUDIOSRC_BIN); @@ -569,8 +612,8 @@ int _mmcamcorder_create_encodesink_bin(MMHandleType handle, MMCamcorderEncodebin const char *str_acs = NULL; char *err_name = NULL; const char *videoconvert_name = NULL; - - GstCaps *caps = NULL; + GstCaps *audio_caps = NULL; + GstCaps *video_caps = NULL; GstPad *pad = NULL; GList *element_list = NULL; @@ -603,8 +646,7 @@ int _mmcamcorder_create_encodesink_bin(MMHandleType handle, MMCamcorderEncodebin /* Create child element */ if (profile != MM_CAMCORDER_ENCBIN_PROFILE_AUDIO) { - GstCaps *video_caps = NULL; - GstCaps *get_caps = NULL; + GstCaps *caps_from_pad = NULL; /* create appsrc and capsfilter */ _MMCAMCORDER_ELEMENT_MAKE(sc, sc->encode_element, _MMCAMCORDER_ENCSINK_SRC, "appsrc", "encodesink_src", element_list, err); @@ -619,54 +661,49 @@ int _mmcamcorder_create_encodesink_bin(MMHandleType handle, MMCamcorderEncodebin /* set appsrc as live source */ MMCAMCORDER_G_OBJECT_SET(sc->encode_element[_MMCAMCORDER_ENCSINK_SRC].gst, "is-live", TRUE); - MMCAMCORDER_G_OBJECT_SET(sc->encode_element[_MMCAMCORDER_ENCSINK_SRC].gst, "max-bytes", (int64_t)0); + MMCAMCORDER_G_OBJECT_SET(sc->encode_element[_MMCAMCORDER_ENCSINK_SRC].gst, "format", 3); /* GST_FORMAT_TIME */ + MMCAMCORDER_G_OBJECT_SET(sc->encode_element[_MMCAMCORDER_ENCSINK_SRC].gst, "max-bytes", 0); /* unlimited */ /* set capsfilter */ - if (sc->element[_MMCAMCORDER_VIDEOSINK_CLS].gst) { - _mmcam_dbg_log("make video/x-raw-rgb caps"); - video_caps = gst_caps_new_simple("video/x-raw-rgb", - NULL); + if (sc->info_image->preview_format == MM_PIXEL_FORMAT_ENCODED_H264) { + _mmcam_dbg_log("get pad from videosrc_filter"); + pad = gst_element_get_static_pad(sc->element[_MMCAMCORDER_VIDEOSRC_FILT].gst, "src"); } else { - _mmcam_dbg_log("get caps from videosrc_filter"); - MMCAMCORDER_G_OBJECT_GET(sc->element[_MMCAMCORDER_VIDEOSRC_FILT].gst, "caps", &get_caps); - if (get_caps) { - video_caps = gst_caps_copy(get_caps); - gst_caps_unref(get_caps); - get_caps = NULL; - } + _mmcam_dbg_log("get pad from videosrc_que"); + pad = gst_element_get_static_pad(sc->element[_MMCAMCORDER_VIDEOSRC_QUE].gst, "src"); + } + if (!pad) { + _mmcam_dbg_err("get videosrc_que src pad failed"); + err = MM_ERROR_CAMCORDER_RESOURCE_CREATION; + goto pipeline_creation_error; } - if (video_caps) { - int set_width = 0; - int set_height = 0; - int set_fps = 0; - - /* normal camera */ - set_width = sc->info_video->video_width; - set_height = sc->info_video->video_height; + caps_from_pad = gst_pad_get_allowed_caps(pad); + video_caps = gst_caps_copy(caps_from_pad); + gst_caps_unref(caps_from_pad); + caps_from_pad = NULL; + gst_object_unref(pad); + pad = NULL; - /* get fps setting */ - mm_camcorder_get_attributes(handle, NULL, - MMCAM_CAMERA_FPS, &set_fps, - NULL); + if (video_caps) { + char *caps_str = NULL; - if(profile != MM_CAMCORDER_ENCBIN_PROFILE_IMAGE) { + if (profile == MM_CAMCORDER_ENCBIN_PROFILE_VIDEO) { gst_caps_set_simple(video_caps, - "width", G_TYPE_INT, set_width, - "height", G_TYPE_INT, set_height, - "framerate", GST_TYPE_FRACTION, set_fps, 1, + "width", G_TYPE_INT, sc->info_video->video_width, + "height", G_TYPE_INT, sc->info_video->video_height, NULL); - - _mmcam_dbg_log("video caps for encodesink bin [%"GST_PTR_FORMAT"], set size %dx%d, fps %d", - video_caps, set_width, set_height, set_fps); } - MMCAMCORDER_G_OBJECT_SET(sc->encode_element[_MMCAMCORDER_ENCSINK_FILT].gst, "caps", video_caps); + caps_str = gst_caps_to_string(video_caps); + _mmcam_dbg_log("encodebin caps [%s]", caps_str); + free(caps_str); + caps_str = NULL; - gst_caps_unref(video_caps); - video_caps = NULL; + MMCAMCORDER_G_OBJECT_SET_POINTER(sc->encode_element[_MMCAMCORDER_ENCSINK_FILT].gst, "caps", video_caps); } else { _mmcam_dbg_err("create recording pipeline caps failed"); + err = MM_ERROR_CAMCORDER_RESOURCE_CREATION; goto pipeline_creation_error; } @@ -737,10 +774,14 @@ int _mmcamcorder_create_encodesink_bin(MMHandleType handle, MMCamcorderEncodebin goto pipeline_creation_error; } - _mmcamcorder_conf_get_value_element_name(VideoencElement, &gst_element_venc_name); + if (sc->info_image->preview_format == MM_PIXEL_FORMAT_ENCODED_H264) { + gst_element_venc_name = "capsfilter"; + } else { + _mmcamcorder_conf_get_value_element_name(VideoencElement, &gst_element_venc_name); + } if (gst_element_venc_name) { - MMCAMCORDER_G_OBJECT_SET(sc->encode_element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "venc-name", gst_element_venc_name); + MMCAMCORDER_G_OBJECT_SET_POINTER(sc->encode_element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "venc-name", gst_element_venc_name); _MMCAMCORDER_ENCODEBIN_ELMGET(sc, _MMCAMCORDER_ENCSINK_VENC, "video-encode", err); } else { _mmcam_dbg_err("Fail to get video encoder name"); @@ -752,27 +793,30 @@ int _mmcamcorder_create_encodesink_bin(MMHandleType handle, MMCamcorderEncodebin if (auto_color_space) { _mmcam_dbg_log("set video convert element [%s]", videoconvert_name); - MMCAMCORDER_G_OBJECT_SET(sc->encode_element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "vconv-name", videoconvert_name); + MMCAMCORDER_G_OBJECT_SET_POINTER(sc->encode_element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "vconv-name", videoconvert_name); _MMCAMCORDER_ENCODEBIN_ELMGET(sc, _MMCAMCORDER_ENCSINK_VCONV, "video-convert", err); /* set colorspace plugin property setting */ _mmcamcorder_conf_set_value_element_property(sc->encode_element[_MMCAMCORDER_ENCSINK_VCONV].gst, sc->VideoconvertElement); + /* fourcc type was removed in GST 1.0 */ if (hcamcorder->use_zero_copy_format) { - caps = gst_caps_new_simple("video/x-raw-yuv", - "format", GST_TYPE_FOURCC, GST_MAKE_FOURCC('S','N','1','2'), + if(strstr(gst_element_venc_name, "omx")) { + video_caps = gst_caps_new_simple("video/x-raw", + "format", G_TYPE_STRING, "SN12", NULL); - if (caps) { - _mmcam_dbg_log("set caps for color space converting [%"GST_PTR_FORMAT"]", caps); + if (video_caps) { + MMCAMCORDER_G_OBJECT_SET_POINTER(sc->encode_element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "vcaps", video_caps); + MMCAMCORDER_G_OBJECT_SET(sc->encode_element[_MMCAMCORDER_ENCSINK_VCONV].gst, "dst-buffer-num", _MMCAMCORDER_CONVERT_OUTPUT_BUFFER_NUM); - MMCAMCORDER_G_OBJECT_SET(sc->encode_element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "vcaps", caps); - MMCAMCORDER_G_OBJECT_SET(sc->encode_element[_MMCAMCORDER_ENCSINK_VCONV].gst, "dst-buffer-num", _MMCAMCORDER_CONVERT_OUTPUT_BUFFER_NUM); - - gst_caps_unref(caps); - caps = NULL; + gst_caps_unref(video_caps); + video_caps = NULL; + } else { + _mmcam_dbg_warn("failed to create caps"); + } } else { - _mmcam_dbg_warn("failed to create caps"); + _mmcam_dbg_log("current video codec is not openmax but [%s]",gst_element_venc_name); } } } @@ -784,6 +828,15 @@ int _mmcamcorder_create_encodesink_bin(MMHandleType handle, MMCamcorderEncodebin if (use_venc_queue) { _MMCAMCORDER_ENCODEBIN_ELMGET(sc, _MMCAMCORDER_ENCSINK_VENC_QUE, "use-venc-queue", err); } + + if (sc->info_image->preview_format == MM_PIXEL_FORMAT_ENCODED_H264) { + MMCAMCORDER_G_OBJECT_SET_POINTER(sc->encode_element[_MMCAMCORDER_ENCSINK_VENC].gst, "caps", video_caps); + } + + if(video_caps) { + gst_caps_unref(video_caps); + video_caps = NULL; + } } if (sc->audio_disable == FALSE && @@ -799,26 +852,25 @@ int _mmcamcorder_create_encodesink_bin(MMHandleType handle, MMCamcorderEncodebin _mmcamcorder_conf_get_value_element_name(AudioencElement, &gst_element_aenc_name); - MMCAMCORDER_G_OBJECT_SET(sc->encode_element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "aenc-name", gst_element_aenc_name); + MMCAMCORDER_G_OBJECT_SET_POINTER(sc->encode_element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "aenc-name", gst_element_aenc_name); _MMCAMCORDER_ENCODEBIN_ELMGET(sc, _MMCAMCORDER_ENCSINK_AENC, "audio-encode", err); if (audio_enc == MM_AUDIO_CODEC_AMR && channel == 2) { - caps = gst_caps_new_simple("audio/x-raw-int", + audio_caps = gst_caps_new_simple("audio/x-raw", "channels", G_TYPE_INT, 1, NULL); MMCAMCORDER_G_OBJECT_SET(sc->encode_element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "auto-audio-convert", TRUE); - MMCAMCORDER_G_OBJECT_SET(sc->encode_element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "acaps", caps); - gst_caps_unref (caps); - caps = NULL; + MMCAMCORDER_G_OBJECT_SET_POINTER(sc->encode_element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "acaps", audio_caps); + gst_caps_unref(audio_caps); + audio_caps = NULL; } if (audio_enc == MM_AUDIO_CODEC_OGG) { - caps = gst_caps_new_simple("audio/x-raw-int", - NULL); + audio_caps = gst_caps_new_empty_simple("audio/x-raw"); MMCAMCORDER_G_OBJECT_SET(sc->encode_element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "auto-audio-convert", TRUE); - MMCAMCORDER_G_OBJECT_SET(sc->encode_element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "acaps", caps); - gst_caps_unref (caps); - caps = NULL; + MMCAMCORDER_G_OBJECT_SET_POINTER(sc->encode_element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "acaps", audio_caps); + gst_caps_unref(audio_caps); + audio_caps = NULL; _mmcam_dbg_log("***** MM_AUDIO_CODEC_OGG : setting audio/x-raw-int "); } @@ -828,7 +880,7 @@ int _mmcamcorder_create_encodesink_bin(MMHandleType handle, MMCamcorderEncodebin &use_aenc_queue); if (use_aenc_queue) { _MMCAMCORDER_ENCODEBIN_ELMGET(sc, _MMCAMCORDER_ENCSINK_AENC_QUE, "use-aenc-queue", err); - MMCAMCORDER_G_OBJECT_SET(sc->encode_element[_MMCAMCORDER_ENCSINK_AENC_QUE].gst,"max-size-time", (int64_t)0); + MMCAMCORDER_G_OBJECT_SET(sc->encode_element[_MMCAMCORDER_ENCSINK_AENC_QUE].gst,"max-size-time", 0); MMCAMCORDER_G_OBJECT_SET(sc->encode_element[_MMCAMCORDER_ENCSINK_AENC_QUE].gst,"max-size-buffers", 0); } } @@ -843,7 +895,7 @@ int _mmcamcorder_create_encodesink_bin(MMHandleType handle, MMCamcorderEncodebin _mmcamcorder_conf_get_value_element_name(ImageencElement, &gst_element_ienc_name); - MMCAMCORDER_G_OBJECT_SET(sc->encode_element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "ienc-name", gst_element_ienc_name); + MMCAMCORDER_G_OBJECT_SET_POINTER(sc->encode_element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "ienc-name", gst_element_ienc_name); _MMCAMCORDER_ENCODEBIN_ELMGET(sc, _MMCAMCORDER_ENCSINK_IENC, "image-encode", err); } @@ -858,7 +910,7 @@ int _mmcamcorder_create_encodesink_bin(MMHandleType handle, MMCamcorderEncodebin _mmcamcorder_conf_get_value_element_name(MuxElement, &gst_element_mux_name); - MMCAMCORDER_G_OBJECT_SET(sc->encode_element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "mux-name", gst_element_mux_name); + MMCAMCORDER_G_OBJECT_SET_POINTER(sc->encode_element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "mux-name", gst_element_mux_name); _MMCAMCORDER_ENCODEBIN_ELMGET(sc, _MMCAMCORDER_ENCSINK_MUX, "mux", err); _mmcamcorder_conf_set_value_element_property(sc->encode_element[_MMCAMCORDER_ENCSINK_MUX].gst, MuxElement); @@ -888,7 +940,7 @@ int _mmcamcorder_create_encodesink_bin(MMHandleType handle, MMCamcorderEncodebin } else { _mmcam_dbg_warn("video bitrate is too small[%d], so skip setting. Use DEFAULT value.", v_bitrate); } - /*MMCAMCORDER_G_OBJECT_SET ((sc->encode_element[_MMCAMCORDER_ENCSINK_VENC].gst),"hw-accel", v_hw);*/ + _mmcamcorder_conf_set_value_element_property(sc->encode_element[_MMCAMCORDER_ENCSINK_VENC].gst, VideoencElement); } @@ -930,7 +982,7 @@ int _mmcamcorder_create_encodesink_bin(MMHandleType handle, MMCamcorderEncodebin if (profile == MM_CAMCORDER_ENCBIN_PROFILE_VIDEO) { pad = gst_element_get_request_pad(sc->encode_element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "video"); - if (gst_element_add_pad(sc->encode_element[_MMCAMCORDER_ENCSINK_BIN].gst, gst_ghost_pad_new("video_sink0", pad)) < 0) { + if (!gst_element_add_pad(sc->encode_element[_MMCAMCORDER_ENCSINK_BIN].gst, gst_ghost_pad_new("video_sink0", pad))) { gst_object_unref(pad); pad = NULL; _mmcam_dbg_err("failed to create ghost video_sink0 on _MMCAMCORDER_ENCSINK_BIN."); @@ -942,7 +994,7 @@ int _mmcamcorder_create_encodesink_bin(MMHandleType handle, MMCamcorderEncodebin if (sc->audio_disable == FALSE) { pad = gst_element_get_request_pad(sc->encode_element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "audio"); - if (gst_element_add_pad(sc->encode_element[_MMCAMCORDER_ENCSINK_BIN].gst, gst_ghost_pad_new("audio_sink0", pad)) < 0) { + if (!gst_element_add_pad(sc->encode_element[_MMCAMCORDER_ENCSINK_BIN].gst, gst_ghost_pad_new("audio_sink0", pad))) { gst_object_unref(pad); pad = NULL; _mmcam_dbg_err("failed to create ghost audio_sink0 on _MMCAMCORDER_ENCSINK_BIN."); @@ -954,7 +1006,7 @@ int _mmcamcorder_create_encodesink_bin(MMHandleType handle, MMCamcorderEncodebin } } else if (profile == MM_CAMCORDER_ENCBIN_PROFILE_AUDIO) { pad = gst_element_get_request_pad(sc->encode_element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "audio"); - if (gst_element_add_pad(sc->encode_element[_MMCAMCORDER_ENCSINK_BIN].gst, gst_ghost_pad_new("audio_sink0", pad)) < 0) { + if (!gst_element_add_pad(sc->encode_element[_MMCAMCORDER_ENCSINK_BIN].gst, gst_ghost_pad_new("audio_sink0", pad))) { gst_object_unref(pad); pad = NULL; _mmcam_dbg_err("failed to create ghost audio_sink0 on _MMCAMCORDER_ENCSINK_BIN."); @@ -966,7 +1018,7 @@ int _mmcamcorder_create_encodesink_bin(MMHandleType handle, MMCamcorderEncodebin } else { /* for stillshot */ pad = gst_element_get_request_pad(sc->encode_element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "image"); - if (gst_element_add_pad(sc->encode_element[_MMCAMCORDER_ENCSINK_BIN].gst, gst_ghost_pad_new("image_sink0", pad)) < 0) { + if (!gst_element_add_pad(sc->encode_element[_MMCAMCORDER_ENCSINK_BIN].gst, gst_ghost_pad_new("image_sink0", pad))) { gst_object_unref(pad); pad = NULL; _mmcam_dbg_err("failed to create ghost image_sink0 on _MMCAMCORDER_ENCSINK_BIN."); @@ -991,11 +1043,18 @@ int _mmcamcorder_create_encodesink_bin(MMHandleType handle, MMCamcorderEncodebin element_list = NULL; } + if (video_caps) { + gst_caps_unref(video_caps); + video_caps = NULL; + } + _mmcam_dbg_log("done"); return MM_ERROR_NONE; pipeline_creation_error : + _mmcamcorder_remove_all_handlers(handle, _MMCAMCORDER_HANDLER_VIDEOREC); + _MMCAMCORDER_ELEMENT_REMOVE(sc->encode_element, _MMCAMCORDER_ENCSINK_ENCBIN); _MMCAMCORDER_ELEMENT_REMOVE(sc->encode_element, _MMCAMCORDER_ENCSINK_SRC); _MMCAMCORDER_ELEMENT_REMOVE(sc->encode_element, _MMCAMCORDER_ENCSINK_FILT); @@ -1011,6 +1070,11 @@ pipeline_creation_error : element_list = NULL; } + if (video_caps) { + gst_caps_unref(video_caps); + video_caps = NULL; + } + return err; } @@ -1063,7 +1127,11 @@ int _mmcamcorder_create_preview_pipeline(MMHandleType handle) } /* set dataprobe for video recording */ - srcpad = gst_element_get_static_pad(sc->element[_MMCAMCORDER_VIDEOSINK_QUE].gst, "src"); + if (sc->info_image->preview_format == MM_PIXEL_FORMAT_ENCODED_H264) { + srcpad = gst_element_get_static_pad(sc->element[_MMCAMCORDER_VIDEOSRC_QUE].gst, "src"); + } else { + srcpad = gst_element_get_static_pad(sc->element[_MMCAMCORDER_VIDEOSINK_QUE].gst, "src"); + } MMCAMCORDER_ADD_BUFFER_PROBE(srcpad, _MMCAMCORDER_HANDLER_PREVIEW, __mmcamcorder_video_dataprobe_push_buffer_to_record, hcamcorder); gst_object_unref(srcpad); @@ -1075,18 +1143,11 @@ int _mmcamcorder_create_preview_pipeline(MMHandleType handle) hcamcorder->pipeline_cb_event_id = gst_bus_add_watch(bus, _mmcamcorder_pipeline_cb_message, (gpointer)hcamcorder); /* set sync handler */ - gst_bus_set_sync_handler(bus, _mmcamcorder_pipeline_bus_sync_callback, (gpointer)hcamcorder); + gst_bus_set_sync_handler(bus, _mmcamcorder_pipeline_bus_sync_callback, (gpointer)hcamcorder, NULL); gst_object_unref(bus); bus = NULL; - /* Below signals are meaningfull only when video source is using. */ - MMCAMCORDER_SIGNAL_CONNECT(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst, - _MMCAMCORDER_HANDLER_PREVIEW, - "nego-complete", - _mmcamcorder_negosig_handler, - hcamcorder); - return MM_ERROR_NONE; pipeline_creation_error: @@ -1095,37 +1156,6 @@ pipeline_creation_error: } -void _mmcamcorder_negosig_handler(GstElement *videosrc, MMHandleType handle) -{ - mmf_camcorder_t *hcamcorder= MMF_CAMCORDER(handle); - _MMCamcorderSubContext *sc = NULL; - - _mmcam_dbg_log(""); - - mmf_return_if_fail(hcamcorder); - mmf_return_if_fail(hcamcorder->sub_context); - sc = MMF_CAMCORDER_SUBCONTEXT(handle); - - /* kernel was modified. No need to set. - _mmcamcorder_set_attribute_to_camsensor(handle); - */ - - if (sc->cam_stability_count != _MMCAMCORDER_CAMSTABLE_COUNT) { - sc->cam_stability_count = _MMCAMCORDER_CAMSTABLE_COUNT; - } - - if (hcamcorder->type != MM_CAMCORDER_MODE_AUDIO) { - _MMCamcorderImageInfo *info = NULL; - info = sc->info_image; - if (info->resolution_change == TRUE) { - _mmcam_dbg_log("open toggle of stillshot sink."); - MMCAMCORDER_G_OBJECT_SET(sc->encode_element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "block", FALSE); - info->resolution_change = FALSE; - } - } -} - - void _mmcamcorder_ready_to_encode_callback(GstElement *element, guint size, gpointer handle) { mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle); @@ -1139,6 +1169,7 @@ void _mmcamcorder_ready_to_encode_callback(GstElement *element, guint size, gpoi /* set flag */ if (sc->info_video->push_encoding_buffer == PUSH_ENCODING_BUFFER_INIT) { + sc->info_video->get_first_I_frame = FALSE; sc->info_video->push_encoding_buffer = PUSH_ENCODING_BUFFER_RUN; _mmcam_dbg_warn("set push_encoding_buffer RUN"); } @@ -1163,6 +1194,7 @@ int _mmcamcorder_videosink_window_set(MMHandleType handle, type_element* Videosi int zoom_attr = 0; int zoom_level = 0; int do_scaling = FALSE; + int display_scaler = 0; int *overlay = NULL; gulong xid; char *err_name = NULL; @@ -1199,6 +1231,7 @@ int _mmcamcorder_videosink_window_set(MMHandleType handle, type_element* Videosi MMCAM_DISPLAY_SCALE, &zoom_attr, MMCAM_DISPLAY_EVAS_DO_SCALING, &do_scaling, MMCAM_DISPLAY_SURFACE, &display_surface, + MMCAM_DISPLAY_SCALER, &display_scaler, NULL); if (err != MM_ERROR_NONE) { if (err_name) { @@ -1226,8 +1259,9 @@ int _mmcamcorder_videosink_window_set(MMHandleType handle, type_element* Videosi _mmcam_dbg_log("set pixmap cb[%p] and user data[%p]", pixmap_cb, pixmap_cb_user_data); /* set pixmap callback and user data */ - MMCAMCORDER_G_OBJECT_SET(vsink, "pixmap-id-callback", pixmap_cb); - MMCAMCORDER_G_OBJECT_SET(vsink, "pixmap-id-callback-userdata", pixmap_cb_user_data); + MMCAMCORDER_G_OBJECT_SET_POINTER(vsink, "pixmap-id-callback", pixmap_cb); + MMCAMCORDER_G_OBJECT_SET_POINTER(vsink, "pixmap-id-callback-userdata", pixmap_cb_user_data); + MMCAMCORDER_G_OBJECT_SET(vsink, "display-scaler", display_scaler); /* connect render error signal */ MMCAMCORDER_SIGNAL_CONNECT(vsink, @@ -1244,16 +1278,16 @@ int _mmcamcorder_videosink_window_set(MMHandleType handle, type_element* Videosi if (overlay) { xid = *overlay; _mmcam_dbg_log("xid = %lu )", xid); - gst_x_overlay_set_xwindow_id(GST_X_OVERLAY(vsink), xid); + gst_video_overlay_set_window_handle(GST_VIDEO_OVERLAY(vsink), xid); } else { _mmcam_dbg_warn("Handle is NULL. Set xid as 0.. but, it's not recommended."); - gst_x_overlay_set_xwindow_id(GST_X_OVERLAY(vsink), 0); + gst_video_overlay_set_window_handle(GST_VIDEO_OVERLAY(vsink), 0); } } else if (!strcmp(videosink_name, "evasimagesink") || !strcmp(videosink_name, "evaspixmapsink")) { _mmcam_dbg_log("videosink : %s, handle : %p", videosink_name, overlay); if (overlay) { - MMCAMCORDER_G_OBJECT_SET(vsink, "evas-object", overlay); + MMCAMCORDER_G_OBJECT_SET_POINTER(vsink, "evas-object", overlay); MMCAMCORDER_G_OBJECT_SET(vsink, "origin-size", !do_scaling); } else { _mmcam_dbg_err("display handle(eavs object) is NULL"); @@ -1295,7 +1329,7 @@ int _mmcamcorder_videosink_window_set(MMHandleType handle, type_element* Videosi MMCAMCORDER_G_OBJECT_SET(vsink, "display-geometry-method", display_geometry_method); MMCAMCORDER_G_OBJECT_SET(vsink, "display-mode", display_mode); MMCAMCORDER_G_OBJECT_SET(vsink, "visible", visible); - MMCAMCORDER_G_OBJECT_SET(vsink, "zoom", (float)zoom_level); + MMCAMCORDER_G_OBJECT_SET(vsink, "zoom", zoom_level); if (display_geometry_method == MM_DISPLAY_METHOD_CUSTOM_ROI) { g_object_set(vsink, @@ -1325,7 +1359,7 @@ int _mmcamcorder_vframe_stablize(MMHandleType handle) mmf_camcorder_t *hcamcorder= MMF_CAMCORDER(handle); _MMCamcorderSubContext *sc = NULL; - /*_mmcam_dbg_log("%d", _MMCAMCORDER_CAMSTABLE_COUNT);*/ + _mmcam_dbg_log("%d", _MMCAMCORDER_CAMSTABLE_COUNT); mmf_return_val_if_fail(hcamcorder, MM_ERROR_CAMCORDER_NOT_INITIALIZED); @@ -1391,21 +1425,32 @@ gboolean _mmcamcorder_get_device_info(MMHandleType handle) return TRUE; } +static guint32 _mmcamcorder_convert_fourcc_string_to_value(const gchar* format_name) +{ + return format_name[0] | (format_name[1] << 8) | (format_name[2] << 16) | (format_name[3] << 24); +} -static gboolean __mmcamcorder_video_dataprobe_preview(GstPad *pad, GstBuffer *buffer, gpointer u_data) +static GstPadProbeReturn __mmcamcorder_video_dataprobe_preview(GstPad *pad, GstPadProbeInfo *info, gpointer u_data) { int current_state = MM_CAMCORDER_STATE_NONE; + int i = 0; mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(u_data); _MMCamcorderSubContext *sc = NULL; _MMCamcorderKPIMeasure *kpi = NULL; + GstBuffer *buffer = GST_PAD_PROBE_INFO_BUFFER(info); + GstMemory *dataBlock = NULL; + GstMemory *metaBlock = NULL; + GstMapInfo mapinfo; - mmf_return_val_if_fail(buffer, FALSE); - mmf_return_val_if_fail(GST_BUFFER_DATA(buffer), FALSE); - mmf_return_val_if_fail(hcamcorder, FALSE); + mmf_return_val_if_fail(buffer, GST_PAD_PROBE_DROP); + mmf_return_val_if_fail(gst_buffer_n_memory(buffer) , GST_PAD_PROBE_DROP); + mmf_return_val_if_fail(hcamcorder, GST_PAD_PROBE_DROP); sc = MMF_CAMCORDER_SUBCONTEXT(u_data); - mmf_return_val_if_fail(sc, FALSE); + mmf_return_val_if_fail(sc, GST_PAD_PROBE_DROP); + + memset(&mapinfo, 0x0, sizeof(GstMapInfo)); current_state = hcamcorder->state; @@ -1416,12 +1461,12 @@ static gboolean __mmcamcorder_video_dataprobe_preview(GstPad *pad, GstBuffer *bu } else { sc->drop_vframe--; _mmcam_dbg_log("Drop video frame by drop_vframe"); - return FALSE; + return GST_PAD_PROBE_DROP; } } else if (sc->cam_stability_count > 0) { sc->cam_stability_count--; _mmcam_dbg_log("Drop video frame by cam_stability_count"); - return FALSE; + return GST_PAD_PROBE_DROP; } if (current_state >= MM_CAMCORDER_STATE_PREPARE) { @@ -1467,18 +1512,19 @@ static gboolean __mmcamcorder_video_dataprobe_preview(GstPad *pad, GstBuffer *bu int state = MM_CAMCORDER_STATE_NULL; unsigned int fourcc = 0; MMCamcorderVideoStreamDataType stream; - SCMN_IMGB *scmn_imgb = NULL; + MMVideoBuffer *mm_buf = NULL; + const gchar *string_format = NULL; state = _mmcamcorder_get_state((MMHandleType)hcamcorder); if (state < MM_CAMCORDER_STATE_PREPARE) { _mmcam_dbg_warn("Not ready for stream callback"); - return TRUE; + return GST_PAD_PROBE_OK; } - caps = gst_buffer_get_caps(buffer); + caps = gst_pad_get_current_caps(pad); if (caps == NULL) { _mmcam_dbg_warn( "Caps is NULL." ); - return TRUE; + return GST_PAD_PROBE_OK; } /* clear stream data structure */ @@ -1487,8 +1533,20 @@ static gboolean __mmcamcorder_video_dataprobe_preview(GstPad *pad, GstBuffer *bu structure = gst_caps_get_structure( caps, 0 ); gst_structure_get_int(structure, "width", &(stream.width)); gst_structure_get_int(structure, "height", &(stream.height)); - gst_structure_get_fourcc(structure, "format", &fourcc); - stream.format = _mmcamcorder_get_pixtype(fourcc); + string_format = gst_structure_get_string(structure, "format"); + if (string_format == NULL) { + gst_caps_unref( caps ); + caps = NULL; + _mmcam_dbg_warn("get string error!!"); + return GST_PAD_PROBE_OK; + } + + if (sc->info_image->preview_format == MM_PIXEL_FORMAT_ENCODED_H264) { + stream.format = MM_PIXEL_FORMAT_ENCODED_H264; + } else { + fourcc = _mmcamcorder_convert_fourcc_string_to_value(string_format); + stream.format = _mmcamcorder_get_pixtype(fourcc); + } gst_caps_unref( caps ); caps = NULL; @@ -1499,29 +1557,32 @@ static gboolean __mmcamcorder_video_dataprobe_preview(GstPad *pad, GstBuffer *bu if (stream.width == 0 || stream.height == 0) { _mmcam_dbg_warn("Wrong condition!!"); - return TRUE; + return GST_PAD_PROBE_OK; } /* set size and timestamp */ - stream.length_total = GST_BUFFER_SIZE(buffer); - stream.timestamp = (unsigned int)(GST_BUFFER_TIMESTAMP(buffer)/1000000); /* nano sec -> mili sec */ - - if (hcamcorder->use_zero_copy_format && GST_BUFFER_MALLOCDATA(buffer)) { - scmn_imgb = (SCMN_IMGB *)GST_BUFFER_MALLOCDATA(buffer); + dataBlock = gst_buffer_peek_memory(buffer, 0); + stream.length_total = gst_memory_get_sizes(dataBlock, NULL, NULL); + stream.timestamp = (unsigned int)(GST_BUFFER_PTS(buffer)/1000000); /* nano sec -> mili sec */ + + if (hcamcorder->use_zero_copy_format && gst_buffer_n_memory(buffer) > 1) { + metaBlock = gst_buffer_peek_memory(buffer, 1); + gst_memory_map(metaBlock, &mapinfo, GST_MAP_READ); + mm_buf = (MMVideoBuffer *)mapinfo.data; } /* set data pointers */ if (stream.format == MM_PIXEL_FORMAT_NV12 || stream.format == MM_PIXEL_FORMAT_NV21 || stream.format == MM_PIXEL_FORMAT_I420) { - if (scmn_imgb) { + if (mm_buf) { if (stream.format == MM_PIXEL_FORMAT_NV12 || stream.format == MM_PIXEL_FORMAT_NV21) { stream.data_type = MM_CAM_STREAM_DATA_YUV420SP; stream.num_planes = 2; - stream.data.yuv420sp.y = scmn_imgb->a[0]; + stream.data.yuv420sp.y = mm_buf->data[0]; stream.data.yuv420sp.length_y = stream.width * stream.height; - stream.data.yuv420sp.uv = scmn_imgb->a[1]; + stream.data.yuv420sp.uv = mm_buf->data[1]; stream.data.yuv420sp.length_uv = stream.data.yuv420sp.length_y >> 1; /* _mmcam_dbg_log("format[%d][num_planes:%d] [Y]p:0x%x,size:%d [UV]p:0x%x,size:%d", @@ -1532,11 +1593,11 @@ static gboolean __mmcamcorder_video_dataprobe_preview(GstPad *pad, GstBuffer *bu } else { stream.data_type = MM_CAM_STREAM_DATA_YUV420P; stream.num_planes = 3; - stream.data.yuv420p.y = scmn_imgb->a[0]; + stream.data.yuv420p.y = mm_buf->data[0]; stream.data.yuv420p.length_y = stream.width * stream.height; - stream.data.yuv420p.u = scmn_imgb->a[1]; + stream.data.yuv420p.u = mm_buf->data[1]; stream.data.yuv420p.length_u = stream.data.yuv420p.length_y >> 2; - stream.data.yuv420p.v = scmn_imgb->a[2]; + stream.data.yuv420p.v = mm_buf->data[2]; stream.data.yuv420p.length_v = stream.data.yuv420p.length_u; /* _mmcam_dbg_log("S420[num_planes:%d] [Y]p:0x%x,size:%d [U]p:0x%x,size:%d [V]p:0x%x,size:%d", @@ -1547,11 +1608,12 @@ static gboolean __mmcamcorder_video_dataprobe_preview(GstPad *pad, GstBuffer *bu */ } } else { + gst_memory_map(dataBlock, &mapinfo, GST_MAP_READWRITE); if (stream.format == MM_PIXEL_FORMAT_NV12 || stream.format == MM_PIXEL_FORMAT_NV21) { stream.data_type = MM_CAM_STREAM_DATA_YUV420SP; stream.num_planes = 2; - stream.data.yuv420sp.y = GST_BUFFER_DATA(buffer); + stream.data.yuv420sp.y = mapinfo.data; stream.data.yuv420sp.length_y = stream.width * stream.height; stream.data.yuv420sp.uv = stream.data.yuv420sp.y + stream.data.yuv420sp.length_y; stream.data.yuv420sp.length_uv = stream.data.yuv420sp.length_y >> 1; @@ -1564,7 +1626,7 @@ static gboolean __mmcamcorder_video_dataprobe_preview(GstPad *pad, GstBuffer *bu } else { stream.data_type = MM_CAM_STREAM_DATA_YUV420P; stream.num_planes = 3; - stream.data.yuv420p.y = GST_BUFFER_DATA(buffer); + stream.data.yuv420p.y = mapinfo.data; stream.data.yuv420p.length_y = stream.width * stream.height; stream.data.yuv420p.u = stream.data.yuv420p.y + stream.data.yuv420p.length_y; stream.data.yuv420p.length_u = stream.data.yuv420p.length_y >> 2; @@ -1580,16 +1642,28 @@ static gboolean __mmcamcorder_video_dataprobe_preview(GstPad *pad, GstBuffer *bu } } } else { + if (mm_buf) { + gst_memory_unmap(metaBlock, &mapinfo); + metaBlock = NULL; + } + gst_memory_map(dataBlock, &mapinfo, GST_MAP_READWRITE); if (stream.format == MM_PIXEL_FORMAT_YUYV || stream.format == MM_PIXEL_FORMAT_UYVY || stream.format == MM_PIXEL_FORMAT_422P || stream.format == MM_PIXEL_FORMAT_ITLV_JPEG_UYVY) { stream.data_type = MM_CAM_STREAM_DATA_YUV422; - stream.data.yuv422.yuv = GST_BUFFER_DATA(buffer); + stream.data.yuv422.yuv = mapinfo.data; stream.data.yuv422.length_yuv = stream.length_total; + } else if (stream.format == MM_PIXEL_FORMAT_ENCODED_H264) { + stream.data_type = MM_CAM_STREAM_DATA_ENCODED; + stream.data.encoded.data = mapinfo.data; + stream.data.encoded.length_data = stream.length_total; + _mmcam_dbg_log("H264[num_planes:%d] [0]p:0x%x,size:%d", + fourcc, fourcc>>8, fourcc>>16, fourcc>>24, stream.num_planes, + stream.data.encoded.data, stream.data.encoded.length_data); } else { stream.data_type = MM_CAM_STREAM_DATA_YUV420; - stream.data.yuv420.yuv = GST_BUFFER_DATA(buffer); + stream.data.yuv420.yuv = mapinfo.data; stream.data.yuv420.length_yuv = stream.length_total; } @@ -1602,13 +1676,12 @@ static gboolean __mmcamcorder_video_dataprobe_preview(GstPad *pad, GstBuffer *bu } /* set tbm bo */ - if (scmn_imgb) { - int i = 0; - - for (i = 0 ; i < SCMN_IMGB_MAX_PLANE ; i++) { - stream.bo[i] = (void *)scmn_imgb->bo[i]; - stream.stride[i] = scmn_imgb->s[i]; - stream.elevation[i] = scmn_imgb->e[i]; + if (mm_buf && mm_buf->type == MM_VIDEO_BUFFER_TYPE_TBM_BO) { + /* set bo, stride and elevation */ + for (i = 0 ; i < MM_VIDEO_BUFFER_PLANE_MAX ; i++) { + stream.bo[i] = (void *)mm_buf->handle.bo[i]; + stream.stride[i] = mm_buf->stride_width[i]; + stream.elevation[i] = mm_buf->stride_height[i]; } /* set gst buffer */ @@ -1619,26 +1692,37 @@ static gboolean __mmcamcorder_video_dataprobe_preview(GstPad *pad, GstBuffer *bu _MMCAMCORDER_LOCK_VSTREAM_CALLBACK(hcamcorder); if (hcamcorder->vstream_cb) { hcamcorder->vstream_cb(&stream, hcamcorder->vstream_cb_param); + + for (i = 0 ; i < MM_VIDEO_BUFFER_PLANE_MAX && stream.bo[i] ; i++) { + tbm_bo_map(stream.bo[i], TBM_DEVICE_CPU, TBM_OPTION_READ|TBM_OPTION_WRITE); + tbm_bo_unmap(stream.bo[i]); + } } _MMCAMCORDER_UNLOCK_VSTREAM_CALLBACK(hcamcorder); + /* Either metaBlock was mapped, or dataBlock, but not both. */ + if (metaBlock) { + gst_memory_unmap(metaBlock, &mapinfo); + }else { + gst_memory_unmap(dataBlock, &mapinfo); + } } - return TRUE; + return GST_PAD_PROBE_OK; } - -static gboolean __mmcamcorder_video_dataprobe_push_buffer_to_record(GstPad *pad, GstBuffer *buffer, gpointer u_data) +static GstPadProbeReturn __mmcamcorder_video_dataprobe_push_buffer_to_record(GstPad *pad, GstPadProbeInfo *info, gpointer u_data) { mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(u_data); _MMCamcorderSubContext *sc = NULL; GstClockTime diff = 0; /* nsec */ + GstBuffer *buffer = GST_PAD_PROBE_INFO_BUFFER(info); - mmf_return_val_if_fail(buffer, FALSE); - mmf_return_val_if_fail(GST_BUFFER_DATA(buffer), FALSE); - mmf_return_val_if_fail(hcamcorder, FALSE); + mmf_return_val_if_fail(buffer, GST_PAD_PROBE_DROP); + mmf_return_val_if_fail(gst_buffer_n_memory(buffer), GST_PAD_PROBE_DROP); + mmf_return_val_if_fail(hcamcorder, GST_PAD_PROBE_DROP); sc = MMF_CAMCORDER_SUBCONTEXT(u_data); - mmf_return_val_if_fail(sc, FALSE); + mmf_return_val_if_fail(sc, GST_PAD_PROBE_DROP); /* push buffer in appsrc to encode */ if(!sc->info_video) { @@ -1650,29 +1734,67 @@ static gboolean __mmcamcorder_video_dataprobe_push_buffer_to_record(GstPad *pad, sc->info_video->record_dual_stream == FALSE && sc->encode_element[_MMCAMCORDER_ENCSINK_SRC].gst) { int ret = 0; - GstClock *pipe_clock = NULL; - GstClockTime timestamp = GST_CLOCK_TIME_NONE; - - pipe_clock = GST_ELEMENT_CLOCK(sc->encode_element[_MMCAMCORDER_ENCSINK_SRC].gst); - if (pipe_clock) { - gst_object_ref(pipe_clock); - timestamp = gst_clock_get_time(pipe_clock) - GST_ELEMENT(sc->encode_element[_MMCAMCORDER_ENCSINK_SRC].gst)->base_time; - gst_object_unref(pipe_clock); + GstClock *clock = NULL; - /* - _mmcam_dbg_log("new time stamp %p [%"GST_TIME_FORMAT"], base time [%"GST_TIME_FORMAT"]", - buffer, GST_TIME_ARGS(timestamp), GST_TIME_ARGS(GST_ELEMENT(sc->encode_element[_MMCAMCORDER_ENCSINK_SRC].gst)->base_time)); - */ + /* + _mmcam_dbg_log("GST_BUFFER_FLAG_DELTA_UNIT is set : %d", + GST_BUFFER_FLAG_IS_SET(buffer, GST_BUFFER_FLAG_DELTA_UNIT)); + */ - if (sc->info_video->prev_video_ts >= timestamp) { - _mmcam_dbg_warn("invalid time stamp %p [%"GST_TIME_FORMAT"], make it different", - buffer, GST_TIME_ARGS(timestamp)); - timestamp = sc->info_video->prev_video_ts + NANO_SEC_PER_MILI_SEC; + /* check first I frame */ + if (sc->info_image->preview_format == MM_PIXEL_FORMAT_ENCODED_H264 && + sc->info_video->get_first_I_frame == FALSE) { + if (!GST_BUFFER_FLAG_IS_SET(buffer, GST_BUFFER_FLAG_DELTA_UNIT)) { + _mmcam_dbg_warn("first I frame is come"); + sc->info_video->get_first_I_frame = TRUE; + } else { + _mmcam_dbg_warn("NOT I frame.. skip this buffer"); + return TRUE; } + } - GST_BUFFER_TIMESTAMP(buffer) = timestamp; - - sc->info_video->prev_video_ts = timestamp; + if (sc->encode_element[_MMCAMCORDER_AUDIOSRC_SRC].gst) { + if (sc->info_video->is_firstframe) { + sc->info_video->is_firstframe = FALSE; + clock = GST_ELEMENT_CLOCK(sc->encode_element[_MMCAMCORDER_AUDIOSRC_SRC].gst); + if (clock) { + gst_object_ref(clock); + sc->info_video->base_video_ts = GST_BUFFER_PTS(buffer) - (gst_clock_get_time(clock) - GST_ELEMENT(sc->encode_element[_MMCAMCORDER_ENCSINK_SRC].gst)->base_time); + gst_object_unref(clock); + } + } + } else { + if(sc->info_video->is_firstframe) { + if (sc->bencbin_capture && sc->info_image->capturing) { + pthread_mutex_lock(&(hcamcorder->task_thread_lock)); + _mmcam_dbg_log("send signal for sound play"); + hcamcorder->task_thread_state = _MMCAMCORDER_TASK_THREAD_STATE_SOUND_SOLO_PLAY_START; + pthread_cond_signal(&(hcamcorder->task_thread_cond)); + pthread_mutex_unlock(&(hcamcorder->task_thread_lock)); + } + sc->info_video->is_firstframe = FALSE; + sc->info_video->base_video_ts = GST_BUFFER_PTS(buffer); + } + } + GST_BUFFER_PTS(buffer) = GST_BUFFER_PTS(buffer) - sc->info_video->base_video_ts; + GST_BUFFER_DTS(buffer) = GST_BUFFER_PTS(buffer); + + /*_mmcam_dbg_log("buffer %p, timestamp %"GST_TIME_FORMAT, buffer, GST_TIME_ARGS(GST_BUFFER_PTS(buffer)));*/ + + if (0) { + GstCaps *caps = gst_pad_get_current_caps(pad); + if (caps) { + char *caps_string = gst_caps_to_string(caps); + if (caps_string) { + _mmcam_dbg_log("%s", caps_string); + free(caps_string); + caps_string = NULL; + } + gst_caps_unref(caps); + caps = NULL; + } else { + _mmcam_dbg_warn("failed to get caps from pad"); + } } g_signal_emit_by_name(sc->encode_element[_MMCAMCORDER_ENCSINK_SRC].gst, "push-buffer", buffer, &ret); @@ -1681,22 +1803,21 @@ static gboolean __mmcamcorder_video_dataprobe_push_buffer_to_record(GstPad *pad, } /* skip display if too fast FPS */ - if (sc->info_video ) { - if (sc->info_video->fps > _MMCAMCORDER_FRAME_PASS_MIN_FPS) { - if (sc->info_video->prev_preview_ts != 0) { - diff = GST_BUFFER_TIMESTAMP(buffer) - sc->info_video->prev_preview_ts; - if (diff < _MMCAMCORDER_MIN_TIME_TO_PASS_FRAME) { - return FALSE; - } + if (sc->info_video && sc->info_video->fps > _MMCAMCORDER_FRAME_PASS_MIN_FPS) { + if (sc->info_video->prev_preview_ts != 0) { + diff = GST_BUFFER_PTS(buffer) - sc->info_video->prev_preview_ts; + if (diff < _MMCAMCORDER_MIN_TIME_TO_PASS_FRAME) { + _mmcam_dbg_log("it's too fast. drop frame..."); + return GST_PAD_PROBE_DROP; } } /*_mmcam_dbg_log("diff %llu", diff);*/ - sc->info_video->prev_preview_ts = GST_BUFFER_TIMESTAMP(buffer); + sc->info_video->prev_preview_ts = GST_BUFFER_PTS(buffer); } - return TRUE; + return GST_PAD_PROBE_OK; } @@ -1964,6 +2085,10 @@ bool _mmcamcorder_set_display_rotation(MMHandleType handle, int display_rotate) if (sc->element[_MMCAMCORDER_VIDEOSINK_SINK].gst) { /* Get videosink name */ _mmcamcorder_conf_get_value_element_name(sc->VideosinkElement, &videosink_name); + if (videosink_name == NULL) { + _mmcam_dbg_err("Please check videosink element in configuration file"); + return FALSE; + } if (!strcmp(videosink_name, "xvimagesink") || !strcmp(videosink_name, "evasimagesink") || !strcmp(videosink_name, "evaspixmapsink")) { MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_SINK].gst, @@ -1998,6 +2123,10 @@ bool _mmcamcorder_set_display_flip(MMHandleType handle, int display_flip) if (sc->element[_MMCAMCORDER_VIDEOSINK_SINK].gst) { /* Get videosink name */ _mmcamcorder_conf_get_value_element_name(sc->VideosinkElement, &videosink_name); + if (videosink_name == NULL) { + _mmcam_dbg_err("Please check videosink element in configuration file"); + return FALSE; + } if (!strcmp(videosink_name, "xvimagesink") || !strcmp(videosink_name, "evasimagesink") || !strcmp(videosink_name, "evaspixmapsink")) { MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_SINK].gst, @@ -2156,7 +2285,7 @@ bool _mmcamcorder_set_videosrc_caps(MMHandleType handle, unsigned int fourcc, in int caps_fps = 0; int caps_rotate = 0; - gst_structure_get_fourcc(structure, "format", &caps_fourcc); + caps_fourcc = _mmcamcorder_convert_fourcc_string_to_value(gst_structure_get_string(structure, "format")); gst_structure_get_int(structure, "width", &caps_width); gst_structure_get_int(structure, "height", &caps_height); gst_structure_get_int(structure, "fps", &caps_fps); @@ -2188,19 +2317,31 @@ bool _mmcamcorder_set_videosrc_caps(MMHandleType handle, unsigned int fourcc, in } if (do_set_caps) { - caps = gst_caps_new_simple("video/x-raw-yuv", - "format", GST_TYPE_FOURCC, fourcc, - "width", G_TYPE_INT, set_width, - "height", G_TYPE_INT, set_height, - "framerate", GST_TYPE_FRACTION, fps, 1, - "rotate", G_TYPE_INT, set_rotate, - NULL); - MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_FILT].gst, "caps", caps); + char fourcc_string[sizeof(fourcc)+1]; + strncpy(fourcc_string, (char*)&fourcc, sizeof(fourcc)); + fourcc_string[sizeof(fourcc)] = '\0'; + + if (sc->info_image->preview_format == MM_PIXEL_FORMAT_ENCODED_H264) { + caps = gst_caps_new_simple("video/x-h264", + "width", G_TYPE_INT, set_width, + "height", G_TYPE_INT, set_height, + "framerate", GST_TYPE_FRACTION, fps, 1, + "stream-format", G_TYPE_STRING, "byte-stream", + NULL); + } else { + caps = gst_caps_new_simple("video/x-raw", + "format", G_TYPE_STRING, fourcc_string, + "width", G_TYPE_INT, set_width, + "height", G_TYPE_INT, set_height, + "framerate", GST_TYPE_FRACTION, fps, 1, + "rotate", G_TYPE_INT, set_rotate, + NULL); + } + + _mmcam_dbg_log("vidoesrc new caps set. %"GST_PTR_FORMAT, caps); + MMCAMCORDER_G_OBJECT_SET_POINTER(sc->element[_MMCAMCORDER_VIDEOSRC_FILT].gst, "caps", caps); gst_caps_unref(caps); caps = NULL; - _mmcam_dbg_log("vidoesrc new caps set. [%c%c%c%c %dx%d, fps %d, rotate %d]", - (sc->fourcc), (sc->fourcc)>>8, (sc->fourcc)>>16, (sc->fourcc)>>24, - set_width, set_height, fps, set_rotate); } if (hcamcorder->type != MM_CAMCORDER_MODE_AUDIO) { @@ -2380,3 +2521,184 @@ bool _mmcamcorder_set_camera_resolution(MMHandleType handle, int width, int heig return _mmcamcorder_set_videosrc_caps(handle, sc->fourcc, width, height, fps, sc->videosrc_rotate); } +bool _mmcamcorder_set_encoded_preview_bitrate(MMHandleType handle, int bitrate) +{ + _MMCamcorderSubContext *sc = NULL; + GstCameraControl *CameraControl = NULL; + GstCameraControlChannel *CameraControlChannel = NULL; + const GList *controls = NULL; + const GList *item = NULL; + + if ((void *)handle == NULL) { + _mmcam_dbg_warn("handle is NULL"); + return FALSE; + } + + sc = MMF_CAMCORDER_SUBCONTEXT(handle); + if (!sc) { + _mmcam_dbg_warn("subcontext is NULL"); + return FALSE; + } + + if (sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst == NULL) { + _mmcam_dbg_warn("videosrc plugin is NULL"); + return FALSE; + } + + _mmcam_dbg_log("set encoded preview bitrate : %d bps", bitrate); + + CameraControl = GST_CAMERA_CONTROL(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst); + controls = gst_camera_control_list_channels(CameraControl); + _mmcam_dbg_log("controls : 0x%x", controls); + if (controls != NULL) { + _mmcam_dbg_log("controls : 0x%x", controls); + for (item = controls ; item && item->data ; item = item->next) { + CameraControlChannel = item->data; + _mmcam_dbg_log("item : %d", item); + if (!strcmp(CameraControlChannel->label, "bitrate")) { + _mmcam_dbg_log("set encoded preview bitrate %d", bitrate); + return gst_camera_control_set_value(CameraControl, CameraControlChannel, bitrate); + } + } + _mmcam_dbg_log("item : %d", item); + if (item == NULL) { + _mmcam_dbg_warn("failed to find \"bitrate\" control channel"); + } + } + _mmcam_dbg_log("item : %d", item); + + return FALSE; +} + + +bool _mmcamcorder_set_encoded_preview_iframe_interval(MMHandleType handle, int interval) +{ + _MMCamcorderSubContext *sc = NULL; + + if ((void *)handle == NULL) { + _mmcam_dbg_warn("handle is NULL"); + return FALSE; + } + + sc = MMF_CAMCORDER_SUBCONTEXT(handle); + if (!sc) { + _mmcam_dbg_warn("subcontext is NULL"); + return FALSE; + } + + if (sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst == NULL) { + _mmcam_dbg_warn("videosrc plugin is NULL"); + return FALSE; + } + + _mmcam_dbg_log("set encoded preview I-frame interval : %d ms", interval); + + MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst, "newgop-interval", interval); + + return TRUE; +} + + +bool _mmcamcorder_recreate_decoder_for_encoded_preview(MMHandleType handle) +{ + int ret = MM_ERROR_NONE; + int device_scaler = 0; + _MMCamcorderSubContext *sc = NULL; + char decoder_name[20] = {'\0',}; + + if ((void *)handle == NULL) { + _mmcam_dbg_warn("handle is NULL"); + return FALSE; + } + + sc = MMF_CAMCORDER_SUBCONTEXT(handle); + if (!sc) { + _mmcam_dbg_warn("subcontext is NULL"); + return FALSE; + } + + if (sc->element[_MMCAMCORDER_MAIN_PIPE].gst == NULL || + sc->element[_MMCAMCORDER_VIDEOSRC_DECODE].gst == NULL) { + _mmcam_dbg_warn("main pipeline or decoder plugin is NULL"); + return FALSE; + } + + _mmcam_dbg_log("start"); + + /* set state as NULL */ + ret = _mmcamcorder_gst_set_state(handle, sc->element[_MMCAMCORDER_VIDEOSRC_DECODE].gst, GST_STATE_NULL); + if (ret != MM_ERROR_NONE) { + _mmcam_dbg_err("failed to set NULL to decoder"); + return FALSE; + } + + /* remove decoder - pads will be unlinked automatically in remove function */ + if (!gst_bin_remove(GST_BIN(sc->element[_MMCAMCORDER_MAIN_PIPE].gst), + sc->element[_MMCAMCORDER_VIDEOSRC_DECODE].gst)) { + _mmcam_dbg_err("failed to remove decoder from pipeline"); + return FALSE; + } + + /* check decoder element */ + if (sc->element[_MMCAMCORDER_VIDEOSRC_DECODE].gst) { + _mmcam_dbg_log("decoder[%p] is still alive - ref count %d", + G_OBJECT(sc->element[_MMCAMCORDER_VIDEOSRC_DECODE].gst), + ((GObject *)sc->element[_MMCAMCORDER_VIDEOSRC_DECODE].gst)->ref_count); + } + + /* get decoder name */ + mm_camcorder_get_attributes(handle, NULL, + MMCAM_DISPLAY_SCALER, &device_scaler, + NULL); + + snprintf(decoder_name, sizeof(decoder_name)-1, "%s%d", _MMCAMCORDER_VIDEO_DECODER_NAME_PREFIX, device_scaler); + + _mmcam_dbg_log("decoder name [%s]", decoder_name); + + /* create decoder */ + sc->element[_MMCAMCORDER_VIDEOSRC_DECODE].gst = gst_element_factory_make(decoder_name, "videosrc_decode"); + if (sc->element[_MMCAMCORDER_VIDEOSRC_DECODE].gst == NULL) { + _mmcam_dbg_err("Decoder[%s] creation fail", decoder_name); + return FALSE; + } + + sc->element[_MMCAMCORDER_VIDEOSRC_DECODE].id = _MMCAMCORDER_VIDEOSRC_DECODE; + g_object_weak_ref(G_OBJECT(sc->element[_MMCAMCORDER_VIDEOSRC_DECODE].gst), + (GWeakNotify)_mmcamcorder_element_release_noti, sc); + + /* add to pipeline */ + if (!gst_bin_add(GST_BIN(sc->element[_MMCAMCORDER_MAIN_PIPE].gst), + sc->element[_MMCAMCORDER_VIDEOSRC_DECODE].gst)) { + _mmcam_dbg_err("failed to add decoder to pipeline"); + gst_object_unref(sc->element[_MMCAMCORDER_VIDEOSRC_DECODE].gst); + return FALSE; + } + + /* link */ + if (_MM_GST_ELEMENT_LINK(GST_ELEMENT(sc->element[_MMCAMCORDER_VIDEOSRC_QUE].gst), + GST_ELEMENT(sc->element[_MMCAMCORDER_VIDEOSRC_DECODE].gst))) { + _mmcam_dbg_log("Link videosrc_queue to decoder OK"); + } else { + _mmcam_dbg_err("Link videosrc_queue to decoder FAILED"); + return FALSE; + } + + if (_MM_GST_ELEMENT_LINK(GST_ELEMENT(sc->element[_MMCAMCORDER_VIDEOSRC_DECODE].gst), + GST_ELEMENT(sc->element[_MMCAMCORDER_VIDEOSINK_QUE].gst))) { + _mmcam_dbg_log("Link decoder to videosink_queue OK"); + } else { + _mmcam_dbg_err("Link decoder to videosink_queue FAILED"); + return FALSE; + } + + /* set state READY */ + ret = _mmcamcorder_gst_set_state(handle, sc->element[_MMCAMCORDER_VIDEOSRC_DECODE].gst, GST_STATE_READY); + if (ret != MM_ERROR_NONE) { + _mmcam_dbg_err("failed to set READY to decoder"); + return FALSE; + } + + _mmcam_dbg_log("done"); + + return TRUE; +} diff --git a/src/mm_camcorder_internal.c b/src/mm_camcorder_internal.c index 62499d0..2748bd2 100644 --- a/src/mm_camcorder_internal.c +++ b/src/mm_camcorder_internal.c @@ -28,24 +28,31 @@ #include #include #include +#include #include #include "mm_camcorder_internal.h" #include -#include -#include +#include +#include #include #include #include #include -#include +#include /*--------------------------------------------------------------------------------------- | GLOBAL VARIABLE DEFINITIONS for internal | ---------------------------------------------------------------------------------------*/ +int g_mm_camcorder_type = -255; +struct sigaction mm_camcorder_int_old_action; +struct sigaction mm_camcorder_abrt_old_action; +struct sigaction mm_camcorder_segv_old_action; +struct sigaction mm_camcorder_term_old_action; +struct sigaction mm_camcorder_sys_old_action; /*--------------------------------------------------------------------------------------- | LOCAL VARIABLE DEFINITIONS for internal | @@ -58,15 +65,6 @@ #define __MMCAMCORDER_PATH_CAMERA_RESOURCE "/usr/share/sounds/mm-camcorder/camera_resource" #define __MMCAMCORDER_PATH_RECORDER_RESOURCE "/usr/share/sounds/mm-camcorder/recorder_resource" -#define SAFE_G_MUTEX_FREE(x) \ - if (x) {\ - g_mutex_free(x); \ - } - -#define SAFE_G_COND_FREE(x) \ - if (x) {\ - g_cond_free(x); \ - } /*--------------------------------------------------------------------------------------- | LOCAL FUNCTION PROTOTYPES: | @@ -92,6 +90,9 @@ ASM_cb_result_t _mmcamcorder_asm_callback(int handle, ASM_event_sources_t event_ static gboolean __mmcamcorder_set_attr_to_camsensor_cb(gpointer data); #endif /* _MMCAMCORDER_USE_SET_ATTR_CB */ +static void __mm_camcorder_signal_handler(int signo); +static void _mmcamcorder_constructor() __attribute__((constructor)); + /*======================================================================================= | FUNCTION DEFINITIONS | =======================================================================================*/ @@ -99,6 +100,100 @@ static gboolean __mmcamcorder_set_attr_to_camsensor_cb(gpointer data); | GLOBAL FUNCTION DEFINITIONS: | ---------------------------------------------------------------------------------------*/ +static void __mm_camcorder_signal_handler(int signo) +{ + pid_t my_pid = getpid(); + pid_t vconf_recorder_pid = -1; + pid_t vconf_camera_pid = -1; + int vconf_flash_state = VCONFKEY_CAMERA_FLASH_STATE_OFF; + + _mmcam_dbg_warn("start - signo [%d], pid [%d], device type [%d]", signo, my_pid, g_mm_camcorder_type); + + /* reset vconf key */ + switch (g_mm_camcorder_type) { + case MM_VIDEO_DEVICE_NONE: + vconf_get_int(VCONFKEY_RECORDER_PID, (int *)&vconf_recorder_pid); + if (my_pid == vconf_recorder_pid) { + vconf_set_int(VCONFKEY_RECORDER_STATE, VCONFKEY_RECORDER_STATE_NULL); + vconf_set_int(VCONFKEY_RECORDER_PID, -1); + _mmcam_dbg_warn("set recorder state NULL"); + } else { + _mmcam_dbg_warn("different pid : my[%d] vconf[%d]", my_pid, vconf_recorder_pid); + } + break; + case MM_VIDEO_DEVICE_CAMERA0: + case MM_VIDEO_DEVICE_CAMERA1: + vconf_get_int(VCONFKEY_CAMERA_FLASH_STATE, &vconf_flash_state); + vconf_get_int(VCONFKEY_CAMERA_PID, (int *)&vconf_camera_pid); + if (my_pid == vconf_camera_pid && + vconf_flash_state == VCONFKEY_CAMERA_FLASH_STATE_ON) { + vconf_set_int(VCONFKEY_CAMERA_FLASH_STATE, VCONFKEY_CAMERA_FLASH_STATE_OFF); + vconf_set_int(VCONFKEY_CAMERA_PID, -1); + _mmcam_dbg_warn("set camera flash state OFF"); + } + + vconf_set_int(VCONFKEY_CAMERA_STATE, VCONFKEY_CAMERA_STATE_NULL); + _mmcam_dbg_warn("set camera state NULL"); + break; + default: + _mmcam_dbg_warn("unknown type [%d]", g_mm_camcorder_type); + break; + } + + /* call old signal handler */ + switch (signo) { + case SIGINT: + sigaction(SIGINT, &mm_camcorder_int_old_action, NULL); + raise(signo); + break; + case SIGABRT: + sigaction(SIGABRT, &mm_camcorder_abrt_old_action, NULL); + raise(signo); + break; + case SIGSEGV: + sigaction(SIGSEGV, &mm_camcorder_segv_old_action, NULL); + raise(signo); + break; + case SIGTERM: + sigaction(SIGTERM, &mm_camcorder_term_old_action, NULL); + raise(signo); + break; + case SIGSYS: + sigaction(SIGSYS, &mm_camcorder_sys_old_action, NULL); + raise(signo); + break; + default: + break; + } + + _mmcam_dbg_warn("done"); + + return; +} + + +static void _mmcamcorder_constructor() +{ + struct sigaction mm_camcorder_action; + mm_camcorder_action.sa_handler = __mm_camcorder_signal_handler; + mm_camcorder_action.sa_flags = SA_NOCLDSTOP; + + _mmcam_dbg_warn("start"); + + sigemptyset(&mm_camcorder_action.sa_mask); + + sigaction(SIGINT, &mm_camcorder_action, &mm_camcorder_int_old_action); + sigaction(SIGABRT, &mm_camcorder_action, &mm_camcorder_abrt_old_action); + sigaction(SIGSEGV, &mm_camcorder_action, &mm_camcorder_segv_old_action); + sigaction(SIGTERM, &mm_camcorder_action, &mm_camcorder_term_old_action); + sigaction(SIGSYS, &mm_camcorder_action, &mm_camcorder_sys_old_action); + + _mmcam_dbg_warn("done"); + + return; +} + + /* Internal command functions {*/ int _mmcamcorder_create(MMHandleType *handle, MMCamPreset *info) { @@ -118,6 +213,7 @@ int _mmcamcorder_create(MMHandleType *handle, MMCamPreset *info) mmf_camcorder_t *hcamcorder = NULL; ASM_resource_t mm_resource = ASM_RESOURCE_NONE; type_element *EvasSurfaceElement = NULL; + char err_msg[MAX_ERROR_MESSAGE_LEN] = {'\0',}; _mmcam_dbg_log("Entered"); @@ -138,23 +234,18 @@ int _mmcamcorder_create(MMHandleType *handle, MMCamPreset *info) hcamcorder->asm_session_type = MM_SESSION_TYPE_RECORD_VIDEO; hcamcorder->asm_handle = -1; - /* thread - for g_mutex_new() */ - if (!g_thread_supported()) { - g_thread_init(NULL); - } - - (hcamcorder->mtsafe).lock = g_mutex_new(); - (hcamcorder->mtsafe).cond = g_cond_new(); - - (hcamcorder->mtsafe).cmd_lock = g_mutex_new(); - (hcamcorder->mtsafe).asm_lock = g_mutex_new(); - (hcamcorder->mtsafe).state_lock = g_mutex_new(); - (hcamcorder->mtsafe).gst_state_lock = g_mutex_new(); - (hcamcorder->mtsafe).gst_encode_state_lock = g_mutex_new(); - (hcamcorder->mtsafe).message_cb_lock = g_mutex_new(); - (hcamcorder->mtsafe).vcapture_cb_lock = g_mutex_new(); - (hcamcorder->mtsafe).vstream_cb_lock = g_mutex_new(); - (hcamcorder->mtsafe).astream_cb_lock = g_mutex_new(); + pthread_mutex_init(&((hcamcorder->mtsafe).lock), NULL); + pthread_cond_init(&((hcamcorder->mtsafe).cond), NULL); + pthread_mutex_init(&((hcamcorder->mtsafe).cmd_lock), NULL); + pthread_cond_init(&((hcamcorder->mtsafe).cmd_cond), NULL); + pthread_mutex_init(&((hcamcorder->mtsafe).asm_lock), NULL); + pthread_mutex_init(&((hcamcorder->mtsafe).state_lock), NULL); + pthread_mutex_init(&((hcamcorder->mtsafe).gst_state_lock), NULL); + pthread_mutex_init(&((hcamcorder->mtsafe).gst_encode_state_lock), NULL); + pthread_mutex_init(&((hcamcorder->mtsafe).message_cb_lock), NULL); + pthread_mutex_init(&((hcamcorder->mtsafe).vcapture_cb_lock), NULL); + pthread_mutex_init(&((hcamcorder->mtsafe).vstream_cb_lock), NULL); + pthread_mutex_init(&((hcamcorder->mtsafe).astream_cb_lock), NULL); pthread_mutex_init(&(hcamcorder->sound_lock), NULL); pthread_cond_init(&(hcamcorder->sound_cond), NULL); @@ -170,7 +261,13 @@ int _mmcamcorder_create(MMHandleType *handle, MMCamPreset *info) hcamcorder->task_thread_state = _MMCAMCORDER_SOUND_STATE_NONE; /* create task thread */ - pthread_create(&(hcamcorder->task_thread), NULL, _mmcamcorder_util_task_thread_func, (void *)hcamcorder); + pthread_create(&(hcamcorder->task_thread), NULL, _mmcamcorder_task_thread_func, (void *)hcamcorder); + + /* get root directory */ + ret = _mmcamcorder_get_root_directory(&hcamcorder->root_directory); + if (ret != MM_ERROR_NONE) { + goto _ERR_DEFAULT_VALUE_INIT; + } if (info->videodev_type < MM_VIDEO_DEVICE_NONE || info->videodev_type >= MM_VIDEO_DEVICE_NUM) { @@ -190,7 +287,8 @@ int _mmcamcorder_create(MMHandleType *handle, MMCamPreset *info) } if (resource_fd < 0) { - _mmcam_dbg_log("open error %s : cur %d",strerror(errno),errno); + strerror_r(errno, err_msg, MAX_ERROR_MESSAGE_LEN); + _mmcam_dbg_log("open error %s : cur %d",err_msg,errno); if(errno == EPERM || errno == EACCES) { ret = MM_ERROR_COMMON_INVALID_PERMISSION; } else { @@ -225,7 +323,8 @@ int _mmcamcorder_create(MMHandleType *handle, MMCamPreset *info) if (hcamcorder->asm_session_type == MM_SESSION_TYPE_RECORD_VIDEO || hcamcorder->asm_session_type == MM_SESSION_TYPE_RECORD_AUDIO || hcamcorder->asm_session_type == MM_SESSION_TYPE_CALL || - hcamcorder->asm_session_type == MM_SESSION_TYPE_VIDEOCALL) { + hcamcorder->asm_session_type == MM_SESSION_TYPE_VIDEOCALL || + hcamcorder->asm_session_type == MM_SESSION_TYPE_VOIP) { hcamcorder->asm_register = _MMCamcorder_ASM_NO_NEED_REGISTER; if (hcamcorder->asm_session_type == MM_SESSION_TYPE_RECORD_AUDIO) { hcamcorder->asm_event_type = ASM_EVENT_MMCAMCORDER_AUDIO; @@ -285,7 +384,12 @@ int _mmcamcorder_create(MMHandleType *handle, MMCamPreset *info) _mmcamcorder_conf_get_value_int(hcamcorder->conf_main, CONFIGURE_CATEGORY_MAIN_VIDEO_INPUT, "UseConfCtrl", &UseConfCtrl); + if (UseConfCtrl) { + int resolution_width = 0; + int resolution_height = 0; + MMCamAttrsInfo fps_info; + _mmcam_dbg_log( "Enable Configure Control system." ); switch (info->videodev_type) { @@ -321,11 +425,15 @@ int _mmcamcorder_create(MMHandleType *handle, MMCamPreset *info) ret = _mmcamcorder_init_convert_table((MMHandleType)hcamcorder); if (ret != MM_ERROR_NONE) { _mmcam_dbg_warn("converting table initialize error!!"); + ret = MM_ERROR_CAMCORDER_INTERNAL; + goto _ERR_ALLOC_ATTRIBUTE; } - ret = _mmcamcorder_init_attr_from_configure((MMHandleType)hcamcorder); + ret = _mmcamcorder_init_attr_from_configure((MMHandleType)hcamcorder, info->videodev_type); if (ret != MM_ERROR_NONE) { _mmcam_dbg_warn("converting table initialize error!!"); + ret = MM_ERROR_CAMCORDER_INTERNAL; + goto _ERR_ALLOC_ATTRIBUTE; } /* Get device info, recommend preview fmt and display rotation from INI */ @@ -386,8 +494,16 @@ int _mmcamcorder_create(MMHandleType *handle, MMCamPreset *info) "SupportMediaPacketPreviewCb", &(hcamcorder->support_media_packet_preview_cb)); + ret = mm_camcorder_get_attributes((MMHandleType)hcamcorder, NULL, + MMCAM_CAMERA_WIDTH, &resolution_width, + MMCAM_CAMERA_HEIGHT, &resolution_height, + NULL); + + mm_camcorder_get_fps_list_by_resolution((MMHandleType)hcamcorder, resolution_width, resolution_height, &fps_info); + _mmcam_dbg_log("UseZeroCopyFormat : %d", hcamcorder->use_zero_copy_format); _mmcam_dbg_log("SupportMediaPacketPreviewCb : %d", hcamcorder->support_media_packet_preview_cb); + _mmcam_dbg_log("res : %d X %d, Default FPS by resolution : %d", resolution_width, resolution_height, fps_info.int_array.def); if (camera_facing_direction == 1) { if (rcmd_dpy_rotation == MM_DISPLAY_ROTATION_270 || rcmd_dpy_rotation == MM_DISPLAY_ROTATION_90) { @@ -407,6 +523,7 @@ int _mmcamcorder_create(MMHandleType *handle, MMCamPreset *info) MMCAM_SUPPORT_ZSL_CAPTURE, hcamcorder->support_zsl_capture, MMCAM_SUPPORT_ZERO_COPY_FORMAT, hcamcorder->use_zero_copy_format, MMCAM_SUPPORT_MEDIA_PACKET_PREVIEW_CB, hcamcorder->support_media_packet_preview_cb, + MMCAM_CAMERA_FPS, fps_info.int_array.def, MMCAM_DISPLAY_FLIP, camera_default_flip, "capture-sound-enable", play_capture_sound, NULL); @@ -414,6 +531,8 @@ int _mmcamcorder_create(MMHandleType *handle, MMCamPreset *info) _mmcam_dbg_err("Set %s FAILED.", err_attr_name); free(err_attr_name); err_attr_name = NULL; + ret = MM_ERROR_CAMCORDER_INTERNAL; + goto _ERR_ALLOC_ATTRIBUTE; } /* Get default value of brightness */ @@ -424,6 +543,8 @@ int _mmcamcorder_create(MMHandleType *handle, MMCamPreset *info) _mmcam_dbg_err("Get brightness FAILED."); free(err_attr_name); err_attr_name = NULL; + ret = MM_ERROR_CAMCORDER_INTERNAL; + goto _ERR_ALLOC_ATTRIBUTE; } _mmcam_dbg_log("Default brightness : %d", hcamcorder->brightness_default); } else { @@ -442,10 +563,23 @@ int _mmcamcorder_create(MMHandleType *handle, MMCamPreset *info) _mmcam_dbg_err("Set %s FAILED.", err_attr_name); free(err_attr_name); err_attr_name = NULL; + ret = MM_ERROR_CAMCORDER_INTERNAL; + goto _ERR_ALLOC_ATTRIBUTE; + } + + ret = _mmcamcorder_init_attr_from_configure((MMHandleType)hcamcorder, info->videodev_type); + if (ret != MM_ERROR_NONE) { + _mmcam_dbg_warn("converting table initialize error!!"); + ret = MM_ERROR_CAMCORDER_INTERNAL; + goto _ERR_ALLOC_ATTRIBUTE; } } + traceBegin(TTRACE_TAG_CAMERA, "MMCAMCORDER:CREATE:INIT_GSTREAMER"); ret = __mmcamcorder_gstreamer_init(hcamcorder->conf_main); + + traceEnd(TTRACE_TAG_CAMERA); + if (!ret) { _mmcam_dbg_err( "Failed to initialize gstreamer!!" ); ret = MM_ERROR_CAMCORDER_NOT_INITIALIZED; @@ -483,16 +617,19 @@ int _mmcamcorder_create(MMHandleType *handle, MMCamPreset *info) _mmcam_dbg_log("current shutter sound policy : %d", hcamcorder->shutter_sound_policy); /* get model name */ - system_info_get_value_string(SYSTEM_INFO_KEY_MODEL, &hcamcorder->model_name); + system_info_get_platform_string("http://tizen.org/system/model_name", &hcamcorder->model_name); /* get software version */ - system_info_get_value_string(SYSTEM_INFO_KEY_BUILD_STRING, &hcamcorder->software_version); + system_info_get_platform_string("http://tizen.org/system/build.string", &hcamcorder->software_version); /* Set initial state */ _mmcamcorder_set_state((MMHandleType)hcamcorder, MM_CAMCORDER_STATE_NULL); _mmcam_dbg_log("created handle %p", hcamcorder); + /* set device type */ + g_mm_camcorder_type = info->videodev_type; + *handle = (MMHandleType)hcamcorder; return MM_ERROR_NONE; @@ -519,17 +656,18 @@ _ERR_AUDIO_BLOCKED: _ERR_DEFAULT_VALUE_INIT: /* Release lock, cond */ - SAFE_G_MUTEX_FREE((hcamcorder->mtsafe).lock); - SAFE_G_COND_FREE((hcamcorder->mtsafe).cond); - SAFE_G_MUTEX_FREE((hcamcorder->mtsafe).cmd_lock); - SAFE_G_MUTEX_FREE((hcamcorder->mtsafe).asm_lock); - SAFE_G_MUTEX_FREE((hcamcorder->mtsafe).state_lock); - SAFE_G_MUTEX_FREE((hcamcorder->mtsafe).gst_state_lock); - SAFE_G_MUTEX_FREE((hcamcorder->mtsafe).gst_encode_state_lock); - SAFE_G_MUTEX_FREE((hcamcorder->mtsafe).message_cb_lock); - SAFE_G_MUTEX_FREE((hcamcorder->mtsafe).vcapture_cb_lock); - SAFE_G_MUTEX_FREE((hcamcorder->mtsafe).vstream_cb_lock); - SAFE_G_MUTEX_FREE((hcamcorder->mtsafe).astream_cb_lock); + pthread_mutex_destroy(&((hcamcorder->mtsafe).lock)); + pthread_cond_destroy(&((hcamcorder->mtsafe).cond)); + pthread_mutex_destroy(&((hcamcorder->mtsafe).cmd_lock)); + pthread_cond_destroy(&((hcamcorder->mtsafe).cmd_cond)); + pthread_mutex_destroy(&((hcamcorder->mtsafe).asm_lock)); + pthread_mutex_destroy(&((hcamcorder->mtsafe).state_lock)); + pthread_mutex_destroy(&((hcamcorder->mtsafe).gst_state_lock)); + pthread_mutex_destroy(&((hcamcorder->mtsafe).gst_encode_state_lock)); + pthread_mutex_destroy(&((hcamcorder->mtsafe).message_cb_lock)); + pthread_mutex_destroy(&((hcamcorder->mtsafe).vcapture_cb_lock)); + pthread_mutex_destroy(&((hcamcorder->mtsafe).vstream_cb_lock)); + pthread_mutex_destroy(&((hcamcorder->mtsafe).astream_cb_lock)); pthread_mutex_destroy(&(hcamcorder->sound_lock)); pthread_cond_destroy(&(hcamcorder->sound_cond)); @@ -650,6 +788,29 @@ int _mmcamcorder_destroy(MMHandleType handle) hcamcorder->setting_event_id = 0; } + /* check current strobe mode */ + if (hcamcorder->type != MM_CAMCORDER_MODE_AUDIO) { + pid_t my_pid = getpid(); + int camera_pid = -1; + vconf_get_int(VCONFKEY_CAMERA_PID, &camera_pid); + + if (camera_pid > -1 && my_pid == camera_pid) { + int strobe_mode = MM_CAMCORDER_STROBE_MODE_OFF; + + vconf_set_int(VCONFKEY_CAMERA_PID, -1); + _mmcam_dbg_log("reset camera pid"); + + mm_camcorder_get_attributes(handle, NULL, + MMCAM_STROBE_MODE, &strobe_mode, + NULL); + if (strobe_mode != MM_CAMCORDER_STROBE_MODE_OFF) { + /* set OFF state of vconf key */ + vconf_set_int(VCONFKEY_CAMERA_FLASH_STATE, VCONFKEY_CAMERA_FLASH_STATE_OFF); + _mmcam_dbg_log("reset flash state"); + } + } + } + /* Remove attributes */ if (hcamcorder->attributes) { _mmcamcorder_dealloc_attribute(hcamcorder->attributes); @@ -672,7 +833,7 @@ int _mmcamcorder_destroy(MMHandleType handle) } /* Remove messages which are not called yet */ - _mmcamcroder_remove_message_all(handle); + _mmcamcorder_remove_message_all(handle); if (hcamcorder->asm_register) { /* Unregister ASM */ @@ -709,17 +870,18 @@ int _mmcamcorder_destroy(MMHandleType handle) _MMCAMCORDER_UNLOCK_CMD(hcamcorder); /* Release lock, cond */ - SAFE_G_MUTEX_FREE((hcamcorder->mtsafe).lock); - SAFE_G_COND_FREE((hcamcorder->mtsafe).cond); - SAFE_G_MUTEX_FREE((hcamcorder->mtsafe).cmd_lock); - SAFE_G_MUTEX_FREE((hcamcorder->mtsafe).asm_lock); - SAFE_G_MUTEX_FREE((hcamcorder->mtsafe).state_lock); - SAFE_G_MUTEX_FREE((hcamcorder->mtsafe).gst_state_lock); - SAFE_G_MUTEX_FREE((hcamcorder->mtsafe).gst_encode_state_lock); - SAFE_G_MUTEX_FREE((hcamcorder->mtsafe).message_cb_lock); - SAFE_G_MUTEX_FREE((hcamcorder->mtsafe).vcapture_cb_lock); - SAFE_G_MUTEX_FREE((hcamcorder->mtsafe).vstream_cb_lock); - SAFE_G_MUTEX_FREE((hcamcorder->mtsafe).astream_cb_lock); + pthread_mutex_destroy(&((hcamcorder->mtsafe).lock)); + pthread_cond_destroy(&((hcamcorder->mtsafe).cond)); + pthread_mutex_destroy(&((hcamcorder->mtsafe).cmd_lock)); + pthread_cond_destroy(&((hcamcorder->mtsafe).cmd_cond)); + pthread_mutex_destroy(&((hcamcorder->mtsafe).asm_lock)); + pthread_mutex_destroy(&((hcamcorder->mtsafe).state_lock)); + pthread_mutex_destroy(&((hcamcorder->mtsafe).gst_state_lock)); + pthread_mutex_destroy(&((hcamcorder->mtsafe).gst_encode_state_lock)); + pthread_mutex_destroy(&((hcamcorder->mtsafe).message_cb_lock)); + pthread_mutex_destroy(&((hcamcorder->mtsafe).vcapture_cb_lock)); + pthread_mutex_destroy(&((hcamcorder->mtsafe).vstream_cb_lock)); + pthread_mutex_destroy(&((hcamcorder->mtsafe).astream_cb_lock)); pthread_mutex_destroy(&(hcamcorder->sound_lock)); pthread_cond_destroy(&(hcamcorder->sound_cond)); @@ -729,6 +891,12 @@ int _mmcamcorder_destroy(MMHandleType handle) pthread_mutex_destroy(&(hcamcorder->task_thread_lock)); pthread_cond_destroy(&(hcamcorder->task_thread_cond)); + /* Release external root directory string */ + if (hcamcorder->root_directory) { + free(hcamcorder->root_directory); + hcamcorder->root_directory = NULL; + } + /* Release handle */ memset(hcamcorder, 0x00, sizeof(mmf_camcorder_t)); free(hcamcorder); @@ -756,10 +924,12 @@ int _mmcamcorder_realize(MMHandleType handle) int state_FROM = MM_CAMCORDER_STATE_NULL; int state_TO = MM_CAMCORDER_STATE_READY; int errorcode = MM_ERROR_NONE; + ASM_resource_t mm_resource = ASM_RESOURCE_NONE; int display_surface_type = MM_DISPLAY_SURFACE_X; double motion_rate = _MMCAMCORDER_DEFAULT_RECORDING_MOTION_RATE; char *videosink_element_type = NULL; const char *videosink_name = NULL; + char err_msg[MAX_ERROR_MESSAGE_LEN] = {'\0',}; mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle); @@ -791,38 +961,6 @@ int _mmcamcorder_realize(MMHandleType handle) /* Get profile mode */ _mmcam_dbg_log("Profile mode [%d]", hcamcorder->type); - /* set camera state to vconf key */ - if (hcamcorder->type != MM_CAMCORDER_MODE_AUDIO) { - int vconf_camera_state = 0; - - /* get current camera state of vconf key */ - vconf_get_int(VCONFKEY_CAMERA_STATE, &vconf_camera_state); - if (vconf_set_int(VCONFKEY_CAMERA_STATE, VCONFKEY_CAMERA_STATE_OPEN)) { - _mmcam_dbg_log("VCONF ERROR %s : cur %d",strerror(errno),errno); - if(errno == EPERM || errno == EACCES) { - ret = MM_ERROR_COMMON_INVALID_PERMISSION; - goto _ERR_CAMCORDER_CMD_PRECON_AFTER_LOCK; - } - } - _mmcam_dbg_log("VCONFKEY_CAMERA_STATE prev %d -> cur %d", - vconf_camera_state, VCONFKEY_CAMERA_STATE_OPEN); - } else { - int vconf_recorder_state = 0; - - /* get current recorder state of vconf key */ - vconf_get_int(VCONFKEY_RECORDER_STATE, &vconf_recorder_state); - if (vconf_set_int(VCONFKEY_RECORDER_STATE, VCONFKEY_RECORDER_STATE_CREATED)) { - _mmcam_dbg_log("VCONF ERROR %s : cur %d",strerror(errno),errno); - if (errno == EPERM || errno == EACCES) { - ret = MM_ERROR_COMMON_INVALID_PERMISSION; - goto _ERR_CAMCORDER_CMD_PRECON_AFTER_LOCK; - } - } - - _mmcam_dbg_log("VCONFKEY_RECORDER_STATE prev %d -> cur %d", - vconf_recorder_state, VCONFKEY_RECORDER_STATE_CREATED); - } - mm_camcorder_get_attributes(handle, NULL, MMCAM_DISPLAY_SURFACE, &display_surface_type, MMCAM_CAMERA_RECORDING_MOTION_RATE, &motion_rate, @@ -830,9 +968,6 @@ int _mmcamcorder_realize(MMHandleType handle) /* Check and make SHARE session as PLAYING */ if (hcamcorder->asm_register) { - int asm_ret = TRUE; - ASM_resource_t mm_resource = ASM_RESOURCE_NONE; - switch (hcamcorder->type) { case MM_CAMCORDER_MODE_AUDIO: mm_resource = ASM_RESOURCE_NONE; @@ -851,9 +986,8 @@ int _mmcamcorder_realize(MMHandleType handle) break; } - asm_ret = ASM_set_sound_state(hcamcorder->asm_handle, hcamcorder->asm_event_type, - ASM_STATE_PLAYING, mm_resource, &errorcode); - if (!asm_ret) { + if (!ASM_set_sound_state(hcamcorder->asm_handle, hcamcorder->asm_event_type, + ASM_STATE_PLAYING, mm_resource, &errorcode)) { switch (errorcode) { case ERR_ASM_POLICY_CANNOT_PLAY_BY_CALL: ret = MM_ERROR_POLICY_BLOCKED_BY_CALL; @@ -889,11 +1023,45 @@ int _mmcamcorder_realize(MMHandleType handle) _mmcam_dbg_log("do nothing for ASM"); } + /* set camera/recorder state to vconf key */ + if (hcamcorder->type != MM_CAMCORDER_MODE_AUDIO) { + int vconf_camera_state = 0; + + /* get current camera state of vconf key */ + vconf_get_int(VCONFKEY_CAMERA_STATE, &vconf_camera_state); + if (vconf_set_int(VCONFKEY_CAMERA_STATE, VCONFKEY_CAMERA_STATE_OPEN)) { + strerror_r(errno, err_msg, MAX_ERROR_MESSAGE_LEN); + _mmcam_dbg_log("VCONF ERROR %s : cur %d",err_msg,errno); + if(errno == EPERM || errno == EACCES) { + ret = MM_ERROR_COMMON_INVALID_PERMISSION; + goto _ERR_CAMCORDER_CMD_PRECON_AFTER_SESSION; + } + } + _mmcam_dbg_log("VCONFKEY_CAMERA_STATE prev %d -> cur %d", + vconf_camera_state, VCONFKEY_CAMERA_STATE_OPEN); + } else { + int vconf_recorder_state = 0; + + /* get current recorder state of vconf key */ + vconf_get_int(VCONFKEY_RECORDER_STATE, &vconf_recorder_state); + if (vconf_set_int(VCONFKEY_RECORDER_STATE, VCONFKEY_RECORDER_STATE_CREATED)) { + strerror_r(errno, err_msg, MAX_ERROR_MESSAGE_LEN); + _mmcam_dbg_log("VCONF ERROR %s : cur %d",err_msg,errno); + if (errno == EPERM || errno == EACCES) { + ret = MM_ERROR_COMMON_INVALID_PERMISSION; + goto _ERR_CAMCORDER_CMD_PRECON_AFTER_SESSION; + } + } + + _mmcam_dbg_log("VCONFKEY_RECORDER_STATE prev %d -> cur %d", + vconf_recorder_state, VCONFKEY_RECORDER_STATE_CREATED); + } + /* alloc sub context */ hcamcorder->sub_context = _mmcamcorder_alloc_subcontext(hcamcorder->type); if(!hcamcorder->sub_context) { ret = MM_ERROR_CAMCORDER_RESOURCE_CREATION; - goto _ERR_CAMCORDER_CMD_PRECON_AFTER_LOCK; + goto _ERR_CAMCORDER_CMD; } /* Set basic configure information */ @@ -969,18 +1137,20 @@ int _mmcamcorder_realize(MMHandleType handle) _mmcam_dbg_log("Support sensor encoded capture : %d", hcamcorder->sub_context->SensorEncodedCapture); /* create pipeline */ + traceBegin(TTRACE_TAG_CAMERA, "MMCAMCORDER:REALIZE:CREATE_PIPELINE"); ret = _mmcamcorder_create_pipeline(handle, hcamcorder->type); + traceEnd(TTRACE_TAG_CAMERA); if (ret != MM_ERROR_NONE) { /* check internal error of gstreamer */ - if (hcamcorder->sub_context->error_code != MM_ERROR_NONE) { - ret = hcamcorder->sub_context->error_code; + if (hcamcorder->error_code != MM_ERROR_NONE) { + ret = hcamcorder->error_code; _mmcam_dbg_log("gstreamer error is occurred. return it %x", ret); } /* release sub context */ _mmcamcorder_dealloc_subcontext(hcamcorder->sub_context); hcamcorder->sub_context = NULL; - goto _ERR_CAMCORDER_CMD_PRECON_AFTER_LOCK; + goto _ERR_CAMCORDER_CMD; } /* set command function */ @@ -989,7 +1159,7 @@ int _mmcamcorder_realize(MMHandleType handle) _mmcamcorder_destroy_pipeline(handle, hcamcorder->type); _mmcamcorder_dealloc_subcontext(hcamcorder->sub_context); hcamcorder->sub_context = NULL; - goto _ERR_CAMCORDER_CMD_PRECON_AFTER_LOCK; + goto _ERR_CAMCORDER_CMD; } _mmcamcorder_set_state(handle, state_TO); @@ -998,13 +1168,7 @@ int _mmcamcorder_realize(MMHandleType handle) return MM_ERROR_NONE; -_ERR_CAMCORDER_CMD_PRECON_AFTER_LOCK: - _MMCAMCORDER_UNLOCK_CMD(hcamcorder); - -_ERR_CAMCORDER_CMD_PRECON: - _mmcam_dbg_err("Realize fail (type %d, state %d, ret %x)", - hcamcorder->type, state, ret); - +_ERR_CAMCORDER_CMD: /* rollback camera state to vconf key */ if (hcamcorder->type != MM_CAMCORDER_MODE_AUDIO) { int vconf_camera_state = 0; @@ -1026,6 +1190,22 @@ _ERR_CAMCORDER_CMD_PRECON: vconf_recorder_state, VCONFKEY_RECORDER_STATE_NULL); } +_ERR_CAMCORDER_CMD_PRECON_AFTER_SESSION: + if (hcamcorder->asm_register) { + /* STOP session */ + if (!ASM_set_sound_state(hcamcorder->asm_handle, hcamcorder->asm_event_type, + ASM_STATE_STOP, mm_resource, &errorcode)) { + _mmcam_dbg_err("Set ASM state to STOP failed 0x%x", errorcode); + } + } + +_ERR_CAMCORDER_CMD_PRECON_AFTER_LOCK: + _MMCAMCORDER_UNLOCK_CMD(hcamcorder); + +_ERR_CAMCORDER_CMD_PRECON: + _mmcam_dbg_err("Realize fail (type %d, state %d, ret %x)", + hcamcorder->type, state, ret); + return ret; } @@ -1170,7 +1350,7 @@ int _mmcamcorder_start(MMHandleType handle) } /* initialize error code */ - hcamcorder->sub_context->error_code = MM_ERROR_NONE; + hcamcorder->error_code = MM_ERROR_NONE; /* set attributes related sensor */ if (hcamcorder->type != MM_CAMCORDER_MODE_AUDIO) { @@ -1180,8 +1360,8 @@ int _mmcamcorder_start(MMHandleType handle) ret = hcamcorder->command((MMHandleType)hcamcorder, _MMCamcorder_CMD_PREVIEW_START); if (ret != MM_ERROR_NONE) { /* check internal error of gstreamer */ - if (hcamcorder->sub_context->error_code != MM_ERROR_NONE) { - ret = hcamcorder->sub_context->error_code; + if (hcamcorder->error_code != MM_ERROR_NONE) { + ret = hcamcorder->error_code; _mmcam_dbg_log("gstreamer error is occurred. return it %x", ret); } goto _ERR_CAMCORDER_CMD_PRECON_AFTER_LOCK; @@ -1211,10 +1391,9 @@ _ERR_CAMCORDER_CMD_PRECON_AFTER_LOCK: _ERR_CAMCORDER_CMD_PRECON: /* check internal error of gstreamer */ - if (hcamcorder->sub_context && - hcamcorder->sub_context->error_code != MM_ERROR_NONE) { - ret = hcamcorder->sub_context->error_code; - hcamcorder->sub_context->error_code = MM_ERROR_NONE; + if (hcamcorder->error_code != MM_ERROR_NONE) { + ret = hcamcorder->error_code; + hcamcorder->error_code = MM_ERROR_NONE; _mmcam_dbg_log("gstreamer error is occurred. return it %x", ret); } @@ -1336,7 +1515,19 @@ int _mmcamcorder_capture_start(MMHandleType handle) ret = MM_ERROR_CAMCORDER_DEVICE_BUSY; goto _ERR_CAMCORDER_CMD_PRECON_AFTER_LOCK; } else { - hcamcorder->capture_in_recording = TRUE; + pthread_mutex_lock(&(hcamcorder->task_thread_lock)); + if (hcamcorder->task_thread_state == _MMCAMCORDER_TASK_THREAD_STATE_NONE) { + hcamcorder->capture_in_recording = TRUE; + hcamcorder->task_thread_state = _MMCAMCORDER_TASK_THREAD_STATE_CHECK_CAPTURE_IN_RECORDING; + _mmcam_dbg_log("send signal for capture in recording"); + pthread_cond_signal(&(hcamcorder->task_thread_cond)); + pthread_mutex_unlock(&(hcamcorder->task_thread_lock)); + } else { + _mmcam_dbg_err("task thread busy : %d", hcamcorder->task_thread_state); + pthread_mutex_unlock(&(hcamcorder->task_thread_lock)); + ret = MM_ERROR_CAMCORDER_INVALID_STATE; + goto _ERR_CAMCORDER_CMD_PRECON_AFTER_LOCK; + } } } @@ -1457,42 +1648,61 @@ int _mmcamcorder_record(MMHandleType handle) goto _ERR_CAMCORDER_CMD_PRECON_AFTER_LOCK; } - /* initialize error code */ - hcamcorder->sub_context->error_code = MM_ERROR_NONE; + if (state == state_FROM1) { + /* initialize error code */ + hcamcorder->error_code = MM_ERROR_NONE; - /* update session information */ - if (hcamcorder->asm_register == _MMCamcorder_ASM_SESSION_REGISTERED_BY_OUTSIDE || - hcamcorder->asm_register == _MMCamcorder_ASM_SESSION_REGISTERED_INTERNALLY) { - ret = _mm_session_util_read_information(-1, &hcamcorder->asm_session_type, &hcamcorder->asm_session_options); - if (ret != MM_ERROR_NONE) { - _mmcam_dbg_warn("_mm_session_util_read_information failed[%x]", ret); - goto _ERR_CAMCORDER_CMD_PRECON_AFTER_LOCK; - } else { - if (hcamcorder->asm_session_type == MM_SESSION_TYPE_MEDIA_RECORD) { - _mmcam_dbg_err("session was already registered to MEDIA_RECORD, could not process it.."); - ret = MM_ERROR_POLICY_INTERNAL; + /* update session information */ + if (hcamcorder->asm_register == _MMCamcorder_ASM_SESSION_REGISTERED_BY_OUTSIDE || + hcamcorder->asm_register == _MMCamcorder_ASM_SESSION_REGISTERED_INTERNALLY) { + ret = _mm_session_util_read_information(-1, &hcamcorder->asm_session_type, &hcamcorder->asm_session_options); + if (ret != MM_ERROR_NONE) { + _mmcam_dbg_warn("_mm_session_util_read_information failed[%x]", ret); goto _ERR_CAMCORDER_CMD_PRECON_AFTER_LOCK; } else { - int asm_ret = MM_ERROR_NONE; - _mmcam_dbg_log("session was already registered to MEDIA, update it to MEDIA_RECORD"); - hcamcorder->asm_session_type = MM_SESSION_TYPE_MEDIA_RECORD; - asm_ret = _mm_session_util_write_information(-1, hcamcorder->asm_session_type, hcamcorder->asm_session_options); - if (asm_ret != MM_ERROR_NONE) { - _mmcam_dbg_err("_mm_session_util_write_information() [type %d, options %x] failed[%x]", hcamcorder->asm_session_type, hcamcorder->asm_session_options, asm_ret); + if (hcamcorder->asm_session_type == MM_SESSION_TYPE_MEDIA_RECORD) { + _mmcam_dbg_err("session was already registered to MEDIA_RECORD, could not process it.."); ret = MM_ERROR_POLICY_INTERNAL; goto _ERR_CAMCORDER_CMD_PRECON_AFTER_LOCK; + } else { + int asm_ret = MM_ERROR_NONE; + _mmcam_dbg_log("session is not MEDIA_RECORD, update it to MEDIA_RECORD"); + hcamcorder->asm_session_type = MM_SESSION_TYPE_MEDIA_RECORD; + asm_ret = _mm_session_util_write_information(-1, hcamcorder->asm_session_type, hcamcorder->asm_session_options); + if (asm_ret != MM_ERROR_NONE) { + _mmcam_dbg_err("_mm_session_util_write_information() [type %d, options %x] failed[%x]", + hcamcorder->asm_session_type, hcamcorder->asm_session_options, asm_ret); + ret = MM_ERROR_POLICY_INTERNAL; + goto _ERR_CAMCORDER_CMD_PRECON_AFTER_LOCK; + } } } } + } else { + _mmcam_dbg_warn("skip session check - NOW PASUED state"); } ret = hcamcorder->command((MMHandleType)hcamcorder, _MMCamcorder_CMD_RECORD); if (ret != MM_ERROR_NONE) { /* check internal error of gstreamer */ - if (hcamcorder->sub_context->error_code != MM_ERROR_NONE) { - ret = hcamcorder->sub_context->error_code; + if (hcamcorder->error_code != MM_ERROR_NONE) { + ret = hcamcorder->error_code; _mmcam_dbg_log("gstreamer error is occurred. return it %x", ret); } + + /* Rollback session to MEDIA */ + if (hcamcorder->asm_register == _MMCamcorder_ASM_SESSION_REGISTERED_BY_OUTSIDE || + hcamcorder->asm_register == _MMCamcorder_ASM_SESSION_REGISTERED_INTERNALLY) { + _mmcam_dbg_log("Rollback session to MEDIA"); + int asm_ret = MM_ERROR_NONE; + hcamcorder->asm_session_type = MM_SESSION_TYPE_MEDIA; + asm_ret = _mm_session_util_write_information(-1, hcamcorder->asm_session_type, hcamcorder->asm_session_options); + if (asm_ret != MM_ERROR_NONE) { + _mmcam_dbg_err("_mm_session_util_write_information() [type %d, options %x] failed[%x]", + hcamcorder->asm_session_type, hcamcorder->asm_session_options, asm_ret); + } + } + goto _ERR_CAMCORDER_CMD_PRECON_AFTER_LOCK; } @@ -1528,10 +1738,9 @@ _ERR_CAMCORDER_CMD_PRECON_AFTER_LOCK: _ERR_CAMCORDER_CMD_PRECON: /* check internal error of gstreamer */ - if (hcamcorder->sub_context && - hcamcorder->sub_context->error_code != MM_ERROR_NONE) { - ret = hcamcorder->sub_context->error_code; - hcamcorder->sub_context->error_code = MM_ERROR_NONE; + if (hcamcorder->error_code != MM_ERROR_NONE) { + ret = hcamcorder->error_code; + hcamcorder->error_code = MM_ERROR_NONE; _mmcam_dbg_log("gstreamer error is occurred. return it %x", ret); } @@ -1678,13 +1887,14 @@ int _mmcamcorder_commit(MMHandleType handle) if (hcamcorder->state_change_by_system != _MMCAMCORDER_STATE_CHANGE_BY_ASM) { /* update session information */ if (hcamcorder->asm_register == _MMCamcorder_ASM_SESSION_REGISTERED_BY_OUTSIDE || - hcamcorder->asm_register == _MMCamcorder_ASM_SESSION_REGISTERED_INTERNALLY) { + hcamcorder->asm_register == _MMCamcorder_ASM_SESSION_REGISTERED_INTERNALLY) { _mmcam_dbg_log("session was registered to MEDIA_RECORD, update it to MEDIA"); int asm_ret = MM_ERROR_NONE; hcamcorder->asm_session_type = MM_SESSION_TYPE_MEDIA; asm_ret = _mm_session_util_write_information(-1, hcamcorder->asm_session_type, hcamcorder->asm_session_options); if (asm_ret != MM_ERROR_NONE) { - _mmcam_dbg_err("_mm_session_util_write_information() [type %d, options %x] failed[%x]", hcamcorder->asm_session_type, hcamcorder->asm_session_options, asm_ret); + _mmcam_dbg_err("_mm_session_util_write_information() [type %d, options %x] failed[%x]", + hcamcorder->asm_session_type, hcamcorder->asm_session_options, asm_ret); } } } @@ -1747,13 +1957,14 @@ int _mmcamcorder_cancel(MMHandleType handle) /* update session information */ if (hcamcorder->asm_register == _MMCamcorder_ASM_SESSION_REGISTERED_BY_OUTSIDE || - hcamcorder->asm_register == _MMCamcorder_ASM_SESSION_REGISTERED_INTERNALLY) { + hcamcorder->asm_register == _MMCamcorder_ASM_SESSION_REGISTERED_INTERNALLY) { _mmcam_dbg_log("session was registered to MEDIA_RECORD, update it to MEDIA"); int asm_ret = MM_ERROR_NONE; hcamcorder->asm_session_type = MM_SESSION_TYPE_MEDIA; asm_ret = _mm_session_util_write_information(-1, hcamcorder->asm_session_type, hcamcorder->asm_session_options); if (asm_ret != MM_ERROR_NONE) { - _mmcam_dbg_err("_mm_session_util_write_information() [type %d, options %x] failed[%x]", hcamcorder->asm_session_type, hcamcorder->asm_session_options, asm_ret); + _mmcam_dbg_err("_mm_session_util_write_information() [type %d, options %x] failed[%x]", + hcamcorder->asm_session_type, hcamcorder->asm_session_options, asm_ret); } } @@ -1985,6 +2196,7 @@ int _mmcamcorder_init_focusing(MMHandleType handle) control = GST_CAMERA_CONTROL (sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst); if (control == NULL) { _mmcam_dbg_err("cast CAMERA_CONTROL failed"); + _MMCAMCORDER_UNLOCK_CMD(hcamcorder); return MM_ERROR_CAMCORDER_INTERNAL; } @@ -2211,6 +2423,7 @@ int _mmcamcorder_stop_focusing(MMHandleType handle) _MMCAMCORDER_UNLOCK_CMD(hcamcorder); return MM_ERROR_NONE; } + control = GST_CAMERA_CONTROL(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst); if (control) { ret = gst_camera_control_stop_auto_focus(control); @@ -2383,8 +2596,8 @@ void _mmcamcorder_set_state(MMHandleType handle, int state) msg.param.state.previous = old_state; msg.param.state.current = state; - /*_mmcam_dbg_log("_mmcamcroder_send_message : msg : %p, id:%x", &msg, msg.id);*/ - _mmcamcroder_send_message(handle, &msg); + /*_mmcam_dbg_log("_mmcamcorder_send_message : msg : %p, id:%x", &msg, msg.id);*/ + _mmcamcorder_send_message(handle, &msg); } _MMCAMCORDER_UNLOCK_STATE(handle); @@ -2676,7 +2889,7 @@ gboolean _mmcamcorder_pipeline_cb_message(GstBus *bus, GstMessage *message, gpoi if (sc->element[_MMCAMCORDER_MAIN_PIPE].gst) { pipeline = sc->element[_MMCAMCORDER_MAIN_PIPE].gst; if (message->src == (GstObject*)pipeline) { - vnewstate = gst_structure_get_value(message->structure, "new-state"); + vnewstate = gst_structure_get_value(gst_message_get_structure(message), "new-state"); newstate = (GstState)vnewstate->data[0].v_int; _mmcam_dbg_log("GST_MESSAGE_STATE_CHANGED[%s]",gst_element_state_get_name(newstate)); } @@ -2721,8 +2934,8 @@ gboolean _mmcamcorder_pipeline_cb_message(GstBus *bus, GstMessage *message, gpoi case GST_MESSAGE_SEGMENT_DONE: _mmcam_dbg_log("GST_MESSAGE_SEGMENT_DONE"); break; - case GST_MESSAGE_DURATION: - _mmcam_dbg_log("GST_MESSAGE_DURATION"); + case GST_MESSAGE_DURATION_CHANGED: + _mmcam_dbg_log("GST_MESSAGE_DURATION_CHANGED"); break; case GST_MESSAGE_LATENCY: _mmcam_dbg_log("GST_MESSAGE_LATENCY"); @@ -2736,6 +2949,9 @@ gboolean _mmcamcorder_pipeline_cb_message(GstBus *bus, GstMessage *message, gpoi case GST_MESSAGE_ANY: _mmcam_dbg_log("GST_MESSAGE_ANY"); break; + case GST_MESSAGE_QOS: +// _mmcam_dbg_log("GST_MESSAGE_QOS"); + break; default: _mmcam_dbg_log("not handled message type=(%d)", GST_MESSAGE_TYPE(message)); break; @@ -2784,115 +3000,92 @@ GstBusSyncReply _mmcamcorder_pipeline_bus_sync_callback(GstBus *bus, GstMessage switch (err->code) { case GST_RESOURCE_ERROR_BUSY: _mmcam_dbg_err("Camera device [busy]"); - sc->error_code = MM_ERROR_CAMCORDER_DEVICE_BUSY; + hcamcorder->error_code = MM_ERROR_CAMCORDER_DEVICE_BUSY; break; case GST_RESOURCE_ERROR_OPEN_WRITE: _mmcam_dbg_err("Camera device [open failed]"); - sc->error_code = MM_ERROR_COMMON_INVALID_PERMISSION; + hcamcorder->error_code = MM_ERROR_COMMON_INVALID_PERMISSION; //sc->error_code = MM_ERROR_CAMCORDER_DEVICE_OPEN; // SECURITY PART REQUEST PRIVILEGE break; case GST_RESOURCE_ERROR_OPEN_READ_WRITE: _mmcam_dbg_err("Camera device [open failed]"); - sc->error_code = MM_ERROR_CAMCORDER_DEVICE_OPEN; + hcamcorder->error_code = MM_ERROR_CAMCORDER_DEVICE_OPEN; break; case GST_RESOURCE_ERROR_OPEN_READ: _mmcam_dbg_err("Camera device [register trouble]"); - sc->error_code = MM_ERROR_CAMCORDER_DEVICE_REG_TROUBLE; + hcamcorder->error_code = MM_ERROR_CAMCORDER_DEVICE_REG_TROUBLE; break; case GST_RESOURCE_ERROR_NOT_FOUND: _mmcam_dbg_err("Camera device [device not found]"); - sc->error_code = MM_ERROR_CAMCORDER_DEVICE_NOT_FOUND; + hcamcorder->error_code = MM_ERROR_CAMCORDER_DEVICE_NOT_FOUND; break; case GST_RESOURCE_ERROR_TOO_LAZY: _mmcam_dbg_err("Camera device [timeout]"); - sc->error_code = MM_ERROR_CAMCORDER_DEVICE_TIMEOUT; + hcamcorder->error_code = MM_ERROR_CAMCORDER_DEVICE_TIMEOUT; break; case GST_RESOURCE_ERROR_SETTINGS: _mmcam_dbg_err("Camera device [not supported]"); - sc->error_code = MM_ERROR_CAMCORDER_NOT_SUPPORTED; + hcamcorder->error_code = MM_ERROR_CAMCORDER_NOT_SUPPORTED; break; case GST_RESOURCE_ERROR_FAILED: _mmcam_dbg_err("Camera device [working failed]."); - sc->error_code = MM_ERROR_CAMCORDER_DEVICE_IO; + hcamcorder->error_code = MM_ERROR_CAMCORDER_DEVICE_IO; break; default: _mmcam_dbg_err("Camera device [General(%d)]", err->code); - sc->error_code = MM_ERROR_CAMCORDER_DEVICE; + hcamcorder->error_code = MM_ERROR_CAMCORDER_DEVICE; break; } - sc->error_occurs = TRUE; + hcamcorder->error_occurs = TRUE; } g_error_free(err); /* store error code and drop this message if cmd is running */ - if (sc->error_code != MM_ERROR_NONE) { + if (hcamcorder->error_code != MM_ERROR_NONE) { _MMCamcorderMsgItem msg; /* post error to application */ - sc->error_occurs = TRUE; + hcamcorder->error_occurs = TRUE; msg.id = MM_MESSAGE_CAMCORDER_ERROR; - msg.param.code = sc->error_code; - _mmcamcroder_send_message((MMHandleType)hcamcorder, &msg); + msg.param.code = hcamcorder->error_code; + _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg); - gst_message_unref(message); - message = NULL; - - return GST_BUS_DROP; + goto DROP_MESSAGE; } } else if (GST_MESSAGE_TYPE(message) == GST_MESSAGE_ELEMENT) { _MMCamcorderMsgItem msg; - if (gst_structure_has_name(message->structure, "avsysvideosrc-AF") || - gst_structure_has_name(message->structure, "camerasrc-AF")) { + if (gst_structure_has_name(gst_message_get_structure(message), "avsysvideosrc-AF") || + gst_structure_has_name(gst_message_get_structure(message), "camerasrc-AF")) { int focus_state = 0; - gst_structure_get_int(message->structure, "focus-state", &focus_state); + gst_structure_get_int(gst_message_get_structure(message), "focus-state", &focus_state); _mmcam_dbg_log("Focus State:%d", focus_state); msg.id = MM_MESSAGE_CAMCORDER_FOCUS_CHANGED; msg.param.code = focus_state; - _mmcamcroder_send_message((MMHandleType)hcamcorder, &msg); - - gst_message_unref(message); - message = NULL; - - return GST_BUS_DROP; - } else if (gst_structure_has_name(message->structure, "camerasrc-Light")) { - int low_light_state = 0; - - gst_structure_get_int(message->structure, "low-light-state", &low_light_state); - _mmcam_dbg_log("Low light state %d", low_light_state); - - msg.id = MM_MESSAGE_CAMCORDER_LOW_LIGHT_STATE; - msg.param.code = low_light_state; - _mmcamcroder_send_message((MMHandleType)hcamcorder, &msg); - - gst_message_unref(message); - message = NULL; + _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg); - return GST_BUS_DROP; - } else if (gst_structure_has_name(message->structure, "camerasrc-HDR")) { + goto DROP_MESSAGE; + } else if (gst_structure_has_name(gst_message_get_structure(message), "camerasrc-HDR")) { int progress = 0; int status = 0; - if (gst_structure_get_int(message->structure, "progress", &progress)) { - gst_structure_get_int(message->structure, "status", &status); + if (gst_structure_get_int(gst_message_get_structure(message), "progress", &progress)) { + gst_structure_get_int(gst_message_get_structure(message), "status", &status); _mmcam_dbg_log("HDR progress %d percent, status %d", progress, status); msg.id = MM_MESSAGE_CAMCORDER_HDR_PROGRESS; msg.param.code = progress; - _mmcamcroder_send_message((MMHandleType)hcamcorder, &msg); + _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg); } - gst_message_unref(message); - message = NULL; - - return GST_BUS_DROP; - } else if (gst_structure_has_name(message->structure, "camerasrc-FD")) { + goto DROP_MESSAGE; + } else if (gst_structure_has_name(gst_message_get_structure(message), "camerasrc-FD")) { int i = 0; - const GValue *g_value = gst_structure_get_value(message->structure, "face-info");; + const GValue *g_value = gst_structure_get_value(gst_message_get_structure(message), "face-info");; GstCameraControlFaceDetectInfo *fd_info = NULL; MMCamFaceDetectInfo *cam_fd_info = NULL; @@ -2902,7 +3095,7 @@ GstBusSyncReply _mmcamcorder_pipeline_bus_sync_callback(GstBus *bus, GstMessage if (fd_info == NULL) { _mmcam_dbg_warn("fd_info is NULL"); - return TRUE; + goto DROP_MESSAGE; } cam_fd_info = (MMCamFaceDetectInfo *)malloc(sizeof(MMCamFaceDetectInfo)); @@ -2912,7 +3105,7 @@ GstBusSyncReply _mmcamcorder_pipeline_bus_sync_callback(GstBus *bus, GstMessage free(fd_info); fd_info = NULL; - return TRUE; + goto DROP_MESSAGE; } /* set total face count */ @@ -2957,21 +3150,18 @@ GstBusSyncReply _mmcamcorder_pipeline_bus_sync_callback(GstBus *bus, GstMessage msg.param.size = sizeof(MMCamFaceDetectInfo); msg.param.code = 0; - _mmcamcroder_send_message((MMHandleType)hcamcorder, &msg); + _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg); } /* free fd_info allocated by plugin */ free(fd_info); fd_info = NULL; - gst_message_unref(message); - message = NULL; - - return GST_BUS_DROP; - } else if (gst_structure_has_name(message->structure, "camerasrc-Capture")) { + goto DROP_MESSAGE; + } else if (gst_structure_has_name(gst_message_get_structure(message), "camerasrc-Capture")) { int capture_done = FALSE; - if (gst_structure_get_int(message->structure, "capture-done", &capture_done)) { + if (gst_structure_get_int(gst_message_get_structure(message), "capture-done", &capture_done)) { sc = MMF_CAMCORDER_SUBCONTEXT(hcamcorder); if (sc && sc->info_image) { /* play capture sound */ @@ -2979,16 +3169,19 @@ GstBusSyncReply _mmcamcorder_pipeline_bus_sync_callback(GstBus *bus, GstMessage } } - gst_message_unref(message); - message = NULL; - - return GST_BUS_DROP; + goto DROP_MESSAGE; } } return GST_BUS_PASS; +DROP_MESSAGE: + gst_message_unref(message); + message = NULL; + + return GST_BUS_DROP; } + GstBusSyncReply _mmcamcorder_audio_pipeline_bus_sync_callback(GstBus *bus, GstMessage *message, gpointer data) { GstElement *element = NULL; @@ -3030,14 +3223,14 @@ GstBusSyncReply _mmcamcorder_audio_pipeline_bus_sync_callback(GstBus *bus, GstMe case GST_RESOURCE_ERROR_OPEN_READ_WRITE: case GST_RESOURCE_ERROR_OPEN_WRITE: _mmcam_dbg_err("audio device [open failed]"); - sc->error_code = MM_ERROR_COMMON_INVALID_PERMISSION; + hcamcorder->error_code = MM_ERROR_COMMON_INVALID_PERMISSION; /* post error to application */ - sc->error_occurs = TRUE; + hcamcorder->error_occurs = TRUE; msg.id = MM_MESSAGE_CAMCORDER_ERROR; - msg.param.code = sc->error_code; - _mmcam_dbg_err(" error : sc->error_occurs %d",sc->error_occurs); + msg.param.code = hcamcorder->error_code; + _mmcam_dbg_err(" error : sc->error_occurs %d", hcamcorder->error_occurs); g_error_free(err); - _mmcamcroder_send_message((MMHandleType)hcamcorder, &msg); + _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg); gst_message_unref(message); message = NULL; return GST_BUS_DROP; @@ -3084,26 +3277,7 @@ ASM_cb_result_t _mmcamcorder_asm_callback(int handle, ASM_event_sources_t event_ case ASM_COMMAND_PAUSE: _mmcam_dbg_log("Got msg from asm to Pause(state:%d)", current_state); - if (hcamcorder->asm_event_type == ASM_EVENT_MMCAMCORDER_AUDIO || hcamcorder->asm_event_type == ASM_EVENT_MEDIA_MMCAMCORDER) { - if (current_state == MM_CAMCORDER_STATE_RECORDING) { - _mmcamcorder_pause((MMHandleType)hcamcorder); - } else if (current_state == MM_CAMCORDER_STATE_PAUSED) { - _MMCamcorderMsgItem msg; - - _mmcam_dbg_warn("Now PAUSED state, only send message to nofity interrupt"); - - msg.id = MM_MESSAGE_CAMCORDER_STATE_CHANGED_BY_ASM; - msg.param.state.code = hcamcorder->asm_event_code; - msg.param.state.previous = MM_CAMCORDER_STATE_PAUSED; - msg.param.state.current = MM_CAMCORDER_STATE_PAUSED; - - _mmcamcroder_send_message((MMHandleType)hcamcorder, &msg); - } else { - _mmcam_dbg_log("do nothing at this state %d", current_state); - } - } else { - __mmcamcorder_force_stop(hcamcorder); - } + __mmcamcorder_force_stop(hcamcorder); cb_res = ASM_CB_RES_STOP; _mmcam_dbg_log("Finish opeartion."); @@ -3136,7 +3310,7 @@ ASM_cb_result_t _mmcamcorder_asm_callback(int handle, ASM_event_sources_t event_ _mmcam_dbg_log("Got msg from asm to Resume(state %d)", current_state); msg.id = MM_MESSAGE_READY_TO_RESUME; - _mmcamcroder_send_message((MMHandleType)hcamcorder, &msg); + _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg); cb_res = ASM_CB_RES_PLAYING; _mmcam_dbg_log("Finish opeartion.(%d)", cb_res); @@ -3197,7 +3371,9 @@ int _mmcamcorder_create_pipeline(MMHandleType handle, int type) pipeline = sc->element[_MMCAMCORDER_MAIN_PIPE].gst; if (type != MM_CAMCORDER_MODE_AUDIO) { + traceBegin(TTRACE_TAG_CAMERA, "MMCAMCORDER:REALIZE:SET_READY_TO_PIPELINE"); ret = _mmcamcorder_gst_set_state(handle, pipeline, GST_STATE_READY); + traceEnd(TTRACE_TAG_CAMERA); } #ifdef _MMCAMCORDER_GET_DEVICE_INFO if (!_mmcamcorder_get_device_info(handle)) { @@ -3333,7 +3509,7 @@ int _mmcamcorder_gst_set_state(MMHandleType handle, GstElement *pipeline, GstSta GstStateChangeReturn setChangeReturn = GST_STATE_CHANGE_FAILURE; GstStateChangeReturn getChangeReturn = GST_STATE_CHANGE_FAILURE; GstClockTime get_timeout = __MMCAMCORDER_SET_GST_STATE_TIMEOUT * GST_SECOND; - GMutex *state_lock = NULL; + pthread_mutex_t *state_lock = NULL; mmf_return_val_if_fail(handle, MM_ERROR_CAMCORDER_NOT_INITIALIZED); sc = MMF_CAMCORDER_SUBCONTEXT(handle); @@ -3341,13 +3517,13 @@ int _mmcamcorder_gst_set_state(MMHandleType handle, GstElement *pipeline, GstSta if (sc->element[_MMCAMCORDER_MAIN_PIPE].gst == pipeline) { _mmcam_dbg_log("Set state to %d - PREVIEW PIPELINE", target_state); - state_lock = _MMCAMCORDER_GET_GST_STATE_LOCK(handle); + state_lock = &_MMCAMCORDER_GET_GST_STATE_LOCK(handle); } else { _mmcam_dbg_log("Set state to %d - ENDODE PIPELINE", target_state); - state_lock = _MMCAMCORDER_GET_GST_ENCODE_STATE_LOCK(handle); + state_lock = &_MMCAMCORDER_GET_GST_ENCODE_STATE_LOCK(handle); } - g_mutex_lock(state_lock); + pthread_mutex_lock(state_lock); for (k = 0; k < _MMCAMCORDER_STATE_SET_COUNT; k++) { setChangeReturn = gst_element_set_state(pipeline, target_state); @@ -3362,7 +3538,7 @@ int _mmcamcorder_gst_set_state(MMHandleType handle, GstElement *pipeline, GstSta /* if we reached the final target state, exit */ if (pipeline_state == target_state) { _mmcam_dbg_log("Set state to %d - DONE", target_state); - g_mutex_unlock(state_lock); + pthread_mutex_unlock(state_lock); return MM_ERROR_NONE; } break; @@ -3370,12 +3546,12 @@ int _mmcamcorder_gst_set_state(MMHandleType handle, GstElement *pipeline, GstSta _mmcam_dbg_log("status=GST_STATE_CHANGE_ASYNC."); break; default: - g_mutex_unlock(state_lock); + pthread_mutex_unlock(state_lock); _mmcam_dbg_log("status=GST_STATE_CHANGE_FAILURE."); return MM_ERROR_CAMCORDER_GST_STATECHANGE; } - g_mutex_unlock(state_lock); + pthread_mutex_unlock(state_lock); _mmcam_dbg_err("timeout of gst_element_get_state()!!"); @@ -3384,7 +3560,7 @@ int _mmcamcorder_gst_set_state(MMHandleType handle, GstElement *pipeline, GstSta usleep(_MMCAMCORDER_STATE_CHECK_INTERVAL); } - g_mutex_unlock(state_lock); + pthread_mutex_unlock(state_lock); _mmcam_dbg_err("Failure. gst_element_set_state timeout!!"); @@ -3646,9 +3822,9 @@ static gboolean __mmcamcorder_handle_gst_error(MMHandleType handle, GstMessage * #endif /* _MMCAMCORDER_SKIP_GST_FLOW_ERROR */ /* post error to application */ - sc->error_occurs = TRUE; + hcamcorder->error_occurs = TRUE; msg.id = MM_MESSAGE_CAMCORDER_ERROR; - _mmcamcroder_send_message(handle, &msg); + _mmcamcorder_send_message(handle, &msg); return TRUE; } diff --git a/src/mm_camcorder_platform.c b/src/mm_camcorder_platform.c index 90d05fd..ed79621 100644 --- a/src/mm_camcorder_platform.c +++ b/src/mm_camcorder_platform.c @@ -221,6 +221,18 @@ _MMCamcorderEnumConvert _mmcamcorder_enum_conv_detect_mode = * For detail information, refer below documents. * */ +static _MMCamcorderInfoConverting g_audio_info[] = { + { + CONFIGURE_TYPE_MAIN, + CONFIGURE_CATEGORY_MAIN_AUDIO_INPUT, + MM_CAM_AUDIO_DEVICE, + MM_CAMCORDER_ATTR_NONE, + "AudioDevice", + MM_CAMCONVERT_TYPE_INT_ARRAY, + NULL, + } +}; + static _MMCamcorderInfoConverting g_display_info[] = { { CONFIGURE_TYPE_MAIN, @@ -282,15 +294,6 @@ static _MMCamcorderInfoConverting g_caminfo_convert[CAMINFO_CONVERT_NUM] = { { CONFIGURE_TYPE_CTRL, CONFIGURE_CATEGORY_CTRL_CAMERA, - MM_CAM_CAMERA_FPS, - MM_CAMCORDER_ATTR_NONE, - "FPS", - MM_CAMCONVERT_TYPE_INT_ARRAY, - NULL, - }, - { /* 5 */ - CONFIGURE_TYPE_CTRL, - CONFIGURE_CATEGORY_CTRL_CAMERA, MM_CAM_CAMERA_FORMAT, MM_CAMCORDER_ATTR_NONE, "PictureFormat", @@ -689,6 +692,68 @@ int _mmcamcorder_convert_msl_to_sensor(MMHandleType handle, int attr_idx, int ms return mslval; } +int _mmcamcorder_get_fps_array_by_resolution(MMHandleType handle, int width, int height, MMCamAttrsInfo* fps_info) +{ + MMCamAttrsInfo *infoW = NULL; + MMCamAttrsInfo *infoH = NULL; + int i = 0; + char nameFps[5] = {0,}; + bool valid_check = false; + + type_int_array *fps_array; + + mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle); + + //_mmcam_dbg_log("prev resolution w:%d, h:%d", width, height); + + infoW = (MMCamAttrsInfo*)calloc(1, sizeof(MMCamAttrsInfo)); + infoH = (MMCamAttrsInfo*)calloc(1, sizeof(MMCamAttrsInfo)); + + if(infoW == NULL || infoH == NULL) { + _mmcam_dbg_err("Fail to alloc infoW [%p], infoH [%p]", infoW, infoH); + if(infoW) + free(infoW); + if(infoH) + free(infoH); + + return MM_ERROR_COMMON_OUT_OF_MEMORY; + } + + mm_camcorder_get_attribute_info(handle, MMCAM_CAMERA_WIDTH, infoW); + mm_camcorder_get_attribute_info(handle, MMCAM_CAMERA_HEIGHT, infoH); + + for(i=0; i < infoW->int_array.count; i++) { + //_mmcam_dbg_log("width :%d, height : %d\n", infoW->int_array.array[i], infoH->int_array.array[i]); + if(infoW->int_array.array[i] == width && infoH->int_array.array[i] == height) { + valid_check = true; + snprintf(nameFps,sizeof(nameFps), "FPS%d", i); + _mmcam_dbg_log("nameFps : %s!!!", nameFps); + break; + } + } + + if(infoW) + free(infoW); + if(infoH) + free(infoH); + + if(!valid_check) { + _mmcam_dbg_err("FAILED : Can't find the valid resolution from attribute."); + return MM_ERROR_CAMCORDER_NOT_SUPPORTED; + } + + if (!_mmcamcorder_conf_get_value_int_array(hcamcorder->conf_ctrl, CONFIGURE_CATEGORY_CTRL_CAMERA, nameFps, &fps_array)) { + _mmcam_dbg_err("FAILED : Can't find the valid FPS array."); + return MM_ERROR_CAMCORDER_CREATE_CONFIGURE; + } + + fps_info->int_array.count = fps_array->count; + fps_info->int_array.array = fps_array->value; + fps_info->int_array.def = fps_array->default_value; + + return MM_ERROR_NONE; +} + //convert sensor value to MSL value int _mmcamcorder_convert_sensor_to_msl(MMHandleType handle, int attr_idx, int sensval) { @@ -700,7 +765,7 @@ int _mmcamcorder_convert_sensor_to_msl(MMHandleType handle, int attr_idx, int se mmf_return_val_if_fail(hcamcorder, MM_ERROR_CAMCORDER_NOT_INITIALIZED); info = hcamcorder->caminfo_convert; - + for( i = 0 ; i < size ; i++ ) { if( info[i].attr_idx == attr_idx ) @@ -745,7 +810,7 @@ __mmcamcorder_get_valid_array(int * original_array, int original_count, int ** v int i = 0; int valid_count = 0; int new_default = _MMCAMCORDER_SENSOR_ENUM_NONE; - + for (i = 0; i < original_count; i++) { if (original_array[i] != _MMCAMCORDER_SENSOR_ENUM_NONE) { valid_count++; @@ -783,7 +848,7 @@ __mmcamcorder_get_valid_array(int * original_array, int original_count, int ** v } -int _mmcamcorder_init_attr_from_configure(MMHandleType handle) +int _mmcamcorder_init_attr_from_configure(MMHandleType handle, int type) { mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle); _MMCamcorderInfoConverting *info = NULL; @@ -793,23 +858,38 @@ int _mmcamcorder_init_attr_from_configure(MMHandleType handle) mmf_return_val_if_fail(hcamcorder, MM_ERROR_CAMCORDER_NOT_INITIALIZED); - _mmcam_dbg_log(""); + _mmcam_dbg_log("type : %d", type); - /* Initialize attribute related to camera control */ - info = hcamcorder->caminfo_convert; - table_size = sizeof(g_caminfo_convert) / sizeof(_MMCamcorderInfoConverting); - ret = __mmcamcorder_set_info_to_attr( handle, info, table_size ); - if( ret != MM_ERROR_NONE ) - { - _mmcam_dbg_err( "ret : %x", ret ); + if (type != MM_VIDEO_DEVICE_NONE) { + /* Initialize attribute related to camera control */ + info = hcamcorder->caminfo_convert; + table_size = sizeof(g_caminfo_convert) / sizeof(_MMCamcorderInfoConverting); + ret = __mmcamcorder_set_info_to_attr( handle, info, table_size ); + if (ret != MM_ERROR_NONE) { + _mmcam_dbg_err("camera info set error : 0x%x", ret); + return ret; + } + + /* Initialize attribute related to display */ + info = g_display_info; + table_size = sizeof(g_display_info) / sizeof(_MMCamcorderInfoConverting); + ret = __mmcamcorder_set_info_to_attr( handle, info, table_size ); + if (ret != MM_ERROR_NONE) { + _mmcam_dbg_err("display info set error : 0x%x", ret); + return ret; + } + } + + /* Initialize attribute related to audio */ + info = g_audio_info; + table_size = sizeof(g_audio_info) / sizeof(_MMCamcorderInfoConverting); + ret = __mmcamcorder_set_info_to_attr(handle, info, table_size); + if (ret != MM_ERROR_NONE) { + _mmcam_dbg_err("audio info set error : 0x%x", ret); return ret; } - /* Initialize attribute related to display */ - info = g_display_info; - table_size = sizeof(g_display_info) / sizeof(_MMCamcorderInfoConverting); - ret = __mmcamcorder_set_info_to_attr( handle, info, table_size ); - _mmcam_dbg_log( "result: %x", ret ); + _mmcam_dbg_log("done"); return ret; } @@ -845,16 +925,12 @@ __mmcamcorder_set_info_to_attr( MMHandleType handle, _MMCamcorderInfoConverting if( info[i].type == CONFIGURE_TYPE_MAIN ) { conf_info = hcamcorder->conf_main; - /* - _mmcam_dbg_log( "MAIN configure [%s]", info[i].keyword ); - */ + /*_mmcam_dbg_log( "MAIN configure [%s]", info[i].keyword );*/ } else { conf_info = hcamcorder->conf_ctrl; - /* - _mmcam_dbg_log( "CTRL configure [%s]", info[i].keyword ); - */ + /*_mmcam_dbg_log( "CTRL configure [%s]", info[i].keyword );*/ } switch(info[i].conv_type) @@ -890,7 +966,7 @@ __mmcamcorder_set_info_to_attr( MMHandleType handle, _MMCamcorderInfoConverting if( tarray ) { idefault = tarray->default_value; - + if( info[i].enum_convert ) { iarray_size = __mmcamcorder_get_valid_array(tarray->value, tarray->count, &iarray, &idefault); @@ -968,7 +1044,7 @@ __mmcamcorder_set_info_to_attr( MMHandleType handle, _MMCamcorderInfoConverting { type_int_pair_array *pair_array = NULL; - //_mmcam_dbg_log("INT PAIR Array. type:%d, attr_idx:%d, attr_idx_pair:%d", info[i].type, info[i].attr_idx, info[i].attr_idx_pair); + /*_mmcam_dbg_log("INT PAIR Array. type:%d, attr_idx:%d, attr_idx_pair:%d", info[i].type, info[i].attr_idx, info[i].attr_idx_pair);*/ if (!_mmcamcorder_conf_get_value_int_pair_array(conf_info, info[i].category, info[i].keyword, &pair_array)) { @@ -1006,7 +1082,7 @@ __mmcamcorder_set_info_to_attr( MMHandleType handle, _MMCamcorderInfoConverting if (ret != MM_ERROR_NONE || mmf_attrs_commit(attrs) == -1) return MM_ERROR_CAMCORDER_INVALID_ARGUMENT; - else + else return MM_ERROR_NONE; } diff --git a/src/mm_camcorder_sound.c b/src/mm_camcorder_sound.c index ed24fa2..b9dbbba 100644 --- a/src/mm_camcorder_sound.c +++ b/src/mm_camcorder_sound.c @@ -22,6 +22,7 @@ /*======================================================================================= | INCLUDE FILES | =======================================================================================*/ +#include #include #include #include @@ -643,6 +644,7 @@ gboolean _mmcamcorder_sound_finalize(MMHandleType handle) info = &(hcamcorder->snd_info); _mmcam_dbg_err("START"); + /*Add the delay because we don't know when shutter sound was complete */ usleep(100000); pthread_mutex_lock(&(info->open_mutex)); @@ -776,6 +778,7 @@ void _mmcamcorder_sound_solo_play(MMHandleType handle, const char* filepath, gbo int sound_enable = TRUE; int sound_played = FALSE; int gain_type = VOLUME_GAIN_SHUTTER1; + char err_msg[MAX_ERROR_MESSAGE_LEN] = {'\0',}; mmf_return_if_fail(filepath && hcamcorder); @@ -785,7 +788,8 @@ void _mmcamcorder_sound_solo_play(MMHandleType handle, const char* filepath, gbo ret = pthread_mutex_trylock(&(hcamcorder->sound_lock)); if (ret != 0) { - _mmcam_dbg_warn("g_mutex_trylock failed.[%s]", strerror(ret)); + strerror_r(errno, err_msg, MAX_ERROR_MESSAGE_LEN); + _mmcam_dbg_warn("g_mutex_trylock failed.[%s]", err_msg); return; } diff --git a/src/mm_camcorder_stillshot.c b/src/mm_camcorder_stillshot.c index 38b7fe8..41cfc86 100644 --- a/src/mm_camcorder_stillshot.c +++ b/src/mm_camcorder_stillshot.c @@ -22,9 +22,10 @@ /*======================================================================================= | INCLUDE FILES | =======================================================================================*/ +#include #include #include -#include +#include #include #include "mm_camcorder_internal.h" #include "mm_camcorder_stillshot.h" @@ -52,6 +53,8 @@ #define TRY_LOCK_MAX_COUNT 100 #define TRY_LOCK_TIME 20000 /* ms */ #define SOUND_THREAD_CAPTURE_SOUND 20 +#define H264_PREVIEW_BITRATE 1024*10 /* kbps */ +#define H264_PREVIEW_NEWGOP_INTERVAL 1000 /* ms */ #define _MMCAMCORDER_MAKE_THUMBNAIL_INTERNAL_ENCODE @@ -63,14 +66,10 @@ int _mmcamcorder_image_cmd_capture(MMHandleType handle); int _mmcamcorder_image_cmd_preview_start(MMHandleType handle); int _mmcamcorder_image_cmd_preview_stop(MMHandleType handle); -static void __mmcamcorder_image_capture_cb(GstElement *element, GstBuffer *buffer1, GstBuffer *buffer2, GstBuffer *buffer3, gpointer u_data); - -/* Function for JPEG capture with Encode bin */ -static gboolean __mmcamcorder_encodesink_handoff_callback(GstElement *fakesink, GstBuffer *buffer, GstPad *pad, gpointer u_data); +static void __mmcamcorder_image_capture_cb(GstElement *element, GstSample *sample1, GstSample *sample2, GstSample *sample3, gpointer u_data); /* sound status changed callback */ static void __sound_status_changed_cb(keynode_t* node, void *data); -static void __volume_level_changed_cb(void* user_data); /*======================================================================================= | FUNCTION DEFINITIONS | @@ -127,7 +126,7 @@ int _mmcamcorder_create_stillshot_pipeline(MMHandleType handle) /* connect handoff signal to get capture data */ MMCAMCORDER_SIGNAL_CONNECT(sc->encode_element[_MMCAMCORDER_ENCSINK_SINK].gst, _MMCAMCORDER_HANDLER_STILLSHOT, "handoff", - G_CALLBACK(__mmcamcorder_encodesink_handoff_callback), + G_CALLBACK(__mmcamcorder_handoff_callback), hcamcorder); return MM_ERROR_NONE; @@ -185,7 +184,7 @@ int _mmcamcorder_remove_stillshot_pipeline(MMHandleType handle) return ret; } - _mmcamcorder_remove_all_handlers(handle, _MMCAMCORDER_HANDLER_STILLSHOT); + _mmcamcorder_remove_all_handlers(handle, _MMCAMCORDER_HANDLER_STILLSHOT | _MMCAMCORDER_HANDLER_VIDEOREC); GstPad *reqpad = NULL; @@ -225,11 +224,19 @@ void _mmcamcorder_destroy_video_capture_pipeline(MMHandleType handle) MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_QUE].gst, "empty-buffers", TRUE); MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_QUE].gst, "empty-buffers", TRUE); + traceBegin(TTRACE_TAG_CAMERA, "MMCAMCORDER:UNREALIZE:SET_NULL_TO_PIPELINE"); + _mmcamcorder_gst_set_state(handle, sc->element[_MMCAMCORDER_MAIN_PIPE].gst, GST_STATE_NULL); + traceEnd(TTRACE_TAG_CAMERA); + _mmcamcorder_remove_all_handlers(handle, _MMCAMCORDER_HANDLER_CATEGORY_ALL); + traceBegin(TTRACE_TAG_CAMERA, "MMCAMCORDER:UNREALIZE:UNREF_PIPELINE"); + gst_object_unref(sc->element[_MMCAMCORDER_MAIN_PIPE].gst); + + traceEnd(TTRACE_TAG_CAMERA); /* NULL initialization will be done in _mmcamcorder_element_release_noti */ } } @@ -253,7 +260,6 @@ int _mmcamcorder_image_cmd_capture(MMHandleType handle) const char *videosrc_name = NULL; GstCameraControl *control = NULL; - GstClock *pipe_clock = NULL; mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle); _MMCamcorderImageInfo *info = NULL; @@ -270,6 +276,11 @@ int _mmcamcorder_image_cmd_capture(MMHandleType handle) info = sc->info_image; + if (info->capturing) { + _mmcam_dbg_err("already capturing"); + return MM_ERROR_CAMCORDER_DEVICE_BUSY; + } + _mmcamcorder_conf_get_value_int(hcamcorder->conf_main, CONFIGURE_CATEGORY_MAIN_CAPTURE, "UseCaptureMode", @@ -282,11 +293,6 @@ int _mmcamcorder_image_cmd_capture(MMHandleType handle) _mmcamcorder_conf_get_value_element_name(VideosrcElement, &videosrc_name); - if (info->capturing) { - ret = MM_ERROR_CAMCORDER_DEVICE_BUSY; - goto cmd_error; - } - /* get current state */ mm_camcorder_get_state(handle, ¤t_state); @@ -312,11 +318,13 @@ int _mmcamcorder_image_cmd_capture(MMHandleType handle) err_name = NULL; } + ret = MM_ERROR_NONE; + /* check capture count */ if (info->count < 1) { _mmcam_dbg_err("capture count[%d] is invalid", info->count); ret = MM_ERROR_CAMCORDER_INVALID_ARGUMENT; - goto cmd_error; + goto cmd_done; } else if (info->count == 1) { info->type = _MMCamcorder_SINGLE_SHOT; } else { @@ -333,8 +341,7 @@ int _mmcamcorder_image_cmd_capture(MMHandleType handle) } _mmcam_dbg_log("preview(%dx%d,fmt:%d), capture(%dx%d,fmt:%d), count(%d), hdr mode(%d), interval (%d)", - width, height, info->preview_format, - info->width, info->height, cap_format, + width, height, info->preview_format, info->width, info->height, cap_format, info->count, info->hdr_capture_mode, info->interval); /* check state */ @@ -343,7 +350,7 @@ int _mmcamcorder_image_cmd_capture(MMHandleType handle) info->hdr_capture_mode != MM_CAMCORDER_HDR_OFF) { _mmcam_dbg_err("does not support multi/HDR capture while recording"); ret = MM_ERROR_CAMCORDER_INVALID_STATE; - goto cmd_error; + goto cmd_done; } /* check capture size if ZSL is not supported*/ @@ -398,7 +405,8 @@ int _mmcamcorder_image_cmd_capture(MMHandleType handle) if (!GST_IS_CAMERA_CONTROL(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst)) { _mmcam_dbg_err("Can't cast Video source into camera control."); - return MM_ERROR_CAMCORDER_NOT_SUPPORTED; + ret = MM_ERROR_CAMCORDER_NOT_SUPPORTED; + goto cmd_done; } control = GST_CAMERA_CONTROL(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst); @@ -412,7 +420,7 @@ int _mmcamcorder_image_cmd_capture(MMHandleType handle) if (current_state >= MM_CAMCORDER_STATE_RECORDING) { _mmcam_dbg_err("could not capture in this target while recording"); ret = MM_ERROR_CAMCORDER_INVALID_STATE; - goto cmd_error; + goto cmd_done; } if (UseCaptureMode) { @@ -436,12 +444,18 @@ int _mmcamcorder_image_cmd_capture(MMHandleType handle) /* make pipeline state as READY */ ret = _mmcamcorder_gst_set_state(handle, sc->element[_MMCAMCORDER_MAIN_PIPE].gst, GST_STATE_READY); + if (sc->info_image->preview_format == MM_PIXEL_FORMAT_ENCODED_H264) { + if (!_mmcamcorder_recreate_decoder_for_encoded_preview(handle)) { + return MM_ERROR_CAMCORDER_INTERNAL; + } + } + MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_QUE].gst, "empty-buffers", FALSE); MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_QUE].gst, "empty-buffers", FALSE); if (ret != MM_ERROR_NONE) { _mmcam_dbg_err("failed to set state PAUSED %x", ret); - return ret; + goto cmd_done; } if (UseCaptureMode) { @@ -465,7 +479,8 @@ int _mmcamcorder_image_cmd_capture(MMHandleType handle) ret = _mmcamcorder_set_videosrc_caps(handle, sc->fourcc, set_width, set_height, fps, rotation); if (!ret) { _mmcam_dbg_err("_mmcamcorder_set_videosrc_caps failed"); - return MM_ERROR_CAMCORDER_INTERNAL; + ret = MM_ERROR_CAMCORDER_INTERNAL; + goto cmd_done; } info->resolution_change = TRUE; @@ -473,14 +488,10 @@ int _mmcamcorder_image_cmd_capture(MMHandleType handle) /* make pipeline state as PLAYING */ ret = _mmcamcorder_gst_set_state(handle, sc->element[_MMCAMCORDER_MAIN_PIPE].gst, GST_STATE_PLAYING); if (ret != MM_ERROR_NONE) { - _mmcam_dbg_err("failed to set state PAUSED %x", ret); - return ret; + _mmcam_dbg_err("failed to set state PLAYING %x", ret); + goto cmd_done; } - /* FIXME: consider delay */ - pipe_clock = gst_pipeline_get_clock(GST_PIPELINE(sc->element[_MMCAMCORDER_MAIN_PIPE].gst)); - sc->stillshot_time = gst_clock_get_time(pipe_clock) - gst_element_get_base_time(GST_ELEMENT(sc->element[_MMCAMCORDER_MAIN_PIPE].gst)); - _mmcam_dbg_log("Change to target resolution(%d, %d)", set_width, set_height); } else { _mmcam_dbg_log("No need to change resolution. Open toggle now."); @@ -491,7 +502,7 @@ int _mmcamcorder_image_cmd_capture(MMHandleType handle) ret = _mmcamcorder_create_stillshot_pipeline((MMHandleType)hcamcorder); if (ret != MM_ERROR_NONE) { _mmcam_dbg_err("failed to create encodesinkbin %x", ret); - return ret; + goto cmd_done; } ret = mm_camcorder_get_attributes(handle, &err_name, @@ -510,6 +521,9 @@ int _mmcamcorder_image_cmd_capture(MMHandleType handle) MMCAMCORDER_G_OBJECT_SET(sc->encode_element[_MMCAMCORDER_ENCSINK_SINK].gst,"signal-handoffs", TRUE); MMCAMCORDER_G_OBJECT_SET(sc->encode_element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "block", FALSE); + /* Prepare for the shutter sound when it's the bencbin mode capture */ + sc->info_video->is_firstframe = TRUE; + /* set push encoding buffer as TRUE */ sc->info_video->push_encoding_buffer = PUSH_ENCODING_BUFFER_INIT; @@ -517,7 +531,7 @@ int _mmcamcorder_image_cmd_capture(MMHandleType handle) ret = _mmcamcorder_gst_set_state(handle, sc->encode_element[_MMCAMCORDER_ENCODE_MAIN_PIPE].gst, GST_STATE_PLAYING); if (ret != MM_ERROR_NONE) { _mmcam_dbg_err("failed to set state PLAYING %x", ret); - return ret; + goto cmd_done; } } @@ -531,7 +545,6 @@ int _mmcamcorder_image_cmd_capture(MMHandleType handle) !info->hdr_capture_mode) { _mmcamcorder_sound_solo_play((MMHandleType)hcamcorder, _MMCAMCORDER_FILEPATH_CAPTURE_SND, FALSE); } - /* set flag */ info->played_capture_sound = TRUE; } else { @@ -539,10 +552,11 @@ int _mmcamcorder_image_cmd_capture(MMHandleType handle) info->played_capture_sound = FALSE; } - return ret; +cmd_done: + if (ret != MM_ERROR_NONE) { + info->capturing = FALSE; + } -cmd_error: - info->capturing = FALSE; return ret; } @@ -697,6 +711,13 @@ int _mmcamcorder_image_cmd_preview_start(MMHandleType handle) MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_QUE].gst, "empty-buffers", TRUE); MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_QUE].gst, "empty-buffers", TRUE); ret = _mmcamcorder_gst_set_state(handle, pipeline, GST_STATE_READY); + + if (sc->info_image->preview_format == MM_PIXEL_FORMAT_ENCODED_H264) { + if (!_mmcamcorder_recreate_decoder_for_encoded_preview(handle)) { + return MM_ERROR_CAMCORDER_INTERNAL; + } + } + MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_QUE].gst, "empty-buffers", FALSE); MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_QUE].gst, "empty-buffers", FALSE); if (ret != MM_ERROR_NONE) { @@ -731,10 +752,19 @@ int _mmcamcorder_image_cmd_preview_start(MMHandleType handle) _mmcamcorder_sound_finalize(handle); } } else { + if (info->preview_format == MM_PIXEL_FORMAT_ENCODED_H264) { + MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst, "newgop-interval", H264_PREVIEW_NEWGOP_INTERVAL); + } + MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_QUE].gst, "empty-buffers", FALSE); MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_QUE].gst, "empty-buffers", FALSE); + traceBegin(TTRACE_TAG_CAMERA, "MMCAMCORDER:START:SET_PLAYING_TO_PIPELINE"); + ret = _mmcamcorder_gst_set_state(handle, pipeline, GST_STATE_PLAYING); + + traceEnd(TTRACE_TAG_CAMERA); + if (ret != MM_ERROR_NONE) { goto cmd_error; } @@ -749,14 +779,8 @@ int _mmcamcorder_image_cmd_preview_start(MMHandleType handle) _mmcam_dbg_log("sound status %d", info->sound_status); - /* get volume level */ - mm_sound_volume_get_value(VOLUME_TYPE_SYSTEM, &info->volume_level); - - _mmcam_dbg_log("volume level %d", info->volume_level); - /* register changed_cb */ vconf_notify_key_changed(VCONFKEY_SETAPPL_SOUND_STATUS_BOOL, __sound_status_changed_cb, hcamcorder); - mm_sound_volume_add_callback(VOLUME_TYPE_SYSTEM, __volume_level_changed_cb, hcamcorder); } } @@ -820,8 +844,12 @@ int _mmcamcorder_image_cmd_preview_stop(MMHandleType handle) MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_QUE].gst, "empty-buffers", TRUE); MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_QUE].gst, "empty-buffers", TRUE); + traceBegin(TTRACE_TAG_CAMERA, "MMCAMCORDER:STOP:SET_READY_TO_PIPELINE"); + ret = _mmcamcorder_gst_set_state(handle, pipeline, GST_STATE_READY); + traceEnd(TTRACE_TAG_CAMERA); + MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_QUE].gst, "empty-buffers", FALSE); MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_QUE].gst, "empty-buffers", FALSE); @@ -914,12 +942,11 @@ void __mmcamcorder_init_stillshot_info (MMHandleType handle) } -int __mmcamcorder_capture_save_exifinfo(MMHandleType handle, MMCamcorderCaptureDataType *original, MMCamcorderCaptureDataType *thumbnail) +int __mmcamcorder_capture_save_exifinfo(MMHandleType handle, MMCamcorderCaptureDataType *original, MMCamcorderCaptureDataType *thumbnail, int provide_exif) { int ret = MM_ERROR_NONE; unsigned char *data = NULL; unsigned int datalen = 0; - int provide_exif = FALSE; _MMCamcorderSubContext *sc = NULL; mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle); @@ -941,8 +968,8 @@ int __mmcamcorder_capture_save_exifinfo(MMHandleType handle, MMCamcorderCaptureD data = original->data; datalen = original->length; } - MMCAMCORDER_G_OBJECT_GET(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst, "provide-exif", &provide_exif); - if(provide_exif == 0){ + + if (provide_exif == FALSE) { if (thumbnail) { if (thumbnail->data && thumbnail->length > 0) { _mmcam_dbg_log("thumbnail is added!thumbnail->data=%p thumbnail->width=%d ,thumbnail->height=%d", @@ -977,14 +1004,15 @@ int __mmcamcorder_capture_save_exifinfo(MMHandleType handle, MMCamcorderCaptureD } -void __mmcamcorder_get_capture_data_from_buffer(MMCamcorderCaptureDataType *capture_data, int pixtype, GstBuffer *buffer) +void __mmcamcorder_get_capture_data_from_buffer(MMCamcorderCaptureDataType *capture_data, int pixtype, GstSample *sample) { GstCaps *caps = NULL; + GstMapInfo mapinfo; const GstStructure *structure; - mmf_return_if_fail(capture_data && buffer); + mmf_return_if_fail(capture_data && sample); - caps = gst_buffer_get_caps(buffer); + caps = gst_sample_get_caps(sample); if (caps == NULL) { _mmcam_dbg_err("failed to get caps"); goto GET_FAILED; @@ -996,18 +1024,19 @@ void __mmcamcorder_get_capture_data_from_buffer(MMCamcorderCaptureDataType *capt goto GET_FAILED; } - capture_data->data = GST_BUFFER_DATA(buffer); + memset(&mapinfo, 0x0, sizeof(GstMapInfo)); + + gst_buffer_map(gst_sample_get_buffer(sample), &mapinfo, GST_MAP_READ); + capture_data->data = mapinfo.data; capture_data->format = pixtype; gst_structure_get_int(structure, "width", &capture_data->width); gst_structure_get_int(structure, "height", &capture_data->height); - capture_data->length = GST_BUFFER_SIZE(buffer); + capture_data->length = mapinfo.size; + gst_buffer_unmap(gst_sample_get_buffer(sample), &mapinfo); _mmcam_dbg_warn("buffer data[%p],size[%dx%d],length[%d],format[%d]", - capture_data->data, capture_data->width, capture_data->height, - capture_data->length, capture_data->format); - gst_caps_unref(caps); - caps = NULL; - + capture_data->data, capture_data->width, capture_data->height, + capture_data->length, capture_data->format); return; GET_FAILED: @@ -1019,7 +1048,7 @@ GET_FAILED: } -int __mmcamcorder_set_jpeg_data(MMHandleType handle, MMCamcorderCaptureDataType *dest, MMCamcorderCaptureDataType *thumbnail) +int __mmcamcorder_set_jpeg_data(MMHandleType handle, MMCamcorderCaptureDataType *dest, MMCamcorderCaptureDataType *thumbnail, int provide_exif) { mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle); _MMCamcorderSubContext *sc = NULL; @@ -1034,18 +1063,15 @@ int __mmcamcorder_set_jpeg_data(MMHandleType handle, MMCamcorderCaptureDataType /* if tag enable and doesn't provide exif, we make it */ _mmcam_dbg_log("Add exif information if existed(thumbnail[%p])", thumbnail); if (thumbnail && thumbnail->data) { - return __mmcamcorder_capture_save_exifinfo(handle, dest, thumbnail); + return __mmcamcorder_capture_save_exifinfo(handle, dest, thumbnail, provide_exif); } else { - return __mmcamcorder_capture_save_exifinfo(handle, dest, NULL); + return __mmcamcorder_capture_save_exifinfo(handle, dest, NULL, provide_exif); } } -void __mmcamcorder_release_jpeg_data(MMHandleType handle, MMCamcorderCaptureDataType *dest) +void __mmcamcorder_release_jpeg_data(MMHandleType handle, MMCamcorderCaptureDataType *dest, int tag_enable, int provide_exif) { - int tag_enable = 0; - int provide_exif = FALSE; - mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle); _MMCamcorderSubContext *sc = NULL; @@ -1055,10 +1081,7 @@ void __mmcamcorder_release_jpeg_data(MMHandleType handle, MMCamcorderCaptureData sc = MMF_CAMCORDER_SUBCONTEXT(hcamcorder); mmf_return_if_fail(sc); - _mmcam_dbg_log(""); - - mm_camcorder_get_attributes(handle, NULL, MMCAM_TAG_ENABLE, &tag_enable, NULL); - MMCAMCORDER_G_OBJECT_GET(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst, "provide-exif", &provide_exif); + _mmcam_dbg_log("tag : %d, provide exif : %d", tag_enable, provide_exif); /* if dest->data is allocated in MSL, release it */ if (tag_enable && !provide_exif) { @@ -1076,7 +1099,7 @@ void __mmcamcorder_release_jpeg_data(MMHandleType handle, MMCamcorderCaptureData } -static void __mmcamcorder_image_capture_cb(GstElement *element, GstBuffer *buffer1, GstBuffer *buffer2, GstBuffer *buffer3, gpointer u_data) +static void __mmcamcorder_image_capture_cb(GstElement *element, GstSample *sample1, GstSample *sample2, GstSample *sample3, gpointer u_data) { int ret = MM_ERROR_NONE; int pixtype_main = MM_PIXEL_FORMAT_INVALID; @@ -1102,10 +1125,13 @@ static void __mmcamcorder_image_capture_cb(GstElement *element, GstBuffer *buffe mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(u_data); _MMCamcorderImageInfo *info = NULL; _MMCamcorderSubContext *sc = NULL; - MMCamcorderCaptureDataType dest = {NULL, 0, 0, 0, 0, 0}; - MMCamcorderCaptureDataType thumb = {NULL, 0, 0, 0, 0, 0}; - MMCamcorderCaptureDataType scrnail = {NULL, 0, 0, 0, 0, 0}; - MMCamcorderCaptureDataType encode_src = {NULL, 0, 0, 0, 0, 0}; + MMCamcorderCaptureDataType dest = {0,}; + MMCamcorderCaptureDataType thumb = {0,}; + MMCamcorderCaptureDataType scrnail = {0,}; + MMCamcorderCaptureDataType encode_src = {0,}; + GstMapInfo mapinfo1; + GstMapInfo mapinfo2; + GstMapInfo mapinfo3; mmf_attrs_t *attrs = NULL; mmf_attribute_t *item_screennail = NULL; @@ -1118,6 +1144,10 @@ static void __mmcamcorder_image_capture_cb(GstElement *element, GstBuffer *buffe info = sc->info_image; + memset(&mapinfo1, 0x0, sizeof(GstMapInfo)); + memset(&mapinfo2, 0x0, sizeof(GstMapInfo)); + memset(&mapinfo3, 0x0, sizeof(GstMapInfo)); + /* get current state */ current_state = _mmcamcorder_get_state((MMHandleType)hcamcorder); @@ -1133,14 +1163,14 @@ static void __mmcamcorder_image_capture_cb(GstElement *element, GstBuffer *buffe stop_cont_shot, info->capturing); /*free GstBuffer*/ - if (buffer1) { - gst_buffer_unref(buffer1); + if (sample1) { + gst_sample_unref(sample1); } - if (buffer2) { - gst_buffer_unref(buffer2); + if (sample2) { + gst_sample_unref(sample2); } - if (buffer3) { - gst_buffer_unref(buffer3); + if (sample3) { + gst_sample_unref(sample3); } return; @@ -1186,7 +1216,7 @@ static void __mmcamcorder_image_capture_cb(GstElement *element, GstBuffer *buffe memset((void *)&scrnail, 0x0, sizeof(MMCamcorderCaptureDataType)); /* Prepare main, thumbnail buffer */ - pixtype_main = _mmcamcorder_get_pixel_format(buffer1); + pixtype_main = _mmcamcorder_get_pixel_format(gst_sample_get_caps(sample1)); if (pixtype_main == MM_PIXEL_FORMAT_INVALID) { _mmcam_dbg_err("Unsupported pixel type"); MMCAM_SEND_MESSAGE(hcamcorder, MM_MESSAGE_CAMCORDER_ERROR, MM_ERROR_CAMCORDER_INTERNAL); @@ -1194,12 +1224,25 @@ static void __mmcamcorder_image_capture_cb(GstElement *element, GstBuffer *buffe } /* Main image buffer */ - if (buffer1 && GST_BUFFER_DATA(buffer1) && (GST_BUFFER_SIZE(buffer1) !=0)) { - __mmcamcorder_get_capture_data_from_buffer(&dest, pixtype_main, buffer1); - } else { - _mmcam_dbg_err("buffer1 has wrong pointer. (buffer1=%p)",buffer1); + if (!sample1 || !gst_buffer_map(gst_sample_get_buffer(sample1), &mapinfo1, GST_MAP_READ)) { + _mmcam_dbg_err("sample1[%p] is NULL or gst_buffer_map failed", sample1); MMCAM_SEND_MESSAGE(hcamcorder, MM_MESSAGE_CAMCORDER_ERROR, MM_ERROR_CAMCORDER_INTERNAL); goto error; + }else{ + if ( (mapinfo1.data == NULL) && (mapinfo1.size == 0) ){ + _mmcam_dbg_err("mapinfo1 is wrong (%p, size %d)", mapinfo1.data, mapinfo1.size); + MMCAM_SEND_MESSAGE(hcamcorder, MM_MESSAGE_CAMCORDER_ERROR, MM_ERROR_CAMCORDER_INTERNAL); + gst_buffer_unmap(gst_sample_get_buffer(sample1), &mapinfo1); + goto error; + }else + __mmcamcorder_get_capture_data_from_buffer(&dest, pixtype_main, sample1); + } + + if ( !sample2 || !gst_buffer_map(gst_sample_get_buffer(sample2), &mapinfo2, GST_MAP_READ) ) { + _mmcam_dbg_log("sample2[%p] is NULL or gst_buffer_map failed. Not Error.", sample2); + } + if ( !sample3 || !gst_buffer_map(gst_sample_get_buffer(sample3), &mapinfo3, GST_MAP_READ)) { + _mmcam_dbg_log("sample3[%p] is NULL or gst_buffer_map failed. Not Error.", sample3); } /* Screennail image buffer */ @@ -1207,17 +1250,17 @@ static void __mmcamcorder_image_capture_cb(GstElement *element, GstBuffer *buffe mm_attrs_get_index((MMHandleType)attrs, MMCAM_CAPTURED_SCREENNAIL, &attr_index); item_screennail = &attrs->items[attr_index]; - if (buffer3 && GST_BUFFER_DATA(buffer3) && GST_BUFFER_SIZE(buffer3) != 0) { - _mmcam_dbg_log("Screennail (buffer3=%p,size=%d)", buffer3, GST_BUFFER_SIZE(buffer3)); + if (sample3 && mapinfo3.data && mapinfo3.size != 0) { + _mmcam_dbg_log("Screennail (sample3=%p,size=%d)", sample3, mapinfo3.size); - pixtype_scrnl = _mmcamcorder_get_pixel_format(buffer3); - __mmcamcorder_get_capture_data_from_buffer(&scrnail, pixtype_scrnl, buffer3); + pixtype_scrnl = _mmcamcorder_get_pixel_format(gst_sample_get_caps(sample3)); + __mmcamcorder_get_capture_data_from_buffer(&scrnail, pixtype_scrnl, sample3); /* Set screennail attribute for application */ ret = mmf_attribute_set_data(item_screennail, &scrnail, sizeof(scrnail)); _mmcam_dbg_log("Screennail set attribute data %p, size %d, ret %x", &scrnail, sizeof(scrnail), ret); } else { - _mmcam_dbg_log("buffer3 has wrong pointer. Not Error. (buffer3=%p)",buffer3); + _mmcam_dbg_log("Sample3 has wrong pointer. Not Error. (sample3=%p)",sample3); mmf_attribute_set_data(item_screennail, NULL, 0); } @@ -1231,12 +1274,12 @@ static void __mmcamcorder_image_capture_cb(GstElement *element, GstBuffer *buffe MMCAMCORDER_G_OBJECT_GET(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst, "provide-exif", &provide_exif); /* Thumbnail image buffer */ - if (buffer2 && GST_BUFFER_DATA(buffer2) && (GST_BUFFER_SIZE(buffer2) != 0)) { - _mmcam_dbg_log("Thumnail (buffer2=%p)",buffer2); - pixtype_thumb = _mmcamcorder_get_pixel_format(buffer2); - __mmcamcorder_get_capture_data_from_buffer(&thumb, pixtype_thumb, buffer2); + if (sample2 && mapinfo2.data && (mapinfo2.size != 0)) { + _mmcam_dbg_log("Thumbnail (buffer2=%p)",gst_sample_get_buffer(sample2)); + pixtype_thumb = _mmcamcorder_get_pixel_format(gst_sample_get_caps(sample2)); + __mmcamcorder_get_capture_data_from_buffer(&thumb, pixtype_thumb, sample2); } else { - _mmcam_dbg_log("buffer2 has wrong pointer. Not Error. (buffer2 %p)", buffer2); + _mmcam_dbg_log("Sample2 has wrong pointer. Not Error. (sample2 %p)", sample2); if (pixtype_main == MM_PIXEL_FORMAT_ENCODED && provide_exif) { ExifLoader *l; @@ -1357,7 +1400,7 @@ static void __mmcamcorder_image_capture_cb(GstElement *element, GstBuffer *buffe if (thumb_raw_data) { ret = _mmcamcorder_encode_jpeg(thumb_raw_data, thumb_width, thumb_height, encode_src.format, thumb_length, THUMBNAIL_JPEG_QUALITY, - (void **)&internal_thumb_data, &internal_thumb_length, JPEG_ENCODER_SOFTWARE); + (void **)&internal_thumb_data, &internal_thumb_length); if (ret) { _mmcam_dbg_log("encode THUMBNAIL done - data %p, length %d", internal_thumb_data, internal_thumb_length); @@ -1393,9 +1436,9 @@ static void __mmcamcorder_image_capture_cb(GstElement *element, GstBuffer *buffe NULL); _mmcam_dbg_log("Start Internal Encode - capture_quality %d", capture_quality); - ret = _mmcamcorder_encode_jpeg(GST_BUFFER_DATA(buffer1), dest.width, dest.height, + ret = _mmcamcorder_encode_jpeg(mapinfo1.data, dest.width, dest.height, pixtype_main, dest.length, capture_quality, - (void **)&internal_main_data, &internal_main_length, JPEG_ENCODER_HARDWARE); + (void **)&internal_main_data, &internal_main_length); if (!ret) { _mmcam_dbg_err("_mmcamcorder_encode_jpeg failed"); @@ -1478,7 +1521,7 @@ static void __mmcamcorder_image_capture_cb(GstElement *element, GstBuffer *buffe case MM_IMAGE_CODEC_JPEG: case MM_IMAGE_CODEC_SRW: case MM_IMAGE_CODEC_JPEG_SRW: - ret = __mmcamcorder_set_jpeg_data((MMHandleType)hcamcorder, &dest, &thumb); + ret = __mmcamcorder_set_jpeg_data((MMHandleType)hcamcorder, &dest, &thumb, provide_exif); if (ret != MM_ERROR_NONE) { _mmcam_dbg_err("Error on setting extra data to jpeg"); MMCAM_SEND_MESSAGE(hcamcorder, MM_MESSAGE_CAMCORDER_ERROR, ret); @@ -1532,7 +1575,7 @@ err_release_exif: /* Release jpeg data */ if (pixtype_main == MM_PIXEL_FORMAT_ENCODED) { - __mmcamcorder_release_jpeg_data((MMHandleType)hcamcorder, &dest); + __mmcamcorder_release_jpeg_data((MMHandleType)hcamcorder, &dest, tag_enable, provide_exif); } error: @@ -1546,7 +1589,7 @@ error: if (sc->internal_encode) { compare_data = internal_main_data; } else { - compare_data = GST_BUFFER_DATA(buffer1); + compare_data = mapinfo1.data; } if (dest.data && compare_data && dest.data != compare_data) { @@ -1570,14 +1613,17 @@ error: compare_data = NULL; /*free GstBuffer*/ - if (buffer1) { - gst_buffer_unref(buffer1); + if (sample1) { + gst_buffer_unmap(gst_sample_get_buffer(sample1), &mapinfo1); + gst_sample_unref(sample1); } - if (buffer2) { - gst_buffer_unref(buffer2); + if (sample2) { + gst_buffer_unmap(gst_sample_get_buffer(sample2), &mapinfo2); + gst_sample_unref(sample2); } - if (buffer3) { - gst_buffer_unref(buffer3); + if (sample3) { + gst_buffer_unmap(gst_sample_get_buffer(sample3), &mapinfo3); + gst_sample_unref(sample3); } /* destroy exif info */ @@ -1599,9 +1645,22 @@ error: } } - /* Handle capture in recording case */ - if (hcamcorder->capture_in_recording) { + if (current_state >= MM_CAMCORDER_STATE_RECORDING) { + /* Handle capture in recording case */ hcamcorder->capture_in_recording = FALSE; + + pthread_mutex_lock(&(hcamcorder->task_thread_lock)); + + if (hcamcorder->task_thread_state == _MMCAMCORDER_TASK_THREAD_STATE_CHECK_CAPTURE_IN_RECORDING) { + _mmcam_dbg_log("send signal for capture in recording"); + pthread_cond_signal(&(hcamcorder->task_thread_cond)); + } else { + _mmcam_dbg_warn("unexpected task thread state : %d", hcamcorder->task_thread_state); + } + + pthread_mutex_unlock(&(hcamcorder->task_thread_lock)); + + _MMCAMCORDER_CMD_SIGNAL(hcamcorder); } _mmcam_dbg_err("END"); @@ -1610,7 +1669,7 @@ error: } -static gboolean __mmcamcorder_encodesink_handoff_callback(GstElement *fakesink, GstBuffer *buffer, GstPad *pad, gpointer u_data) +gboolean __mmcamcorder_handoff_callback(GstElement *fakesink, GstBuffer *buffer, GstPad *pad, gpointer u_data) { mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(u_data); _MMCamcorderSubContext *sc = NULL; @@ -1623,7 +1682,7 @@ static gboolean __mmcamcorder_encodesink_handoff_callback(GstElement *fakesink, _mmcam_dbg_log(""); /* FIXME. How could you get a thumbnail? */ - __mmcamcorder_image_capture_cb(fakesink, buffer, NULL, NULL, u_data); + __mmcamcorder_image_capture_cb(fakesink, gst_sample_new(buffer, gst_pad_get_current_caps(pad), NULL, NULL), NULL, NULL, u_data); if (sc->encode_element[_MMCAMCORDER_ENCSINK_ENCBIN].gst) { MMCAMCORDER_G_OBJECT_SET(sc->encode_element[_MMCAMCORDER_ENCSINK_SINK].gst, "signal-handoffs", FALSE); @@ -1673,8 +1732,7 @@ static ExifData *__mmcamcorder_update_exif_make(MMHandleType handle, ExifData *e EXIF_SET_ERR(ret, EXIF_TAG_MAKE); } } else { - ret = MM_ERROR_CAMCORDER_LOW_MEMORY; - EXIF_SET_ERR(ret, EXIF_TAG_MAKE); + _mmcam_dbg_err("low memory maker is null"); } exit: @@ -2058,8 +2116,8 @@ int __mmcamcorder_set_exif_basic_info(MMHandleType handle, int image_width, int /* get ExifData from exif info */ ed = mm_exif_get_exif_from_info(hcamcorder->exif_info); - if (ed == NULL || ed->ifd == NULL) { - _mmcam_dbg_err("get exif data error!!(%p, %p)", ed, (ed ? ed->ifd : NULL)); + if (ed == NULL) { + _mmcam_dbg_err("exif data is null from exif_info"); return MM_ERROR_INVALID_HANDLE; } @@ -2807,22 +2865,3 @@ static void __sound_status_changed_cb(keynode_t* node, void *data) return; } - - -static void __volume_level_changed_cb(void *data) -{ - mmf_camcorder_t *hcamcorder = (mmf_camcorder_t *)data; - _MMCamcorderImageInfo *info = NULL; - - mmf_return_if_fail(hcamcorder && hcamcorder->sub_context && hcamcorder->sub_context->info_image); - - _mmcam_dbg_log("START"); - - info = hcamcorder->sub_context->info_image; - - mm_sound_volume_get_value(VOLUME_TYPE_SYSTEM, &info->volume_level); - - _mmcam_dbg_log("DONE : volume level %d", info->volume_level); - - return; -} diff --git a/src/mm_camcorder_util.c b/src/mm_camcorder_util.c index 9b27762..b079d86 100644 --- a/src/mm_camcorder_util.c +++ b/src/mm_camcorder_util.c @@ -24,14 +24,21 @@ =======================================================================================*/ #include #include +#include #include /* struct statfs */ -#include #include /* gettimeofday */ +#include +#include +#include +#include #include "mm_camcorder_internal.h" #include "mm_camcorder_util.h" #include "mm_camcorder_sound.h" #include +#include + +#include /*----------------------------------------------------------------------- | GLOBAL VARIABLE DEFINITIONS for internal | @@ -40,7 +47,8 @@ /*----------------------------------------------------------------------- | LOCAL VARIABLE DEFINITIONS for internal | -----------------------------------------------------------------------*/ -#define TIME_STRING_MAX_LEN 64 +#define TIME_STRING_MAX_LEN 64 +#define __MMCAMCORDER_CAPTURE_WAIT_TIMEOUT 5 #define FPUTC_CHECK(x_char, x_file)\ {\ @@ -64,7 +72,7 @@ | LOCAL FUNCTION PROTOTYPES: | ---------------------------------------------------------------------------*/ /* STATIC INTERNAL FUNCTION */ - + //static gint skip_mdat(FILE *f); static guint16 get_language_code(const char *str); static gchar* str_to_utf8(const gchar *str); @@ -72,6 +80,13 @@ static inline gboolean write_tag(FILE *f, const gchar *tag); static inline gboolean write_to_32(FILE *f, guint val); static inline gboolean write_to_16(FILE *f, guint val); static inline gboolean write_to_24(FILE *f, guint val); +#ifdef _USE_YUV_TO_RGB888_ +static gboolean _mmcamcorder_convert_YUV_to_RGB888(unsigned char *src, int src_fmt, guint width, guint height, unsigned char **dst, unsigned int *dst_len); +#endif /* _USE_YUV_TO_RGB888_ */ +static gboolean _mmcamcorder_convert_YUYV_to_I420(unsigned char *src, guint width, guint height, unsigned char **dst, unsigned int *dst_len); +static gboolean _mmcamcorder_convert_UYVY_to_I420(unsigned char *src, guint width, guint height, unsigned char **dst, unsigned int *dst_len); +static gboolean _mmcamcorder_convert_NV12_to_I420(unsigned char *src, guint width, guint height, unsigned char **dst, unsigned int *dst_len); + /*=========================================================================================== | | @@ -82,88 +97,83 @@ static inline gboolean write_to_24(FILE *f, guint val); | GLOBAL FUNCTION DEFINITIONS: | ---------------------------------------------------------------------------*/ -static int __append_variant(DBusMessageIter *iter, const char *sig, char *param[]) +static int __gdbus_method_call_sync(const char* bus_name, const char* object, const char* iface, + const char* method, GVariant* args, GVariant** result, bool is_sync) { - const char *ch; - int i; - int int_type; - uint64_t int64_type; - - if (!sig || !param) - return 0; - - for (ch = sig, i = 0; *ch != '\0'; ++i, ++ch) { - switch (*ch) { - case 'i': - int_type = atoi(param[i]); - dbus_message_iter_append_basic(iter, DBUS_TYPE_INT32, &int_type); - break; - case 'u': - int_type = atoi(param[i]); - dbus_message_iter_append_basic(iter, DBUS_TYPE_UINT32, &int_type); - break; - case 't': - int64_type = atoi(param[i]); - dbus_message_iter_append_basic(iter, DBUS_TYPE_UINT64, &int64_type); - break; - case 's': - dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, ¶m[i]); - break; - default: - return -1; + int ret = MM_ERROR_NONE; + GError *err = NULL; + GVariant* dbus_reply = NULL; + GDBusConnection *conn = NULL; + + if (!object || !iface || !method) { + _mmcam_dbg_err("Invalid Argument"); + if (!object) + _mmcam_dbg_err("object null"); + if (!iface) + _mmcam_dbg_err("iface null"); + if (!method) + _mmcam_dbg_err("method null"); + return MM_ERROR_INVALID_ARGUMENT; + } + + conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, NULL); + if (conn == NULL) { + _mmcam_dbg_err("get connection failed"); + return MM_ERROR_CAMCORDER_INTERNAL; + } + + _mmcam_dbg_log("Dbus call with obj : '%s' iface : '%s' method : '%s'", object, iface, method); + + if (is_sync) { + dbus_reply = g_dbus_connection_call_sync(conn, bus_name, object, iface, + method, args, NULL, G_DBUS_CALL_FLAGS_NONE, + G_DBUS_REPLY_TIMEOUT, NULL, &err); + if (dbus_reply) { + _mmcam_dbg_log("Method Call '%s.%s' Success", iface, method); + *result = dbus_reply; + } else { + _mmcam_dbg_err("dbus method call sync reply failed"); + ret = MM_ERROR_CAMCORDER_INTERNAL; } + } else { + g_dbus_connection_call(conn, bus_name, object, iface, \ + method, args, \ + NULL, G_DBUS_CALL_FLAGS_NONE, G_DBUS_REPLY_TIMEOUT, \ + NULL, NULL, NULL); } - - return 0; + g_object_unref(conn); + return ret; } -#define DBUS_REPLY_TIMEOUT (120 * 1000) -static DBusMessage *__invoke_dbus_method_sync(const char *dest, const char *path, - const char *interface, const char *method, - const char *sig, char *param[]) -{ - DBusConnection *conn; - DBusMessage *msg; - DBusMessageIter iter; - DBusMessage *reply; - DBusError err; - int r; - - conn = dbus_bus_get(DBUS_BUS_SYSTEM, NULL); - if (!conn) { - _mmcam_dbg_err( "dbus_bus_get error"); - return NULL; - } - msg = dbus_message_new_method_call(dest, path, interface, method); - if (!msg) { - _mmcam_dbg_err("dbus_message_new_method_call(%s:%s-%s)", path, interface, method); - return NULL; - } +static int __storage_device_supported_cb(int storage_id, storage_type_e type, storage_state_e state, const char *path, void *user_data) +{ + char **root_directory = (char **)user_data; - dbus_message_iter_init_append(msg, &iter); - r = __append_variant(&iter, sig, param); - if (r < 0) { - _mmcam_dbg_err("append_variant error(%d)", r); - return NULL; + if (root_directory == NULL) { + _mmcam_dbg_warn("user data is NULL"); + return FALSE; } - dbus_error_init(&err); + _mmcam_dbg_log("storage id %d, type %d, state %d, path %s", + storage_id, type, state, path ? path : "NULL"); - reply = dbus_connection_send_with_reply_and_block(conn, msg, DBUS_REPLY_TIMEOUT, &err); - if (!reply) { - _mmcam_dbg_err("dbus_connection_send error(No reply)"); - } + if (type == STORAGE_TYPE_INTERNAL && path) { + if (*root_directory) { + free(*root_directory); + *root_directory = NULL; + } - if (dbus_error_is_set(&err)) { - _mmcam_dbg_err("dbus_connection_send error(%s:%s)", err.name, err.message); - reply = NULL; + *root_directory = strdup(path); + if (*root_directory) { + _mmcam_dbg_log("get root directory %s", *root_directory); + return FALSE; + } else { + _mmcam_dbg_warn("strdup %s failed"); + } } - dbus_message_unref(msg); - dbus_error_free(&err); - - return reply; + return TRUE; } @@ -183,8 +193,8 @@ gint _mmcamcorder_find_tag(FILE *f, guint32 tag_fourcc, gboolean do_rewind) } while ((read_item = fread(&buf, sizeof(guchar), 8, f)) > 0) { - unsigned long long buf_size = 0; - unsigned int buf_fourcc = 0; + uint64_t buf_size = 0; + uint32_t buf_fourcc = 0; if (read_item < 8) { _mmcam_dbg_err("fread failed : %d", read_item); @@ -199,27 +209,28 @@ gint _mmcamcorder_find_tag(FILE *f, guint32 tag_fourcc, gboolean do_rewind) } else { _mmcam_dbg_log("skip [%c%c%c%c] tag", MMCAM_FOURCC_ARGS(buf_fourcc)); - buf_size = (unsigned long long)_mmcamcorder_get_container_size(buf); - buf_size = buf_size - 8; /* include tag */ - - do { - if (buf_size > _MMCAMCORDER_MAX_INT) { - _mmcam_dbg_log("seek %d", _MMCAMCORDER_MAX_INT); - if (fseek(f, _MMCAMCORDER_MAX_INT, SEEK_CUR) != 0) { - _mmcam_dbg_err("fseek() fail"); - return FALSE; - } + buf_size = _mmcamcorder_get_container_size(buf); - buf_size -= _MMCAMCORDER_MAX_INT; - } else { - _mmcam_dbg_log("seek %d", buf_size); - if (fseek(f, buf_size, SEEK_CUR) != 0) { - _mmcam_dbg_err("fseek() fail"); - return FALSE; - } - break; + /* if size of mdat is 1, it means largesize is used.(bigger than 4GB) */ + if (buf_fourcc == MMCAM_FOURCC('m','d','a','t') && + buf_size == 1) { + read_item = fread(&buf, sizeof(guchar), 8, f); + if (read_item < 8) { + _mmcam_dbg_err("fread failed"); + return FALSE; } - } while (TRUE); + + buf_size = _mmcamcorder_get_container_size64(buf); + buf_size = buf_size - 16; /* include tag and large file flag(size 1) */ + } else { + buf_size = buf_size - 8; /* include tag */ + } + + _mmcam_dbg_log("seek %llu", buf_size); + if (fseeko(f, (off_t)buf_size, SEEK_CUR) != 0) { + _mmcam_dbg_err("fseeko() fail"); + return FALSE; + } } } @@ -238,8 +249,8 @@ gboolean _mmcamcorder_find_fourcc(FILE *f, guint32 tag_fourcc, gboolean do_rewin } while ((read_item = fread(&buf, sizeof(guchar), 8, f)) > 0) { - unsigned long long buf_size = 0; - unsigned int buf_fourcc = 0; + uint64_t buf_size = 0; + uint32_t buf_fourcc = 0; if (read_item < 8) { _mmcam_dbg_err("fread failed : %d", read_item); @@ -251,38 +262,38 @@ gboolean _mmcamcorder_find_fourcc(FILE *f, guint32 tag_fourcc, gboolean do_rewin if (tag_fourcc == buf_fourcc) { _mmcam_dbg_log("find tag : %c%c%c%c", MMCAM_FOURCC_ARGS(tag_fourcc)); return TRUE; - } - else if((buf_fourcc == MMCAM_FOURCC('m','o','o','v')) && (tag_fourcc != buf_fourcc)){ - if(_mmcamcorder_find_fourcc(f,tag_fourcc,FALSE)){ + } else if (buf_fourcc == MMCAM_FOURCC('m','o','o','v') && + tag_fourcc != buf_fourcc) { + if (_mmcamcorder_find_fourcc(f, tag_fourcc, FALSE)) { return TRUE; - } - else{ + } else { continue; } } else { _mmcam_dbg_log("skip [%c%c%c%c] tag", MMCAM_FOURCC_ARGS(buf_fourcc)); - buf_size = (unsigned long long)_mmcamcorder_get_container_size(buf); - buf_size = buf_size - 8; /* include tag */ + buf_size = _mmcamcorder_get_container_size(buf); - do { - if (buf_size > _MMCAMCORDER_MAX_INT) { - _mmcam_dbg_log("seek %d", _MMCAMCORDER_MAX_INT); - if (fseek(f, _MMCAMCORDER_MAX_INT, SEEK_CUR) != 0) { - _mmcam_dbg_err("fseek() fail"); - return FALSE; - } - - buf_size -= _MMCAMCORDER_MAX_INT; - } else { - _mmcam_dbg_log("seek %d", buf_size); - if (fseek(f, buf_size, SEEK_CUR) != 0) { - _mmcam_dbg_err("fseek() fail"); - return FALSE; - } - break; + /* if size of mdat is 1, it means largesize is used.(bigger than 4GB) */ + if (buf_fourcc == MMCAM_FOURCC('m','d','a','t') && + buf_size == 1) { + read_item = fread(&buf, sizeof(guchar), 8, f); + if (read_item < 8) { + _mmcam_dbg_err("fread failed"); + return FALSE; } - } while (TRUE); + + buf_size = _mmcamcorder_get_container_size64(buf); + buf_size = buf_size - 16; /* include tag and large file flag(size 1) */ + } else { + buf_size = buf_size - 8; /* include tag */ + } + + _mmcam_dbg_log("seek %llu", buf_size); + if (fseeko(f, (off_t)buf_size, SEEK_CUR) != 0) { + _mmcam_dbg_err("fseeko() fail"); + return FALSE; + } } } @@ -294,7 +305,7 @@ gboolean _mmcamcorder_find_fourcc(FILE *f, guint32 tag_fourcc, gboolean do_rewin gboolean _mmcamcorder_update_size(FILE *f, gint64 prev_pos, gint64 curr_pos) { _mmcam_dbg_log("size : %"G_GINT64_FORMAT"", curr_pos-prev_pos); - if(fseek(f, prev_pos, SEEK_SET) != 0) + if(fseeko(f, prev_pos, SEEK_SET) != 0) { _mmcam_dbg_err("fseek() fail"); return FALSE; @@ -303,7 +314,7 @@ gboolean _mmcamcorder_update_size(FILE *f, gint64 prev_pos, gint64 curr_pos) if (!write_to_32(f, curr_pos -prev_pos)) return FALSE; - if(fseek(f, curr_pos, SEEK_SET) != 0) + if(fseeko(f, curr_pos, SEEK_SET) != 0) { _mmcam_dbg_err("fseek() fail"); return FALSE; @@ -311,7 +322,7 @@ gboolean _mmcamcorder_update_size(FILE *f, gint64 prev_pos, gint64 curr_pos) return TRUE; } -// VIDEO TAG - CAMCORDER + gboolean _mmcamcorder_write_loci(FILE *f, _MMCamcorderLocationInfo info) { gint64 current_pos, pos; @@ -319,9 +330,9 @@ gboolean _mmcamcorder_write_loci(FILE *f, _MMCamcorderLocationInfo info) _mmcam_dbg_log(""); - if((pos = ftell(f))<0) + if((pos = ftello(f))<0) { - _mmcam_dbg_err("ftell() returns negative value"); + _mmcam_dbg_err("ftello() returns negative value"); return FALSE; } @@ -330,50 +341,50 @@ gboolean _mmcamcorder_write_loci(FILE *f, _MMCamcorderLocationInfo info) if(!write_tag(f, "loci")) // type return FALSE; - + FPUTC_CHECK(0, f); // version if(!write_to_24(f, 0)) // flags return FALSE; - + if(!write_to_16(f, get_language_code("eng"))) // language return FALSE; - + str = str_to_utf8("location_name"); - + FPUTS_CHECK(str, f); // name SAFE_FREE(str); - + FPUTC_CHECK('\0', f); FPUTC_CHECK(0, f); //role - + if(!write_to_32(f, info.longitude)) // Longitude return FALSE; - + if(!write_to_32(f, info.latitude)) // Latitude return FALSE; - + if(! write_to_32(f, info.altitude)) // Altitude return FALSE; - + str = str_to_utf8("Astronomical_body"); FPUTS_CHECK(str, f);//Astronomical_body SAFE_FREE(str); - + FPUTC_CHECK('\0', f); - + str = str_to_utf8("Additional_notes"); FPUTS_CHECK(str, f); // Additional_notes SAFE_FREE(str); - + FPUTC_CHECK('\0', f); - - if((current_pos = ftell(f))<0) + + if((current_pos = ftello(f))<0) { - _mmcam_dbg_err("ftell() returns negative value"); + _mmcam_dbg_err("ftello() returns negative value"); return FALSE; } - + if(! _mmcamcorder_update_size(f, pos, current_pos)) return FALSE; @@ -442,9 +453,9 @@ gboolean _mmcamcorder_write_geodata(FILE *f,_MMCamcorderLocationInfo info) { _mmcam_dbg_log(""); - if((pos = ftell(f))<0) + if((pos = ftello(f))<0) { - _mmcam_dbg_err("ftell() returns negative value"); + _mmcam_dbg_err("ftello() returns negative value"); return FALSE; } @@ -462,9 +473,9 @@ gboolean _mmcamcorder_write_geodata(FILE *f,_MMCamcorderLocationInfo info) { FPUTC_CHECK(0x2F, f); - if((current_pos = ftell(f))<0) + if((current_pos = ftello(f))<0) { - _mmcam_dbg_err("ftell() returns negative value"); + _mmcam_dbg_err("ftello() returns negative value"); return FALSE; } @@ -485,8 +496,8 @@ gboolean _mmcamcorder_write_udta(FILE *f, int gps_enable, _MMCamcorderLocationIn return TRUE; } - if ((pos = ftell(f))<0) { - _mmcam_dbg_err("ftell() returns negative value"); + if ((pos = ftello(f))<0) { + _mmcam_dbg_err("ftello() returns negative value"); return FALSE; } @@ -514,8 +525,8 @@ gboolean _mmcamcorder_write_udta(FILE *f, int gps_enable, _MMCamcorderLocationIn } } - if ((current_pos = ftell(f))<0) { - _mmcam_dbg_err("ftell() returns negative value"); + if ((current_pos = ftello(f))<0) { + _mmcam_dbg_err("ftello() returns negative value"); return FALSE; } @@ -549,6 +560,33 @@ guint64 _mmcamcorder_get_container_size(const guchar *size) } +guint64 _mmcamcorder_get_container_size64(const guchar *size) +{ + guint64 result = 0; + guint64 temp = 0; + + temp = size[0]; + result = temp << 56; + temp = size[1]; + result = result | (temp << 48); + temp = size[2]; + result = result | (temp << 40); + temp = size[3]; + result = result | (temp << 32); + temp = size[4]; + result = result | (temp << 24); + temp = size[5]; + result = result | (temp << 16); + temp = size[6]; + result = result | (temp << 8); + result = result | size[7]; + + _mmcam_dbg_log("result : %lld", (unsigned long long)result); + + return result; +} + + gboolean _mmcamcorder_update_composition_matrix(FILE *f, int orientation) { /* for 0 degree */ @@ -596,24 +634,55 @@ gboolean _mmcamcorder_update_composition_matrix(FILE *f, int orientation) } -int _mmcamcorder_get_freespace(const gchar *path, guint64 *free_space) +int _mmcamcorder_get_freespace(const gchar *path, const gchar *root_directory, guint64 *free_space) { - struct statfs fs; + int ret = 0; + int is_internal = 0; + struct statvfs vfs; + struct stat stat_path; + struct stat stat_root; - g_assert(path); + if (path == NULL || root_directory == NULL || free_space == NULL) { + _mmcam_dbg_err("invalid parameter %p, %p, %p", path, root_directory, free_space); + return -1; + } - if (!g_file_test(path, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR)) { - _mmcam_dbg_log("File(%s) doesn't exist.", path); - return -2; + if (stat(path, &stat_path) != 0) { + *free_space = 0; + _mmcam_dbg_err("failed to stat for [%s][errno %d]", path, errno); + return -1; } - if (-1 == statfs(path, &fs)) { - _mmcam_dbg_log("statfs failed.(%s)", path); + if (stat(root_directory, &stat_root) != 0) { + *free_space = 0; + _mmcam_dbg_err("failed to stat for [%s][errno %d]", path, errno); return -1; } - *free_space = (guint64)fs.f_bsize * fs.f_bavail; - return 1; + if (stat_path.st_dev == stat_root.st_dev) { + is_internal = TRUE; + } else { + is_internal = FALSE; + } + + if (is_internal) { + ret = storage_get_internal_memory_size(&vfs); + } else { + ret = storage_get_external_memory_size(&vfs); + } + + if (ret < 0) { + *free_space = 0; + _mmcam_dbg_err("failed to get memory size [%s]", path); + return -1; + } else { + *free_space = vfs.f_bsize * vfs.f_bavail; + /* + _mmcam_dbg_log("vfs.f_bsize [%lu], vfs.f_bavail [%lu]", vfs.f_bsize, vfs.f_bavail); + _mmcam_dbg_log("memory size %llu [%s]", *free_space, path); + */ + return 1; + } } @@ -639,36 +708,34 @@ int _mmcamcorder_get_file_system_type(const gchar *path, int *file_system_type) } -int _mmcamcorder_get_freespace_except_system(guint64 *free_space) +int _mmcamcorder_get_device_flash_brightness(int *brightness) { - DBusError err; - DBusMessage *msg; - int ret; - double total_space=0; - double avail_space=0; - - msg = __invoke_dbus_method_sync("org.tizen.system.deviced", "/Org/Tizen/System/DeviceD/Storage", - "org.tizen.system.deviced.storage", "getstorage", NULL, NULL); - if (!msg) { - _mmcam_dbg_log("method_call failed"); - return FALSE; - } - - dbus_error_init(&err); - - ret = dbus_message_get_args(msg, &err, DBUS_TYPE_INT64, &total_space, DBUS_TYPE_INT64, &avail_space, DBUS_TYPE_INVALID); - if (!ret) { - _mmcam_dbg_log("no message : [%s:%s]", err.name, err.message); - return FALSE; + int get_value = 0; + int ret = MM_ERROR_NONE; + GVariant *params = NULL, *result = NULL; + const char *param_type = "(i)"; + + if ((ret = __gdbus_method_call_sync("org.tizen.system.deviced", + "/Org/Tizen/System/DeviceD/Led", + "org.tizen.system.deviced.Led", + "GetBrightnessForCamera", + params, + &result, + TRUE)) != MM_ERROR_NONE) { + _mmcam_dbg_err("Dbus Call on Client Error"); + return ret; + } + + if (result) { + g_variant_get(result, param_type, &get_value); + *brightness = get_value; + _mmcam_dbg_log("flash brightness : %d", *brightness); + } else { + _mmcam_dbg_err("replied result is null"); + ret = MM_ERROR_CAMCORDER_INTERNAL; } - dbus_message_unref(msg); - dbus_error_free(&err); - - *free_space = (guint64)avail_space; - _mmcam_dbg_err(" free space [%" G_GUINT64_FORMAT "] ",*free_space); - - return 1; + return ret; } int _mmcamcorder_get_file_size(const char *filename, guint64 *size) @@ -710,7 +777,7 @@ void _mmcamcorder_remove_buffer_probe(MMHandleType handle, _MMCamcorderHandlerCa if (item->object && GST_IS_PAD(item->object)) { _mmcam_dbg_log("Remove buffer probe on [%s:%s] - [ID : %lu], [Category : %x]", GST_DEBUG_PAD_NAME(item->object), item->handler_id, item->category); - gst_pad_remove_buffer_probe(GST_PAD(item->object), item->handler_id); + gst_pad_remove_probe(GST_PAD(item->object), item->handler_id); } else { _mmcam_dbg_warn("Remove buffer probe faild, the pad is null or not pad, just remove item from list and free it"); } @@ -763,7 +830,7 @@ void _mmcamcorder_remove_one_buffer_probe(MMHandleType handle, void *object) if (GST_IS_PAD(item->object)) { _mmcam_dbg_log("Remove buffer probe on [%s:%s] - [ID : %lu], [Category : %x]", GST_DEBUG_PAD_NAME(item->object), item->handler_id, item->category); - gst_pad_remove_buffer_probe(GST_PAD(item->object), item->handler_id); + gst_pad_remove_probe(GST_PAD(item->object), item->handler_id); } else { _mmcam_dbg_warn("Remove buffer probe faild, the pad is null or not pad, just remove item from list and free it"); } @@ -813,7 +880,7 @@ void _mmcamcorder_remove_event_probe(MMHandleType handle, _MMCamcorderHandlerCat if (item->object && GST_IS_PAD(item->object)) { _mmcam_dbg_log("Remove event probe on [%s:%s] - [ID : %lu], [Category : %x]", GST_DEBUG_PAD_NAME(item->object), item->handler_id, item->category); - gst_pad_remove_event_probe(GST_PAD(item->object), item->handler_id); + gst_pad_remove_probe(GST_PAD(item->object), item->handler_id); } else { _mmcam_dbg_warn("Remove event probe faild, the pad is null or not pad, just remove item from list and free it"); } @@ -949,8 +1016,7 @@ void _mmcamcorder_element_release_noti(gpointer data, GObject *where_the_object_ } -gboolean -_mmcamcroder_msg_callback(void *data) +gboolean _mmcamcorder_msg_callback(void *data) { _MMCamcorderMsgItem *item = (_MMCamcorderMsgItem*)data; mmf_camcorder_t *hcamcorder = NULL; @@ -960,11 +1026,10 @@ _mmcamcroder_msg_callback(void *data) hcamcorder = MMF_CAMCORDER(item->handle); if (hcamcorder == NULL) { - _mmcam_dbg_warn("msg id:%x, item:%p, handle is NULL", item->id, item); + _mmcam_dbg_warn("msg id:0x%x, item:%p, handle is NULL", item->id, item); goto MSG_CALLBACK_DONE; } - /*_mmcam_dbg_log("msg id:%x, msg_cb:%p, msg_data:%p, item:%p", item->id, hcamcorder->msg_cb, hcamcorder->msg_data, item);*/ _MMCAMCORDER_LOCK((MMHandleType)hcamcorder); @@ -986,6 +1051,8 @@ _mmcamcroder_msg_callback(void *data) _MMCAMCORDER_UNLOCK_MESSAGE_CALLBACK(hcamcorder); + _MMCAMCORDER_SIGNAL(hcamcorder); + MSG_CALLBACK_DONE: /* release allocated memory */ if (item->id == MM_MESSAGE_CAMCORDER_FACE_DETECT_INFO) { @@ -994,10 +1061,23 @@ MSG_CALLBACK_DONE: SAFE_FREE(cam_fd_info->face_info); free(cam_fd_info); cam_fd_info = NULL; + + item->param.data = NULL; + item->param.size = 0; } + } else if (item->id == MM_MESSAGE_CAMCORDER_VIDEO_CAPTURED || + item->id == MM_MESSAGE_CAMCORDER_AUDIO_CAPTURED) { + MMCamRecordingReport *report = (MMCamRecordingReport *)item->param.data; + if (report) { + if (report->recording_filename) { + free(report->recording_filename); + report->recording_filename = NULL; + } + free(report); + report = NULL; - item->param.data = NULL; - item->param.size = 0; + item->param.data = NULL; + } } g_mutex_unlock(&item->lock); @@ -1011,8 +1091,7 @@ MSG_CALLBACK_DONE: } -gboolean -_mmcamcroder_send_message(MMHandleType handle, _MMCamcorderMsgItem *data) +gboolean _mmcamcorder_send_message(MMHandleType handle, _MMCamcorderMsgItem *data) { mmf_camcorder_t* hcamcorder = MMF_CAMCORDER(handle); _MMCamcorderMsgItem *item = NULL; @@ -1057,27 +1136,30 @@ _mmcamcroder_send_message(MMHandleType handle, _MMCamcorderMsgItem *data) _MMCAMCORDER_LOCK(handle); hcamcorder->msg_data = g_list_append(hcamcorder->msg_data, item); - //_mmcam_dbg_log("item[%p]", item); + /*_mmcam_dbg_log("item[%p]", item);*/ /* Use DEFAULT priority */ - g_idle_add_full(G_PRIORITY_DEFAULT, _mmcamcroder_msg_callback, item, NULL); + g_idle_add_full(G_PRIORITY_DEFAULT, _mmcamcorder_msg_callback, item, NULL); _MMCAMCORDER_UNLOCK(handle); } else { - _mmcam_dbg_err("item malloc failed : %d", sizeof(_MMCamcorderMsgItem)); + _mmcam_dbg_err("item[id:0x%x] malloc failed : %d", data->id, sizeof(_MMCamcorderMsgItem)); } return TRUE; } -void -_mmcamcroder_remove_message_all(MMHandleType handle) +void _mmcamcorder_remove_message_all(MMHandleType handle) { mmf_camcorder_t* hcamcorder = MMF_CAMCORDER(handle); _MMCamcorderMsgItem *item = NULL; gboolean ret = TRUE; GList *list = NULL; + struct timespec timeout; + struct timeval tv; + struct timeval tv_to_add; + struct timeval tv_result; mmf_return_if_fail(hcamcorder); @@ -1086,6 +1168,9 @@ _mmcamcroder_remove_message_all(MMHandleType handle) if (!hcamcorder->msg_data) { _mmcam_dbg_log("No message data is remained."); } else { + tv_to_add.tv_sec = 0; + tv_to_add.tv_usec = 1000 * 100; /* 100 ms */ + list = hcamcorder->msg_data; while (list) { @@ -1096,36 +1181,66 @@ _mmcamcroder_remove_message_all(MMHandleType handle) _mmcam_dbg_err("Fail to remove message. The item is NULL"); } else { if (g_mutex_trylock(&item->lock)) { - ret = g_idle_remove_by_data (item); - _mmcam_dbg_log("Remove item[%p]. ret[%d]", item, ret); + ret = g_idle_remove_by_data(item); - hcamcorder->msg_data = g_list_remove(hcamcorder->msg_data, item); + _mmcam_dbg_log("remove msg item[%p], ret[%d]", item, ret); - if (ret ) { - /* release allocated memory */ - if (item->id == MM_MESSAGE_CAMCORDER_FACE_DETECT_INFO) { - MMCamFaceDetectInfo *cam_fd_info = (MMCamFaceDetectInfo *)item->param.data; - if (cam_fd_info) { - SAFE_FREE(cam_fd_info->face_info); - free(cam_fd_info); - cam_fd_info = NULL; - } + if (ret == FALSE) { + item->handle = 0; + _mmcam_dbg_warn("failed to remove msg cb for item %p, it will be called later with NULL handle", item); + } + + /* release allocated memory */ + if (item->id == MM_MESSAGE_CAMCORDER_FACE_DETECT_INFO) { + MMCamFaceDetectInfo *cam_fd_info = (MMCamFaceDetectInfo *)item->param.data; + if (cam_fd_info) { + SAFE_FREE(cam_fd_info->face_info); + free(cam_fd_info); + cam_fd_info = NULL; item->param.data = NULL; item->param.size = 0; } + } else if (item->id == MM_MESSAGE_CAMCORDER_VIDEO_CAPTURED || + item->id == MM_MESSAGE_CAMCORDER_AUDIO_CAPTURED) { + MMCamRecordingReport *report = (MMCamRecordingReport *)item->param.data; + if (report) { + if (report->recording_filename) { + free(report->recording_filename); + report->recording_filename = NULL; + } + free(report); + report = NULL; + + item->param.data = NULL; + } + } - g_mutex_unlock(&item->lock); + hcamcorder->msg_data = g_list_remove(hcamcorder->msg_data, item); + + g_mutex_unlock(&item->lock); + + if (ret == TRUE) { g_mutex_clear(&item->lock); - SAFE_FREE(item); - } else { - item->handle = 0; - _mmcam_dbg_warn("Fail to remove item[%p]", item); - g_mutex_unlock(&item->lock); + free(item); + item = NULL; + + _mmcam_dbg_log("remove msg done"); } } else { _mmcam_dbg_warn("item lock failed. it's being called..."); + + gettimeofday(&tv, NULL); + timeradd(&tv, &tv_to_add, &tv_result); + timeout.tv_sec = tv_result.tv_sec; + timeout.tv_nsec = tv_result.tv_usec * 1000; + + if (_MMCAMCORDER_TIMED_WAIT(handle, timeout)) { + _mmcam_dbg_warn("timeout"); + } else { + _mmcam_dbg_warn("signal received"); + } } } } @@ -1146,17 +1261,16 @@ _mmcamcroder_remove_message_all(MMHandleType handle) } -int _mmcamcorder_get_pixel_format(GstBuffer *buffer) +int _mmcamcorder_get_pixel_format(GstCaps *caps) { - GstCaps *caps = NULL; const GstStructure *structure; const char *media_type; + GstVideoInfo media_info; MMPixelFormatType type = 0; unsigned int fourcc = 0; - - mmf_return_val_if_fail( buffer != NULL, MM_PIXEL_FORMAT_INVALID ); - caps = gst_buffer_get_caps (buffer); + mmf_return_val_if_fail( caps != NULL, MM_PIXEL_FORMAT_INVALID ); + structure = gst_caps_get_structure (caps, 0); media_type = gst_structure_get_name (structure); if (media_type == NULL) { @@ -1164,25 +1278,31 @@ int _mmcamcorder_get_pixel_format(GstBuffer *buffer) return MM_PIXEL_FORMAT_INVALID; } + gst_video_info_init (&media_info); + if (!strcmp (media_type, "image/jpeg") ) { _mmcam_dbg_log("It is jpeg."); type = MM_PIXEL_FORMAT_ENCODED; - } else if (!strcmp (media_type, "video/x-raw-yuv")) { + } else if (!strcmp (media_type, "video/x-raw") && + gst_video_info_from_caps(&media_info, caps) && + GST_VIDEO_INFO_IS_YUV(&media_info)) { _mmcam_dbg_log("It is yuv."); - gst_structure_get_fourcc (structure, "format", &fourcc); + fourcc = gst_video_format_to_fourcc(GST_VIDEO_INFO_FORMAT(&media_info)); type = _mmcamcorder_get_pixtype(fourcc); - } else if (!strcmp (media_type, "video/x-raw-rgb")) { + } else if (!strcmp (media_type, "video/x-raw") && + gst_video_info_from_caps(&media_info, caps) && + GST_VIDEO_INFO_IS_RGB(&media_info)) { _mmcam_dbg_log("It is rgb."); type = MM_PIXEL_FORMAT_RGB888; + } else if (!strcmp (media_type, "video/x-h264")) { + _mmcam_dbg_log("It is H264"); + type = MM_PIXEL_FORMAT_ENCODED_H264; } else { - _mmcam_dbg_err("Not supported format"); + _mmcam_dbg_err("Not supported format [%s]",media_type); type = MM_PIXEL_FORMAT_INVALID; } - - /*_mmcam_dbg_log( "Type [%d]", type );*/ - gst_caps_unref( caps ); - caps = NULL; + /*_mmcam_dbg_log( "Type [%d]", type );*/ return type; } @@ -1258,6 +1378,9 @@ unsigned int _mmcamcorder_get_fourcc(int pixtype, int codectype, int use_zero_co case MM_PIXEL_FORMAT_ITLV_JPEG_UYVY: fourcc = GST_MAKE_FOURCC('I','T','L','V'); break; + case MM_PIXEL_FORMAT_ENCODED_H264: + fourcc = GST_MAKE_FOURCC('H','2','6','4'); + break; default: _mmcam_dbg_log("Not proper pixel type[%d]. Set default - I420", pixtype); if (use_zero_copy_format) { @@ -1333,6 +1456,9 @@ int _mmcamcorder_get_pixtype(unsigned int fourcc) case GST_MAKE_FOURCC ('I', 'T', 'L', 'V'): pixtype = MM_PIXEL_FORMAT_ITLV_JPEG_UYVY; break; + case GST_MAKE_FOURCC ('H', '2', '6', '4'): + pixtype = MM_PIXEL_FORMAT_ENCODED_H264; + break; default: _mmcam_dbg_log("Not supported fourcc type(%c%c%c%c)", fourcc, fourcc>>8, fourcc>>16, fourcc>>24); @@ -1480,93 +1606,97 @@ gboolean _mmcamcorder_resize_frame(unsigned char *src_data, unsigned int src_wid gboolean _mmcamcorder_encode_jpeg(void *src_data, unsigned int src_width, unsigned int src_height, int src_format, unsigned int src_length, unsigned int jpeg_quality, - void **result_data, unsigned int *result_length, int enc_type) + void **result_data, unsigned int *result_length) { int ret = 0; - int i = 0; + gboolean ret_conv = TRUE; guint32 src_fourcc = 0; - gboolean do_encode = FALSE; - jpegenc_parameter enc_param; - jpegenc_info enc_info; - - _mmcam_dbg_log("START - enc_type [%d]", enc_type); + int jpeg_format = 0; + unsigned char *converted_src = NULL; + unsigned int converted_src_size = 0; mmf_return_val_if_fail(src_data && result_data && result_length, FALSE); - CLEAR(enc_param); - CLEAR(enc_info); - - camsrcjpegenc_get_info(&enc_info); - src_fourcc = _mmcamcorder_get_fourcc(src_format, 0, FALSE); - camsrcjpegenc_get_src_fmt(src_fourcc, &(enc_param.src_fmt)); - if (enc_param.src_fmt == COLOR_FORMAT_NOT_SUPPORT) { - _mmcam_dbg_err("Not Supported FOURCC(format:%d)", src_format); - return FALSE; - } - - /* check H/W encoder */ - if (enc_info.hw_support && enc_type == JPEG_ENCODER_HARDWARE) { - _mmcam_dbg_log("check H/W encoder supported format list"); - /* Check supported format */ - for (i = 0 ; i < enc_info.hw_enc.input_fmt_num ; i++) { - if (enc_param.src_fmt == enc_info.hw_enc.input_fmt_list[i]) { - do_encode = TRUE; - break; - } - } + switch (src_format) { + case MM_PIXEL_FORMAT_NV12: + //jpeg_format = MM_UTIL_JPEG_FMT_NV12; + ret_conv = _mmcamcorder_convert_NV12_to_I420(src_data,src_width,src_height,&converted_src,&converted_src_size); + jpeg_format = MM_UTIL_JPEG_FMT_YUV420; + break; + case MM_PIXEL_FORMAT_NV16: + jpeg_format = MM_UTIL_JPEG_FMT_NV16; + converted_src = src_data; + break; + case MM_PIXEL_FORMAT_NV21: + jpeg_format = MM_UTIL_JPEG_FMT_NV21; + converted_src = src_data; + break; + case MM_PIXEL_FORMAT_YUYV: + //jpeg_format = MM_UTIL_JPEG_FMT_YUYV; + ret_conv = _mmcamcorder_convert_YUYV_to_I420(src_data,src_width,src_height,&converted_src,&converted_src_size); + jpeg_format = MM_UTIL_JPEG_FMT_YUV420; + break; + case MM_PIXEL_FORMAT_UYVY: + //jpeg_format = MM_UTIL_JPEG_FMT_UYVY; + ret_conv = _mmcamcorder_convert_UYVY_to_I420(src_data,src_width,src_height,&converted_src,&converted_src_size); + jpeg_format = MM_UTIL_JPEG_FMT_YUV420; + break; + case MM_PIXEL_FORMAT_I420: + jpeg_format = MM_UTIL_JPEG_FMT_YUV420; + converted_src = src_data; + break; + case MM_PIXEL_FORMAT_RGB888: + jpeg_format = MM_UTIL_JPEG_FMT_RGB888; + converted_src = src_data; + break; + case MM_PIXEL_FORMAT_RGBA: + jpeg_format = MM_UTIL_JPEG_FMT_RGBA8888; + converted_src = src_data; + break; + case MM_PIXEL_FORMAT_ARGB: + jpeg_format = MM_UTIL_JPEG_FMT_ARGB8888; + converted_src = src_data; + break; + case MM_PIXEL_FORMAT_422P: + jpeg_format = MM_UTIL_JPEG_FMT_YUV422; // not supported + return FALSE; + case MM_PIXEL_FORMAT_NV12T: + case MM_PIXEL_FORMAT_YV12: + case MM_PIXEL_FORMAT_RGB565: + case MM_PIXEL_FORMAT_ENCODED: + case MM_PIXEL_FORMAT_ITLV_JPEG_UYVY: + default: + return FALSE; - if (do_encode) { - enc_type = JPEG_ENCODER_HARDWARE; - } } - /* check S/W encoder */ - if (!do_encode && enc_info.sw_support) { - _mmcam_dbg_log("check S/W encoder supported format list"); - /* Check supported format */ - for (i = 0 ; i < enc_info.sw_enc.input_fmt_num ; i++) { - if (enc_param.src_fmt == enc_info.sw_enc.input_fmt_list[i]) { - do_encode = TRUE; - break; - } - } - - if (do_encode) { - enc_type = JPEG_ENCODER_SOFTWARE; + if (ret_conv == FALSE) { + if (converted_src && + converted_src != src_data) { + free(converted_src); + converted_src = NULL; } + _mmcam_dbg_err("color convert error source format[%d], jpeg format[%d]", src_format, jpeg_format); + return FALSE; } - if (do_encode) { - enc_param.src_data = src_data; - enc_param.width = src_width; - enc_param.height = src_height; - enc_param.src_len = src_length; - enc_param.jpeg_mode = JPEG_MODE_BASELINE; - enc_param.jpeg_quality = jpeg_quality; - - _mmcam_dbg_log("%ux%u, size %u, quality %u, type %d", - src_width, src_height, src_length, - jpeg_quality, enc_type); - - ret = camsrcjpegenc_encode(&enc_info, enc_type, &enc_param ); - if (ret == CAMSRC_JPEGENC_ERROR_NONE) { - *result_data = enc_param.result_data; - *result_length = enc_param.result_len; - - _mmcam_dbg_log("JPEG encode length(%d)", *result_length); + ret = mm_util_jpeg_encode_to_memory(result_data, (int *)result_length, + converted_src, src_width, src_height, + jpeg_format, jpeg_quality); - return TRUE; - } else { - _mmcam_dbg_err("camsrcjpegenc_encode failed(%x)", ret); - return FALSE; - } + if (converted_src && (converted_src != src_data)) { + free(converted_src); + converted_src = NULL; } - _mmcam_dbg_err("No encoder supports %d format", src_format); + if (ret != MM_ERROR_NONE) { + _mmcam_dbg_err("No encoder supports %d format, error code %x", src_format, ret); + return FALSE; + } - return FALSE; + return TRUE; } @@ -1630,14 +1760,6 @@ gboolean _mmcamcorder_downscale_UYVYorYUYV(unsigned char *src, unsigned int src_ return TRUE; } -gboolean _mmcamcorder_check_file_path(const gchar *path) -{ - if(strstr(path, "/opt/usr") != NULL) { - return TRUE; - } - return FALSE; -} - static guint16 get_language_code(const char *str) { return (guint16) (((str[0]-0x60) & 0x1F) << 10) + (((str[1]-0x60) & 0x1F) << 5) + ((str[2]-0x60) & 0x1F); @@ -1653,7 +1775,7 @@ static inline gboolean write_tag(FILE *f, const gchar *tag) while(*tag) FPUTC_CHECK(*tag++, f); - return TRUE; + return TRUE; } static inline gboolean write_to_32(FILE *f, guint val) @@ -1669,17 +1791,17 @@ static inline gboolean write_to_16(FILE *f, guint val) { FPUTC_CHECK(val >> 8, f); FPUTC_CHECK(val, f); - return TRUE; + return TRUE; } static inline gboolean write_to_24(FILE *f, guint val) { write_to_16(f, val >> 8); FPUTC_CHECK(val, f); - return TRUE; + return TRUE; } -void *_mmcamcorder_util_task_thread_func(void *data) +void *_mmcamcorder_task_thread_func(void *data) { int ret = MM_ERROR_NONE; mmf_camcorder_t *hcamcorder = (mmf_camcorder_t *)data; @@ -1704,6 +1826,10 @@ void *_mmcamcorder_util_task_thread_func(void *data) _mmcamcorder_sound_play((MMHandleType)hcamcorder, _MMCAMCORDER_SAMPLE_SOUND_NAME_CAPTURE, FALSE); hcamcorder->task_thread_state = _MMCAMCORDER_TASK_THREAD_STATE_NONE; break; + case _MMCAMCORDER_TASK_THREAD_STATE_SOUND_SOLO_PLAY_START: + _mmcamcorder_sound_solo_play((MMHandleType)hcamcorder, _MMCAMCORDER_FILEPATH_CAPTURE_SND, FALSE); + hcamcorder->task_thread_state = _MMCAMCORDER_TASK_THREAD_STATE_NONE; + break; case _MMCAMCORDER_TASK_THREAD_STATE_ENCODE_PIPE_CREATE: ret = _mmcamcorder_video_prepare_record((MMHandleType)hcamcorder); @@ -1713,6 +1839,37 @@ void *_mmcamcorder_util_task_thread_func(void *data) _mmcam_dbg_log("_mmcamcorder_video_prepare_record return 0x%x", ret); hcamcorder->task_thread_state = _MMCAMCORDER_TASK_THREAD_STATE_NONE; break; + case _MMCAMCORDER_TASK_THREAD_STATE_CHECK_CAPTURE_IN_RECORDING: + { + struct timespec timeout; + struct timeval tv; + + gettimeofday(&tv, NULL); + timeout.tv_sec = tv.tv_sec + __MMCAMCORDER_CAPTURE_WAIT_TIMEOUT; + timeout.tv_nsec = tv.tv_usec * 1000; + + _mmcam_dbg_warn("wait for capture data in recording. wait signal..."); + + if (!pthread_cond_timedwait(&(hcamcorder->task_thread_cond), &(hcamcorder->task_thread_lock), &timeout)) { + _mmcam_dbg_warn("signal received"); + } else { + _MMCamcorderMsgItem message; + + memset(&message, 0x0, sizeof(_MMCamcorderMsgItem)); + + _mmcam_dbg_err("capture data wait time out, send error message"); + + message.id = MM_MESSAGE_CAMCORDER_ERROR; + message.param.code = MM_ERROR_CAMCORDER_RESPONSE_TIMEOUT; + + _mmcamcorder_send_message((MMHandleType)hcamcorder, &message); + + hcamcorder->capture_in_recording = FALSE; + } + + hcamcorder->task_thread_state = _MMCAMCORDER_TASK_THREAD_STATE_NONE; + } + break; default: _mmcam_dbg_warn("invalid task thread state %d", hcamcorder->task_thread_state); hcamcorder->task_thread_state = _MMCAMCORDER_TASK_THREAD_STATE_EXIT; @@ -1726,3 +1883,258 @@ void *_mmcamcorder_util_task_thread_func(void *data) return NULL; } + +#ifdef _USE_YUV_TO_RGB888_ +static gboolean +_mmcamcorder_convert_YUV_to_RGB888(unsigned char *src, int src_fmt, guint width, guint height, unsigned char **dst, unsigned int *dst_len) +{ + int ret = 0; + int src_cs = MM_UTIL_IMG_FMT_UYVY; + int dst_cs = MM_UTIL_IMG_FMT_RGB888; + unsigned int dst_size = 0; + + if (src_fmt == COLOR_FORMAT_YUYV) + { + _mmcam_dbg_log("Convert YUYV to RGB888\n"); + src_cs = MM_UTIL_IMG_FMT_YUYV; + } + else if (src_fmt == COLOR_FORMAT_UYVY) + { + _mmcam_dbg_log("Convert UYVY to RGB888\n"); + src_cs = MM_UTIL_IMG_FMT_UYVY; + } + else if (src_fmt == COLOR_FORMAT_NV12) + { + _mmcam_dbg_log("Convert NV12 to RGB888\n"); + src_cs = MM_UTIL_IMG_FMT_NV12; + } + else + { + _mmcam_dbg_err("NOT supported format [%d]\n", src_fmt); + return FALSE; + } + + ret = mm_util_get_image_size(dst_cs, width, height, &dst_size); + if (ret != 0) { + _mmcam_dbg_err("mm_util_get_image_size failed [%x]\n", ret); + return FALSE; + } + + *dst = malloc(dst_size); + if (*dst == NULL) + { + _mmcam_dbg_err("malloc failed\n"); + return FALSE; + } + + *dst_len = dst_size; + ret = mm_util_convert_colorspace(src, width, height, src_cs, *dst, dst_cs); + if(ret == 0) + { + _mmcam_dbg_log("Convert [dst_size:%d] OK.\n", dst_size); + return TRUE; + } + else + { + free(*dst); + *dst = NULL; + + _mmcam_dbg_err("Convert [size:%d] FAILED.\n", dst_size); + return FALSE; + } +} +#endif /* _USE_YUV_TO_RGB888_ */ + + +static gboolean _mmcamcorder_convert_YUYV_to_I420(unsigned char *src, guint width, guint height, unsigned char **dst, unsigned int *dst_len) +{ + unsigned int i = 0; + int j = 0; + int src_offset = 0; + int dst_y_offset = 0; + int dst_u_offset = 0; + int dst_v_offset = 0; + int loop_length = 0; + unsigned int dst_size = 0; + unsigned char *dst_data = NULL; + + if (!src || !dst || !dst_len) { + _mmcam_dbg_err("NULL pointer %p, %p, %p", src, dst, dst_len); + return FALSE; + } + + dst_size = (width * height * 3) >> 1; + + _mmcam_dbg_log("YUVY -> I420 : %dx%d, dst size %d", width, height, dst_size); + + dst_data = (unsigned char *)malloc(dst_size); + if (!dst_data) { + _mmcam_dbg_err("failed to alloc dst_data. size %d", dst_size); + return FALSE; + } + + loop_length = width << 1; + dst_u_offset = width * height; + dst_v_offset = dst_u_offset + (dst_u_offset >> 2); + + _mmcam_dbg_log("offset y %d, u %d, v %d", dst_y_offset, dst_u_offset, dst_v_offset); + + for (i = 0 ; i < height ; i++) { + for (j = 0 ; j < loop_length ; j += 2) { + dst_data[dst_y_offset++] = src[src_offset++]; /*Y*/ + + if (i % 2 == 0) { + if (j % 4 == 0) { + dst_data[dst_u_offset++] = src[src_offset++]; /*U*/ + } else { + dst_data[dst_v_offset++] = src[src_offset++]; /*V*/ + } + } else { + src_offset++; + } + } + } + + *dst = dst_data; + *dst_len = dst_size; + + _mmcam_dbg_log("DONE: YUVY -> I420 : %dx%d, dst data %p, size %d", + width, height, *dst, dst_size); + + return TRUE; +} + + +static gboolean _mmcamcorder_convert_UYVY_to_I420(unsigned char *src, guint width, guint height, unsigned char **dst, unsigned int *dst_len) +{ + unsigned int i = 0; + int j = 0; + int src_offset = 0; + int dst_y_offset = 0; + int dst_u_offset = 0; + int dst_v_offset = 0; + int loop_length = 0; + unsigned int dst_size = 0; + unsigned char *dst_data = NULL; + + if (!src || !dst || !dst_len) { + _mmcam_dbg_err("NULL pointer %p, %p, %p", src, dst, dst_len); + return FALSE; + } + + dst_size = (width * height * 3) >> 1; + + _mmcam_dbg_log("UYVY -> I420 : %dx%d, dst size %d", width, height, dst_size); + + dst_data = (unsigned char *)malloc(dst_size); + if (!dst_data) { + _mmcam_dbg_err("failed to alloc dst_data. size %d", dst_size); + return FALSE; + } + + loop_length = width << 1; + dst_u_offset = width * height; + dst_v_offset = dst_u_offset + (dst_u_offset >> 2); + + _mmcam_dbg_log("offset y %d, u %d, v %d", dst_y_offset, dst_u_offset, dst_v_offset); + + for (i = 0 ; i < height ; i++) { + for (j = 0 ; j < loop_length ; j += 2) { + if (i % 2 == 0) { + if (j % 4 == 0) { + dst_data[dst_u_offset++] = src[src_offset++]; /*U*/ + } else { + dst_data[dst_v_offset++] = src[src_offset++]; /*V*/ + } + } else { + src_offset++; + } + + dst_data[dst_y_offset++] = src[src_offset++]; /*Y*/ + } + } + + *dst = dst_data; + *dst_len = dst_size; + + _mmcam_dbg_log("DONE: UYVY -> I420 : %dx%d, dst data %p, size %d", + width, height, *dst, dst_size); + + return TRUE; +} + + +static gboolean _mmcamcorder_convert_NV12_to_I420(unsigned char *src, guint width, guint height, unsigned char **dst, unsigned int *dst_len) +{ + int i = 0; + int src_offset = 0; + int dst_y_offset = 0; + int dst_u_offset = 0; + int dst_v_offset = 0; + int loop_length = 0; + unsigned int dst_size = 0; + unsigned char *dst_data = NULL; + + if (!src || !dst || !dst_len) { + _mmcam_dbg_err("NULL pointer %p, %p, %p", src, dst, dst_len); + return FALSE; + } + + dst_size = (width * height * 3) >> 1; + + _mmcam_dbg_log("NV12 -> I420 : %dx%d, dst size %d", width, height, dst_size); + + dst_data = (unsigned char *)malloc(dst_size); + if (!dst_data) { + _mmcam_dbg_err("failed to alloc dst_data. size %d", dst_size); + return FALSE; + } + + loop_length = width << 1; + dst_u_offset = width * height; + dst_v_offset = dst_u_offset + (dst_u_offset >> 2); + + _mmcam_dbg_log("offset y %d, u %d, v %d", dst_y_offset, dst_u_offset, dst_v_offset); + + /* memcpy Y */ + memcpy(dst_data, src, dst_u_offset); + + loop_length = dst_u_offset >> 1; + src_offset = dst_u_offset; + + /* set U and V */ + for (i = 0 ; i < loop_length ; i++) { + if (i % 2 == 0) { + dst_data[dst_u_offset++] = src[src_offset++]; + } else { + dst_data[dst_v_offset++] = src[src_offset++]; + } + } + + *dst = dst_data; + *dst_len = dst_size; + + _mmcam_dbg_log("DONE: NV12 -> I420 : %dx%d, dst data %p, size %d", + width, height, *dst, dst_size); + + return TRUE; +} + + +int _mmcamcorder_get_root_directory(char **root_directory) +{ + int ret = STORAGE_ERROR_NONE; + + if (root_directory == NULL) { + _mmcam_dbg_warn("user data is NULL"); + return MM_ERROR_CAMCORDER_INVALID_ARGUMENT; + } + + ret = storage_foreach_device_supported((storage_device_supported_cb)__storage_device_supported_cb, root_directory); + if (ret != STORAGE_ERROR_NONE) { + _mmcam_dbg_err("storage_foreach_device_supported failed 0x%x", ret); + return MM_ERROR_CAMCORDER_INTERNAL; + } + + return MM_ERROR_NONE; +} diff --git a/src/mm_camcorder_videorec.c b/src/mm_camcorder_videorec.c index 78788d0..b4307c9 100644 --- a/src/mm_camcorder_videorec.c +++ b/src/mm_camcorder_videorec.c @@ -22,7 +22,7 @@ /*======================================================================================= | INCLUDE FILES | =======================================================================================*/ -#include +#include #include #include "mm_camcorder_internal.h" #include "mm_camcorder_videorec.h" @@ -31,7 +31,6 @@ | GLOBAL VARIABLE DEFINITIONS for internal | ---------------------------------------------------------------------------------------*/ #define _MMCAMCORDER_LOCATION_INFO // for add gps information -#define MAX_ERROR_MESSAGE_LEN 128 /*--------------------------------------------------------------------------------------- | LOCAL VARIABLE DEFINITIONS for internal | @@ -39,21 +38,23 @@ #define _MMCAMCORDER_MINIMUM_FRAME 5 #define _MMCAMCORDER_RETRIAL_COUNT 10 #define _MMCAMCORDER_FRAME_WAIT_TIME 200000 /* ms */ +#define _MMCAMCORDER_CAPTURE_WAIT_TIME 5 /* seconds */ #define _OFFSET_COMPOSITION_MATRIX 40L +#define _GOP_GEN_INTERVAL 1000000000 /*nano seconds*/ /*--------------------------------------------------------------------------------------- | LOCAL FUNCTION PROTOTYPES: | ---------------------------------------------------------------------------------------*/ /* STATIC INTERNAL FUNCTION */ -static void __mmcamcorder_video_stream_cb(GstElement *element, GstBuffer *buffer, gpointer u_data); -static gboolean __mmcamcorder_audio_dataprobe_check(GstPad *pad, GstBuffer *buffer, gpointer u_data); -static gboolean __mmcamcorder_video_dataprobe_record(GstPad *pad, GstBuffer *buffer, gpointer u_data); -static gboolean __mmcamcorder_audioque_dataprobe(GstPad *pad, GstBuffer *buffer, gpointer u_data); -static gboolean __mmcamcorder_video_dataprobe_audio_disable(GstPad *pad, GstBuffer *buffer, gpointer u_data); -static gboolean __mmcamcorder_audio_dataprobe_audio_mute(GstPad *pad, GstBuffer *buffer, gpointer u_data); +static void __mmcamcorder_video_stream_cb(GstElement *element, GstSample *sample, gpointer u_data); +static GstPadProbeReturn __mmcamcorder_audio_dataprobe_check(GstPad *pad, GstPadProbeInfo *info, gpointer u_data); +static GstPadProbeReturn __mmcamcorder_video_dataprobe_record(GstPad *pad, GstPadProbeInfo *info, gpointer u_data); +static GstPadProbeReturn __mmcamcorder_audioque_dataprobe(GstPad *pad, GstPadProbeInfo *info, gpointer u_data); +static GstPadProbeReturn __mmcamcorder_video_dataprobe_audio_disable(GstPad *pad, GstPadProbeInfo *info, gpointer u_data); +static GstPadProbeReturn __mmcamcorder_audio_dataprobe_audio_mute(GstPad *pad, GstPadProbeInfo *info, gpointer u_data); static gboolean __mmcamcorder_add_metadata(MMHandleType handle, int fileformat); static gboolean __mmcamcorder_add_metadata_mp4(MMHandleType handle); -static gboolean __mmcamcorder_eventprobe_monitor(GstPad *pad, GstEvent *event, gpointer u_data); +static GstPadProbeReturn __mmcamcorder_eventprobe_monitor(GstPad *pad, GstPadProbeInfo *info, gpointer u_data); /*======================================================================================= | FUNCTION DEFINITIONS | @@ -61,13 +62,14 @@ static gboolean __mmcamcorder_eventprobe_monitor(GstPad *pad, GstEvent *event, g /*--------------------------------------------------------------------------------------- | GLOBAL FUNCTION DEFINITIONS: | ---------------------------------------------------------------------------------------*/ -static void __mmcamcorder_video_stream_cb(GstElement *element, GstBuffer *buffer, gpointer u_data) +static void __mmcamcorder_video_stream_cb(GstElement *element, GstSample *sample, gpointer u_data) { mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(u_data); _MMCamcorderSubContext *sc = NULL; + GstBuffer *buffer = gst_sample_get_buffer(sample); mmf_return_if_fail(buffer); - mmf_return_if_fail(GST_BUFFER_DATA(buffer)); + mmf_return_if_fail(gst_buffer_n_memory(buffer)); mmf_return_if_fail(hcamcorder); sc = MMF_CAMCORDER_SUBCONTEXT(hcamcorder); @@ -84,8 +86,6 @@ static void __mmcamcorder_video_stream_cb(GstElement *element, GstBuffer *buffer sc->encode_element[_MMCAMCORDER_ENCSINK_SRC].gst) { GstFlowReturn ret = 0; GstClock *pipe_clock = NULL; - GstClockTime timestamp = GST_CLOCK_TIME_NONE; - GstPad *capsfilter_pad = NULL; if(sc->encode_element[_MMCAMCORDER_AUDIOSRC_SRC].gst) { if(sc->info_video->is_firstframe) { @@ -93,31 +93,22 @@ static void __mmcamcorder_video_stream_cb(GstElement *element, GstBuffer *buffer pipe_clock = GST_ELEMENT_CLOCK(sc->encode_element[_MMCAMCORDER_AUDIOSRC_SRC].gst); if (pipe_clock) { gst_object_ref(pipe_clock); - timestamp = GST_BUFFER_TIMESTAMP(buffer) - (gst_clock_get_time(pipe_clock) - GST_ELEMENT(sc->encode_element[_MMCAMCORDER_ENCSINK_SRC].gst)->base_time); + sc->info_video->base_video_ts = GST_BUFFER_PTS(buffer) - (gst_clock_get_time(pipe_clock) - GST_ELEMENT(sc->encode_element[_MMCAMCORDER_ENCSINK_SRC].gst)->base_time); gst_object_unref(pipe_clock); - sc->info_video->prev_video_ts = timestamp; } } } else { if(sc->info_video->is_firstframe) { sc->info_video->is_firstframe = FALSE; - sc->info_video->prev_video_ts = GST_BUFFER_TIMESTAMP(buffer); + sc->info_video->base_video_ts = GST_BUFFER_PTS(buffer); } } - GST_BUFFER_TIMESTAMP(buffer) = GST_BUFFER_TIMESTAMP (buffer) - sc->info_video->prev_video_ts; - capsfilter_pad = gst_element_get_static_pad(sc->encode_element[_MMCAMCORDER_ENCSINK_FILT].gst, "src"); - if (capsfilter_pad) { - gst_buffer_set_caps(buffer, GST_PAD_CAPS(capsfilter_pad)); - gst_object_unref(capsfilter_pad); - capsfilter_pad = NULL; - } else { - _mmcam_dbg_warn("failed to get static pad : encsink_filter - src"); - } + GST_BUFFER_PTS(buffer) = GST_BUFFER_PTS (buffer) - sc->info_video->base_video_ts; ret = gst_app_src_push_buffer((GstAppSrc *)sc->encode_element[_MMCAMCORDER_ENCSINK_SRC].gst, buffer); if (ret != GST_FLOW_OK && - ret != GST_FLOW_WRONG_STATE) { + ret != GST_FLOW_FLUSHING) { _mmcam_dbg_err("gst_app_src_push_buffer failed [0x%x]", ret); gst_buffer_unref(buffer); buffer = NULL; @@ -357,7 +348,7 @@ int _mmcamcorder_remove_encode_pipeline(MMHandleType handle) GstPad *reqpad = NULL; mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle); _MMCamcorderSubContext *sc = NULL; - + mmf_return_val_if_fail(hcamcorder, MM_ERROR_CAMCORDER_NOT_INITIALIZED); sc = MMF_CAMCORDER_SUBCONTEXT(handle); @@ -472,6 +463,7 @@ int _mmcamcorder_video_command(MMHandleType handle, int command) { int size = 0; int fileformat = 0; + int count = 0; int ret = MM_ERROR_NONE; double motion_rate = _MMCAMCORDER_DEFAULT_RECORDING_MOTION_RATE; char *err_name = NULL; @@ -509,7 +501,6 @@ int _mmcamcorder_video_command(MMHandleType handle, int command) int ret_free_space = 0; char *dir_name = NULL; guint64 free_space = 0; - guint64 free_space_exceptsystem = 0; int file_system_type = 0; /* Recording */ @@ -559,15 +550,9 @@ int _mmcamcorder_video_command(MMHandleType handle, int command) dir_name = g_path_get_dirname(temp_filename); if (dir_name) { - ret_free_space = _mmcamcorder_get_freespace(dir_name, &free_space); - if(_mmcamcorder_check_file_path(dir_name)) { - ret_free_space = _mmcamcorder_get_freespace_except_system(&free_space_exceptsystem); - hcamcorder->system_memory = free_space - free_space_exceptsystem; - free_space = free_space - hcamcorder->system_memory; - } + ret_free_space = _mmcamcorder_get_freespace(dir_name, hcamcorder->root_directory, &free_space); - _mmcam_dbg_warn("current space - %s [%" G_GUINT64_FORMAT "], system [%" G_GUINT64_FORMAT "]", - dir_name, free_space, hcamcorder->system_memory); + _mmcam_dbg_warn("current space - %s [%" G_GUINT64_FORMAT "]", dir_name, free_space); if (_mmcamcorder_get_file_system_type(dir_name, &file_system_type) == 0) { /* MSDOS_SUPER_MAGIC : 0x4d44 */ @@ -605,15 +590,40 @@ int _mmcamcorder_video_command(MMHandleType handle, int command) } pthread_mutex_unlock(&(hcamcorder->task_thread_lock)); - /* check restart_preview */ + _mmcam_dbg_warn("video size [%dx%d]", info->video_width, info->video_height); - if (info->preview_width != info->video_width && - info->preview_height != info->video_height) { - info->restart_preview = TRUE; - } else { + if (info->video_width == 0 || info->video_height == 0) { + _mmcam_dbg_warn("video size is invalid [%dx%d] use preview size [%dx%d]", + info->video_width, info->video_height, info->preview_width, info->preview_height); + info->video_width = info->preview_width; + info->video_height = info->preview_height; + } + + if (info->support_dual_stream) { + _mmcam_dbg_warn("DUAL STREAM MODE"); + + info->record_dual_stream = TRUE; + + /* No need to restart preview */ + info->restart_preview = FALSE; + + MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst, "video-width", info->video_width); + MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst, "video-height", info->video_height); + } else if (sc->info_image->preview_format == MM_PIXEL_FORMAT_ENCODED_H264 && + info->preview_width == info->video_width && + info->preview_height == info->video_height) { + _mmcam_dbg_log("H264 preview mode and same resolution"); + + /* No need to restart preview */ info->restart_preview = FALSE; + } else { + /* always need to restart preview */ + info->restart_preview = TRUE; } + /* set recording hint */ + MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst, "recording-hint", TRUE); + if (info->restart_preview) { /* stop preview and set new size */ _mmcam_dbg_log("restart preview"); @@ -622,6 +632,12 @@ int _mmcamcorder_video_command(MMHandleType handle, int command) MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_QUE].gst, "empty-buffers", TRUE); ret = _mmcamcorder_gst_set_state(handle, pipeline, GST_STATE_READY); + if (sc->info_image->preview_format == MM_PIXEL_FORMAT_ENCODED_H264) { + if (!_mmcamcorder_recreate_decoder_for_encoded_preview(handle)) { + ret = MM_ERROR_CAMCORDER_INTERNAL; + goto _ERR_CAMCORDER_VIDEO_COMMAND; + } + } MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_QUE].gst, "empty-buffers", FALSE); MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_QUE].gst, "empty-buffers", FALSE); @@ -675,7 +691,7 @@ int _mmcamcorder_video_command(MMHandleType handle, int command) /* set push buffer flag */ info->push_encoding_buffer = PUSH_ENCODING_BUFFER_INIT; - info->prev_video_ts = 0; + info->base_video_ts = 0; /* connect video stream cb signal */ /*130826 Connect video stream cb for handling fast record frame cb*/ @@ -731,7 +747,7 @@ int _mmcamcorder_video_command(MMHandleType handle, int command) info->filesize = 0; sc->ferror_send = FALSE; sc->ferror_count = 0; - sc->error_occurs = FALSE; + hcamcorder->error_occurs = FALSE; sc->bget_eos = FALSE; ret = _mmcamcorder_gst_set_state(handle, sc->encode_element[_MMCAMCORDER_ENCODE_MAIN_PIPE].gst, GST_STATE_PLAYING); @@ -776,8 +792,6 @@ int _mmcamcorder_video_command(MMHandleType handle, int command) break; case _MMCamcorder_CMD_PAUSE: { - int count = 0; - if (info->b_commiting) { _mmcam_dbg_warn("now on commiting previous file!!(command : %d)", command); return MM_ERROR_CAMCORDER_CMD_IS_RUNNING; @@ -789,11 +803,11 @@ int _mmcamcorder_video_command(MMHandleType handle, int command) if (info->video_frame_count >= _MMCAMCORDER_MINIMUM_FRAME) { break; } else if (count == _MMCAMCORDER_RETRIAL_COUNT) { - _mmcam_dbg_err("Pause fail, frame count %" G_GUINT64_FORMAT "", + _mmcam_dbg_err("Pause fail, frame count %llu", info->video_frame_count); return MM_ERROR_CAMCORDER_INVALID_CONDITION; } else { - _mmcam_dbg_warn("Waiting for enough video frame, retrial[%d], frame %" G_GUINT64_FORMAT "", + _mmcam_dbg_warn("Waiting for enough video frame, retrial[%d], frame %llu", count, info->video_frame_count); } @@ -803,11 +817,11 @@ int _mmcamcorder_video_command(MMHandleType handle, int command) if (info->video_frame_count >= _MMCAMCORDER_MINIMUM_FRAME && info->audio_frame_count) { break; } else if (count == _MMCAMCORDER_RETRIAL_COUNT) { - _mmcam_dbg_err("Pause fail, frame count VIDEO[%" G_GUINT64_FORMAT "], AUDIO [%" G_GUINT64_FORMAT "]", + _mmcam_dbg_err("Pause fail, frame count VIDEO[%llu], AUDIO [%llu]", info->video_frame_count, info->audio_frame_count); return MM_ERROR_CAMCORDER_INVALID_CONDITION; } else { - _mmcam_dbg_warn("Waiting for enough frames, retrial [%d], VIDEO[%" G_GUINT64_FORMAT "], AUDIO [%" G_GUINT64_FORMAT "]", + _mmcam_dbg_warn("Waiting for enough frames, retrial [%d], VIDEO[%llu], AUDIO [%llu]", count, info->video_frame_count, info->audio_frame_count); } @@ -826,6 +840,21 @@ int _mmcamcorder_video_command(MMHandleType handle, int command) return MM_ERROR_CAMCORDER_CMD_IS_RUNNING; } + for (count = 0 ; count <= _MMCAMCORDER_RETRIAL_COUNT ; count++) { + /* capturing */ + if (hcamcorder->capture_in_recording == FALSE) { + break; + } else if (count == _MMCAMCORDER_RETRIAL_COUNT) { + _mmcam_dbg_err("Failed to Wait capture data"); + hcamcorder->capture_in_recording = FALSE; + break; + } else { + _mmcam_dbg_warn("Waiting for capture data - retrial [%d]", count); + } + + usleep(_MMCAMCORDER_FRAME_WAIT_TIME); + } + /* block push buffer */ info->push_encoding_buffer = PUSH_ENCODING_BUFFER_STOP; @@ -834,6 +863,9 @@ int _mmcamcorder_video_command(MMHandleType handle, int command) goto _ERR_CAMCORDER_VIDEO_COMMAND; } + /* set recording hint */ + MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst, "recording-hint", FALSE); + /* stop video stream */ if (info->record_dual_stream) { GstCameraControl *control = GST_CAMERA_CONTROL(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst); @@ -856,6 +888,11 @@ int _mmcamcorder_video_command(MMHandleType handle, int command) ret =_mmcamcorder_gst_set_state(handle, pipeline, GST_STATE_READY); + if (sc->info_image->preview_format == MM_PIXEL_FORMAT_ENCODED_H264) { + if (!_mmcamcorder_recreate_decoder_for_encoded_preview(handle)) { + ret = MM_ERROR_CAMCORDER_INTERNAL; + } + } MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_QUE].gst, "empty-buffers", FALSE); MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_QUE].gst, "empty-buffers", FALSE); if (ret != MM_ERROR_NONE) { @@ -865,8 +902,8 @@ int _mmcamcorder_video_command(MMHandleType handle, int command) /* reset restart_preview for inset window layout */ info->restart_preview = FALSE; - ret = _mmcamcorder_set_camera_resolution(handle, info->preview_width, info->preview_height); - if (ret != MM_ERROR_NONE) { + if (!_mmcamcorder_set_camera_resolution(handle, info->preview_width, info->preview_height)) { + ret = MM_ERROR_CAMCORDER_INTERNAL; goto _ERR_CAMCORDER_VIDEO_COMMAND; } @@ -890,12 +927,11 @@ int _mmcamcorder_video_command(MMHandleType handle, int command) info->video_frame_count = 0; info->audio_frame_count = 0; info->filesize = 0; + hcamcorder->capture_in_recording = FALSE; break; } case _MMCamcorder_CMD_COMMIT: { - int count = 0; - if (info->b_commiting) { _mmcam_dbg_err("now on commiting previous file!!(command : %d)", command); return MM_ERROR_CAMCORDER_CMD_IS_RUNNING; @@ -908,34 +944,66 @@ int _mmcamcorder_video_command(MMHandleType handle, int command) for (count = 0 ; count <= _MMCAMCORDER_RETRIAL_COUNT ; count++) { if (sc->audio_disable) { /* check only video frame */ - if (info->video_frame_count >= _MMCAMCORDER_MINIMUM_FRAME) { + if (info->video_frame_count >= _MMCAMCORDER_MINIMUM_FRAME && + hcamcorder->capture_in_recording == FALSE) { break; } else if (count == _MMCAMCORDER_RETRIAL_COUNT) { - _mmcam_dbg_err("Commit fail, frame count is %" G_GUINT64_FORMAT "", - info->video_frame_count); - info->b_commiting = FALSE; - return MM_ERROR_CAMCORDER_INVALID_CONDITION; + _mmcam_dbg_err("Commit fail, frame count is %llu, capturing %d", + info->video_frame_count, hcamcorder->capture_in_recording); + + if (info->video_frame_count >= _MMCAMCORDER_MINIMUM_FRAME) { + _mmcam_dbg_warn("video frames are enough. keep going..."); + } else { + info->b_commiting = FALSE; + return MM_ERROR_CAMCORDER_INVALID_CONDITION; + } } else { - _mmcam_dbg_warn("Waiting for enough video frame, retrial [%d], frame %" G_GUINT64_FORMAT "", - count, info->video_frame_count); + _mmcam_dbg_warn("Waiting for enough video frame, retrial [%d], frame %llu, capturing %d", + count, info->video_frame_count, hcamcorder->capture_in_recording); } - - usleep(_MMCAMCORDER_FRAME_WAIT_TIME); } else { /* check both of video and audio frame */ - if (info->video_frame_count >= _MMCAMCORDER_MINIMUM_FRAME && info->audio_frame_count) { + if (info->video_frame_count >= _MMCAMCORDER_MINIMUM_FRAME && + info->audio_frame_count && + hcamcorder->capture_in_recording == FALSE) { break; } else if (count == _MMCAMCORDER_RETRIAL_COUNT) { - _mmcam_dbg_err("Commit fail, VIDEO[%" G_GUINT64_FORMAT "], AUDIO [%" G_GUINT64_FORMAT "]", - info->video_frame_count, info->audio_frame_count); + _mmcam_dbg_err("Commit fail, VIDEO[%llu], AUDIO [%llu], capturing %d", + info->video_frame_count, info->audio_frame_count, hcamcorder->capture_in_recording); - info->b_commiting = FALSE; - return MM_ERROR_CAMCORDER_INVALID_CONDITION; + if (info->video_frame_count >= _MMCAMCORDER_MINIMUM_FRAME && info->audio_frame_count) { + _mmcam_dbg_warn("video/audio frames are enough. keep going..."); + } else { + info->b_commiting = FALSE; + return MM_ERROR_CAMCORDER_INVALID_CONDITION; + } } else { - _mmcam_dbg_warn("Waiting for enough frames, retrial [%d], VIDEO[%" G_GUINT64_FORMAT "], AUDIO [%" G_GUINT64_FORMAT "]", - count, info->video_frame_count, info->audio_frame_count); + _mmcam_dbg_warn("Waiting for enough frames, retrial [%d], VIDEO[%llu], AUDIO [%llu], capturing %d", + count, info->video_frame_count, info->audio_frame_count, hcamcorder->capture_in_recording); } + } + + if (hcamcorder->capture_in_recording) { + struct timespec timeout; + struct timeval tv; + struct timeval tv_to_add; + struct timeval tv_result; + + gettimeofday(&tv, NULL); + tv_to_add.tv_sec = _MMCAMCORDER_CAPTURE_WAIT_TIME; + tv_to_add.tv_usec = 0; + + timeradd(&tv, &tv_to_add, &tv_result); + timeout.tv_sec = tv_result.tv_sec; + timeout.tv_nsec = tv_result.tv_usec * 1000; + + if (_MMCAMCORDER_CMD_TIMED_WAIT(handle, timeout)) { + _mmcam_dbg_warn("timeout"); + } else { + _mmcam_dbg_warn("signal received"); + } + } else { usleep(_MMCAMCORDER_FRAME_WAIT_TIME); } } @@ -945,22 +1013,38 @@ int _mmcamcorder_video_command(MMHandleType handle, int command) _mmcam_dbg_log("block push buffer to appsrc"); if (sc->encode_element[_MMCAMCORDER_ENCSINK_SRC].gst != NULL) { - ret = gst_element_send_event(sc->encode_element[_MMCAMCORDER_ENCSINK_SRC].gst, gst_event_new_eos()); - _mmcam_dbg_warn("send eos to appsrc result : %d", ret); + if (gst_element_send_event(sc->encode_element[_MMCAMCORDER_ENCSINK_SRC].gst, gst_event_new_eos())) { + _mmcam_dbg_warn("VIDEO: send eos to appsrc done"); + } else { + _mmcam_dbg_err("VIDEO: send EOS failed"); + info->b_commiting = FALSE; + ret = MM_ERROR_CAMCORDER_INTERNAL; + goto _ERR_CAMCORDER_VIDEO_COMMAND; + } + } else { + _mmcam_dbg_err("No video stream source"); + info->b_commiting = FALSE; + ret = MM_ERROR_CAMCORDER_INTERNAL; + goto _ERR_CAMCORDER_VIDEO_COMMAND; } if (sc->encode_element[_MMCAMCORDER_AUDIOSRC_SRC].gst != NULL) { - ret = gst_element_send_event(sc->encode_element[_MMCAMCORDER_AUDIOSRC_SRC].gst, gst_event_new_eos()); - _mmcam_dbg_warn("send eos to audiosrc result : %d", ret); + if (gst_element_send_event(sc->encode_element[_MMCAMCORDER_AUDIOSRC_SRC].gst, gst_event_new_eos())) { + _mmcam_dbg_warn("AUDIO: send eos to audiosrc done"); + } else { + _mmcam_dbg_err("AUDIO: send EOS failed"); + info->b_commiting = FALSE; + ret = MM_ERROR_CAMCORDER_INTERNAL; + goto _ERR_CAMCORDER_VIDEO_COMMAND; + } + } else { + _mmcam_dbg_log("No audio stream"); } /* sc */ sc->display_interval = 0; sc->previous_slot_time = 0; - /* init system memory size */ - hcamcorder->system_memory=0; - /* Wait EOS */ _mmcam_dbg_log("Start to wait EOS"); ret =_mmcamcorder_get_eos_message(handle); @@ -968,6 +1052,9 @@ int _mmcamcorder_video_command(MMHandleType handle, int command) info->b_commiting = FALSE; goto _ERR_CAMCORDER_VIDEO_COMMAND; } + + /* reset flag */ + hcamcorder->capture_in_recording = FALSE; } break; default: @@ -1037,6 +1124,9 @@ int _mmcamcorder_video_handle_eos(MMHandleType handle) _mmcam_dbg_warn("_MMCamcorder_CMD_COMMIT:__mmcamcorder_remove_recorder_pipeline failed. error[%x]", ret); } + /* set recording hint */ + MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst, "recording-hint", FALSE); + /* stop video stream */ if (info->record_dual_stream) { GstCameraControl *control = GST_CAMERA_CONTROL(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst); @@ -1072,7 +1162,7 @@ int _mmcamcorder_video_handle_eos(MMHandleType handle) _mmcam_dbg_err("File size is greater than max size !!"); message.id = MM_MESSAGE_CAMCORDER_ERROR; message.param.code = MM_ERROR_CAMCORDER_FILE_SIZE_OVER; - _mmcamcroder_send_message((MMHandleType)hcamcorder, &message); + _mmcamcorder_send_message((MMHandleType)hcamcorder, &message); } } @@ -1084,13 +1174,19 @@ int _mmcamcorder_video_handle_eos(MMHandleType handle) _mmcam_dbg_log("Set state of pipeline as READY"); ret = _mmcamcorder_gst_set_state(handle, sc->element[_MMCAMCORDER_MAIN_PIPE].gst, GST_STATE_READY); + if (sc->info_image->preview_format == MM_PIXEL_FORMAT_ENCODED_H264) { + if (!_mmcamcorder_recreate_decoder_for_encoded_preview(handle)) { + ret = MM_ERROR_CAMCORDER_INTERNAL; + } + } + /* unblock queue */ MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_QUE].gst, "empty-buffers", FALSE); MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_QUE].gst, "empty-buffers", FALSE); if (ret != MM_ERROR_NONE) { msg.id = MM_MESSAGE_CAMCORDER_ERROR; msg.param.code = ret; - _mmcamcroder_send_message((MMHandleType)hcamcorder, &msg); + _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg); _mmcam_dbg_err("Failed to set state READY[%x]", ret); } @@ -1106,7 +1202,7 @@ int _mmcamcorder_video_handle_eos(MMHandleType handle) if (ret != MM_ERROR_NONE) { msg.id = MM_MESSAGE_CAMCORDER_ERROR; msg.param.code = ret; - _mmcamcroder_send_message((MMHandleType)hcamcorder, &msg); + _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg); _mmcam_dbg_err("Failed to set state PLAYING[%x]", ret); } } else { @@ -1122,7 +1218,7 @@ int _mmcamcorder_video_handle_eos(MMHandleType handle) report->recording_filename = strdup(info->filename); msg.param.data= report; msg.param.code = 1; - _mmcamcroder_send_message((MMHandleType)hcamcorder, &msg); + _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg); } /* Finishing */ @@ -1130,7 +1226,7 @@ int _mmcamcorder_video_handle_eos(MMHandleType handle) sc->pause_time = 0; sc->isMaxsizePausing = FALSE; /*In async function, this variable should set in callback function. */ sc->isMaxtimePausing = FALSE; - sc->error_occurs = FALSE; + hcamcorder->error_occurs = FALSE; info->video_frame_count = 0; info->audio_frame_count = 0; @@ -1160,8 +1256,8 @@ int _mmcamcorder_video_handle_eos(MMHandleType handle) * @remarks * @see */ -static gboolean __mmcamcorder_eventprobe_monitor(GstPad *pad, GstEvent *event, gpointer u_data) -{ +static GstPadProbeReturn __mmcamcorder_eventprobe_monitor(GstPad *pad, GstPadProbeInfo *info, gpointer u_data){ + GstEvent *event = GST_PAD_PROBE_INFO_EVENT(info); switch (GST_EVENT_TYPE(event)) { case GST_EVENT_UNKNOWN: /* upstream events */ @@ -1170,7 +1266,7 @@ static gboolean __mmcamcorder_eventprobe_monitor(GstPad *pad, GstEvent *event, g case GST_EVENT_NAVIGATION: case GST_EVENT_LATENCY: /* downstream serialized events */ - case GST_EVENT_NEWSEGMENT : + case GST_EVENT_SEGMENT : case GST_EVENT_TAG: case GST_EVENT_BUFFERSIZE: _mmcam_dbg_log("[%s:%s] gots %s", GST_DEBUG_PAD_NAME(pad), GST_EVENT_TYPE_NAME(event)); @@ -1188,62 +1284,70 @@ static gboolean __mmcamcorder_eventprobe_monitor(GstPad *pad, GstEvent *event, g break; } - return TRUE; + return GST_PAD_PROBE_OK; } -static gboolean __mmcamcorder_audio_dataprobe_check(GstPad *pad, GstBuffer *buffer, gpointer u_data) +static GstPadProbeReturn __mmcamcorder_audio_dataprobe_check(GstPad *pad, GstPadProbeInfo *info, gpointer u_data) { mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(u_data); + GstBuffer *buffer = GST_PAD_PROBE_INFO_BUFFER(info); + GstMapInfo mapinfo; _MMCamcorderSubContext *sc = NULL; - _MMCamcorderVideoInfo *info = NULL; + _MMCamcorderVideoInfo *videoinfo = NULL; _MMCamcorderMsgItem msg; guint64 buffer_size = 0; guint64 trailer_size = 0; - mmf_return_val_if_fail(hcamcorder, TRUE); - mmf_return_val_if_fail(buffer, FALSE); + mmf_return_val_if_fail(hcamcorder, GST_PAD_PROBE_OK); + mmf_return_val_if_fail(buffer, GST_PAD_PROBE_DROP); sc = MMF_CAMCORDER_SUBCONTEXT(hcamcorder); - mmf_return_val_if_fail(sc && sc->info_video, TRUE); - info = sc->info_video; + mmf_return_val_if_fail(sc && sc->info_video, GST_PAD_PROBE_OK); + videoinfo = sc->info_video; /* get buffer size */ - buffer_size = GST_BUFFER_SIZE(buffer); + if (!gst_buffer_map(buffer, &mapinfo, GST_MAP_READ)) { + _mmcam_dbg_warn("map failed : buffer %p", buffer); + return GST_PAD_PROBE_OK; + } - /*_mmcam_dbg_err("[%" GST_TIME_FORMAT "]", GST_TIME_ARGS(GST_BUFFER_TIMESTAMP(buffer)));*/ + buffer_size = mapinfo.size; + gst_buffer_unmap(buffer, &mapinfo); - pthread_mutex_lock(&(info->size_check_lock)); + /*_mmcam_dbg_err("[%" GST_TIME_FORMAT "]", GST_TIME_ARGS(GST_BUFFER_PTS(buffer)));*/ - if (info->audio_frame_count == 0) { - info->filesize += buffer_size; - info->audio_frame_count++; - pthread_mutex_unlock(&(info->size_check_lock)); - return TRUE; + pthread_mutex_lock(&(videoinfo->size_check_lock)); + + if (videoinfo->audio_frame_count == 0) { + videoinfo->filesize += buffer_size; + videoinfo->audio_frame_count++; + pthread_mutex_unlock(&(videoinfo->size_check_lock)); + return GST_PAD_PROBE_OK; } if (sc->ferror_send || sc->isMaxsizePausing) { _mmcam_dbg_warn("Recording is paused, drop frames"); - pthread_mutex_unlock(&(info->size_check_lock)); - return FALSE; + pthread_mutex_unlock(&(videoinfo->size_check_lock)); + return GST_PAD_PROBE_DROP; } /* get trailer size */ - if (info->fileformat == MM_FILE_FORMAT_3GP || info->fileformat == MM_FILE_FORMAT_MP4) { + if (videoinfo->fileformat == MM_FILE_FORMAT_3GP || videoinfo->fileformat == MM_FILE_FORMAT_MP4) { MMCAMCORDER_G_OBJECT_GET(sc->encode_element[_MMCAMCORDER_ENCSINK_MUX].gst, "expected-trailer-size", &trailer_size); } else { trailer_size = 0; } /* check max size of recorded file */ - if (info->max_size > 0 && - info->max_size < info->filesize + buffer_size + trailer_size + _MMCAMCORDER_MMS_MARGIN_SPACE) { + if (videoinfo->max_size > 0 && + videoinfo->max_size < videoinfo->filesize + buffer_size + trailer_size + _MMCAMCORDER_MMS_MARGIN_SPACE) { GstState pipeline_state = GST_STATE_VOID_PENDING; GstElement *pipeline = sc->element[_MMCAMCORDER_MAIN_PIPE].gst; _mmcam_dbg_warn("Max size!!! Recording is paused."); _mmcam_dbg_warn("Max size : [%" G_GUINT64_FORMAT "], current file size : [%" G_GUINT64_FORMAT "]," \ " buffer size : [%" G_GUINT64_FORMAT "], trailer size : [%" G_GUINT64_FORMAT "]", - info->max_size, info->filesize, buffer_size, trailer_size); + videoinfo->max_size, videoinfo->filesize, buffer_size, trailer_size); if (!sc->isMaxsizePausing) { sc->isMaxsizePausing = TRUE; @@ -1253,24 +1357,24 @@ static gboolean __mmcamcorder_audio_dataprobe_check(GstPad *pad, GstBuffer *buff } msg.id = MM_MESSAGE_CAMCORDER_MAX_SIZE; - _mmcamcroder_send_message((MMHandleType)hcamcorder, &msg); + _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg); } - pthread_mutex_unlock(&(info->size_check_lock)); + pthread_mutex_unlock(&(videoinfo->size_check_lock)); return FALSE; } - info->filesize += buffer_size; - info->audio_frame_count++; + videoinfo->filesize += buffer_size; + videoinfo->audio_frame_count++; - pthread_mutex_unlock(&(info->size_check_lock)); + pthread_mutex_unlock(&(videoinfo->size_check_lock)); - return TRUE; + return GST_PAD_PROBE_OK; } -static gboolean __mmcamcorder_video_dataprobe_record(GstPad *pad, GstBuffer *buffer, gpointer u_data) +static GstPadProbeReturn __mmcamcorder_video_dataprobe_record(GstPad *pad, GstPadProbeInfo *info, gpointer u_data) { gint ret = 0; guint vq_size = 0; @@ -1279,50 +1383,57 @@ static gboolean __mmcamcorder_video_dataprobe_record(GstPad *pad, GstBuffer *buf guint64 buffer_size = 0; guint64 trailer_size = 0; guint64 queued_buffer = 0; - char *filename = NULL; + char *dir_name = NULL; + GstBuffer *buffer = GST_PAD_PROBE_INFO_BUFFER(info); + GstMapInfo mapinfo; mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(u_data); _MMCamcorderMsgItem msg; _MMCamcorderSubContext *sc = NULL; - _MMCamcorderVideoInfo *info = NULL; + _MMCamcorderVideoInfo *videoinfo = NULL; - mmf_return_val_if_fail(hcamcorder, TRUE); - mmf_return_val_if_fail(buffer, FALSE); + mmf_return_val_if_fail(hcamcorder, GST_PAD_PROBE_OK); + mmf_return_val_if_fail(buffer, GST_PAD_PROBE_DROP); sc = MMF_CAMCORDER_SUBCONTEXT(hcamcorder); - mmf_return_val_if_fail(sc && sc->info_video, TRUE); - info = sc->info_video; + mmf_return_val_if_fail(sc && sc->info_video, GST_PAD_PROBE_OK); + videoinfo = sc->info_video; - /*_mmcam_dbg_log("[%" GST_TIME_FORMAT "]", GST_TIME_ARGS(GST_BUFFER_TIMESTAMP(buffer)));*/ + /*_mmcam_dbg_log("[%" GST_TIME_FORMAT "]", GST_TIME_ARGS(GST_BUFFER_PTS(buffer)));*/ if (sc->ferror_send) { _mmcam_dbg_warn("file write error, drop frames"); - return FALSE; + return GST_PAD_PROBE_DROP; } - info->video_frame_count++; - if (info->video_frame_count <= (guint64)_MMCAMCORDER_MINIMUM_FRAME) { + gst_buffer_map(buffer, &mapinfo, GST_MAP_READ); + buffer_size = mapinfo.size; + gst_buffer_unmap(buffer, &mapinfo); + + videoinfo->video_frame_count++; + if (videoinfo->video_frame_count <= (guint64)_MMCAMCORDER_MINIMUM_FRAME) { /* _mmcam_dbg_log("Pass minimum frame: info->video_frame_count: %" G_GUINT64_FORMAT " ", info->video_frame_count); */ - pthread_mutex_lock(&(info->size_check_lock)); - info->filesize += (guint64)GST_BUFFER_SIZE(buffer); - pthread_mutex_unlock(&(info->size_check_lock)); - return TRUE; + pthread_mutex_lock(&(videoinfo->size_check_lock)); + videoinfo->filesize += buffer_size; + pthread_mutex_unlock(&(videoinfo->size_check_lock)); + return GST_PAD_PROBE_OK; } - buffer_size = GST_BUFFER_SIZE(buffer); - /* get trailer size */ - if (info->fileformat == MM_FILE_FORMAT_3GP || info->fileformat == MM_FILE_FORMAT_MP4) { + if (videoinfo->fileformat == MM_FILE_FORMAT_3GP || videoinfo->fileformat == MM_FILE_FORMAT_MP4) { MMCAMCORDER_G_OBJECT_GET(sc->encode_element[_MMCAMCORDER_ENCSINK_MUX].gst, "expected-trailer-size", &trailer_size); } else { trailer_size = 0; } - filename = info->filename; - ret = _mmcamcorder_get_freespace(filename, &free_space); - - if(_mmcamcorder_check_file_path(filename) && hcamcorder->system_memory) { - free_space = free_space - hcamcorder->system_memory; + dir_name = g_path_get_dirname(videoinfo->filename); + if (dir_name) { + ret = _mmcamcorder_get_freespace(dir_name, hcamcorder->root_directory, &free_space); + g_free(dir_name); + dir_name = NULL; + } else { + _mmcam_dbg_err("failed to get dir name from [%s]", videoinfo->filename); + ret = -1; } /*_mmcam_dbg_log("check free space for recording");*/ @@ -1339,12 +1450,12 @@ static gboolean __mmcamcorder_video_dataprobe_record(GstPad *pad, GstBuffer *buf } else { msg.param.code = MM_ERROR_FILE_READ; } - _mmcamcroder_send_message((MMHandleType)hcamcorder, &msg); + _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg); } else { sc->ferror_count++; } - return FALSE; /* skip this buffer */ + return GST_PAD_PROBE_DROP; /* skip this buffer */ break; default: /* succeeded to get free space */ /* check free space for recording */ @@ -1370,25 +1481,25 @@ static gboolean __mmcamcorder_video_dataprobe_record(GstPad *pad, GstBuffer *buf sc->isMaxsizePausing = TRUE; msg.id = MM_MESSAGE_CAMCORDER_NO_FREE_SPACE; - _mmcamcroder_send_message((MMHandleType)hcamcorder, &msg); + _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg); } - return FALSE; + return GST_PAD_PROBE_DROP; } break; } - pthread_mutex_lock(&(info->size_check_lock)); + pthread_mutex_lock(&(videoinfo->size_check_lock)); /* check max size of recorded file */ - if (info->max_size > 0 && - info->max_size < info->filesize + buffer_size + trailer_size + _MMCAMCORDER_MMS_MARGIN_SPACE) { + if (videoinfo->max_size > 0 && + videoinfo->max_size < videoinfo->filesize + buffer_size + trailer_size + _MMCAMCORDER_MMS_MARGIN_SPACE) { GstState pipeline_state = GST_STATE_VOID_PENDING; GstElement *pipeline = sc->element[_MMCAMCORDER_MAIN_PIPE].gst; _mmcam_dbg_warn("Max size!!! Recording is paused."); _mmcam_dbg_warn("Max size : [%" G_GUINT64_FORMAT "], current file size : [%" G_GUINT64_FORMAT "]," \ " buffer size : [%" G_GUINT64_FORMAT "], trailer size : [%" G_GUINT64_FORMAT "]", - info->max_size, info->filesize, buffer_size, trailer_size); + videoinfo->max_size, videoinfo->filesize, buffer_size, trailer_size); if (!sc->isMaxsizePausing) { sc->isMaxsizePausing = TRUE; @@ -1398,27 +1509,27 @@ static gboolean __mmcamcorder_video_dataprobe_record(GstPad *pad, GstBuffer *buf } msg.id = MM_MESSAGE_CAMCORDER_MAX_SIZE; - _mmcamcroder_send_message((MMHandleType)hcamcorder, &msg); + _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg); } - pthread_mutex_unlock(&(info->size_check_lock)); + pthread_mutex_unlock(&(videoinfo->size_check_lock)); - return FALSE; + return GST_PAD_PROBE_DROP; } - info->filesize += (guint64)buffer_size; + videoinfo->filesize += (guint64)buffer_size; /* - _mmcam_dbg_log("filesize %lld Byte, ", info->filesize); + _mmcam_dbg_log("filesize %lld Byte, ", videoinfo->filesize); */ - pthread_mutex_unlock(&(info->size_check_lock)); + pthread_mutex_unlock(&(videoinfo->size_check_lock)); - return TRUE; + return GST_PAD_PROBE_OK; } -static gboolean __mmcamcorder_video_dataprobe_audio_disable(GstPad *pad, GstBuffer *buffer, gpointer u_data) +static GstPadProbeReturn __mmcamcorder_video_dataprobe_audio_disable(GstPad *pad, GstPadProbeInfo *info, gpointer u_data) { guint64 trailer_size = 0; guint64 rec_pipe_time = 0; @@ -1429,31 +1540,33 @@ static gboolean __mmcamcorder_video_dataprobe_audio_disable(GstPad *pad, GstBuff mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(u_data); _MMCamcorderMsgItem msg; _MMCamcorderSubContext *sc = NULL; - _MMCamcorderVideoInfo *info = NULL; + _MMCamcorderVideoInfo *videoinfo = NULL; - mmf_return_val_if_fail(buffer, FALSE); - mmf_return_val_if_fail(hcamcorder, TRUE); + GstBuffer *buffer = GST_PAD_PROBE_INFO_BUFFER(info); + + mmf_return_val_if_fail(buffer, GST_PAD_PROBE_DROP); + mmf_return_val_if_fail(hcamcorder, GST_PAD_PROBE_OK); sc = MMF_CAMCORDER_SUBCONTEXT(u_data); - mmf_return_val_if_fail(sc, TRUE); - mmf_return_val_if_fail(sc->info_video, TRUE); + mmf_return_val_if_fail(sc, GST_PAD_PROBE_OK); + mmf_return_val_if_fail(sc->info_video, GST_PAD_PROBE_OK); - info = sc->info_video; + videoinfo = sc->info_video; - b_time = GST_BUFFER_TIMESTAMP(buffer); + b_time = GST_BUFFER_PTS(buffer); rec_pipe_time = GST_TIME_AS_MSECONDS(b_time); - if (info->fileformat == MM_FILE_FORMAT_3GP || info->fileformat == MM_FILE_FORMAT_MP4) { + if (videoinfo->fileformat == MM_FILE_FORMAT_3GP || videoinfo->fileformat == MM_FILE_FORMAT_MP4) { MMCAMCORDER_G_OBJECT_GET(sc->encode_element[_MMCAMCORDER_ENCSINK_MUX].gst, "expected-trailer-size", &trailer_size); } else { trailer_size = 0; } /* check max time */ - if (info->max_time > 0 && rec_pipe_time > info->max_time) { + if (videoinfo->max_time > 0 && rec_pipe_time > videoinfo->max_time) { _mmcam_dbg_warn("Current time : [%" G_GUINT64_FORMAT "], Maximum time : [%" G_GUINT64_FORMAT "]", \ - rec_pipe_time, info->max_time); + rec_pipe_time, videoinfo->max_time); if (!sc->isMaxtimePausing) { MMCAMCORDER_G_OBJECT_SET(sc->encode_element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "block", TRUE); @@ -1462,114 +1575,115 @@ static gboolean __mmcamcorder_video_dataprobe_audio_disable(GstPad *pad, GstBuff msg.id = MM_MESSAGE_CAMCORDER_RECORDING_STATUS; msg.param.recording_status.elapsed = (unsigned long long)rec_pipe_time; - msg.param.recording_status.filesize = (unsigned long long)((info->filesize + trailer_size) >> 10); + msg.param.recording_status.filesize = (unsigned long long)((videoinfo->filesize + trailer_size) >> 10); msg.param.recording_status.remained_time = 0; - _mmcamcroder_send_message((MMHandleType)hcamcorder, &msg); + _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg); msg.id = MM_MESSAGE_CAMCORDER_TIME_LIMIT; - _mmcamcroder_send_message((MMHandleType)hcamcorder, &msg); + _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg); } - return FALSE; + return GST_PAD_PROBE_DROP; } /* calculate remained time can be recorded */ - if (info->max_time > 0 && info->max_time < (remained_time + rec_pipe_time)) { - remained_time = info->max_time - rec_pipe_time; - } else if (info->max_size > 0) { - long double max_size = (long double)info->max_size; - long double current_size = (long double)(info->filesize + trailer_size); + if (videoinfo->max_time > 0 && videoinfo->max_time < (remained_time + rec_pipe_time)) { + remained_time = videoinfo->max_time - rec_pipe_time; + } else if (videoinfo->max_size > 0) { + long double max_size = (long double)videoinfo->max_size; + long double current_size = (long double)(videoinfo->filesize + trailer_size); remained_time = (unsigned int)((long double)rec_pipe_time * (max_size/current_size)) - rec_pipe_time; } msg.id = MM_MESSAGE_CAMCORDER_RECORDING_STATUS; msg.param.recording_status.elapsed = (unsigned long long)rec_pipe_time; - msg.param.recording_status.filesize = (unsigned long long)((info->filesize + trailer_size) >> 10); + msg.param.recording_status.filesize = (unsigned long long)((videoinfo->filesize + trailer_size) >> 10); msg.param.recording_status.remained_time = remained_time; - _mmcamcroder_send_message((MMHandleType)hcamcorder, &msg); + _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg); /* _mmcam_dbg_log("time [%" GST_TIME_FORMAT "], size [%d]", GST_TIME_ARGS(rec_pipe_time), msg.param.recording_status.filesize); */ - if (info->record_timestamp_ratio != _MMCAMCORDER_DEFAULT_RECORDING_MOTION_RATE) { - guint record_motion_rate = (guint)info->record_motion_rate; + if (videoinfo->record_timestamp_ratio != _MMCAMCORDER_DEFAULT_RECORDING_MOTION_RATE) { + guint record_motion_rate = (guint)videoinfo->record_motion_rate; /* - _mmcam_dbg_log("record_motion_rate %d, info->record_drop_count %d", - record_motion_rate, info->record_drop_count); + _mmcam_dbg_log("record_motion_rate %d, videoinfo->record_drop_count %d", + record_motion_rate, videoinfo->record_drop_count); */ /* drop some frame if fast motion */ - if (info->record_motion_rate > _MMCAMCORDER_DEFAULT_RECORDING_MOTION_RATE) { - if (record_motion_rate != (info->record_drop_count++)) { + if (videoinfo->record_motion_rate > _MMCAMCORDER_DEFAULT_RECORDING_MOTION_RATE) { + if (record_motion_rate != (videoinfo->record_drop_count++)) { /* _mmcam_dbg_warn("drop frame"); */ - return FALSE; + return GST_PAD_PROBE_DROP; } - info->record_drop_count = 1; + videoinfo->record_drop_count = 1; /* _mmcam_dbg_warn("pass frame"); */ } - GST_BUFFER_TIMESTAMP(buffer) = b_time * (info->record_timestamp_ratio); + GST_BUFFER_PTS(buffer) = b_time * (videoinfo->record_timestamp_ratio); } - return TRUE; + return GST_PAD_PROBE_OK; } -static gboolean __mmcamcorder_audioque_dataprobe(GstPad *pad, GstBuffer *buffer, gpointer u_data) +static GstPadProbeReturn __mmcamcorder_audioque_dataprobe(GstPad *pad, GstPadProbeInfo *info, gpointer u_data) { _MMCamcorderMsgItem msg; guint64 trailer_size = 0; guint64 rec_pipe_time = 0; _MMCamcorderSubContext *sc = NULL; mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(u_data); - _MMCamcorderVideoInfo *info = NULL; + _MMCamcorderVideoInfo *videoinfo = NULL; unsigned int remained_time = 0; + GstBuffer *buffer = GST_PAD_PROBE_INFO_BUFFER(info); - mmf_return_val_if_fail(buffer, FALSE); - mmf_return_val_if_fail(hcamcorder, TRUE); + mmf_return_val_if_fail(buffer, GST_PAD_PROBE_DROP); + mmf_return_val_if_fail(hcamcorder, GST_PAD_PROBE_OK); sc = MMF_CAMCORDER_SUBCONTEXT(u_data); - mmf_return_val_if_fail(sc, TRUE); - mmf_return_val_if_fail(sc->info_video, TRUE); - mmf_return_val_if_fail(sc->element, TRUE); + mmf_return_val_if_fail(sc, GST_PAD_PROBE_OK); + mmf_return_val_if_fail(sc->info_video, GST_PAD_PROBE_OK); + mmf_return_val_if_fail(sc->element, GST_PAD_PROBE_OK); - info = sc->info_video; + videoinfo = sc->info_video; - if (!GST_CLOCK_TIME_IS_VALID(GST_BUFFER_TIMESTAMP(buffer))) { + if (!GST_CLOCK_TIME_IS_VALID(GST_BUFFER_PTS(buffer))) { _mmcam_dbg_err( "Buffer timestamp is invalid, check it"); - return TRUE; + return GST_PAD_PROBE_OK; } - rec_pipe_time = GST_TIME_AS_MSECONDS(GST_BUFFER_TIMESTAMP(buffer)); + rec_pipe_time = GST_TIME_AS_MSECONDS(GST_BUFFER_PTS(buffer)); - if (info->fileformat == MM_FILE_FORMAT_3GP || info->fileformat == MM_FILE_FORMAT_MP4) { + if (videoinfo->fileformat == MM_FILE_FORMAT_3GP || videoinfo->fileformat == MM_FILE_FORMAT_MP4) { MMCAMCORDER_G_OBJECT_GET(sc->encode_element[_MMCAMCORDER_ENCSINK_MUX].gst, "expected-trailer-size", &trailer_size); } else { trailer_size = 0; } /* calculate remained time can be recorded */ - if (info->max_time > 0 && info->max_time < (remained_time + rec_pipe_time)) { - remained_time = info->max_time - rec_pipe_time; - } else if (info->max_size > 0) { - long double max_size = (long double)info->max_size; - long double current_size = (long double)(info->filesize + trailer_size); + if (videoinfo->max_time > 0 && videoinfo->max_time < (remained_time + rec_pipe_time)) { + remained_time = videoinfo->max_time - rec_pipe_time; + } else if (videoinfo->max_size > 0) { + long double max_size = (long double)videoinfo->max_size; + long double current_size = (long double)(videoinfo->filesize + trailer_size); remained_time = (unsigned long long)((long double)rec_pipe_time * (max_size/current_size)) - rec_pipe_time; } - if (info->max_time > 0 && rec_pipe_time > info->max_time) { + if (videoinfo->max_time > 0 && rec_pipe_time > videoinfo->max_time) { _mmcam_dbg_warn("Current time : [%" G_GUINT64_FORMAT "], Maximum time : [%" G_GUINT64_FORMAT "]", \ - rec_pipe_time, info->max_time); + rec_pipe_time, videoinfo->max_time); if (!sc->isMaxtimePausing) { MMCAMCORDER_G_OBJECT_SET(sc->encode_element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "block", TRUE); @@ -1578,33 +1692,33 @@ static gboolean __mmcamcorder_audioque_dataprobe(GstPad *pad, GstBuffer *buffer, msg.id = MM_MESSAGE_CAMCORDER_RECORDING_STATUS; msg.param.recording_status.elapsed = (unsigned long long)rec_pipe_time; - msg.param.recording_status.filesize = (unsigned long long)((info->filesize + trailer_size) >> 10); + msg.param.recording_status.filesize = (unsigned long long)((videoinfo->filesize + trailer_size) >> 10); msg.param.recording_status.remained_time = 0; - _mmcamcroder_send_message((MMHandleType)hcamcorder, &msg); + _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg); msg.id = MM_MESSAGE_CAMCORDER_TIME_LIMIT; - _mmcamcroder_send_message((MMHandleType)hcamcorder, &msg); + _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg); } - return FALSE; + return GST_PAD_PROBE_DROP; } msg.id = MM_MESSAGE_CAMCORDER_RECORDING_STATUS; msg.param.recording_status.elapsed = (unsigned long long)rec_pipe_time; - msg.param.recording_status.filesize = (unsigned long long)((info->filesize + trailer_size) >> 10); + msg.param.recording_status.filesize = (unsigned long long)((videoinfo->filesize + trailer_size) >> 10); msg.param.recording_status.remained_time = remained_time; - _mmcamcroder_send_message((MMHandleType)hcamcorder, &msg); + _mmcamcorder_send_message((MMHandleType)hcamcorder, &msg); /* _mmcam_dbg_log("audio data probe :: time [%" GST_TIME_FORMAT "], size [%lld KB]", GST_TIME_ARGS(rec_pipe_time), msg.param.recording_status.filesize); */ - return TRUE; + return GST_PAD_PROBE_OK; } -static gboolean __mmcamcorder_audio_dataprobe_audio_mute(GstPad *pad, GstBuffer *buffer, gpointer u_data) +static GstPadProbeReturn __mmcamcorder_audio_dataprobe_audio_mute(GstPad *pad, GstPadProbeInfo *info, gpointer u_data) { mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(u_data); double volume = 0.0; @@ -1612,11 +1726,13 @@ static gboolean __mmcamcorder_audio_dataprobe_audio_mute(GstPad *pad, GstBuffer int channel = 0; int err = MM_ERROR_UNKNOWN; char *err_name = NULL; + GstBuffer *buffer = GST_PAD_PROBE_INFO_BUFFER(info); + GstMapInfo mapinfo; - mmf_return_val_if_fail(buffer, FALSE); - mmf_return_val_if_fail(hcamcorder, FALSE); + mmf_return_val_if_fail(buffer, GST_PAD_PROBE_DROP); + mmf_return_val_if_fail(hcamcorder, GST_PAD_PROBE_DROP); - /*_mmcam_dbg_log("AUDIO SRC time stamp : [%" GST_TIME_FORMAT "] \n", GST_TIME_ARGS(GST_BUFFER_TIMESTAMP(buffer)));*/ + /*_mmcam_dbg_log("AUDIO SRC time stamp : [%" GST_TIME_FORMAT "] \n", GST_TIME_ARGS(GST_BUFFER_PTS(buffer)));*/ err = mm_camcorder_get_attributes((MMHandleType)hcamcorder, &err_name, MMCAM_AUDIO_VOLUME, &volume, MMCAM_AUDIO_FORMAT, &format, @@ -1628,28 +1744,33 @@ static gboolean __mmcamcorder_audio_dataprobe_audio_mute(GstPad *pad, GstBuffer return err; } + memset(&mapinfo, 0x0, sizeof(GstMapInfo)); + + gst_buffer_map(buffer, &mapinfo, GST_MAP_READWRITE); + /* Set audio stream NULL */ if (volume == 0.0) { - memset(GST_BUFFER_DATA(buffer), 0, GST_BUFFER_SIZE(buffer)); + memset(mapinfo.data, 0, mapinfo.size); } /* CALL audio stream callback */ - if (hcamcorder->astream_cb && buffer && GST_BUFFER_DATA(buffer)) { + if (hcamcorder->astream_cb && buffer && mapinfo.data && mapinfo.size > 0) { MMCamcorderAudioStreamDataType stream; if (_mmcamcorder_get_state((MMHandleType)hcamcorder) < MM_CAMCORDER_STATE_PREPARE) { _mmcam_dbg_warn("Not ready for stream callback"); - return TRUE; + gst_buffer_unmap(buffer, &mapinfo); + return GST_PAD_PROBE_OK; } /*_mmcam_dbg_log("Call video steramCb, data[%p], Width[%d],Height[%d], Format[%d]", GST_BUFFER_DATA(buffer), width, height, format);*/ - stream.data = (void *)GST_BUFFER_DATA(buffer); + stream.data = (void *)mapinfo.data; stream.format = format; stream.channel = channel; - stream.length = GST_BUFFER_SIZE(buffer); - stream.timestamp = (unsigned int)(GST_BUFFER_TIMESTAMP(buffer)/1000000); /* nano -> milli second */ + stream.length = mapinfo.size; + stream.timestamp = (unsigned int)(GST_BUFFER_PTS(buffer)/1000000); /* nano -> milli second */ _MMCAMCORDER_LOCK_ASTREAM_CALLBACK(hcamcorder); @@ -1660,7 +1781,8 @@ static gboolean __mmcamcorder_audio_dataprobe_audio_mute(GstPad *pad, GstBuffer _MMCAMCORDER_UNLOCK_ASTREAM_CALLBACK(hcamcorder); } - return TRUE; + gst_buffer_unmap(buffer, &mapinfo); + return GST_PAD_PROBE_OK; } @@ -1715,7 +1837,7 @@ static gboolean __mmcamcorder_add_metadata_mp4(MMHandleType handle) info = sc->info_video; - f = fopen(info->filename, "rb+"); + f = fopen64(info->filename, "rb+"); if (f == NULL) { strerror_r(errno, err_msg, MAX_ERROR_MESSAGE_LEN); _mmcam_dbg_err("file open failed [%s]", err_msg); @@ -1753,7 +1875,7 @@ static gboolean __mmcamcorder_add_metadata_mp4(MMHandleType handle) goto fail; } - udta_pos = ftell(f); + udta_pos = ftello(f); if (udta_pos < 0) { goto ftell_fail; } @@ -1781,7 +1903,7 @@ static gboolean __mmcamcorder_add_metadata_mp4(MMHandleType handle) } } - current_pos = ftell(f); + current_pos = ftello(f); if (current_pos < 0) { goto ftell_fail; } @@ -1803,18 +1925,23 @@ static gboolean __mmcamcorder_add_metadata_mp4(MMHandleType handle) /* find moov container. update moov container size. */ - if((current_pos = ftell(f))<0) + if((current_pos = ftello(f))<0) goto ftell_fail; if (_mmcamcorder_find_tag(f, MMCAM_FOURCC('m','o','o','v'), TRUE)) { - gint64 internal_pos = ftell(f); + gint64 internal_pos = ftello(f); _mmcam_dbg_log("found moov container"); + + if (internal_pos < 0) { + goto ftell_fail; + } + if (fseek(f, -8L, SEEK_CUR) !=0) { goto fail; } - moov_pos = ftell(f); + moov_pos = ftello(f); if (moov_pos < 0) { goto ftell_fail; } @@ -1824,7 +1951,7 @@ static gboolean __mmcamcorder_add_metadata_mp4(MMHandleType handle) } /* add orientation info */ - if (fseek(f, internal_pos, SEEK_SET) < 0) { + if (fseeko(f, internal_pos, SEEK_SET) < 0) { _mmcam_dbg_err("fseek failed : errno %d", errno); goto fail; } @@ -1933,7 +2060,7 @@ int _mmcamcorder_video_prepare_record(MMHandleType handle) _mmcam_dbg_log("Record file name [%s]", info->filename); - MMCAMCORDER_G_OBJECT_SET(sc->encode_element[_MMCAMCORDER_ENCSINK_SINK].gst, "location", info->filename); + MMCAMCORDER_G_OBJECT_SET_POINTER(sc->encode_element[_MMCAMCORDER_ENCSINK_SINK].gst, "location", info->filename); MMCAMCORDER_G_OBJECT_SET(sc->encode_element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "block", 0); /* Adjust display FPS */ diff --git a/test/Makefile.am b/test/Makefile.am old mode 100755 new mode 100644 index 6e06157..c5d0238 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -13,8 +13,8 @@ mm_camcorder_testsuite_CFLAGS = -I$(srcdir)/../src/include \ #mm_camcorder_testsuite_CFLAGS += -DAPPSRC_TEST ############################################ -mm_camcorder_testsuite_DEPENDENCIES = $(top_builddir)/src/libmmfcamcorder.la - +mm_camcorder_testsuite_DEPENDENCIES = $(top_builddir)/src/libmmfcamcorder.la + mm_camcorder_testsuite_LDADD = $(top_builddir)/src/libmmfcamcorder.la \ $(GLIB_LIBS)\ $(GST_LIBS)\ diff --git a/test/mm_camcorder_testsuite.c b/test/mm_camcorder_testsuite.c index cfc9708..b0e0f38 100644 --- a/test/mm_camcorder_testsuite.c +++ b/test/mm_camcorder_testsuite.c @@ -29,6 +29,7 @@ when who what, where, why 10/10/07 wh01.cho@samsung.com Created 12/30/08 jh1979.park@samsung.com Modified 08/31/11 sc11.lee@samsung.com Modified (Reorganized for easy look) +10/23/14 p.gamov@samsung.com Upgraded to Gstreamer 1.0 */ @@ -43,7 +44,7 @@ when who what, where, why #include "../src/include/mm_camcorder.h" #include "../src/include/mm_camcorder_internal.h" #include "../src/include/mm_camcorder_util.h" -#include +#include /*----------------------------------------------------------------------- | GLOBAL VARIABLE DEFINITIONS: | @@ -154,7 +155,7 @@ static GTimer *timer = NULL; #define IMAGE_CAPTURE_THUMBNAIL_PATH TARGET_FILENAME_PATH"thumbnail.jpg" #define IMAGE_CAPTURE_SCREENNAIL_PATH TARGET_FILENAME_PATH"screennail.yuv" #define IMAGE_CAPTURE_EXIF_PATH TARGET_FILENAME_PATH"exif.raw" -#define TARGET_FILENAME_VIDEO TARGET_FILENAME_PATH"test_rec_video.3gp" +#define TARGET_FILENAME_VIDEO TARGET_FILENAME_PATH"test_rec_video.mp4" #define TARGET_FILENAME_AUDIO TARGET_FILENAME_PATH"test_rec_audio.m4a" #define CAPTURE_FILENAME_LEN 256 @@ -631,7 +632,7 @@ camcordertest_video_capture_cb(MMCamcorderCaptureDataType *main, MMCamcorderCapt void *dst = NULL; nret = _mmcamcorder_encode_jpeg(main->data, main->width, main->height, main->format, - main->length, 90, &dst, &dst_size, 0); + main->length, 90, &dst, &dst_size); if (nret) { _file_write(m_filename, dst, dst_size); } else { @@ -803,7 +804,7 @@ int camcordertest_get_attr_valid_intrange(const char * attr_name, int *min, int err = mm_camcorder_get_attribute_info(hcamcorder->camcorder, attr_name, &info); if (err != MM_ERROR_NONE) { - err_msg_t("camcordertest_get_attr_valid_intarray : Error(%x)!!", err); + err_msg_t("camcordertest_get_attr_valid_intrange : Error(%x)!!", err); return FALSE; } else { if (info.type == MM_CAM_ATTRS_TYPE_INT) { @@ -815,17 +816,17 @@ int camcordertest_get_attr_valid_intrange(const char * attr_name, int *min, int } } - err_msg_t("camcordertest_get_attr_valid_intarray : Type mismatched!!"); + err_msg_t("camcordertest_get_attr_valid_intrange : Type mismatched!!"); return FALSE; } //success } - debug_msg_t("camcordertest_get_attr_valid_intarray(!hcamcorder->camcorde)"); + debug_msg_t("camcordertest_get_attr_valid_intrange(!hcamcorder->camcorde)"); } - debug_msg_t("camcordertest_get_attr_valid_intarray(!hcamcorder)"); + debug_msg_t("camcordertest_get_attr_valid_intrange(!hcamcorder)"); return FALSE; } @@ -933,6 +934,8 @@ static void print_menu() g_print("\t 'u' Touch AF area \n"); g_print("\t 'm' Stream callback function \n"); g_print("\t 'M' Camcorder Motion Rate setting \n"); + g_print("\t 'B' Encoded preview bitrate \n"); + g_print("\t 'I' Encoded preview I-frame interval \n"); g_print("\t 'b' back\n"); g_print("\t=======================================\n"); break; @@ -989,6 +992,7 @@ static void main_menu(gchar buf) g_print("*Recording start!\n"); video_stream_cb_cnt = 0; audio_stream_cb_cnt = 0; + hcamcorder->elapsed_time = 0; g_timer_reset(timer); err = mm_camcorder_record(hcamcorder->camcorder); @@ -1082,6 +1086,7 @@ static void main_menu(gchar buf) switch(buf) { case '1' : // Start Recording g_print("*Recording start!\n"); + hcamcorder->elapsed_time = 0; g_timer_reset(timer); err = mm_camcorder_record(hcamcorder->camcorder); @@ -1223,13 +1228,14 @@ static void setting_menu(gchar buf) g_print("MMCAM_RECOMMEND_CAMERA_WIDTH/HEIGHT Not supported!!\n"); } else { g_print("\n - MMCAM_RECOMMEND_CAMERA_WIDTH and HEIGHT (count %d) -\n", width_count); - g_print("\t NORMAL ratio : %dx%d\n", - width_array[MM_CAMCORDER_PREVIEW_TYPE_NORMAL], height_array[MM_CAMCORDER_PREVIEW_TYPE_NORMAL]); - if (width_count >= 2) { - g_print("\t WIDE ratio : %dx%d\n\n", - width_array[MM_CAMCORDER_PREVIEW_TYPE_WIDE], height_array[MM_CAMCORDER_PREVIEW_TYPE_WIDE]); - } else { - g_print("\t There is ONLY NORMAL resolution\n\n"); + if (width_count > 0) { + g_print("\t NORMAL ratio : %dx%d\n", width_array[MM_CAMCORDER_PREVIEW_TYPE_NORMAL], height_array[MM_CAMCORDER_PREVIEW_TYPE_NORMAL]); + } + if (width_count > 1) { + g_print("\t WIDE ratio : %dx%d\n", width_array[MM_CAMCORDER_PREVIEW_TYPE_WIDE], height_array[MM_CAMCORDER_PREVIEW_TYPE_WIDE]); + } + if (width_count > 2) { + g_print("\t SQUARE ratio : %dx%d\n", width_array[MM_CAMCORDER_PREVIEW_TYPE_SQUARE], height_array[MM_CAMCORDER_PREVIEW_TYPE_SQUARE]); } } @@ -1422,14 +1428,14 @@ static void setting_menu(gchar buf) case 'r' : // Setting > Rotate camera input when recording g_print("*Rotate camera input\n"); - camcordertest_get_attr_valid_intrange(MMCAM_CAMERA_ROTATION, &min, &max); + camcordertest_get_attr_valid_intarray(MMCAM_CAMERA_ROTATION, &array, &count); - if(min >= max) { + if(count <= 0) { g_print("Not supported !! \n"); } else { flush_stdin(); - for (i = min ; i <= max ; i++) { - g_print("\t %d. %s\n", i, camera_rotation[i]); + for ( i = 0; i < count; i++) { + g_print("\t %d. %s\n", array[i], camera_rotation[array[i]]); } err = scanf("%d",&idx); CHECK_MM_ERROR(mm_camcorder_stop(hcamcorder->camcorder)); @@ -1983,6 +1989,52 @@ static void setting_menu(gchar buf) } break; + case 'B': + { + int bitrate = 0; + + flush_stdin(); + + g_print("*Encoded preview Bitrate (bps, should be bigger than zero)\n"); + + err = scanf("%d", &bitrate); + + err = mm_camcorder_set_attributes(hcamcorder->camcorder, &err_attr_name, + MMCAM_ENCODED_PREVIEW_BITRATE, bitrate, + NULL); + if (err != MM_ERROR_NONE) { + g_print("Failed to set Encoded preview Bitrate %d [err:0x%x]\n", bitrate, err); + free( err_attr_name ); + err_attr_name = NULL; + } else { + g_print("Succeed to set Encoded preview Bitrate %d\n", bitrate); + } + } + break; + + case 'I': + { + int interval = 0; + + flush_stdin(); + + g_print("*Encoded preview I-frame interval (ms, should be bigger than zero)\n"); + + err = scanf("%d", &interval); + + err = mm_camcorder_set_attributes(hcamcorder->camcorder, &err_attr_name, + MMCAM_ENCODED_PREVIEW_IFRAME_INTERVAL, interval, + NULL); + if (err != MM_ERROR_NONE) { + g_print("Failed to set Encoded preview I-frame interval %d [err:0x%x]\n", interval, err); + free( err_attr_name ); + err_attr_name = NULL; + } else { + g_print("Succeed to set Encoded preview I-frame interval %d\n", interval); + } + } + break; + case 'b' : // back hcamcorder->menu_state = MENU_STATE_MAIN; break; @@ -2099,6 +2151,7 @@ static gboolean init(int type) int preview_format = MM_PIXEL_FORMAT_NV12; int support_zero_copy_format = 0; int support_media_packet_preview_cb = 0; + int recommend_display_rotation = 0; MMHandleType cam_handle = 0; char *err_attr_name = NULL; @@ -2119,10 +2172,12 @@ static gboolean init(int type) MMCAM_RECOMMEND_PREVIEW_FORMAT_FOR_CAPTURE, &preview_format, MMCAM_SUPPORT_ZERO_COPY_FORMAT, &support_zero_copy_format, MMCAM_SUPPORT_MEDIA_PACKET_PREVIEW_CB, &support_media_packet_preview_cb, + MMCAM_RECOMMEND_DISPLAY_ROTATION, &recommend_display_rotation, NULL); warn_msg_t("MMCAM_SUPPORT_ZERO_COPY_FORMAT %d", support_zero_copy_format); warn_msg_t("MMCAM_SUPPORT_MEDIA_PACKET_PREVIEW_CB %d", support_media_packet_preview_cb); + warn_msg_t("MMCAM_RECOMMEND_DISPLAY_ROTATION %d", recommend_display_rotation); /* camcorder attribute setting */ err = mm_camcorder_set_attributes( (MMHandleType)cam_handle, &err_attr_name, @@ -2155,7 +2210,7 @@ static gboolean init(int type) MMCAM_AUDIO_ENCODER, MM_AUDIO_CODEC_AAC, MMCAM_VIDEO_ENCODER, MM_VIDEO_CODEC_MPEG4, MMCAM_VIDEO_ENCODER_BITRATE, VIDEO_ENCODE_BITRATE, - MMCAM_FILE_FORMAT, MM_FILE_FORMAT_3GP, + MMCAM_FILE_FORMAT, MM_FILE_FORMAT_MP4, //MMCAM_CAMERA_FPS, SRC_VIDEO_FRAME_RATE_30, MMCAM_CAMERA_FPS_AUTO, 0, MMCAM_CAMERA_ROTATION, MM_VIDEO_INPUT_ROTATION_NONE, @@ -2166,6 +2221,9 @@ static gboolean init(int type) MMCAM_TARGET_FILENAME, TARGET_FILENAME_VIDEO, strlen(TARGET_FILENAME_VIDEO), //MMCAM_TARGET_TIME_LIMIT, 360000, //MMCAM_TARGET_MAX_SIZE, 102400, + MMCAM_RECORDER_TAG_ENABLE, 1, + MMCAM_TAG_VIDEO_ORIENTATION, 1, + MMCAM_DISPLAY_ROTATION, recommend_display_rotation, NULL ); if (err != MM_ERROR_NONE) { @@ -2194,11 +2252,7 @@ static gboolean init(int type) MMCAM_AUDIO_CHANNEL, AUDIO_SOURCE_CHANNEL_AAC, MMCAM_TARGET_FILENAME, TARGET_FILENAME_AUDIO, size, MMCAM_TARGET_TIME_LIMIT, 360000, - //MMCAM_AUDIO_ENCODER_BITRATE, 12200, - MMCAM_TAG_GPS_ENABLE, TRUE, - MMCAM_TAG_LATITUDE, 35.3036944, - MMCAM_TAG_LONGITUDE, 176.67837, - MMCAM_TAG_ALTITUDE, 190.3455, + MMCAM_AUDIO_ENCODER_BITRATE, 128000, MMCAM_TARGET_MAX_SIZE, 300, NULL); @@ -2307,9 +2361,6 @@ static gboolean msg_callback(int message, void *msg_param, void *user_param) g_print("*******************************************************\n"); g_print("[Camcorder Testsuite] Camcorder Captured(filename=%s)\n", report->recording_filename); g_print("*******************************************************\n"); - - SAFE_FREE (report->recording_filename); - SAFE_FREE (report); } else { g_print( "[Camcorder Testsuite] report is NULL.\n" ); } @@ -2633,8 +2684,10 @@ int main(int argc, char **argv) { int bret; +#if !GLIB_CHECK_VERSION(2,35,0) if (!g_thread_supported()) g_thread_init (NULL); +#endif timer = g_timer_new(); -- 2.7.4