summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorKibum Kim <kb0929.kim@samsung.com>2012-02-27 21:16:21 +0900
committerKibum Kim <kb0929.kim@samsung.com>2012-02-27 21:16:21 +0900
commit235c811494b7fcc70c9575df92cc69990352f888 (patch)
tree2748ff06cd7e40e5cc18a70c4e37f14c7700fafb /src
downloadlibmm-camcorder-235c811494b7fcc70c9575df92cc69990352f888.tar.gz
libmm-camcorder-235c811494b7fcc70c9575df92cc69990352f888.tar.bz2
libmm-camcorder-235c811494b7fcc70c9575df92cc69990352f888.zip
tizen beta release
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am69
-rw-r--r--src/include/mm_camcorder.h2925
-rw-r--r--src/include/mm_camcorder_attribute.h365
-rw-r--r--src/include/mm_camcorder_audiorec.h103
-rw-r--r--src/include/mm_camcorder_configure.h366
-rw-r--r--src/include/mm_camcorder_exifdef.h99
-rw-r--r--src/include/mm_camcorder_exifinfo.h161
-rw-r--r--src/include/mm_camcorder_gstcommon.h183
-rw-r--r--src/include/mm_camcorder_internal.h1072
-rw-r--r--src/include/mm_camcorder_platform.h223
-rw-r--r--src/include/mm_camcorder_sound.h103
-rw-r--r--src/include/mm_camcorder_stillshot.h134
-rw-r--r--src/include/mm_camcorder_util.h246
-rw-r--r--src/include/mm_camcorder_videorec.h139
-rw-r--r--src/mm_camcorder.c428
-rw-r--r--src/mm_camcorder_attribute.c3882
-rw-r--r--src/mm_camcorder_audiorec.c1050
-rw-r--r--src/mm_camcorder_configure.c3276
-rw-r--r--src/mm_camcorder_exifinfo.c642
-rw-r--r--src/mm_camcorder_gstcommon.c2243
-rw-r--r--src/mm_camcorder_internal.c3449
-rw-r--r--src/mm_camcorder_platform.c977
-rw-r--r--src/mm_camcorder_sound.c491
-rw-r--r--src/mm_camcorder_stillshot.c2815
-rw-r--r--src/mm_camcorder_util.c1092
-rw-r--r--src/mm_camcorder_videorec.c1496
26 files changed, 28029 insertions, 0 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
new file mode 100644
index 0000000..dfaa6ba
--- /dev/null
+++ b/src/Makefile.am
@@ -0,0 +1,69 @@
+ACLOCAL_AMFLAGS='-I m4'
+
+lib_LTLIBRARIES = libmmfcamcorder.la
+
+includelibmmfcamcorderdir = $(includedir)/mmf
+
+includelibmmfcamcorder_HEADERS = include/mm_camcorder.h
+
+noinst_HEADERS = include/mm_camcorder_audiorec.h \
+ include/mm_camcorder_attribute.h \
+ include/mm_camcorder_configure.h \
+ include/mm_camcorder_gstcommon.h \
+ include/mm_camcorder_internal.h \
+ include/mm_camcorder_platform.h \
+ include/mm_camcorder_stillshot.h \
+ include/mm_camcorder_videorec.h \
+ include/mm_camcorder_util.h \
+ include/mm_camcorder_exifinfo.h\
+ include/mm_camcorder_exifdef.h \
+ include/mm_camcorder_sound.h
+
+libmmfcamcorder_la_SOURCES = mm_camcorder.c \
+ mm_camcorder_internal.c \
+ mm_camcorder_attribute.c \
+ mm_camcorder_stillshot.c \
+ mm_camcorder_videorec.c \
+ mm_camcorder_audiorec.c \
+ mm_camcorder_gstcommon.c \
+ mm_camcorder_platform.c \
+ mm_camcorder_configure.c \
+ mm_camcorder_util.c \
+ mm_camcorder_exifinfo.c \
+ mm_camcorder_sound.c
+
+libmmfcamcorder_la_CFLAGS = -I$(srcdir)/include \
+ $(GST_CFLAGS) \
+ $(GST_PLUGIN_BASE_CFLAGS) \
+ $(GST_INTERFACES_CFLAGS) \
+ $(MM_LOG_CFLAGS) \
+ $(MMTA_CFLAGS) \
+ $(EXIF_CFLAGS) \
+ $(MM_COMMON_CFLAGS) \
+ $(MMSESSION_CFLAGS) \
+ $(MMSOUND_CFLAGS) \
+ $(SNDFILE_CFLAGS) \
+ $(CAMSRCJPEGENC_CFLAGS) \
+ $(AUDIOSESSIONMGR_CFLAGS)
+
+libmmfcamcorder_la_LIBADD = \
+ $(GST_LIBS) \
+ $(GST_PLUGIN_BASE_LIBS) \
+ $(GST_INTERFACES_LIBS) \
+ $(MM_COMMON_LIBS) \
+ $(MM_LOG_LIBS) \
+ $(MMTA_LIBS) \
+ $(EXIF_LIBS) \
+ $(MMSESSION_LIBS) \
+ $(MMSOUND_LIBS) \
+ $(SNDFILE_LIBS) \
+ $(CAMSRCJPEGENC_LIBS) \
+ $(AUDIOSESSIONMGR_LIBS)
+
+libmmfcamcorder_la_CFLAGS += $(MMLOGSVR_CFLAGS) -DMMF_LOG_OWNER=0x010 -DMMF_DEBUG_PREFIX=\"MMF-CAMCORDER\" -D_INTERNAL_SESSION_MANAGER_
+libmmfcamcorder_la_LIBADD += $(MMLOGSVR_LIBS)
+
+install-exec-hook:
+ mkdir -p $(DESTDIR)$(prefix)/share/sounds/mm-camcorder && \
+ cp $(srcdir)/../sounds/*.wav $(DESTDIR)$(prefix)/share/sounds/mm-camcorder/
+
diff --git a/src/include/mm_camcorder.h b/src/include/mm_camcorder.h
new file mode 100644
index 0000000..a3f2f73
--- /dev/null
+++ b/src/include/mm_camcorder.h
@@ -0,0 +1,2925 @@
+/*
+ * libmm-camcorder
+ *
+ * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: Jeongmo Yang <jm80.yang@samsung.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+/**
+ @addtogroup CAMCORDER
+ @{
+
+ @par
+ This part describes the APIs with repect to Multimedia Camcorder.
+ Camcorder is for recording audio and video from audio and video input devices, capturing
+ still image from video input device, and audio recording from audio input
+ device.
+
+ @par
+ Camcorder can be reached by calling functions as shown in the following
+ figure, "The State of Camcorder".
+
+ @par
+ @image html camcorder_state.png "The State of Camcorder" width=12cm
+ @image latex camcorder_state.png "The State of Camcorder" width=12cm
+
+ @par
+ Between each states there is intermediate state, and in this state,
+ any function call which change the camcorder state will be failed.
+
+ @par
+ Recording state and paused state exists when the mode of camcorder is
+ video-capture or audio-capture mode. In case of image-capture mode, CAPTURING state will
+ exsit.
+
+ @par
+<div>
+<table>
+ <tr>
+ <td>FUNCTION</td>
+ <td>PRE-STATE</td>
+ <td>POST-STATE</td>
+ <td>SYNC TYPE</td>
+ </tr>
+ <tr>
+ <td>mm_camcorder_create()</td>
+ <td>NONE</td>
+ <td>NULL</td>
+ <td>SYNC</td>
+ </tr>
+ <tr>
+ <td>mm_camcorder_destroy()</td>
+ <td>NULL</td>
+ <td>NONE</td>
+ <td>SYNC</td>
+ </tr>
+ <tr>
+ <td>mm_camcorder_realize()</td>
+ <td>NULL</td>
+ <td>READY</td>
+ <td>SYNC</td>
+ </tr>
+ <tr>
+ <td>mm_camcorder_unrealize()</td>
+ <td>READY</td>
+ <td>NULL</td>
+ <td>SYNC</td>
+ </tr>
+ <tr>
+ <td>mm_camcorder_start()</td>
+ <td>READY</td>
+ <td>PREPARED</td>
+ <td>SYNC</td>
+ </tr>
+ <tr>
+ <td>mm_camcorder_stop()</td>
+ <td>PREPARED</td>
+ <td>READY</td>
+ <td>SYNC</td>
+ </tr>
+ <tr>
+ <td>mm_camcorder_capture_start()</td>
+ <td>PREPARED</td>
+ <td>CAPTURING</td>
+ <td>SYNC</td>
+ </tr>
+ <tr>
+ <td>mm_camcorder_capture_stop()</td>
+ <td>CAPTURING</td>
+ <td>PREPARED</td>
+ <td>SYNC</td>
+ </tr>
+ <tr>
+ <td>mm_camcorder_record()</td>
+ <td>PREPARED/PAUSED</td>
+ <td>RECORDING</td>
+ <td>SYNC</td>
+ </tr>
+ <tr>
+ <td>mm_camcorder_pause()</td>
+ <td>RECORDING</td>
+ <td>PAUSED</td>
+ <td>SYNC</td>
+ </tr>
+ <tr>
+ <td>mm_camcorder_commit()</td>
+ <td>RECORDING/PAUSED</td>
+ <td>PREPARED</td>
+ <td>SYNC</td>
+ </tr>
+ <tr>
+ <td>mm_camcorder_cancel()</td>
+ <td>RECORDING/PAUSED</td>
+ <td>PREPARED</td>
+ <td>SYNC</td>
+ </tr>
+ <tr>
+ <td>mm_camcorder_set_message_callback()</td>
+ <td>N/A</td>
+ <td>N/A</td>
+ <td>SYNC</td>
+ </tr>
+ <tr>
+ <td>mm_camcorder_set_video_stream_callback()</td>
+ <td>N/A</td>
+ <td>N/A</td>
+ <td>SYNC</td>
+ </tr>
+ <tr>
+ <td>mm_camcorder_set_video_capture_callback()</td>
+ <td>N/A</td>
+ <td>N/A</td>
+ <td>SYNC</td>
+ </tr>
+ <tr>
+ <td>mm_camcorder_get_state()</td>
+ <td>N/A</td>
+ <td>N/A</td>
+ <td>SYNC</td>
+ </tr>
+ <tr>
+ <td>mm_camcorder_get_attributes()</td>
+ <td>N/A</td>
+ <td>N/A</td>
+ <td>SYNC</td>
+ </tr>
+ <tr>
+ <td>mm_camcorder_set_attributes()</td>
+ <td>N/A</td>
+ <td>N/A</td>
+ <td>SYNC</td>
+ </tr>
+ <tr>
+ <td>mm_camcorder_get_attribute_info()</td>
+ <td>N/A</td>
+ <td>N/A</td>
+ <td>SYNC</td>
+ </tr>
+ <tr>
+ <td>mm_camcorder_init_focusing()</td>
+ <td>N/A</td>
+ <td>N/A</td>
+ <td>SYNC</td>
+ </tr>
+ <tr>
+ <td>mm_camcorder_start_focusing()</td>
+ <td>N/A</td>
+ <td>N/A</td>
+ <td>SYNC</td>
+ </tr>
+ <tr>
+ <td>mm_camcorder_stop_focusing()</td>
+ <td>N/A</td>
+ <td>N/A</td>
+ <td>SYNC</td>
+ </tr>
+</table>
+</div>
+
+ @par
+ * Attribute @n
+ Attribute system is an interface to operate camcorder. Depending on each attribute, camcorder behaves differently.
+ Attribute system provides get/set functions. Setting proper attributes, a user can control camcorder as he want. (mm_camcorder_set_attributes())
+ Also, a user can comprehend current status of the camcorder, calling getter function(mm_camcorder_get_attributes()).
+ Beware, arguments of mm_camcorder_set_attributes() and mm_camcorder_get_attributes() should be finished with 'NULL'.
+ This is a rule for the variable argument.
+ @par
+ Besides its value, each Attribute also has 'type' and 'validity type'. 'type' describes variable type that the attribute can get.
+ If you input a value that has wrong type, camcorder will not work properly or be crashed. 'validity' describes array or
+ range of values that are able to set to the attribute. 'validity type' defines type of the 'validity'.
+ @par
+ A user can retrieve these values using mm_camcorder_get_attribute_info().
+ Following tables have 'Attribute name', 'Attribute macro', 'Type', and 'Validity type'. You can refer '#MMCamAttrsType' and '#MMCamAttrsValidType'
+ for discerning 'Type' and 'Validity type'.
+
+
+ @par
+ Following are the attributes which should be set before initialization (#mm_camcorder_realize):
+
+ @par
+<div>
+<table>
+ <tr>
+ <td><center><b>Attribute</b></center></td>
+ <td><center><b>Description</b></center></td>
+ </tr>
+ <tr>
+ <td>#MMCAM_MODE</td>
+ <td>Mode of camcorder ( still/video/audio )</td>
+ </tr>
+ <tr>
+ <td>#MMCAM_AUDIO_DEVICE</td>
+ <td>Audio device ID for capturing audio stream</td>
+ </tr>
+ <tr>
+ <td>#MMCAM_CAMERA_DEVICE</td>
+ <td>Video device ID for capturing video stream</td>
+ </tr>
+ <tr>
+ <td>#MMCAM_AUDIO_ENCODER</td>
+ <td>Audio codec for encoding audio stream</td>
+ </tr>
+ <tr>
+ <td>#MMCAM_VIDEO_ENCODER</td>
+ <td>Video codec for encoding video stream</td>
+ </tr>
+ <tr>
+ <td>#MMCAM_IMAGE_ENCODER</td>
+ <td>Image codec for capturing still-image</td>
+ </tr>
+ <tr>
+ <td>#MMCAM_FILE_FORMAT</td>
+ <td>File format for recording media stream</td>
+ </tr>
+ <tr>
+ <td>#MMCAM_AUDIO_SAMPLERATE</td>
+ <td>Sampling rate of audio stream ( This is an integer field )</td>
+ </tr>
+ <tr>
+ <td>#MMCAM_AUDIO_FORMAT</td>
+ <td>Audio format of each sample</td>
+ </tr>
+ <tr>
+ <td>#MMCAM_AUDIO_CHANNEL</td>
+ <td>Channels of each sample ( This is an integer field )</td>
+ </tr>
+ <tr>
+ <td>#MMCAM_AUDIO_INPUT_ROUTE(deprecated)</td>
+ <td>Set audio input route</td>
+ </tr>
+ <tr>
+ <td>#MMCAM_CAMERA_FORMAT</td>
+ <td>Format of video stream. This is an integer field</td>
+ </tr>
+ <tr>
+ <td>#MMCAM_CAMERA_FPS</td>
+ <td>Frames per second ( This is an integer field )</td>
+ </tr>
+ <tr>
+ <td>#MMCAM_CAMERA_WIDTH</td>
+ <td>Width of input video stream</td>
+ </tr>
+ <tr>
+ <td>#MMCAM_CAMERA_HEIGHT</td>
+ <td>Height of input video stream</td>
+ </tr>
+ <tr>
+ <td>#MMCAM_CAMERA_FPS_AUTO</td>
+ <td>FPS Auto. When you set true to this attribute, FPS will vary depending on the amount of the light.</td>
+ </tr>
+ <tr>
+ <td>#MMCAM_DISPLAY_HANDLE</td>
+ <td>Pointer of display buffer or ID of xwindow</td>
+ </tr>
+ <tr>
+ <td>#MMCAM_DISPLAY_DEVICE</td>
+ <td>Device of display</td>
+ </tr>
+ <tr>
+ <td>#MMCAM_DISPLAY_SURFACE</td>
+ <td>Surface of display</td>
+ </tr>
+ <tr>
+ <td>#MMCAM_DISPLAY_SOURCE_X</td>
+ <td>X position of source rectangle. When you want to crop the source, you can set the area with this value.</td>
+ </tr>
+ <tr>
+ <td>#MMCAM_DISPLAY_SOURCE_Y</td>
+ <td>Y position of source rectangle. When you want to crop the source, you can set the area with this value.</td>
+ </tr>
+ <tr>
+ <td>#MMCAM_DISPLAY_SOURCE_WIDTH</td>
+ <td>Width of source rectangle. When you want to crop the source, you can set the area with this value.</td>
+ </tr>
+ <tr>
+ <td>#MMCAM_DISPLAY_SOURCE_HEIGHT</td>
+ <td>Height of source rectangle. When you want to crop the source, you can set the area with this value.</td>
+ </tr>
+ <tr>
+ <td>#MMCAM_DISPLAY_ROTATION</td>
+ <td>Rotation of display</td>
+ </tr>
+ <tr>
+ <td>#MMCAM_DISPLAY_VISIBLE</td>
+ <td>Visible of display</td>
+ </tr>
+ <tr>
+ <td>#MMCAM_DISPLAY_SCALE</td>
+ <td>A scale of displayed image</td>
+ </tr>
+ <tr>
+ <td>#MMCAM_DISPLAY_GEOMETRY_METHOD</td>
+ <td>A method that describes a form of geometry for display</td>
+ </tr>
+</table>
+</div>
+
+ @par
+ Following are the attributes which should be set before recording (mm_camcorder_record()):
+
+ @par
+<div>
+<table>
+ <tr>
+ <td><center><b>Attribute</b></center></td>
+ <td><center><b>Description</b></center></td>
+ </tr>
+ <tr>
+ <td>#MMCAM_AUDIO_ENCODER_BITRATE</td>
+ <td>Bitrate of Audio Encoder</td>
+ </tr>
+ <tr>
+ <td>#MMCAM_VIDEO_ENCODER_BITRATE</td>
+ <td>Bitrate of Video Encoder</td>
+ </tr>
+ <tr>
+ <td>#MMCAM_TARGET_FILENAME</td>
+ <td>Target filename. Only used in Audio/Video recording. This is not used for capturing.</td>
+ </tr>
+ <tr>
+ <td>#MMCAM_TARGET_TIME_LIMIT</td>
+ <td>Time limit of recording file. If the elapsed time of recording reaches this value.</td>
+ </tr>
+</table>
+</div>
+
+ @par
+ Following are the attributes which should be set before capturing (mm_camcorder_capture_start()):
+
+ @par
+<div>
+<table>
+ <tr>
+ <td><center><b>Attribute</b></center></td>
+ <td><center><b>Description</b></center></td>
+ </tr>
+ <tr>
+ <td>#MMCAM_IMAGE_ENCODER_QUALITY</td>
+ <td>Encoding quality of Image codec</td>
+ </tr>
+ <tr>
+ <td>#MMCAM_CAPTURE_FORMAT</td>
+ <td>Pixel format that you want to capture</td>
+ </tr>
+ <tr>
+ <td>#MMCAM_CAPTURE_WIDTH</td>
+ <td>Width of the image that you want to capture</td>
+ </tr>
+ <tr>
+ <td>#MMCAM_CAPTURE_HEIGHT</td>
+ <td>Height of the image that you want to capture</td>
+ </tr>
+ <tr>
+ <td>#MMCAM_CAPTURE_COUNT</td>
+ <td>Total count of capturing</td>
+ </tr>
+ <tr>
+ <td>#MMCAM_CAPTURE_INTERVAL</td>
+ <td>Interval between each capturing on Multishot ( MMCAM_CAPTURE_COUNT > 1 )</td>
+ </tr>
+</table>
+</div>
+
+ @par
+ Following are the attributes which can be set anytime:
+
+ @par
+<div>
+<table>
+ <tr>
+ <td><center><b>Attribute</b></center></td>
+ <td><center><b>Description</b></center></td>
+ </tr>
+ <tr>
+ <td>#MMCAM_AUDIO_VOLUME</td>
+ <td>Input volume of audio source ( double value )</td>
+ </tr>
+ <tr>
+ <td>#MMCAM_CAMERA_DIGITAL_ZOOM</td>
+ <td>Digital zoom level</td>
+ </tr>
+ <tr>
+ <td>#MMCAM_CAMERA_OPTICAL_ZOOM</td>
+ <td>Optical zoom level</td>
+ </tr>
+ <tr>
+ <td>#MMCAM_CAMERA_FOCUS_MODE</td>
+ <td>Focus mode</td>
+ </tr>
+ <tr>
+ <td>#MMCAM_CAMERA_AF_SCAN_RANGE</td>
+ <td>AF Scan range</td>
+ </tr>
+ <tr>
+ <td>#MMCAM_CAMERA_AF_TOUCH_X</td>
+ <td>X coordinate of touching position</td>
+ </tr>
+ <tr>
+ <td>#MMCAM_CAMERA_AF_TOUCH_Y</td>
+ <td>Y coordinate of touching position</td>
+ </tr>
+ <tr>
+ <td>#MMCAM_CAMERA_AF_TOUCH_WIDTH</td>
+ <td>Width of touching area</td>
+ </tr>
+ <tr>
+ <td>#MMCAM_CAMERA_AF_TOUCH_HEIGHT</td>
+ <td>Height of touching area</td>
+ </tr>
+ <tr>
+ <td>#MMCAM_CAMERA_EXPOSURE_MODE</td>
+ <td>Exposure mode</td>
+ </tr>
+ <tr>
+ <td>#MMCAM_CAMERA_EXPOSURE_VALUE</td>
+ <td>Exposure value</td>
+ </tr>
+ <tr>
+ <td>#MMCAM_CAMERA_F_NUMBER</td>
+ <td>f number of camera</td>
+ </tr>
+ <tr>
+ <td>#MMCAM_CAMERA_SHUTTER_SPEED</td>
+ <td>Shutter speed</td>
+ </tr>
+ <tr>
+ <td>#MMCAM_CAMERA_ISO</td>
+ <td>ISO of capturing image</td>
+ </tr>
+ <tr>
+ <td>#MMCAM_CAMERA_WDR</td>
+ <td>Wide dynamic range</td>
+ </tr>
+ <tr>
+ <td>#MMCAM_CAMERA_ANTI_HANDSHAKE</td>
+ <td>Anti Handshake</td>
+ </tr>
+ <tr>
+ <td>#MMCAM_CAMERA_FOCAL_LENGTH</td>
+ <td>Focal length of camera lens</td>
+ </tr>
+ <tr>
+ <td>#MMCAM_FILTER_BRIGHTNESS</td>
+ <td>Brightness level</td>
+ </tr>
+ <tr>
+ <td>#MMCAM_FILTER_CONTRAST</td>
+ <td>Contrast level</td>
+ </tr>
+ <tr>
+ <td>#MMCAM_FILTER_WB</td>
+ <td>White balance</td>
+ </tr>
+ <tr>
+ <td>#MMCAM_FILTER_COLOR_TONE</td>
+ <td>Color tone (Color effect)</td>
+ </tr>
+ <tr>
+ <td>#MMCAM_FILTER_SCENE_MODE</td>
+ <td>Scene mode (Program mode)</td>
+ </tr>
+ <tr>
+ <td>#MMCAM_FILTER_SATURATION</td>
+ <td>Saturation level</td>
+ </tr>
+ <tr>
+ <td>#MMCAM_FILTER_HUE</td>
+ <td>Hue level</td>
+ </tr>
+ <tr>
+ <td>#MMCAM_FILTER_SHARPNESS</td>
+ <td>Sharpness level</td>
+ </tr>
+ <tr>
+ <td>#MMCAM_CAPTURE_BREAK_CONTINUOUS_SHOT</td>
+ <td>Set this as true when you want to stop multishot immediately</td>
+ </tr>
+ <tr>
+ <td>#MMCAM_DISPLAY_RECT_X</td>
+ <td>X position of display rectangle (This is only available when MMCAM_DISPLAY_GEOMETRY_METHOD is MM_CAMCORDER_CUSTOM_ROI)</td>
+ </tr>
+ <tr>
+ <td>#MMCAM_DISPLAY_RECT_Y</td>
+ <td>Y position of display rectangle (This is only available when MMCAM_DISPLAY_GEOMETRY_METHOD is MM_CAMCORDER_CUSTOM_ROI)</td>
+ </tr>
+ <tr>
+ <td>#MMCAM_DISPLAY_RECT_WIDTH</td>
+ <td>Width of display rectangle (This is only available when MMCAM_DISPLAY_GEOMETRY_METHOD is MM_CAMCORDER_CUSTOM_ROI)</td>
+ </tr>
+ <tr>
+ <td>#MMCAM_DISPLAY_RECT_HEIGHT</td>
+ <td>Height of display rectangle (This is only available when MMCAM_DISPLAY_GEOMETRY_METHOD is MM_CAMCORDER_CUSTOM_ROI)</td>
+ </tr>
+ <tr>
+ <td>#MMCAM_TAG_ENABLE</td>
+ <td>Enable to write tags (If this value is FALSE, none of tag information will be written to captured file)</td>
+ </tr>
+ <tr>
+ <td>#MMCAM_TAG_IMAGE_DESCRIPTION</td>
+ <td>Image description</td>
+ </tr>
+ <tr>
+ <td>#MMCAM_TAG_ORIENTATION</td>
+ <td>Orientation of captured image</td>
+ </tr>
+ <tr>
+ <td>#MMCAM_TAG_SOFTWARE</td>
+ <td>software name and version</td>
+ </tr>
+ <tr>
+ <td>#MMCAM_TAG_LATITUDE</td>
+ <td>Latitude of captured postion (GPS information)</td>
+ </tr>
+ <tr>
+ <td>#MMCAM_TAG_LONGITUDE</td>
+ <td>Longitude of captured postion (GPS information)</td>
+ </tr>
+ <tr>
+ <td>#MMCAM_TAG_ALTITUDE</td>
+ <td>Altitude of captured postion (GPS information)</td>
+ </tr>
+ <tr>
+ <td>#MMCAM_STROBE_CONTROL</td>
+ <td>Strobe control</td>
+ </tr>
+ <tr>
+ <td>#MMCAM_STROBE_MODE</td>
+ <td>Operation Mode of strobe</td>
+ </tr>
+ <tr>
+ <td>#MMCAM_DETECT_MODE</td>
+ <td>Detection mode</td>
+ </tr>
+ <tr>
+ <td>#MMCAM_DETECT_NUMBER</td>
+ <td>Total number of detected object</td>
+ </tr>
+ <tr>
+ <td>#MMCAM_DETECT_FOCUS_SELECT</td>
+ <td>Select one of detected objects</td>
+ </tr>
+</table>
+</div>
+ */
+
+
+
+#ifndef __MM_CAMCORDER_H__
+#define __MM_CAMCORDER_H__
+
+
+/*=======================================================================================
+| INCLUDE FILES |
+========================================================================================*/
+#include <glib.h>
+
+#include <mm_types.h>
+#include <mm_error.h>
+#include <mm_message.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*=======================================================================================
+| GLOBAL DEFINITIONS AND DECLARATIONS FOR CAMCORDER |
+========================================================================================*/
+
+/*=======================================================================================
+| MACRO DEFINITIONS |
+========================================================================================*/
+/**
+ * Get numerator. Definition for fraction setting, such as MMCAM_CAMERA_SHUTTER_SPEED and MMCAM_CAMERA_EXPOSURE_VALUE.
+ */
+#define MM_CAMCORDER_GET_NUMERATOR(x) ((int)(((int)(x) >> 16) & 0xFFFF))
+/**
+ * Get denominator. Definition for fraction setting, such as MMCAM_CAMERA_SHUTTER_SPEED and MMCAM_CAMERA_EXPOSURE_VALUE.
+ */
+#define MM_CAMCORDER_GET_DENOMINATOR(x) ((int)(((int)(x)) & 0xFFFF))
+/**
+ * Set fraction value. Definition for fraction setting, such as MMCAM_CAMERA_SHUTTER_SPEED and MMCAM_CAMERA_EXPOSURE_VALUE.
+ */
+#define MM_CAMCORDER_SET_FRACTION(numerator,denominator) ((int)((((int)(numerator)) << 16) | (int)(denominator)))
+
+/* Attributes Macros */
+/**
+ * Mode of camcorder (still/video/audio).
+ * @see MMCamcorderModeType
+ */
+#define MMCAM_MODE "mode"
+
+/**
+ * Audio device ID for capturing audio stream.
+ * @see MMAudioDeviceType (in mm_types.h)
+ */
+#define MMCAM_AUDIO_DEVICE "audio-device"
+
+/**
+ * Video device ID for capturing video stream.
+ * @see MMVideoDeviceType (in mm_types.h)
+ */
+#define MMCAM_CAMERA_DEVICE "camera-device"
+
+/**
+ * Audio codec for encoding audio stream.
+ * @see MMAudioCodecType (in mm_types.h)
+ */
+#define MMCAM_AUDIO_ENCODER "audio-encoder"
+
+/**
+ * Video codec for encoding video stream.
+ * @see MMVideoCodecType (in mm_types.h)
+ */
+#define MMCAM_VIDEO_ENCODER "video-encoder"
+
+/**
+ * Image codec for capturing still-image.
+ * @see MMImageCodecType (in mm_types.h)
+ */
+#define MMCAM_IMAGE_ENCODER "image-encoder"
+
+/**
+ * File format for recording media stream.
+ * @see MMFileFormatType (in mm_types.h)
+ */
+#define MMCAM_FILE_FORMAT "file-format"
+
+/**
+ * Sampling rate of audio stream. This is an integer field.
+ */
+#define MMCAM_AUDIO_SAMPLERATE "audio-samplerate"
+
+/**
+ * Audio format of each sample.
+ * @see MMCamcorderAudioFormat
+ */
+#define MMCAM_AUDIO_FORMAT "audio-format"
+
+/**
+ * Channels of each sample. This is an integer field.
+ */
+#define MMCAM_AUDIO_CHANNEL "audio-channel"
+
+/**
+ * Input volume of audio source. Double value.
+ */
+#define MMCAM_AUDIO_VOLUME "audio-volume"
+
+/**
+ * Set audio input route
+ * @remarks Deprecated. This will be removed soon.
+ * @see MMAudioRoutePolicy (in mm_types.h)
+ */
+#define MMCAM_AUDIO_INPUT_ROUTE "audio-input-route"
+
+/**
+ * Format of video stream. This is an integer field
+ * @see MMPixelFormatType (in mm_types.h)
+ */
+#define MMCAM_CAMERA_FORMAT "camera-format"
+
+/**
+ * Frames per second. This is an integer field
+ *
+ */
+#define MMCAM_CAMERA_FPS "camera-fps"
+
+/**
+ * Width of input video stream.
+ */
+#define MMCAM_CAMERA_WIDTH "camera-width"
+
+/**
+ * Height of input video stream.
+ * @see
+ */
+#define MMCAM_CAMERA_HEIGHT "camera-height"
+
+/**
+ * Digital zoom level.
+ */
+#define MMCAM_CAMERA_DIGITAL_ZOOM "camera-digital-zoom"
+
+/**
+ * Optical zoom level.
+ */
+#define MMCAM_CAMERA_OPTICAL_ZOOM "camera-optical-zoom"
+
+/**
+ * Focus mode
+ * @see MMCamcorderFocusMode
+ */
+#define MMCAM_CAMERA_FOCUS_MODE "camera-focus-mode"
+
+/**
+ * AF Scan range
+ * @see MMCamcorderAutoFocusType
+ */
+#define MMCAM_CAMERA_AF_SCAN_RANGE "camera-af-scan-range"
+
+/**
+ * X coordinate of touching position. Only available when you set '#MM_CAMCORDER_AUTO_FOCUS_TOUCH' to '#MMCAM_CAMERA_AF_SCAN_RANGE'.
+ * @see MMCamcorderAutoFocusType
+ */
+#define MMCAM_CAMERA_AF_TOUCH_X "camera-af-touch-x"
+
+/**
+ * Y coordinate of touching position. Only available when you set '#MM_CAMCORDER_AUTO_FOCUS_TOUCH' to '#MMCAM_CAMERA_AF_SCAN_RANGE'.
+ * @see MMCamcorderAutoFocusType
+ */
+#define MMCAM_CAMERA_AF_TOUCH_Y "camera-af-touch-y"
+
+/**
+ * Width of touching area. Only available when you set '#MM_CAMCORDER_AUTO_FOCUS_TOUCH' to '#MMCAM_CAMERA_AF_SCAN_RANGE'.
+ * @see MMCamcorderAutoFocusType
+ */
+#define MMCAM_CAMERA_AF_TOUCH_WIDTH "camera-af-touch-width"
+
+/**
+ * Height of touching area. Only available when you set '#MM_CAMCORDER_AUTO_FOCUS_TOUCH' to '#MMCAM_CAMERA_AF_SCAN_RANGE'.
+ * @see MMCamcorderAutoFocusType
+ */
+#define MMCAM_CAMERA_AF_TOUCH_HEIGHT "camera-af-touch-height"
+
+/**
+ * Exposure mode
+ * @see MMCamcorderAutoExposureType
+ */
+#define MMCAM_CAMERA_EXPOSURE_MODE "camera-exposure-mode"
+
+/**
+ * Exposure value
+ */
+#define MMCAM_CAMERA_EXPOSURE_VALUE "camera-exposure-value"
+
+/**
+ * f number of camera
+ */
+#define MMCAM_CAMERA_F_NUMBER "camera-f-number"
+
+/**
+ * Shutter speed
+ */
+#define MMCAM_CAMERA_SHUTTER_SPEED "camera-shutter-speed"
+
+/**
+ * ISO of capturing image
+ * @see MMCamcorderISOType
+ */
+#define MMCAM_CAMERA_ISO "camera-iso"
+
+/**
+ * Wide dynamic range.
+ * @see MMCamcorderWDRMode
+ */
+#define MMCAM_CAMERA_WDR "camera-wdr"
+
+/**
+ * Focal length of camera lens.
+ */
+#define MMCAM_CAMERA_FOCAL_LENGTH "camera-focal-length"
+
+/**
+ * Anti Handshake
+ * @see MMCamcorderAHSMode
+ */
+#define MMCAM_CAMERA_ANTI_HANDSHAKE "camera-anti-handshake"
+
+/**
+ * FPS Auto. When you set true to this attribute, FPS will vary depending on the amount of the light.
+ */
+#define MMCAM_CAMERA_FPS_AUTO "camera-fps-auto"
+
+/**
+ * Rotation angle of video input stream.
+ * @see MMVideoInputRotationType (in mm_types.h)
+ */
+#define MMCAM_CAMERA_ROTATION "camera-rotation"
+
+/**
+ * Bitrate of Audio Encoder
+ */
+#define MMCAM_AUDIO_ENCODER_BITRATE "audio-encoder-bitrate"
+
+/**
+ * Bitrate of Video Encoder
+ */
+#define MMCAM_VIDEO_ENCODER_BITRATE "video-encoder-bitrate"
+
+/**
+ * Encoding quality of Image codec
+ */
+#define MMCAM_IMAGE_ENCODER_QUALITY "image-encoder-quality"
+
+/**
+ * Brightness level
+ */
+#define MMCAM_FILTER_BRIGHTNESS "filter-brightness"
+
+/**
+ * Contrast level
+ */
+#define MMCAM_FILTER_CONTRAST "filter-contrast"
+
+/**
+ * White balance
+ * @see MMCamcorderWhiteBalanceType
+ */
+#define MMCAM_FILTER_WB "filter-wb"
+
+/**
+ * Color tone. (Color effect)
+ * @see MMCamcorderColorToneType
+ */
+#define MMCAM_FILTER_COLOR_TONE "filter-color-tone"
+
+/**
+ * Scene mode (Program mode)
+ * @see MMCamcorderSceneModeType
+ */
+#define MMCAM_FILTER_SCENE_MODE "filter-scene-mode"
+
+/**
+ * Saturation level
+ */
+#define MMCAM_FILTER_SATURATION "filter-saturation"
+
+/**
+ * Hue level
+ */
+#define MMCAM_FILTER_HUE "filter-hue"
+
+/**
+ * Sharpness level
+ */
+#define MMCAM_FILTER_SHARPNESS "filter-sharpness"
+
+/**
+ * Pixel format that you want to capture. If you set MM_PIXEL_FORMAT_ENCODED,
+ * the result will be encoded by image codec specified in #MMCAM_IMAGE_ENCODER.
+ * If not, the result will be raw data.
+ *
+ * @see MMPixelFormatType (in mm_types.h)
+ */
+#define MMCAM_CAPTURE_FORMAT "capture-format"
+
+/**
+ * Width of the image that you want to capture
+ */
+#define MMCAM_CAPTURE_WIDTH "capture-width"
+
+/**
+ * Height of the image that you want to capture
+
+ */
+#define MMCAM_CAPTURE_HEIGHT "capture-height"
+
+/**
+ * Total count of capturing. If you set this, it will caputre multiple time.
+ */
+#define MMCAM_CAPTURE_COUNT "capture-count"
+
+/**
+ * Interval between each capturing on Multishot.
+ */
+#define MMCAM_CAPTURE_INTERVAL "capture-interval"
+
+/**
+ * Set this when you want to stop multishot immediately.
+ */
+#define MMCAM_CAPTURE_BREAK_CONTINUOUS_SHOT "capture-break-cont-shot"
+
+/**
+ * Pointer of display buffer or ID of xwindow.
+ */
+#define MMCAM_DISPLAY_HANDLE "display-handle"
+
+/**
+ * Device of display.
+ * @see MMDisplayDeviceType (in mm_types.h)
+ */
+#define MMCAM_DISPLAY_DEVICE "display-device"
+
+/**
+ * Surface of display.
+ * @see MMDisplaySurfaceType (in mm_types.h)
+ */
+#define MMCAM_DISPLAY_SURFACE "display-surface"
+
+/**
+ * X position of display rectangle.
+ * This is only available when #MMCAM_DISPLAY_GEOMETRY_METHOD is MM_CAMCORDER_CUSTOM_ROI.
+ * @see MMCamcorderGeometryMethod
+ */
+#define MMCAM_DISPLAY_RECT_X "display-rect-x"
+
+/**
+ * Y position of display rectangle
+ * This is only available when #MMCAM_DISPLAY_GEOMETRY_METHOD is MM_CAMCORDER_CUSTOM_ROI.
+ * @see MMCamcorderGeometryMethod
+ */
+#define MMCAM_DISPLAY_RECT_Y "display-rect-y"
+
+/**
+ * Width of display rectangle
+ * This is only available when #MMCAM_DISPLAY_GEOMETRY_METHOD is MM_CAMCORDER_CUSTOM_ROI.
+ * @see MMCamcorderGeometryMethod
+ */
+#define MMCAM_DISPLAY_RECT_WIDTH "display-rect-width"
+
+/**
+ * Height of display rectangle
+ * This is only available when #MMCAM_DISPLAY_GEOMETRY_METHOD is MM_CAMCORDER_CUSTOM_ROI.
+ * @see MMCamcorderGeometryMethod
+ */
+#define MMCAM_DISPLAY_RECT_HEIGHT "display-rect-height"
+
+/**
+ * X position of source rectangle. When you want to crop the source, you can set the area with this value.
+ */
+#define MMCAM_DISPLAY_SOURCE_X "display-src-x"
+
+/**
+ * Y position of source rectangle. When you want to crop the source, you can set the area with this value.
+ */
+#define MMCAM_DISPLAY_SOURCE_Y "display-src-y"
+
+/**
+ * Width of source rectangle. When you want to crop the source, you can set the area with this value.
+ */
+#define MMCAM_DISPLAY_SOURCE_WIDTH "display-src-width"
+
+/**
+ * Height of source rectangle. When you want to crop the source, you can set the area with this value.
+ */
+#define MMCAM_DISPLAY_SOURCE_HEIGHT "display-src-height"
+
+/**
+ * Rotation angle of display.
+ * @see MMDisplayRotationType (in mm_types.h)
+ */
+#define MMCAM_DISPLAY_ROTATION "display-rotation"
+
+/**
+ * Visible of display.
+ */
+#define MMCAM_DISPLAY_VISIBLE "display-visible"
+
+/**
+ * A scale of displayed image. Available value is like below.
+ * @see MMDisplayScaleType (in mm_types.h)
+ */
+#define MMCAM_DISPLAY_SCALE "display-scale"
+
+/**
+ * A method that describes a form of geometry for display.
+ * @see MMCamcorderGeometryMethod
+ */
+#define MMCAM_DISPLAY_GEOMETRY_METHOD "display-geometry-method"
+
+/**
+ * Target filename. Only used in Audio/Video recording. This is not used for capturing.
+ */
+#define MMCAM_TARGET_FILENAME "target-filename"
+
+/**
+ * Time limit(Second) of recording file. If the elapsed time of recording reaches this value,
+ * camcorder will send 'MM_MESSAGE_CAMCORDER_TIME_LIMIT' message.
+ */
+#define MMCAM_TARGET_TIME_LIMIT "target-time-limit"
+
+/**
+ * Enable to write tags. If this value is FALSE, none of tag information will be written to captured file.
+ */
+#define MMCAM_TAG_ENABLE "tag-enable"
+
+/**
+ * Image description.
+ */
+#define MMCAM_TAG_IMAGE_DESCRIPTION "tag-image-description"
+
+/**
+ * Orientation of captured image
+ * @see MMCamcorderTagOrientation
+ */
+#define MMCAM_TAG_ORIENTATION "tag-orientation"
+
+/**
+ * software name and version
+ */
+#define MMCAM_TAG_SOFTWARE "tag-software"
+
+/**
+ * Enable to write tags related to GPS. If this value is TRUE, tags related GPS information will be written to captured file.
+ */
+#define MMCAM_TAG_GPS_ENABLE "tag-gps-enable"
+
+/**
+ * Latitude of captured postion. GPS information.
+ */
+#define MMCAM_TAG_LATITUDE "tag-latitude"
+
+/**
+ * Longitude of captured postion. GPS information.
+ */
+#define MMCAM_TAG_LONGITUDE "tag-longitude"
+
+/**
+ * Altitude of captured postion. GPS information.
+ */
+#define MMCAM_TAG_ALTITUDE "tag-altitude"
+
+/**
+ * Strobe control
+ * @see MMCamcorderStrobeControl
+ */
+#define MMCAM_STROBE_CONTROL "strobe-control"
+
+/**
+ * Operation Mode of strobe
+ * @see MMCamcorderStrobeMode
+ */
+#define MMCAM_STROBE_MODE "strobe-mode"
+
+/**
+ * Detection mode
+ * @see MMCamcorderDetectMode
+ */
+#define MMCAM_DETECT_MODE "detect-mode"
+
+/**
+ * Total number of detected object
+ */
+#define MMCAM_DETECT_NUMBER "detect-number"
+
+/**
+ * You can use this attribute to select one of detected objects.
+ */
+#define MMCAM_DETECT_FOCUS_SELECT "detect-focus-select"
+
+/**
+ * Recommend preview format for capture
+ */
+#define MMCAM_RECOMMEND_PREVIEW_FORMAT_FOR_CAPTURE "recommend-preview-format-for-capture"
+
+/**
+ * Recommend preview format for recording
+ */
+#define MMCAM_RECOMMEND_PREVIEW_FORMAT_FOR_RECORDING "recommend-preview-format-for-recording"
+
+/**
+ * Recommend rotation of display
+ */
+#define MMCAM_RECOMMEND_DISPLAY_ROTATION "recommend-display-rotation"
+
+/**
+ * Rotation angle of video input stream and display for video recording.
+ */
+#define MMCAM_CAMCORDER_ROTATION "camcorder-rotation"
+
+/*=======================================================================================
+| ENUM DEFINITIONS |
+========================================================================================*/
+/**
+ * An enumeration for camcorder states.
+ */
+typedef enum {
+ MM_CAMCORDER_STATE_NONE, /**< Camcorder is not created yet */
+ MM_CAMCORDER_STATE_NULL, /**< Camcorder is created, but not initialized yet */
+ MM_CAMCORDER_STATE_READY, /**< Camcorder is ready to capture */
+ MM_CAMCORDER_STATE_PREPARE, /**< Camcorder is prepared to capture (Preview) */
+ MM_CAMCORDER_STATE_CAPTURING, /**< Camcorder is now capturing still images */
+ MM_CAMCORDER_STATE_RECORDING, /**< Camcorder is now recording */
+ MM_CAMCORDER_STATE_PAUSED, /**< Camcorder is paused while recording */
+ MM_CAMCORDER_STATE_NUM, /**< Number of camcorder states */
+} MMCamcorderStateType;
+
+/**
+ * An enumeration for camcorder mode.
+ */
+typedef enum {
+ MM_CAMCORDER_MODE_IMAGE = 0, /**< Still image capture mode */
+ MM_CAMCORDER_MODE_AUDIO, /**< Audio recording mode */
+ MM_CAMCORDER_MODE_VIDEO, /**< Video recording mode */
+} MMCamcorderModeType;
+
+
+/**
+ * An enumeration of Audio Format.
+ */
+typedef enum
+{
+ MM_CAMCORDER_AUDIO_FORMAT_PCM_U8 = 0, /**< unsigned 8bit audio */
+ MM_CAMCORDER_AUDIO_FORMAT_PCM_S16_LE = 2, /**< signed 16bit audio. Little endian. */
+} MMCamcorderAudioFormat;
+
+
+/**
+ * An enumeration for color tone. Color tone provides an impression of
+ * seeing through a tinted glass.
+ */
+enum MMCamcorderColorToneType {
+ MM_CAMCORDER_COLOR_TONE_NONE = 0, /**< None */
+ MM_CAMCORDER_COLOR_TONE_MONO, /**< Mono */
+ MM_CAMCORDER_COLOR_TONE_SEPIA, /**< Sepia */
+ MM_CAMCORDER_COLOR_TONE_NEGATIVE, /**< Negative */
+ MM_CAMCORDER_COLOR_TONE_BLUE, /**< Blue */
+ MM_CAMCORDER_COLOR_TONE_GREEN, /**< Green */
+ MM_CAMCORDER_COLOR_TONE_AQUA, /**< Aqua */
+ MM_CAMCORDER_COLOR_TONE_VIOLET, /**< Violet */
+ MM_CAMCORDER_COLOR_TONE_ORANGE, /**< Orange */
+ MM_CAMCORDER_COLOR_TONE_GRAY, /**< Gray */
+ MM_CAMCORDER_COLOR_TONE_RED, /**< Red */
+ MM_CAMCORDER_COLOR_TONE_ANTIQUE, /**< Antique */
+ MM_CAMCORDER_COLOR_TONE_WARM, /**< Warm */
+ MM_CAMCORDER_COLOR_TONE_PINK, /**< Pink */
+ MM_CAMCORDER_COLOR_TONE_YELLOW, /**< Yellow */
+ MM_CAMCORDER_COLOR_TONE_PURPLE, /**< Purple */
+ MM_CAMCORDER_COLOR_TONE_EMBOSS, /**< Emboss */
+ MM_CAMCORDER_COLOR_TONE_OUTLINE, /**< Outline */
+
+ MM_CAMCORDER_COLOR_TONE_SOLARIZATION_1, /**< Solarization1 */
+ MM_CAMCORDER_COLOR_TONE_SOLARIZATION_2, /**< Solarization2 */
+ MM_CAMCORDER_COLOR_TONE_SOLARIZATION_3, /**< Solarization3 */
+ MM_CAMCORDER_COLOR_TONE_SOLARIZATION_4, /**< Solarization4 */
+
+ MM_CAMCORDER_COLOR_TONE_SKETCH_1, /**< Sketch1 */
+ MM_CAMCORDER_COLOR_TONE_SKETCH_2, /**< Sketch2 */
+ MM_CAMCORDER_COLOR_TONE_SKETCH_3, /**< Sketch3 */
+ MM_CAMCORDER_COLOR_TONE_SKETCH_4, /**< Sketch4 */
+};
+
+
+/**
+ * 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.
+ */
+enum MMCamcorderWhiteBalanceType {
+ MM_CAMCORDER_WHITE_BALANCE_NONE = 0, /**< None */
+ MM_CAMCORDER_WHITE_BALANCE_AUTOMATIC, /**< Automatic */
+ MM_CAMCORDER_WHITE_BALANCE_DAYLIGHT, /**< Daylight */
+ MM_CAMCORDER_WHITE_BALANCE_CLOUDY, /**< Cloudy */
+ MM_CAMCORDER_WHITE_BALANCE_FLUOROSCENT, /**< Fluorescent */
+ MM_CAMCORDER_WHITE_BALANCE_INCANDESCENT, /**< Incandescent */
+ MM_CAMCORDER_WHITE_BALANCE_SHADE, /**< Shade */
+ 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
+ * backlight. It can be an automatic setting also.
+ */
+enum MMCamcorderSceneModeType {
+ MM_CAMCORDER_SCENE_MODE_NORMAL = 0, /**< Normal */
+ MM_CAMCORDER_SCENE_MODE_PORTRAIT, /**< Portrait */
+ MM_CAMCORDER_SCENE_MODE_LANDSCAPE, /**< Landscape */
+ MM_CAMCORDER_SCENE_MODE_SPORTS, /**< Sports */
+ MM_CAMCORDER_SCENE_MODE_PARTY_N_INDOOR, /**< Party & indoor */
+ MM_CAMCORDER_SCENE_MODE_BEACH_N_INDOOR, /**< Beach & indoor */
+ MM_CAMCORDER_SCENE_MODE_SUNSET, /**< Sunset */
+ MM_CAMCORDER_SCENE_MODE_DUSK_N_DAWN, /**< Dusk & dawn */
+ MM_CAMCORDER_SCENE_MODE_FALL_COLOR, /**< Fall */
+ MM_CAMCORDER_SCENE_MODE_NIGHT_SCENE, /**< Night scene */
+ MM_CAMCORDER_SCENE_MODE_FIREWORK, /**< Firework */
+ MM_CAMCORDER_SCENE_MODE_TEXT, /**< Text */
+ MM_CAMCORDER_SCENE_MODE_SHOW_WINDOW, /**< Show window */
+ MM_CAMCORDER_SCENE_MODE_CANDLE_LIGHT, /**< Candle light */
+ MM_CAMCORDER_SCENE_MODE_BACKLIGHT, /**< Backlight */
+};
+
+
+/**
+ * An enumeration for focusing .
+ */
+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_MANUAL, /**< Manual focus mode*/
+ MM_CAMCORDER_FOCUS_MODE_TOUCH_AUTO, /**< Touch Autofocus mode*/
+ MM_CAMCORDER_FOCUS_MODE_CONTINUOUS, /**< Continuous Autofocus mode*/
+};
+
+
+/**
+ * An enumeration for auto focus scan range (af scan range)
+ */
+enum MMCamcorderAutoFocusType {
+ MM_CAMCORDER_AUTO_FOCUS_NONE = 0, /**< Scan autofocus is not set */
+ MM_CAMCORDER_AUTO_FOCUS_NORMAL, /**< Scan autofocus normally*/
+ MM_CAMCORDER_AUTO_FOCUS_MACRO, /**< Scan autofocus in macro mode(close distance)*/
+ MM_CAMCORDER_AUTO_FOCUS_FULL, /**< Scan autofocus in full mode(all range scan, limited by dev spec)*/
+};
+
+
+/**
+ * An enumeration for focus state.
+ * When 'MM_MESSAGE_CAMCORDER_FOCUS_CHANGED' is delievered through 'MMMessageCallback',
+ * this enumeration will be set to 'code' of MMMessageParamType.
+ */
+enum MMCamcorderFocusStateType {
+ MM_CAMCORDER_FOCUS_STATE_RELEASED = 0, /**< Focus released.*/
+ MM_CAMCORDER_FOCUS_STATE_ONGOING, /**< Focus in pregress*/
+ MM_CAMCORDER_FOCUS_STATE_FOCUSED, /**< Focus success*/
+ MM_CAMCORDER_FOCUS_STATE_FAILED, /**< Focus failed*/
+};
+
+
+/**
+ * An enumeration for ISO.
+ */
+enum MMCamcorderISOType {
+ MM_CAMCORDER_ISO_AUTO = 0, /**< ISO auto mode*/
+ MM_CAMCORDER_ISO_50, /**< ISO 50*/
+ MM_CAMCORDER_ISO_100, /**< ISO 100*/
+ MM_CAMCORDER_ISO_200, /**< ISO 200*/
+ MM_CAMCORDER_ISO_400, /**< ISO 400*/
+ MM_CAMCORDER_ISO_800, /**< ISO 800*/
+ MM_CAMCORDER_ISO_1600, /**< ISO 1600*/
+ MM_CAMCORDER_ISO_3200, /**< ISO 3200*/
+ MM_CAMCORDER_ISO_6400, /**< ISO 6400*/
+ MM_CAMCORDER_ISO_12800, /**< ISO 12800*/
+};
+
+/**
+ * An enumeration for Automatic exposure.
+ */
+enum MMCamcorderAutoExposureType {
+ MM_CAMCORDER_AUTO_EXPOSURE_OFF = 0, /**< AE off*/
+ MM_CAMCORDER_AUTO_EXPOSURE_ALL, /**< AE on, XXX mode*/
+ MM_CAMCORDER_AUTO_EXPOSURE_CENTER_1, /**< AE on, XXX mode*/
+ MM_CAMCORDER_AUTO_EXPOSURE_CENTER_2, /**< AE on, XXX mode*/
+ MM_CAMCORDER_AUTO_EXPOSURE_CENTER_3, /**< AE on, XXX mode*/
+ MM_CAMCORDER_AUTO_EXPOSURE_SPOT_1, /**< AE on, XXX mode*/
+ MM_CAMCORDER_AUTO_EXPOSURE_SPOT_2, /**< AE on, XXX mode*/
+ MM_CAMCORDER_AUTO_EXPOSURE_CUSTOM_1, /**< AE on, XXX mode*/
+ MM_CAMCORDER_AUTO_EXPOSURE_CUSTOM_2, /**< AE on, XXX mode*/
+};
+
+
+/**
+ * An enumeration for WDR mode .
+ */
+enum MMCamcorderWDRMode {
+ MM_CAMCORDER_WDR_OFF = 0, /**< WDR OFF*/
+ MM_CAMCORDER_WDR_ON, /**< WDR ON*/
+ MM_CAMCORDER_WDR_AUTO, /**< WDR AUTO*/
+};
+
+
+/**
+ * An enumeration for Anti-handshake mode .
+ */
+enum MMCamcorderAHSMode {
+ MM_CAMCORDER_AHS_OFF = 0, /**< AHS OFF*/
+ MM_CAMCORDER_AHS_ON, /**< AHS ON*/
+ MM_CAMCORDER_AHS_AUTO, /**< AHS AUTO*/
+ MM_CAMCORDER_AHS_MOVIE, /**< AHS MOVIE*/
+};
+
+
+/**
+ * Geometry method for camcorder display.
+ */
+enum MMCamcorderGeometryMethod {
+ MM_CAMCORDER_LETTER_BOX = 0, /**< Letter box*/
+ MM_CAMCORDER_ORIGIN_SIZE, /**< Origin size*/
+ MM_CAMCORDER_FULL, /**< full-screen*/
+ MM_CAMCORDER_CROPPED_FULL, /**< Cropped full-screen*/
+ MM_CAMCORDER_CUSTOM_ROI, /**< Explicitely described destination ROI*/
+};
+
+
+/**
+ * An enumeration for orientation values of tag .
+ */
+enum MMCamcorderTagOrientation {
+ MM_CAMCORDER_TAG_ORT_NONE =0, /**< No Orientation.*/
+ MM_CAMCORDER_TAG_ORT_0R_VT_0C_VL, /**< The 0th row is at the visual top of the image, and the 0th column is the visual left-hand side.*/
+ MM_CAMCORDER_TAG_ORT_0R_VT_0C_VR, /**< The 0th row is at the visual top of the image, and the 0th column is the visual right-hand side.*/
+ MM_CAMCORDER_TAG_ORT_0R_VB_0C_VR, /**< The 0th row is at the visual bottom of the image, and the 0th column is the visual right-hand side.*/
+ MM_CAMCORDER_TAG_ORT_0R_VB_0C_VL, /**< The 0th row is at the visual bottom of the image, and the 0th column is the visual left-hand side.*/
+ MM_CAMCORDER_TAG_ORT_0R_VL_0C_VT, /**< The 0th row is the visual left-hand side of the image, and the 0th column is the visual top.*/
+ MM_CAMCORDER_TAG_ORT_0R_VR_0C_VT, /**< The 0th row is the visual right-hand side of the image, and the 0th column is the visual top.*/
+ MM_CAMCORDER_TAG_ORT_0R_VR_0C_VB, /**< The 0th row is the visual right-hand side of the image, and the 0th column is the visual bottom.*/
+ MM_CAMCORDER_TAG_ORT_0R_VL_0C_VB, /**< The 0th row is the visual left-hand side of the image, and the 0th column is the visual bottom.*/
+};
+
+
+/**
+ * An enumeration for Strobe mode.
+ */
+enum MMCamcorderStrobeMode {
+ MM_CAMCORDER_STROBE_MODE_OFF = 0, /**< Always off */
+ MM_CAMCORDER_STROBE_MODE_ON, /**< Always splashes */
+ MM_CAMCORDER_STROBE_MODE_AUTO, /**< Depending on intensity of light, strobe starts to flash. */
+ MM_CAMCORDER_STROBE_MODE_REDEYE_REDUCTION, /**< Red eye reduction. Multiple flash before capturing. */
+ MM_CAMCORDER_STROBE_MODE_SLOW_SYNC, /**< Slow sync. A type of curtain synchronization. */
+ MM_CAMCORDER_STROBE_MODE_FRONT_CURTAIN, /**< Front curtain. A type of curtain synchronization. */
+ MM_CAMCORDER_STROBE_MODE_REAR_CURTAIN, /**< Rear curtain. A type of curtain synchronization. */
+ MM_CAMCORDER_STROBE_MODE_PERMANENT, /**< keep turned on until turning off */
+};
+
+
+/**
+ * An enumeration for Strobe Control.
+ */
+enum MMCamcorderStrobeControl {
+ MM_CAMCORDER_STROBE_CONTROL_OFF = 0, /**< turn off the flash light */
+ MM_CAMCORDER_STROBE_CONTROL_ON, /**< turn on the flash light */
+ MM_CAMCORDER_STROBE_CONTROL_CHARGE, /**< charge the flash light */
+};
+
+
+/**
+ * An enumeration for Detection mode.
+ */
+enum MMCamcorderDetectMode {
+ MM_CAMCORDER_DETECT_MODE_OFF = 0, /**< turn detection off */
+ MM_CAMCORDER_DETECT_MODE_ON, /**< turn detection on */
+};
+
+
+/**********************************
+* Attribute info *
+**********************************/
+/**
+ * An enumeration for attribute values types.
+ */
+typedef enum{
+ MM_CAM_ATTRS_TYPE_INVALID = -1, /**< Type is invalid */
+ MM_CAM_ATTRS_TYPE_INT, /**< Integer type attribute */
+ MM_CAM_ATTRS_TYPE_DOUBLE, /**< Double type attribute */
+ MM_CAM_ATTRS_TYPE_STRING, /**< UTF-8 String type attribute */
+ MM_CAM_ATTRS_TYPE_DATA, /**< Pointer type attribute */
+ MM_CAM_ATTRS_TYPE_ARRAY, /**< Array type attribute */
+ MM_CAM_ATTRS_TYPE_RANGE, /**< Range type attribute */
+}MMCamAttrsType;
+
+
+/**
+ * An enumeration for attribute validation type.
+ */
+typedef enum {
+ MM_CAM_ATTRS_VALID_TYPE_INVALID = -1, /**< Invalid validation type */
+ MM_CAM_ATTRS_VALID_TYPE_NONE, /**< Do not check validity */
+ MM_CAM_ATTRS_VALID_TYPE_INT_ARRAY, /**< validity checking type of integer array */
+ MM_CAM_ATTRS_VALID_TYPE_INT_RANGE, /**< validity checking type of integer range */
+ MM_CAM_ATTRS_VALID_TYPE_DOUBLE_ARRAY, /**< validity checking type of double array */
+ MM_CAM_ATTRS_VALID_TYPE_DOUBLE_RANGE, /**< validity checking type of double range */
+} MMCamAttrsValidType;
+
+
+/**
+ * An enumeration for attribute access flag.
+ */
+typedef enum {
+ MM_CAM_ATTRS_FLAG_DISABLED = 0, /**< None flag is set. This means the attribute is not allowed to use. */
+ MM_CAM_ATTRS_FLAG_READABLE = 1 << 0, /**< Readable */
+ MM_CAM_ATTRS_FLAG_WRITABLE = 1 << 1, /**< Writable */
+ MM_CAM_ATTRS_FLAG_MODIFIED = 1 << 2, /**< Modified */
+ MM_CAM_ATTRS_FLAG_RW = MM_CAM_ATTRS_FLAG_READABLE | MM_CAM_ATTRS_FLAG_WRITABLE, /**< Readable and Writable */
+} MMCamAttrsFlag;
+
+
+/*=======================================================================================
+| STRUCTURE DEFINITIONS |
+========================================================================================*/
+/**
+ * A structure for attribute information
+ */
+typedef struct {
+ MMCamAttrsType type;
+ MMCamAttrsFlag flag;
+ MMCamAttrsValidType validity_type;
+
+ /**
+ * A union that describes validity of the attribute.
+ * Only when type is 'MM_CAM_ATTRS_TYPE_INT' or 'MM_CAM_ATTRS_TYPE_DOUBLE',
+ * the attribute can have validity.
+ */
+ union {
+ /**
+ * Validity structure for integer array.
+ */
+ struct {
+ int *array; /**< a pointer of array */
+ int count; /**< size of array */
+ int def; /**< default value. Real value not index of array */
+ } int_array;
+
+ /**
+ * Validity structure for integer range.
+ */
+ struct {
+ int min; /**< minimum range */
+ int max; /**< maximum range */
+ int def; /**< default value */
+ } int_range;
+
+ /**
+ * Validity structure for double array.
+ */
+ struct {
+ double *array; /**< a pointer of array */
+ int count; /**< size of array */
+ double def; /**< default value. Real value not index of array */
+ } double_array;
+
+ /**
+ * Validity structure for double range.
+ */
+ struct {
+ double min; /**< minimum range */
+ double max; /**< maximum range */
+ double def; /**< default value */
+ } double_range;
+ };
+} MMCamAttrsInfo;
+
+
+/* General Structure */
+/**
+ * Structure for capture data.
+ */
+typedef struct {
+ void *data; /**< pointer of captured image */
+ unsigned int length; /**< length of captured image (in byte)*/
+ MMPixelFormatType format; /**< image format */
+ int width; /**< width of captured image */
+ int height; /**< height of captured image */
+ int encoder_type; /**< encoder type */
+} MMCamcorderCaptureDataType;
+
+
+/**
+ * Structure for video stream data.
+ */
+typedef struct {
+ void *data; /**< pointer of captured stream */
+ unsigned int length; /**< length of stream buffer (in byte)*/
+ MMPixelFormatType format; /**< image format */
+ int width; /**< width of video buffer */
+ int height; /**< height of video buffer */
+ unsigned int timestamp; /**< timestamp of stream buffer (msec)*/
+} MMCamcorderVideoStreamDataType;
+
+
+/**
+ * Structure for audio stream data.
+ */
+typedef struct {
+ void *data; /**< pointer of captured stream */
+ unsigned int length; /**< length of stream buffer (in byte)*/
+ MMCamcorderAudioFormat format; /**< audio format */
+ int channel; /**< number of channel of the stream */
+ unsigned int timestamp; /**< timestamp of stream buffer (msec)*/
+ float volume_dB; /**< dB value of audio stream */
+} MMCamcorderAudioStreamDataType;
+
+
+/**
+ * Prerequisite information for mm_camcorder_create()
+ * The information to set prior to create.
+ */
+typedef struct {
+ enum MMVideoDeviceType videodev_type; /**< Video device type */
+ /* For future use */
+ int reserved[4]; /**< reserved fields */
+} MMCamPreset;
+
+
+/**
+ * Report structure of recording file
+ */
+typedef struct MMCamRecordingReport {
+ char *recording_filename; /**< File name of stored recording file. Please free after using. */
+}MMCamRecordingReport; /**< report structure definition of recording file */
+
+
+/*=======================================================================================
+| TYPE DEFINITIONS |
+========================================================================================*/
+/**
+ * Function definition for video stream callback.
+ * Be careful! In this function, you can't call functions that change the state of camcorder such as mm_camcorder_stop(),
+ * mm_camcorder_unrealize(), mm_camcorder_record(), mm_camcorder_commit(), and mm_camcorder_cancel(), etc.
+ * Please don't hang this function long. It may cause low performance of preview or occur timeout error from video source.
+ * Also, you're not allowed to call mm_camcorder_stop() even in other context, while you're hanging this function.
+ * I recommend to you releasing this function ASAP.
+ *
+ * @param[in] stream Reference pointer to video stream data
+ * @param[in] user_param User parameter which is received from user when callback function was set
+ * @return This function returns true on success, or false on failure.
+ * @remarks This function is issued in the context of gstreamer (video sink thread).
+ */
+typedef gboolean (*mm_camcorder_video_stream_callback)(MMCamcorderVideoStreamDataType *stream, void *user_param);
+
+
+/**
+ * Function definition for audio stream callback.
+ * Be careful! In this function, you can't call functions that change the state of camcorder such as mm_camcorder_stop(),
+ * mm_camcorder_unrealize(), mm_camcorder_record(), mm_camcorder_commit(), and mm_camcorder_cancel(), etc.
+ * Please don't hang this function long. It may cause low performance of camcorder or occur timeout error from audio source.
+ * I recommend to you releasing this function ASAP.
+ *
+ * @param[in] stream Reference pointer to audio stream data
+ * @param[in] user_param User parameter which is received from user when callback function was set
+ * @return This function returns true on success, or false on failure.
+ * @remarks
+ */
+typedef gboolean (*mm_camcorder_audio_stream_callback)(MMCamcorderAudioStreamDataType *stream, void *user_param);
+
+
+/**
+ * Function definition for video capture callback.
+ * Like '#mm_camcorder_video_stream_callback', you can't call mm_camcorder_stop() while you are hanging this function.
+ *
+ * @param[in] frame Reference pointer to captured data
+ * @param[in] thumbnail Reference pointer to thumbnail data
+ * @param[in] user_param User parameter which is received from user when callback function was set
+ * @return This function returns true on success, or false on failure.
+ * @remarks This function is issued in the context of gstreamer (video src thread).
+ */
+typedef gboolean (*mm_camcorder_video_capture_callback)(MMCamcorderCaptureDataType *frame, MMCamcorderCaptureDataType *thumbnail, void *user_param);
+
+
+/*=======================================================================================
+| GLOBAL FUNCTION PROTOTYPES |
+========================================================================================*/
+/**
+ * mm_camcorder_create:\n
+ * Create camcorder object. This is the function that an user who wants to use mm_camcorder calls first.
+ * This function creates handle structure and initialize mutex, attributes, gstreamer.
+ * When this function success, it will return a handle of newly created object.
+ * A user have to put the handle when he calls every function of mm_camcorder. \n
+ * Second argument of this function is the field to decribe pre-setting information of mm_camcorder such as which camera device it will use.
+ * Normally, MM_VIDEO_DEVICE_CAMERA0 is for Main camera(or Mega camera, Back camera),
+ * and MM_VIDEO_DEVICE_CAMERA1 is for VGA camera (or Front camera). If you want audio recording,
+ * please set MM_VIDEO_DEVICE_NONE. (No camera device is needed.)
+ *
+ * @param[out] camcorder A handle of camcorder.
+ * @param[in] info Information for camera device. Depending on this information,
+ * camcorder opens different camera devices.
+ * @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.
+ * @see mm_camcorder_destroy
+ * @pre None
+ * @post Next state of mm-camcorder will be MM_CAMCORDER_STATE_NULL
+ * @remarks You can create multiple handles on a context at the same time. However,
+ * camcorder cannot guarantee proper operation because of limitation of resources, such as
+ * camera device, audio device, and display device.
+ * @par example
+ * @code
+
+#include <mm_camcorder.h>
+
+gboolean initialize_camcorder()
+{
+ int err;
+ MMCamPreset cam_info;
+#if 1
+ cam_info.videodev_type = MM_VIDEO_DEVICE_CAMERA0;
+#else
+ // when you want to record audio only, enable this.
+ cam_info.videodev_type = MM_VIDEO_DEVICE_NONE;
+#endif
+
+ err = mm_camcorder_create(&hcam, &cam_info);
+
+ if (err != MM_ERROR_NONE) {
+ printf("Fail to call mm_camcorder_create = %x\n", err);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+ * @endcode
+ */
+int mm_camcorder_create(MMHandleType *camcorder, MMCamPreset *info);
+
+
+/**
+ * mm_camcorder_destroy:\n
+ * Destroy camcorder object. Release handle and all of the resources that were created in mm_camcorder_create().\n
+ * This is the finalizing function of mm_camcorder. If this function is not called or fails to call, the handle isn't released fully.
+ * This function releases attributes, mutexes, sessions, and handle itself. This function also removes all of remaining messages.
+ * So if your application should wait a certain message of mm_camcorder, please wait to call this function till getting the message.
+ *
+ *
+ * @param[in] camcorder A handle of camcorder.
+ * @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.
+ * @see mm_camcorder_create
+ * @pre Previous state of mm-camcorder should be MM_CAMCORDER_STATE_NULL
+ * @post Because the handle is not valid, you can't check the state.
+ * @remarks None
+ * @par example
+ * @code
+
+#include <mm_camcorder.h>
+
+gboolean destroy_camcorder()
+{
+ int err;
+
+ //Destroy camcorder handle
+ err = mm_camcorder_destroy(hcam);
+ if (err < 0) {
+ printf("Fail to call mm_camcorder_destroy = %x\n", err);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+ * @endcode
+ */
+int mm_camcorder_destroy(MMHandleType camcorder);
+
+
+/**
+ * mm_camcorder_realize:\n
+ * Allocate resources for camcorder and initialize it.
+ * This also creates streamer pipeline. So you have to set attributes that are pivotal to create
+ * the pipeline before calling this function. This function also takes a roll to manage confliction
+ * between different applications which use camcorder. For example, if you try to use camcorder when
+ * other application that is more important such as call application, this function will return
+ * 'MM_ERROR_POLICY_BLOCKED'. On the contrary, if your application that uses camcorder starts to launch
+ * while another application that uses speaker and has lower priority, your application will kick
+ * another application.
+ *
+ * @param[in] camcorder A handle of camcorder.
+ * @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.
+ * @see mm_camcorder_unrealize
+ * @pre Previous state of mm-camcorder should be MM_CAMCORDER_STATE_NULL
+ * @post Next state of mm-camcorder will be MM_CAMCORDER_STATE_READY
+ * @remarks None
+ * @par example
+ * @code
+
+#include <mm_camcorder.h>
+
+//For image capturing
+gboolean initialize_image_capture()
+{
+ int err;
+ MMCamPreset cam_info;
+ char *err_attr_name = NULL;
+ void * hdisplay = NULL;
+ int hsize = 0;
+
+ //Set video device as 'camera0' (main camera device)
+ cam_info.videodev_type = MM_VIDEO_DEVICE_CAMERA0;
+
+ err = mm_camcorder_create(&hcam, &cam_info);
+
+ if (err != MM_ERROR_NONE) {
+ printf("Fail to call mm_camcorder_create = %x\n", err);
+ return FALSE;
+ }
+
+ mm_camcorder_set_message_callback(hcam,(MMMessageCallback)msg_callback, (void*)hcam);
+ mm_camcorder_set_video_capture_callback(hcam,(mm_camcorder_video_capture_callback)camcordertest_video_capture_cb, (void*)hcam);
+
+ hdisplay = &ad.xid; //xid of xwindow. This value can be different depending on your environment.
+ hsize = sizeof(ad.xid); //size of xid structure.
+
+ // camcorder attribute setting
+ err = mm_camcorder_set_attributes((MMHandleType)hcam, &err_attr_name,
+ MMCAM_MODE, MM_CAMCORDER_MODE_IMAGE,
+ MMCAM_IMAGE_ENCODER, MM_IMAGE_CODEC_JPEG,
+ MMCAM_CAMERA_WIDTH, 640,
+ MMCAM_CAMERA_HEIGHT, 480,
+ MMCAM_CAMERA_FORMAT, MM_PIXEL_FORMAT_YUYV,
+ MMCAM_CAMERA_FPS, 30,
+ MMCAM_DISPLAY_ROTATION, MM_DISPLAY_ROTATION_270,
+ MMCAM_DISPLAY_HANDLE, (void*) hdisplay, hsize,
+ MMCAM_CAPTURE_FORMAT, MM_PIXEL_FORMAT_ENCODED,
+ MMCAM_CAPTURE_WIDTH, 640,
+ MMCAM_CAPTURE_HEIGHT, 480,
+ NULL);
+
+ if (err < 0) {
+ printf("Set attrs fail. (%s:%x)\n", err_attr_name, err);
+ if (err_attr_name) {
+ free(err_attr_name);
+ err_attr_name = NULL;
+ return FALSE;
+ }
+ }
+
+ err = mm_camcorder_realize(hcam);
+ if (err < 0) {
+ printf("Fail to call mm_camcorder_realize = %x\n", err);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+//For A/V capturing
+gboolean initialize_video_capture()
+{
+ int err;
+ MMCamPreset cam_info;
+ char *err_attr_name = NULL;
+ void * hdisplay = NULL;
+ int hsize = 0;
+
+ //Set video device as 'camera0' (main camera device)
+ cam_info.videodev_type = MM_VIDEO_DEVICE_CAMERA0;
+
+ err = mm_camcorder_create(&hcam, &cam_info);
+
+ if (err != MM_ERROR_NONE) {
+ printf("Fail to call mm_camcorder_create = %x\n", err);
+ return FALSE;
+ }
+
+ mm_camcorder_set_message_callback(hcam,(MMMessageCallback)msg_callback, hcam);
+
+ hdisplay = &ad.xid; //xid of xwindow. This value can be different depending on your environment.
+ hsize = sizeof(ad.xid); //size of xid structure.
+
+ // camcorder attribute setting
+ err = mm_camcorder_set_attributes((MMHandleType)hcam, &err_attr_name,
+ MMCAM_MODE, MM_CAMCORDER_MODE_VIDEO,
+ MMCAM_AUDIO_DEVICE, MM_AUDIO_DEVICE_MIC,
+ MMCAM_AUDIO_ENCODER, MM_AUDIO_CODEC_AAC,
+ MMCAM_VIDEO_ENCODER, MM_VIDEO_CODEC_MPEG4,
+ MMCAM_FILE_FORMAT, MM_FILE_FORMAT_3GP,
+ MMCAM_CAMERA_WIDTH, 1280,
+ MMCAM_CAMERA_HEIGHT, 720,
+ MMCAM_CAMERA_FORMAT, MM_PIXEL_FORMAT_NV12,
+ MMCAM_CAMERA_FPS, 30,
+ MMCAM_AUDIO_SAMPLERATE, 44100,
+ MMCAM_AUDIO_FORMAT, MM_CAMCORDER_AUDIO_FORMAT_PCM_S16_LE,
+ MMCAM_AUDIO_CHANNEL, 2,
+ MMCAM_DISPLAY_ROTATION, MM_DISPLAY_ROTATION_270,
+ MMCAM_DISPLAY_HANDLE, (void*) hdisplay, hsize,
+ MMCAM_TARGET_FILENAME, TARGET_FILENAME, strlen(TARGET_FILENAME),
+ NULL);
+
+ if (err < 0) {
+ printf("Set attrs fail. (%s:%x)\n", err_attr_name, err);
+ if (err_attr_name) {
+ free(err_attr_name);
+ err_attr_name = NULL;
+ return FALSE;
+ }
+ }
+
+ err = mm_camcorder_realize(hcam);
+ if (err < 0) {
+ printf("Fail to call mm_camcorder_realize = %x\n", err);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+//For audio(only) capturing
+gboolean initialize_audio_capture()
+{
+ int err;
+ MMCamPreset cam_info;
+ char *err_attr_name = NULL;
+ void * hdisplay = NULL;
+ int hsize = 0;
+
+ //Set no video device, because audio recording doesn't need video input.
+ cam_info.videodev_type = MM_VIDEO_DEVICE_NONE;
+
+ err = mm_camcorder_create(&hcam, &cam_info);
+
+ if (err != MM_ERROR_NONE) {
+ printf("Fail to call mm_camcorder_create = %x\n", err);
+ return FALSE;
+ }
+
+ mm_camcorder_set_message_callback(hcam,(MMMessageCallback)msg_callback, (void*)hcam);
+
+ hdisplay = &ad.xid; //xid of xwindow. This value can be different depending on your environment.
+ hsize = sizeof(ad.xid); //size of xid structure.
+
+ // camcorder attribute setting
+ err = mm_camcorder_set_attributes((MMHandleType)hcam, &err_attr_name,
+ MMCAM_MODE, MM_CAMCORDER_MODE_AUDIO,
+ MMCAM_AUDIO_DEVICE, MM_AUDIO_DEVICE_MIC,
+ MMCAM_AUDIO_ENCODER, MM_AUDIO_CODEC_AAC,
+ MMCAM_FILE_FORMAT, MM_FILE_FORMAT_3GP,
+ MMCAM_AUDIO_SAMPLERATE, 44100,
+ MMCAM_AUDIO_FORMAT, MM_CAMCORDER_AUDIO_FORMAT_PCM_S16_LE,
+ MMCAM_AUDIO_CHANNEL, 2,
+ MMCAM_TARGET_FILENAME, TARGET_FILENAME, strlen(TARGET_FILENAME),
+ MMCAM_TARGET_TIME_LIMIT, 360000,
+ NULL);
+
+ if (err < 0) {
+ printf("Set attrs fail. (%s:%x)\n", err_attr_name, err);
+ if (err_attr_name) {
+ free(err_attr_name);
+ err_attr_name = NULL;
+ return FALSE;
+ }
+ }
+
+ err = mm_camcorder_realize(hcam);
+ if (err < 0) {
+ printf("Fail to call mm_camcorder_realize = %x\n", err);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+ * @endcode
+ */
+int mm_camcorder_realize(MMHandleType camcorder);
+
+
+/**
+ * mm_camcorder_unrealize:\n
+ * Uninitialize camcoder resources and free allocated memory.
+ * Most important resource that is released here is gstreamer pipeline of mm_camcorder.
+ * Because most of resources, such as camera device, video display device, and audio I/O device, are operating on the gstreamer pipeline,
+ * this function should be called to release its resources.
+ * Moreover, mm_camcorder is controlled by audio session manager. If an user doesn't call this function when he want to release mm_camcorder,
+ * other multimedia frameworks may face session problem. For more detail information, please refer mm_session module.
+ *
+ * @param[in] camcorder A handle of camcorder.
+ * @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.
+ * @see mm_camcorder_realize
+ * @pre Previous state of mm-camcorder should be MM_CAMCORDER_STATE_READY
+ * @post Next state of mm-camcorder will be MM_CAMCORDER_STATE_NULL
+ * @remarks None
+ * @par example
+ * @code
+
+#include <mm_camcorder.h>
+
+gboolean unrealize_camcorder()
+{
+ int err;
+
+ //Release all resources of camcorder handle
+ err = mm_camcorder_unrealize(hcam);
+ if (err < 0) {
+ printf("Fail to call mm_camcorder_unrealize = %x\n", err);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+ * @endcode
+ */
+int mm_camcorder_unrealize(MMHandleType camcorder);
+
+
+/**
+ * mm_camcorder_start:\n
+ * Start previewing. (Image/Video mode)
+ * 'mm_camcorder_video_stream_callback' is activated after calling this function.
+ *
+ * @param[in] camcorder A handle of camcorder.
+ * @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.
+ * @see mm_camcorder_stop
+ * @pre Previous state of mm-camcorder should be MM_CAMCORDER_STATE_READY
+ * @post Next state of mm-camcorder will be MM_CAMCORDER_STATE_PREPARE
+ * @remarks None
+ * @par example
+ * @code
+
+#include <mm_camcorder.h>
+
+//For image capturing
+gboolean initialize_image_capture()
+{
+ int err;
+ MMCamPreset cam_info;
+ char *err_attr_name = NULL;
+ void * hdisplay = NULL;
+ int hsize = 0;
+
+ //Set video device as 'camera0' (main camera device)
+ cam_info.videodev_type = MM_VIDEO_DEVICE_CAMERA0;
+
+ err = mm_camcorder_create(&hcam, &cam_info);
+
+ if (err != MM_ERROR_NONE) {
+ printf("Fail to call mm_camcorder_create = %x\n", err);
+ return FALSE;
+ }
+
+ mm_camcorder_set_message_callback(hcam,(MMMessageCallback)msg_callback, (void*)hcam);
+ mm_camcorder_set_video_capture_callback(hcam,(mm_camcorder_video_capture_callback)camcordertest_video_capture_cb, (void*)hcam);
+
+ hdisplay = &ad.xid; //xid of xwindow. This value can be different depending on your environment.
+ hsize = sizeof(ad.xid); //size of xid structure.
+
+ // camcorder attribute setting
+ err = mm_camcorder_set_attributes((MMHandleType)hcam, &err_attr_name,
+ MMCAM_MODE, MM_CAMCORDER_MODE_IMAGE,
+ MMCAM_IMAGE_ENCODER, MM_IMAGE_CODEC_JPEG,
+ MMCAM_CAMERA_WIDTH, 640,
+ MMCAM_CAMERA_HEIGHT, 480,
+ MMCAM_CAMERA_FORMAT, MM_PIXEL_FORMAT_YUYV,
+ MMCAM_CAMERA_FPS, 30,
+ MMCAM_DISPLAY_ROTATION, MM_DISPLAY_ROTATION_270,
+ MMCAM_DISPLAY_HANDLE, (void*) hdisplay, hsize,
+ MMCAM_CAPTURE_FORMAT, MM_PIXEL_FORMAT_ENCODED,
+ MMCAM_CAPTURE_WIDTH, 640,
+ MMCAM_CAPTURE_HEIGHT, 480,
+ NULL);
+
+ if (err < 0) {
+ printf("Set attrs fail. (%s:%x)\n", err_attr_name, err);
+ if (err_attr_name) {
+ free(err_attr_name);
+ err_attr_name = NULL;
+ return FALSE;
+ }
+ }
+
+ err = mm_camcorder_realize(hcam);
+ if (err < 0) {
+ printf("Fail to call mm_camcorder_realize = %x\n", err);
+ return FALSE;
+ }
+
+ // start camcorder
+ err = mm_camcorder_start(hcam);
+ if (err < 0) {
+ printf("Fail to call mm_camcorder_start = %x\n", err);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+//For A/V capturing
+gboolean initialize_video_capture()
+{
+ int err;
+ MMCamPreset cam_info;
+ char *err_attr_name = NULL;
+ void * hdisplay = NULL;
+ int hsize = 0;
+
+ //Set video device as 'camera0' (main camera device)
+ cam_info.videodev_type = MM_VIDEO_DEVICE_CAMERA0;
+
+ err = mm_camcorder_create(&hcam, &cam_info);
+
+ if (err != MM_ERROR_NONE) {
+ printf("Fail to call mm_camcorder_create = %x\n", err);
+ return FALSE;
+ }
+
+ mm_camcorder_set_message_callback(hcam,(MMMessageCallback)msg_callback, hcam);
+
+ hdisplay = &ad.xid; //xid of xwindow. This value can be different depending on your environment.
+ hsize = sizeof(ad.xid); //size of xid structure.
+
+ // camcorder attribute setting
+ err = mm_camcorder_set_attributes((MMHandleType)hcam, &err_attr_name,
+ MMCAM_MODE, MM_CAMCORDER_MODE_VIDEO,
+ MMCAM_AUDIO_DEVICE, MM_AUDIO_DEVICE_MIC,
+ MMCAM_AUDIO_ENCODER, MM_AUDIO_CODEC_AAC,
+ MMCAM_VIDEO_ENCODER, MM_VIDEO_CODEC_MPEG4,
+ MMCAM_FILE_FORMAT, MM_FILE_FORMAT_3GP,
+ MMCAM_CAMERA_WIDTH, 1280,
+ MMCAM_CAMERA_HEIGHT, 720,
+ MMCAM_CAMERA_FORMAT, MM_PIXEL_FORMAT_NV12,
+ MMCAM_CAMERA_FPS, 30,
+ MMCAM_AUDIO_SAMPLERATE, 44100,
+ MMCAM_AUDIO_FORMAT, MM_CAMCORDER_AUDIO_FORMAT_PCM_S16_LE,
+ MMCAM_AUDIO_CHANNEL, 2,
+ MMCAM_DISPLAY_ROTATION, MM_DISPLAY_ROTATION_270,
+ MMCAM_DISPLAY_HANDLE, (void*) hdisplay, hsize,
+ MMCAM_TARGET_FILENAME, TARGET_FILENAME, strlen(TARGET_FILENAME),
+ NULL);
+
+ if (err < 0) {
+ printf("Set attrs fail. (%s:%x)\n", err_attr_name, err);
+ if (err_attr_name) {
+ free(err_attr_name);
+ err_attr_name = NULL;
+ return FALSE;
+ }
+ }
+
+ err = mm_camcorder_realize(hcam);
+ if (err < 0) {
+ printf("Fail to call mm_camcorder_realize = %x\n", err);
+ return FALSE;
+ }
+
+ // start camcorder
+ err = mm_camcorder_start(hcam);
+ if (err < 0) {
+ printf("Fail to call mm_camcorder_start = %x\n", err);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+//For audio(only) capturing
+gboolean initialize_audio_capture()
+{
+ int err;
+ MMCamPreset cam_info;
+ char *err_attr_name = NULL;
+ void * hdisplay = NULL;
+ int hsize = 0;
+
+ //Set no video device, because audio recording doesn't need video input.
+ cam_info.videodev_type = MM_VIDEO_DEVICE_NONE;
+
+ err = mm_camcorder_create(&hcam, &cam_info);
+
+ if (err != MM_ERROR_NONE) {
+ printf("Fail to call mm_camcorder_create = %x\n", err);
+ return FALSE;
+ }
+
+ mm_camcorder_set_message_callback(hcam,(MMMessageCallback)msg_callback, (void*)hcam);
+
+ hdisplay = &ad.xid; //xid of xwindow. This value can be different depending on your environment.
+ hsize = sizeof(ad.xid); //size of xid structure.
+
+ // camcorder attribute setting
+ err = mm_camcorder_set_attributes((MMHandleType)hcam, &err_attr_name,
+ MMCAM_MODE, MM_CAMCORDER_MODE_AUDIO,
+ MMCAM_AUDIO_DEVICE, MM_AUDIO_DEVICE_MIC,
+ MMCAM_AUDIO_ENCODER, MM_AUDIO_CODEC_AAC,
+ MMCAM_FILE_FORMAT, MM_FILE_FORMAT_3GP,
+ MMCAM_AUDIO_SAMPLERATE, 44100,
+ MMCAM_AUDIO_FORMAT, MM_CAMCORDER_AUDIO_FORMAT_PCM_S16_LE,
+ MMCAM_AUDIO_CHANNEL, 2,
+ MMCAM_TARGET_FILENAME, TARGET_FILENAME, strlen(TARGET_FILENAME),
+ MMCAM_TARGET_TIME_LIMIT, 360000,
+ NULL);
+
+ if (err < 0) {
+ printf("Set attrs fail. (%s:%x)\n", err_attr_name, err);
+ if (err_attr_name) {
+ free(err_attr_name);
+ err_attr_name = NULL;
+ return FALSE;
+ }
+ }
+
+ err = mm_camcorder_realize(hcam);
+ if (err < 0) {
+ printf("Fail to call mm_camcorder_realize = %x\n", err);
+ return FALSE;
+ }
+
+ // start camcorder
+ err = mm_camcorder_start(hcam);
+ if (err < 0) {
+ printf("Fail to call mm_camcorder_start = %x\n", err);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+ * @endcode
+ */
+int mm_camcorder_start(MMHandleType camcorder);
+
+
+/**
+ * mm_camcorder_stop:\n
+ * Stop previewing. (Image/Video mode)
+ * This function will change the status of pipeline. If an application doesn't return callbacks
+ * of camcorder, this function can be locked. For example, if your application still
+ * holds '#mm_camcorder_video_capture_callback' or '#mm_camcorder_video_stream_callback',
+ * this function could be hung. So users have to return every callback before calling this function.
+ *
+ * @param[in] camcorder A handle of camcorder.
+ * @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.
+ * @see mm_camcorder_start
+ * @pre Previous state of mm-camcorder should be MM_CAMCORDER_STATE_PREPARE
+ * @post Next state of mm-camcorder will be MM_CAMCORDER_STATE_READY
+ * @remarks None
+ * @par example
+ * @code
+
+#include <mm_camcorder.h>
+
+gboolean stop_camcorder()
+{
+ int err;
+
+ //Stop preview
+ err = mm_camcorder_stop(hcam);
+ if (err < 0) {
+ printf("Fail to call mm_camcorder_stop = %x\n", err);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+ * @endcode
+ */
+int mm_camcorder_stop(MMHandleType camcorder);
+
+
+/**
+ * mm_camcorder_capture_start:\n
+ * Start capturing of still images. (Image mode only)
+ * Captured image will be delievered through 'mm_camcorder_video_capture_callback'.
+ * So basically, the operation is working asynchronously. \n
+ * When a user call this function, MSL will stop to retrieving preview from camera device.
+ * Then set capture resolution, pixel format, and encoding type to camera driver. After resuming,
+ * camera can get still image. A user will be notified by
+ * 'MM_MESSAGE_CAMCORDER_CAPTURED' message when capturing succeed. When a user sets
+ * multishot (by setting multiple number to MMCAM_CAPTURE_COUNT), the message
+ * will be called multiple time. You can get the number of image from 'code' of
+ * 'MMMessageParamType'.
+ *
+ * @param[in] camcorder A handle of camcorder.
+ * @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.
+ * @see mm_camcorder_capture_stop
+ * @pre Previous state of mm-camcorder should be MM_CAMCORDER_STATE_PREPARE
+ * @post Next state of mm-camcorder will be MM_CAMCORDER_STATE_CAPTURING
+ * @remarks To call this function, preview should be started successfully.\n
+ * This function is a pair of mm_camcorder_capture_stop().
+ * So user should call mm_camcorder_capture_stop() after getting captured image.
+ * @par example
+ * @code
+
+#include <mm_camcorder.h>
+
+gboolean capturing_picture()
+{
+ int err;
+
+ err = mm_camcorder_capture_start(hcam);
+ if (err < 0)
+ {
+ printf("Fail to call mm_camcorder_capture_start = %x\n", err);
+ return FALSE;
+ }
+
+ //mm_camcorder_capture_stop should be called after getting
+ //MM_MESSAGE_CAMCORDER_CAPTURED message.
+
+ return TRUE;
+}
+
+
+ * @endcode
+ */
+int mm_camcorder_capture_start(MMHandleType camcorder);
+
+
+/**
+ * mm_camcorder_capture_stop:\n
+ * Stop capturing of still images. (Image mode only)
+ * This function notifies the end of capturing and launch preview again.
+ * Just as mm_camcorder_capture_start(), this funciton stops still image stream and set preview information such as
+ * resolution, pixel format, and framerate to camera driver. Then it command to start preview.
+ * If you don't call this, preview will not be displayed even though capturing was finished.
+ *
+ * @param[in] camcorder A handle of camcorder.
+ * @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.
+ * @see mm_camcorder_capture_start
+ * @pre Previous state of mm-camcorder should be MM_CAMCORDER_STATE_CAPTURING
+ * @post Next state of mm-camcorder will be MM_CAMCORDER_STATE_PREPARE
+ * @remarks To call this function, a user has to call mm_camcorder_capture_start() first.\n
+ * This is not a function to stop multishot in the middle of operation. For that,
+ * please use '#MMCAM_CAPTURE_BREAK_CONTINUOUS_SHOT' instead.
+ * @par example
+ * @code
+
+#include <mm_camcorder.h>
+
+gboolean capturing_picture_stop()
+{
+ int err;
+
+ err = mm_camcorder_capture_stop(hcam);
+ if (err < 0) {
+ printf("Fail to call mm_camcorder_capture_stop = %x\n", err);
+ return FALSE;
+ }
+
+ //After calling upper function, preview will start.
+
+ return TRUE;
+}
+
+ * @endcode
+ */
+int mm_camcorder_capture_stop(MMHandleType camcorder);
+
+
+/**
+ * mm_camcorder_record:\n
+ * Start recording. (Audio/Video mode only)
+ * Camcorder starts to write a file when you call this function. You can specify the name of file
+ * using '#MMCAM_TARGET_FILENAME'. Beware, if you fail to call mm_camcorder_commit() or mm_camcorder_cancel(),
+ * the recorded file is still on the storage.
+ *
+ * @param[in] camcorder A handle of camcorder.
+ * @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.
+ * @see mm_camcorder_pause
+ * @pre Previous state of mm-camcorder should be MM_CAMCORDER_STATE_PREPARE
+ * @post Next state of mm-camcorder will be MM_CAMCORDER_STATE_RECORDING
+ * @remarks None
+ * @par example
+ * @code
+
+#include <mm_camcorder.h>
+
+gboolean record_and_cancel_video_file()
+{
+ int err;
+
+ // Start recording
+ err = mm_camcorder_record(hcam);
+ if (err < 0) {
+ printf("Fail to call mm_camcorder_record = %x\n", err);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+ * @endcode
+ */
+int mm_camcorder_record(MMHandleType camcorder);
+
+
+/**
+ * mm_camcorder_pause:\n
+ * Pause A/V recording or Audio recording. (Audio/Video mode only)
+ * On video recording, you can see preview while on pausing. So mm_camcorder cuts video stream path to encoder and keep the flow to preview.
+ * If you call mm_camcorder_commit() while on pausing, the recorded file only has Audio and Video stream which were generated before pause().
+ *
+ * @param[in] camcorder A handle of camcorder.
+ * @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.
+ * @see mm_camcorder_record
+ * @pre Previous state of mm-camcorder should be MM_CAMCORDER_STATE_RECORDING
+ * @post Next state of mm-camcorder will be MM_CAMCORDER_STATE_PAUSED
+ * @remarks Even though this function is for pausing recording, small amount of buffers could be recorded after pause().
+ * Because the buffers which are existed in the queue were created before pause(), the buffers should be recorded.
+ * @par example
+ * @code
+
+#include <mm_camcorder.h>
+
+gboolean record_pause_and_resume_recording()
+{
+ int err;
+
+ // Start recording
+ err = mm_camcorder_record(hcam);
+ if (err < 0) {
+ printf("Fail to call mm_camcorder_record = %x\n", err);
+ return FALSE;
+ }
+
+ // Wait while recording...
+
+ // Pause
+ err = mm_camcorder_pause(hcam);
+ if (err < 0) {
+ printf("Fail to call mm_camcorder_pause = %x\n", err);
+ return FALSE;
+ }
+
+ // Pausing...
+
+ // Resume
+ err = mm_camcorder_record(hcam);
+ if (err < 0) {
+ printf("Fail to call mm_camcorder_record = %x\n", err);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+
+ * @endcode
+ */
+int mm_camcorder_pause(MMHandleType camcorder);
+
+
+/**
+ * mm_camcorder_commit:\n
+ * Stop recording and save results. (Audio/Video mode only)\n
+ * After starting recording, encoded data frame will be stored in the location specified in MMCAM_TARGET_FILENAME.
+ * Some encoder or muxer require a certain type of finalizing such as adding some information to header.
+ * This function takes that roll. So if you don't call this function after recording, the result file may not be playable.\n
+ * After committing successfully, camcorder resumes displaying preview (video recording case).
+ * Because this is the function for saving the recording result, the operation is available
+ * only when the mode of camcorder is MM_CAMCORDER_MODE_AUDIO or MM_CAMCORDER_MODE_VIDEO.
+ *
+ * @param[in] camcorder A handle of camcorder.
+ * @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.
+ * @see mm_camcorder_cancel
+ * @pre Previous state of mm-camcorder should be MM_CAMCORDER_STATE_RECORDING
+ * @post Next state of mm-camcorder will be MM_CAMCORDER_STATE_PREPARE
+ * @remarks This function can take a few second when recording time is long.
+ * and if there are only quite few input buffer from video src or audio src,
+ * committing could be failed.
+ * @par example
+ * @code
+
+#include <mm_camcorder.h>
+
+gboolean record_and_save_video_file()
+{
+ int err;
+
+ // Start recording
+ err = mm_camcorder_record(hcam);
+ if (err < 0) {
+ printf("Fail to call mm_camcorder_record = %x\n", err);
+ return FALSE;
+ }
+
+ // Wait while recording for test...
+ // In normal case, mm_camcorder_record() and mm_camcorder_commit() aren't called in the same function.
+
+ // Save file
+ err = mm_camcorder_commit(hcam);
+ if (err < 0) {
+ printf("Fail to call mm_camcorder_commit = %x\n", err);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+ * @endcode
+ */
+int mm_camcorder_commit(MMHandleType camcorder);
+
+
+/**
+ * mm_camcorder_cancel:\n
+ * Stop recording and discard the result. (Audio/Video mode only)
+ * When a user want to finish recording without saving the result file, this function can be used.
+ * Like mm_camcorder_commit(), this function also stops recording, release related resources(like codec) ,and goes back to preview status.
+ * However, instead of saving file, this function unlinks(delete) the result.\n
+ * Because this is the function for canceling recording, the operation is available
+ * only when mode is MM_CAMCORDER_MODE_AUDIO or MM_CAMCORDER_MODE_VIDEO.
+ *
+ * @param[in] camcorder A handle of camcorder.
+ * @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.
+ * @see mm_camcorder_commit
+ * @pre Previous state of mm-camcorder should be MM_CAMCORDER_STATE_RECORDING
+ * @post Next state of mm-camcorder will be MM_CAMCORDER_STATE_PREPARE
+ * @remarks None
+ * @par example
+ * @code
+
+#include <mm_camcorder.h>
+
+gboolean record_and_cancel_video_file()
+{
+ int err;
+
+ // Start recording
+ err = mm_camcorder_record(hcam);
+ if (err < 0) {
+ printf("Fail to call mm_camcorder_record = %x\n", err);
+ return FALSE;
+ }
+
+ // Wait while recording...
+
+ // Cancel recording
+ err = mm_camcorder_cancel(hcam);
+ if (err < 0) {
+ printf("Fail to call mm_camcorder_cancel = %x\n", err);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+ * @endcode
+ */
+int mm_camcorder_cancel(MMHandleType camcorder);
+
+
+/**
+ * mm_camcorder_set_message_callback:\n
+ * Set callback for receiving messages from camcorder. Through this callback function, camcorder
+ * sends various message including status changes, asynchronous error, capturing, and limitations.
+ * One thing you have to know is that message callback is working on the main loop of application.
+ * So until releasing the main loop, message callback will not be called.
+ *
+ * @param[in] camcorder A handle of camcorder.
+ * @param[in] callback Function pointer of callback function. Please refer 'MMMessageCallback'.
+ * @param[in] user_data User parameter for passing to callback function.
+ * @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.
+ * @see MMMessageCallback
+ * @pre None
+ * @post None
+ * @remarks registered 'callback' is called on main loop of the application. So until the main loop is released, 'callback' will not be called.
+ * @par example
+ * @code
+
+#include <mm_camcorder.h>
+
+gboolean setting_msg_callback()
+{
+ //set callback
+ mm_camcorder_set_message_callback(hcam,(MMMessageCallback)msg_callback, (void*)hcam);
+
+ return TRUE;
+}
+
+
+ * @endcode
+ */
+int mm_camcorder_set_message_callback(MMHandleType camcorder, MMMessageCallback callback, void *user_data);
+
+
+/**
+ * mm_camcorder_set_video_stream_callback:\n
+ * Set callback for user defined video stream callback function.
+ * Users can retrieve video frame using registered callback.
+ * The callback function holds the same buffer that will be drawed on the display device.
+ * So if an user change the buffer, it will be displayed on the device.
+ *
+ * @param[in] camcorder A handle of camcorder.
+ * @param[in] callback Function pointer of callback function.
+ * @param[in] user_data User parameter for passing to callback function.
+ * @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.
+ * @see mm_camcorder_video_stream_callback
+ * @pre None
+ * @post None
+ * @remarks registered 'callback' is called on internal thread of camcorder. Regardless of the status of main loop, this function will be called.
+ * @par example
+ * @code
+
+#include <mm_camcorder.h>
+
+gboolean setting_video_stream_callback()
+{
+ //set callback
+ mm_camcorder_set_video_stream_callback(hcam, (mm_camcorder_video_stream_callback)camcordertest_video_stream_cb, (void*)hcam);
+
+ return TRUE;
+}
+ * @endcode
+ */
+int mm_camcorder_set_video_stream_callback(MMHandleType camcorder, mm_camcorder_video_stream_callback callback, void *user_data);
+
+
+/**
+ * mm_camcorder_set_video_capture_callback:\n
+ * Set callback for user defined video capture callback function. (Image mode only)
+ * mm_camcorder deliever captured image through the callback.\n
+ * Normally, this function provides main captured image and thumnail image. But depending on the environment,
+ * thumnail would not be available. Information related with main captured image and thumnail image is also included
+ * in the argument of the callback function.
+ * For more detail information of callback, please refer 'mm_camcorder_video_capture_callback'.
+ *
+ * @param[in] camcorder A handle of camcorder.
+ * @param[in] callback Function pointer of callback function.
+ * @param[in] user_data User parameter for passing to callback function.
+ * @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.
+ * @see mm_camcorder_video_capture_callback
+ * @pre None
+ * @post None
+ * @remarks registered 'callback' is called on internal thread of camcorder. Regardless of the status of main loop, this function will be called.
+ * @par example
+ * @code
+
+#include <mm_camcorder.h>
+
+gboolean setting_capture_callback()
+{
+ //set callback
+ mm_camcorder_set_video_capture_callback(hcam,(mm_camcorder_video_capture_callback)camcordertest_video_capture_cb, (void*)hcam);
+
+ return TRUE;
+}
+ * @endcode
+ */
+int mm_camcorder_set_video_capture_callback(MMHandleType camcorder, mm_camcorder_video_capture_callback callback, void *user_data);
+
+
+/**
+ * mm_camcorder_set_audio_stream_callback:\n
+ * Set callback for user defined audio stream callback function.
+ * Users can retrieve audio data using registered callback.
+ * The callback function holds the same buffer that will be recorded.
+ * So if an user change the buffer, the result file will has the buffer.
+ *
+ * @param[in] camcorder A handle of camcorder.
+ * @param[in] callback Function pointer of callback function.
+ * @param[in] user_data User parameter for passing to callback function.
+ * @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.
+ * @see mm_camcorder_audio_stream_callback
+ * @pre None
+ * @post None
+ * @remarks registered 'callback' is called on internal thread of camcorder. Regardless of the status of main loop, this function will be called.
+ * @par example
+ * @code
+
+#include <mm_camcorder.h>
+
+gboolean setting_audio_stream_callback()
+{
+ //set callback
+ mm_camcorder_set_audio_stream_callback(hcam, (mm_camcorder_audio_stream_callback)camcordertest_audio_stream_cb, (void*)hcam);
+
+ return TRUE;
+}
+ * @endcode
+ */
+int mm_camcorder_set_audio_stream_callback(MMHandleType camcorder, mm_camcorder_audio_stream_callback callback, void *user_data);
+
+
+/**
+ * mm_camcorder_get_state:\n
+ * Get the current state of camcorder.
+ * mm_camcorder is working on the base of its state. An user should check the state of mm_camcorder before calling its functions.
+ * If the handle is avaiable, user can retrieve the value.
+ *
+ * @param[in] camcorder A handle of camcorder.
+ * @param[out] state On return, it contains current state of camcorder.
+ * @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.
+ * @see MMCamcorderStateType
+ * @pre None
+ * @post None
+ * @remarks None
+ * @par example
+ * @code
+
+#include <mm_camcorder.h>
+
+gboolean get_state_of_camcorder()
+{
+ MMCamcorderStateType state;
+
+ //Get state of camcorder
+ mm_camcorder_get_state(hcam, &state);
+ printf("Current status is %d\n", state);
+
+ return TRUE;
+}
+
+ * @endcode
+ */
+int mm_camcorder_get_state(MMHandleType camcorder, MMCamcorderStateType *state);
+
+
+/**
+ * mm_camcorder_get_attributes:\n
+ * Get attributes of camcorder with given attribute names. This function can get multiple attributes
+ * simultaneously. If one of attribute fails, this function will stop at the point.
+ * 'err_attr_name' let you know the name of the attribute.
+ *
+ * @param[in] camcorder Specifies the camcorder handle.
+ * @param[out] err_attr_name Specifies the name of attributes that made an error. If the function doesn't make an error, this will be null. @n
+ * Free this variable after using.
+ * @param[in] attribute_name attribute name that user want to get.
+ * @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 You can retrieve multiple attributes at the same time. @n
+ * This function must finish with 'NULL' argument. @n
+ * ex) mm_camcorder_get_attributes(....... , NULL);
+ * @see mm_camcorder_set_attributes
+ * @par example
+ * @code
+
+#include <mm_camcorder.h>
+
+gboolean getting_attribute()
+{
+ int err;
+ MMCamPreset cam_info;
+ char *err_attr_name = NULL;
+ void * hdisplay = NULL;
+ int hsize = 0;
+
+ hdisplay = &ad.xid; //xid of xwindow. This value can be different depending on your environment.
+ hsize = sizeof(ad.xid); //size of xid structure.
+
+ // camcorder attribute setting
+ err = mm_camcorder_get_attributes(hcamcorder, NULL, //The second is the argument for debugging. But you can skip this.
+ MMCAM_MODE, &mode, //You have to input a pointer instead of variable itself.
+ NULL); //mm_camcorder_set_attributes() should be finished with a NULL argument.
+
+ return TRUE;
+}
+
+ * @endcode
+ */
+int mm_camcorder_get_attributes(MMHandleType camcorder, char **err_attr_name, const char *attribute_name, ...) G_GNUC_NULL_TERMINATED;
+
+
+
+/**
+ * mm_camcorder_set_attributes:\n
+ * Set attributes of camcorder with given attribute names. This function can set multiple attributes
+ * simultaneously. If one of attribute fails, this function will stop at the point.
+ * 'err_attr_name' let you know the name of the attribute.
+ *
+ * @param[in] camcorder Specifies the camcorder handle.
+ * @param[out] err_attr_name Specifies the name of attributes that made an error. If the function doesn't make an error, this will be null. @n
+ * Free this variable after using.
+ * @param[in] attribute_name attribute name that user want to set.
+ * @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 You can put multiple attributes to camcorder at the same time. @n
+ * This function must finish with 'NULL' argument. @n
+ * ex) mm_camcorder_set_attributes(....... , NULL);
+ * @see mm_camcorder_get_attributes
+ * @par example
+ * @code
+
+#include <mm_camcorder.h>
+
+gboolean setting_attribute()
+{
+ int err;
+ MMCamPreset cam_info;
+ char *err_attr_name = NULL;
+ void * hdisplay = NULL;
+ int hsize = 0;
+
+ hdisplay = &ad.xid; //xid of xwindow. This value can be different depending on your environment.
+ hsize = sizeof(ad.xid); //size of xid structure.
+
+ // camcorder attribute setting
+ err = mm_camcorder_set_attributes((MMHandleType)hcam, &err_attr_name, //The second is the argument for debugging.
+ MMCAM_MODE, MM_CAMCORDER_MODE_IMAGE,
+ MMCAM_IMAGE_ENCODER, MM_IMAGE_CODEC_JPEG,
+ MMCAM_CAMERA_WIDTH, 640,
+ MMCAM_CAMERA_HEIGHT, 480,
+ MMCAM_CAMERA_FORMAT, MM_PIXEL_FORMAT_YUYV,
+ MMCAM_CAMERA_FPS, 30,
+ MMCAM_DISPLAY_ROTATION, MM_DISPLAY_ROTATION_270,
+ MMCAM_DISPLAY_HANDLE, (void*) hdisplay, hsize, //Beware some types require 'size' value, too. (STRING, DATA type attributes)
+ MMCAM_CAPTURE_FORMAT, MM_PIXEL_FORMAT_ENCODED,
+ MMCAM_CAPTURE_WIDTH, 640,
+ MMCAM_CAPTURE_HEIGHT, 480,
+ NULL); //mm_camcorder_set_attributes() should be finished with a NULL argument.
+
+ if (err < 0) {
+ printf("Set attrs fail. (%s:%x)\n", err_attr_name, err); //When the function failed, 'err_attr_name' has the name of attr that made the error.
+ if (err_attr_name) {
+ free(err_attr_name); //Please free 'err_attr_name', after using the argument.
+ err_attr_name = NULL;
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+ * @endcode
+ */
+int mm_camcorder_set_attributes(MMHandleType camcorder, char **err_attr_name, const char *attribute_name, ...) G_GNUC_NULL_TERMINATED;
+
+
+/**
+ * mm_camcorder_get_attribute_info:\n
+ * Get detail information of the attribute. To manager attributes, an user may want to know the exact character of the attribute,
+ * such as type, flag, and validity. This is the function to provide such information.
+ * 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] attribute_name attribute name that user want to get information.
+ * @param[out] 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 <mm_camcorder.h>
+
+gboolean getting_info_from_attribute()
+{
+ MMCamAttrsInfo info;
+ int err;
+
+ err = mm_camcorder_get_attribute_info(handle, MMCAM_CAPTURE_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_attribute_info(MMHandleType camcorder, const char *attribute_name, MMCamAttrsInfo *info);
+
+
+/**
+ * mm_camcorder_init_focusing:\n
+ * Initialize focusing. \n
+ * This function stops focusing action and adjust the camera lens to initial position.
+ * Some camera applciation requires to initialize its lens position after releasing half shutter. In that case,
+ * this should be a good choice. Comparing with mm_camcorder_stop_focusing, this function not only stops focusing,
+ * but also initialize the lens. Preview image might be out-focused after calling this function.
+ * @param[in] camcorder A handle of camcorder.
+ * @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 The status of camcorder should be MM_CAMCORDER_STATE_PREPARE, MM_CAMCORDER_STATE_RECORDING, or MM_CAMCORDER_STATE_PAUSED.
+ * @post None
+ * @remarks None
+ * @see mm_camcorder_start_focusing, mm_camcorder_stop_focusing
+ * @par example
+ * @code
+
+#include <mm_camcorder.h>
+
+gboolean start_autofocus()
+{
+ int err;
+ char * err_attr_name = NULL;
+
+ // Set focus mode to 'AUTO' and scan range to 'AF Normal'.
+ //You just need to set these values one time. After that, just call mm_camcorder_start_focusing().
+ err = mm_camcorder_set_attributes((MMHandleType)hcam, &err_attr_name,
+ MMCAM_CAMERA_FOCUS_MODE, MM_CAMCORDER_FOCUS_MODE_AUTO,
+ MMCAM_CAMERA_AF_SCAN_RANGE, MM_CAMCORDER_AUTO_FOCUS_NORMAL,
+ NULL);
+
+ if (err < 0) {
+ printf("Set attrs fail. (%s:%x)\n", err_attr_name, err);
+ if (err_attr_name) {
+ free(err_attr_name);
+ err_attr_name = NULL;
+ return FALSE;
+ }
+ }
+
+ mm_camcorder_init_focusing(hcam);
+ mm_camcorder_start_focusing(hcam);
+ printf("Waiting for adjusting focus\n");
+
+ // Waiting for 'MM_MESSAGE_CAMCORDER_FOCUS_CHANGED'
+
+ return TRUE;
+}
+
+ * @endcode
+ */
+int mm_camcorder_init_focusing(MMHandleType camcorder);
+
+
+/**
+ * mm_camcorder_start_focusing:\n
+ * Start focusing. \n
+ * This function command to start focusing opeartion. Because focusing operation depends on mechanic or electric module,
+ * it may take small amount of time. (For ex, 500ms ~ 3sec). \n
+ * This function works asynchronously. When an user call this function, it will return immediately.
+ * However, focusing operation will continue until it gets results.
+ * After finishing operation, you can get 'MM_MESSAGE_CAMCORDER_FOCUS_CHANGED' message.
+ * 'param.code' of the message structure describes the fucusing was success or not.
+ *
+ * @param[in] camcorder A handle of camcorder.
+ * @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 None
+ * @see mm_camcorder_init_focusing, mm_camcorder_stop_focusing
+ * @par example
+ * @code
+
+#include <mm_camcorder.h>
+
+gboolean start_autofocus()
+{
+ int err;
+ char * err_attr_name = NULL;
+
+ // Set focus mode to 'AUTO' and scan range to 'AF Normal'.
+ //You just need to set these values one time. After that, just call mm_camcorder_start_focusing().
+ err = mm_camcorder_set_attributes((MMHandleType)hcam, &err_attr_name,
+ MMCAM_CAMERA_FOCUS_MODE, MM_CAMCORDER_FOCUS_MODE_AUTO,
+ MMCAM_CAMERA_AF_SCAN_RANGE, MM_CAMCORDER_AUTO_FOCUS_NORMAL,
+ NULL);
+
+ if (err < 0) {
+ printf("Set attrs fail. (%s:%x)\n", err_attr_name, err);
+ if (err_attr_name) {
+ free(err_attr_name);
+ err_attr_name = NULL;
+ return FALSE;
+ }
+ }
+
+ mm_camcorder_init_focusing(hcam);
+ mm_camcorder_start_focusing(hcam);
+ printf("Waiting for adjusting focus\n");
+
+ // Waiting for 'MM_MESSAGE_CAMCORDER_FOCUS_CHANGED'
+
+ return TRUE;
+}
+
+ * @endcode
+ */
+int mm_camcorder_start_focusing(MMHandleType camcorder);
+
+
+/**
+ * mm_camcorder_stop_focusing:\n
+ * Stop focusing. This function halts focusing operation.\n
+ * This is the function to stop focusing in the middle of the operation. So if focusing is already finished or not started yet,
+ * this function will do nothing.
+ *
+ * @param[in] camcorder A handle of camcorder.
+ * @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.
+ * @see mm_camcorder_init_focusing, mm_camcorder_start_focusing
+ * @pre mm_camcorder_start_focusing() should be called before calling this function.
+ * @post None
+ * @remarks None
+ * @par example
+ * @code
+
+#include <mm_camcorder.h>
+
+gboolean stop_autofocus()
+{
+ int err;
+
+ //Stop focusing
+ mm_camcorder_stop_focusing(hcam);
+
+ return TRUE;
+}
+
+ * @endcode
+ */
+int mm_camcorder_stop_focusing(MMHandleType camcorder);
+
+/**
+ @}
+ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __MM_CAMCORDER_H__ */
diff --git a/src/include/mm_camcorder_attribute.h b/src/include/mm_camcorder_attribute.h
new file mode 100644
index 0000000..8a499e5
--- /dev/null
+++ b/src/include/mm_camcorder_attribute.h
@@ -0,0 +1,365 @@
+/*
+ * libmm-camcorder
+ *
+ * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: Jeongmo Yang <jm80.yang@samsung.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef __MM_CAMCORDER_ATTRIBUTE_H__
+#define __MM_CAMCORDER_ATTRIBUTE_H__
+
+/*=======================================================================================
+| INCLUDE FILES |
+========================================================================================*/
+#include <mm_types.h>
+#include <stdarg.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*=======================================================================================
+| GLOBAL DEFINITIONS AND DECLARATIONS FOR CAMCORDER |
+========================================================================================*/
+/* Disabled
+#define GET_AND_STORE_ATTRS_AFTER_SCENE_MODE
+*/
+
+/*=======================================================================================
+| MACRO DEFINITIONS |
+========================================================================================*/
+/**
+ * Caster of attributes handle
+ */
+#define MMF_CAMCORDER_ATTRS(h) (((mmf_camcorder_t *)(h))->attributes)
+
+/*=======================================================================================
+| ENUM DEFINITIONS |
+========================================================================================*/
+/**
+ * Enumerations for camcorder attribute ID.
+ */
+typedef enum
+{
+ MM_CAM_MODE, /* 0 */
+ MM_CAM_AUDIO_DEVICE,
+ MM_CAM_CAMERA_DEVICE,
+ MM_CAM_AUDIO_ENCODER,
+ MM_CAM_VIDEO_ENCODER,
+ MM_CAM_IMAGE_ENCODER,
+ MM_CAM_FILE_FORMAT,
+ MM_CAM_CAMERA_DEVICE_NAME,
+ MM_CAM_AUDIO_SAMPLERATE,
+ MM_CAM_AUDIO_FORMAT,
+ MM_CAM_AUDIO_CHANNEL, /* 10 */
+ MM_CAM_AUDIO_VOLUME,
+ MM_CAM_AUDIO_INPUT_ROUTE,
+ MM_CAM_FILTER_SCENE_MODE,
+ MM_CAM_FILTER_BRIGHTNESS,
+ MM_CAM_FILTER_CONTRAST,
+ MM_CAM_FILTER_WB,
+ MM_CAM_FILTER_COLOR_TONE,
+ MM_CAM_FILTER_SATURATION,
+ MM_CAM_FILTER_HUE,
+ MM_CAM_FILTER_SHARPNESS, /* 20 */
+ MM_CAM_CAMERA_FORMAT,
+ MM_CAM_CAMERA_SLOW_MOTION_FPS,
+ MM_CAM_CAMERA_FPS,
+ MM_CAM_CAMERA_WIDTH,
+ MM_CAM_CAMERA_HEIGHT,
+ MM_CAM_CAMERA_DIGITAL_ZOOM,
+ MM_CAM_CAMERA_OPTICAL_ZOOM,
+ MM_CAM_CAMERA_FOCUS_MODE,
+ MM_CAM_CAMERA_AF_SCAN_RANGE,
+ MM_CAM_CAMERA_EXPOSURE_MODE, /* 30 */
+ MM_CAM_CAMERA_EXPOSURE_VALUE,
+ MM_CAM_CAMERA_F_NUMBER,
+ MM_CAM_CAMERA_SHUTTER_SPEED,
+ MM_CAM_CAMERA_ISO,
+ MM_CAM_CAMERA_WDR,
+ MM_CAM_CAMERA_ANTI_HANDSHAKE,
+ MM_CAM_CAMERA_FPS_AUTO,
+ MM_CAM_CAMERA_HOLD_AF_AFTER_CAPTURING,
+ MM_CAM_CAMERA_DELAY_ATTR_SETTING,
+ MM_CAM_AUDIO_ENCODER_BITRATE, /* 40 */
+ MM_CAM_VIDEO_ENCODER_BITRATE,
+ MM_CAM_IMAGE_ENCODER_QUALITY,
+ MM_CAM_CAPTURE_FORMAT,
+ MM_CAM_CAPTURE_WIDTH,
+ MM_CAM_CAPTURE_HEIGHT,
+ MM_CAM_CAPTURE_COUNT,
+ MM_CAM_CAPTURE_INTERVAL,
+ MM_CAM_CAPTURE_BREAK_CONTINUOUS_SHOT,
+ MM_CAM_DISPLAY_HANDLE,
+ MM_CAM_DISPLAY_DEVICE, /* 50 */
+ MM_CAM_DISPLAY_SURFACE,
+ MM_CAM_DISPLAY_RECT_X,
+ MM_CAM_DISPLAY_RECT_Y,
+ MM_CAM_DISPLAY_RECT_WIDTH,
+ MM_CAM_DISPLAY_RECT_HEIGHT,
+ MM_CAM_DISPLAY_SOURCE_X,
+ MM_CAM_DISPLAY_SOURCE_Y,
+ MM_CAM_DISPLAY_SOURCE_WIDTH,
+ MM_CAM_DISPLAY_SOURCE_HEIGHT,
+ MM_CAM_DISPLAY_ROTATION, /* 60 */
+ MM_CAM_DISPLAY_VISIBLE,
+ MM_CAM_DISPLAY_SCALE,
+ MM_CAM_DISPLAY_GEOMETRY_METHOD,
+ MM_CAM_TARGET_FILENAME,
+ MM_CAM_TARGET_MAX_SIZE,
+ MM_CAM_TARGET_TIME_LIMIT,
+ MM_CAM_TAG_ENABLE,
+ MM_CAM_TAG_IMAGE_DESCRIPTION,
+ MM_CAM_TAG_ORIENTATION,
+ MM_CAM_TAG_SOFTWARE, /* 70 */
+ MM_CAM_TAG_LATITUDE,
+ MM_CAM_TAG_LONGITUDE,
+ MM_CAM_TAG_ALTITUDE,
+ MM_CAM_STROBE_CONTROL,
+ MM_CAM_STROBE_CAPABILITIES,
+ MM_CAM_STROBE_MODE,
+ MM_CAM_DETECT_MODE,
+ MM_CAM_DETECT_NUMBER,
+ MM_CAM_DETECT_FOCUS_SELECT,
+ MM_CAM_DETECT_SELECT_NUMBER, /* 80 */
+ MM_CAM_DETECT_STATUS,
+ MM_CAM_CAPTURE_ZERO_SYSTEMLAG,
+ MM_CAM_CAMERA_AF_TOUCH_X,
+ MM_CAM_CAMERA_AF_TOUCH_Y,
+ MM_CAM_CAMERA_AF_TOUCH_WIDTH,
+ MM_CAM_CAMERA_AF_TOUCH_HEIGHT,
+ MM_CAM_CAMERA_FOCAL_LENGTH,
+ MM_CAM_RECOMMEND_PREVIEW_FORMAT_FOR_CAPTURE,
+ MM_CAM_RECOMMEND_PREVIEW_FORMAT_FOR_RECORDING,
+ MM_CAM_CAPTURE_THUMBNAIL, /* 90 */
+ MM_CAM_TAG_GPS_ENABLE,
+ MM_CAM_TAG_GPS_TIME_STAMP,
+ MM_CAM_TAG_GPS_DATE_STAMP,
+ MM_CAM_TAG_GPS_PROCESSING_METHOD,
+ MM_CAM_CAMERA_ROTATION,
+ MM_CAM_ENABLE_CONVERTED_STREAM_CALLBACK,
+ MM_CAM_CAPTURED_SCREENNAIL,
+ MM_CAM_CAPTURE_SOUND_ENABLE,
+ MM_CAM_RECOMMEND_DISPLAY_ROTATION,
+ MM_CAM_CAMCORDER_ROTATION, /* 100 */
+ MM_CAM_NUM
+}MMCamcorderAttrsID;
+
+/*=======================================================================================
+| TYPE DEFINITIONS |
+========================================================================================*/
+typedef bool (*mmf_cam_commit_func_t)(MMHandleType handle, int attr_idx, const mmf_value_t *value);
+
+/*=======================================================================================
+| STRUCTURE DEFINITIONS |
+========================================================================================*/
+typedef struct {
+ MMCamcorderAttrsID attrid;
+ char *name;
+ int value_type;
+ int flags;
+ void* default_value;
+ MMCamAttrsValidType validity_type;
+ int validity_value1; /* can be int min, int *array, double *array, or cast to double min. */
+ int validity_value2; /* can be int max, int count, int count, or cast to double max. */
+ mmf_cam_commit_func_t attr_commit;
+} mm_cam_attr_construct_info;
+
+/*=======================================================================================
+| CONSTANT DEFINITIONS |
+========================================================================================*/
+
+/*=======================================================================================
+| STATIC VARIABLES |
+========================================================================================*/
+
+/*=======================================================================================
+| EXTERN GLOBAL VARIABLE |
+========================================================================================*/
+
+/*=======================================================================================
+| GLOBAL FUNCTION PROTOTYPES |
+========================================================================================*/
+/**
+ * This function allocates structure of attributes and sets initial values.
+ *
+ * @param[in] handle Handle of camcorder.
+ * @param[in] info Preset information of camcorder.
+ * @return This function returns allocated structure of attributes.
+ * @remarks
+ * @see _mmcamcorder_dealloc_attribute()
+ *
+ */
+MMHandleType _mmcamcorder_alloc_attribute(MMHandleType handle, MMCamPreset *info);
+
+/**
+ * This function release structure of attributes.
+ *
+ * @param[in] attrs Handle of camcorder attribute.
+ * @return void
+ * @remarks
+ * @see _mmcamcorder_alloc_attribute()
+ *
+ */
+void _mmcamcorder_dealloc_attribute(MMHandleType attrs);
+
+/**
+ * This is a meta function to get attributes of camcorder with given attribute names.
+ *
+ * @param[in] handle Handle of camcorder.
+ * @param[out] err_attr_name Specifies the name of attributes that made an error. If the function doesn't make an error, this will be null.
+ * @param[in] attribute_name attribute name that user want to get.
+ * @param[in] var_args Specifies variable arguments.
+ * @return This function returns MM_ERROR_NONE on Success, minus on Failure.
+ * @remarks You can retrieve multiple attributes at the same time. @n
+ * @see _mmcamcorder_set_attributes
+ */
+int _mmcamcorder_get_attributes(MMHandleType handle, char **err_attr_name, const char *attribute_name, va_list var_args);
+
+
+/**
+ * This is a meta function to set attributes of camcorder with given attribute names.
+ *
+ * @param[in] handle Handle of camcorder.
+ * @param[out] err_attr_name Specifies the name of attributes that made an error. If the function doesn't make an error, this will be null.
+ * @param[in] attribute_name attribute name that user want to set.
+ * @param[in] var_args Specifies variable arguments.
+ * @return This function returns MM_ERROR_NONE on Success, minus on Failure.
+ * @remarks You can put multiple attributes to camcorder at the same time. @n
+ * @see _mmcamcorder_get_attributes
+ */
+int _mmcamcorder_set_attributes(MMHandleType handle, char **err_attr_name, const char *attribute_name, va_list var_args);
+
+
+/**
+ * This is a meta function to get detail information of the attribute.
+ *
+ * @param[in] handle Handle of camcorder.
+ * @param[in] attr_name attribute name that user want to get information.
+ * @param[out] info a structure that holds information related with the attribute.
+ * @return This function returns MM_ERROR_NONE on Success, minus on Failure.
+ * @remarks If the function succeeds, 'info' holds detail information about the attribute, such as type, flag, validity_type, validity_values @n
+ * @see _mmcamcorder_get_attributes, _mmcamcorder_set_attributes
+ */
+int _mmcamcorder_get_attribute_info(MMHandleType handle, const char *attr_name, MMCamAttrsInfo *info);
+
+/*=======================================================================================
+| CAMCORDER INTERNAL LOCAL |
+========================================================================================*/
+/**
+ * A commit function to set camcorder attributes
+ * If the attribute needs actual setting, this function handles that activity.
+ * When application sets an attribute, setting function in MSL common calls this function.
+ * If this function fails, original value will not change.
+ *
+ * @param[in] attr_idx Attribute index of subcategory.
+ * @param[in] attr_name Attribute name.
+ * @param[in] value Handle of camcorder.
+ * @param[in] commit_param Allocation type of camcorder context.
+ * @return This function returns TRUE on success, or FALSE on failure
+ * @remarks
+ * @see
+ *
+ */
+bool _mmcamcorder_commit_camcorder_attrs(int attr_idx, const char *attr_name, const mmf_value_t *value, void *commit_param);
+
+/**
+ * A commit function to set videosource attribute
+ * If the attribute needs actual setting, this function handles that activity.
+ * When application sets an attribute, setting function in MSL common calls this function.
+ * If this function fails, original value will not change.
+ *
+ * @param[in] attr_idx Attribute index of subcategory.
+ * @param[in] attr_name Attribute name.
+ * @param[in] value Handle of camcorder.
+ * @param[in] commit_param Allocation type of camcorder context.
+ * @return This function returns TRUE on success, or FALSE on failure
+ * @remarks
+ * @see
+ *
+ */
+bool _mmcamcorder_commit_capture_width(MMHandleType handle, int attr_idx, const mmf_value_t *value);
+bool _mmcamcorder_commit_capture_height(MMHandleType handle, int attr_idx, const mmf_value_t *value);
+bool _mmcamcorder_commit_capture_break_cont_shot(MMHandleType handle, int attr_idx, const mmf_value_t *value);
+bool _mmcamcorder_commit_capture_count(MMHandleType handle, int attr_idx, const mmf_value_t *value);
+bool _mmcamcorder_commit_audio_volume(MMHandleType handle, int attr_idx, const mmf_value_t *value);
+bool _mmcamcorder_commit_audio_input_route(MMHandleType handle, int attr_idx, const mmf_value_t *value);
+bool _mmcamcorder_commit_camera_fps(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);
+bool _mmcamcorder_commit_camera_height(MMHandleType handle, int attr_idx, const mmf_value_t *value);
+bool _mmcamcorder_commit_camera_zoom(MMHandleType handle, int attr_idx, const mmf_value_t *value);
+bool _mmcamcorder_commit_camera_focus_mode(MMHandleType handle, int attr_idx, const mmf_value_t *value);
+bool _mmcamcorder_commit_camera_af_scan_range(MMHandleType handle, int attr_idx, const mmf_value_t *value);
+bool _mmcamcorder_commit_camera_af_touch_area(MMHandleType handle, int attr_idx, const mmf_value_t *value);
+bool _mmcamcorder_commit_camera_capture_mode(MMHandleType handle, int attr_idx, const mmf_value_t *value);
+bool _mmcamcorder_commit_camera_wdr(MMHandleType handle, int attr_idx, const mmf_value_t *value);
+bool _mmcamcorder_commit_camera_anti_handshake(MMHandleType handle, int attr_idx, const mmf_value_t *value);
+bool _mmcamcorder_commit_camera_hold_af_after_capturing(MMHandleType handle, int attr_idx, const mmf_value_t *value);
+bool _mmcamcorder_commit_camera_rotate(MMHandleType handle, int attr_idx, const mmf_value_t *value);
+bool _mmcamcorder_commit_image_encoder_quality(MMHandleType handle, int attr_idx, const mmf_value_t *value);
+bool _mmcamcorder_commit_target_filename(MMHandleType handle, int attr_idx, const mmf_value_t *value);
+bool _mmcamcorder_commit_filter(MMHandleType handle, int attr_idx, const mmf_value_t *value);
+bool _mmcamcorder_commit_filter_scene_mode(MMHandleType handle, int attr_idx, const mmf_value_t *value);
+bool _mmcamcorder_commit_filter_flip(MMHandleType handle, int attr_idx, const mmf_value_t *value);
+bool _mmcamcorder_commit_display_handle(MMHandleType handle, int attr_idx, const mmf_value_t *value);
+bool _mmcamcorder_commit_display_rotation(MMHandleType handle, int attr_idx, const mmf_value_t *value);
+bool _mmcamcorder_commit_display_visible(MMHandleType handle, int attr_idx, const mmf_value_t *value);
+bool _mmcamcorder_commit_display_geometry_method(MMHandleType handle, int attr_idx, const mmf_value_t *value);
+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_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_camcorder_rotate(MMHandleType handle, int attr_idx, const mmf_value_t *value);
+
+/**
+ * This function initialize effect setting.
+ *
+ * @param[in] handle Handle of camcorder.
+ * @return bool
+ * @remarks
+ * @see
+ *
+ */
+bool _mmcamcorder_set_attribute_to_camsensor(MMHandleType handle);
+
+/**
+ * This function removes writable flag from pre-defined attributes.
+ *
+ * @param[in] handle Handle of camcorder.
+ * @return void
+ * @remarks
+ * @see
+ *
+ */
+int _mmcamcorder_lock_readonly_attributes(MMHandleType handle);
+
+/**
+ * This function disable pre-defined attributes.
+ *
+ * @param[in] handle Handle of camcorder.
+ * @return void
+ * @remarks
+ * @see
+ *
+ */
+int _mmcamcorder_set_disabled_attributes(MMHandleType handle);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __MM_CAMCORDER_ATTRIBUTE_H__ */
diff --git a/src/include/mm_camcorder_audiorec.h b/src/include/mm_camcorder_audiorec.h
new file mode 100644
index 0000000..eb10677
--- /dev/null
+++ b/src/include/mm_camcorder_audiorec.h
@@ -0,0 +1,103 @@
+/*
+ * libmm-camcorder
+ *
+ * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: Jeongmo Yang <jm80.yang@samsung.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef __MM_CAMCORDER_AUDIOREC_H__
+#define __MM_CAMCORDER_AUDIOREC_H__
+
+/*=======================================================================================
+| INCLUDE FILES |
+========================================================================================*/
+#include <mm_types.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*=======================================================================================
+| STRUCTURE DEFINITIONS |
+========================================================================================*/
+/**
+ * MMCamcorder information for audio mode
+ */
+typedef struct {
+ int iSamplingRate; /**< Sampling rate */
+ int iBitDepth; /**< Bit depth */
+ int iChannels; /**< audio channels */
+ char *filename; /**< recorded file name */
+ gboolean b_commiting; /**< Is it commiting now? */
+ gboolean bMuxing; /**< whether muxing */
+ guint64 filesize; /**< current recorded file size */
+ guint64 max_time; /**< max recording time */
+ int fileformat; /**< recording file format */
+} _MMCamcorderAudioInfo;
+
+/*=======================================================================================
+| GLOBAL FUNCTION PROTOTYPES |
+========================================================================================*/
+/**
+ * This function creates audio pipeline for audio recording.
+ *
+ * @param[in] handle Handle of camcorder.
+ * @return This function returns MM_ERROR_NONE on success, or others on failure.
+ * @remarks
+ * @see _mmcamcorder_destroy_audio_pipeline()
+ *
+ */
+int _mmcamcorder_create_audio_pipeline(MMHandleType handle);
+
+/**
+ * This function destroy audio pipeline.
+ *
+ * @param[in] handle Handle of camcorder.
+ * @return void
+ * @remarks
+ * @see _mmcamcorder_destroy_pipeline()
+ *
+ */
+void _mmcamcorder_destroy_audio_pipeline(MMHandleType handle);
+
+/**
+ * This function runs command for audio recording.
+ *
+ * @param[in] handle Handle of camcorder.
+ * @param[in] command audio recording command.
+ * @return This function returns MM_ERROR_NONE on success, or others on failure.
+ * @remarks
+ * @see
+ *
+ */
+int _mmcamcorder_audio_command(MMHandleType handle, int command);
+
+/**
+ * This function handles EOS(end of stream) when audio recording is finished.
+ *
+ * @param[in] handle Handle of camcorder.
+ * @return This function returns TRUE on success, or FALSE on failure.
+ * @remarks
+ * @see
+ *
+ */
+int _mmcamcorder_audio_handle_eos(MMHandleType handle);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* __MM_CAMCORDER_AUDIOREC_H__ */
diff --git a/src/include/mm_camcorder_configure.h b/src/include/mm_camcorder_configure.h
new file mode 100644
index 0000000..5f2abf3
--- /dev/null
+++ b/src/include/mm_camcorder_configure.h
@@ -0,0 +1,366 @@
+/*
+ * libmm-camcorder
+ *
+ * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: Jeongmo Yang <jm80.yang@samsung.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef __MM_CAMCORDER_CONFIGURE_H__
+#define __MM_CAMCORDER_CONFIGURE_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*=======================================================================================
+| MACRO DEFINITIONS |
+========================================================================================*/
+#define SAFE_FREE(x) \
+ if (x) {\
+ g_free(x); \
+ x = NULL; \
+ }
+
+#define CONFIGURE_MAIN_FILE "mmfw_camcorder.ini"
+
+/*=======================================================================================
+| ENUM DEFINITIONS |
+========================================================================================*/
+enum ConfigureType {
+ CONFIGURE_TYPE_MAIN,
+ CONFIGURE_TYPE_CTRL,
+};
+
+enum ConfigureValueType {
+ CONFIGURE_VALUE_INT,
+ CONFIGURE_VALUE_INT_RANGE,
+ CONFIGURE_VALUE_INT_ARRAY,
+ CONFIGURE_VALUE_INT_PAIR_ARRAY,
+ CONFIGURE_VALUE_STRING,
+ CONFIGURE_VALUE_STRING_ARRAY,
+ CONFIGURE_VALUE_ELEMENT,
+ CONFIGURE_VALUE_NUM,
+};
+
+enum ConfigureCategoryMain {
+ CONFIGURE_CATEGORY_MAIN_GENERAL,
+ CONFIGURE_CATEGORY_MAIN_VIDEO_INPUT,
+ CONFIGURE_CATEGORY_MAIN_AUDIO_INPUT,
+ CONFIGURE_CATEGORY_MAIN_VIDEO_OUTPUT,
+ CONFIGURE_CATEGORY_MAIN_CAPTURE,
+ CONFIGURE_CATEGORY_MAIN_RECORD,
+ CONFIGURE_CATEGORY_MAIN_VIDEO_ENCODER,
+ CONFIGURE_CATEGORY_MAIN_AUDIO_ENCODER,
+ CONFIGURE_CATEGORY_MAIN_IMAGE_ENCODER,
+ CONFIGURE_CATEGORY_MAIN_MUX,
+ CONFIGURE_CATEGORY_MAIN_NUM,
+};
+
+enum ConfigureCategoryCtrl {
+ CONFIGURE_CATEGORY_CTRL_CAMERA,
+ CONFIGURE_CATEGORY_CTRL_STROBE,
+ CONFIGURE_CATEGORY_CTRL_EFFECT,
+ CONFIGURE_CATEGORY_CTRL_PHOTOGRAPH,
+ CONFIGURE_CATEGORY_CTRL_CAPTURE,
+ CONFIGURE_CATEGORY_CTRL_DETECT,
+ CONFIGURE_CATEGORY_CTRL_NUM,
+};
+
+/*=======================================================================================
+| STRUCTURE DEFINITIONS |
+========================================================================================*/
+typedef struct _type_int type_int;
+struct _type_int {
+ char *name;
+ int value;
+};
+
+typedef struct _type_int_range type_int_range;
+struct _type_int_range {
+ char *name;
+ int min;
+ int max;
+ int default_value;
+};
+
+typedef struct _type_int_array type_int_array;
+struct _type_int_array {
+ char *name;
+ int *value;
+ int count;
+ int default_value;
+};
+
+typedef struct _type_int_pair_array type_int_pair_array;
+struct _type_int_pair_array {
+ char *name;
+ int *value[2];
+ int count;
+ int default_value[2];
+};
+
+typedef struct _type_string type_string;
+struct _type_string {
+ char *name;
+ char *value;
+};
+
+typedef struct _type_string_array type_string_array;
+struct _type_string_array {
+ char *name;
+ char **value;
+ int count;
+ char *default_value;
+};
+
+typedef struct _type_element type_element;
+struct _type_element {
+ char *name;
+ char *element_name;
+ type_int **value_int;
+ int count_int;
+ type_string **value_string;
+ int count_string;
+};
+
+typedef struct _conf_info conf_info;
+struct _conf_info {
+ int count;
+ void **detail_info;
+};
+
+typedef struct _conf_info_table conf_info_table;
+struct _conf_info_table {
+ char *name;
+ int value_type;
+ union {
+ int value_int;
+ char *value_string;
+ type_element *value_element;
+ };
+};
+
+typedef struct _camera_conf camera_conf;
+struct _camera_conf {
+ int type;
+ conf_info **info;
+};
+
+/*=======================================================================================
+| MODULE FUNCTION PROTOTYPES |
+========================================================================================*/
+/* User function */
+/**
+ * This function creates configure info structure from ini file.
+ *
+ * @param[in] type configure type(MAIN or CTRL).
+ * @param[in] ConfFile ini file path.
+ * @param[out] configure_info configure structure to be got.
+ * @return This function returns MM_ERROR_NONE on success, or others on failure.
+ * @remarks
+ * @see _mmcamcorder_conf_release_info()
+ *
+ */
+int _mmcamcorder_conf_get_info(int type, char *ConfFile, camera_conf **configure_info);
+
+/**
+ * This function releases configure info.
+ *
+ * @param[in] configure_info configure structure to be released.
+ * @return void
+ * @remarks
+ * @see _mmcamcorder_conf_get_info()
+ *
+ */
+void _mmcamcorder_conf_release_info(camera_conf **configure_info);
+
+/**
+ * This function gets integer type value from configure info.
+ *
+ * @param[in] configure_info configure structure created by _mmcamcorder_conf_get_info.
+ * @param[in] category configure category.
+ * @param[in] name detail name in category.
+ * @param[out] value value to be got.
+ * @return This function returns TRUE on success, or FALSE on failure.
+ * @remarks
+ * @see
+ *
+ */
+int _mmcamcorder_conf_get_value_int(camera_conf *configure_info, int category, char *name, int *value);
+
+/**
+ * This function gets integer-range type value from configure info.
+ *
+ * @param[in] configure_info configure structure created by _mmcamcorder_conf_get_info.
+ * @param[in] category configure category.
+ * @param[in] name detail name in category.
+ * @param[out] value value to be got.
+ * @return This function returns TRUE on success, or FALSE on failure.
+ * @remarks
+ * @see
+ *
+ */
+int _mmcamcorder_conf_get_value_int_range(camera_conf *configure_info, int category, char *name, type_int_range **value);
+
+/**
+ * This function gets integer-array type value from configure info.
+ *
+ * @param[in] configure_info configure structure created by _mmcamcorder_conf_get_info.
+ * @param[in] category configure category.
+ * @param[in] name detail name in category.
+ * @param[out] value value to be got.
+ * @return This function returns TRUE on success, or FALSE on failure.
+ * @remarks
+ * @see
+ *
+ */
+int _mmcamcorder_conf_get_value_int_array(camera_conf *configure_info, int category, char *name, type_int_array **value);
+
+/**
+ * This function gets integer-pair-array type value from configure info.
+ *
+ * @param[in] configure_info configure structure created by _mmcamcorder_conf_get_info.
+ * @param[in] category configure category.
+ * @param[in] name detail name in category.
+ * @param[out] value value to be got.
+ * @return This function returns TRUE on success, or FALSE on failure.
+ * @remarks
+ * @see
+ *
+ */
+int _mmcamcorder_conf_get_value_int_pair_array(camera_conf *configure_info, int category, char *name, type_int_pair_array **value);
+
+/**
+ * This function gets string type value from configure info.
+ *
+ * @param[in] configure_info configure structure created by _mmcamcorder_conf_get_info.
+ * @param[in] category configure category.
+ * @param[in] name detail name in category.
+ * @param[out] value value to be got.
+ * @return This function returns TRUE on success, or FALSE on failure.
+ * @remarks
+ * @see
+ *
+ */
+int _mmcamcorder_conf_get_value_string(camera_conf *configure_info, int category, char *name, char **value);
+
+/**
+ * This function gets string-array type value from configure info.
+ *
+ * @param[in] configure_info configure structure created by _mmcamcorder_conf_get_info.
+ * @param[in] category configure category.
+ * @param[in] name detail name in category.
+ * @param[out] value value to be got.
+ * @return This function returns TRUE on success, or FALSE on failure.
+ * @remarks
+ * @see
+ *
+ */
+int _mmcamcorder_conf_get_value_string_array(camera_conf *configure_info, int category, char *name, type_string_array **value);
+
+/**
+ * This function gets element info from configure info.
+ *
+ * @param[in] configure_info configure structure created by _mmcamcorder_conf_get_info.
+ * @param[in] category configure category.
+ * @param[in] name detail name in category.
+ * @param[out] element element info to be got.
+ * @return This function returns TRUE on success, or FALSE on failure.
+ * @remarks
+ * @see
+ *
+ */
+int _mmcamcorder_conf_get_element(camera_conf *configure_info, int category, char *name, type_element **element);
+
+/**
+ * This function gets element name from element info.
+ *
+ * @param[in] element element info.
+ * @param[out] name element name to be got.
+ * @return This function returns TRUE on success, or FALSE on failure.
+ * @remarks
+ * @see
+ *
+ */
+int _mmcamcorder_conf_get_value_element_name(type_element *element, char **value);
+
+/**
+ * This function gets integer value of element's named property from element info.
+ *
+ * @param[in] element element info.
+ * @param[in] name property name.
+ * @param[out] value value to be got.
+ * @return This function returns TRUE on success, or FALSE on failure.
+ * @remarks
+ * @see
+ *
+ */
+int _mmcamcorder_conf_get_value_element_int(type_element *element, char *name, int *value);
+
+/**
+ * This function gets string value of element's named property from element info.
+ *
+ * @param[in] element element info.
+ * @param[in] name property name.
+ * @param[out] value value to be got.
+ * @return This function returns TRUE on success, or FALSE on failure.
+ * @remarks
+ * @see
+ *
+ */
+int _mmcamcorder_conf_get_value_element_string(type_element *element, char *name, char **value);
+
+/**
+ * This function sets all property of element info.
+ *
+ * @param[in] gst gstreamer element.
+ * @param[in] element element info.
+ * @return This function returns TRUE on success, or FALSE on failure.
+ * @remarks
+ * @see
+ *
+ */
+int _mmcamcorder_conf_set_value_element_property(GstElement *gst, type_element *element);
+
+/**
+ * This function prints all values of configure info.
+ *
+ * @param[in] configure_info configure structure created by _mmcamcorder_conf_get_info.
+ * @return This function returns TRUE on success, or FALSE on failure.
+ * @remarks
+ * @see
+ *
+ */
+void _mmcamcorder_conf_print_info(camera_conf **configure_info);
+
+type_element *_mmcamcorder_get_type_element(MMHandleType handle, int type);
+int _mmcamcorder_get_available_format(MMHandleType handle, int conf_category, int **format);
+
+/* Internal function */
+void _mmcamcorder_conf_init(int type, camera_conf **configure_info);
+int _mmcamcorder_conf_parse_info(int type, FILE *fd, camera_conf **configure_info);
+int _mmcamcorder_conf_get_value_type(int type, int category, char *name, int *value_type);
+int _mmcamcorder_conf_add_info(int type, conf_info **info, char **buffer_details, int category, int count_details);
+int _mmcamcorder_conf_get_default_value_int(int type, int category, char *name, int *value);
+int _mmcamcorder_conf_get_default_value_string(int type, int category, char *name, char **value);
+int _mmcamcorder_conf_get_default_element(int type, int category, char *name, type_element **element);
+int _mmcamcorder_conf_get_category_size(int type, int category, int *size);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* __MM_CAMCORDER_CONFIGURE_H__ */
diff --git a/src/include/mm_camcorder_exifdef.h b/src/include/mm_camcorder_exifdef.h
new file mode 100644
index 0000000..b27db16
--- /dev/null
+++ b/src/include/mm_camcorder_exifdef.h
@@ -0,0 +1,99 @@
+/*
+ * libmm-camcorder
+ *
+ * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: Jeongmo Yang <jm80.yang@samsung.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+/*! \brief The definitions for exif information
+
+ Some of the EXIF informations aren't needed to be changed within a
+ session. For example, everytime still-image taken, [Maker name] field
+ or [Model name] field always be same in a device, while [Datetime] or
+ [Exposure value] isn't. This definitions are for the un-changeable
+ values.
+*/
+
+/*!
+ \def MM_MAKER_NAME
+ Shows manufacturer of digicam, "Samsung".
+*/
+/*!
+ \def MM_MODEL_NAME
+ Shows model number of digicam.
+*/
+/*!
+ \def MM_SOFTWARE_NAME
+ Shows firmware(internal software of digicam) version number.
+*/
+/*!
+ \def MM_EXIF_ORIENTATION
+ The orientation of the camera relative to the scene, when the image
+ was captured. The start point of stored data is, '1' means upper left,
+ '3' lower right, '6' upper right, '8' lower left, '9' undefined.
+*/
+/*!
+ \def MM_EXIF_YCBCRPOSITIONING
+ When image format is YCbCr and uses 'Subsampling'(cropping of chroma
+ data, all the digicam do that), this value defines the chroma sample
+ point of subsampled pixel array. '1' means the center of pixel array,
+ '2' means the datum point(0,0).
+*/
+/*!
+ \def MM_COMPONENTS_CONFIGURATION
+ Order arrangement of pixel.
+*/
+/*!
+ \def MM_EXIF_COLORSPACE
+ Color space of stilled JPEG image.
+*/
+/*!
+ \def MM_EXIF_CUSTOMRENDERED
+ The method of compressed jpeg image rendering.
+*/
+
+#ifndef __MM_EXIFDEF_H__
+#define __MM_EXIFDEF_H__
+
+/*=======================================================================================
+| MACRO DEFINITIONS |
+========================================================================================*/
+#define MM_EXIF_VERSION (0x00000030) | (0x00000032 << 8) | (0x00000032 << 16) | (0x00000030 << 24) /* ASCII 0220 */
+#define MM_MAKER_NAME "SAMSUNG"
+#define MM_USER_COMMENT "User comment "
+#define MM_SOFTWARE_NAME "Camera Application "
+#define MM_EXIF_ORIENTATION 1 /* upper-top */
+#define MM_EXIF_YCBCRPOSITIONING 1 /* centered */
+#define MM_COMPONENTS_CONFIGURATION (0x00000000) | (0x00000001) | (0x00000002 << 8) | (0x00000003 << 16) /* Y Cb Cr - */
+#define MM_EXIF_COLORSPACE 1 /* sRGB */
+#define MM_EXIF_CUSTOMRENDERED 0 /* Normal rendered */
+#define MM_EXPOSURE_PROGRAM 3 /* 0~8 0 : not defined */
+#define MM_METERING_MODE 0 /* 0~6 0: unkown */
+#define MM_SENSING_MODE 1 /* 1~8 1: not defined */
+#define MM_FOCAL_LENGTH 450
+#define MM_FOCAL_LENGTH_35MMFILM 0 /*unknown */
+#define MM_GAIN_CONTROL 0 /* 0~4 0 none */
+#define MM_FILE_SOURCE 3 /* 3: DSC */
+#define MM_SCENE_TYPE 1 /* 1 DSC : a directly photographed image */
+#define MM_EXPOSURE_MODE 0 /*0~2 0 : auto exposure */
+#define MM_VALUE_NORMAL 0 /* 1 DSC : a directly photographed image */
+#define MM_VALUE_LOW 1 /* 1 DSC : a directly photographed image */
+#define MM_VALUE_HARD 2 /* 1 DSC : a directly photographed image */
+#define MM_SUBJECT_DISTANCE_RANGE 0 /* 0~3. 0 : unknown */
+#define INVALID_GPS_VALUE 1000
+
+#endif /* __MM_EXIFDEF_H__ */
diff --git a/src/include/mm_camcorder_exifinfo.h b/src/include/mm_camcorder_exifinfo.h
new file mode 100644
index 0000000..3356122
--- /dev/null
+++ b/src/include/mm_camcorder_exifinfo.h
@@ -0,0 +1,161 @@
+/*
+ * libmm-camcorder
+ *
+ * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: Jeongmo Yang <jm80.yang@samsung.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef _MM_EXIFINFO_H_
+#define _MM_EXIFINFO_H_
+
+/*=======================================================================================
+| INCLUDE FILES |
+========================================================================================*/
+#include <libexif/exif-ifd.h>
+#include <libexif/exif-tag.h>
+#include <libexif/exif-format.h>
+#include <libexif/exif-data.h>
+#include <libexif/mnote-samsung-tag.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*=======================================================================================
+| STRUCTURE DEFINITIONS |
+========================================================================================*/
+/**
+ * Structure for exif data infomation.
+ */
+typedef struct {
+ void *data; /**< saved exif data*/
+ unsigned int size; /**< size of saved exif data*/
+} mm_exif_info_t;
+
+/*=======================================================================================
+| GLOBAL FUNCTION PROTOTYPES |
+========================================================================================*/
+/**
+ * Create exif info
+ * @param[in] info exif info.
+ * @return return int.
+ */
+int mm_exif_create_exif_info(mm_exif_info_t **info);
+
+/**
+ * Destroy exif info
+ * @param[in] info exif info.
+ * @return void
+ */
+void mm_exif_destory_exif_info(mm_exif_info_t *info);
+
+/**
+ * get exif data information from data buffer
+ * @param[in] info exif info.
+ * @return return ExifData.
+ */
+ExifData *mm_exif_get_exif_data_from_data(mm_exif_info_t *info);
+
+/**
+ * get exif data information from exif info
+ * @param[in] info exif info.
+ * @param[out] Exif tag .
+ * @return return int.
+ */
+ExifData *mm_exif_get_exif_from_info(mm_exif_info_t *info);
+
+/**
+ * Write exif data information into exif info
+ * @param[in] info exif info.
+ * @param[in] Exif tag .
+ * @param[in] Exif tag value to be written.
+ * @return return int.
+ */
+int mm_exif_set_exif_to_info(mm_exif_info_t *info, ExifData *exif);
+
+/**
+ * add one tag information into exif
+ * @param[in] info exif info.
+ * @param[in] Exif tag .
+ * @param[in] tag content category.
+ * @param[in] tag format.
+ * @param[in] the number of the component .
+ * @param[in] the pointer of the tag data.
+ * @return return int.
+ */
+int mm_exif_set_add_entry(ExifData *exif, ExifIfd ifd, ExifTag tag,
+ ExifFormat format, unsigned long components,
+ unsigned char *data);
+
+/**
+ * Write thumbnail data into exif info.
+ * @param[in] info exif info.
+ * @param[in] thumbnail image thumbnail data.
+ * @param[in] width width of thumbnail image.
+ * @param[in] height height of thumbnail image.
+ * @param[in] length length of thumbnail image.
+ * @return return int.
+ */
+int mm_exif_add_thumbnail_info(mm_exif_info_t *info, void *thumbnail,
+ int width, int height, int len);
+
+/**
+ * create ExifMnoteDataSamsung and set up related function pointers
+ * @param[in/out] info exif info.
+ * @return return int.
+ */
+int mm_exif_mnote_create(ExifData *exif);
+
+/**
+ * add one Samsung maker note tag information into exif
+ * @param[in/out] info exif info.
+ * @param[in] Samsung maker note tag .
+ * @param[in] tag index.
+ * @param[in] sub tag index 1.
+ * @param[in] sub tag index 2.
+ * @return return int.
+ */
+int mm_exif_mnote_set_add_entry(ExifData *exif, MnoteSamsungTag tag,
+ int index, int subindex1, int subindex2);
+
+/**
+ * Write exif info into a jpeg image and then save as a jpeg file.
+ * @param[in/out] filename jpeg filename.
+ * @param[in] info exif info.
+ * @param[in] jpeg jpeg image data.
+ * @param[in] length length of jpeg image.
+ * @return return int.
+ */
+int mm_exif_write_exif_jpeg_to_file(char *filename, mm_exif_info_t *info, void *jpeg, int jpeg_len);
+
+/**
+ * Write exif info into a jpeg memory buffer.
+ * @param[in/out] mem image data buffer.
+ * @param[in/out] length image data length.
+ * @param[in] info exif info.
+ * @param[in] jpeg jpeg image data.
+ * @param[in] length length of jpeg image.
+ * @return return int.
+ */
+int mm_exif_write_exif_jpeg_to_memory(void **mem, unsigned int *length,
+ mm_exif_info_t *info, void *jpeg,
+ unsigned int jpeg_len);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /*_MM_EXIFINFO_H_*/
diff --git a/src/include/mm_camcorder_gstcommon.h b/src/include/mm_camcorder_gstcommon.h
new file mode 100644
index 0000000..7ba1605
--- /dev/null
+++ b/src/include/mm_camcorder_gstcommon.h
@@ -0,0 +1,183 @@
+/*
+ * libmm-camcorder
+ *
+ * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: Jeongmo Yang <jm80.yang@samsung.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef __MM_CAMCORDER_GSTCOMMON_H__
+#define __MM_CAMCORDER_GSTCOMMON_H__
+
+/*=======================================================================================
+| INCLUDE FILES |
+========================================================================================*/
+#include <mm_types.h>
+#include "mm_camcorder_configure.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*=======================================================================================
+| GLOBAL DEFINITIONS AND DECLARATIONS FOR CAMCORDER |
+========================================================================================*/
+
+/*=======================================================================================
+| MACRO DEFINITIONS |
+========================================================================================*/
+
+/*=======================================================================================
+| ENUM DEFINITIONS |
+========================================================================================*/
+/**
+* Enumerations for AMR bitrate
+*/
+typedef enum MMCamcorderAMRBitRate {
+ MM_CAMCORDER_MR475, /**< MR475 : 4.75 kbit/s */
+ MM_CAMCORDER_MR515, /**< MR515 : 5.15 kbit/s */
+ MM_CAMCORDER_MR59, /**< MR59 : 5.90 kbit/s */
+ MM_CAMCORDER_MR67, /**< MR67 : 6.70 kbit/s */
+ MM_CAMCORDER_MR74, /**< MR74 : 7.40 kbit/s */
+ MM_CAMCORDER_MR795, /**< MR795 : 7.95 kbit/s */
+ MM_CAMCORDER_MR102, /**< MR102 : 10.20 kbit/s */
+ MM_CAMCORDER_MR122, /**< MR122 : 12.20 kbit/s */
+ MM_CAMCORDER_MRDTX /**< MRDTX */
+} MMCamcorderAMRBitRate;
+
+/*=======================================================================================
+| STRUCTURE DEFINITIONS |
+========================================================================================*/
+/**
+ * Element name table.
+ * @note if name is NULL, not supported.
+ */
+typedef struct {
+ unsigned int prof_id; /**< id of mmcamcorder_profile_attrs_id */
+ unsigned int id; /**< id of value id */
+ char *name; /**< gstreamer element name*/
+} _MMCamcorderElementName;
+
+/*=======================================================================================
+| CONSTANT DEFINITIONS |
+========================================================================================*/
+
+/*=======================================================================================
+| STATIC VARIABLES |
+========================================================================================*/
+
+/*=======================================================================================
+| EXTERN GLOBAL VARIABLE |
+========================================================================================*/
+
+/*=======================================================================================
+| GLOBAL FUNCTION PROTOTYPES |
+========================================================================================*/
+/* create bin */
+/**
+ * This function creates bin of video source.
+ * Basically, main pipeline of camcorder is composed of several bin(a bundle
+ * of elements). Each bin operates its own function. This bin has a roll
+ * inputting video data from camera.
+ *
+ * @param[in] handle Handle of camcorder context.
+ * @return This function returns MM_ERROR_NONE on success, or the other values on error.
+ * @remarks
+ * @see __mmcamcorder_create_preview_pipeline()
+ */
+int _mmcamcorder_create_videosrc_bin(MMHandleType handle);
+
+/**
+ * This function creates bin of audio source.
+ * Basically, main pipeline of camcorder is composed of several bin(a bundle
+ * of elements). Each bin operates its own function. This bin has a roll
+ * inputting audio data from audio source(such as mike).
+ *
+ * @param[in] handle Handle of camcorder context.
+ * @return This function returns MM_ERROR_NONE on success, or the other values on error.
+ * @remarks
+ * @see __mmcamcorder_create_preview_pipeline()
+ */
+int _mmcamcorder_create_audiosrc_bin(MMHandleType handle);
+
+/**
+ * This function creates bin of video sink.
+ * Basically, main pipeline of camcorder is composed of several bin(a bundle
+ * of elements). Each bin operates its own function. This bin has a roll
+ * transferring video data to frame buffer.
+ *
+ * @param[in] handle Handle of camcorder context.
+ * @return This function returns MM_ERROR_NONE on success, or the other values on error.
+ * @remarks
+ * @see __mmcamcorder_create_preview_pipeline()
+ */
+int _mmcamcorder_create_videosink_bin(MMHandleType handle);
+
+/**
+ * This function creates outputsink bin.
+ *
+ * @param[in] handle Handle of camcorder context.
+ * @return This function returns MM_ERROR_NONE on success, or the other values on error.
+ * @remarks
+ * @see __mmcamcorder_create_preview_pipeline()
+ */
+int _mmcamcorder_create_encodesink_bin(MMHandleType handle);
+
+/**
+ * This function creates bin of still shot sink.
+ * Basically, main pipeline of camcorder is composed of several bin(a bundle
+ * of elements). Each bin operates its own function. This bin has a roll
+ * writting image file with video stream.
+ *
+ * @param[in] handle Handle of camcorder context.
+ * @return This function returns MM_ERROR_NONE on success, or the other values on error.
+ * @remarks
+ * @see __mmcamcorder_create_preview_pipeline()
+ */
+int _mmcamcorder_create_stillshotsink_bin(MMHandleType handle);
+
+/**
+ * This function creates main pipeline of camcorder.
+ * Basically, main pipeline of camcorder is composed of several bin(a bundle
+ * of elements). And if the appilcation wants to make pipeline working, the
+ * application assemble bin that is proper to that task.
+ * When this function is called, bins that is needed for preview will be composed.
+ *
+ * @param[in] handle Handle of camcorder context.
+ * @return This function returns MM_ERROR_NONE on success, or the other values on error.
+ * @remarks
+ * @see _mmcamcorder_create_pipeline()
+ */
+int _mmcamcorder_create_preview_pipeline(MMHandleType handle);
+
+/* plug-in related */
+void _mmcamcorder_negosig_handler(GstElement *videosrc, MMHandleType handle);
+bool _mmcamcorder_set_display_rotation(MMHandleType handle, int display_rotate);
+bool _mmcamcorder_set_videosrc_rotation(MMHandleType handle, int videosrc_rotate);
+
+/* etc */
+int _mmcamcorder_videosink_window_set(MMHandleType handle, type_element *VideosinkElement);
+int _mmcamcorder_vframe_stablize(MMHandleType handle);
+gboolean _mmcamcorder_get_device_info(MMHandleType handle);
+int _mmcamcorder_get_eos_message(MMHandleType handle);
+void _mmcamcorder_remove_element_handle(MMHandleType handle, int first_elem, int last_elem);
+int _mmcamcorder_check_audiocodec_fileformat_compatibility(MMHandleType handle);
+int _mmcamcorder_check_videocodec_fileformat_compatibility(MMHandleType handle);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* __MM_CAMCORDER_GSTCOMMON_H__ */
diff --git a/src/include/mm_camcorder_internal.h b/src/include/mm_camcorder_internal.h
new file mode 100644
index 0000000..c887273
--- /dev/null
+++ b/src/include/mm_camcorder_internal.h
@@ -0,0 +1,1072 @@
+/*
+ * libmm-camcorder
+ *
+ * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: Jeongmo Yang <jm80.yang@samsung.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef __MM_CAMCORDER_INTERNAL_H__
+#define __MM_CAMCORDER_INTERNAL_H__
+
+
+/*=======================================================================================
+| INCLUDE FILES |
+========================================================================================*/
+#include <malloc.h>
+#include <string.h>
+#include <unistd.h>
+#include <pthread.h>
+#include <semaphore.h>
+
+#include <mm_types.h>
+#include <mm_attrs.h>
+#include <mm_attrs_private.h>
+#include <mm_message.h>
+#include <mm_ta.h>
+#include <sndfile.h>
+
+#include "mm_camcorder.h"
+#include "mm_debug.h"
+
+/* camcorder sub module */
+#include "mm_camcorder_attribute.h"
+#include "mm_camcorder_platform.h"
+#include "mm_camcorder_stillshot.h"
+#include "mm_camcorder_videorec.h"
+#include "mm_camcorder_audiorec.h"
+#include "mm_camcorder_gstcommon.h"
+#include "mm_camcorder_exifinfo.h"
+#include "mm_camcorder_util.h"
+#include "mm_camcorder_configure.h"
+#include "mm_camcorder_sound.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*=======================================================================================
+| MACRO DEFINITIONS |
+========================================================================================*/
+#define _mmcam_dbg_verb(fmt, args...) mmf_debug(MMF_DEBUG_VERBOSE,"[%05d][%s]: " fmt "\n", __LINE__, __func__, ##args);
+#define _mmcam_dbg_log(fmt, args...) mmf_debug(MMF_DEBUG_LOG,"[%05d][%s]: " fmt "\n", __LINE__, __func__, ##args);
+#define _mmcam_dbg_warn(fmt, args...) mmf_debug(MMF_DEBUG_WARNING,"[%05d][%s]: " fmt "\n", __LINE__, __func__, ##args);
+#define _mmcam_dbg_err(fmt, args...) mmf_debug(MMF_DEBUG_ERROR,"[%05d][%s]: " fmt "\n", __LINE__, __func__, ##args);
+#define _mmcam_dbg_crit(fmt, args...) mmf_debug(MMF_DEBUG_CRITICAL,"[%05d][%s]: " fmt "\n", __LINE__, __func__, ##args);
+
+/**
+ * Macro for checking validity and debugging
+ */
+#define mmf_return_if_fail( expr ) \
+ if( expr ){} \
+ else \
+ { \
+ _mmcam_dbg_err( "failed [%s]", #expr); \
+ return; \
+ };
+
+/**
+ * Macro for checking validity and debugging
+ */
+#define mmf_return_val_if_fail( expr, val ) \
+ if( expr ){} \
+ else \
+ { \
+ _mmcam_dbg_err("failed [%s]", #expr); \
+ return( val ); \
+ };
+
+#ifndef ARRAY_SIZE
+/**
+ * Macro for getting array size
+ */
+#define ARRAY_SIZE(a) (sizeof((a)) / sizeof((a)[0]))
+#endif
+
+/* gstreamer element creation macro */
+#define _MMCAMCORDER_PIPELINE_MAKE(sub_context, eid, name /*char* */, err) \
+ if (sub_context->element[eid].gst != NULL) { \
+ _mmcam_dbg_err("The element(Pipeline) is existed. element_id=[%d], name=[%s]", eid, name); \
+ gst_object_unref(sub_context->element[eid].gst); \
+ } \
+ sub_context->element[eid].id = eid; \
+ sub_context->element[eid].gst = gst_pipeline_new(name); \
+ if (sub_context->element[eid].gst == NULL) { \
+ _mmcam_dbg_err("Pipeline creation fail. element_id=[%d], name=[%s]", eid, name); \
+ err = MM_ERROR_CAMCORDER_RESOURCE_CREATION; \
+ goto pipeline_creation_error; \
+ } else { \
+ g_object_weak_ref(G_OBJECT(sub_context->element[eid].gst), (GWeakNotify)_mmcamcorder_element_release_noti, sub_context); \
+ }
+
+#define _MMCAMCORDER_BIN_MAKE(sub_context, eid, name /*char* */, err) \
+ if (sub_context->element[eid].gst != NULL) { \
+ _mmcam_dbg_err("The element(Bin) is existed. element_id=[%d], name=[%s]", eid, name); \
+ gst_object_unref(sub_context->element[eid].gst); \
+ } \
+ sub_context->element[eid].id = eid; \
+ sub_context->element[eid].gst = gst_bin_new(name); \
+ if (sub_context->element[eid].gst == NULL) { \
+ _mmcam_dbg_err("Bin creation fail. element_id=[%d], name=[%s]\n", eid, name); \
+ err = MM_ERROR_CAMCORDER_RESOURCE_CREATION; \
+ goto pipeline_creation_error; \
+ } else { \
+ g_object_weak_ref(G_OBJECT(sub_context->element[eid].gst), (GWeakNotify)_mmcamcorder_element_release_noti, sub_context); \
+ }
+
+#define _MMCAMCORDER_ELEMENT_MAKE(sub_context, eid, name /*char* */, nickname /*char* */, elist, err) \
+ if (sub_context->element[eid].gst != NULL) { \
+ _mmcam_dbg_err("The element is existed. element_id=[%d], name=[%s]", eid, name); \
+ gst_object_unref(sub_context->element[eid].gst); \
+ } \
+ sub_context->element[eid].id = eid; \
+ sub_context->element[eid].gst = gst_element_factory_make(name, nickname); \
+ if (sub_context->element[eid].gst == NULL) { \
+ _mmcam_dbg_err("Element creation fail. element_id=[%d], name=[%s]", eid, name); \
+ err = MM_ERROR_CAMCORDER_RESOURCE_CREATION; \
+ goto pipeline_creation_error; \
+ } else { \
+ g_object_weak_ref(G_OBJECT(sub_context->element[eid].gst), (GWeakNotify)_mmcamcorder_element_release_noti, sub_context); \
+ } \
+ elist = g_list_append(elist, &(sub_context->element[eid]));
+
+#define _MMCAMCORDER_ENCODEBIN_ELMGET(sub_context, eid, name /*char* */, err) \
+ if (sub_context->element[eid].gst != NULL) { \
+ _mmcam_dbg_err("The element is existed. element_id=[%d], name=[%s]", eid, name); \
+ gst_object_unref(sub_context->element[eid].gst); \
+ } \
+ sub_context->element[eid].id = eid; \
+ g_object_get(G_OBJECT(sc->element[_MMCAMCORDER_ENCSINK_ENCBIN].gst), name, &(sc->element[eid].gst), NULL); \
+ if (sub_context->element[eid].gst == NULL) { \
+ _mmcam_dbg_err("Element get fail. element_id=[%d], name=[%s]", eid, name); \
+ err = MM_ERROR_CAMCORDER_RESOURCE_CREATION; \
+ goto pipeline_creation_error; \
+ } else{ \
+ gst_object_unref(sub_context->element[eid].gst); \
+ g_object_weak_ref(G_OBJECT(sub_context->element[eid].gst), (GWeakNotify)_mmcamcorder_element_release_noti, sub_context); \
+ }
+
+/* GStreamer element remove macro */
+#define _MMCAMCORDER_ELEMENT_REMOVE(sub_context, eid) \
+ if (sub_context->element[eid].gst != NULL) { \
+ gst_object_unref(sub_context->element[eid].gst); \
+ }
+
+#define _MM_GST_ELEMENT_LINK_MANY gst_element_link_many
+#define _MM_GST_ELEMENT_LINK gst_element_link
+#define _MM_GST_PAD_LINK gst_pad_link
+
+#define _MM_GST_PAD_LINK_UNREF( srcpad, sinkpad, err, if_fail_goto ) \
+{ \
+ GstPadLinkReturn ret = _MM_GST_PAD_LINK( srcpad, sinkpad ); \
+ gst_object_unref( srcpad ); srcpad = NULL; \
+ gst_object_unref( sinkpad ); sinkpad = NULL; \
+ if (ret != GST_PAD_LINK_OK) { \
+ err = MM_ERROR_CAMCORDER_GST_LINK; \
+ goto if_fail_goto; \
+ } \
+}
+
+#define _MM_GST_PAD_UNLINK_UNREF( srcpad, sinkpad) \
+ gst_pad_unlink( srcpad, sinkpad ); \
+ gst_object_unref( srcpad ); srcpad = NULL; \
+ gst_object_unref( sinkpad ); sinkpad = NULL;
+
+#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 */
+
+/**
+ * Total level count of manual focus */
+#define _MMFCAMCORDER_FOCUS_TOTAL_LEVEL 8
+
+/**
+ * File name length limit
+ */
+#define _MMCamcorder_FILENAME_LEN (512)
+
+/**
+ * Minimum integer value
+ */
+#define _MMCAMCORDER_MIN_INT (-2147483648)
+
+/**
+ * Maximum integer value
+ */
+#define _MMCAMCORDER_MAX_INT (2147483647)
+
+/**
+ * Audio timestamp margin (msec)
+ */
+#define _MMCAMCORDER_AUDIO_TIME_MARGIN (300)
+
+/**
+ * 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));
+
+/* 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))
+
+/* 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))
+
+/* 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))
+
+/* 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_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_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_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))
+
+/**
+ * Caster of main handle (camcorder)
+ */
+#define MMF_CAMCORDER(h) (mmf_camcorder_t *)(h)
+
+/**
+ * Caster of subcontext
+ */
+#define MMF_CAMCORDER_SUBCONTEXT(h) (((mmf_camcorder_t *)(h))->sub_context)
+
+/* LOCAL CONSTANT DEFINITIONS */
+/**
+ * Total Numbers of Attribute values.
+ * If you increase any enum of attribute values, you also have to increase this.
+ */
+#define MM_CAMCORDER_MODE_NUM 3 /**< Number of mode type */
+#define MM_CAMCORDER_COLOR_TONE_NUM 27 /**< Number of color-tone modes */
+#define MM_CAMCORDER_WHITE_BALANCE_NUM 10 /**< Number of WhiteBalance modes*/
+#define MM_CAMCORDER_SCENE_MODE_NUM 15 /**< Number of program-modes */
+#define MM_CAMCORDER_FOCUS_MODE_NUM 6 /**< Number of focus mode*/
+#define MM_CAMCORDER_AUTO_FOCUS_NUM 5 /**< Total count of auto focus type*/
+#define MM_CAMCORDER_FOCUS_STATE_NUM 4 /**< Number of focus state */
+#define MM_CAMCORDER_ISO_NUM 10 /**< Number of ISO */
+#define MM_CAMCORDER_AUTO_EXPOSURE_NUM 9 /**< Number of Auto exposure type */
+#define MM_CAMCORDER_WDR_NUM 3 /**< Number of wide dynamic range */
+#define MM_CAMCORDER_AHS_NUM 4 /**< Number of anti-handshake */
+#define MM_CAMCORDER_GEOMETRY_METHOD_NUM 4 /**< Number of geometry method */
+#define MM_CAMCORDER_TAG_ORT_NUM 8 /**< Number of tag orientation */
+#define MM_CAMCORDER_STROBE_MODE_NUM 8 /**< Number of strobe mode type */
+#define MM_CAMCORDER_STROBE_CONTROL_NUM 3 /**< Number of strobe control type */
+#define MM_CAMCORDER_DETECT_MODE_NUM 2 /**< Number of detect mode type */
+
+
+/*=======================================================================================
+| ENUM DEFINITIONS |
+========================================================================================*/
+/**
+ * Command for Camcorder.
+ */
+enum {
+ /* Command for Video/Audio recording */
+ _MMCamcorder_CMD_RECORD,
+ _MMCamcorder_CMD_PAUSE,
+ _MMCamcorder_CMD_CANCEL,
+ _MMCamcorder_CMD_COMMIT,
+
+ /* Command for Image capture */
+ _MMCamcorder_CMD_CAPTURE,
+ _MMCamcorder_CMD_CAPTURE_CANCEL,
+
+ /* Command for Preview(Video/Image only effective) */
+ _MMCamcorder_CMD_PREVIEW_START,
+ _MMCamcorder_CMD_PREVIEW_STOP,
+};
+
+/**
+ * Still-shot type
+ */
+enum {
+ _MMCamcorder_SINGLE_SHOT,
+ _MMCamcorder_MULTI_SHOT,
+};
+
+/**
+ * Enumerations for manual focus direction.
+ * If focusing mode is not "MM_CAMCORDER_AF_MODE_MANUAL", this value will be ignored.
+ */
+enum MMCamcorderMfLensDir {
+ MM_CAMCORDER_MF_LENS_DIR_FORWARD = 1, /**< Focus direction to forward */
+ MM_CAMCORDER_MF_LENS_DIR_BACKWARD, /**< Focus direction to backward */
+ MM_CAMCORDER_MF_LENS_DIR_NUM, /**< Total number of the directions */
+};
+
+/**
+ * Camcorder Pipeline's Element name.
+ * @note index of element.
+ */
+typedef enum {
+ _MMCAMCORDER_NONE = (-1),
+
+ /* Main Pipeline Element */
+ _MMCAMCORDER_MAIN_PIPE = 0x00,
+
+ /* Pipeline element of Video input */
+ _MMCAMCORDER_VIDEOSRC_BIN,
+ _MMCAMCORDER_VIDEOSRC_SRC,
+ _MMCAMCORDER_VIDEOSRC_FILT,
+ _MMCAMCORDER_VIDEOSRC_CLS,
+ _MMCAMCORDER_VIDEOSRC_SCALE,
+ _MMCAMCORDER_VIDEOSRC_VSFLT,
+ _MMCAMCORDER_VIDEOSRC_TEE,
+
+ /* Pipeline element of Audio input */
+ _MMCAMCORDER_AUDIOSRC_BIN,
+ _MMCAMCORDER_AUDIOSRC_SRC,
+ _MMCAMCORDER_AUDIOSRC_FILT,
+ _MMCAMCORDER_AUDIOSRC_NS,
+ _MMCAMCORDER_AUDIOSRC_QUE,
+ _MMCAMCORDER_AUDIOSRC_CONV,
+ _MMCAMCORDER_AUDIOSRC_VOL,
+ _MMCAMCORDER_AUDIOSRC_ENC,
+
+ /* Pipeline element of Video output */
+ _MMCAMCORDER_VIDEOSINK_BIN,
+ _MMCAMCORDER_VIDEOSINK_QUE,
+ _MMCAMCORDER_VIDEOSINK_SCALE,
+ _MMCAMCORDER_VIDEOSINK_FILT,
+ _MMCAMCORDER_VIDEOSINK_OVERLAY,
+ _MMCAMCORDER_VIDEOSINK_CLS,
+ _MMCAMCORDER_VIDEOSINK_ROTATE,
+ _MMCAMCORDER_VIDEOSINK_SINK,
+
+ /* Pipeline element of Encodebin */
+ _MMCAMCORDER_ENCSINK_BIN,
+ _MMCAMCORDER_ENCSINK_ENCBIN,
+ _MMCAMCORDER_ENCSINK_AQUE,
+ _MMCAMCORDER_ENCSINK_CONV,
+ _MMCAMCORDER_ENCSINK_AENC,
+ _MMCAMCORDER_ENCSINK_AENC_QUE,
+ _MMCAMCORDER_ENCSINK_VQUE,
+ _MMCAMCORDER_ENCSINK_VENC,
+ _MMCAMCORDER_ENCSINK_VENC_QUE,
+ _MMCAMCORDER_ENCSINK_ITOG,
+ _MMCAMCORDER_ENCSINK_ICROP,
+ _MMCAMCORDER_ENCSINK_ISCALE,
+ _MMCAMCORDER_ENCSINK_IFILT,
+ _MMCAMCORDER_ENCSINK_IQUE,
+ _MMCAMCORDER_ENCSINK_IENC,
+ _MMCAMCORDER_ENCSINK_MUX,
+ _MMCAMCORDER_ENCSINK_SINK,
+
+ /* Pipeline element of Stillshot output */
+ _MMCAMCORDER_STILLSHOTSINK_BIN,
+ _MMCAMCORDER_STILLSHOTSINK_QUE,
+ _MMCAMCORDER_STILLSHOTSINK_TOGGLE,
+ _MMCAMCORDER_STILLSHOTSINK_CLS,
+ _MMCAMCORDER_STILLSHOTSINK_CROP,
+ _MMCAMCORDER_STILLSHOTSINK_FILT,
+ _MMCAMCORDER_STILLSHOTSINK_SCALE,
+ _MMCAMCORDER_STILLSHOTSINK_FILT2,
+ _MMCAMCORDER_STILLSHOTSINK_ENC,
+ _MMCAMCORDER_STILLSHOTSINK_SINK,
+
+ _MMCamcorder_PIPELINE_ELEMENT_NUM,
+} _MMCAMCORDER_PIPELINE_ELELMENT;
+
+/**
+ * Command type for Camcorder.
+ */
+typedef enum {
+ _MMCAMCORDER_CMD_CREATE,
+ _MMCAMCORDER_CMD_DESTROY,
+ _MMCAMCORDER_CMD_REALIZE,
+ _MMCAMCORDER_CMD_UNREALIZE,
+ _MMCAMCORDER_CMD_START,
+ _MMCAMCORDER_CMD_STOP,
+ _MMCAMCORDER_CMD_CAPTURESTART,
+ _MMCAMCORDER_CMD_CAPTURESTOP,
+ _MMCAMCORDER_CMD_RECORD,
+ _MMCAMCORDER_CMD_PAUSE,
+ _MMCAMCORDER_CMD_COMMIT,
+ _MMCAMCORDER_CMD_CANCEL,
+ _MMCAMCORDER_CMD_QUIT,
+} _MMCamcorderCommandType;
+
+/**
+ * System state change cause
+ */
+typedef enum {
+ _MMCAMCORDER_STATE_CHANGE_NORMAL = 0,
+ _MMCAMCORDER_STATE_CHANGE_BY_ASM,
+} _MMCamcorderStateChange;
+
+
+
+/*=======================================================================================
+| STRUCTURE DEFINITIONS |
+========================================================================================*/
+/**
+ * MMCamcorder Gstreamer Element
+ */
+typedef struct {
+ unsigned int id; /**< Gstreamer piplinem element name */
+ GstElement *gst; /**< Gstreamer element */
+} _MMCamcorderGstElement;
+
+/**
+ * MMCamcorder information for KPI measurement
+ */
+typedef struct {
+ int current_fps; /**< current fps of this second */
+ int average_fps; /**< average fps */
+ unsigned int video_framecount; /**< total number of video frame */
+ unsigned int last_framecount; /**< total number of video frame in last measurement */
+ struct timeval init_video_time; /**< time when start to measure */
+ struct timeval last_video_time; /**< last measurement time */
+} _MMCamcorderKPIMeasure;
+
+/**
+ * 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 *state_lock; /**< Mutex (for state change) */
+ GMutex *gst_state_lock; /**< Mutex (for 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) */
+} _MMCamcorderMTSafe;
+
+/**
+ * MMCamcorder information for command loop
+ */
+typedef struct {
+ pthread_t pCommandThread; /**< Command loop handle */
+ GQueue *cmd_queue; /**< Queue for Command loop */
+ sem_t sema; /**< Semaphore for Command loop */
+} _MMCamcorderCommand;
+
+/**
+ * MMCamcorder command information
+ */
+typedef struct {
+ MMHandleType handle; /**< camcorder handle */
+ _MMCamcorderCommandType type; /**< Type of command */
+} __MMCamcorderCmdInfo;
+
+/**
+ * MMCamcorder Sub Context
+ */
+typedef struct {
+ bool isMaxsizePausing; /**< Because of size limit, pipeline is paused. */
+ bool isMaxtimePausing; /**< Because of time limit, pipeline is paused. */
+ int element_num; /**< count of element */
+ int cam_stability_count; /**< camsensor stability count. the count of frame will drop */
+ GstClockTime pipeline_time; /**< current time of Gstreamer Pipeline */
+ GstClockTime pause_time; /** amount of time while pipeline is in PAUSE state.*/
+ GstClockTime stillshot_time; /** pipeline time of capturing moment*/
+ gboolean is_slow;
+ gboolean error_occurs;
+ gboolean ferror_send; /** file write/seek error **/
+ guint ferror_count; /** file write/seek error count **/
+ GstClockTime previous_slot_time;
+ int display_interval; /** This value is set as 'GST_SECOND / display FPS' */
+ gboolean bget_eos; /** Whether getting EOS */
+ gboolean bencbin_capture; /** Use Encodebin for capturing */
+ gboolean now_continuous_af; /** whether continuous af starts */
+
+ /* For dropping video frame when start recording */
+ int drop_vframe; /**< When this value is bigger than zero and pass_first_vframe is zero, MSL will drop video frame though cam_stability count is bigger then zero. */
+ int pass_first_vframe; /**< When this value is bigger than zero, MSL won't drop video frame though "drop_vframe" is bigger then zero. */
+
+ /* INI information */
+ unsigned int fourcc; /**< Get fourcc value of camera INI file */
+ void *info; /**< extra information for camcorder */
+
+ _MMCamcorderGstElement *element; /**< array of Gstreamer element */
+ _MMCamcorderKPIMeasure kpi; /**< information related with performance measurement */
+
+ type_element *VideosinkElement; /**< configure data of videosink element */
+ gboolean SensorEncodedCapture; /**< whether camera sensor support encoded image capture */
+ gboolean internal_encode; /**< whether use internal encoding function */
+} _MMCamcorderSubContext;
+
+/**
+ * _MMCamcorderContext
+ */
+typedef struct mmf_camcorder {
+ /* information */
+ int type; /**< mmcamcorder_mode_type */
+ int state; /**< state of camcorder */
+ int target_state; /**< Target state that want to set. This is a flag that
+ * stands for async state changing. If this value differ from state,
+ * it means state is changing now asychronously. */
+
+ /* handles */
+ MMHandleType attributes; /**< Attribute handle */
+ _MMCamcorderSubContext *sub_context; /**< sub context */
+ mm_exif_info_t *exif_info; /**< EXIF */
+ GList *buffer_probes; /**< a list of buffer probe handle */
+ GList *event_probes; /**< a list of event probe handle */
+ GList *data_probes; /**< a list of data probe handle */
+ GList *signals; /**< a list of signal handle */
+ GList *msg_data; /**< a list of msg data */
+ camera_conf *conf_main; /**< Camera configure Main structure */
+ camera_conf *conf_ctrl; /**< Camera configure Control structure */
+ int asm_handle; /**< Audio session manager handle */
+ guint pipeline_cb_event_id; /**< Event source ID of pipeline message callback */
+ guint setting_event_id; /**< Event source ID of attributes setting to sensor */
+ SOUND_INFO snd_info; /**< Sound handle for multishot capture */
+
+ /* callback handlers */
+ MMMessageCallback msg_cb; /**< message callback */
+ void *msg_cb_param; /**< message callback parameter */
+ mm_camcorder_video_stream_callback vstream_cb; /**< Video stream callback */
+ void *vstream_cb_param; /**< Video stream callback parameter */
+ mm_camcorder_audio_stream_callback astream_cb; /**< Audio stream callback */
+ void *astream_cb_param; /**< Audio stream callback parameter */
+ mm_camcorder_video_capture_callback vcapture_cb; /**< Video capture callback */
+ void *vcapture_cb_param; /**< Video capture callback parameter */
+ int (*command)(MMHandleType, int); /**< camcorder's command */
+
+ /* etc */
+ _MMCamcorderMTSafe mtsafe; /**< Thread safe */
+ _MMCamcorderCommand cmd; /**< information for command loop */
+ int sync_state_change; /**< Change framework state synchronously */
+ int quick_device_close;
+ int state_change_by_system; /**< MSL changes its state by itself because of system(ASM,MDM..) **/
+ int asm_event_code; /**< event code of audio session manager */
+ pthread_mutex_t sound_lock; /**< Capture sound mutex */
+ pthread_cond_t sound_cond; /**< Capture sound cond */
+ int use_zero_copy_format; /**< Whether use zero copy format for camera input */
+
+ int reserved[4]; /**< reserved */
+} mmf_camcorder_t;
+
+/*=======================================================================================
+| EXTERN GLOBAL VARIABLE |
+========================================================================================*/
+
+/*=======================================================================================
+| GLOBAL FUNCTION PROTOTYPES |
+========================================================================================*/
+/**
+ * This function creates camcorder for capturing still image and recording.
+ *
+ * @param[out] handle Specifies the camcorder handle
+ * @param[in] info Preset information of camcorder
+ * @return This function returns zero on success, or negative value with error code.
+ * @remarks When this function calls successfully, camcorder handle will be filled with a @n
+ * valid value and the state of the camcorder will become MM_CAMCORDER_STATE_NULL.@n
+ * Note that it's not ready to working camcorder. @n
+ * You should call mmcamcorder_realize before starting camcorder.
+ * @see _mmcamcorder_create
+ */
+int _mmcamcorder_create(MMHandleType *handle, MMCamPreset *info);
+
+/**
+ * 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.
+ * @see _mmcamcorder_create
+ */
+int _mmcamcorder_destroy(MMHandleType hcamcorder);
+
+/**
+ * This function allocates memory for camcorder.
+ *
+ * @param[in] hcamcorder Specifies the camcorder handle
+ * @return This function returns zero on success, or negative value with error code.
+ * @remarks This function can be called successfully when current state is MM_CAMCORDER_STATE_NULL @n
+ * and the state of the camcorder will become MM_CAMCORDER_STATE_READY. @n
+ * Otherwise, this function will return MM_ERROR_CAMCORDER_INVALID_CONDITION.
+ * @see _mmcamcorder_unrealize
+ * @pre MM_CAMCORDER_STATE_NULL
+ * @post MM_CAMCORDER_STATE_READY
+ */
+int _mmcamcorder_realize(MMHandleType hcamcorder);
+
+/**
+ * This function free allocated memory for camcorder.
+ *
+ * @param[in] hcamcorder Specifies the camcorder handle
+ * @return This function returns zero on success, or negative value with error code.
+ * @remarks This function release all resources which are allocated for the camcorder engine.@n
+ * This function can be called successfully when current state is MM_CAMCORDER_STATE_READY and @n
+ * the state of the camcorder will become MM_CAMCORDER_STATE_NULL. @n
+ * Otherwise, this function will return MM_ERROR_CAMCORDER_INVALID_CONDITION.
+ * @see _mmcamcorder_realize
+ * @pre MM_CAMCORDER_STATE_READY
+ * @post MM_CAMCORDER_STATE_NULL
+ */
+int _mmcamcorder_unrealize(MMHandleType hcamcorder);
+
+/**
+ * This function is to start previewing.
+ *
+ * @param[in] hcamcorder Specifies the camcorder handle
+ * @return This function returns zero on success, or negative value with error code.
+ * @remarks This function can be called successfully when current state is MM_CAMCORDER_STATE_READY and @n
+ * the state of the camcorder will become MM_CAMCORDER_STATE_PREPARE. @n
+ * Otherwise, this function will return MM_ERROR_CAMCORDER_INVALID_CONDITION.
+ * @see _mmcamcorder_stop
+ */
+int _mmcamcorder_start(MMHandleType hcamcorder);
+
+/**
+ * This function is to stop previewing.
+ *
+ * @param[in] hcamcorder Specifies the camcorder handle
+ * @return This function returns zero on success, or negative value with error code.
+ * @remarks This function can be called successfully when current state is MM_CAMCORDER_STATE_PREPARE and @n
+ * the state of the camcorder will become MM_CAMCORDER_STATE_READY.@n
+ * Otherwise, this function will return MM_ERROR_CAMCORDER_INVALID_CONDITION.
+ * @see _mmcamcorder_start
+ */
+int _mmcamcorder_stop(MMHandleType hcamcorder);
+
+/**
+ * This function to start capturing of still images.
+ *
+ * @param[in] hcamcorder Specifies the camcorder handle.
+ * @return This function returns zero on success, or negative value with error code.
+ * @remarks This function can be called successfully when current state is MM_CAMCORDER_STATE_PREPARE and @n
+ * the state of the camcorder will become MM_CAMCORDER_STATE_CAPTURING. @n
+ * Otherwise, this function will return MM_ERROR_CAMCORDER_INVALID_CONDITION.
+ * @see _mmcamcorder_capture_stop
+ */
+int _mmcamcorder_capture_start(MMHandleType hcamcorder);
+
+/**
+ * This function is to stop capturing still images.
+ *
+ * @param[in] hcamcorder Specifies the camcorder handle
+ * @return This function returns zero on success, or negative value with error code.
+ * @remarks This function can be called successfully when current state is MM_CAMCORDER_STATE_CAPTURING and @n
+ * the state of the camcorder will become MM_CAMCORDER_STATE_PREPARE. @n
+ * Otherwise, this function will return MM_ERROR_CAMCORDER_INVALID_CONDITION.
+ * @see _mmcamcorder_capture_start
+ */
+int _mmcamcorder_capture_stop(MMHandleType hcamcorder);
+
+/**
+ * This function is to start video and audio recording.
+ *
+ * @param[in] hcamcorder Specifies the camcorder handle
+ * @return This function returns zero on success, or negative value with error code.
+ * @remarks This function can be called successfully when current state is @n
+ * MM_CAMCORDER_STATE_PREPARE or MM_CAMCORDER_STATE_PAUSED and @n
+ * the state of the camcorder will become MM_CAMCORDER_STATE_RECORDING.@n
+ * Otherwise, this function will return MM_ERROR_CAMCORDER_INVALID_CONDITION.
+ * @see _mmcamcorder_pause
+ */
+int _mmcamcorder_record(MMHandleType hcamcorder);
+
+/**
+ * This function is to pause video and audio recording
+ *
+ * @param[in] hcamcorder Specifies the camcorder handle
+ * @return This function returns zero on success, or negative value with error code.
+ * @remarks This function can be called successfully when current state is MM_CAMCORDER_STATE_RECORDING and @n
+ * the state of the camcorder will become MM_CAMCORDER_STATE_PAUSED.@n
+ * Otherwise, this function will return MM_ERROR_CAMCORDER_INVALID_CONDITION.@n
+ * @see _mmcamcorder_record
+ */
+int _mmcamcorder_pause(MMHandleType hcamcorder);
+
+/**
+ * This function is to stop video and audio recording and save results.
+ *
+ * @param[in] hcamcorder Specifies the camcorder handle
+ * @return This function returns zero on success, or negative value with error code.
+ * @remarks This function can be called successfully when current state is @n
+ * MM_CAMCORDER_STATE_PAUSED or MM_CAMCORDER_STATE_RECORDING and @n
+ * the state of the camcorder will become MM_CAMCORDER_STATE_PREPARE. @n
+ * Otherwise, this function will return MM_ERROR_CAMCORDER_INVALID_CONDITION
+ * @see _mmcamcorder_cancel
+ */
+int _mmcamcorder_commit(MMHandleType hcamcorder);
+
+/**
+ * This function is to stop video and audio recording and do not save results.
+ *
+ * @param[in] hcamcorder Specifies the camcorder handle
+ * @return This function returns zero on success, or negative value with error code.
+ * @remarks This function can be called successfully when current state is @n
+ * MM_CAMCORDER_STATE_PAUSED or MM_CAMCORDER_STATE_RECORDING and @n
+ * the state of the camcorder will become MM_CAMCORDER_STATE_PREPARE. @n
+ * Otherwise, this function will return MM_ERROR_CAMCORDER_INVALID_CONDITION.
+ * @see _mmcamcorder_commit
+ */
+int _mmcamcorder_cancel(MMHandleType hcamcorder);
+
+/**
+ * This function calls after commiting action finished asynchronously.
+ * In this function, remaining process , such as state change, happens.
+ *
+ * @param[in] hcamcorder Specifies the camcorder handle
+ * @return This function returns zero on success, or negative value with error code.
+ * @remarks This function can be called successfully when current state is @n
+ * MM_CAMCORDER_STATE_PAUSED or MM_CAMCORDER_STATE_RECORDING and @n
+ * the state of the camcorder will become MM_CAMCORDER_STATE_PREPARE. @n
+ * Otherwise, this function will return MM_ERROR_CAMCORDER_INVALID_CONDITION.
+ * @see _mmcamcorder_commit
+ */
+int _mmcamcorder_commit_async_end(MMHandleType hcamcorder);
+
+/**
+ * This function is to set callback for receiving messages from camcorder.
+ *
+ * @param[in] hcamcorder Specifies the camcorder handle
+ * @param[in] callback Specifies the function pointer of callback function
+ * @param[in] user_data Specifies the user poiner for passing to callback function
+ *
+ * @return This function returns zero on success, or negative value with error code.
+ * @remarks typedef bool (*mm_message_callback) (int msg, mm_messageType *param, void *user_param);@n
+ * @n
+ * typedef union @n
+ * { @n
+ * int code; @n
+ * struct @n
+ * { @n
+ * int total; @n
+ * int elapsed; @n
+ * } time; @n
+ * struct @n
+ * { @n
+ * int previous; @n
+ * int current; @n
+ * } state; @n
+ * } mm_message_type; @n
+ * @n
+ * If a message value for mm_message_callback is MM_MESSAGE_STATE_CHANGED, @n
+ * state value in mm_message_type will be a mmcamcorder_state_type enum value;@n
+ * @n
+ * If a message value for mm_message_callback is MM_MESSAGE_ERROR, @n
+ * the code value in mm_message_type will be a mmplayer_error_type enum value;
+ *
+ * @see mm_message_type, mmcamcorder_state_type, mmcamcorder_error_type
+ */
+int _mmcamcorder_set_message_callback(MMHandleType hcamcorder,
+ MMMessageCallback callback,
+ void *user_data);
+
+/**
+ * This function is to set callback for video stream.
+ *
+ * @param[in] hcamcorder Specifies the camcorder handle
+ * @param[in] callback Specifies the function pointer of callback function
+ * @param[in] user_data Specifies the user poiner for passing to callback function
+ *
+ * @return This function returns zero on success, or negative value with error code.
+ * @see mmcamcorder_error_type
+ */
+int _mmcamcorder_set_video_stream_callback(MMHandleType hcamcorder,
+ mm_camcorder_video_stream_callback callback,
+ void *user_data);
+
+/**
+ * This function is to set callback for audio stream.
+ *
+ * @param[in] hcamcorder Specifies the camcorder handle
+ * @param[in] callback Specifies the function pointer of callback function
+ * @param[in] user_data Specifies the user poiner for passing to callback function
+ *
+ * @return This function returns zero on success, or negative value with error code.
+ * @see mmcamcorder_error_type
+ */
+int _mmcamcorder_set_audio_stream_callback(MMHandleType handle,
+ mm_camcorder_audio_stream_callback callback,
+ void *user_data);
+
+/**
+ * This function is to set callback for video capture.
+ *
+ * @param[in] hcamcorder Specifies the camcorder handle
+ * @param[in] callback Specifies the function pointer of callback function
+ * @param[in] user_data Specifies the user poiner for passing to callback function
+ *
+ * @return This function returns zero on success, or negative value with error code.
+ * @see mmcamcorder_error_type
+ */
+int _mmcamcorder_set_video_capture_callback(MMHandleType hcamcorder,
+ mm_camcorder_video_capture_callback callback,
+ void *user_data);
+
+/**
+ * This function returns current state of camcorder, or negative value with error code.
+ *
+ * @param[in] hcamcorder Specifies the camcorder handle.
+ * @return This function returns current state of camcorder, or negative value with error code.
+ * @see mmcamcorder_state_type
+ */
+int _mmcamcorder_get_current_state(MMHandleType hcamcorder);
+
+int _mmcamcorder_init_focusing(MMHandleType handle);
+int _mmcamcorder_adjust_focus(MMHandleType handle, int direction);
+int _mmcamcorder_adjust_manual_focus(MMHandleType handle, int direction);
+int _mmcamcorder_adjust_auto_focus(MMHandleType handle);
+int _mmcamcorder_stop_focusing(MMHandleType handle);
+
+/**
+ * This function gets current state of camcorder.
+ *
+ * @param void
+ * @return This function returns state of current camcorder context
+ * @remarks
+ * @see _mmcamcorder_set_state()
+ *
+ */
+int _mmcamcorder_streamer_init(void);
+
+/**
+ * This function gets current state of camcorder.
+ *
+ * @param void
+ * @return This function returns state of current camcorder context
+ * @remarks
+ * @see _mmcamcorder_set_state()
+ *
+ */
+int _mmcamcorder_display_init(void);
+
+/**
+ * This function gets current state of camcorder.
+ *
+ * @param[in] handle Handle of camcorder context.
+ * @return This function returns state of current camcorder context
+ * @remarks
+ * @see _mmcamcorder_set_state()
+ *
+ */
+int _mmcamcorder_get_state(MMHandleType handle);
+
+/**
+ * This function sets new state of camcorder.
+ *
+ * @param[in] handle Handle of camcorder context.
+ * @param[in] state setting state value of camcorder.
+ * @return void
+ * @remarks
+ * @see _mmcamcorder_get_state()
+ *
+ */
+void _mmcamcorder_set_state(MMHandleType handle, int state);
+
+/**
+ * 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.
+ * @return This function returns asynchrnous state.
+ * @remarks
+ * @see _mmcamcorder_set_async_state()
+ *
+ */
+int _mmcamcorder_get_async_state(MMHandleType handle);
+
+/**
+ * This function sets new target state of camcorder.
+ *
+ * @param[in] handle Handle of camcorder context.
+ * @param[in] target_state setting target_state value of camcorder.
+ * @return This function returns zero on success, or negative value with error code.
+ * @remarks
+ * @see _mmcamcorder_get_async_state(), _mmcamcorder_set_async_cancel()
+ *
+ */
+int _mmcamcorder_set_async_state(MMHandleType handle, int target_state);
+
+/**
+ * This function sets new target state of camcorder.
+ *
+ * @param[in] handle Handle of camcorder context.
+ * @return gboolean
+ * @remarks
+ * @see _mmcamcorder_set_async_cancel()
+ *
+ */
+gboolean _mmcamcorder_set_async_cancel(MMHandleType handle);
+
+/**
+ * Check whether camcorder changes its state now.
+ *
+ * @param[in] handle Handle of camcorder context.
+ * @return gboolean
+ * @remarks
+ * @see _mmcamcorder_set_async_state(), _mmcamcorder_set_async_cancel()
+ *
+ */
+gboolean _mmcamcorder_is_state_changing(MMHandleType handle);
+
+/**
+ * This function allocates structure of subsidiary attributes.
+ *
+ * @param[in] type Allocation type of camcorder context.
+ * @return This function returns structure pointer on success, NULL value on failure.
+ * @remarks
+ * @see _mmcamcorder_dealloc_subcontext()
+ *
+ */
+_MMCamcorderSubContext *_mmcamcorder_alloc_subcontext(int type);
+
+/**
+ * This function releases structure of subsidiary attributes.
+ *
+ * @param[in] sc Handle of camcorder subcontext.
+ * @return void
+ * @remarks
+ * @see _mmcamcorder_alloc_subcontext()
+ *
+ */
+void _mmcamcorder_dealloc_subcontext(_MMCamcorderSubContext *sc);
+
+/**
+ * This function sets command function according to the type.
+ *
+ * @param[in] handle Handle of camcorder context.
+ * @param[in] type Allocation type of camcorder context.
+ * @return This function returns MM_ERROR_NONE on success, or other values with error code.
+ * @remarks
+ * @see __mmcamcorder_video_command(), __mmcamcorder_audio_command(), __mmcamcorder_image_command()
+ *
+ */
+int _mmcamcorder_set_functions(MMHandleType handle, int type);
+
+/**
+ * This function is callback function of main pipeline.
+ * Once this function is registered with certain pipeline using gst_bus_add_watch(),
+ * this callback will be called every time when there is upcomming message from pipeline.
+ * Basically, this function is used as error handling function, now.
+ *
+ * @param[in] bus pointer of buf that called this function.
+ * @param[in] message callback message from pipeline.
+ * @param[in] data user data.
+ * @return This function returns true on success, or false value with error
+ * @remarks
+ * @see __mmcamcorder_create_preview_pipeline()
+ *
+ */
+gboolean _mmcamcorder_pipeline_cb_message(GstBus *bus, GstMessage *message, gpointer data);
+
+/**
+ * This function create main pipeline according to type.
+ *
+ * @param[in] handle Handle of camcorder context.
+ * @param[in] type Allocation type of camcorder context.
+ * @return This function returns zero on success, or negative value with error code.
+ * @remarks
+ * @see _mmcamcorder_destroy_pipeline()
+ *
+ */
+int _mmcamcorder_create_pipeline(MMHandleType handle, int type);
+
+/**
+ * This function release all element of main pipeline according to type.
+ *
+ * @param[in] handle Handle of camcorder context.
+ * @param[in] type Allocation type of camcorder context.
+ * @return void
+ * @remarks
+ * @see _mmcamcorder_create_pipeline()
+ *
+ */
+void _mmcamcorder_destroy_pipeline(MMHandleType handle, int type);
+
+/**
+ * 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.
+ *
+ * @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
+ *
+ */
+int _mmcamcorder_gst_set_state(MMHandleType handle, GstElement *pipeline, GstState target_state);
+
+/**
+ * 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
+ *
+ */
+int _mmcamcorder_gst_set_state_async(MMHandleType handle, GstElement *pipeline, GstState target_state);
+
+/* For xvimagesink */
+GstBusSyncReply __mmcamcorder_sync_callback(GstBus *bus, GstMessage *message, gulong data);
+
+/* For querying capabilities */
+int _mmcamcorder_read_vidsrc_info(int videodevidx, camera_conf **configure_info);
+
+/* for performance check */
+void _mmcamcorder_video_current_framerate_init(MMHandleType handle);
+int _mmcamcorder_video_current_framerate(MMHandleType handle);
+int _mmcamcorder_video_average_framerate(MMHandleType handle);
+
+/* command */
+void _mmcamcorder_delete_command_info(__MMCamcorderCmdInfo *cmdinfo);
+int _mmcamcorder_create_command_loop(MMHandleType handle);
+int _mmcamcorder_destroy_command_loop(MMHandleType handle);
+int _mmcamcorder_append_command(MMHandleType handle, __MMCamcorderCmdInfo *info);
+int _mmcamcorder_append_simple_command(MMHandleType handle, _MMCamcorderCommandType type);
+void *_mmcamcorder_command_loop_thread(void *arg);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __MM_CAMCORDER_INTERNAL_H__ */
diff --git a/src/include/mm_camcorder_platform.h b/src/include/mm_camcorder_platform.h
new file mode 100644
index 0000000..171a9f4
--- /dev/null
+++ b/src/include/mm_camcorder_platform.h
@@ -0,0 +1,223 @@
+/*
+ * libmm-camcorder
+ *
+ * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: Jeongmo Yang <jm80.yang@samsung.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef __MM_CAMCORDER_PLATFORM_H__
+#define __MM_CAMCORDER_PLATFORM_H__
+
+/*=======================================================================================
+| INCLUDE FILES |
+========================================================================================*/
+#include <gst/gst.h>
+#include <mm_types.h>
+
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*=======================================================================================
+| GLOBAL DEFINITIONS AND DECLARATIONS FOR CAMCORDER |
+========================================================================================*/
+
+/*=======================================================================================
+| MACRO DEFINITIONS |
+========================================================================================*/
+/* CAMERA DEFINED VALUE */
+/* WQSXGA (5M) */
+#define MMF_CAM_W2560 2560
+#define MMF_CAM_H1920 1920
+
+/* QXGA (3M) */
+#define MMF_CAM_W2048 2048
+#define MMF_CAM_H1536 1536
+
+/* UXGA (2M) */
+#define MMF_CAM_W1600 1600
+#define MMF_CAM_H1200 1200
+
+/* WSXGA (1M) */
+#define MMF_CAM_W1280 1280
+#define MMF_CAM_H960 960
+
+/* SVGA */
+#define MMF_CAM_W800 800
+#define MMF_CAM_H600 600
+
+/* WVGA */
+#define MMF_CAM_W800 800
+#define MMF_CAM_H480 480
+
+/* VGA */
+#define MMF_CAM_W640 640
+#define MMF_CAM_H480 480
+
+/* CIF */
+#define MMF_CAM_W352 352
+#define MMF_CAM_H288 288
+
+/* QVGA */
+#define MMF_CAM_W320 320
+#define MMF_CAM_H240 240
+
+/* QCIF */
+#define MMF_CAM_W176 176
+#define MMF_CAM_H144 144
+
+/* QQVGA */
+#define MMF_CAM_W160 160
+#define MMF_CAM_H120 120
+
+/* QQCIF */
+#define MMF_CAM_W88 88
+#define MMF_CAM_H72 72
+
+/* WQVGA */
+#define MMF_CAM_W400 400
+#define MMF_CAM_H240 240
+
+/* RQVGA */
+#define MMF_CAM_W240 240
+#define MMF_CAM_H320 320
+
+/* RWQVGA */
+#define MMF_CAM_W240 240
+#define MMF_CAM_H400 400
+
+/* Non-specified */
+#define MMF_CAM_W400 400
+#define MMF_CAM_H300 300
+
+/* HD */
+#define MMF_CAM_W1280 1280
+#define MMF_CAM_H720 720
+
+//Zero
+#define MMF_CAM_W0 0
+#define MMF_CAM_H0 0
+
+
+/* Capture related */
+/* High quality resolution */
+#define MMFCAMCORDER_HIGHQUALITY_WIDTH MMF_CAM_W0 /* High quality resolution is not needed, */
+#define MMFCAMCORDER_HIGHQUALITY_HEIGHT MMF_CAM_H0 /* because camsensor has a JPEG encoder inside */
+
+/* VGA (1 : 0.75) */
+#define MMF_CROP_VGA_LEFT 0
+#define MMF_CROP_VGA_RIGHT 0
+#define MMF_CROP_VGA_TOP 0
+#define MMF_CROP_VGA_BOTTOM 0
+
+/* QCIF (1 : 0.818) */
+#define MMF_CROP_CIF_LEFT 68 /* little bit confusing */
+#define MMF_CROP_CIF_RIGHT 68
+#define MMF_CROP_CIF_TOP 0
+#define MMF_CROP_CIF_BOTTOM 0
+
+/* Camera etc */
+#define _MMCAMCORDER_CAMSTABLE_COUNT 0 /* stablize count of camsensor */
+#define _MMCAMCORDER_MINIMUM_SPACE (512*1024) /* byte */
+#define _MMCAMCORDER_MMS_MARGIN_SPACE (512) /* byte */
+
+/**
+ * Default None value for camera sensor enumeration.
+ */
+#define _MMCAMCORDER_SENSOR_ENUM_NONE -255
+
+
+/*=======================================================================================
+| ENUM DEFINITIONS |
+========================================================================================*/
+/**
+ * Enumerations for attribute converting.
+ */
+typedef enum {
+ MM_CAMCONVERT_TYPE_INT,
+ MM_CAMCONVERT_TYPE_INT_RANGE,
+ MM_CAMCONVERT_TYPE_INT_ARRAY,
+ MM_CAMCONVERT_TYPE_INT_PAIR_ARRAY,
+ MM_CAMCONVERT_TYPE_STRING,
+/*
+ MM_CAMCONVERT_TYPE_DOUBLE,
+ MM_CAMCONVERT_TYPE_DOUBLE_PAIR,
+*/
+ MM_CAMCONVERT_TYPE_USER, /* user define */
+} MMCamConvertingType;
+
+/*=======================================================================================
+| STRUCTURE DEFINITIONS |
+========================================================================================*/
+/**
+ * Structure for enumeration converting.
+ */
+typedef struct {
+ int total_enum_num; /**< total enumeration count */
+ int *enum_arr; /**< enumeration array */
+ int category; /**< category */
+ char *keyword; /**< keyword array */
+} _MMCamcorderEnumConvert;
+
+
+/**
+ * Converting table of camera configuration.
+ */
+typedef struct {
+ int type; /**< type of configuration */
+ int category; /**< category of configuration */
+ int attr_idx; /**< attribute index */
+ int attr_idx_pair; /**< attribute index (only for 'pair' type) */
+ char *keyword;
+ MMCamConvertingType conv_type;
+ _MMCamcorderEnumConvert *enum_convert; /**< converting value table */
+} _MMCamcorderInfoConverting;
+
+/*=======================================================================================
+| CONSTANT DEFINITIONS |
+========================================================================================*/
+
+/*=======================================================================================
+| STATIC VARIABLES |
+========================================================================================*/
+
+/*=======================================================================================
+| EXTERN GLOBAL VARIABLE |
+========================================================================================*/
+
+/*=======================================================================================
+| GLOBAL FUNCTION PROTOTYPES |
+========================================================================================*/
+int _mmcamcorder_convert_msl_to_sensor(int attr_idx, int mslval);
+int _mmcamcorder_convert_sensor_to_msl(int attr_idx, int sensval);
+
+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_convert_brightness(int mslVal);
+int _mmcamcorder_convert_whitebalance(int mslVal);
+int _mmcamcorder_convert_colortone(int mslVal);
+double _mmcamcorder_convert_volume(int mslVal);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __MM_CAMCORDER_PLATFORM_H__ */
diff --git a/src/include/mm_camcorder_sound.h b/src/include/mm_camcorder_sound.h
new file mode 100644
index 0000000..199f27c
--- /dev/null
+++ b/src/include/mm_camcorder_sound.h
@@ -0,0 +1,103 @@
+/*
+ * libmm-camcorder
+ *
+ * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: Jeongmo Yang <jm80.yang@samsung.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef __MM_CAMCORDER_SOUND_H__
+#define __MM_CAMCORDER_SOUND_H__
+
+/*=======================================================================================
+| INCLUDE FILES |
+========================================================================================*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*=======================================================================================
+| GLOBAL DEFINITIONS AND DECLARATIONS FOR CAMCORDER |
+========================================================================================*/
+
+/*=======================================================================================
+| MACRO DEFINITIONS |
+========================================================================================*/
+#define _MMCAMCORDER_FILEPATH_CAPTURE_SND "/usr/share/sounds/mm-camcorder/capture_shutter_01.wav"
+#define _MMCAMCORDER_FILEPATH_CAPTURE2_SND "/usr/share/sounds/mm-camcorder/capture_shutter_02.wav"
+#define _MMCAMCORDER_FILEPATH_REC_START_SND "/usr/share/sounds/mm-camcorder/recording_start_01.wav"
+#define _MMCAMCORDER_FILEPATH_REC_STOP_SND "/usr/share/sounds/mm-camcorder/recording_stop_01.wav"
+#define _MMCAMCORDER_FILEPATH_AF_SUCCEED_SND "/usr/share/sounds/mm-camcorder/af_succeed.wav"
+#define _MMCAMCORDER_FILEPATH_AF_FAIL_SND "/usr/share/sounds/mm-camcorder/af_fail.wav"
+#define _MMCAMCORDER_FILEPATH_NO_SND "/usr/share/sounds/mm-camcorder/no_sound.wav"
+
+/*=======================================================================================
+| ENUM DEFINITIONS |
+========================================================================================*/
+typedef enum {
+ _MMCAMCORDER_SOUND_STATE_NONE,
+ _MMCAMCORDER_SOUND_STATE_INIT,
+ _MMCAMCORDER_SOUND_STATE_PREPARE,
+ _MMCAMCORDER_SOUND_STATE_PLAYING,
+} _MMCamcorderSoundState;
+
+/*=======================================================================================
+| STRUCTURE DEFINITIONS |
+========================================================================================*/
+/**
+ * Structure of sound info
+ */
+typedef struct __SOUND_INFO {
+ SF_INFO sfinfo;
+ SNDFILE *infile;
+ short *pcm_buf;
+ int pcm_size;
+ char *filename;
+
+ MMSoundPcmHandle_t handle;
+
+ int thread_run;
+ pthread_t thread;
+ pthread_mutex_t play_mutex;
+ pthread_cond_t play_cond;
+ pthread_mutex_t open_mutex;
+ pthread_cond_t open_cond;
+ system_audio_route_t route_policy_backup;
+
+ _MMCamcorderSoundState state;
+} SOUND_INFO;
+
+/*=======================================================================================
+| CONSTANT DEFINITIONS |
+========================================================================================*/
+
+
+/*=======================================================================================
+| GLOBAL FUNCTION PROTOTYPES |
+========================================================================================*/
+gboolean _mmcamcorder_sound_init(MMHandleType handle, char *filename);
+gboolean _mmcamcorder_sound_prepare(MMHandleType handle);
+gboolean _mmcamcorder_sound_play(MMHandleType handle);
+gboolean _mmcamcorder_sound_finalize(MMHandleType handle);
+
+void _mmcamcorder_sound_solo_play(MMHandleType handle, const char *filepath, gboolean sync);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __MM_CAMCORDER_SOUND_H__ */
diff --git a/src/include/mm_camcorder_stillshot.h b/src/include/mm_camcorder_stillshot.h
new file mode 100644
index 0000000..525237a
--- /dev/null
+++ b/src/include/mm_camcorder_stillshot.h
@@ -0,0 +1,134 @@
+/*
+ * libmm-camcorder
+ *
+ * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: Jeongmo Yang <jm80.yang@samsung.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef __MM_CAMCORDER_STILLSHOT_H__
+#define __MM_CAMCORDER_STILLSHOT_H__
+
+/*=======================================================================================
+| INCLUDE FILES |
+========================================================================================*/
+#include <gst/gst.h>
+#include <mm_types.h>
+#include <mm_sound.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*=======================================================================================
+| GLOBAL DEFINITIONS AND DECLARATIONS FOR CAMCORDER |
+========================================================================================*/
+
+/*=======================================================================================
+| MACRO DEFINITIONS |
+========================================================================================*/
+#define _MMCAMCORDER_CAPTURE_STOP_CHECK_INTERVAL 5000
+#define _MMCAMCORDER_CAPTURE_STOP_CHECK_COUNT 600
+#define _MNOTE_VALUE_NONE 0
+
+/*=======================================================================================
+| ENUM DEFINITIONS |
+========================================================================================*/
+
+/*=======================================================================================
+| STRUCTURE DEFINITIONS |
+========================================================================================*/
+/**
+ * MMCamcorder information for image(preview/capture) mode
+ */
+typedef struct {
+ int type; /**< Still-shot/Multi-shot */
+ int count; /**< Multi-shot capture count */
+ int capture_cur_count; /**< Multi-shot capture current count */
+ int capture_send_count; /**< Multi-shot capture send count */
+ unsigned long long next_shot_time; /**< next still capture time */
+ gboolean multi_shot_stop; /**< Multi-shot stop flag */
+ gboolean capturing; /**< whether MSL is on capturing */
+ gboolean resolution_change; /**< whether on resolution changing for capturing. After changing to capture resolution, it sets to FALSE again. */
+ int width; /**< Width of capture image */
+ int height; /**< Height of capture image */
+ int interval; /**< Capture interval */
+} _MMCamcorderImageInfo;
+
+/*=======================================================================================
+| CONSTANT DEFINITIONS |
+========================================================================================*/
+
+/*=======================================================================================
+| STATIC VARIABLES |
+========================================================================================*/
+
+/*=======================================================================================
+| EXTERN GLOBAL VARIABLE |
+========================================================================================*/
+
+/*=======================================================================================
+| GLOBAL FUNCTION PROTOTYPES |
+========================================================================================*/
+/**
+ * This function add still shot bin to main pipeline.
+ * When application creates initial pipeline, there are only bins for preview.
+ * If application wants to add stil shot function, bins for stillshot should be added.
+ *
+ * @param[in] handle Handle of camcorder context.
+ * @return This function returns MM_ERROR_NONE on success, or the other values on error.
+ * @remarks
+ * @see __mmcamcorder_create_preview_pipeline()
+ */
+int _mmcamcorder_add_stillshot_pipeline(MMHandleType handle);
+
+/**
+ * This function remove still shot bin from main pipeline.
+ *
+ * @param[in] handle Handle of camcorder context.
+ * @return This function returns MM_ERROR_NONE on success, or the other values on error.
+ * @remarks
+ * @see __mmcamcorder_create_preview_pipeline(), __mmcamcorder_add_stillshot_pipeline()
+ */
+int _mmcamcorder_remove_stillshot_pipeline(MMHandleType handle);
+
+/**
+ * This function destroy image pipeline.
+ *
+ * @param[in] handle Handle of camcorder context.
+ * @return void
+ * @remarks
+ * @see _mmcamcorder_destroy_pipeline()
+ *
+ */
+void _mmcamcorder_destroy_image_pipeline(MMHandleType handle);
+int _mmcamcorder_image_command(MMHandleType handle, int command);
+int _mmcamcorder_set_resize_property(MMHandleType handle, int capture_width, int capture_height);
+
+/* Function for capture */
+int __mmcamcorder_set_exif_basic_info(MMHandleType handle);
+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);
+gboolean __mmcamcorder_capture_save_exifinfo(MMHandleType handle, MMCamcorderCaptureDataType *original, MMCamcorderCaptureDataType *thumbnail);
+gboolean __mmcamcorder_capture_send_msg(MMHandleType handle, int type, int count);
+gboolean __mmcamcorder_set_jpeg_data(MMHandleType handle, MMCamcorderCaptureDataType *dest, MMCamcorderCaptureDataType *thumbnail);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __MM_CAMCORDER_STILLSHOT_H__ */
diff --git a/src/include/mm_camcorder_util.h b/src/include/mm_camcorder_util.h
new file mode 100644
index 0000000..c9df689
--- /dev/null
+++ b/src/include/mm_camcorder_util.h
@@ -0,0 +1,246 @@
+/*
+ * libmm-camcorder
+ *
+ * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: Jeongmo Yang <jm80.yang@samsung.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef __MM_CAMCORDER_UTIL_H__
+#define __MM_CAMCORDER_UTIL_H__
+
+/*=======================================================================================
+| INCLUDE FILES |
+========================================================================================*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*=======================================================================================
+| GLOBAL DEFINITIONS AND DECLARATIONS FOR CAMCORDER |
+========================================================================================*/
+
+/*=======================================================================================
+| MACRO DEFINITIONS |
+========================================================================================*/
+#ifndef CLEAR
+#define CLEAR(x) memset (&(x), 0, sizeof (x))
+#endif
+
+#define MMCAMCORDER_ADD_BUFFER_PROBE(x_pad, x_category, x_callback, x_hcamcorder) \
+do { \
+ MMCamcorderHandlerItem *item = NULL; \
+ item = (MMCamcorderHandlerItem *)g_malloc(sizeof(MMCamcorderHandlerItem)); \
+ if (!item) {\
+ _mmcam_dbg_err("Cannot connect buffer probe [malloc fail] \n"); \
+ } else if (x_category == 0 || !(x_category & _MMCAMCORDER_HANDLER_CATEGORY_ALL)) { \
+ _mmcam_dbg_err("Invalid handler category : %x \n", x_category); \
+ } 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); \
+ 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); \
+ } \
+} while (0);
+
+#define MMCAMCORDER_ADD_EVENT_PROBE(x_pad, x_category, x_callback, x_hcamcorder) \
+do { \
+ MMCamcorderHandlerItem *item = NULL; \
+ item = (MMCamcorderHandlerItem *) g_malloc(sizeof(MMCamcorderHandlerItem)); \
+ if (!item) { \
+ _mmcam_dbg_err("Cannot connect buffer probe [malloc fail] \n"); \
+ } \
+ else if (x_category == 0 || !(x_category & _MMCAMCORDER_HANDLER_CATEGORY_ALL)) { \
+ _mmcam_dbg_err("Invalid handler category : %x \n", x_category); \
+ } 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); \
+ 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); \
+ } \
+} while (0);
+
+#define MMCAMCORDER_ADD_DATA_PROBE(x_pad, x_category, x_callback, x_hcamcorder) \
+do { \
+ MMCamcorderHandlerItem *item = NULL; \
+ item = (MMCamcorderHandlerItem *) g_malloc(sizeof(MMCamcorderHandlerItem)); \
+ if (!item) { \
+ _mmcam_dbg_err("Cannot connect buffer probe [malloc fail] \n"); \
+ } else if (x_category == 0 || !(x_category & _MMCAMCORDER_HANDLER_CATEGORY_ALL)) { \
+ _mmcam_dbg_err("Invalid handler category : %x \n", x_category); \
+ } else { \
+ item->object =G_OBJECT(x_pad); \
+ item->category = x_category; \
+ item->handler_id = gst_pad_add_data_probe(x_pad, G_CALLBACK(x_callback), x_hcamcorder); \
+ x_hcamcorder->data_probes = g_list_append(x_hcamcorder->data_probes, item); \
+ _mmcam_dbg_log("Adding data probe on [%s:%s] - [ID : %lu], [Category : %x] ", GST_DEBUG_PAD_NAME(item->object), item->handler_id, item->category); \
+ } \
+} while (0);
+
+#define MMCAMCORDER_SIGNAL_CONNECT( x_object, x_category, x_signal, x_callback, x_hcamcorder) \
+do { \
+ MMCamcorderHandlerItem* item = NULL; \
+ item = (MMCamcorderHandlerItem *) g_malloc(sizeof(MMCamcorderHandlerItem)); \
+ if (!item) { \
+ _mmcam_dbg_err("Cannot connect signal [%s]\n", x_signal ); \
+ } else if (x_category == 0 || !(x_category & _MMCAMCORDER_HANDLER_CATEGORY_ALL)) { \
+ _mmcam_dbg_err("Invalid handler category : %x \n", x_category); \
+ } else { \
+ item->object = G_OBJECT(x_object); \
+ item->category = x_category; \
+ 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); \
+ } \
+} while (0);
+
+#define MMCAMCORDER_G_OBJECT_GET(obj, name, value) \
+do { \
+ if (obj) { \
+ if(g_object_class_find_property(G_OBJECT_GET_CLASS(G_OBJECT(obj)), name)) { \
+ g_object_get(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(obj, name, value) \
+do { \
+ if (obj) { \
+ if(g_object_class_find_property(G_OBJECT_GET_CLASS(G_OBJECT(obj)), name)) { \
+ 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 MMCAM_FOURCC(a,b,c,d) (guint32)((a)|(b)<<8|(c)<<16|(d)<<24)
+#define MMCAM_FOURCC_ARGS(fourcc) \
+ ((gchar)((fourcc)&0xff)), \
+ ((gchar)(((fourcc)>>8)&0xff)), \
+ ((gchar)(((fourcc)>>16)&0xff)), \
+ ((gchar)(((fourcc)>>24)&0xff))
+
+/*=======================================================================================
+| ENUM DEFINITIONS |
+========================================================================================*/
+/**
+ *Type define of util.
+ */
+typedef enum {
+ _MMCAMCORDER_HANDLER_PREVIEW = (1 << 0),
+ _MMCAMCORDER_HANDLER_VIDEOREC = (1 << 1),
+ _MMCAMCORDER_HANDLER_STILLSHOT = (1 << 2),
+ _MMCAMCORDER_HANDLER_AUDIOREC = (1 << 3),
+} _MMCamcorderHandlerCategory;
+
+/*=======================================================================================
+| STRUCTURE DEFINITIONS |
+========================================================================================*/
+
+/**
+ * Structure of location info
+ */
+typedef struct {
+ gint32 longitude;
+ gint32 latitude;
+ gint32 altitude;
+} _MMCamcorderLocationInfo;
+
+/**
+ * Structure of handler item
+ */
+typedef struct {
+ GObject *object;
+ _MMCamcorderHandlerCategory category;
+ gulong handler_id;
+} MMCamcorderHandlerItem;
+
+/**
+ * Structure of message item
+ */
+typedef struct {
+ MMHandleType handle; /**< handle */
+ int id; /**< message id */
+ MMMessageParamType param; /**< message parameter */
+} _MMCamcorderMsgItem;
+
+/*=======================================================================================
+| CONSTANT DEFINITIONS |
+========================================================================================*/
+#define _MMCAMCORDER_HANDLER_CATEGORY_ALL \
+ (_MMCAMCORDER_HANDLER_PREVIEW | _MMCAMCORDER_HANDLER_VIDEOREC |_MMCAMCORDER_HANDLER_STILLSHOT | _MMCAMCORDER_HANDLER_AUDIOREC)
+
+/*=======================================================================================
+| GLOBAL FUNCTION PROTOTYPES |
+========================================================================================*/
+/* GStreamer */
+void _mmcamcorder_remove_buffer_probe(MMHandleType handle, _MMCamcorderHandlerCategory category);
+void _mmcamcorder_remove_event_probe(MMHandleType handle, _MMCamcorderHandlerCategory category);
+void _mmcamcorder_remove_data_probe(MMHandleType handle, _MMCamcorderHandlerCategory category);
+void _mmcamcorder_disconnect_signal(MMHandleType handle, _MMCamcorderHandlerCategory category);
+void _mmcamcorder_remove_all_handlers(MMHandleType handle, _MMCamcorderHandlerCategory category);
+void _mmcamcorder_element_release_noti(gpointer data, GObject *where_the_object_was);
+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);
+
+/* Pixel format */
+int _mmcamcorder_get_pixel_format(GstBuffer *buffer);
+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);
+
+/* Recording */
+/* find top level tag only, do not use this function for finding sub level tags.
+ tag_fourcc is Four-character-code (FOURCC) */
+gint _mmcamcorder_find_tag(FILE *f, guint32 tag_fourcc);
+gint32 _mmcamcorder_double_to_fix(gdouble d_number);
+gboolean _mmcamcorder_update_size(FILE *f, gint64 prev_pos, gint64 curr_pos);
+gboolean _mmcamcorder_write_loci(FILE *f, _MMCamcorderLocationInfo info);
+gboolean _mmcamcorder_write_udta(FILE *f, _MMCamcorderLocationInfo info);
+gulong _mmcamcorder_get_container_size(const guchar *size);
+
+/* File system */
+int _mmcamcorder_get_freespace(const gchar *path, guint64 *free_space);
+int _mmcamcorder_get_file_size(const char *filename, guint64 *size);
+
+/* Debug */
+void _mmcamcorder_err_trace_write(char *str_filename, char *func_name, int line_num, char *fmt, ...);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __MM_CAMCORDER_UTIL_H__ */
diff --git a/src/include/mm_camcorder_videorec.h b/src/include/mm_camcorder_videorec.h
new file mode 100644
index 0000000..e5018d5
--- /dev/null
+++ b/src/include/mm_camcorder_videorec.h
@@ -0,0 +1,139 @@
+/*
+ * libmm-camcorder
+ *
+ * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: Jeongmo Yang <jm80.yang@samsung.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#ifndef __MM_CAMCORDER_VIDEOREC_H__
+#define __MM_CAMCORDER_VIDEOREC_H__
+
+/*=======================================================================================
+| INCLUDE FILES |
+========================================================================================*/
+#include <mm_types.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*=======================================================================================
+| GLOBAL DEFINITIONS AND DECLARATIONS FOR CAMCORDER |
+========================================================================================*/
+
+/*=======================================================================================
+| MACRO DEFINITIONS |
+========================================================================================*/
+
+/*=======================================================================================
+| ENUM DEFINITIONS |
+========================================================================================*/
+
+/*=======================================================================================
+| STRUCTURE DEFINITIONS |
+========================================================================================*/
+/**
+ * MMCamcorder information for video(preview/recording) mode
+ */
+typedef struct {
+ gboolean b_commiting; /**< Is it commiting now? */
+ char *filename; /**< recorded filename */
+ gint multiple_fps; /**< fps for high speed recording(slow motion recording) */
+ guint64 video_frame_count; /**< current video frame */
+ guint64 audio_frame_count; /**< current audio frame */
+ guint64 filesize; /**< current file size */
+ guint64 max_time; /**< max recording time */
+ int fileformat; /**< recording file format */
+/*
+ guint checker_id;
+ guint checker_count;
+*/
+} _MMCamcorderVideoInfo;
+
+/*=======================================================================================
+| CONSTANT DEFINITIONS |
+========================================================================================*/
+
+/*=======================================================================================
+| STATIC VARIABLES |
+========================================================================================*/
+
+/*=======================================================================================
+| EXTERN GLOBAL VARIABLE |
+========================================================================================*/
+
+/*=======================================================================================
+| GLOBAL FUNCTION PROTOTYPES |
+========================================================================================*/
+/**
+ * This function add recorder bin to main pipeline.
+ * When application creates initial pipeline, there are only bins for preview.
+ * If application wants to add recording function, bins for recording should be added.
+ *
+ * @param[in] handle Handle of camcorder context.
+ * @return This function returns MM_ERROR_NONE on success, or the other values on error.
+ * @remarks
+ * @see __mmcamcorder_create_preview_pipeline()
+ */
+int _mmcamcorder_add_recorder_pipeline(MMHandleType handle);
+
+/**
+ * This function remove recorder bin from main pipeline.
+ *
+ * @param[in] handle Handle of camcorder context.
+ * @return This function returns MM_ERROR_NONE on success, or the other values on error.
+ * @remarks
+ * @see __mmcamcorder_create_preview_pipeline(), __mmcamcorder_add_recorder_pipeline()
+ */
+int _mmcamcorder_remove_recorder_pipeline(MMHandleType handle);
+
+/**
+ * This function destroy video pipeline.
+ *
+ * @param[in] handle Handle of camcorder context.
+ * @return void
+ * @remarks
+ * @see _mmcamcorder_destroy_pipeline()
+ */
+void _mmcamcorder_destroy_video_pipeline(MMHandleType handle);
+
+/**
+ * This function operates each command on video mode.
+ *
+ * @param[in] handle Handle of camcorder context.
+ * @param[in] command command type received from Multimedia Framework.
+ * @return This function returns MM_ERROR_NONE on success, or the other values on error.
+ * @remarks
+ * @see _mmcamcorder_set_functions()
+ */
+int _mmcamcorder_video_command(MMHandleType handle, int command);
+
+/**
+ * This function handles EOS(end of stream) when commit video recording.
+ *
+ * @param[in] handle Handle of camcorder context.
+ * @return This function returns TRUE on success, or FALSE on failure.
+ * @remarks
+ * @see _mmcamcorder_set_functions()
+ */
+int _mmcamcorder_video_handle_eos(MMHandleType handle);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __MM_CAMCORDER_VIDEOREC_H__ */
diff --git a/src/mm_camcorder.c b/src/mm_camcorder.c
new file mode 100644
index 0000000..2514355
--- /dev/null
+++ b/src/mm_camcorder.c
@@ -0,0 +1,428 @@
+/*
+ * libmm-camcorder
+ *
+ * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: Jeongmo Yang <jm80.yang@samsung.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+/* ==============================================================================
+| INCLUDE FILES |
+===============================================================================*/
+#include <stdio.h>
+#include <string.h>
+
+
+#include <mm_error.h>
+#include <mm_ta.h>
+
+#include <mm_attrs_private.h>
+#include "mm_camcorder.h"
+#include "mm_camcorder_internal.h"
+
+
+/*===============================================================================
+| FUNCTION DEFINITIONS |
+===============================================================================*/
+/*-------------------------------------------------------------------------------
+| GLOBAL FUNCTION DEFINITIONS: |
+-------------------------------------------------------------------------------*/
+int mm_camcorder_create(MMHandleType *camcorder, MMCamPreset *info)
+{
+ int error = MM_ERROR_NONE;
+
+ mmf_return_val_if_fail((void *)camcorder, MM_ERROR_CAMCORDER_INVALID_ARGUMENT);
+ mmf_return_val_if_fail((void *)info, MM_ERROR_CAMCORDER_INVALID_ARGUMENT);
+
+ _mmcam_dbg_err("");
+
+ MMTA_INIT() ;
+
+ __ta__("_mmcamcorder_create",
+ error = _mmcamcorder_create(camcorder, info);
+ );
+
+ _mmcam_dbg_err("END");
+
+ return error;
+}
+
+
+int mm_camcorder_destroy(MMHandleType camcorder)
+{
+ int error = MM_ERROR_NONE;
+
+ mmf_return_val_if_fail((void *)camcorder, MM_ERROR_CAMCORDER_INVALID_ARGUMENT);
+
+ _mmcam_dbg_err("");
+
+ __ta__("_mmcamcorder_destroy",
+ error = _mmcamcorder_destroy(camcorder);
+ );
+
+ MMTA_ACUM_ITEM_SHOW_RESULT_TO(MMTA_SHOW_FILE);
+ MMTA_RELEASE();
+
+ _mmcam_dbg_err("END!!!");
+
+ return error;
+}
+
+
+int mm_camcorder_realize(MMHandleType camcorder)
+{
+ int error = MM_ERROR_NONE;
+
+ mmf_return_val_if_fail((void *)camcorder, MM_ERROR_CAMCORDER_INVALID_ARGUMENT);
+
+ _mmcam_dbg_err("");
+
+ if(((mmf_camcorder_t *)camcorder)->sync_state_change) {
+ __ta__("_mmcamcorder_realize",
+ error = _mmcamcorder_realize(camcorder);
+ );
+ } else {
+ /* After sending command, this function just return immediately. */
+ error = _mmcamcorder_append_simple_command(camcorder, _MMCAMCORDER_CMD_REALIZE);
+ }
+
+ _mmcam_dbg_err("END");
+
+ return error;
+}
+
+
+int mm_camcorder_unrealize(MMHandleType camcorder)
+{
+ int error = MM_ERROR_NONE;
+
+ mmf_return_val_if_fail((void *)camcorder, MM_ERROR_CAMCORDER_INVALID_ARGUMENT);
+
+ _mmcam_dbg_err("");
+
+ if(((mmf_camcorder_t *)camcorder)->sync_state_change) {
+ __ta__("_mmcamcorder_unrealize",
+ error = _mmcamcorder_unrealize(camcorder);
+ );
+ } else {
+ /* After sending command, this function just return immediately. */
+ error = _mmcamcorder_append_simple_command(camcorder, _MMCAMCORDER_CMD_UNREALIZE);
+ }
+
+ _mmcam_dbg_err("END");
+
+ return error;
+}
+
+
+int mm_camcorder_start(MMHandleType camcorder)
+{
+ int error = MM_ERROR_NONE;
+
+ mmf_return_val_if_fail((void *)camcorder, MM_ERROR_CAMCORDER_INVALID_ARGUMENT);
+
+ _mmcam_dbg_err("");
+
+ if(((mmf_camcorder_t *)camcorder)->sync_state_change) {
+ __ta__("_mmcamcorder_start",
+ error = _mmcamcorder_start(camcorder);
+ );
+ } else {
+ /* After sending command, this function just return immediately. */
+ error = _mmcamcorder_append_simple_command(camcorder, _MMCAMCORDER_CMD_START);
+ }
+
+ _mmcam_dbg_err("END");
+
+ return error;
+}
+
+
+int mm_camcorder_stop(MMHandleType camcorder)
+{
+ int error = MM_ERROR_NONE;
+
+ mmf_return_val_if_fail((void *)camcorder, MM_ERROR_CAMCORDER_INVALID_ARGUMENT);
+
+ _mmcam_dbg_err("");
+
+ if(((mmf_camcorder_t *)camcorder)->sync_state_change) {
+ __ta__("_mmcamcorder_stop",
+ error = _mmcamcorder_stop(camcorder);
+ );
+ } else {
+ /* After sending command, this function just return immediately. */
+ error = _mmcamcorder_append_simple_command(camcorder, _MMCAMCORDER_CMD_STOP);
+ }
+
+ _mmcam_dbg_err("END");
+
+ return error;
+}
+
+
+int mm_camcorder_capture_start(MMHandleType camcorder)
+{
+ int error = MM_ERROR_NONE;
+
+ mmf_return_val_if_fail((void *)camcorder, MM_ERROR_CAMCORDER_INVALID_ARGUMENT);
+
+ _mmcam_dbg_err("");
+
+ __ta__("_mmcamcorder_capture_start",
+ error = _mmcamcorder_capture_start(camcorder);
+ );
+
+ _mmcam_dbg_err("END");
+
+ return error;
+}
+
+
+int mm_camcorder_capture_stop(MMHandleType camcorder)
+{
+ int error = MM_ERROR_NONE;
+
+ mmf_return_val_if_fail((void *)camcorder, MM_ERROR_CAMCORDER_INVALID_ARGUMENT);
+
+ _mmcam_dbg_err("");
+
+ __ta__("_mmcamcorder_capture_stop",
+ error = _mmcamcorder_capture_stop(camcorder);
+ );
+
+ _mmcam_dbg_err("END");
+
+ return error;
+}
+
+
+int mm_camcorder_record(MMHandleType camcorder)
+{
+ int error = MM_ERROR_NONE;
+
+ mmf_return_val_if_fail((void*)camcorder, MM_ERROR_CAMCORDER_INVALID_ARGUMENT);
+
+ _mmcam_dbg_err("");
+
+ __ta__("_mmcamcorder_record",
+ error = _mmcamcorder_record(camcorder);
+ );
+
+ _mmcam_dbg_err("END");
+
+ return error;
+}
+
+
+int mm_camcorder_pause(MMHandleType camcorder)
+{
+ int error = MM_ERROR_NONE;
+
+ mmf_return_val_if_fail((void *)camcorder, MM_ERROR_CAMCORDER_INVALID_ARGUMENT);
+
+ _mmcam_dbg_err("");
+
+ __ta__("_mmcamcorder_pause",
+ error = _mmcamcorder_pause(camcorder);
+ );
+
+ _mmcam_dbg_err("END");
+
+ return error;
+}
+
+
+int mm_camcorder_commit(MMHandleType camcorder)
+{
+ int error = MM_ERROR_NONE;
+
+ mmf_return_val_if_fail((void *)camcorder, MM_ERROR_CAMCORDER_INVALID_ARGUMENT);
+
+ _mmcam_dbg_err("");
+
+ MMTA_ACUM_ITEM_BEGIN("Real Commit Time", 0);
+
+ if(((mmf_camcorder_t *)camcorder)->sync_state_change) {
+ __ta__("_mmcamcorder_stop",
+ error = _mmcamcorder_commit(camcorder);
+ );
+ } else {
+ /* After sending command, this function just return immediately. */
+ error = _mmcamcorder_append_simple_command(camcorder, _MMCAMCORDER_CMD_COMMIT);
+ }
+
+ _mmcam_dbg_err("END");
+
+ return error;
+}
+
+
+int mm_camcorder_cancel(MMHandleType camcorder)
+{
+ int error = MM_ERROR_NONE;
+
+ mmf_return_val_if_fail((void *)camcorder, MM_ERROR_CAMCORDER_INVALID_ARGUMENT);
+
+ _mmcam_dbg_err("");
+
+ __ta__("_mmcamcorder_cancel",
+ error = _mmcamcorder_cancel(camcorder);
+ );
+
+ _mmcam_dbg_err("END");
+
+ return error;
+}
+
+
+int mm_camcorder_set_message_callback(MMHandleType camcorder, MMMessageCallback callback, void *user_data)
+{
+ int error = MM_ERROR_NONE;
+
+ mmf_return_val_if_fail((void *)camcorder, MM_ERROR_CAMCORDER_INVALID_ARGUMENT);
+
+ error = _mmcamcorder_set_message_callback(camcorder, callback, user_data);
+
+ return error;
+}
+
+
+int mm_camcorder_set_video_stream_callback(MMHandleType camcorder, mm_camcorder_video_stream_callback callback, void* user_data)
+{
+ int error = MM_ERROR_NONE;
+
+ mmf_return_val_if_fail((void *)camcorder, MM_ERROR_CAMCORDER_INVALID_ARGUMENT);
+
+ error = _mmcamcorder_set_video_stream_callback(camcorder, callback, user_data);
+
+ return error;
+}
+
+
+int mm_camcorder_set_audio_stream_callback(MMHandleType camcorder, mm_camcorder_audio_stream_callback callback, void* user_data)
+{
+ int error = MM_ERROR_NONE;
+
+ mmf_return_val_if_fail((void *)camcorder, MM_ERROR_CAMCORDER_INVALID_ARGUMENT);
+
+ error = _mmcamcorder_set_audio_stream_callback(camcorder, callback, user_data);
+
+ return error;
+}
+
+
+int mm_camcorder_set_video_capture_callback(MMHandleType camcorder, mm_camcorder_video_capture_callback callback, void* user_data)
+{
+ int error = MM_ERROR_NONE;
+
+ mmf_return_val_if_fail((void *)camcorder, MM_ERROR_CAMCORDER_INVALID_ARGUMENT );
+
+ error = _mmcamcorder_set_video_capture_callback(camcorder, callback, user_data);
+
+ return error;
+}
+
+
+int mm_camcorder_get_state(MMHandleType camcorder, MMCamcorderStateType *status)
+{
+ int ret = MM_ERROR_NONE;
+
+ if (!camcorder) {
+ _mmcam_dbg_warn("Empty handle.");
+ return MM_ERROR_CAMCORDER_INVALID_ARGUMENT;
+ }
+
+ *status = _mmcamcorder_get_state(camcorder);
+
+ return ret;
+
+}
+
+
+int mm_camcorder_get_attributes(MMHandleType camcorder, char **err_attr_name, const char *attribute_name, ...)
+{
+ va_list var_args;
+ int ret = MM_ERROR_NONE;
+
+ return_val_if_fail(attribute_name, MM_ERROR_COMMON_INVALID_ARGUMENT);
+
+ va_start(var_args, attribute_name);
+ ret = _mmcamcorder_get_attributes(camcorder, err_attr_name, attribute_name, var_args);
+ va_end (var_args);
+
+ return ret;
+}
+
+
+int mm_camcorder_set_attributes(MMHandleType camcorder, char **err_attr_name, const char *attribute_name, ...)
+{
+ va_list var_args;
+ int ret = MM_ERROR_NONE;
+
+ return_val_if_fail(attribute_name, MM_ERROR_COMMON_INVALID_ARGUMENT);
+
+ va_start (var_args, attribute_name);
+ ret = _mmcamcorder_set_attributes(camcorder, err_attr_name, attribute_name, var_args);
+ va_end (var_args);
+
+ return ret;
+}
+
+
+int mm_camcorder_get_attribute_info(MMHandleType camcorder, const char *attribute_name, MMCamAttrsInfo *info)
+{
+ return _mmcamcorder_get_attribute_info(camcorder, attribute_name, info);
+}
+
+
+int mm_camcorder_init_focusing(MMHandleType camcorder)
+{
+ int error = MM_ERROR_NONE;
+
+ mmf_return_val_if_fail((void *)camcorder, MM_ERROR_CAMCORDER_INVALID_ARGUMENT);
+
+ error = _mmcamcorder_init_focusing(camcorder);
+
+ return error;
+}
+
+
+int mm_camcorder_start_focusing( MMHandleType camcorder )
+{
+ int error = MM_ERROR_NONE;
+
+ mmf_return_val_if_fail((void *)camcorder, MM_ERROR_CAMCORDER_INVALID_ARGUMENT);
+
+ /* TODO : Add direction parameter */
+
+ error = _mmcamcorder_adjust_focus(camcorder, MM_CAMCORDER_MF_LENS_DIR_FORWARD);
+
+ return error;
+}
+
+
+int mm_camcorder_stop_focusing(MMHandleType camcorder)
+{
+ int error = MM_ERROR_NONE;
+
+ mmf_return_val_if_fail((void *)camcorder, MM_ERROR_CAMCORDER_INVALID_ARGUMENT);
+
+ error = _mmcamcorder_stop_focusing(camcorder);
+
+ return error;
+}
+
diff --git a/src/mm_camcorder_attribute.c b/src/mm_camcorder_attribute.c
new file mode 100644
index 0000000..f9df6d7
--- /dev/null
+++ b/src/mm_camcorder_attribute.c
@@ -0,0 +1,3882 @@
+/*
+ * libmm-camcorder
+ *
+ * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: Jeongmo Yang <jm80.yang@samsung.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+
+/*=======================================================================================
+| INCLUDE FILES |
+=======================================================================================*/
+#include "mm_camcorder_internal.h"
+
+#include <gst/interfaces/colorbalance.h>
+#include <gst/interfaces/cameracontrol.h>
+#include <gst/interfaces/xoverlay.h>
+
+
+/*---------------------------------------------------------------------------------------
+| GLOBAL VARIABLE DEFINITIONS for internal |
+---------------------------------------------------------------------------------------*/
+int video_input_rotation[] = {MM_VIDEO_INPUT_ROTATION_NONE,
+ MM_VIDEO_INPUT_ROTATION_90,
+ MM_VIDEO_INPUT_ROTATION_180,
+ MM_VIDEO_INPUT_ROTATION_270,
+ MM_VIDEO_INPUT_ROTATION_FLIP_HORZ,
+ MM_VIDEO_INPUT_ROTATION_FLIP_VERT};
+
+int depth[] = {MM_CAMCORDER_AUDIO_FORMAT_PCM_U8,
+ MM_CAMCORDER_AUDIO_FORMAT_PCM_S16_LE};
+
+int rotation[] = {MM_DISPLAY_ROTATION_NONE,
+ MM_DISPLAY_ROTATION_90,
+ MM_DISPLAY_ROTATION_180,
+ MM_DISPLAY_ROTATION_270,
+ MM_DISPLAY_ROTATION_FLIP_HORZ,
+ MM_DISPLAY_ROTATION_FLIP_VERT};
+
+int visible_values[] = { 0, 1 }; /*0: off, 1:on*/
+
+int strobe_mode[] = {MM_CAMCORDER_STROBE_MODE_OFF,
+ MM_CAMCORDER_STROBE_MODE_ON,
+ MM_CAMCORDER_STROBE_MODE_AUTO,
+ MM_CAMCORDER_STROBE_MODE_REDEYE_REDUCTION,
+ MM_CAMCORDER_STROBE_MODE_SLOW_SYNC,
+ MM_CAMCORDER_STROBE_MODE_FRONT_CURTAIN,
+ MM_CAMCORDER_STROBE_MODE_REAR_CURTAIN,
+ MM_CAMCORDER_STROBE_MODE_PERMANENT};
+
+int tag_enable_values[] = { 0, 1 };
+
+int tag_orientation_values[] =
+{
+ 1, /*The 0th row is at the visual top of the image, and the 0th column is the visual left-hand side.*/
+ 2, /*the 0th row is at the visual top of the image, and the 0th column is the visual right-hand side.*/
+ 3, /*the 0th row is at the visual bottom of the image, and the 0th column is the visual right-hand side.*/
+ 4, /*the 0th row is at the visual bottom of the image, and the 0th column is the visual left-hand side.*/
+ 5, /*the 0th row is the visual left-hand side of the image, and the 0th column is the visual top.*/
+ 6, /*the 0th row is the visual right-hand side of the image, and the 0th column is the visual top.*/
+ 7, /*the 0th row is the visual right-hand side of the image, and the 0th column is the visual bottom.*/
+ 8, /*the 0th row is the visual left-hand side of the image, and the 0th column is the visual bottom.*/
+};
+
+/* basic attributes' info */
+mm_cam_attr_construct_info cam_attrs_const_info[] ={
+ //0
+ {
+ MM_CAM_MODE, /* ID */
+ "mode", /* Name */
+ MMF_VALUE_TYPE_INT, /* Type */
+ MM_ATTRS_FLAG_RW, /* Flag */
+ (void*)MM_CAMCORDER_MODE_IMAGE, /* Default value */
+ MM_ATTRS_VALID_TYPE_INT_RANGE, /* Validity type */
+ MM_CAMCORDER_MODE_IMAGE, /* Validity val1 (min, *array,...) */
+ MM_CAMCORDER_MODE_VIDEO, /* Validity val2 (max, count, ...) */
+ NULL, /* Runtime setting function of the attribute */
+ },
+ // 1
+ {
+ MM_CAM_AUDIO_DEVICE,
+ "audio-device",
+ MMF_VALUE_TYPE_INT,
+ MM_ATTRS_FLAG_RW,
+ (void*)MM_AUDIO_DEVICE_MIC,
+ MM_ATTRS_VALID_TYPE_INT_RANGE,
+ 0,
+ MM_AUDIO_DEVICE_NUM-1,
+ NULL,
+ },
+ // 2
+ {
+ MM_CAM_CAMERA_DEVICE,
+ "camera-device",
+ MMF_VALUE_TYPE_INT,
+ MM_ATTRS_FLAG_RW,
+ (void*)MM_VIDEO_DEVICE_NONE,
+ MM_ATTRS_VALID_TYPE_INT_RANGE,
+ MM_VIDEO_DEVICE_NONE,
+ MM_VIDEO_DEVICE_NUM-1,
+ NULL,
+ },
+ // 3
+ {
+ MM_CAM_AUDIO_ENCODER,
+ "audio-encoder",
+ MMF_VALUE_TYPE_INT,
+ MM_ATTRS_FLAG_RW,
+ (void*)MM_AUDIO_CODEC_AMR,
+ MM_ATTRS_VALID_TYPE_INT_ARRAY,
+ (int)NULL,
+ 0,
+ NULL,
+ },
+ // 4
+ {
+ MM_CAM_VIDEO_ENCODER,
+ "video-encoder",
+ MMF_VALUE_TYPE_INT,
+ MM_ATTRS_FLAG_RW,
+ (void*)MM_VIDEO_CODEC_MPEG4,
+ MM_ATTRS_VALID_TYPE_INT_ARRAY,
+ (int)NULL,
+ 0,
+ NULL,
+ },
+ //5
+ {
+ MM_CAM_IMAGE_ENCODER,
+ "image-encoder",
+ MMF_VALUE_TYPE_INT,
+ MM_ATTRS_FLAG_RW,
+ (void*)MM_IMAGE_CODEC_JPEG,
+ MM_ATTRS_VALID_TYPE_INT_ARRAY,
+ (int)NULL,
+ 0,
+ NULL,
+ },
+ //6
+ {
+ MM_CAM_FILE_FORMAT,
+ "file-format",
+ MMF_VALUE_TYPE_INT,
+ MM_ATTRS_FLAG_RW,
+ (void*)MM_FILE_FORMAT_MP4,
+ MM_ATTRS_VALID_TYPE_INT_ARRAY,
+ (int)NULL,
+ 0,
+ NULL,
+ },
+ //7
+ {
+ MM_CAM_CAMERA_DEVICE_NAME,
+ "camera-device-name",
+ MMF_VALUE_TYPE_STRING,
+ MM_ATTRS_FLAG_RW,
+ (void*)NULL,
+ MM_ATTRS_VALID_TYPE_NONE,
+ 0,
+ 0,
+ NULL,
+ },
+ //8
+ {
+ MM_CAM_AUDIO_SAMPLERATE,
+ "audio-samplerate",
+ MMF_VALUE_TYPE_INT,
+ MM_ATTRS_FLAG_RW,
+ (void*)8000,
+ MM_ATTRS_VALID_TYPE_INT_RANGE,
+ 0,
+ _MMCAMCORDER_MAX_INT,
+ NULL,
+ },
+ //9
+ {
+ MM_CAM_AUDIO_FORMAT,
+ "audio-format",
+ MMF_VALUE_TYPE_INT,
+ MM_ATTRS_FLAG_RW,
+ (void*)MM_CAMCORDER_AUDIO_FORMAT_PCM_S16_LE,
+ MM_ATTRS_VALID_TYPE_INT_ARRAY,
+ (int)depth,
+ ARRAY_SIZE(depth),
+ NULL,
+ },
+ //10
+ {
+ MM_CAM_AUDIO_CHANNEL,
+ "audio-channel",
+ MMF_VALUE_TYPE_INT,
+ MM_ATTRS_FLAG_RW,
+ (void*)2,
+ MM_ATTRS_VALID_TYPE_INT_RANGE,
+ 1,
+ 2,
+ NULL,
+ },
+ //11
+ {
+ MM_CAM_AUDIO_VOLUME,
+ "audio-volume",
+ MMF_VALUE_TYPE_DOUBLE,
+ MM_ATTRS_FLAG_RW,
+ (void*)1,
+ MM_ATTRS_VALID_TYPE_DOUBLE_RANGE,
+ 0,
+ 10.0,
+ _mmcamcorder_commit_audio_volume,
+ },
+ //12
+ {
+ MM_CAM_AUDIO_INPUT_ROUTE,
+ "audio-input-route",
+ MMF_VALUE_TYPE_INT,
+ MM_ATTRS_FLAG_RW,
+ (void*)MM_AUDIOROUTE_USE_EXTERNAL_SETTING,
+ MM_ATTRS_VALID_TYPE_INT_RANGE,
+ MM_AUDIOROUTE_USE_EXTERNAL_SETTING,
+ MM_AUDIOROUTE_CAPTURE_STEREOMIC_ONLY,
+ _mmcamcorder_commit_audio_input_route,
+ },
+ //13
+ {
+ MM_CAM_FILTER_SCENE_MODE,
+ "filter-scene-mode",
+ MMF_VALUE_TYPE_INT,
+ MM_ATTRS_FLAG_RW,
+ (void*)0,
+ MM_ATTRS_VALID_TYPE_INT_ARRAY,
+ 0,
+ 0,
+ _mmcamcorder_commit_filter_scene_mode,
+ },
+ //14
+ {
+ MM_CAM_FILTER_BRIGHTNESS,
+ "filter-brightness",
+ MMF_VALUE_TYPE_INT,
+ MM_ATTRS_FLAG_RW,
+ (void*)1,
+ MM_ATTRS_VALID_TYPE_INT_RANGE,
+ 0,
+ -1,
+ _mmcamcorder_commit_filter,
+ },
+ //15
+ {
+ MM_CAM_FILTER_CONTRAST,
+ "filter-contrast",
+ MMF_VALUE_TYPE_INT,
+ MM_ATTRS_FLAG_RW,
+ (void*)0,
+ MM_ATTRS_VALID_TYPE_INT_RANGE,
+ 0,
+ -1,
+ _mmcamcorder_commit_filter,
+ },
+ //16
+ {
+ MM_CAM_FILTER_WB,
+ "filter-wb",
+ MMF_VALUE_TYPE_INT,
+ MM_ATTRS_FLAG_RW,
+ (void*)0,
+ MM_ATTRS_VALID_TYPE_INT_ARRAY,
+ 0,
+ 0,
+ _mmcamcorder_commit_filter,
+ },
+ //17
+ {
+ MM_CAM_FILTER_COLOR_TONE,
+ "filter-color-tone",
+ MMF_VALUE_TYPE_INT,
+ MM_ATTRS_FLAG_RW,
+ (void*)0,
+ MM_ATTRS_VALID_TYPE_INT_ARRAY,
+ 0,
+ 0,
+ _mmcamcorder_commit_filter,
+ },
+ //18
+ {
+ MM_CAM_FILTER_SATURATION,
+ "filter-saturation",
+ MMF_VALUE_TYPE_INT,
+ MM_ATTRS_FLAG_RW,
+ (void*)0,
+ MM_ATTRS_VALID_TYPE_INT_RANGE,
+ 0,
+ -1,
+ _mmcamcorder_commit_filter,
+ },
+ //19
+ {
+ MM_CAM_FILTER_HUE,
+ "filter-hue",
+ MMF_VALUE_TYPE_INT,
+ MM_ATTRS_FLAG_RW,
+ (void*)0,
+ MM_ATTRS_VALID_TYPE_INT_RANGE,
+ 0,
+ -1,
+ _mmcamcorder_commit_filter,
+ },
+ //20
+ {
+ MM_CAM_FILTER_SHARPNESS,
+ "filter-sharpness",
+ MMF_VALUE_TYPE_INT,
+ MM_ATTRS_FLAG_RW,
+ (void*)0,
+ MM_ATTRS_VALID_TYPE_INT_RANGE,
+ 0,
+ -1,
+ _mmcamcorder_commit_filter,
+ },
+ //21
+ {
+ MM_CAM_CAMERA_FORMAT,
+ "camera-format",
+ MMF_VALUE_TYPE_INT,
+ MM_ATTRS_FLAG_RW,
+ (void*)MM_PIXEL_FORMAT_YUYV,
+ MM_ATTRS_VALID_TYPE_INT_ARRAY,
+ 0,
+ 0,
+ NULL,
+ },
+ //22
+ {
+ MM_CAM_CAMERA_SLOW_MOTION_FPS,
+ "camera-slow-motion-fps",
+ MMF_VALUE_TYPE_INT,
+ MM_ATTRS_FLAG_RW,
+ (void*)0,
+ MM_ATTRS_VALID_TYPE_INT_RANGE,
+ 0,
+ _MMCAMCORDER_MAX_INT,
+ NULL,
+ },
+ //23
+ {
+ MM_CAM_CAMERA_FPS,
+ "camera-fps",
+ MMF_VALUE_TYPE_INT,
+ MM_ATTRS_FLAG_RW,
+ (void*)30,
+ MM_ATTRS_VALID_TYPE_INT_ARRAY,
+ 0,
+ 0,
+ _mmcamcorder_commit_camera_fps,
+ },
+ //24
+ {
+ MM_CAM_CAMERA_WIDTH,
+ "camera-width",
+ MMF_VALUE_TYPE_INT,
+ MM_ATTRS_FLAG_RW,
+ (void*)320,
+ MM_ATTRS_VALID_TYPE_INT_ARRAY,
+ 0,
+ 0,
+ _mmcamcorder_commit_camera_width,
+ },
+ //25
+ {
+ MM_CAM_CAMERA_HEIGHT,
+ "camera-height",
+ MMF_VALUE_TYPE_INT,
+ MM_ATTRS_FLAG_RW,
+ (void*)240,
+ MM_ATTRS_VALID_TYPE_INT_ARRAY,
+ 0,
+ 0,
+ _mmcamcorder_commit_camera_height,
+ },
+ //26
+ {
+ MM_CAM_CAMERA_DIGITAL_ZOOM,
+ "camera-digital-zoom",
+ MMF_VALUE_TYPE_INT,
+ MM_ATTRS_FLAG_RW,
+ (void*)10,
+ MM_ATTRS_VALID_TYPE_INT_RANGE,
+ 0,
+ -1,
+ _mmcamcorder_commit_camera_zoom,
+ },
+ //27
+ {
+ MM_CAM_CAMERA_OPTICAL_ZOOM,
+ "camera-optical-zoom",
+ MMF_VALUE_TYPE_INT,
+ MM_ATTRS_FLAG_RW,
+ (void*)0,
+ MM_ATTRS_VALID_TYPE_INT_RANGE,
+ 0,
+ -1,
+ _mmcamcorder_commit_camera_zoom,
+ },
+ //28
+ {
+ MM_CAM_CAMERA_FOCUS_MODE,
+ "camera-focus-mode",
+ MMF_VALUE_TYPE_INT,
+ MM_ATTRS_FLAG_RW,
+ (void*)MM_CAMCORDER_FOCUS_MODE_NONE,
+ MM_ATTRS_VALID_TYPE_INT_ARRAY,
+ 0,
+ 0,
+ _mmcamcorder_commit_camera_focus_mode,
+ },
+ //29
+ {
+ MM_CAM_CAMERA_AF_SCAN_RANGE,
+ "camera-af-scan-range",
+ MMF_VALUE_TYPE_INT,
+ MM_ATTRS_FLAG_RW,
+ (void*)0,
+ MM_ATTRS_VALID_TYPE_INT_ARRAY,
+ 0,
+ 0,
+ _mmcamcorder_commit_camera_af_scan_range,
+ },
+ //30
+ {
+ MM_CAM_CAMERA_EXPOSURE_MODE,
+ "camera-exposure-mode",
+ MMF_VALUE_TYPE_INT,
+ MM_ATTRS_FLAG_RW,
+ (void*)0,
+ MM_ATTRS_VALID_TYPE_INT_ARRAY,
+ 0,
+ 0,
+ _mmcamcorder_commit_camera_capture_mode,
+ },
+ //31
+ {
+ MM_CAM_CAMERA_EXPOSURE_VALUE,
+ "camera-exposure-value",
+ MMF_VALUE_TYPE_INT,
+ MM_ATTRS_FLAG_RW,
+ (void*)0,
+ MM_ATTRS_VALID_TYPE_INT_RANGE,
+ 0,
+ -1,
+ _mmcamcorder_commit_camera_capture_mode,
+ },
+ //32
+ {
+ MM_CAM_CAMERA_F_NUMBER,
+ "camera-f-number",
+ MMF_VALUE_TYPE_INT,
+ MM_ATTRS_FLAG_RW,
+ (void*)0,
+ MM_ATTRS_VALID_TYPE_INT_ARRAY,
+ 0,
+ 0,
+ _mmcamcorder_commit_camera_capture_mode,
+ },
+ //33
+ {
+ MM_CAM_CAMERA_SHUTTER_SPEED,
+ "camera-shutter-speed",
+ MMF_VALUE_TYPE_INT,
+ MM_ATTRS_FLAG_RW,
+ (void*)0,
+ MM_ATTRS_VALID_TYPE_INT_ARRAY,
+ 0,
+ 0,
+ _mmcamcorder_commit_camera_capture_mode,
+ },
+ //34
+ {
+ MM_CAM_CAMERA_ISO,
+ "camera-iso",
+ MMF_VALUE_TYPE_INT,
+ MM_ATTRS_FLAG_RW,
+ (void*)0,
+ MM_ATTRS_VALID_TYPE_INT_ARRAY,
+ 0,
+ 0,
+ _mmcamcorder_commit_camera_capture_mode,
+ },
+ //35
+ {
+ MM_CAM_CAMERA_WDR,
+ "camera-wdr",
+ MMF_VALUE_TYPE_INT,
+ MM_ATTRS_FLAG_RW,
+ (void*)0,
+ MM_ATTRS_VALID_TYPE_INT_ARRAY,
+ 0,
+ 0,
+ _mmcamcorder_commit_camera_wdr,
+ },
+ //36
+ {
+ MM_CAM_CAMERA_ANTI_HANDSHAKE,
+ "camera-anti-handshake",
+ MMF_VALUE_TYPE_INT,
+ MM_ATTRS_FLAG_RW,
+ (void*)0,
+ MM_ATTRS_VALID_TYPE_INT_ARRAY,
+ 0,
+ 0,
+ _mmcamcorder_commit_camera_anti_handshake,
+ },
+ //37
+ {
+ MM_CAM_CAMERA_FPS_AUTO,
+ "camera-fps-auto",
+ MMF_VALUE_TYPE_INT,
+ MM_ATTRS_FLAG_RW,
+ (void*)FALSE,
+ MM_ATTRS_VALID_TYPE_INT_RANGE,
+ 0,
+ 1,
+ NULL,
+ },
+ //38
+ {
+ MM_CAM_CAMERA_HOLD_AF_AFTER_CAPTURING,
+ "camera-hold-af-after-capturing",
+ MMF_VALUE_TYPE_INT,
+ MM_ATTRS_FLAG_RW,
+ (void*)0,
+ MM_ATTRS_VALID_TYPE_INT_RANGE,
+ 0,
+ 1,
+ _mmcamcorder_commit_camera_hold_af_after_capturing,
+ },
+ //39
+ {
+ MM_CAM_CAMERA_DELAY_ATTR_SETTING,
+ "camera-delay-attr-setting",
+ MMF_VALUE_TYPE_INT,
+ MM_ATTRS_FLAG_RW,
+ (void*)FALSE,
+ MM_ATTRS_VALID_TYPE_INT_RANGE,
+ 0,
+ 1,
+ NULL,
+ },
+ //40
+ {
+ MM_CAM_AUDIO_ENCODER_BITRATE,
+ "audio-encoder-bitrate",
+ MMF_VALUE_TYPE_INT,
+ MM_ATTRS_FLAG_RW,
+ (void*)0,
+ MM_ATTRS_VALID_TYPE_INT_RANGE,
+ 0,
+ _MMCAMCORDER_MAX_INT,
+ NULL,
+ },
+ //41
+ {
+ MM_CAM_VIDEO_ENCODER_BITRATE,
+ "video-encoder-bitrate",
+ MMF_VALUE_TYPE_INT,
+ MM_ATTRS_FLAG_RW,
+ (void*)0,
+ MM_ATTRS_VALID_TYPE_INT_RANGE,
+ 0,
+ _MMCAMCORDER_MAX_INT,
+ NULL,
+ },
+ //42
+ {
+ MM_CAM_IMAGE_ENCODER_QUALITY,
+ "image-encoder-quality",
+ MMF_VALUE_TYPE_INT,
+ MM_ATTRS_FLAG_RW,
+ (void*)95,
+ MM_ATTRS_VALID_TYPE_INT_RANGE,
+ 0,
+ -1,
+ _mmcamcorder_commit_image_encoder_quality,
+ },
+ //43
+ {
+ MM_CAM_CAPTURE_FORMAT,
+ "capture-format",
+ MMF_VALUE_TYPE_INT,
+ MM_ATTRS_FLAG_RW,
+ (void*)MM_PIXEL_FORMAT_ENCODED,
+ MM_ATTRS_VALID_TYPE_INT_ARRAY,
+ 0,
+ 0,
+ NULL,
+ },
+ //44
+ {
+ MM_CAM_CAPTURE_WIDTH,
+ "capture-width",
+ MMF_VALUE_TYPE_INT,
+ MM_ATTRS_FLAG_RW,
+ (void*)1600,
+ MM_ATTRS_VALID_TYPE_INT_ARRAY,
+ 0,
+ 0,
+ _mmcamcorder_commit_capture_width ,
+ },
+ //45
+ {
+ MM_CAM_CAPTURE_HEIGHT,
+ "capture-height",
+ MMF_VALUE_TYPE_INT,
+ MM_ATTRS_FLAG_RW,
+ (void*)1200,
+ MM_ATTRS_VALID_TYPE_INT_ARRAY,
+ 0,
+ 0,
+ _mmcamcorder_commit_capture_height,
+ },
+ //46
+ {
+ MM_CAM_CAPTURE_COUNT,
+ "capture-count",
+ MMF_VALUE_TYPE_INT,
+ MM_ATTRS_FLAG_RW,
+ (void*)1,
+ MM_ATTRS_VALID_TYPE_INT_RANGE,
+ 0,
+ -1,
+ _mmcamcorder_commit_capture_count,
+ },
+ //47
+ {
+ MM_CAM_CAPTURE_INTERVAL,
+ "capture-interval",
+ MMF_VALUE_TYPE_INT,
+ MM_ATTRS_FLAG_RW,
+ (void*)0,
+ MM_ATTRS_VALID_TYPE_INT_RANGE,
+ 0,
+ _MMCAMCORDER_MAX_INT,
+ NULL,
+ },
+ //48
+ {
+ MM_CAM_CAPTURE_BREAK_CONTINUOUS_SHOT,
+ "capture-break-cont-shot",
+ MMF_VALUE_TYPE_INT,
+ MM_ATTRS_FLAG_RW,
+ (void*)FALSE,
+ MM_ATTRS_VALID_TYPE_INT_RANGE,
+ 0,
+ 1,
+ _mmcamcorder_commit_capture_break_cont_shot,
+ },
+ //49
+ {
+ MM_CAM_DISPLAY_HANDLE,
+ "display-handle",
+ MMF_VALUE_TYPE_DATA,
+ MM_ATTRS_FLAG_RW,
+ (void*)NULL,
+ MM_ATTRS_VALID_TYPE_NONE,
+ 0,
+ 0,
+ _mmcamcorder_commit_display_handle,
+ },
+ //50
+ {
+ MM_CAM_DISPLAY_DEVICE,
+ "display-device",
+ MMF_VALUE_TYPE_INT,
+ MM_ATTRS_FLAG_RW,
+ (void*)MM_DISPLAY_DEVICE_MAINLCD,
+ MM_ATTRS_VALID_TYPE_INT_ARRAY,
+ 0,
+ 0,
+ NULL,
+ },
+ //51
+ {
+ MM_CAM_DISPLAY_SURFACE,
+ "display-surface",
+ MMF_VALUE_TYPE_INT,
+ MM_ATTRS_FLAG_RW,
+ (void*)MM_DISPLAY_SURFACE_X,
+ MM_ATTRS_VALID_TYPE_INT_ARRAY,
+ 0,
+ 0,
+ NULL,
+ },
+ //52
+ {
+ MM_CAM_DISPLAY_RECT_X,
+ "display-rect-x",
+ MMF_VALUE_TYPE_INT,
+ MM_ATTRS_FLAG_RW,
+ (void*)0,
+ MM_ATTRS_VALID_TYPE_INT_RANGE,
+ 0,
+ _MMCAMCORDER_MAX_INT,
+ _mmcamcorder_commit_display_rect,
+ },
+ //53
+ {
+ MM_CAM_DISPLAY_RECT_Y,
+ "display-rect-y",
+ MMF_VALUE_TYPE_INT,
+ MM_ATTRS_FLAG_RW,
+ (void*)0,
+ MM_ATTRS_VALID_TYPE_INT_RANGE,
+ 0,
+ _MMCAMCORDER_MAX_INT,
+ _mmcamcorder_commit_display_rect,
+ },
+ //54
+ {
+ MM_CAM_DISPLAY_RECT_WIDTH,
+ "display-rect-width",
+ MMF_VALUE_TYPE_INT,
+ MM_ATTRS_FLAG_RW,
+ (void*)0,
+ MM_ATTRS_VALID_TYPE_INT_RANGE,
+ 0,
+ _MMCAMCORDER_MAX_INT,
+ _mmcamcorder_commit_display_rect,
+ },
+ //55
+ {
+ MM_CAM_DISPLAY_RECT_HEIGHT,
+ "display-rect-height",
+ MMF_VALUE_TYPE_INT,
+ MM_ATTRS_FLAG_RW,
+ (void*)0,
+ MM_ATTRS_VALID_TYPE_INT_RANGE,
+ 0,
+ _MMCAMCORDER_MAX_INT,
+ _mmcamcorder_commit_display_rect,
+ },
+ //56
+ {
+ MM_CAM_DISPLAY_SOURCE_X,
+ "display-src-x",
+ MMF_VALUE_TYPE_INT,
+ MM_ATTRS_FLAG_RW,
+ (void*)0,
+ MM_ATTRS_VALID_TYPE_INT_RANGE,
+ 0,
+ _MMCAMCORDER_MAX_INT,
+ NULL,
+ },
+ //57
+ {
+ MM_CAM_DISPLAY_SOURCE_Y,
+ "display-src-y",
+ MMF_VALUE_TYPE_INT,
+ MM_ATTRS_FLAG_RW,
+ (void*)0,
+ MM_ATTRS_VALID_TYPE_INT_RANGE,
+ 0,
+ _MMCAMCORDER_MAX_INT,
+ NULL,
+ },
+ //58
+ {
+ MM_CAM_DISPLAY_SOURCE_WIDTH,
+ "display-src-width",
+ MMF_VALUE_TYPE_INT,
+ MM_ATTRS_FLAG_RW,
+ (void*)0,
+ MM_ATTRS_VALID_TYPE_INT_RANGE,
+ 0,
+ _MMCAMCORDER_MAX_INT,
+ NULL,
+ },
+ //59
+ {
+ MM_CAM_DISPLAY_SOURCE_HEIGHT,
+ "display-src-height",
+ MMF_VALUE_TYPE_INT,
+ MM_ATTRS_FLAG_RW,
+ (void*)0,
+ MM_ATTRS_VALID_TYPE_INT_RANGE,
+ 0,
+ _MMCAMCORDER_MAX_INT,
+ NULL,
+ },
+ //60
+ {
+ MM_CAM_DISPLAY_ROTATION,
+ "display-rotation",
+ MMF_VALUE_TYPE_INT,
+ MM_ATTRS_FLAG_RW,
+ (void*)MM_DISPLAY_ROTATION_NONE,
+ MM_ATTRS_VALID_TYPE_INT_ARRAY,
+ (int)rotation,
+ ARRAY_SIZE(rotation),
+ _mmcamcorder_commit_display_rotation,
+ },
+ //61
+ {
+ MM_CAM_DISPLAY_VISIBLE,
+ "display-visible",
+ MMF_VALUE_TYPE_INT,
+ MM_ATTRS_FLAG_RW,
+ (void*)1,
+ MM_ATTRS_VALID_TYPE_INT_ARRAY,
+ (int)visible_values,
+ ARRAY_SIZE(visible_values),
+ _mmcamcorder_commit_display_visible,
+ },
+ //62
+ {
+ MM_CAM_DISPLAY_SCALE,
+ "display-scale",
+ MMF_VALUE_TYPE_INT,
+ MM_ATTRS_FLAG_RW,
+ (void*)0,
+ MM_ATTRS_VALID_TYPE_INT_RANGE,
+ MM_DISPLAY_SCALE_DEFAULT,
+ MM_DISPLAY_SCALE_TRIPLE_LENGTH,
+ _mmcamcorder_commit_display_scale,
+ },
+ //63
+ {
+ MM_CAM_DISPLAY_GEOMETRY_METHOD,
+ "display-geometry-method",
+ MMF_VALUE_TYPE_INT,
+ MM_ATTRS_FLAG_RW,
+ (void*)0,
+ MM_ATTRS_VALID_TYPE_INT_RANGE,
+ MM_DISPLAY_METHOD_LETTER_BOX,
+ MM_DISPLAY_METHOD_CUSTOM_ROI,
+ _mmcamcorder_commit_display_geometry_method,
+ },
+ //64
+ {
+ MM_CAM_TARGET_FILENAME,
+ "target-filename",
+ MMF_VALUE_TYPE_STRING,
+ MM_ATTRS_FLAG_RW,
+ (void*)"/tmp/CAM-NONAME",
+ MM_ATTRS_VALID_TYPE_NONE,
+ 0,
+ 0,
+ _mmcamcorder_commit_target_filename,
+ },
+ //65
+ {
+ MM_CAM_TARGET_MAX_SIZE,
+ "target-max-size",
+ MMF_VALUE_TYPE_INT,
+ MM_ATTRS_FLAG_RW,
+ (void*)0,
+ MM_ATTRS_VALID_TYPE_INT_RANGE,
+ 0,
+ _MMCAMCORDER_MAX_INT,
+ NULL,
+ },
+ //66
+ {
+ MM_CAM_TARGET_TIME_LIMIT,
+ "target-time-limit",
+ MMF_VALUE_TYPE_INT,
+ MM_ATTRS_FLAG_RW,
+ (void*)0,
+ MM_ATTRS_VALID_TYPE_INT_RANGE,
+ 0,
+ _MMCAMCORDER_MAX_INT,
+ NULL,
+ },
+ //67
+ {
+ MM_CAM_TAG_ENABLE,
+ "tag-enable",
+ MMF_VALUE_TYPE_INT,
+ MM_ATTRS_FLAG_RW,
+// (void*)tag_enable_values[0],
+ (void*)0,
+ MM_ATTRS_VALID_TYPE_INT_RANGE,
+ 0,
+ 1,
+ NULL,
+ },
+ //68
+ {
+ MM_CAM_TAG_IMAGE_DESCRIPTION,
+ "tag-image-description",
+ MMF_VALUE_TYPE_STRING,
+ MM_ATTRS_FLAG_RW,
+ (void*)NULL,
+ MM_ATTRS_VALID_TYPE_NONE,
+ 0,
+ 0,
+ NULL,
+ },
+ //69
+ {
+ MM_CAM_TAG_ORIENTATION,
+ "tag-orientation",
+ MMF_VALUE_TYPE_INT,
+ MM_ATTRS_FLAG_RW,
+// (void*)tag_orientation_values[0],
+ (void*)1,
+ MM_ATTRS_VALID_TYPE_INT_ARRAY,
+ (int)tag_orientation_values,
+ ARRAY_SIZE(tag_orientation_values),
+ NULL,
+ },
+ //70
+ {
+ MM_CAM_TAG_SOFTWARE,
+ "tag-software",
+ MMF_VALUE_TYPE_STRING,
+ MM_ATTRS_FLAG_RW,
+ (void*)NULL,
+ MM_ATTRS_VALID_TYPE_NONE,
+ 0,
+ 0,
+ NULL,
+ },
+ //71
+ {
+ MM_CAM_TAG_LATITUDE,
+ "tag-latitude",
+ MMF_VALUE_TYPE_DOUBLE,
+ MM_ATTRS_FLAG_RW,
+ (void*)0,
+ MM_ATTRS_VALID_TYPE_DOUBLE_RANGE,
+ -360,
+ 360,
+ NULL,
+ },
+ //72
+ {
+ MM_CAM_TAG_LONGITUDE,
+ "tag-longitude",
+ MMF_VALUE_TYPE_DOUBLE,
+ MM_ATTRS_FLAG_RW,
+ (void*)0,
+ MM_ATTRS_VALID_TYPE_DOUBLE_RANGE,
+ -360,
+ 360,
+ NULL,
+ },
+ //73
+ {
+ MM_CAM_TAG_ALTITUDE,
+ "tag-altitude",
+ MMF_VALUE_TYPE_DOUBLE,
+ MM_ATTRS_FLAG_RW,
+ (void*)0,
+ MM_ATTRS_VALID_TYPE_DOUBLE_RANGE,
+ -999999,
+ 999999,
+ NULL,
+ },
+ //74
+ {
+ MM_CAM_STROBE_CONTROL,
+ "strobe-control",
+ MMF_VALUE_TYPE_INT,
+ MM_ATTRS_FLAG_RW,
+ (void*)0,
+ MM_ATTRS_VALID_TYPE_INT_RANGE,
+ 0,
+ -1,
+ _mmcamcorder_commit_strobe,
+ },
+ //75
+ {
+ MM_CAM_STROBE_CAPABILITIES,
+ "strobe-capabilities",
+ MMF_VALUE_TYPE_INT,
+ MM_ATTRS_FLAG_RW,
+ (void*)0,
+ MM_ATTRS_VALID_TYPE_INT_RANGE,
+ 0,
+ -1,
+ _mmcamcorder_commit_strobe,
+ },
+ //76
+ {
+ MM_CAM_STROBE_MODE,
+ "strobe-mode",
+ MMF_VALUE_TYPE_INT,
+ MM_ATTRS_FLAG_RW,
+ (void*)0,
+ MM_ATTRS_VALID_TYPE_INT_ARRAY,
+ (int)strobe_mode,
+ ARRAY_SIZE(strobe_mode),
+ _mmcamcorder_commit_strobe,
+ },
+ //77
+ {
+ MM_CAM_DETECT_MODE,
+ "detect-mode",
+ MMF_VALUE_TYPE_INT,
+ MM_ATTRS_FLAG_RW,
+ (void*)0,
+ MM_ATTRS_VALID_TYPE_INT_ARRAY,
+ 0,
+ 0,
+ _mmcamcorder_commit_detect,
+ },
+ //78
+ {
+ MM_CAM_DETECT_NUMBER,
+ "detect-number",
+ MMF_VALUE_TYPE_INT,
+ MM_ATTRS_FLAG_RW,
+ (void*)0,
+ MM_ATTRS_VALID_TYPE_INT_RANGE,
+ 0,
+ -1,
+ _mmcamcorder_commit_detect,
+ },
+ //79
+ {
+ MM_CAM_DETECT_FOCUS_SELECT,
+ "detect-focus-select",
+ MMF_VALUE_TYPE_INT,
+ MM_ATTRS_FLAG_RW,
+ (void*)0,
+ MM_ATTRS_VALID_TYPE_INT_RANGE,
+ 0,
+ -1,
+ _mmcamcorder_commit_detect,
+ },
+ //80
+ {
+ MM_CAM_DETECT_SELECT_NUMBER,
+ "detect-select-number",
+ MMF_VALUE_TYPE_INT,
+ MM_ATTRS_FLAG_RW,
+ (void*)0,
+ MM_ATTRS_VALID_TYPE_INT_RANGE,
+ 0,
+ -1,
+ _mmcamcorder_commit_detect,
+ },
+ //81
+ {
+ MM_CAM_DETECT_STATUS,
+ "detect-status",
+ MMF_VALUE_TYPE_INT,
+ MM_ATTRS_FLAG_RW,
+ (void*)0,
+ MM_ATTRS_VALID_TYPE_INT_ARRAY,
+ 0,
+ 0,
+ _mmcamcorder_commit_detect,
+ },
+ //82
+ {
+ MM_CAM_CAPTURE_ZERO_SYSTEMLAG,
+ "capture-zero-systemlag",
+ MMF_VALUE_TYPE_INT,
+ MM_ATTRS_FLAG_RW,
+ (void*)FALSE,
+ MM_ATTRS_VALID_TYPE_INT_RANGE,
+ 0,
+ 1,
+ NULL,
+ },
+ //83
+ {
+ MM_CAM_CAMERA_AF_TOUCH_X,
+ "camera-af-touch-x",
+ MMF_VALUE_TYPE_INT,
+ MM_ATTRS_FLAG_RW,
+ (void*)0,
+ MM_ATTRS_VALID_TYPE_INT_RANGE,
+ 0,
+ _MMCAMCORDER_MAX_INT,
+ _mmcamcorder_commit_camera_af_touch_area,
+ },
+ //84
+ {
+ MM_CAM_CAMERA_AF_TOUCH_Y,
+ "camera-af-touch-y",
+ MMF_VALUE_TYPE_INT,
+ MM_ATTRS_FLAG_RW,
+ (void*)0,
+ MM_ATTRS_VALID_TYPE_INT_RANGE,
+ 0,
+ _MMCAMCORDER_MAX_INT,
+ _mmcamcorder_commit_camera_af_touch_area,
+ },
+ //85
+ {
+ MM_CAM_CAMERA_AF_TOUCH_WIDTH,
+ "camera-af-touch-width",
+ MMF_VALUE_TYPE_INT,
+ MM_ATTRS_FLAG_RW,
+ (void*)0,
+ MM_ATTRS_VALID_TYPE_INT_RANGE,
+ 0,
+ _MMCAMCORDER_MAX_INT,
+ _mmcamcorder_commit_camera_af_touch_area,
+ },
+ //86
+ {
+ MM_CAM_CAMERA_AF_TOUCH_HEIGHT,
+ "camera-af-touch-height",
+ MMF_VALUE_TYPE_INT,
+ MM_ATTRS_FLAG_RW,
+ (void*)0,
+ MM_ATTRS_VALID_TYPE_INT_RANGE,
+ 0,
+ _MMCAMCORDER_MAX_INT,
+ _mmcamcorder_commit_camera_af_touch_area,
+ },
+ //87
+ {
+ MM_CAM_CAMERA_FOCAL_LENGTH,
+ "camera-focal-length",
+ MMF_VALUE_TYPE_DOUBLE,
+ MM_ATTRS_FLAG_RW,
+ (void*)0,
+ MM_ATTRS_VALID_TYPE_DOUBLE_RANGE,
+ 0,
+ 1000,
+ _mmcamcorder_commit_camera_capture_mode,
+ },
+ //88
+ {
+ MM_CAM_RECOMMEND_PREVIEW_FORMAT_FOR_CAPTURE,
+ "recommend-preview-format-for-capture",
+ MMF_VALUE_TYPE_INT,
+ MM_ATTRS_FLAG_RW,
+ (void*)MM_PIXEL_FORMAT_YUYV,
+ MM_ATTRS_VALID_TYPE_INT_RANGE,
+ MM_PIXEL_FORMAT_NV12,
+ MM_PIXEL_FORMAT_ENCODED,
+ NULL,
+ },
+ //89
+ {
+ MM_CAM_RECOMMEND_PREVIEW_FORMAT_FOR_RECORDING,
+ "recommend-preview-format-for-recording",
+ MMF_VALUE_TYPE_INT,
+ MM_ATTRS_FLAG_RW,
+ (void*)MM_PIXEL_FORMAT_NV12,
+ MM_ATTRS_VALID_TYPE_INT_RANGE,
+ MM_PIXEL_FORMAT_NV12,
+ MM_PIXEL_FORMAT_ENCODED,
+ NULL,
+ },
+ //90
+ {
+ MM_CAM_CAPTURE_THUMBNAIL,
+ "capture-thumbnail",
+ MMF_VALUE_TYPE_INT,
+ MM_ATTRS_FLAG_RW,
+ (void*)TRUE,
+ MM_ATTRS_VALID_TYPE_NONE,
+ 0,
+ 0,
+ NULL,
+ },
+ //91
+ {
+ MM_CAM_TAG_GPS_ENABLE,
+ "tag-gps-enable",
+ MMF_VALUE_TYPE_INT,
+ MM_ATTRS_FLAG_RW,
+ (void*)TRUE,
+ MM_ATTRS_VALID_TYPE_INT_RANGE,
+ 0,
+ 1,
+ NULL,
+ },
+ //92
+ {
+ MM_CAM_TAG_GPS_TIME_STAMP,
+ "tag-gps-time-stamp",
+ MMF_VALUE_TYPE_DOUBLE,
+ MM_ATTRS_FLAG_RW,
+ (void*)0,
+ MM_ATTRS_VALID_TYPE_NONE,
+ 0,
+ 0,
+ NULL,
+ },
+ //93
+ {
+ MM_CAM_TAG_GPS_DATE_STAMP,
+ "tag-gps-date-stamp",
+ MMF_VALUE_TYPE_STRING,
+ MM_ATTRS_FLAG_RW,
+ NULL,
+ MM_ATTRS_VALID_TYPE_NONE,
+ 0,
+ 0,
+ NULL,
+ },
+ //94
+ {
+ MM_CAM_TAG_GPS_PROCESSING_METHOD,
+ "tag-gps-processing-method",
+ MMF_VALUE_TYPE_STRING,
+ MM_ATTRS_FLAG_RW,
+ NULL,
+ MM_ATTRS_VALID_TYPE_NONE,
+ 0,
+ 0,
+ NULL,
+ },
+ //95
+ {
+ MM_CAM_CAMERA_ROTATION,
+ "camera-rotation",
+ MMF_VALUE_TYPE_INT,
+ MM_ATTRS_FLAG_RW,
+ (void*)MM_VIDEO_INPUT_ROTATION_NONE,
+ MM_ATTRS_VALID_TYPE_INT_ARRAY,
+ (int)video_input_rotation,
+ ARRAY_SIZE(video_input_rotation),
+ _mmcamcorder_commit_camera_rotate,
+ },
+ //96
+ {
+ MM_CAM_ENABLE_CONVERTED_STREAM_CALLBACK,
+ "enable-converted-stream-callback",
+ MMF_VALUE_TYPE_INT,
+ MM_ATTRS_FLAG_RW,
+ (void*)0,
+ MM_ATTRS_VALID_TYPE_INT_RANGE,
+ 0,
+ 1,
+ NULL,
+ },
+ //97
+ {
+ MM_CAM_CAPTURED_SCREENNAIL,
+ "captured-screennail",
+ MMF_VALUE_TYPE_DATA,
+ MM_ATTRS_FLAG_RW,
+ (void*)NULL,
+ MM_ATTRS_VALID_TYPE_NONE,
+ 0,
+ 0,
+ NULL,
+ },
+ //98
+ {
+ MM_CAM_CAPTURE_SOUND_ENABLE,
+ "capture-sound-enable",
+ MMF_VALUE_TYPE_INT,
+ MM_ATTRS_FLAG_RW,
+ (void*)FALSE,
+ MM_ATTRS_VALID_TYPE_INT_RANGE,
+ 0,
+ 1,
+ NULL,
+ },
+ //99
+ {
+ MM_CAM_RECOMMEND_DISPLAY_ROTATION,
+ "recommend-display-rotation",
+ MMF_VALUE_TYPE_INT,
+ MM_ATTRS_FLAG_RW,
+ (void*)MM_DISPLAY_ROTATION_270,
+ MM_ATTRS_VALID_TYPE_INT_RANGE,
+ MM_DISPLAY_ROTATION_NONE,
+ MM_DISPLAY_ROTATION_FLIP_VERT,
+ NULL,
+ },
+ //100
+ {
+ MM_CAM_CAMCORDER_ROTATION,
+ "camcorder-rotation",
+ MMF_VALUE_TYPE_INT,
+ MM_ATTRS_FLAG_RW,
+ (void*)MM_VIDEO_INPUT_ROTATION_NONE,
+ MM_ATTRS_VALID_TYPE_INT_RANGE,
+ MM_VIDEO_INPUT_ROTATION_NONE,
+ MM_VIDEO_INPUT_ROTATION_270,
+ _mmcamcorder_commit_camcorder_rotate,
+ },
+};
+
+
+/*---------------------------------------------------------------------------
+| LOCAL VARIABLE DEFINITIONS for internal |
+---------------------------------------------------------------------------*/
+/* Readonly attributes list.
+* If you want to make some attributes read only, write down here.
+* It will make them read only after composing whole attributes.
+*/
+
+static int readonly_attributes[] = {
+ MM_CAM_CAMERA_DEVICE,
+ MM_CAM_CAMERA_DEVICE_NAME,
+ MM_CAM_CAMERA_SHUTTER_SPEED,
+ MM_CAM_RECOMMEND_PREVIEW_FORMAT_FOR_CAPTURE,
+ MM_CAM_RECOMMEND_PREVIEW_FORMAT_FOR_RECORDING,
+ MM_CAM_CAPTURED_SCREENNAIL,
+ MM_CAM_RECOMMEND_DISPLAY_ROTATION,
+};
+
+/*---------------------------------------------------------------------------
+| LOCAL FUNCTION PROTOTYPES: |
+---------------------------------------------------------------------------*/
+/* STATIC INTERNAL FUNCTION */
+static bool __mmcamcorder_set_capture_resolution(MMHandleType handle, int width, int height);
+static bool __mmcamcorder_set_camera_resolution(MMHandleType handle, int width, int height);
+static int __mmcamcorder_set_conf_to_valid_info(MMHandleType handle);
+static bool __mmcamcorder_attrs_is_supported(MMHandleType handle, int idx);
+static int __mmcamcorder_check_valid_pair(MMHandleType handle, char **err_attr_name, const char *attribute_name, va_list var_args);
+
+/*===========================================================================================
+| |
+| FUNCTION DEFINITIONS |
+| |
+========================================================================================== */
+/*---------------------------------------------------------------------------
+| GLOBAL FUNCTION DEFINITIONS: |
+---------------------------------------------------------------------------*/
+MMHandleType
+_mmcamcorder_alloc_attribute( MMHandleType handle, MMCamPreset *info )
+{
+ _mmcam_dbg_log( "" );
+
+ MMHandleType attrs = 0;
+ mmf_attrs_construct_info_t * attrs_const_info = NULL;
+ int attr_count = 0;
+ int idx;
+
+ /* Create attribute constructor */
+ _mmcam_dbg_log( "start" );
+ //set runtime values to 'cam_attrs_const_info'
+ {
+ cam_attrs_const_info[MM_CAM_CAMERA_DEVICE].default_value = (void*)info->videodev_type;
+ }
+
+ //alloc 'mmf_attrs_construct_info_t'
+ attr_count = ARRAY_SIZE( cam_attrs_const_info );
+ attrs_const_info = malloc(attr_count * sizeof(mmf_attrs_construct_info_t));
+
+ if (!attrs_const_info)
+ {
+ _mmcam_dbg_err( "Fail to alloc constructor." );
+ return 0;
+ }
+
+ for (idx = 0; idx < attr_count; idx++)
+ {
+ //attribute order check.
+ if (idx != cam_attrs_const_info[idx].attrid) //This should be same.
+ {
+ _mmcam_dbg_err( "Please check attributes order. Is the idx same with enum val?" );
+ return 0;
+ }
+
+ attrs_const_info[idx].name = cam_attrs_const_info[idx].name;
+ attrs_const_info[idx].value_type = cam_attrs_const_info[idx].value_type;
+ attrs_const_info[idx].flags = cam_attrs_const_info[idx].flags;
+ attrs_const_info[idx].default_value = cam_attrs_const_info[idx].default_value;
+ }
+
+ /* Camcorder Attributes */
+ _mmcam_dbg_log( "Create Camcorder Attributes[%p, %d]", attrs_const_info, attr_count);
+
+ attrs = mmf_attrs_new_from_data( "Camcorder_Attributes",
+ attrs_const_info,
+ attr_count,
+ _mmcamcorder_commit_camcorder_attrs,
+ (void*)handle );
+
+ free(attrs_const_info);
+ attrs_const_info = NULL;
+
+ if( attrs == 0 )
+ {
+ _mmcam_dbg_err( "Fail to alloc attribute handle" );
+ return 0;
+ }
+
+ __mmcamcorder_set_conf_to_valid_info(handle);
+
+ for (idx = 0; idx < attr_count; idx++)
+ {
+/* _mmcam_dbg_log("Valid type [%s:%d, %d, %d]", cam_attrs_const_info[idx].name, cam_attrs_const_info[idx].validity_type
+ , cam_attrs_const_info[idx].validity_value1, cam_attrs_const_info[idx].validity_value2);
+*/
+ mmf_attrs_set_valid_type (attrs, idx, cam_attrs_const_info[idx].validity_type);
+
+ switch (cam_attrs_const_info[idx].validity_type)
+ {
+ case MM_ATTRS_VALID_TYPE_INT_ARRAY:
+ if ((cam_attrs_const_info[idx].validity_value1) &&(cam_attrs_const_info[idx].validity_value2 > 0))
+ mmf_attrs_set_valid_array (attrs, idx, (const int*)(cam_attrs_const_info[idx].validity_value1), cam_attrs_const_info[idx].validity_value2);
+ break;
+ case MM_ATTRS_VALID_TYPE_INT_RANGE:
+ mmf_attrs_set_valid_range (attrs, idx, cam_attrs_const_info[idx].validity_value1, cam_attrs_const_info[idx].validity_value2);
+ break;
+ case MM_ATTRS_VALID_TYPE_DOUBLE_ARRAY:
+ if ((cam_attrs_const_info[idx].validity_value1) &&(cam_attrs_const_info[idx].validity_value2 > 0))
+ mmf_attrs_set_valid_double_array (attrs, idx, (const double*)(cam_attrs_const_info[idx].validity_value1), cam_attrs_const_info[idx].validity_value2);
+ break;
+ case MM_ATTRS_VALID_TYPE_DOUBLE_RANGE:
+ mmf_attrs_set_valid_double_range (attrs, idx, (double)cam_attrs_const_info[idx].validity_value1, (double)cam_attrs_const_info[idx].validity_value2);
+ break;
+ case MM_ATTRS_VALID_TYPE_NONE:
+ break;
+ case MM_ATTRS_VALID_TYPE_INVALID:
+ default:
+ _mmcam_dbg_err("Valid type error.");
+ break;
+ }
+ }
+
+ return attrs;
+}
+
+
+void
+_mmcamcorder_dealloc_attribute(MMHandleType attrs)
+{
+ _mmcam_dbg_log("");
+
+ if (attrs)
+ {
+ mmf_attrs_free(attrs);
+
+ _mmcam_dbg_log("released attribute");
+ }
+}
+
+
+int
+_mmcamcorder_get_attributes(MMHandleType handle, char **err_attr_name, const char *attribute_name, va_list var_args)
+{
+ MMHandleType attrs = 0;
+ int ret = MM_ERROR_NONE;
+
+ mmf_return_val_if_fail( handle, MM_ERROR_CAMCORDER_INVALID_ARGUMENT );
+// mmf_return_val_if_fail( err_attr_name, MM_ERROR_CAMCORDER_INVALID_ARGUMENT );
+
+ attrs = MMF_CAMCORDER_ATTRS(handle);
+ mmf_return_val_if_fail( attrs, MM_ERROR_CAMCORDER_NOT_INITIALIZED );
+
+ ret = mm_attrs_get_valist (attrs, err_attr_name, attribute_name, var_args);
+
+ return ret;
+}
+
+
+int
+_mmcamcorder_set_attributes(MMHandleType handle, char **err_attr_name, const char *attribute_name, va_list var_args)
+{
+ MMHandleType attrs = 0;
+ int ret = MM_ERROR_NONE;
+
+ mmf_return_val_if_fail( handle, MM_ERROR_CAMCORDER_INVALID_ARGUMENT );
+// mmf_return_val_if_fail( err_attr_name, MM_ERROR_CAMCORDER_INVALID_ARGUMENT );
+
+ attrs = MMF_CAMCORDER_ATTRS(handle);
+ mmf_return_val_if_fail( attrs, MM_ERROR_CAMCORDER_NOT_INITIALIZED );
+
+ __ta__( "__mmcamcorder_check_valid_pair",
+ ret = __mmcamcorder_check_valid_pair( handle, err_attr_name, attribute_name, var_args );
+ );
+
+ if( ret == MM_ERROR_NONE )
+ {
+ ret = mm_attrs_set_valist (attrs, err_attr_name, attribute_name, var_args);
+ }
+
+ return ret;
+}
+
+
+int
+_mmcamcorder_get_attribute_info(MMHandleType handle, const char *attr_name, MMCamAttrsInfo *info)
+{
+ MMHandleType attrs = 0;
+ MMAttrsInfo attrinfo;
+ int ret = MM_ERROR_NONE;
+
+ mmf_return_val_if_fail( handle, MM_ERROR_CAMCORDER_INVALID_ARGUMENT );
+ mmf_return_val_if_fail( attr_name, MM_ERROR_CAMCORDER_INVALID_ARGUMENT );
+ mmf_return_val_if_fail( info, MM_ERROR_CAMCORDER_INVALID_ARGUMENT );
+
+ attrs = MMF_CAMCORDER_ATTRS(handle);
+ mmf_return_val_if_fail( attrs, MM_ERROR_CAMCORDER_INVALID_ARGUMENT);
+
+ ret = mm_attrs_get_info_by_name(attrs, attr_name, (MMAttrsInfo*)&attrinfo);
+
+ if (ret == MM_ERROR_NONE)
+ {
+ memset(info, 0x00, sizeof(MMCamAttrsInfo));
+ info->type = attrinfo.type;
+ info->flag = attrinfo.flag;
+ info->validity_type= attrinfo.validity_type;
+
+ switch(attrinfo.validity_type)
+ {
+ case MM_ATTRS_VALID_TYPE_INT_ARRAY:
+ info->int_array.array = attrinfo.int_array.array;
+ info->int_array.count = attrinfo.int_array.count;
+ info->int_array.def = 0;
+ break;
+ case MM_ATTRS_VALID_TYPE_INT_RANGE:
+ info->int_range.min = attrinfo.int_range.min;
+ info->int_range.max = attrinfo.int_range.max;
+ info->int_range.def = 0;
+ break;
+ case MM_ATTRS_VALID_TYPE_DOUBLE_ARRAY:
+ info->double_array.array = attrinfo.double_array.array;
+ info->double_array.count = attrinfo.double_array.count;
+ info->double_array.def = 0;
+ break;
+ case MM_ATTRS_VALID_TYPE_DOUBLE_RANGE:
+ info->double_range.min = attrinfo.double_range.min;
+ info->double_range.max = attrinfo.double_range.max;
+ info->double_range.def = 0;
+ break;
+ case MM_ATTRS_VALID_TYPE_NONE:
+ break;
+ case MM_ATTRS_VALID_TYPE_INVALID:
+ default:
+ break;
+ }
+ }
+
+ return ret;
+}
+
+
+//attribute commiter
+void
+__mmcamcorder_print_attrs (const char *attr_name, const mmf_value_t *value, char* cmt_way)
+{
+ switch(value->type)
+ {
+ case MMF_VALUE_TYPE_INT:
+ _mmcam_dbg_log("%s :(%s:%d)", cmt_way, attr_name, value->value.i_val);
+ break;
+ case MMF_VALUE_TYPE_DOUBLE:
+ _mmcam_dbg_log("%s :(%s:%f)", cmt_way, attr_name, value->value.d_val);
+ break;
+ case MMF_VALUE_TYPE_STRING:
+ _mmcam_dbg_log("%s :(%s:%s)", cmt_way, attr_name, value->value.s_val);
+ break;
+ case MMF_VALUE_TYPE_DATA:
+ _mmcam_dbg_log("%s :(%s:%p)", cmt_way, attr_name, value->value.p_val);
+ break;
+ }
+
+ return;
+}
+
+bool
+_mmcamcorder_commit_camcorder_attrs (int attr_idx, const char *attr_name, const mmf_value_t *value, void *commit_param)
+{
+ bool bret = FALSE;
+
+ mmf_return_val_if_fail(commit_param, FALSE);
+ mmf_return_val_if_fail(attr_idx >= 0, FALSE);
+ mmf_return_val_if_fail(attr_name, FALSE);
+ mmf_return_val_if_fail(value, FALSE);
+
+ if (cam_attrs_const_info[attr_idx].attr_commit)
+ {
+// _mmcam_dbg_log("Dynamic commit:(%s)", attr_name);
+ __mmcamcorder_print_attrs(attr_name, value, "Dynamic");
+ bret = cam_attrs_const_info[attr_idx].attr_commit((MMHandleType)commit_param, attr_idx, value);
+ }
+ else
+ {
+// _mmcam_dbg_log("Static commit:(%s)", attr_name);
+ __mmcamcorder_print_attrs(attr_name, value, "Static");
+ bret = TRUE;
+ }
+
+ return bret;
+}
+
+
+int
+__mmcamcorder_set_conf_to_valid_info(MMHandleType handle)
+{
+ //mmf_camcorder_t *hcamcorder= MMF_CAMCORDER(handle);
+ int *format = NULL;
+ int total_count = 0;
+
+ /* Audio encoder */
+ total_count = _mmcamcorder_get_available_format(handle, CONFIGURE_CATEGORY_MAIN_AUDIO_ENCODER, &format);
+ cam_attrs_const_info[MM_CAM_AUDIO_ENCODER].validity_value1 = (int)format;
+ cam_attrs_const_info[MM_CAM_AUDIO_ENCODER].validity_value2 = (int)total_count;
+
+ /* Video encoder */
+ total_count = _mmcamcorder_get_available_format(handle, CONFIGURE_CATEGORY_MAIN_VIDEO_ENCODER, &format);
+ cam_attrs_const_info[MM_CAM_VIDEO_ENCODER].validity_value1 = (int)format;
+ cam_attrs_const_info[MM_CAM_VIDEO_ENCODER].validity_value2 = (int)total_count;
+
+ /* Image encoder */
+ total_count = _mmcamcorder_get_available_format(handle, CONFIGURE_CATEGORY_MAIN_IMAGE_ENCODER, &format);
+ cam_attrs_const_info[MM_CAM_IMAGE_ENCODER].validity_value1 = (int)format;
+ cam_attrs_const_info[MM_CAM_IMAGE_ENCODER].validity_value2 = (int)total_count;
+
+ /* File format */
+ total_count = _mmcamcorder_get_available_format(handle, CONFIGURE_CATEGORY_MAIN_MUX, &format);
+ cam_attrs_const_info[MM_CAM_FILE_FORMAT].validity_value1 = (int)format;
+ cam_attrs_const_info[MM_CAM_FILE_FORMAT].validity_value2 = (int)total_count;
+
+ return MM_ERROR_NONE;
+}
+
+
+bool _mmcamcorder_commit_capture_width (MMHandleType handle, int attr_idx, const mmf_value_t *value)
+{
+ MMHandleType attr = 0;
+ int current_state = MM_CAMCORDER_STATE_NONE;
+
+ attr = MMF_CAMCORDER_ATTRS(handle);
+ mmf_return_val_if_fail(attr, FALSE);
+
+ _mmcam_dbg_log("(%d)", attr_idx);
+
+ current_state = _mmcamcorder_get_state( handle);
+
+ if( !_mmcamcorder_is_state_changing(handle)
+ && ( current_state == MM_CAMCORDER_STATE_NULL
+ || current_state == MM_CAMCORDER_STATE_READY
+ || current_state == MM_CAMCORDER_STATE_PREPARE ) )
+ {
+ int flags = MM_ATTRS_FLAG_NONE;
+ int capture_width, capture_height;
+ MMCamAttrsInfo info;
+
+ mm_camcorder_get_attribute_info(handle, MMCAM_CAPTURE_HEIGHT, &info);
+ flags = info.flag;
+
+ if (!(flags & MM_ATTRS_FLAG_MODIFIED))
+ {
+ mm_camcorder_get_attributes(handle, NULL, MMCAM_CAPTURE_HEIGHT, &capture_height, NULL);
+ capture_width = value->value.i_val;
+
+ /* Check whether they are valid pair */
+ return __mmcamcorder_set_capture_resolution(handle, capture_width, capture_height);
+ }
+
+ return TRUE;
+ }
+ else
+ {
+ _mmcam_dbg_log("Capture resolution can't be set.(state=%d)", current_state);
+ return FALSE;
+ }
+}
+
+
+bool _mmcamcorder_commit_capture_height (MMHandleType handle, int attr_idx, const mmf_value_t *value)
+{
+ int current_state = MM_CAMCORDER_STATE_NONE;
+
+ current_state = _mmcamcorder_get_state( handle);
+
+ if( current_state == MM_CAMCORDER_STATE_NULL
+ || current_state == MM_CAMCORDER_STATE_READY
+ || current_state == MM_CAMCORDER_STATE_PREPARE )
+ {
+ int capture_width, capture_height;
+
+ mm_camcorder_get_attributes(handle, NULL, MMCAM_CAPTURE_WIDTH, &capture_width, NULL);
+ capture_height = value->value.i_val;
+
+ return __mmcamcorder_set_capture_resolution(handle, capture_width, capture_height);
+ }
+ else
+ {
+ _mmcam_dbg_log("Capture resolution can't be set.(state=%d)", current_state);
+ return FALSE;
+ }
+}
+
+
+bool _mmcamcorder_commit_capture_break_cont_shot (MMHandleType handle, int attr_idx, const mmf_value_t *value)
+{
+ int current_state = _mmcamcorder_get_state( handle);
+ int ivalue = value->value.i_val;
+
+ mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
+ _MMCamcorderSubContext *sc = NULL;
+ GstCameraControl *control = NULL;
+ type_element *VideosrcElement = NULL;
+
+ char* videosrc_name = NULL;
+
+ _mmcamcorder_conf_get_element( hcamcorder->conf_main,
+ CONFIGURE_CATEGORY_MAIN_VIDEO_INPUT,
+ "VideosrcElement",
+ &VideosrcElement );
+ _mmcamcorder_conf_get_value_element_name( VideosrcElement, &videosrc_name );
+
+ sc = MMF_CAMCORDER_SUBCONTEXT(handle);
+ if (!sc)
+ return TRUE;
+
+ if( ivalue && current_state == MM_CAMCORDER_STATE_CAPTURING )
+ {
+ if( !strcmp( videosrc_name, "avsysvideosrc" ) || !strcmp( videosrc_name, "camerasrc" ) )
+ {
+ 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;
+ }
+
+ control = GST_CAMERA_CONTROL( sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst );
+
+ 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 );
+ }
+ else
+ {
+ _mmcam_dbg_warn( "Another videosrc plugin[%s] is not supported yet.", videosrc_name );
+ }
+ }
+ else
+ {
+ _mmcam_dbg_warn( "Commit Break continuous shot : No effect. value[%d],current state[%d]", ivalue, current_state );
+ }
+
+ return TRUE;
+}
+
+
+bool _mmcamcorder_commit_capture_count (MMHandleType handle, int attr_idx, const mmf_value_t *value)
+{
+ int ret = FALSE;
+ int cap_count = 0;
+ int mode = MM_CAMCORDER_MODE_IMAGE;
+
+ mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
+
+ mmf_return_val_if_fail(hcamcorder, FALSE);
+
+ cap_count = value->value.i_val;
+
+ mm_camcorder_get_attributes(handle, NULL, MMCAM_MODE, &mode, NULL);
+ if (mode == MM_CAMCORDER_MODE_IMAGE) {
+ if (cap_count > 1) {
+ __ta__("_mmcamcorder_sound_init",
+ ret = _mmcamcorder_sound_init(handle, _MMCAMCORDER_FILEPATH_CAPTURE2_SND);
+ );
+ if (ret == TRUE) {
+ __ta__("_mmcamcorder_sound_prepare",
+ ret = _mmcamcorder_sound_prepare(handle);
+ );
+ _mmcam_dbg_log("sound prepare [%d]", ret);
+ }
+ } else if (cap_count == 1) {
+ __ta__("_mmcamcorder_sound_finalize",
+ ret = _mmcamcorder_sound_finalize(handle);
+ );
+ _mmcam_dbg_log("sound finalize [%d]", ret);
+ }
+ }
+
+ _mmcam_dbg_log("Capture Count(%d)", cap_count);
+
+ return TRUE;
+}
+
+
+bool _mmcamcorder_commit_audio_volume (MMHandleType handle, int attr_idx, const mmf_value_t *value)
+{
+ int current_state = MM_CAMCORDER_STATE_NONE;
+ _MMCamcorderSubContext *sc = NULL;
+ bool bret = FALSE;
+
+ sc = MMF_CAMCORDER_SUBCONTEXT(handle);
+ if (!sc)
+ return TRUE;
+
+ current_state = _mmcamcorder_get_state( handle);
+
+ if ((current_state == MM_CAMCORDER_STATE_RECORDING)||(current_state == MM_CAMCORDER_STATE_PAUSED))
+ {
+ double mslNewVal = 0;
+ mslNewVal = value->value.d_val;
+
+ if (sc->element[_MMCAMCORDER_AUDIOSRC_VOL].gst)
+ {
+ if(mslNewVal == 0.0)
+ {
+ //Because data probe of audio src do the same job, it doesn't need to set mute here. Already null raw data.
+// MMCAMCORDER_G_OBJECT_SET( sc->element[_MMCAMCORDER_AUDIOSRC_VOL].gst, "mute", TRUE);
+ MMCAMCORDER_G_OBJECT_SET( sc->element[_MMCAMCORDER_AUDIOSRC_VOL].gst, "volume", 1.0);
+ }
+ else
+ {
+ MMCAMCORDER_G_OBJECT_SET( sc->element[_MMCAMCORDER_AUDIOSRC_VOL].gst, "mute", FALSE);
+ MMCAMCORDER_G_OBJECT_SET( sc->element[_MMCAMCORDER_AUDIOSRC_VOL].gst, "volume", mslNewVal);
+ }
+ }
+
+ _mmcam_dbg_log("Commit : volume(%f)", mslNewVal);
+ bret = TRUE;
+ }
+ else
+ {
+ _mmcam_dbg_log("Commit : nothing to commit. status(%d)", current_state);
+ bret = TRUE;
+ }
+ return bret;
+
+}
+
+
+bool _mmcamcorder_commit_camera_fps (MMHandleType handle, int attr_idx, const mmf_value_t *value)
+{
+ _mmcam_dbg_log("FPS(%d)", value->value.i_val);
+ return TRUE;
+}
+
+
+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;
+ int width, height;
+
+ attr = MMF_CAMCORDER_ATTRS(handle);
+ mmf_return_val_if_fail(attr, FALSE);
+
+ _mmcam_dbg_log("Width(%d)", value->value.i_val);
+
+ current_state = _mmcamcorder_get_state( handle);
+
+ if ((current_state > MM_CAMCORDER_STATE_READY) || _mmcamcorder_is_state_changing( handle ) ) {
+ _mmcam_dbg_log("Resolution can't be changed.(state=%d)", current_state);
+ return FALSE;
+ } else {
+ int flags = MM_ATTRS_FLAG_NONE;
+ MMCamAttrsInfo info;
+ mm_camcorder_get_attribute_info(handle, MMCAM_CAMERA_HEIGHT, &info);
+ flags = info.flag;
+
+ if (!(flags & MM_ATTRS_FLAG_MODIFIED)) {
+ mm_camcorder_get_attributes(handle, NULL, MMCAM_CAMERA_HEIGHT, &height, NULL);
+ width = value->value.i_val;
+ //This means that width is changed while height isn't changed. So call _mmcamcorder_commit_camera_height forcely.
+ _mmcam_dbg_log("Call _mmcamcorder_commit_camera_height");
+ return __mmcamcorder_set_camera_resolution(handle, width, height);
+ }
+ return TRUE;
+ }
+}
+
+
+bool _mmcamcorder_commit_camera_height (MMHandleType handle, int attr_idx, const mmf_value_t *value)
+{
+ int width, height;
+ int current_state = MM_CAMCORDER_STATE_NONE;
+ MMHandleType attr = 0;
+
+ attr = MMF_CAMCORDER_ATTRS(handle);
+ mmf_return_val_if_fail(attr, FALSE);
+
+ _mmcam_dbg_log("Height(%d)", value->value.i_val);
+ current_state = _mmcamcorder_get_state( handle);
+
+ if ( (current_state > MM_CAMCORDER_STATE_READY) || _mmcamcorder_is_state_changing( handle )) {
+ _mmcam_dbg_log("Resolution can't be changed.(state=%d)", current_state);
+ return FALSE;
+ } else {
+ height = value->value.i_val;
+ mm_camcorder_get_attributes(handle, NULL, MMCAM_CAMERA_WIDTH, &width, NULL);
+ return __mmcamcorder_set_camera_resolution(handle, width, height);
+ }
+}
+
+
+bool _mmcamcorder_commit_camera_zoom (MMHandleType handle, int attr_idx, const mmf_value_t *value)
+{
+ _MMCamcorderSubContext *sc = NULL;
+ int current_state = MM_CAMCORDER_STATE_NONE;
+ GstCameraControl *control = NULL;
+ int zoom_level = value->value.i_val;
+ int zoom_type;
+
+ sc = MMF_CAMCORDER_SUBCONTEXT(handle);
+ mmf_return_val_if_fail(sc, TRUE);
+
+ _mmcam_dbg_log("(%d)", attr_idx);
+
+ current_state = _mmcamcorder_get_state(handle);
+
+ if (current_state < MM_CAMCORDER_STATE_PREPARE) {
+ return TRUE;
+ }
+
+ if (attr_idx == MM_CAM_CAMERA_OPTICAL_ZOOM) {
+ zoom_type = GST_CAMERA_CONTROL_OPTICAL_ZOOM;
+ } else {
+ zoom_type = GST_CAMERA_CONTROL_DIGITAL_ZOOM;
+ }
+
+ if (sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst) {
+ int ret = FALSE;
+
+ if (!GST_IS_CAMERA_CONTROL(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst)) {
+ _mmcam_dbg_log("Can't cast Video source into camera control.");
+ return TRUE;
+ }
+
+ control = GST_CAMERA_CONTROL (sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst);
+
+ __ta__(" gst_camera_control_set_zoom",
+ ret = gst_camera_control_set_zoom(control, zoom_type, zoom_level);
+ );
+
+ if (ret) {
+ _mmcam_dbg_log("Succeed in operating Zoom[%d].", zoom_level);
+ return TRUE;
+ } else {
+ _mmcam_dbg_warn("Failed to operate Zoom. Type[%d],Level[%d]", zoom_type, zoom_level);
+ }
+ } else {
+ _mmcam_dbg_log("pointer of video src is null");
+ }
+
+ return FALSE;
+}
+
+
+bool _mmcamcorder_commit_camera_focus_mode (MMHandleType handle, int attr_idx, const mmf_value_t *value)
+{
+ MMHandleType attr = 0;
+ int current_state = MM_CAMCORDER_STATE_NONE;
+ _MMCamcorderSubContext *sc = NULL;
+ GstCameraControl *control = NULL;
+ int mslVal;
+ int mode, cur_focus_mode, cur_focus_range;
+
+ attr = MMF_CAMCORDER_ATTRS(handle);
+ mmf_return_val_if_fail(attr, FALSE);
+
+ sc = MMF_CAMCORDER_SUBCONTEXT(handle);
+ if (!sc)
+ return TRUE;
+
+ _mmcam_dbg_log("Focus mode(%d)", value->value.i_val);
+
+ current_state = _mmcamcorder_get_state( handle);
+
+ if (current_state < MM_CAMCORDER_STATE_READY) {
+ _mmcam_dbg_log("Focus mode will be changed later.(state=%d)", current_state);
+ return TRUE;
+ }
+
+ if( sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst )
+ {
+ int flags = MM_ATTRS_FLAG_NONE;
+ MMCamAttrsInfo info;
+
+ if (!GST_IS_CAMERA_CONTROL(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst))
+ {
+ _mmcam_dbg_log("Can't cast Video source into camera control.");
+ return TRUE;
+ }
+
+ control = GST_CAMERA_CONTROL (sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst);
+
+ mslVal = value->value.i_val;
+ mode = _mmcamcorder_convert_msl_to_sensor( attr_idx, mslVal );
+
+ mm_camcorder_get_attribute_info(handle, MMCAM_CAMERA_AF_SCAN_RANGE, &info);
+ flags = info.flag;
+
+ if (!(flags & MM_ATTRS_FLAG_MODIFIED))
+ {
+ if( gst_camera_control_get_focus( control, &cur_focus_mode, &cur_focus_range ) )
+ {
+ if( mode != cur_focus_mode )
+ {
+ MMTA_ACUM_ITEM_BEGIN(" gst_camera_control_set_focus", 0);
+ if( gst_camera_control_set_focus( control, mode, cur_focus_range ) )
+ {
+ MMTA_ACUM_ITEM_END(" gst_camera_control_set_focus", 0);
+ //_mmcam_dbg_log( "Succeed in setting AF mode[%d]", mslVal );
+ return TRUE;
+ }
+ else
+ {
+ _mmcam_dbg_warn( "Failed to set AF mode[%d]", mslVal );
+ }
+ MMTA_ACUM_ITEM_END(" gst_camera_control_set_focus", 0);
+ }
+ else
+ {
+ //_mmcam_dbg_log( "No need to set AF mode. Current[%d]", mslVal );
+ return TRUE;
+ }
+ }
+ else
+ {
+ _mmcam_dbg_warn( "Failed to get AF mode, so do not set new AF mode[%d]", mslVal );
+ }
+ }
+ }
+ else
+ {
+ _mmcam_dbg_log("pointer of video src is null");
+ }
+ return TRUE;
+}
+
+
+bool _mmcamcorder_commit_camera_af_scan_range (MMHandleType handle, int attr_idx, const mmf_value_t *value)
+{
+ _MMCamcorderSubContext *sc = NULL;
+ GstCameraControl *control = NULL;
+ int current_state = MM_CAMCORDER_STATE_NONE;
+ int mslVal, newVal;
+ int cur_focus_mode = 0;
+ int cur_focus_range = 0;
+ int msl_mode = MM_CAMCORDER_FOCUS_MODE_NONE;
+ int converted_mode = 0;
+
+ sc = MMF_CAMCORDER_SUBCONTEXT(handle);
+ if (!sc)
+ return TRUE;
+
+ _mmcam_dbg_log("(%d)", attr_idx);
+
+ current_state = _mmcamcorder_get_state( handle);
+
+ mslVal = value->value.i_val;
+ newVal = _mmcamcorder_convert_msl_to_sensor( attr_idx, mslVal );
+
+ 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))
+ {
+ _mmcam_dbg_log("Can't cast Video source into camera control.");
+ return TRUE;
+ }
+
+ control = GST_CAMERA_CONTROL (sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst);
+
+ mm_camcorder_get_attributes(handle, NULL, MMCAM_CAMERA_FOCUS_MODE, &msl_mode, NULL);
+ converted_mode = _mmcamcorder_convert_msl_to_sensor( MM_CAM_CAMERA_FOCUS_MODE, msl_mode );
+
+ if( gst_camera_control_get_focus( control, &cur_focus_mode, &cur_focus_range ) )
+ {
+
+ if (( newVal != cur_focus_range ) || ( converted_mode != cur_focus_mode ))
+ {
+ MMTA_ACUM_ITEM_BEGIN(" gst_camera_control_set_focus", 0);
+ if( gst_camera_control_set_focus( control, converted_mode, newVal ) )
+ {
+ MMTA_ACUM_ITEM_END(" gst_camera_control_set_focus", 0);
+ //_mmcam_dbg_log( "Succeed in setting AF mode[%d]", mslVal );
+ return TRUE;
+ }
+ else
+ {
+ MMTA_ACUM_ITEM_END(" gst_camera_control_set_focus", 0);
+ _mmcam_dbg_warn( "Failed to set AF mode[%d]", mslVal );
+ }
+ }
+ else
+ {
+ //_mmcam_dbg_log( "No need to set AF mode. Current[%d]", mslVal );
+ return TRUE;
+ }
+ }
+ else
+ {
+ _mmcam_dbg_warn( "Failed to get AF mode, so do not set new AF mode[%d]", mslVal );
+ }
+ }
+ else
+ {
+ _mmcam_dbg_log("pointer of video src is null");
+ }
+ return FALSE;
+}
+
+bool _mmcamcorder_commit_camera_af_touch_area (MMHandleType handle, int attr_idx, const mmf_value_t *value)
+{
+ _MMCamcorderSubContext *sc = NULL;
+ GstCameraControl *control = NULL;
+ GstCameraControlRectType set_area = { 0, 0, 0, 0 }, get_area = { 0, 0, 0, 0 };
+
+ int current_state = MM_CAMCORDER_STATE_NONE;
+ int ret = FALSE;
+ int focus_mode = MM_CAMCORDER_FOCUS_MODE_NONE;
+
+ gboolean do_set = FALSE;
+
+ MMCamAttrsInfo info_y, info_w, info_h;
+
+ sc = MMF_CAMCORDER_SUBCONTEXT(handle);
+ if (!sc)
+ return TRUE;
+
+ _mmcam_dbg_log("(%d)", attr_idx);
+
+ 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;
+ }
+
+ 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 );
+ 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;
+ }
+
+ 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;
+ 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 )
+ {
+ control = GST_CAMERA_CONTROL (sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst);
+
+ __ta__( " gst_camera_control_get_focus_area",
+ 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 );
+ return TRUE;
+ }
+
+ __ta__( " gst_camera_control_set_focus_area",
+ 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_log("pointer of video src is null");
+ }
+
+ return FALSE;
+}
+
+
+bool _mmcamcorder_commit_camera_capture_mode (MMHandleType handle, int attr_idx, const mmf_value_t *value)
+{
+ GstCameraControl *control = NULL;
+ int ivalue = value->value.i_val;
+ int mslVal1 = 0, mslVal2 = 0;
+ int newVal1 = 0, newVal2 = 0;
+ int cur_value1 = 0, cur_value2 = 0;
+ int exposure_type = 0;
+ int current_state = MM_CAMCORDER_STATE_NONE;
+ _MMCamcorderSubContext *sc = NULL;
+
+ int scene_mode = MM_CAMCORDER_SCENE_MODE_NORMAL;
+ gboolean check_scene_mode = FALSE;
+
+ sc = MMF_CAMCORDER_SUBCONTEXT(handle);
+ if (!sc)
+ return TRUE;
+
+ current_state = _mmcamcorder_get_state( handle);
+
+ if (current_state < MM_CAMCORDER_STATE_READY) {
+ return TRUE;
+ }
+
+ if (attr_idx == MM_CAM_CAMERA_F_NUMBER) {
+ exposure_type = GST_CAMERA_CONTROL_F_NUMBER;
+ mslVal1 = newVal1 = MM_CAMCORDER_GET_NUMERATOR( ivalue );
+ mslVal2 = newVal2 = MM_CAMCORDER_GET_DENOMINATOR( ivalue );
+ } else if (attr_idx == MM_CAM_CAMERA_SHUTTER_SPEED) {
+ exposure_type = GST_CAMERA_CONTROL_SHUTTER_SPEED;
+ mslVal1 = newVal1 = MM_CAMCORDER_GET_NUMERATOR( ivalue );
+ mslVal2 = newVal2 = MM_CAMCORDER_GET_DENOMINATOR( ivalue );
+ } else if (attr_idx == MM_CAM_CAMERA_ISO) {
+ exposure_type = GST_CAMERA_CONTROL_ISO;
+ mslVal1 = ivalue;
+ newVal1 = _mmcamcorder_convert_msl_to_sensor(attr_idx, mslVal1);
+ check_scene_mode = TRUE;
+ } else if (attr_idx == MM_CAM_CAMERA_EXPOSURE_MODE) {
+ exposure_type = GST_CAMERA_CONTROL_EXPOSURE_MODE;
+ mslVal1 = ivalue;
+ newVal1 = _mmcamcorder_convert_msl_to_sensor(attr_idx, mslVal1);
+ } else if (attr_idx == MM_CAM_CAMERA_EXPOSURE_VALUE) {
+ exposure_type = GST_CAMERA_CONTROL_EXPOSURE_VALUE;
+ mslVal1 = newVal1 = MM_CAMCORDER_GET_NUMERATOR( ivalue );
+ mslVal2 = newVal2 = MM_CAMCORDER_GET_DENOMINATOR( ivalue );
+ }
+
+ if (check_scene_mode) {
+ mm_camcorder_get_attributes(handle, NULL, MMCAM_FILTER_SCENE_MODE, &scene_mode, NULL);
+ if (scene_mode != MM_CAMCORDER_SCENE_MODE_NORMAL) {
+ _mmcam_dbg_warn("can not set [%d] when scene mode is NOT normal.", attr_idx);
+ return FALSE;
+ }
+ }
+
+ 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;
+ }
+
+ control = GST_CAMERA_CONTROL (sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst);
+ if (gst_camera_control_get_exposure(control, exposure_type, &cur_value1, &cur_value2)) {
+ if (newVal1 != cur_value1 || newVal2 != cur_value2) {
+ int ret = 0;
+ __ta__(" gst_camera_control_set_exposure",
+ ret = gst_camera_control_set_exposure(control, exposure_type, newVal1, newVal2);
+ );
+
+ if (ret) {
+ //_mmcam_dbg_log( "Succeed in setting exposure. Type[%d],value1[%d],value2[%d]", exposure_type, mslVal1, mslVal2 );
+ return TRUE;
+ } else {
+ _mmcam_dbg_warn( "Failed to set exposure. Type[%d],value1[%d],value2[%d]", exposure_type, mslVal1, mslVal2 );
+ }
+ } else {
+ //_mmcam_dbg_log( "No need to set exposure. Type[%d],value1[%d],value2[%d]", exposure_type, mslVal1, mslVal2 );
+ return TRUE;
+ }
+ } else {
+ _mmcam_dbg_warn( "Failed to get exposure. Type[%d]", exposure_type );
+ }
+ } else {
+ _mmcam_dbg_log("pointer of video src is null");
+ }
+
+ return FALSE;
+}
+
+
+bool _mmcamcorder_commit_camera_wdr (MMHandleType handle, int attr_idx, const mmf_value_t *value)
+{
+ GstCameraControl *control = NULL;
+ int mslVal = value->value.i_val;
+ int newVal = _mmcamcorder_convert_msl_to_sensor( MM_CAM_CAMERA_WDR, mslVal);
+ int cur_value = 0;
+ _MMCamcorderSubContext *sc = NULL;
+ int current_state = MM_CAMCORDER_STATE_NONE;
+
+ sc = MMF_CAMCORDER_SUBCONTEXT(handle);
+ if (!sc)
+ return TRUE;
+
+ 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))
+ {
+ _mmcam_dbg_log("Can't cast Video source into camera control.");
+ return TRUE;
+ }
+
+ control = GST_CAMERA_CONTROL( sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst );
+
+ if( gst_camera_control_get_wdr( control, &cur_value ) )
+ {
+ if( newVal != cur_value )
+ {
+ if( gst_camera_control_set_wdr( control, newVal ) )
+ {
+ //_mmcam_dbg_log( "Success - set wdr[%d]", mslVal );
+ return TRUE;
+ }
+ else
+ {
+ _mmcam_dbg_warn( "Failed to set WDR. NewVal[%d],CurVal[%d]", newVal, cur_value );
+ }
+ }
+ else
+ {
+ //_mmcam_dbg_log( "No need to set new WDR. Current[%d]", mslVal );
+ return TRUE;
+ }
+ }
+ else
+ {
+ _mmcam_dbg_warn( "Failed to get WDR." );
+ }
+ }
+ else
+ {
+ _mmcam_dbg_log("pointer of video src is null");
+ }
+
+ return FALSE;
+}
+
+
+bool _mmcamcorder_commit_camera_anti_handshake (MMHandleType handle, int attr_idx, const mmf_value_t *value)
+{
+ GstCameraControl *control = NULL;
+ int mslVal = value->value.i_val;
+ int newVal = _mmcamcorder_convert_msl_to_sensor(MM_CAM_CAMERA_ANTI_HANDSHAKE, mslVal);
+ int cur_value = 0;
+ _MMCamcorderSubContext *sc = NULL;
+ int current_state = MM_CAMCORDER_STATE_NONE;
+
+ sc = MMF_CAMCORDER_SUBCONTEXT(handle);
+ if (!sc)
+ return TRUE;
+
+ 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);
+ return TRUE;
+ }
+
+ 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;
+ }
+
+ control = GST_CAMERA_CONTROL (sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst);
+
+ if( gst_camera_control_get_ahs( control, &cur_value ) )
+ {
+ if( newVal != cur_value )
+ {
+ if (gst_camera_control_set_ahs(control, newVal))
+ {
+ //_mmcam_dbg_log("Succeed in operating anti-handshake.");
+ return TRUE;
+ }
+ else
+ {
+ _mmcam_dbg_warn("Failed to operate anti-handshake. value[%d]", newVal);
+ }
+ }
+ else
+ {
+ //_mmcam_dbg_log( "No need to set new Anti-Handshake. Current[%d]", mslVal );
+ return TRUE;
+ }
+ }
+ else
+ {
+ _mmcam_dbg_warn( "Failed to get Anti-Handshake." );
+ }
+ }
+ else
+ {
+ _mmcam_dbg_warn("pointer of video src is null");
+ }
+
+ return FALSE;
+}
+
+
+bool _mmcamcorder_commit_camera_hold_af_after_capturing (MMHandleType handle, int attr_idx, const mmf_value_t *value)
+{
+ _MMCamcorderSubContext *sc = NULL;
+ int current_state = MM_CAMCORDER_STATE_NONE;
+
+ sc = MMF_CAMCORDER_SUBCONTEXT(handle);
+ if (!sc)
+ return TRUE;
+
+ 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);
+ return TRUE;
+ }
+
+ if (sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst)
+ {
+ _mmcam_dbg_log("Commit : value of Hold af after capturing is %d", value->value.i_val);
+ MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst, "hold-af-after-capturing", value->value.i_val);
+ }
+ else
+ _mmcam_dbg_warn("Commit : Hold af after capturing cannot be set");
+
+ return TRUE;
+}
+
+
+bool _mmcamcorder_commit_camera_rotate (MMHandleType handle, int attr_idx, const mmf_value_t *value)
+{
+ int current_state = MM_CAMCORDER_STATE_NONE;
+ gboolean bstate_changing = FALSE;
+
+ _mmcam_dbg_log("rotate(%d)", value->value.i_val);
+
+ current_state = _mmcamcorder_get_state( handle);
+ bstate_changing = _mmcamcorder_is_state_changing( handle);
+
+ if ((current_state > MM_CAMCORDER_STATE_READY) || bstate_changing ) {
+ _mmcam_dbg_err("camera rotation setting failed.(state=%d, is_state_changing(%d))", current_state, bstate_changing);
+ return FALSE;
+ } else {
+ return _mmcamcorder_set_videosrc_rotation( handle, value->value.i_val );
+ }
+}
+
+
+bool _mmcamcorder_commit_image_encoder_quality (MMHandleType handle, int attr_idx, const mmf_value_t *value)
+{
+ _mmcam_dbg_log("Image encoder quality(%d)", value->value.i_val);
+ return TRUE;
+}
+
+
+bool _mmcamcorder_commit_target_filename (MMHandleType handle, int attr_idx, const mmf_value_t *value)
+{
+ mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
+ _MMCamcorderSubContext *sc = NULL;
+ char * filename = NULL;
+ int size = 0;
+
+ sc = MMF_CAMCORDER_SUBCONTEXT(handle);
+ if (!sc)
+ return TRUE;
+
+ //Set basic infomation
+ if (value->type != MM_ATTRS_TYPE_STRING)
+ {
+ _mmcam_dbg_log("Mismatched value type (%d)", value->type);
+ return FALSE;
+ }
+ else
+ {
+ filename = (char*)mmf_value_get_string(value, &size);
+ }
+
+ if (sc->element != NULL)
+ {
+ if ((hcamcorder->type == MM_CAMCORDER_MODE_VIDEO) || (hcamcorder->type == MM_CAMCORDER_MODE_AUDIO))
+ {
+ if (sc->element[_MMCAMCORDER_ENCSINK_BIN].gst != NULL)
+ {
+ if (sc->element[_MMCAMCORDER_ENCSINK_SINK].gst != NULL)
+ {
+ MMCAMCORDER_G_OBJECT_SET( sc->element[_MMCAMCORDER_ENCSINK_SINK].gst, "location", filename);
+ _mmcam_dbg_log("new file location set.(%s)", filename);
+ }
+ else
+ {
+ _mmcam_dbg_warn("filesink is not created.");
+ }
+ }
+ else
+ {
+ _mmcam_dbg_warn("filesink is not created.");
+ }
+ }
+ else
+ {
+ _mmcam_dbg_log("new file location set.(%s)", filename);
+ }
+ }
+ else
+ {
+ _mmcam_dbg_warn("gstreamer pipeline is not created.");
+ }
+ return TRUE;
+}
+
+
+
+
+bool _mmcamcorder_commit_filter (MMHandleType handle, int attr_idx, const mmf_value_t *value)
+{
+ GstColorBalance *balance = NULL;
+ GstColorBalanceChannel *Colorchannel = NULL;
+ const GList *controls = NULL;
+ const GList *item = NULL;
+ int newVal = 0;
+ int mslNewVal = 0;
+ int cur_value = 0;
+ int current_state = MM_CAMCORDER_STATE_NONE;
+ gchar * control_label = NULL;
+ _MMCamcorderSubContext *sc = NULL;
+
+ int scene_mode = MM_CAMCORDER_SCENE_MODE_NORMAL;
+ gboolean check_scene_mode = FALSE;
+
+ sc = MMF_CAMCORDER_SUBCONTEXT(handle);
+ if (!sc)
+ return TRUE;
+
+ current_state = _mmcamcorder_get_state(handle);
+
+ //status check
+ if (current_state < MM_CAMCORDER_STATE_PREPARE) {
+ //_mmcam_dbg_log("It doesn't need to change dynamically.(state=%d)", current_state);
+ return TRUE;
+ }
+
+ if (value->type != MM_ATTRS_TYPE_INT) {
+ _mmcam_dbg_warn("Mismatched value type (%d)", value->type);
+ return FALSE;
+ } else {
+ mslNewVal = value->value.i_val;
+ }
+
+ switch (attr_idx)
+ {
+ case MM_CAM_FILTER_BRIGHTNESS:
+ control_label = "brightness";
+ check_scene_mode = TRUE;
+ break;
+
+ case MM_CAM_FILTER_CONTRAST:
+ control_label = "contrast";
+ break;
+
+ case MM_CAM_FILTER_WB:
+ control_label = "white balance";
+ check_scene_mode = TRUE;
+ break;
+
+ case MM_CAM_FILTER_COLOR_TONE:
+ control_label = "color tone";
+ break;
+
+ case MM_CAM_FILTER_SATURATION:
+ control_label = "saturation";
+ check_scene_mode = TRUE;
+ break;
+
+ case MM_CAM_FILTER_HUE:
+ control_label = "hue";
+ break;
+
+ case MM_CAM_FILTER_SHARPNESS:
+ control_label = "sharpness";
+ check_scene_mode = TRUE;
+ break;
+ }
+
+ if (check_scene_mode) {
+ mm_camcorder_get_attributes(handle, NULL, MMCAM_FILTER_SCENE_MODE, &scene_mode, NULL);
+ if (scene_mode != MM_CAMCORDER_SCENE_MODE_NORMAL) {
+ _mmcam_dbg_warn("can not set %s when scene mode is NOT normal.", control_label);
+ return FALSE;
+ }
+ }
+
+ newVal = _mmcamcorder_convert_msl_to_sensor(attr_idx, mslNewVal);
+ if (newVal == _MMCAMCORDER_SENSOR_ENUM_NONE)
+ return FALSE;
+
+ _mmcam_dbg_log("label(%s): MSL(%d)->Sensor(%d)", control_label, mslNewVal, newVal);
+
+ if (!GST_IS_COLOR_BALANCE(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst))
+ {
+ _mmcam_dbg_log("Can't cast Video source into color balance.");
+ return TRUE;
+ }
+
+ balance = GST_COLOR_BALANCE (sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst);
+
+ controls = gst_color_balance_list_channels (balance);
+ //_mmcam_dbg_log("controls(%x)", controls);
+ if (controls == NULL) {
+ _mmcam_dbg_log("There is no list of colorbalance controls");
+ return FALSE;
+ }
+
+ for (item = controls;item != NULL;item = item->next)
+ {
+ if (item)
+ {
+ if (item->data)
+ {
+ Colorchannel = item->data;
+ //_mmcam_dbg_log("Getting name of CID=(%s), input CID=(%s)", Colorchannel->label, control_label);
+
+ if (strcmp(Colorchannel->label, control_label) == 0)
+ {
+ break;
+ }
+ else
+ Colorchannel = NULL;
+ }
+ }
+ }
+
+ if (Colorchannel== NULL) {
+ _mmcam_dbg_log("There is no data in the colorbalance controls(%d)", attr_idx);
+ return FALSE;
+ }
+
+ //_mmcam_dbg_log("Colorchannel(%x, %s)", Colorchannel, Colorchannel->label);
+
+ cur_value = gst_color_balance_get_value( balance, Colorchannel );
+ _mmcam_dbg_log( "device[cur:%d,new%d]", cur_value, newVal );
+
+ if( newVal != cur_value )
+ {
+ __ta__(" gst_color_balance_set_value",
+ gst_color_balance_set_value (balance, Colorchannel, newVal);
+ );
+ //_mmcam_dbg_log( "Set complete - %s[%d]", Colorchannel->label, mslNewVal );
+ }
+ else
+ {
+ _mmcam_dbg_log( "No need to set %s. Current[%d]", Colorchannel->label, mslNewVal);
+ }
+
+ return TRUE;
+}
+
+
+bool _mmcamcorder_commit_filter_scene_mode (MMHandleType handle, int attr_idx, const mmf_value_t *value)
+{
+ GstCameraControl *control = NULL;
+ int mslVal = value->value.i_val;
+ int newVal = _mmcamcorder_convert_msl_to_sensor( MM_CAM_FILTER_SCENE_MODE, mslVal );
+ int cur_program_mode = MM_CAMCORDER_SCENE_MODE_NORMAL;
+ _MMCamcorderSubContext *sc = NULL;
+ int current_state = MM_CAMCORDER_STATE_NONE;
+
+ sc = MMF_CAMCORDER_SUBCONTEXT(handle);
+ if (!sc)
+ return TRUE;
+
+ 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)) {
+ _mmcam_dbg_log("Can't cast Video source into camera control.");
+ return TRUE;
+ }
+
+ control = GST_CAMERA_CONTROL (sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst);
+ if( gst_camera_control_get_exposure( control, GST_CAMERA_CONTROL_PROGRAM_MODE, &cur_program_mode, NULL ) )
+ {
+ if( newVal != cur_program_mode )
+ {
+ int ret = 0;
+ __ta__(" gst_camera_control_set_exposure:GST_CAMERA_CONTROL_PROGRAM_MODE",
+ ret = gst_camera_control_set_exposure(control, GST_CAMERA_CONTROL_PROGRAM_MODE, newVal, 0);
+ );
+ if (ret) {
+ _mmcam_dbg_log("Succeed in setting program mode[%d].", mslVal);
+
+ if (mslVal == MM_CAMCORDER_SCENE_MODE_NORMAL) {
+ int i = 0;
+ int attr_idxs[] = {
+ MM_CAM_CAMERA_ISO
+ , MM_CAM_FILTER_BRIGHTNESS
+ , MM_CAM_FILTER_WB
+ , MM_CAM_FILTER_SATURATION
+ , MM_CAM_FILTER_SHARPNESS
+ };
+ mmf_attrs_t *attr = (mmf_attrs_t *)MMF_CAMCORDER_ATTRS(handle);
+
+ for (i = 0 ; i < ARRAY_SIZE(attr_idxs) ; i++) {
+ if (__mmcamcorder_attrs_is_supported((MMHandleType)attr, attr_idxs[i])) {
+ mmf_attribute_set_modified(&(attr->items[attr_idxs[i]]));
+ }
+ }
+ }
+
+ return TRUE;
+ } else {
+ _mmcam_dbg_log( "Failed to set program mode[%d].", mslVal );
+ }
+ } else {
+ _mmcam_dbg_log( "No need to set program mode. Current[%d]", mslVal );
+ return TRUE;
+ }
+ } else {
+ _mmcam_dbg_warn( "Failed to get program mode, so do not set new program mode[%d]", mslVal );
+ }
+ } else {
+ _mmcam_dbg_warn("pointer of video src is null");
+ }
+
+ return FALSE;
+}
+
+
+bool _mmcamcorder_commit_filter_flip (MMHandleType handle, int attr_idx, const mmf_value_t *value)
+{
+ _mmcam_dbg_warn("Filter Flip(%d)", value->value.i_val);
+ return TRUE;
+}
+
+
+bool _mmcamcorder_commit_camcorder_rotate(MMHandleType handle, int attr_idx, const mmf_value_t *value)
+{
+ int current_state = MM_CAMCORDER_STATE_NONE;
+ gboolean bstate_changing = FALSE;
+
+ _mmcam_dbg_log("camcorder-rotation(%d)", value->value.i_val);
+ current_state = _mmcamcorder_get_state( handle);
+ bstate_changing = _mmcamcorder_is_state_changing( handle);
+
+ if ((current_state > MM_CAMCORDER_STATE_PREPARE) || bstate_changing ) {
+ _mmcam_dbg_err("camcorder-rotation setting failed.(state=%d, is_state_changing(%d))", current_state, bstate_changing);
+ return FALSE;
+ } else {
+ return TRUE;
+ }
+}
+
+
+bool _mmcamcorder_commit_audio_input_route (MMHandleType handle, int attr_idx, const mmf_value_t *value)
+{
+ _mmcam_dbg_log("Commit : Do nothing. this attr will be removed soon.");
+
+ return TRUE;
+}
+
+
+bool _mmcamcorder_commit_display_handle (MMHandleType handle, int attr_idx, const mmf_value_t *value)
+{
+ _MMCamcorderSubContext *sc = NULL;
+
+ char* videosink_name = NULL;
+
+ sc = MMF_CAMCORDER_SUBCONTEXT(handle);
+ if (!sc)
+ return TRUE;
+
+ if( sc )
+ {
+ _mmcamcorder_conf_get_value_element_name( sc->VideosinkElement, &videosink_name );
+ _mmcam_dbg_log( "Commit : videosinkname[%s]", videosink_name );
+
+ if( !strcmp( videosink_name, "xvimagesink" ) || !strcmp( videosink_name, "xvimagesink" ) )
+ {
+ if( sc->element )
+ {
+ if( sc->element[_MMCAMCORDER_VIDEOSINK_SINK].gst )
+ {
+ _mmcam_dbg_log( "Commit : Set XID[%x]", *(int*)(value->value.p_val) );
+ gst_x_overlay_set_xwindow_id( GST_X_OVERLAY(sc->element[_MMCAMCORDER_VIDEOSINK_SINK].gst), *(int*)(value->value.p_val) );
+ }
+ }
+ }
+ else
+ {
+ _mmcam_dbg_log( "Commit : Nothing to commit with this element[%s]", videosink_name );
+ }
+ }
+ else
+ {
+ _mmcam_dbg_log( "Commit : Nothing to commit with this attribute(MM_CAMCORDER_DISPLAY_HANDLE)" );
+ }
+
+ return TRUE;
+
+}
+
+
+bool _mmcamcorder_commit_display_rotation (MMHandleType handle, int attr_idx, const mmf_value_t *value)
+{
+ mmf_camcorder_t *hcamcorder = NULL;
+ _MMCamcorderSubContext *sc = NULL;
+ int current_state = MM_CAMCORDER_STATE_NONE;
+
+ hcamcorder = MMF_CAMCORDER(handle);
+ if(!hcamcorder)
+ return TRUE;
+ sc = MMF_CAMCORDER_SUBCONTEXT(handle);
+ if (!sc)
+ return TRUE;
+
+ current_state = _mmcamcorder_get_state( handle);
+
+ if( current_state > MM_CAMCORDER_STATE_NULL ) {
+ if( hcamcorder->type != MM_CAMCORDER_MODE_AUDIO ) {
+ return _mmcamcorder_set_display_rotation( handle, value->value.i_val );
+ } else {
+ _mmcam_dbg_warn( "Current Mode is AUDIO only mode." );
+ return FALSE;
+ }
+ } else {
+ _mmcam_dbg_err("display rotation change failed.(state=%d)", current_state);
+ return FALSE;
+ }
+}
+
+
+bool _mmcamcorder_commit_display_visible (MMHandleType handle, int attr_idx, const mmf_value_t *value)
+{
+ mmf_camcorder_t *hcamcorder= MMF_CAMCORDER( handle);
+ _MMCamcorderSubContext *sc = NULL;
+
+ int is_visible = 0;
+ int current_state = MM_CAMCORDER_STATE_NONE;
+ int bret = 0;
+
+ char *videosink_name = NULL;
+
+ sc = MMF_CAMCORDER_SUBCONTEXT(handle);
+ if (!sc)
+ return TRUE;
+ current_state = _mmcamcorder_get_state( handle);
+
+ if( current_state > MM_CAMCORDER_STATE_NULL )
+ {
+ if( hcamcorder->type != MM_CAMCORDER_MODE_AUDIO )
+ {
+ if( sc->element[_MMCAMCORDER_VIDEOSINK_SINK].gst )
+ {
+ // Get videosink name
+ _mmcamcorder_conf_get_value_element_name( sc->VideosinkElement, &videosink_name );
+
+ is_visible = value->value.i_val;
+
+ if( !strcmp( videosink_name, "xvimagesink" )
+ || !strcmp( videosink_name, "avsysvideosink" ) )
+ {
+ MMCAMCORDER_G_OBJECT_SET( sc->element[_MMCAMCORDER_VIDEOSINK_SINK].gst,
+ "visible", is_visible);
+
+ _mmcam_dbg_log( "Set visible [%d] done.", is_visible );
+ bret = TRUE;
+ }
+ else
+ {
+ _mmcam_dbg_warn( "videosink[%s] does not support VISIBLE.", videosink_name );
+ bret = FALSE;
+ }
+ }
+ else
+ {
+ _mmcam_dbg_warn( "Videosink element is null, but current state is [%d]", current_state );
+ bret = FALSE;
+ }
+ }
+ else
+ {
+ _mmcam_dbg_warn( "Current Mode is AUDIO only mode." );
+ bret = FALSE;
+ }
+ }
+ else
+ {
+ _mmcam_dbg_log("It doesn't need to change dynamically.(state=%d)", current_state);
+ bret = TRUE;
+ }
+ return bret;
+}
+
+
+bool _mmcamcorder_commit_display_geometry_method (MMHandleType handle, int attr_idx, const mmf_value_t *value)
+{
+ mmf_camcorder_t *hcamcorder= MMF_CAMCORDER( handle);
+ _MMCamcorderSubContext *sc = NULL;
+
+ int newattrs = 0;
+ int current_state = MM_CAMCORDER_STATE_NONE;
+ int bret = 0;
+
+ char *videosink_name = NULL;
+
+ sc = MMF_CAMCORDER_SUBCONTEXT(handle);
+ if (!sc)
+ return TRUE;
+ current_state = _mmcamcorder_get_state( handle);
+
+ if (current_state > MM_CAMCORDER_STATE_NULL)
+ {
+ if (sc->element[_MMCAMCORDER_VIDEOSINK_SINK].gst)
+ {
+ // Get videosink name
+ _mmcamcorder_conf_get_value_element_name( sc->VideosinkElement, &videosink_name );
+
+ if(strcmp(videosink_name, "xvimagesink") == 0) //only for xvimagesink
+ {
+ if (hcamcorder->type != MM_CAMCORDER_MODE_AUDIO)
+ {
+ newattrs = value->value.i_val;
+ MMCAMCORDER_G_OBJECT_SET( sc->element[_MMCAMCORDER_VIDEOSINK_SINK].gst, "display-geometry-method", newattrs);
+ }
+ }
+ bret = TRUE;
+ }
+ else
+ {
+ _mmcam_dbg_log("Videosink element is null");
+ bret = FALSE;
+ }
+ }
+ else
+ {
+ _mmcam_dbg_log("It doesn't need to change dynamically.(state=%d)", current_state);
+ bret = TRUE;
+ }
+
+ return bret;
+}
+
+
+bool _mmcamcorder_commit_display_rect (MMHandleType handle, int attr_idx, const mmf_value_t *value)
+{
+ mmf_camcorder_t *hcamcorder= MMF_CAMCORDER( handle);
+ _MMCamcorderSubContext *sc = NULL;
+
+ int current_state = MM_CAMCORDER_STATE_NONE;
+ int bret = 0;
+
+ char *videosink_name = NULL;
+
+ sc = MMF_CAMCORDER_SUBCONTEXT(handle);
+ if (!sc)
+ return TRUE;
+ current_state = _mmcamcorder_get_state( handle);
+
+ if (current_state > MM_CAMCORDER_STATE_NULL)
+ {
+ if (sc->element[_MMCAMCORDER_VIDEOSINK_SINK].gst)
+ {
+ // Get videosink name
+ _mmcamcorder_conf_get_value_element_name( sc->VideosinkElement, &videosink_name );
+
+ if(strcmp(videosink_name, "xvimagesink") == 0) //only for xvimagesink
+ {
+ if (hcamcorder->type != MM_CAMCORDER_MODE_AUDIO)
+ {
+ int err = 0;
+ int rectx, recty, rectw, recth;
+ int display_geometry_method = 0;
+
+ err = mm_camcorder_get_attributes(handle, NULL,
+ MMCAM_DISPLAY_RECT_X, &rectx,
+ MMCAM_DISPLAY_RECT_Y, &recty,
+ MMCAM_DISPLAY_RECT_WIDTH, &rectw,
+ MMCAM_DISPLAY_RECT_HEIGHT, &recth,
+ MMCAM_DISPLAY_GEOMETRY_METHOD, &display_geometry_method,
+ NULL);
+ if (err < 0)
+ {
+ _mmcam_dbg_warn("Get display-geometry-method attrs fail. (%x)", err);
+ return FALSE;
+ }
+
+ if (display_geometry_method == MM_DISPLAY_METHOD_CUSTOM_ROI)
+ {
+ int flags = MM_ATTRS_FLAG_NONE;
+ MMCamAttrsInfo info;
+ _mmcam_dbg_log("FRECT(x,y,w,h) = (%d,%d,%d,%d)", rectx, recty, rectw, recth);
+ switch(attr_idx)
+ {
+ case MM_CAM_DISPLAY_RECT_X:
+ mm_camcorder_get_attribute_info(handle, MMCAM_DISPLAY_RECT_Y, &info);
+ flags |= info.flag;
+ memset(&info, 0x00, sizeof(info));
+ mm_camcorder_get_attribute_info(handle, MMCAM_DISPLAY_RECT_WIDTH, &info);
+ flags |= info.flag;
+ memset(&info, 0x00, sizeof(info));
+ mm_camcorder_get_attribute_info(handle, MMCAM_DISPLAY_RECT_HEIGHT, &info);
+ flags |= info.flag;
+
+ rectx = value->value.i_val;
+ break;
+ case MM_CAM_DISPLAY_RECT_Y:
+ mm_camcorder_get_attribute_info(handle, MMCAM_DISPLAY_RECT_WIDTH, &info);
+ flags |= info.flag;
+ memset(&info, 0x00, sizeof(info));
+ mm_camcorder_get_attribute_info(handle, MMCAM_DISPLAY_RECT_HEIGHT, &info);
+ flags |= info.flag;
+
+ recty = value->value.i_val;
+ break;
+ case MM_CAM_DISPLAY_RECT_WIDTH:
+ mm_camcorder_get_attribute_info(handle, MMCAM_DISPLAY_RECT_HEIGHT, &info);
+ flags |= info.flag;
+
+ rectw = value->value.i_val;
+ break;
+ case MM_CAM_DISPLAY_RECT_HEIGHT:
+ recth = value->value.i_val;
+ break;
+ default:
+ _mmcam_dbg_err("Wrong attr_idx!");
+ return FALSE;
+ }
+
+ if (!(flags & MM_ATTRS_FLAG_MODIFIED))
+ {
+ _mmcam_dbg_log("RECT(x,y,w,h) = (%d,%d,%d,%d)", rectx, recty, rectw, recth);
+
+ //Do we need to check all?
+ if(g_object_class_find_property(G_OBJECT_GET_CLASS(G_OBJECT(sc->element[_MMCAMCORDER_VIDEOSINK_SINK].gst)), "dst-roi-x"))
+ {
+ g_object_set (sc->element[_MMCAMCORDER_VIDEOSINK_SINK].gst,
+ "dst-roi-x", rectx,
+ "dst-roi-y", recty,
+ "dst-roi-w", rectw,
+ "dst-roi-h", recth,
+ NULL);
+ }
+ }
+ }
+ }
+ }
+ bret = TRUE;
+ }
+ else
+ {
+ _mmcam_dbg_log("Videosink element is null");
+ bret = FALSE;
+ }
+ }
+ else
+ {
+ _mmcam_dbg_log("It doesn't need to change dynamically.(state=%d)", current_state);
+ bret = TRUE;
+ }
+
+ return bret;
+}
+
+
+bool _mmcamcorder_commit_display_scale (MMHandleType handle, int attr_idx, const mmf_value_t *value)
+{
+ mmf_camcorder_t *hcamcorder= MMF_CAMCORDER( handle);
+ _MMCamcorderSubContext *sc = NULL;
+
+ int zoom = 0;
+ int current_state = MM_CAMCORDER_STATE_NONE;
+ int bret = 0;
+
+ char *videosink_name = NULL;
+
+ sc = MMF_CAMCORDER_SUBCONTEXT(handle);
+ if (!sc)
+ return TRUE;
+ current_state = _mmcamcorder_get_state( handle);
+
+ if( current_state > MM_CAMCORDER_STATE_NULL )
+ {
+ if( hcamcorder->type != MM_CAMCORDER_MODE_AUDIO )
+ {
+ if( sc->element[_MMCAMCORDER_VIDEOSINK_SINK].gst )
+ {
+ // Get videosink name
+ _mmcamcorder_conf_get_value_element_name( sc->VideosinkElement, &videosink_name );
+
+ zoom = value->value.i_val;
+
+ if( !strcmp( videosink_name, "xvimagesink" ))
+ {
+ //xvimagesink
+ switch (zoom)
+ {
+ case MM_DISPLAY_SCALE_DEFAULT:
+ {
+ MMCAMCORDER_G_OBJECT_SET( sc->element[_MMCAMCORDER_VIDEOSINK_SINK].gst, "zoom", 1);
+
+ _mmcam_dbg_log( "Set display zoom to default.");
+ break;
+ }
+ case MM_DISPLAY_SCALE_DOUBLE_LENGTH:
+ {
+ MMCAMCORDER_G_OBJECT_SET( sc->element[_MMCAMCORDER_VIDEOSINK_SINK].gst, "zoom", 2);
+
+ _mmcam_dbg_log( "Set display zoom to double.");
+ break;
+ }
+ case MM_DISPLAY_SCALE_TRIPLE_LENGTH:
+ {
+ MMCAMCORDER_G_OBJECT_SET( sc->element[_MMCAMCORDER_VIDEOSINK_SINK].gst, "zoom", 3);
+
+ _mmcam_dbg_log( "Set display zoom to triple.");
+ break;
+ }
+ default:
+ {
+ _mmcam_dbg_warn( "Unsupported value.");
+ }
+ }
+
+ bret = TRUE;
+ }
+ else if (!strcmp( videosink_name, "avsysvideosink" ) )
+ {
+ //avsysvideosink
+ bret = TRUE;
+ }
+ else
+ {
+ _mmcam_dbg_warn( "videosink[%s] does not support 'zoom'.", videosink_name );
+ bret = FALSE;
+ }
+ }
+ else
+ {
+ _mmcam_dbg_warn( "Videosink element is null, but current state is [%d]", current_state );
+ bret = FALSE;
+ }
+ }
+ else
+ {
+ _mmcam_dbg_warn( "Current Mode is AUDIO only mode." );
+ bret = FALSE;
+ }
+ }
+ else
+ {
+ _mmcam_dbg_log("It doesn't need to change dynamically.(state=%d)", current_state);
+ bret = TRUE;
+ }
+
+ return bret;
+}
+
+
+bool _mmcamcorder_commit_strobe (MMHandleType handle, int attr_idx, const mmf_value_t *value)
+{
+ bool bret = FALSE;
+ _MMCamcorderSubContext* sc = NULL;
+ int strobe_type, mslVal, newVal, cur_value;
+ int current_state = MM_CAMCORDER_STATE_NONE;
+
+ sc = MMF_CAMCORDER_SUBCONTEXT( handle );
+ if (!sc)
+ return TRUE;
+
+ _mmcam_dbg_log( "Commit : strobe attribute(%d)", attr_idx );
+
+ //status check
+ current_state = _mmcamcorder_get_state( handle);
+
+ if (current_state < MM_CAMCORDER_STATE_PREPARE ||
+ current_state == MM_CAMCORDER_STATE_CAPTURING) {
+ //_mmcam_dbg_log("It doesn't need to change dynamically.(state=%d)", current_state);
+ return TRUE;
+ }
+
+ mslVal = value->value.i_val;
+
+ switch( attr_idx )
+ {
+ case MM_CAM_STROBE_CONTROL:
+ strobe_type = GST_CAMERA_CONTROL_STROBE_CONTROL;
+ newVal = _mmcamcorder_convert_msl_to_sensor( MM_CAM_STROBE_CONTROL, mslVal);
+ break;
+ case MM_CAM_STROBE_CAPABILITIES:
+ strobe_type = GST_CAMERA_CONTROL_STROBE_CAPABILITIES;
+ newVal = mslVal;
+ break;
+ case MM_CAM_STROBE_MODE:
+ strobe_type = GST_CAMERA_CONTROL_STROBE_MODE;
+ newVal = _mmcamcorder_convert_msl_to_sensor( MM_CAM_STROBE_MODE, mslVal);
+ break;
+ default:
+ {
+ _mmcam_dbg_err("Commit : strobe attribute(attr_idx(%d) is out of range)", attr_idx);
+ return FALSE;
+ }
+ }
+
+ GstCameraControl *control = NULL;
+ if (!GST_IS_CAMERA_CONTROL(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst))
+ {
+ _mmcam_dbg_err("Can't cast Video source into camera control.");
+ bret = FALSE;
+ }
+ else
+ {
+ control = GST_CAMERA_CONTROL( sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst );
+
+ if( gst_camera_control_get_strobe( control, strobe_type, &cur_value ) )
+ {
+ if( newVal != cur_value )
+ {
+ if( gst_camera_control_set_strobe( control, strobe_type, newVal ) )
+ {
+ _mmcam_dbg_log( "Succeed in setting strobe. Type[%d],value[%d]", strobe_type, mslVal );
+ bret = TRUE;
+ }
+ else
+ {
+ _mmcam_dbg_warn( "Set strobe failed. Type[%d],value[%d]", strobe_type, mslVal );
+ bret = FALSE;
+ }
+ }
+ else
+ {
+ _mmcam_dbg_log( "No need to set strobe. Type[%d],value[%d]", strobe_type, mslVal );
+ bret = TRUE;
+ }
+ }
+ else
+ {
+ _mmcam_dbg_warn( "Failed to get strobe. Type[%d]", strobe_type );
+ bret = FALSE;
+ }
+ }
+
+ return bret;
+}
+
+
+bool _mmcamcorder_commit_detect (MMHandleType handle, int attr_idx, const mmf_value_t *value)
+{
+ bool bret = FALSE;
+ _MMCamcorderSubContext* sc = NULL;
+ int detect_type, mslVal, newVal, curVal;
+ GstCameraControl *control = NULL;
+ int current_state = MM_CAMCORDER_STATE_NONE;
+
+ sc = MMF_CAMCORDER_SUBCONTEXT( handle );
+ if (!sc)
+ return TRUE;
+
+ _mmcam_dbg_log( "Commit : detect attribute(%d)", attr_idx);
+
+ //status check
+ 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);
+ return TRUE;
+ }
+
+ switch( attr_idx )
+ {
+ case MM_CAM_DETECT_MODE:
+ detect_type = GST_CAMERA_CONTROL_FACE_DETECT_MODE;
+ break;
+ case MM_CAM_DETECT_NUMBER:
+ detect_type = GST_CAMERA_CONTROL_FACE_DETECT_NUMBER;
+ break;
+ case MM_CAM_DETECT_FOCUS_SELECT:
+ detect_type = GST_CAMERA_CONTROL_FACE_FOCUS_SELECT;
+ break;
+ case MM_CAM_DETECT_SELECT_NUMBER:
+ detect_type = GST_CAMERA_CONTROL_FACE_SELECT_NUMBER;
+ break;
+ case MM_CAM_DETECT_STATUS:
+ detect_type = GST_CAMERA_CONTROL_FACE_DETECT_STATUS;
+ break;
+ default:
+ {
+ _mmcam_dbg_err("Commit : strobe attribute(attr_idx(%d) is out of range)", attr_idx);
+ bret = FALSE;
+ return bret;
+ }
+ }
+
+ mslVal = value->value.i_val;
+ newVal = _mmcamcorder_convert_msl_to_sensor( attr_idx, mslVal );
+
+
+ if (!GST_IS_CAMERA_CONTROL(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst))
+ {
+ _mmcam_dbg_err("Can't cast Video source into camera control.");
+ bret = FALSE;
+ }
+ else
+ {
+ control = GST_CAMERA_CONTROL( sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst );
+
+ if( gst_camera_control_get_detect( control, detect_type, &curVal ) )
+ {
+ if( curVal == newVal )
+ {
+ _mmcam_dbg_log( "No need to set detect. Type[%d],value[%d]", detect_type, mslVal );
+ bret = TRUE;
+ }
+ else
+ {
+ if( !gst_camera_control_set_detect( control, detect_type, newVal ) )
+ {
+ _mmcam_dbg_warn( "Set detect failed. Type[%d],value[%d]", detect_type, mslVal );
+ bret = FALSE;
+ }
+ else
+ {
+ _mmcam_dbg_log( "Set detect success. Type[%d],value[%d]", detect_type, mslVal );
+ bret = TRUE;
+ }
+ }
+ }
+ else
+ {
+ _mmcam_dbg_warn( "Get detect failed. Type[%d]", detect_type );
+ bret = FALSE;
+ }
+ }
+
+ return bret;
+}
+
+
+static bool
+__mmcamcorder_attrs_is_supported(MMHandleType handle, int idx)
+{
+ mmf_attrs_t *attr = (mmf_attrs_t*)handle;
+ int flag;
+
+ if (mm_attrs_get_flags(handle, idx, &flag) == MM_ERROR_NONE) {
+ if (flag == MM_ATTRS_FLAG_NONE) {
+ return FALSE;
+ }
+ } else {
+ return FALSE;
+ }
+
+ if (attr->items[idx].value_spec.type == MM_ATTRS_VALID_TYPE_INT_RANGE) {
+ int min, max;
+ mm_attrs_get_valid_range((MMHandleType)attr, idx, &min, &max);
+ if (max < min) {
+ return FALSE;
+ }
+ } else if (attr->items[idx].value_spec.type == MM_ATTRS_VALID_TYPE_INT_ARRAY) {
+ int count;
+ int *array;
+ mm_attrs_get_valid_array((MMHandleType)attr, idx, &count, &array);
+ if (count == 0) {
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+
+bool
+_mmcamcorder_set_attribute_to_camsensor(MMHandleType handle)
+{
+ mmf_camcorder_t *hcamcorder= MMF_CAMCORDER(handle);
+ mmf_attrs_t *attr = NULL;
+
+ int scene_mode = MM_CAMCORDER_SCENE_MODE_NORMAL;
+
+ int i = 0 ;
+ int ret = TRUE;
+ int attr_idxs_default[] = {
+ MM_CAM_CAMERA_DIGITAL_ZOOM
+ , MM_CAM_CAMERA_OPTICAL_ZOOM
+ , MM_CAM_CAMERA_FOCUS_MODE
+ , MM_CAM_CAMERA_AF_SCAN_RANGE
+ , MM_CAM_CAMERA_EXPOSURE_MODE
+ , MM_CAM_CAMERA_EXPOSURE_VALUE
+ , MM_CAM_CAMERA_F_NUMBER
+ , MM_CAM_CAMERA_SHUTTER_SPEED
+ , MM_CAM_CAMERA_WDR
+ , MM_CAM_CAMERA_ANTI_HANDSHAKE
+ , MM_CAM_CAMERA_FPS_AUTO
+ , MM_CAM_CAMERA_HOLD_AF_AFTER_CAPTURING
+ , MM_CAM_FILTER_CONTRAST
+ , MM_CAM_FILTER_COLOR_TONE
+ , MM_CAM_FILTER_HUE
+ , MM_CAM_STROBE_CONTROL
+ , MM_CAM_STROBE_MODE
+ , MM_CAM_DETECT_MODE
+ , MM_CAM_DETECT_NUMBER
+ , MM_CAM_DETECT_FOCUS_SELECT
+ , MM_CAM_DETECT_SELECT_NUMBER
+ , MM_CAM_CAMERA_AF_TOUCH_X
+ , MM_CAM_CAMERA_AF_TOUCH_Y
+ , MM_CAM_CAMERA_AF_TOUCH_WIDTH
+ , MM_CAM_CAMERA_AF_TOUCH_HEIGHT
+ };
+
+ int attr_idxs_extra[] = {
+ MM_CAM_CAMERA_ISO
+ , MM_CAM_FILTER_BRIGHTNESS
+ , MM_CAM_FILTER_WB
+ , MM_CAM_FILTER_SATURATION
+ , MM_CAM_FILTER_SHARPNESS
+ };
+
+ mmf_return_val_if_fail(hcamcorder, FALSE);
+
+ _mmcam_dbg_log("Set all attribute again.");
+
+ MMTA_ACUM_ITEM_BEGIN(" _mmcamcorder_set_attribute_to_camsensor", 0);
+
+ attr = (mmf_attrs_t *)MMF_CAMCORDER_ATTRS(handle);
+ if (attr == NULL) {
+ _mmcam_dbg_err("Get attribute handle failed.");
+ return FALSE;
+ } else {
+ /* Get Scene mode */
+ mm_camcorder_get_attributes(handle, NULL, MMCAM_FILTER_SCENE_MODE, &scene_mode, NULL);
+
+ _mmcam_dbg_log("attribute count(%d)", attr->count);
+
+ for (i = 0 ; i < ARRAY_SIZE(attr_idxs_default) ; i++) {
+ if (__mmcamcorder_attrs_is_supported((MMHandleType)attr, attr_idxs_default[i])) {
+ mmf_attribute_set_modified(&(attr->items[attr_idxs_default[i]]));
+ }
+ }
+
+ /* Set extra if scene mode is NORMAL */
+ if (scene_mode == MM_CAMCORDER_SCENE_MODE_NORMAL) {
+ for (i = 0 ; i < ARRAY_SIZE(attr_idxs_extra) ; i++) {
+ if (__mmcamcorder_attrs_is_supported((MMHandleType)attr, attr_idxs_extra[i])) {
+ mmf_attribute_set_modified(&(attr->items[attr_idxs_extra[i]]));
+ }
+ }
+ } else {
+ /* Set scene mode if scene mode is NOT NORMAL */
+ if (__mmcamcorder_attrs_is_supported((MMHandleType)attr, MM_CAM_FILTER_SCENE_MODE)) {
+ mmf_attribute_set_modified(&(attr->items[MM_CAM_FILTER_SCENE_MODE]));
+ }
+ }
+
+ if (mmf_attrs_commit((MMHandleType)attr) == -1) {
+ ret = FALSE;
+ } else {
+ ret = TRUE;
+ }
+ }
+
+ MMTA_ACUM_ITEM_END(" _mmcamcorder_set_attribute_to_camsensor", 0);
+
+ _mmcam_dbg_log("Done.");
+
+ return ret;
+}
+
+
+int _mmcamcorder_lock_readonly_attributes(MMHandleType handle)
+{
+ mmf_camcorder_t *hcamcorder= MMF_CAMCORDER(handle);
+ int table_size = 0;
+ int i = 0;
+ mmf_attrs_t *attr = NULL;
+ int nerror = MM_ERROR_NONE ;
+
+ mmf_return_val_if_fail(hcamcorder, MM_ERROR_CAMCORDER_INVALID_ARGUMENT);
+
+ attr = (mmf_attrs_t*) MMF_CAMCORDER_ATTRS(handle);
+ mmf_return_val_if_fail(attr, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
+
+ _mmcam_dbg_log("");
+
+ table_size = ARRAY_SIZE(readonly_attributes);
+ _mmcam_dbg_log("%d", table_size);
+ for (i = 0; i < table_size; i++)
+ {
+ int sCategory = readonly_attributes[i];
+
+ mmf_attribute_set_readonly(&(attr->items[sCategory]));
+ }
+
+ return nerror;
+}
+
+
+int _mmcamcorder_set_disabled_attributes(MMHandleType handle)
+{
+ mmf_camcorder_t *hcamcorder= MMF_CAMCORDER(handle);
+ //int table_size = 0;
+ int i = 0;
+ mmf_attrs_t *attr = NULL;
+ type_string_array * disabled_attr = NULL;
+ int cnt_str = 0;
+ int nerror = MM_ERROR_NONE ;
+
+ mmf_return_val_if_fail(hcamcorder, MM_ERROR_CAMCORDER_INVALID_ARGUMENT);
+
+ attr = (mmf_attrs_t*) MMF_CAMCORDER_ATTRS(handle);
+ mmf_return_val_if_fail(attr, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
+
+ _mmcam_dbg_log("");
+
+ /* add gst_param */
+ _mmcamcorder_conf_get_value_string_array( hcamcorder->conf_main,
+ CONFIGURE_CATEGORY_MAIN_GENERAL,
+ "DisabledAttributes",
+ &disabled_attr );
+ if (disabled_attr != NULL && disabled_attr->value) {
+ cnt_str = disabled_attr->count;
+ for (i = 0; i < cnt_str; i++) {
+ int idx = 0;
+ _mmcam_dbg_log("[%d]%s", i, disabled_attr->value[i] );
+ nerror = mm_attrs_get_index((MMHandleType)attr, disabled_attr->value[i], &idx);
+ if (nerror == MM_ERROR_NONE) {
+ mmf_attribute_set_disabled(&(attr->items[idx]));
+ } else {
+ _mmcam_dbg_warn("No ATTR named %s[%d]",disabled_attr->value[i], i);
+ }
+ }
+ }
+
+ return nerror;
+}
+
+
+/*---------------------------------------------------------------------------------------
+| INTERNAL FUNCTION DEFINITIONS: |
+---------------------------------------------------------------------------------------*/
+static bool __mmcamcorder_set_capture_resolution(MMHandleType handle, int width, int height)
+{
+ mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
+ _MMCamcorderSubContext *sc = NULL;
+ int current_state = MM_CAMCORDER_STATE_NULL;
+
+ mmf_return_val_if_fail(hcamcorder, FALSE);
+
+ sc = MMF_CAMCORDER_SUBCONTEXT(handle);
+ mmf_return_val_if_fail(sc && sc->info, TRUE);
+
+ current_state = _mmcamcorder_get_state(handle);
+
+ if (sc->element && sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst) {
+ if (current_state <= MM_CAMCORDER_STATE_PREPARE) {
+ _mmcam_dbg_log("set capture width and height [%dx%d] to camera plugin", width, height);
+ MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst, "capture-width", width);
+ MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst, "capture-height", height);
+ } else {
+ _mmcam_dbg_warn("invalid state[%d]", current_state);
+ return FALSE;
+ }
+ } else {
+ _mmcam_dbg_log("element is not created yet");
+ }
+
+ return TRUE;
+}
+
+
+static bool __mmcamcorder_set_camera_resolution(MMHandleType handle, int width, int height)
+{
+ mmf_camcorder_t *hcamcorder= MMF_CAMCORDER(handle);
+ int fps, slow_fps;
+ _MMCamcorderSubContext *sc = NULL;
+ GstCaps *caps = NULL;
+ int set_width, set_height;
+
+ sc = MMF_CAMCORDER_SUBCONTEXT(handle);
+ if (!sc)
+ return TRUE;
+
+ mm_camcorder_get_attributes(handle, NULL,
+ MMCAM_CAMERA_FPS, &fps,
+ "camera-slow-motion-fps", &slow_fps,
+ NULL);
+
+ if (hcamcorder->type == MM_CAMCORDER_MODE_VIDEO) {
+ if(slow_fps > 0) {
+ sc->is_slow = TRUE;
+ MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst, "high-speed-fps", fps);
+ } else {
+ sc->is_slow = FALSE;
+ MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst, "high-speed-fps", 0);
+ }
+ } else {
+ sc->is_slow = FALSE;
+ }
+
+ set_width = width;
+ set_height = height;
+
+ caps = gst_caps_new_simple( "video/x-raw-yuv",
+ "format", GST_TYPE_FOURCC, sc->fourcc,
+ "width", G_TYPE_INT, set_width,
+ "height", G_TYPE_INT, set_height,
+ "framerate", GST_TYPE_FRACTION, (sc->is_slow ? slow_fps : fps), 1,
+ NULL
+ );
+ MMCAMCORDER_G_OBJECT_SET( sc->element[_MMCAMCORDER_VIDEOSRC_FILT].gst, "caps", caps);
+ gst_caps_unref(caps);
+
+ return TRUE;
+}
+
+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 2
+ #define CAMERA_RESOLUTION 0
+ #define CAPTURE_RESOLUTION 1
+
+ mmf_camcorder_t *hcamcorder= MMF_CAMCORDER(handle);
+ MMHandleType attrs = 0;
+
+ int ret = MM_ERROR_NONE;
+ int i = 0, j = 0;
+ char *name = NULL;
+ char *check_pair_name[2][3] = {
+ { MMCAM_CAMERA_WIDTH, MMCAM_CAMERA_HEIGHT, "MMCAM_CAMERA_WIDTH and HEIGHT" },
+ { MMCAM_CAPTURE_WIDTH, MMCAM_CAPTURE_HEIGHT, "MMCAM_CAPTURE_WIDTH and HEIGHT" },
+ };
+
+ int check_pair_value[2][2] = {
+ { INIT_VALUE, INIT_VALUE },
+ { INIT_VALUE, INIT_VALUE },
+ };
+
+ if( hcamcorder == NULL || attribute_name == NULL )
+ {
+ _mmcam_dbg_warn( "handle[%p] or attribute_name[%p] is NULL.",
+ hcamcorder, attribute_name );
+ return MM_ERROR_CAMCORDER_INVALID_ARGUMENT;
+ }
+
+ if( err_attr_name )
+ *err_attr_name = NULL;
+
+ //_mmcam_dbg_log( "ENTER" );
+
+ attrs = MMF_CAMCORDER_ATTRS(handle);
+
+ name = (char*)attribute_name;
+
+ while( name )
+ {
+ int idx = -1;
+ MMAttrsType attr_type = MM_ATTRS_TYPE_INVALID;
+
+ /*_mmcam_dbg_log( "NAME : %s", name );*/
+
+ /* attribute name check */
+ if ((ret = mm_attrs_get_index(attrs, name, &idx)) != MM_ERROR_NONE)
+ {
+ if (err_attr_name)
+ *err_attr_name = strdup(name);
+
+ if (ret == MM_ERROR_COMMON_OUT_OF_ARRAY) //to avoid confusing
+ return MM_ERROR_COMMON_ATTR_NOT_EXIST;
+ else
+ return ret;
+ }
+
+ /* type check */
+ if ((ret = mm_attrs_get_type(attrs, idx, &attr_type)) != MM_ERROR_NONE)
+ return ret;
+
+ switch (attr_type)
+ {
+ case MM_ATTRS_TYPE_INT:
+ {
+ gboolean matched = FALSE;
+ for( i = 0 ; i < CHECK_COUNT ; i++ ) {
+ for( j = 0 ; j < 2 ; j++ ) {
+ if( !strcmp( name, check_pair_name[i][j] ) )
+ {
+ check_pair_value[i][j] = va_arg( (var_args), int );
+ _mmcam_dbg_log( "%s : %d", check_pair_name[i][j], check_pair_value[i][j] );
+ matched = TRUE;
+ break;
+ }
+ }
+ if( matched )
+ break;
+ }
+ if( matched == FALSE )
+ {
+ va_arg ((var_args), int);
+ }
+ break;
+ }
+ case MM_ATTRS_TYPE_DOUBLE:
+ va_arg ((var_args), double);
+ break;
+ case MM_ATTRS_TYPE_STRING:
+ va_arg ((var_args), char*); /* string */
+ va_arg ((var_args), int); /* size */
+ break;
+ case MM_ATTRS_TYPE_DATA:
+ va_arg ((var_args), void*); /* data */
+ va_arg ((var_args), int); /* size */
+ break;
+ case MM_ATTRS_TYPE_ARRAY:
+ va_arg ((var_args), void*); /* array */
+ va_arg ((var_args), int); /* length */
+ break;
+ case MM_ATTRS_TYPE_RANGE:
+ va_arg ((var_args), int); /* min */
+ va_arg ((var_args), int); /* max */
+ break;
+ case MM_ATTRS_TYPE_INVALID:
+ default:
+ _mmcam_dbg_err( "Not supported attribute type(%d, name:%s)", attr_type, name);
+ if (err_attr_name)
+ *err_attr_name = strdup(name);
+ return MM_ERROR_CAMCORDER_INVALID_ARGUMENT;
+ }
+
+ /* next name */
+ name = va_arg (var_args, char*);
+ }
+
+ for( i = 0 ; i < CHECK_COUNT ; i++ )
+ {
+ if( check_pair_value[i][0] != INIT_VALUE || check_pair_value[i][1] != INIT_VALUE )
+ {
+ gboolean check_result = FALSE;
+ char *err_name = NULL;
+ MMCamAttrsInfo attr_info_0, attr_info_1;
+
+ if( check_pair_value[i][0] == INIT_VALUE )
+ {
+ mm_attrs_get_int_by_name( attrs, check_pair_name[i][0], &check_pair_value[i][0] );
+ err_name = strdup(check_pair_name[i][1]);
+ }
+ else if( check_pair_value[i][1] == INIT_VALUE )
+ {
+ mm_attrs_get_int_by_name( attrs, check_pair_name[i][1], &check_pair_value[i][1] );
+ err_name = strdup(check_pair_name[i][0]);
+ }
+ else
+ {
+ err_name = strdup(check_pair_name[i][2]);
+ }
+
+ mm_camcorder_get_attribute_info(handle, check_pair_name[i][0], &attr_info_0);
+ mm_camcorder_get_attribute_info(handle, check_pair_name[i][1], &attr_info_1);
+
+ check_result = FALSE;
+
+ for( j = 0 ; j < attr_info_0.int_array.count ; j++ ) {
+ if( attr_info_0.int_array.array[j] == check_pair_value[i][0]
+ && attr_info_1.int_array.array[j] == check_pair_value[i][1] )
+ {
+ _mmcam_dbg_log( "Valid Pair[%s,%s] existed %dx%d[index:%d]",
+ check_pair_name[i][0], check_pair_name[i][1],
+ check_pair_value[i][0], check_pair_value[i][1], i );
+ check_result = TRUE;
+ break;
+ }
+ }
+
+ if( check_result == FALSE )
+ {
+ _mmcam_dbg_err( "INVALID pair[%s,%s] %dx%d",
+ check_pair_name[i][0], check_pair_name[i][1],
+ check_pair_value[i][0], check_pair_value[i][1] );
+ if (err_attr_name)
+ *err_attr_name = err_name;
+
+ return MM_ERROR_CAMCORDER_INVALID_ARGUMENT;
+ }
+ }
+ }
+
+ /*_mmcam_dbg_log("DONE");*/
+
+ return MM_ERROR_NONE;
+}
diff --git a/src/mm_camcorder_audiorec.c b/src/mm_camcorder_audiorec.c
new file mode 100644
index 0000000..b810fe7
--- /dev/null
+++ b/src/mm_camcorder_audiorec.c
@@ -0,0 +1,1050 @@
+/*
+ * libmm-camcorder
+ *
+ * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: Jeongmo Yang <jm80.yang@samsung.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+/*=======================================================================================
+| INCLUDE FILES |
+=======================================================================================*/
+#include "mm_camcorder_internal.h"
+#include "mm_camcorder_audiorec.h"
+#include <math.h>
+
+/*---------------------------------------------------------------------------------------
+| GLOBAL VARIABLE DEFINITIONS for internal |
+---------------------------------------------------------------------------------------*/
+#define MM_CAMCORDER_START_CHANGE_STATE _MMCamcorderStartHelperFunc((void *)hcamcorder)
+#define MM_CAMCORDER_STOP_CHANGE_STATE _MMCamcorderStopHelperFunc((void *)hcamcorder)
+/*---------------------------------------------------------------------------------------
+| LOCAL VARIABLE DEFINITIONS for internal |
+---------------------------------------------------------------------------------------*/
+#define RESET_PAUSE_TIME 0
+#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_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 int __mmcamcorder_create_audiop_with_encodebin(MMHandleType handle);
+static void __mmcamcorder_audiorec_pad_added_cb(GstElement *element, GstPad *pad, MMHandleType handle);
+
+/*=======================================================================================
+| FUNCTION DEFINITIONS |
+=======================================================================================*/
+
+/*---------------------------------------------------------------------------------------
+| GLOBAL FUNCTION DEFINITIONS: |
+---------------------------------------------------------------------------------------*/
+
+
+static int __mmcamcorder_create_audiop_with_encodebin(MMHandleType handle)
+{
+ int err = MM_ERROR_NONE;
+ char *aenc_name = NULL;
+ char *mux_name = NULL;
+
+ GstBus *bus = NULL;
+ GstPad *srcpad = NULL;
+ GstPad *sinkpad = NULL;
+ GList *element_list = NULL;
+
+ _MMCamcorderAudioInfo *info = NULL;
+ mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
+ _MMCamcorderSubContext *sc = NULL;
+ type_element *aenc_elem = NULL;
+ type_element *mux_elem = NULL;
+
+ mmf_return_val_if_fail(hcamcorder, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
+ sc = MMF_CAMCORDER_SUBCONTEXT(handle);
+
+ mmf_return_val_if_fail(sc, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
+ mmf_return_val_if_fail(sc->element, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
+ mmf_return_val_if_fail(sc->info, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
+
+ info = (_MMCamcorderAudioInfo *)sc->info;
+
+ _mmcam_dbg_log("");
+
+ mux_elem = _mmcamcorder_get_type_element(handle, MM_CAM_FILE_FORMAT);
+ err = _mmcamcorder_conf_get_value_element_name( mux_elem, &mux_name );
+
+ if (!mux_name || !strcmp( mux_name, "wavenc" ) ) /* IF MUX in not chosen then record in raw amr file */
+ {
+ //But shoud we support non-mux recording??
+ _mmcam_dbg_log("Record without muxing.");
+ info->bMuxing = FALSE;
+ }
+ else
+ {
+ _mmcam_dbg_log("Record with mux.");
+ info->bMuxing = TRUE;
+ }
+
+ //Create gstreamer element
+ //Main pipeline
+ __ta__(" camcorder_pipeline",
+ _MMCAMCORDER_PIPELINE_MAKE(sc, _MMCAMCORDER_MAIN_PIPE, "camcorder_pipeline", err);
+ );
+
+ __ta__(" __mmcamcorder_create_audiosrc_bin",
+ err = _mmcamcorder_create_audiosrc_bin(handle);
+ );
+ if (err != MM_ERROR_NONE) {
+ return err;
+ }
+
+ if (info->bMuxing) {
+ /* Muxing. can use encodebin. */
+ __ta__(" _mmcamcorder_create_encodesink_bin",
+ err = _mmcamcorder_create_encodesink_bin((MMHandleType)hcamcorder);
+ );
+ if (err != MM_ERROR_NONE ) {
+ return err;
+ }
+ } else {
+ /* without muxing. can't use encodebin. */
+ aenc_elem = _mmcamcorder_get_type_element(handle, MM_CAM_AUDIO_ENCODER);
+ if (!aenc_elem)
+ {
+ _mmcam_dbg_err("Fail to get type element");
+ err = MM_ERROR_CAMCORDER_RESOURCE_CREATION;
+ goto pipeline_creation_error;
+ }
+
+ err = _mmcamcorder_conf_get_value_element_name(aenc_elem, &aenc_name);
+
+ if ((!err) || (!aenc_name))
+ {
+ _mmcam_dbg_err("Fail to get element name");
+ err = MM_ERROR_CAMCORDER_RESOURCE_CREATION;
+ goto pipeline_creation_error;
+ }
+
+ __ta__(" audiopipeline_audioqueue",
+ _MMCAMCORDER_ELEMENT_MAKE(sc, _MMCAMCORDER_ENCSINK_AQUE, "queue", NULL, element_list, err);
+ );
+
+ if( strcmp( aenc_name, "wavenc" ) != 0 )
+ {
+ __ta__(" audiopipeline_audioconvertor",
+ _MMCAMCORDER_ELEMENT_MAKE(sc, _MMCAMCORDER_ENCSINK_CONV, "audioconvert", NULL, element_list, err);
+ );
+ }
+
+ __ta__(" audiopipeline_audioencoder",
+ _MMCAMCORDER_ELEMENT_MAKE(sc, _MMCAMCORDER_ENCSINK_AENC, aenc_name, NULL, element_list, err);
+ );
+
+ __ta__(" audiopipeline_filesink",
+ _MMCAMCORDER_ELEMENT_MAKE(sc, _MMCAMCORDER_ENCSINK_SINK, "filesink", NULL, element_list, err);
+ );
+
+ /* audio encoder attribute setting */
+ if(strcmp(aenc_name,"ari_amrnbenc") == 0) //ari_armnbenc supports attatching amr header
+ {
+ MMCAMCORDER_G_OBJECT_SET( sc->element[_MMCAMCORDER_ENCSINK_AENC].gst, "write-header", TRUE);
+ }
+
+ }
+
+ //Set basic infomation
+
+ if (info->bMuxing) /* IF MUX is indicated create MUX */
+ {
+ gst_bin_add_many(GST_BIN(sc->element[_MMCAMCORDER_MAIN_PIPE].gst),
+ sc->element[_MMCAMCORDER_AUDIOSRC_BIN].gst,
+ sc->element[_MMCAMCORDER_ENCSINK_BIN].gst,
+ NULL);
+
+ srcpad = gst_element_get_static_pad (sc->element[_MMCAMCORDER_AUDIOSRC_BIN].gst, "src");
+ sinkpad = gst_element_get_static_pad (sc->element[_MMCAMCORDER_ENCSINK_BIN].gst, "audio_sink0");
+ _MM_GST_PAD_LINK_UNREF(srcpad, sinkpad, err, pipeline_creation_error);
+ }
+ else /* IF MUX in not chosen then record in raw amr file */
+ {
+ if( !strcmp( aenc_name, "wavenc" ) )
+ {
+ gst_bin_add_many( GST_BIN(sc->element[_MMCAMCORDER_MAIN_PIPE].gst),
+ sc->element[_MMCAMCORDER_AUDIOSRC_BIN].gst,
+ sc->element[_MMCAMCORDER_ENCSINK_AQUE].gst,
+ sc->element[_MMCAMCORDER_ENCSINK_AENC].gst,
+ sc->element[_MMCAMCORDER_ENCSINK_SINK].gst,
+ NULL );
+
+ if (!_MM_GST_ELEMENT_LINK_MANY( sc->element[_MMCAMCORDER_AUDIOSRC_BIN].gst,
+ sc->element[_MMCAMCORDER_ENCSINK_AQUE].gst,
+ sc->element[_MMCAMCORDER_ENCSINK_AENC].gst,
+ sc->element[_MMCAMCORDER_ENCSINK_SINK].gst,
+ NULL ))
+ {
+ err = MM_ERROR_CAMCORDER_GST_LINK;
+ goto pipeline_creation_error;
+ }
+ }
+ else
+ {
+ gst_bin_add_many( GST_BIN(sc->element[_MMCAMCORDER_MAIN_PIPE].gst),
+ sc->element[_MMCAMCORDER_AUDIOSRC_BIN].gst,
+ sc->element[_MMCAMCORDER_ENCSINK_AQUE].gst,
+ sc->element[_MMCAMCORDER_ENCSINK_CONV].gst,
+ sc->element[_MMCAMCORDER_ENCSINK_AENC].gst,
+ sc->element[_MMCAMCORDER_ENCSINK_SINK].gst,
+ NULL );
+
+ if (!_MM_GST_ELEMENT_LINK_MANY( sc->element[_MMCAMCORDER_AUDIOSRC_BIN].gst,
+ sc->element[_MMCAMCORDER_ENCSINK_AQUE].gst,
+ sc->element[_MMCAMCORDER_ENCSINK_CONV].gst,
+ sc->element[_MMCAMCORDER_ENCSINK_AENC].gst,
+ sc->element[_MMCAMCORDER_ENCSINK_SINK].gst,
+ NULL ))
+ {
+ err = MM_ERROR_CAMCORDER_GST_LINK;
+ goto pipeline_creation_error;
+ }
+ }
+ }
+
+
+ //set data probe function
+ srcpad = gst_element_get_static_pad(sc->element[_MMCAMCORDER_AUDIOSRC_SRC].gst, "src");
+ MMCAMCORDER_ADD_BUFFER_PROBE(srcpad, _MMCAMCORDER_HANDLER_AUDIOREC,
+ __mmcamcorder_audio_dataprobe_voicerecorder, hcamcorder);
+ gst_object_unref(srcpad);
+ srcpad = NULL;
+
+ if(info->bMuxing)
+ {
+ MMCAMCORDER_SIGNAL_CONNECT(sc->element[_MMCAMCORDER_ENCSINK_MUX].gst,
+ _MMCAMCORDER_HANDLER_AUDIOREC,
+ "pad-added",
+ __mmcamcorder_audiorec_pad_added_cb,
+ hcamcorder);
+ }
+ else
+ {
+ srcpad = gst_element_get_static_pad(sc->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;
+ }
+
+ /*
+ * To get the message callback from the gstreamer.
+ * This can be used to make the API calls asynchronous
+ * as per LiMO compliancy
+ */
+ bus = gst_pipeline_get_bus(GST_PIPELINE(sc->element[_MMCAMCORDER_MAIN_PIPE].gst));
+ hcamcorder->pipeline_cb_event_id = gst_bus_add_watch( bus, (GstBusFunc)_mmcamcorder_pipeline_cb_message, hcamcorder );
+ gst_bus_set_sync_handler(bus, gst_bus_sync_signal_handler, hcamcorder);
+ gst_object_unref(bus);
+
+ return MM_ERROR_NONE;
+
+pipeline_creation_error:
+ return err;
+}
+
+
+int
+_mmcamcorder_create_audio_pipeline(MMHandleType handle)
+{
+ 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);
+
+ mmf_return_val_if_fail(sc, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
+
+ return __mmcamcorder_create_audiop_with_encodebin(handle);
+}
+
+
+/**
+ * This function destroy audio pipeline.
+ *
+ * @param[in] handle Handle of camcorder.
+ * @return void
+ * @remarks
+ * @see _mmcamcorder_destroy_pipeline()
+ *
+ */
+void
+_mmcamcorder_destroy_audio_pipeline(MMHandleType handle)
+{
+ mmf_camcorder_t *hcamcorder= MMF_CAMCORDER(handle);
+ _MMCamcorderSubContext *sc = NULL;
+ _MMCamcorderAudioInfo* info = NULL;
+ mmf_return_if_fail(hcamcorder);
+ sc = MMF_CAMCORDER_SUBCONTEXT(handle);
+
+ mmf_return_if_fail(sc);
+ mmf_return_if_fail(sc->element);
+
+ info = sc->info;
+
+ _mmcam_dbg_log("");
+
+ if(sc->element[_MMCAMCORDER_MAIN_PIPE].gst)
+ {
+ _mmcamcorder_gst_set_state(handle, sc->element[_MMCAMCORDER_MAIN_PIPE].gst, GST_STATE_NULL);
+
+ _mmcamcorder_remove_all_handlers((MMHandleType)hcamcorder, _MMCAMCORDER_HANDLER_CATEGORY_ALL);
+
+ if( info->bMuxing)
+ {
+ GstPad *reqpad = NULL;
+ //release request pad
+ /* FIXME */
+ /*
+ The ref_count of mux is always # of streams in here, i don't know why it happens.
+ So, i unref the mux manually
+ */
+ reqpad = gst_element_get_static_pad(sc->element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "audio");
+ gst_element_release_request_pad(sc->element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, reqpad);
+ gst_object_unref(reqpad);
+
+ if(GST_IS_ELEMENT(sc->element[_MMCAMCORDER_ENCSINK_MUX].gst) && \
+ GST_OBJECT_REFCOUNT_VALUE(sc->element[_MMCAMCORDER_ENCSINK_MUX].gst) > 1)
+ gst_object_unref(sc->element[_MMCAMCORDER_ENCSINK_MUX].gst);
+ }
+ gst_object_unref(sc->element[_MMCAMCORDER_MAIN_PIPE].gst);
+// sc->element[_MMCAMCORDER_MAIN_PIPE].gst = NULL;
+ }
+
+}
+
+
+/**
+ * This function operates each command on audio mode.
+ *
+ * @param c [in] Handle of camcorder context.
+ * @param command [in] command type received from Multimedia Framework.
+ *
+ * @return This function returns MM_ERROR_NONE on success, or the other values
+ * on error.
+ * @remark
+ * @see _mmcamcorder_set_functions()
+ *
+ */
+ /* ADDED BY SISO */
+
+
+void* _MMCamcorderStartHelperFunc(void *handle)
+{
+ mmf_camcorder_t *hcamcorder= MMF_CAMCORDER(handle);
+ _mmcamcorder_set_state((MMHandleType)hcamcorder, hcamcorder->target_state);
+
+ return NULL;
+}
+
+void* _MMCamcorderStopHelperFunc(void *handle)
+{
+ mmf_camcorder_t *hcamcorder= MMF_CAMCORDER(handle);
+ _mmcamcorder_set_state((MMHandleType)hcamcorder, hcamcorder->target_state);
+
+ return NULL;
+}
+
+
+int
+_mmcamcorder_audio_command(MMHandleType handle, int command)
+{
+ int cmd = command;
+ GstElement *pipeline = NULL;
+ GstElement *audioSrc = NULL;
+ int ret = MM_ERROR_NONE;
+ int err = 0;
+ char *dir_name = NULL;
+ int size=0;
+ guint64 free_space = 0;
+ mmf_camcorder_t *hcamcorder= MMF_CAMCORDER(handle);
+ _MMCamcorderSubContext *sc = NULL;
+ _MMCamcorderAudioInfo *info = NULL;
+ char *err_attr_name = NULL;
+
+ mmf_return_val_if_fail(hcamcorder, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
+ sc = MMF_CAMCORDER_SUBCONTEXT(handle);
+
+ mmf_return_val_if_fail(sc, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
+ mmf_return_val_if_fail(sc->element, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
+ mmf_return_val_if_fail(sc->info, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
+ pipeline = sc->element[_MMCAMCORDER_MAIN_PIPE].gst;
+ info = sc->info;
+
+ _mmcam_dbg_log("");
+
+ pipeline = sc->element[_MMCAMCORDER_MAIN_PIPE].gst;
+ audioSrc = sc->element[_MMCAMCORDER_AUDIOSRC_SRC].gst;
+ switch(cmd)
+ {
+ case _MMCamcorder_CMD_RECORD:
+ //check status for resume case
+ if (_mmcamcorder_get_state((MMHandleType)hcamcorder) != MM_CAMCORDER_STATE_PAUSED)
+ {
+ guint imax_time = 0;
+ char *temp_filename = NULL;
+
+ if(sc->pipeline_time) {
+ gst_pipeline_set_new_stream_time(GST_PIPELINE(pipeline), sc->pipeline_time);
+ }
+ sc->pipeline_time = RESET_PAUSE_TIME;
+
+ ret = mm_camcorder_get_attributes(handle, &err_attr_name,
+ MMCAM_TARGET_TIME_LIMIT, &imax_time,
+ MMCAM_FILE_FORMAT, &(info->fileformat),
+ MMCAM_TARGET_FILENAME, &temp_filename, &size,
+ NULL);
+ if (ret != MM_ERROR_NONE) {
+ _mmcam_dbg_warn("failed to get attribute. (%s:%x)", err_attr_name, ret);
+ SAFE_FREE (err_attr_name);
+ goto _ERR_CAMCORDER_AUDIO_COMMAND;
+ }
+
+ info->filename = strdup(temp_filename);
+ if (!info->filename)
+ {
+ _mmcam_dbg_err("STRDUP was failed");
+ goto _ERR_CAMCORDER_AUDIO_COMMAND;
+ }
+
+ _mmcam_dbg_log("Record start : set file name using attribute - %s\n ",info->filename);
+
+ MMCAMCORDER_G_OBJECT_SET( sc->element[_MMCAMCORDER_ENCSINK_SINK].gst, "location", info->filename);
+
+ sc->ferror_send = FALSE;
+ sc->ferror_count = 0;
+ sc->bget_eos = FALSE;
+ info->filesize =0;
+
+ /* set max time */
+ if (imax_time <= 0) {
+ info->max_time = 0; /* do not check */
+ } else {
+ info->max_time = ((guint64)imax_time) * 1000; /* to millisecond */
+ }
+
+/*
+ //set data probe function
+ gst_pad_add_buffer_probe(gst_element_get_pad(sc->element[_MMCAMCORDER_AUDIOSRC_SRC].gst, "src"),
+ G_CALLBACK(__mmcamcorder_audio_dataprobe_voicerecorder),
+ hcamcorder);
+*/
+/* TODO : check free space before recording start, need to more discussion */
+#if 1
+ dir_name = g_path_get_dirname(info->filename);
+ err = _mmcamcorder_get_freespace(dir_name, &free_space);
+ if((err == -1) || free_space <= (_MMCAMCORDER_AUDIO_MINIMUM_SPACE+(5*1024)))
+ {
+ _mmcam_dbg_err("No more space for recording - %s : [%" G_GUINT64_FORMAT "]\n ", dir_name, free_space);
+ if(dir_name)
+ {
+ g_free(dir_name);
+ dir_name = NULL;
+ }
+ return MM_MESSAGE_CAMCORDER_NO_FREE_SPACE;
+ }
+ if(dir_name)
+ {
+ g_free(dir_name);
+ dir_name = NULL;
+ }
+#endif
+ }
+
+ ret = _mmcamcorder_gst_set_state(handle, pipeline, GST_STATE_PLAYING);
+ if(ret<0) {
+ goto _ERR_CAMCORDER_AUDIO_COMMAND;
+ }
+ break;
+
+ case _MMCamcorder_CMD_PAUSE:
+ {
+ GstClock *clock = NULL;
+ int count = 0;
+
+ if (info->b_commiting)
+ {
+ _mmcam_dbg_warn("now on commiting previous file!!(cmd : %d)", cmd);
+ return MM_ERROR_CAMCORDER_CMD_IS_RUNNING;
+ }
+
+ for(count=0; count <= _MMCAMCORDER_RETRIAL_COUNT ; count++)
+ {
+ if(info->filesize > 0)
+ {
+ break;
+ }
+ else if(count == _MMCAMCORDER_RETRIAL_COUNT)
+ {
+ _mmcam_dbg_err("Pause fail, we are waiting for 100 milisecond, but still file size is %" G_GUINT64_FORMAT "",
+ info->filesize);
+ return MM_ERROR_CAMCORDER_INVALID_CONDITION;
+ }
+ else
+ {
+ _mmcam_dbg_warn("Pause is Waiting for enough audio frame, retrial count[%d], file size is %" G_GUINT64_FORMAT "",
+ count, info->filesize);
+ }
+ usleep(_MMCAMCORDER_FRAME_WAIT_TIME);
+ }
+
+ ret = _mmcamcorder_gst_set_state(handle, pipeline, GST_STATE_PAUSED);
+ if(ret<0) {
+ goto _ERR_CAMCORDER_AUDIO_COMMAND;
+ }
+ //fixed me. consider delay.
+ clock = gst_pipeline_get_clock(GST_PIPELINE(pipeline));
+ sc->pipeline_time = gst_clock_get_time(clock) - gst_element_get_base_time(GST_ELEMENT(sc->element[_MMCAMCORDER_MAIN_PIPE].gst));
+ }
+ break;
+
+ case _MMCamcorder_CMD_CANCEL:
+ if (info->b_commiting)
+ {
+ _mmcam_dbg_warn("now on commiting previous file!!(cmd : %d)", cmd);
+ return MM_ERROR_CAMCORDER_CMD_IS_RUNNING;
+ }
+
+// ret = _mmcamcorder_gst_set_state(handle, pipeline, GST_STATE_NULL);
+ ret = _mmcamcorder_gst_set_state(handle, pipeline, GST_STATE_READY);
+ if(ret<0) {
+ goto _ERR_CAMCORDER_AUDIO_COMMAND;
+ }
+
+ if(info->bMuxing)
+ {
+ MMCAMCORDER_G_OBJECT_SET( sc->element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "block", FALSE);
+ }
+ else
+ {
+ MMCAMCORDER_G_OBJECT_SET( sc->element[_MMCAMCORDER_ENCSINK_AQUE].gst, "empty-buffers", FALSE);
+ }
+
+ _mmcamcorder_gst_set_state(handle, sc->element[_MMCAMCORDER_ENCSINK_SINK].gst, GST_STATE_NULL);
+
+ sc->pipeline_time = 0;
+ sc->pause_time = 0;
+ sc->isMaxsizePausing = FALSE;
+ sc->isMaxtimePausing = FALSE;
+
+ if(info->filename)
+ {
+ _mmcam_dbg_log("file delete(%s)", info->filename);
+ unlink(info->filename);
+ g_free(info->filename);
+ info->filename = NULL;
+ }
+
+ break;
+ case _MMCamcorder_CMD_COMMIT:
+ {
+ int count = 0;
+ g_print("\n\n _MMCamcorder_CMD_COMMIT\n\n");
+
+ if (info->b_commiting)
+ {
+ _mmcam_dbg_warn("now on commiting previous file!!(cmd : %d)", cmd);
+ return MM_ERROR_CAMCORDER_CMD_IS_RUNNING;
+ }
+ else
+ {
+ _mmcam_dbg_log("_MMCamcorder_CMD_COMMIT : start");
+ info->b_commiting = TRUE;
+ }
+
+ for(count=0; count <= _MMCAMCORDER_RETRIAL_COUNT ; count++)
+ {
+ if(info->filesize > 0)
+ {
+ break;
+ }
+ else if(count == _MMCAMCORDER_RETRIAL_COUNT)
+ {
+ _mmcam_dbg_err("Commit fail, we are waiting for 100 milisecond, but still file size is %" G_GUINT64_FORMAT "",
+ info->filesize);
+ info->b_commiting = FALSE;
+ return MM_ERROR_CAMCORDER_INVALID_CONDITION;
+ }
+ else
+ {
+ _mmcam_dbg_warn("Commit is Waiting for enough audio frame, retrial count[%d], file size is %" G_GUINT64_FORMAT "",
+ count, info->filesize);
+ }
+ usleep(_MMCAMCORDER_FRAME_WAIT_TIME);
+ }
+
+ if (audioSrc) {
+ GstPad *pad = gst_element_get_static_pad (audioSrc, "src");
+// gst_pad_push_event (pad, gst_event_new_eos());
+ ret = gst_element_send_event(audioSrc, gst_event_new_eos());
+ gst_object_unref(pad);
+ pad = NULL;
+ if (_mmcamcorder_get_state((MMHandleType)hcamcorder) == MM_CAMCORDER_STATE_PAUSED) // for pause -> commit case
+ {
+ ret = _mmcamcorder_gst_set_state(handle, pipeline, GST_STATE_PLAYING);
+ if(ret<0) {
+ goto _ERR_CAMCORDER_AUDIO_COMMAND;
+ }
+ }
+
+ }
+
+ //wait until finishing EOS
+ _mmcam_dbg_log("Start to wait EOS");
+ if ((ret =_mmcamcorder_get_eos_message(handle)) != MM_ERROR_NONE)
+ {
+ goto _ERR_CAMCORDER_AUDIO_COMMAND;
+ }
+/*
+ while ((!sc->get_eos)&&((retry_cnt--) > 0)) {
+ if ((gMessage = gst_bus_timed_pop (bus, timeout)) != NULL)
+ {
+ if (GST_MESSAGE_TYPE(gMessage) ==GST_MESSAGE_EOS)
+ {
+ _mmcam_dbg_log("Get a EOS message");
+ gst_message_unref(gMessage);
+ break;
+ }
+ else
+ {
+ _mmcam_dbg_log("Get another message(%x). Post this message to bus again.", GST_MESSAGE_TYPE(gMessage));
+ gst_bus_post(bus, gMessage);
+ }
+ }
+ else
+ {
+ _mmcam_dbg_log("timeout of gst_bus_timed_pop()");
+ break;
+ }
+
+ usleep(100); //To Prevent busy waiting
+ }
+
+ _mmcamcorder_audio_handle_eos((MMHandleType)hcamcorder);
+*/
+
+
+ }
+ break;
+
+ case _MMCamcorder_CMD_PREVIEW_START:
+ // MM_CAMCORDER_START_CHANGE_STATE;
+ break;
+ case _MMCamcorder_CMD_PREVIEW_STOP:
+ // MM_CAMCORDER_STOP_CHANGE_STATE;
+ //void
+ break;
+
+ default:
+ ret = MM_ERROR_CAMCORDER_INVALID_ARGUMENT;
+ break;
+ }
+
+_ERR_CAMCORDER_AUDIO_COMMAND:
+ return ret;
+
+}
+
+int
+_mmcamcorder_audio_handle_eos(MMHandleType handle)
+{
+ mmf_camcorder_t *hcamcorder= MMF_CAMCORDER(handle);
+ _MMCamcorderSubContext *sc = NULL;
+ _MMCamcorderAudioInfo *info = NULL;
+ GstElement *pipeline = NULL;
+ _MMCamcorderMsgItem msg;
+ MMCamRecordingReport * report;
+
+ int err = MM_ERROR_NONE;
+
+ mmf_return_val_if_fail(hcamcorder, FALSE);
+ sc = MMF_CAMCORDER_SUBCONTEXT(handle);
+
+ mmf_return_val_if_fail(sc, FALSE);
+ mmf_return_val_if_fail(sc->info, FALSE);
+
+ _mmcam_dbg_err("");
+
+ info = sc->info;
+
+ //changing pipeline for display
+ pipeline = sc->element[_MMCAMCORDER_MAIN_PIPE].gst;
+
+
+ __ta__(" _MMCamcorder_CMD_COMMIT:GST_STATE_READY",
+ err = _mmcamcorder_gst_set_state(handle, pipeline, GST_STATE_READY);
+ );
+
+ if( err != MM_ERROR_NONE )
+ {
+ _mmcam_dbg_warn( "Failed:_MMCamcorder_CMD_COMMIT:GST_STATE_READY. err[%x]", err );
+ }
+
+// __ta__(" _MMCamcorder_CMD_COMMIT:GST_STATE_NULL",
+// _mmcamcorder_gst_set_state(handle, pipeline, GST_STATE_NULL);
+// )
+
+ //Send message
+ //Send recording report to application
+ msg.id = MM_MESSAGE_CAMCORDER_CAPTURED;
+
+ report = (MMCamRecordingReport*) malloc(sizeof(MMCamRecordingReport)); //who free this?
+ if (!report)
+ {
+ //think more.
+ _mmcam_dbg_err("Recording report fail(%s). Out of memory.", info->filename);
+ return FALSE;
+ }
+
+ report->recording_filename = strdup(info->filename);
+ msg.param.data= report;
+
+ _mmcamcroder_send_message(handle, &msg);
+
+
+ if(info->bMuxing)
+ {
+ MMCAMCORDER_G_OBJECT_SET( sc->element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "block", FALSE);
+ }
+ else
+ {
+ MMCAMCORDER_G_OBJECT_SET( sc->element[_MMCAMCORDER_ENCSINK_AQUE].gst, "empty-buffers", FALSE);
+ }
+ _mmcamcorder_gst_set_state(handle, sc->element[_MMCAMCORDER_ENCSINK_SINK].gst, GST_STATE_NULL);
+
+ sc->pipeline_time = 0;
+ sc->pause_time = 0;
+ sc->isMaxsizePausing = FALSE;
+ sc->isMaxtimePausing = FALSE;
+
+ g_free(info->filename);
+ info->filename = NULL;
+
+ _mmcam_dbg_err("_MMCamcorder_CMD_COMMIT : end");
+
+ info->b_commiting = FALSE;
+
+ return TRUE;
+}
+
+
+static float
+__mmcamcorder_get_decibel(unsigned char* raw, int size, MMCamcorderAudioFormat format)
+{
+ #define MAX_AMPLITUDE_MEAN_16BIT 23170.115738161934
+ #define MAX_AMPLITUDE_MEAN_08BIT 89.803909382810
+
+ int i = 0;
+ int depthByte = 0;
+ int count = 0;
+
+ short* pcm16 = 0;
+ char* pcm8 = 0;
+
+ float db = 0.0;
+ float rms = 0.0;
+ unsigned long long square_sum = 0;
+
+ if (format == MM_CAMCORDER_AUDIO_FORMAT_PCM_S16_LE)
+ depthByte = 2;
+ else //MM_CAMCORDER_AUDIO_FORMAT_PCM_U8
+ depthByte = 1;
+
+ for( ; i < size ; i += (depthByte<<1) )
+ {
+ if (depthByte == 1)
+ {
+ pcm8 = (char *)(raw + i);
+ square_sum += (*pcm8)*(*pcm8);
+ }
+ else //2byte
+ {
+ pcm16 = (short*)(raw + i);
+ square_sum += (*pcm16)*(*pcm16);
+ }
+
+ count++;
+ }
+
+ rms = sqrt( square_sum/count );
+
+ if (depthByte == 1)
+ db = 20 * log10( rms/MAX_AMPLITUDE_MEAN_08BIT );
+ else
+ db = 20 * log10( rms/MAX_AMPLITUDE_MEAN_16BIT );
+
+ /*
+ _mmcam_dbg_log("size[%d],depthByte[%d],count[%d],rms[%f],db[%f]",
+ size, depthByte, count, rms, db);
+ */
+
+ return db;
+}
+
+
+static gboolean
+__mmcamcorder_audio_dataprobe_voicerecorder(GstPad *pad, GstBuffer *buffer, gpointer u_data)
+{
+ mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(u_data);
+ double volume = 0.0;
+ int format = 0;
+ int channel = 0;
+ float curdcb = 0.0;
+ _MMCamcorderMsgItem msg;
+ int err = MM_ERROR_UNKNOWN;
+ char *err_name = NULL;
+
+ mmf_return_val_if_fail(hcamcorder, FALSE);
+
+ /* Set volume to audio input */
+ err = mm_camcorder_get_attributes((MMHandleType)hcamcorder, &err_name,
+ MMCAM_AUDIO_VOLUME, &volume,
+ MMCAM_AUDIO_FORMAT, &format,
+ MMCAM_AUDIO_CHANNEL, &channel,
+ NULL);
+ if (err < 0)
+ {
+ _mmcam_dbg_warn("Get attrs fail. (%s:%x)", err_name, err);
+ SAFE_FREE (err_name);
+ return err;
+ }
+
+ if(volume == 0) //mute
+ memset (GST_BUFFER_DATA(buffer), 0, GST_BUFFER_SIZE(buffer));
+
+ /* Get current volume level of real input stream */
+// currms = __mmcamcorder_get_RMS(GST_BUFFER_DATA(buffer), GST_BUFFER_SIZE(buffer), depth);
+ __ta__( "__mmcamcorder_get_decibel",
+ curdcb = __mmcamcorder_get_decibel(GST_BUFFER_DATA(buffer), GST_BUFFER_SIZE(buffer), format);
+ );
+
+ msg.id = MM_MESSAGE_CAMCORDER_CURRENT_VOLUME;
+ msg.param.rec_volume_dB = curdcb;
+ _mmcamcroder_send_message((MMHandleType)hcamcorder, &msg);
+
+ /* CALL audio stream callback */
+ if ((hcamcorder->astream_cb) && buffer && GST_BUFFER_DATA(buffer))
+ {
+ MMCamcorderAudioStreamDataType stream;
+
+ if (_mmcamcorder_get_state((MMHandleType)hcamcorder) < MM_CAMCORDER_STATE_PREPARE)
+ {
+ _mmcam_dbg_warn("Not ready for stream callback");
+ return TRUE;
+ }
+
+ /*
+ _mmcam_dbg_log("Call audio steramCb, data[%p], format[%d], channel[%d], length[%d], volume_dB[%f]",
+ GST_BUFFER_DATA(buffer), format, channel, GST_BUFFER_SIZE(buffer), curdcb);
+ */
+
+ stream.data = (void *)GST_BUFFER_DATA(buffer);
+ stream.format = format;
+ stream.channel = channel;
+ stream.length = GST_BUFFER_SIZE(buffer);
+ stream.timestamp = (unsigned int)(GST_BUFFER_TIMESTAMP(buffer)/1000000); //nano -> msecond
+ stream.volume_dB = curdcb;
+
+ _MMCAMCORDER_LOCK_ASTREAM_CALLBACK( hcamcorder );
+
+ if(hcamcorder->astream_cb)
+ {
+ hcamcorder->astream_cb(&stream, hcamcorder->astream_cb_param);
+ }
+
+ _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;
+}
+
+
+static gboolean __mmcamcorder_audio_dataprobe_record(GstPad *pad, GstBuffer *buffer, gpointer u_data)
+{
+ static int count = 0;
+ guint64 rec_pipe_time = 0;
+ guint64 free_space = 0;
+ guint64 buffer_size = 0;
+ guint64 trailer_size = 0;
+ char *filename = NULL;
+
+ _MMCamcorderSubContext *sc = NULL;
+ mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(u_data);
+ _MMCamcorderAudioInfo *info = NULL;
+ _MMCamcorderMsgItem msg;
+
+ mmf_return_val_if_fail(hcamcorder, FALSE);
+ mmf_return_val_if_fail(buffer, FALSE);
+
+ sc = MMF_CAMCORDER_SUBCONTEXT(hcamcorder);
+ mmf_return_val_if_fail(sc && sc->info, FALSE);
+ info = sc->info;
+
+ if (sc->isMaxtimePausing || sc->isMaxsizePausing) {
+ _mmcam_dbg_warn("isMaxtimePausing[%d],isMaxsizePausing[%d]",
+ sc->isMaxtimePausing, sc->isMaxsizePausing);
+ return FALSE;
+ }
+
+ buffer_size = (guint64)GST_BUFFER_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 */
+ }
+
+ info->filesize += buffer_size;
+ return TRUE;
+ }
+
+ if (sc->ferror_send) {
+ _mmcam_dbg_warn("file write error, drop frames");
+ return FALSE;
+ }
+
+ /* get trailer size */
+ if (info->fileformat == MM_FILE_FORMAT_3GP || info->fileformat == MM_FILE_FORMAT_MP4) {
+ MMCAMCORDER_G_OBJECT_GET(sc->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;
+
+ /* 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);
+
+ /*_mmcam_dbg_log("check free space for recording");*/
+
+ switch (free_space_ret) {
+ case -2: /* file not exist */
+ case -1: /* failed to get free space */
+ _mmcam_dbg_err("Error occured. [%d]", free_space_ret);
+ if (sc->ferror_count == 2 && sc->ferror_send == FALSE) {
+ sc->ferror_send = TRUE;
+ msg.id = MM_MESSAGE_CAMCORDER_ERROR;
+ if (free_space_ret == -2) {
+ msg.param.code = MM_ERROR_FILE_NOT_FOUND;
+ } else {
+ msg.param.code = MM_ERROR_FILE_READ;
+ }
+ _mmcamcroder_send_message((MMHandleType)hcamcorder, &msg);
+ } else {
+ sc->ferror_count++;
+ }
+
+ return FALSE; /* 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);
+
+ if (info->bMuxing) {
+ MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "block", TRUE);
+ } else {
+ MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_ENCSINK_AQUE].gst, "empty-buffers", TRUE);
+ }
+
+ sc->isMaxsizePausing = TRUE;
+ msg.id = MM_MESSAGE_CAMCORDER_NO_FREE_SPACE;
+ _mmcamcroder_send_message((MMHandleType)hcamcorder, &msg);
+
+ return FALSE; /* skip this buffer */
+ }
+ break;
+ }
+ }
+
+ if (!GST_CLOCK_TIME_IS_VALID(GST_BUFFER_TIMESTAMP(buffer))) {
+ _mmcam_dbg_err("Buffer timestamp is invalid, check it");
+ return FALSE;
+ }
+
+ rec_pipe_time = GST_TIME_AS_MSECONDS(GST_BUFFER_TIMESTAMP(buffer));
+
+ /* check recording time limit and send recording status message */
+ if (info->max_time > 0 && rec_pipe_time > info->max_time) {
+ _mmcam_dbg_warn("Current time : [%" G_GUINT64_FORMAT "], Maximum time : [%" G_GUINT64_FORMAT "]", \
+ rec_pipe_time, info->max_time);
+
+ if (info->bMuxing) {
+ MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "block", TRUE);
+ } else {
+ MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_ENCSINK_AQUE].gst, "empty-buffers", TRUE);
+ }
+
+ sc->isMaxtimePausing = TRUE;
+ msg.id = MM_MESSAGE_CAMCORDER_TIME_LIMIT;
+ _mmcamcroder_send_message((MMHandleType)hcamcorder, &msg);
+
+ /* skip this buffer */
+ return FALSE;
+ }
+
+ /* send message for recording time and recorded file size */
+ if (info->b_commiting == FALSE) {
+ info->filesize += buffer_size;
+
+ msg.id = MM_MESSAGE_CAMCORDER_RECORDING_STATUS;
+ msg.param.recording_status.elapsed = (unsigned int)rec_pipe_time;
+ msg.param.recording_status.filesize = (unsigned int)((info->filesize + trailer_size) >> 10);
+ _mmcamcroder_send_message((MMHandleType)hcamcorder, &msg);
+
+ return TRUE;
+ } else {
+ /* skip this buffer if commit process has been started */
+ return FALSE;
+ }
+}
diff --git a/src/mm_camcorder_configure.c b/src/mm_camcorder_configure.c
new file mode 100644
index 0000000..ae4e205
--- /dev/null
+++ b/src/mm_camcorder_configure.c
@@ -0,0 +1,3276 @@
+/*
+ * libmm-camcorder
+ *
+ * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: Jeongmo Yang <jm80.yang@samsung.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+/*===========================================================================================
+| |
+| INCLUDE FILES |
+| |
+========================================================================================== */
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "mm_camcorder_internal.h"
+#include "mm_camcorder_configure.h"
+
+/*---------------------------------------------------------------------------
+| MACRO DEFINITIONS: |
+---------------------------------------------------------------------------*/
+#define CONFIGURE_PATH "/opt/etc"
+#define CONFIGURE_PATH_RETRY "/usr/etc"
+
+/*---------------------------------------------------------------------------
+| GLOBAL VARIABLE DEFINITIONS |
+---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------
+| LOCAL VARIABLE DEFINITIONS |
+---------------------------------------------------------------------------*/
+static int conf_main_category_size[CONFIGURE_CATEGORY_MAIN_NUM] = { 0, };
+static int conf_ctrl_category_size[CONFIGURE_CATEGORY_CTRL_NUM] = { 0, };
+
+static conf_info_table* conf_main_info_table[CONFIGURE_CATEGORY_MAIN_NUM] = { NULL, };
+static conf_info_table* conf_ctrl_info_table[CONFIGURE_CATEGORY_CTRL_NUM] = { NULL, };
+
+/*
+ * Videosrc element default value
+ */
+static type_element _videosrc_element_default = {
+ "VideosrcElement",
+ "videotestsrc",
+ NULL,
+ 0,
+ NULL,
+ 0,
+};
+
+/*
+ * Audiosrc element default value
+ */
+static type_int ___audiosrc_default_channel = { "Channel", 1 };
+static type_int ___audiosrc_default_bitrate = { "BitRate", 8000 };
+static type_int ___audiosrc_default_depth = { "Depth", 16 };
+static type_int ___audiosrc_default_blocksize = { "BlockSize", 1280 };
+static type_int* __audiosrc_default_int_array[] = {
+ &___audiosrc_default_channel,
+ &___audiosrc_default_bitrate,
+ &___audiosrc_default_depth,
+ &___audiosrc_default_blocksize,
+};
+static type_string ___audiosrc_default_device = { "Device", "default" };
+static type_string* __audiosrc_default_string_array[] = {
+ &___audiosrc_default_device,
+};
+static type_element _audiosrc_element_default = {
+ "AudiosrcElement",
+ "audiotestsrc",
+ __audiosrc_default_int_array,
+ sizeof( __audiosrc_default_int_array ) / sizeof( type_int* ),
+ __audiosrc_default_string_array,
+ sizeof( __audiosrc_default_string_array ) / sizeof( type_string* ),
+};
+
+static type_element _audiomodemsrc_element_default = {
+ "AudiomodemsrcElement",
+ "audiotestsrc",
+ __audiosrc_default_int_array,
+ sizeof( __audiosrc_default_int_array ) / sizeof( type_int* ),
+ __audiosrc_default_string_array,
+ sizeof( __audiosrc_default_string_array ) / sizeof( type_string* ),
+};
+
+
+/*
+ * Videosink element default value
+ */
+static type_int ___videosink_default_display_id = { "display-id", 3 };
+static type_int ___videosink_default_x = { "x", 0 };
+static type_int ___videosink_default_y = { "y", 0 };
+static type_int ___videosink_default_width = { "width", 800 };
+static type_int ___videosink_default_height = { "height", 480 };
+static type_int ___videosink_default_rotation = { "rotation", 1 };
+static type_int* __videosink_default_int_array[] = {
+ &___videosink_default_display_id,
+ &___videosink_default_x,
+ &___videosink_default_y,
+ &___videosink_default_width,
+ &___videosink_default_height,
+ &___videosink_default_rotation,
+};
+static type_string* __videosink_default_string_array[] = { NULL };
+static type_element _videosink_element_x_default = {
+ "VideosinkElementX",
+ "xvimagesink",
+ __videosink_default_int_array,
+ sizeof( __videosink_default_int_array ) / sizeof( type_int* ),
+ __videosink_default_string_array,
+ sizeof( __videosink_default_string_array ) / sizeof( type_string* ),
+};
+static type_element _videosink_element_evas_default = {
+ "VideosinkElementEvas",
+ "evasimagesink",
+ __videosink_default_int_array,
+ sizeof( __videosink_default_int_array ) / sizeof( type_int* ),
+ __videosink_default_string_array,
+ sizeof( __videosink_default_string_array ) / sizeof( type_string* ),
+};
+static type_element _videosink_element_gl_default = {
+ "VideosinkElementGL",
+ "glimagesink",
+ __videosink_default_int_array,
+ sizeof( __videosink_default_int_array ) / sizeof( type_int* ),
+ __videosink_default_string_array,
+ sizeof( __videosink_default_string_array ) / sizeof( type_string* ),
+};
+static type_element _videosink_element_null_default = {
+ "VideosinkElementNull",
+ "fakesink",
+ __videosink_default_int_array,
+ sizeof( __videosink_default_int_array ) / sizeof( type_int* ),
+ __videosink_default_string_array,
+ sizeof( __videosink_default_string_array ) / sizeof( type_string* ),
+};
+
+/*
+ * Videoscale element default value
+ */
+static type_element _videoscale_element_default = {
+ "VideoscaleElement",
+ "videoscale",
+ NULL,
+ 0,
+ NULL,
+ 0,
+};
+
+/*
+ * Record sink element default value
+ */
+static type_element _recordsink_element_default = {
+ "RecordsinkElement",
+ "fakesink",
+ NULL,
+ 0,
+ NULL,
+ 0,
+};
+
+/*
+ * H263 element default value
+ */
+static type_element _h263_element_default = {
+ "H263",
+ "ffenc_h263",
+ NULL,
+ 0,
+ NULL,
+ 0,
+};
+
+/*
+ * H264 element default value
+ */
+static type_element _h264_element_default = {
+ "H264",
+ "savsenc_h264",
+ NULL,
+ 0,
+ NULL,
+ 0,
+};
+
+/*
+ * H26L element default value
+ */
+static type_element _h26l_element_default = {
+ "H26L",
+ NULL,
+ NULL,
+ 0,
+ NULL,
+ 0,
+};
+
+/*
+ * MPEG4 element default value
+ */
+static type_element _mpeg4_element_default = {
+ "MPEG4",
+ "ffenc_mpeg4",
+ NULL,
+ 0,
+ NULL,
+ 0,
+};
+
+/*
+ * MPEG1 element default value
+ */
+static type_element _mpeg1_element_default = {
+ "MPEG1",
+ "ffenc_mpeg1video",
+ NULL,
+ 0,
+ NULL,
+ 0,
+};
+
+/*
+ * THEORA element default value
+ */
+static type_element _theora_element_default = {
+ "THEORA",
+ "theoraenc",
+ NULL,
+ 0,
+ NULL,
+ 0,
+};
+
+/*
+ * AMR element default value
+ */
+static type_element _amr_element_default = {
+ "AMR",
+ "secenc_amr",
+ NULL,
+ 0,
+ NULL,
+ 0,
+};
+
+/*
+ * G723_1 element default value
+ */
+static type_element _g723_1_element_default = {
+ "G723_1",
+ NULL,
+ NULL,
+ 0,
+ NULL,
+ 0,
+};
+
+/*
+ * MP3 element default value
+ */
+static type_element _mp3_element_default = {
+ "MP3",
+ "lame",
+ NULL,
+ 0,
+ NULL,
+ 0,
+};
+
+/*
+ * AAC element default value
+ */
+static type_element _aac_element_default = {
+ "AAC",
+ NULL,
+ NULL,
+ 0,
+ NULL,
+ 0,
+};
+
+/*
+ * MMF element default value
+ */
+static type_element _mmf_element_default = {
+ "MMF",
+ NULL,
+ NULL,
+ 0,
+ NULL,
+ 0,
+};
+
+/*
+ * ADPCM element default value
+ */
+static type_element _adpcm_element_default = {
+ "ADPCM",
+ "ffenc_adpcm_ima_qt",
+ NULL,
+ 0,
+ NULL,
+ 0,
+};
+
+/*
+ * WAVE element default value
+ */
+static type_element _wave_element_default = {
+ "WAVE",
+ "wavenc",
+ NULL,
+ 0,
+ NULL,
+ 0,
+};
+
+static type_element _vorbis_element_default = {
+ "VORBIS",
+ "vorbisenc",
+ NULL,
+ 0,
+ NULL,
+ 0,
+};
+
+/*
+ * MIDI element default value
+ */
+static type_element _midi_element_default = {
+ "MIDI",
+ NULL,
+ NULL,
+ 0,
+ NULL,
+ 0,
+};
+
+/*
+ * IMELODY element default value
+ */
+static type_element _imelody_element_default = {
+ "IMELODY",
+ NULL,
+ NULL,
+ 0,
+ NULL,
+ 0,
+};
+
+/*
+ * JPEG element default value
+ */
+static type_element _jpeg_element_default = {
+ "JPEG",
+ "secjpeg_enc",
+ NULL,
+ 0,
+ NULL,
+ 0,
+};
+
+/*
+ * PNG element default value
+ */
+static type_element _png_element_default = {
+ "PNG",
+ "pngenc",
+ NULL,
+ 0,
+ NULL,
+ 0,
+};
+
+/*
+ * BMP element default value
+ */
+static type_element _bmp_element_default = {
+ "BMP",
+ NULL,
+ NULL,
+ 0,
+ NULL,
+ 0,
+};
+
+/*
+ * WBMP element default value
+ */
+static type_element _wbmp_element_default = {
+ "WBMP",
+ NULL,
+ NULL,
+ 0,
+ NULL,
+ 0,
+};
+
+/*
+ * TIFF element default value
+ */
+static type_element _tiff_element_default = {
+ "TIFF",
+ NULL,
+ NULL,
+ 0,
+ NULL,
+ 0,
+};
+
+/*
+ * PCX element default value
+ */
+static type_element _pcx_element_default = {
+ "PCX",
+ NULL,
+ NULL,
+ 0,
+ NULL,
+ 0,
+};
+
+/*
+ * GIF element default value
+ */
+static type_element _gif_element_default = {
+ "GIF",
+ NULL,
+ NULL,
+ 0,
+ NULL,
+ 0,
+};
+
+/*
+ * ICO element default value
+ */
+static type_element _ico_element_default = {
+ "ICO",
+ NULL,
+ NULL,
+ 0,
+ NULL,
+ 0,
+};
+
+/*
+ * RAS element default value
+ */
+static type_element _ras_element_default = {
+ "RAS",
+ NULL,
+ NULL,
+ 0,
+ NULL,
+ 0,
+};
+
+/*
+ * TGA element default value
+ */
+static type_element _tga_element_default = {
+ "TGA",
+ NULL,
+ NULL,
+ 0,
+ NULL,
+ 0,
+};
+
+/*
+ * XBM element default value
+ */
+static type_element _xbm_element_default = {
+ "XBM",
+ NULL,
+ NULL,
+ 0,
+ NULL,
+ 0,
+};
+
+/*
+ * XPM element default value
+ */
+static type_element _xpm_element_default = {
+ "XPM",
+ NULL,
+ NULL,
+ 0,
+ NULL,
+ 0,
+};
+
+/*
+ * 3GP element default value
+ */
+static type_element _3gp_element_default = {
+ "3GP",
+ "ffmux_3gp",
+ NULL,
+ 0,
+ NULL,
+ 0,
+};
+
+/*
+ * AMR mux element default value
+ */
+static type_element _amrmux_element_default = {
+ "AMR",
+ "ffmux_amr",
+ NULL,
+ 0,
+ NULL,
+ 0,
+};
+
+/*
+ * MP4 element default value
+ */
+static type_element _mp4_element_default = {
+ "MP4",
+ "ffmux_mp4",
+ NULL,
+ 0,
+ NULL,
+ 0,
+};
+
+/*
+ * AAC mux element default value
+ */
+static type_element _aacmux_element_default = {
+ "AAC",
+ NULL,
+ NULL,
+ 0,
+ NULL,
+ 0,
+};
+
+/*
+ * MP3 mux element default value
+ */
+static type_element _mp3mux_element_default = {
+ "MP3",
+ NULL,
+ NULL,
+ 0,
+ NULL,
+ 0,
+};
+
+/*
+ * OGG element default value
+ */
+static type_element _ogg_element_default = {
+ "OGG",
+ "oggmux",
+ NULL,
+ 0,
+ NULL,
+ 0,
+};
+
+/*
+ * WAV element default value
+ */
+static type_element _wav_element_default = {
+ "WAV",
+ NULL,
+ NULL,
+ 0,
+ NULL,
+ 0,
+};
+
+/*
+ * AVI element default value
+ */
+static type_element _avi_element_default = {
+ "AVI",
+ "avimux",
+ NULL,
+ 0,
+ NULL,
+ 0,
+};
+
+/*
+ * WMA element default value
+ */
+static type_element _wma_element_default = {
+ "WMA",
+ NULL,
+ NULL,
+ 0,
+ NULL,
+ 0,
+};
+
+/*
+ * WMV element default value
+ */
+static type_element _wmv_element_default = {
+ "WMV",
+ NULL,
+ NULL,
+ 0,
+ NULL,
+ 0,
+};
+
+/*
+ * MID element default value
+ */
+static type_element _mid_element_default = {
+ "MID",
+ NULL,
+ NULL,
+ 0,
+ NULL,
+ 0,
+};
+
+/*
+ * MMF mux element default value
+ */
+static type_element _mmfmux_element_default = {
+ "MMF",
+ "ffmux_mmf",
+ NULL,
+ 0,
+ NULL,
+ 0,
+};
+
+/*
+ * MATROSKA element default value
+ */
+static type_element _matroska_element_default = {
+ "MATROSKA",
+ "matroskamux",
+ NULL,
+ 0,
+ NULL,
+ 0,
+};
+
+/*
+ * [General] matching table
+ */
+static conf_info_table conf_main_general_table[] = {
+ { "SyncStateChange", CONFIGURE_VALUE_INT, {1} },
+ { "GSTInitOption", CONFIGURE_VALUE_STRING_ARRAY, {NULL} },
+ { "ModelName", CONFIGURE_VALUE_STRING, {(char*)"Samsung Camera"} },
+ { "DisabledAttributes", CONFIGURE_VALUE_STRING_ARRAY, {NULL} },
+};
+
+/*
+ * [VideoInput] matching table
+ */
+static conf_info_table conf_main_video_input_table[] = {
+ { "UseConfCtrl", CONFIGURE_VALUE_INT, {1} },
+ { "ConfCtrlFile0", CONFIGURE_VALUE_STRING, {(char*)"mmfw_camcorder_dev_video_pri.ini"} },
+ { "ConfCtrlFile1", CONFIGURE_VALUE_STRING, {(char*)"mmfw_camcorder_dev_video_sec.ini"} },
+ { "VideosrcElement", CONFIGURE_VALUE_ELEMENT, {(type_element*)&_videosrc_element_default} },
+ { "UseVideoscale", CONFIGURE_VALUE_INT, {0} },
+ { "VideoscaleElement", CONFIGURE_VALUE_ELEMENT, {(type_element*)&_videoscale_element_default} },
+ { "UseZeroCopyFormat", CONFIGURE_VALUE_INT, {0} },
+};
+
+/*
+ * [AudioInput] matching table
+ */
+static conf_info_table conf_main_audio_input_table[] = {
+ { "AudiosrcElement", CONFIGURE_VALUE_ELEMENT, {(type_element*)&_audiosrc_element_default} },
+ { "AudiomodemsrcElement", CONFIGURE_VALUE_ELEMENT, {(type_element*)&_audiomodemsrc_element_default} },
+};
+
+/*
+ * [VideoOutput] matching table
+ */
+static conf_info_table conf_main_video_output_table[] = {
+ { "DisplayDevice", CONFIGURE_VALUE_INT_ARRAY, {NULL} },
+ { "Videosink", CONFIGURE_VALUE_INT_ARRAY, {NULL} },
+ { "VideosinkElementX", CONFIGURE_VALUE_ELEMENT, {(type_element*)&_videosink_element_x_default} },
+ { "VideosinkElementEvas", CONFIGURE_VALUE_ELEMENT, {(type_element*)&_videosink_element_evas_default} },
+ { "VideosinkElementGL", CONFIGURE_VALUE_ELEMENT, {(type_element*)&_videosink_element_gl_default} },
+ { "VideosinkElementNull", CONFIGURE_VALUE_ELEMENT, {(type_element*)&_videosink_element_null_default} },
+ { "UseVideoscale", CONFIGURE_VALUE_INT, {0} },
+ { "VideoscaleElement", CONFIGURE_VALUE_ELEMENT, {(type_element*)&_videoscale_element_default} },
+};
+
+/*
+ * [Capture] matching table
+ */
+static conf_info_table conf_main_capture_table[] = {
+ { "UseEncodebin", CONFIGURE_VALUE_INT, {0} },
+ { "UseCaptureMode", CONFIGURE_VALUE_INT, {0} },
+ { "VideoscaleElement", CONFIGURE_VALUE_ELEMENT, {(type_element*)&_videoscale_element_default} },
+};
+
+/*
+ * [Record] matching table
+ */
+static conf_info_table conf_main_record_table[] = {
+ { "UseAudioEncoderQueue", CONFIGURE_VALUE_INT, {1} },
+ { "UseVideoEncoderQueue", CONFIGURE_VALUE_INT, {1} },
+ { "VideoProfile", CONFIGURE_VALUE_INT, {0} },
+ { "VideoAutoAudioConvert", CONFIGURE_VALUE_INT, {0} },
+ { "VideoAutoAudioResample", CONFIGURE_VALUE_INT, {0} },
+ { "VideoAutoColorSpace", CONFIGURE_VALUE_INT, {0} },
+ { "AudioProfile", CONFIGURE_VALUE_INT, {0} },
+ { "AudioAutoAudioConvert", CONFIGURE_VALUE_INT, {0} },
+ { "AudioAutoAudioResample", CONFIGURE_VALUE_INT, {0} },
+ { "AudioAutoColorSpace", CONFIGURE_VALUE_INT, {0} },
+ { "ImageProfile", CONFIGURE_VALUE_INT, {0} },
+ { "ImageAutoAudioConvert", CONFIGURE_VALUE_INT, {0} },
+ { "ImageAutoAudioResample", CONFIGURE_VALUE_INT, {0} },
+ { "ImageAutoColorSpace", CONFIGURE_VALUE_INT, {0} },
+ { "RecordsinkElement", CONFIGURE_VALUE_ELEMENT, {(type_element*)&_recordsink_element_default} },
+ { "UseNoiseSuppressor", CONFIGURE_VALUE_INT, {0} },
+ { "DropVideoFrame", CONFIGURE_VALUE_INT, {0} },
+ { "PassFirstVideoFrame", CONFIGURE_VALUE_INT, {0} },
+};
+
+/*
+ * [VideoEncoder] matching table
+ */
+static conf_info_table conf_main_video_encoder_table[] = {
+ { "H263", CONFIGURE_VALUE_ELEMENT, {(type_element*)&_h263_element_default} },
+ { "H264", CONFIGURE_VALUE_ELEMENT, {(type_element*)&_h264_element_default} },
+ { "H26L", CONFIGURE_VALUE_ELEMENT, {(type_element*)&_h26l_element_default} },
+ { "MPEG4", CONFIGURE_VALUE_ELEMENT, {(type_element*)&_mpeg4_element_default} },
+ { "MPEG1", CONFIGURE_VALUE_ELEMENT, {(type_element*)&_mpeg1_element_default} },
+ { "THEORA", CONFIGURE_VALUE_ELEMENT, {(type_element*)&_theora_element_default} },
+};
+
+/*
+ * [AudioEncoder] matching table
+ */
+static conf_info_table conf_main_audio_encoder_table[] = {
+ { "AMR", CONFIGURE_VALUE_ELEMENT, {(type_element*)&_amr_element_default} },
+ { "G723_1", CONFIGURE_VALUE_ELEMENT, {(type_element*)&_g723_1_element_default} },
+ { "MP3", CONFIGURE_VALUE_ELEMENT, {(type_element*)&_mp3_element_default} },
+ { "AAC", CONFIGURE_VALUE_ELEMENT, {(type_element*)&_aac_element_default} },
+ { "MMF", CONFIGURE_VALUE_ELEMENT, {(type_element*)&_mmf_element_default} },
+ { "ADPCM", CONFIGURE_VALUE_ELEMENT, {(type_element*)&_adpcm_element_default} },
+ { "WAVE", CONFIGURE_VALUE_ELEMENT, {(type_element*)&_wave_element_default} },
+ { "MIDI", CONFIGURE_VALUE_ELEMENT, {(type_element*)&_midi_element_default} },
+ { "IMELODY", CONFIGURE_VALUE_ELEMENT, {(type_element*)&_imelody_element_default} },
+ { "VORBIS", CONFIGURE_VALUE_ELEMENT, {(type_element*)&_vorbis_element_default} },
+};
+
+/*
+ * [ImageEncoder] matching table
+ */
+static conf_info_table conf_main_image_encoder_table[] = {
+ { "JPEG", CONFIGURE_VALUE_ELEMENT, {(type_element*)&_jpeg_element_default} },
+ { "PNG", CONFIGURE_VALUE_ELEMENT, {(type_element*)&_png_element_default} },
+ { "BMP", CONFIGURE_VALUE_ELEMENT, {(type_element*)&_bmp_element_default} },
+ { "WBMP", CONFIGURE_VALUE_ELEMENT, {(type_element*)&_wbmp_element_default} },
+ { "TIFF", CONFIGURE_VALUE_ELEMENT, {(type_element*)&_tiff_element_default} },
+ { "PCX", CONFIGURE_VALUE_ELEMENT, {(type_element*)&_pcx_element_default} },
+ { "GIF", CONFIGURE_VALUE_ELEMENT, {(type_element*)&_gif_element_default} },
+ { "ICO", CONFIGURE_VALUE_ELEMENT, {(type_element*)&_ico_element_default} },
+ { "RAS", CONFIGURE_VALUE_ELEMENT, {(type_element*)&_ras_element_default} },
+ { "TGA", CONFIGURE_VALUE_ELEMENT, {(type_element*)&_tga_element_default} },
+ { "XBM", CONFIGURE_VALUE_ELEMENT, {(type_element*)&_xbm_element_default} },
+ { "XPM", CONFIGURE_VALUE_ELEMENT, {(type_element*)&_xpm_element_default} },
+};
+
+/*
+ * [Mux] matching table
+ */
+static conf_info_table conf_main_mux_table[] = {
+ { "3GP", CONFIGURE_VALUE_ELEMENT, {(type_element*)&_3gp_element_default} },
+ { "AMR", CONFIGURE_VALUE_ELEMENT, {(type_element*)&_amrmux_element_default} },
+ { "MP4", CONFIGURE_VALUE_ELEMENT, {(type_element*)&_mp4_element_default} },
+ { "AAC", CONFIGURE_VALUE_ELEMENT, {(type_element*)&_aacmux_element_default} },
+ { "MP3", CONFIGURE_VALUE_ELEMENT, {(type_element*)&_mp3mux_element_default} },
+ { "OGG", CONFIGURE_VALUE_ELEMENT, {(type_element*)&_ogg_element_default} },
+ { "WAV", CONFIGURE_VALUE_ELEMENT, {(type_element*)&_wav_element_default} },
+ { "AVI", CONFIGURE_VALUE_ELEMENT, {(type_element*)&_avi_element_default} },
+ { "WMA", CONFIGURE_VALUE_ELEMENT, {(type_element*)&_wma_element_default} },
+ { "WMV", CONFIGURE_VALUE_ELEMENT, {(type_element*)&_wmv_element_default} },
+ { "MID", CONFIGURE_VALUE_ELEMENT, {(type_element*)&_mid_element_default} },
+ { "MMF", CONFIGURE_VALUE_ELEMENT, {(type_element*)&_mmfmux_element_default} },
+ { "MATROSKA", CONFIGURE_VALUE_ELEMENT, {(type_element*)&_matroska_element_default} },
+};
+
+
+/*******************
+ * Camera control *
+ *******************/
+
+/*
+ * [Camera] matching table
+ */
+static conf_info_table conf_ctrl_camera_table[] = {
+ { "InputIndex", CONFIGURE_VALUE_INT_ARRAY, {NULL} },
+ { "DeviceName", CONFIGURE_VALUE_STRING, {NULL} },
+ { "PreviewResolution", CONFIGURE_VALUE_INT_PAIR_ARRAY, {NULL} },
+ { "CaptureResolution", CONFIGURE_VALUE_INT_PAIR_ARRAY, {NULL} },
+ { "FPS", CONFIGURE_VALUE_INT_ARRAY, {NULL} },
+ { "PictureFormat", CONFIGURE_VALUE_INT_ARRAY, {NULL} },
+ { "Overlay", CONFIGURE_VALUE_INT_RANGE, {NULL} },
+ { "RecommendDisplayRotation", CONFIGURE_VALUE_INT, {3} },
+ { "RecommendPreviewFormatCapture", CONFIGURE_VALUE_INT, {MM_PIXEL_FORMAT_YUYV} },
+ { "RecommendPreviewFormatRecord", CONFIGURE_VALUE_INT, {MM_PIXEL_FORMAT_NV12} },
+};
+
+/*
+ * [Strobe] matching table
+ */
+static conf_info_table conf_ctrl_strobe_table[] = {
+ { "StrobeControl", CONFIGURE_VALUE_INT_ARRAY, {NULL} },
+ { "StrobeMode", CONFIGURE_VALUE_INT_ARRAY, {NULL} },
+ { "StrobeEV", CONFIGURE_VALUE_INT_RANGE, {NULL} },
+};
+
+/*
+ * [Effect] matching table
+ */
+static conf_info_table conf_ctrl_effect_table[] = {
+ { "Brightness", CONFIGURE_VALUE_INT_RANGE, {NULL} },
+ { "Contrast", CONFIGURE_VALUE_INT_RANGE, {NULL} },
+ { "Saturation", CONFIGURE_VALUE_INT_RANGE, {NULL} },
+ { "Sharpness", CONFIGURE_VALUE_INT_RANGE, {NULL} },
+ { "WhiteBalance", CONFIGURE_VALUE_INT_ARRAY, {NULL} },
+ { "ColorTone", CONFIGURE_VALUE_INT_ARRAY, {NULL} },
+ { "Flip", CONFIGURE_VALUE_INT_ARRAY, {NULL} },
+ { "WDR", CONFIGURE_VALUE_INT_ARRAY, {NULL} },
+ { "PartColorMode", CONFIGURE_VALUE_INT_ARRAY, {NULL} },
+ { "PartColor", CONFIGURE_VALUE_INT_ARRAY, {NULL} },
+};
+
+/*
+ * [Photograph] matching table
+ */
+static conf_info_table conf_ctrl_photograph_table[] = {
+ { "LensInit", CONFIGURE_VALUE_INT_ARRAY, {NULL} },
+ { "DigitalZoom", CONFIGURE_VALUE_INT_RANGE, {NULL} },
+ { "OpticalZoom", CONFIGURE_VALUE_INT_RANGE, {NULL} },
+ { "FocusMode", CONFIGURE_VALUE_INT_ARRAY, {NULL} },
+ { "AFType", CONFIGURE_VALUE_INT_ARRAY, {NULL} },
+ { "AEType", CONFIGURE_VALUE_INT_ARRAY, {NULL} },
+ { "ExposureValue", CONFIGURE_VALUE_INT_RANGE, {NULL} },
+ { "FNumber", CONFIGURE_VALUE_INT_ARRAY, {NULL} },
+ { "ShutterSpeed", CONFIGURE_VALUE_INT_ARRAY, {NULL} },
+ { "ISO", CONFIGURE_VALUE_INT_ARRAY, {NULL} },
+ { "ProgramMode", CONFIGURE_VALUE_INT_ARRAY, {NULL} },
+ { "AntiHandshake", CONFIGURE_VALUE_INT_ARRAY, {NULL} },
+};
+
+/*
+ * [Capture] matching table
+ */
+static conf_info_table conf_ctrl_capture_table[] = {
+ { "OutputMode", CONFIGURE_VALUE_INT_ARRAY, {NULL} },
+ { "JpegQuality", CONFIGURE_VALUE_INT_RANGE, {NULL} },
+ { "MultishotNumber", CONFIGURE_VALUE_INT_RANGE, {NULL} },
+ { "SensorEncodedCapture", CONFIGURE_VALUE_INT, {1} },
+};
+
+/*
+ * [Detect] matching table
+ */
+static conf_info_table conf_ctrl_detect_table[] = {
+ { "DetectMode", CONFIGURE_VALUE_INT_ARRAY, {NULL} },
+ { "DetectNumber", CONFIGURE_VALUE_INT_RANGE, {NULL} },
+ { "DetectSelect", CONFIGURE_VALUE_INT_RANGE, {NULL} },
+ { "DetectSelectNumber", CONFIGURE_VALUE_INT_RANGE, {NULL} },
+};
+
+
+
+char*
+get_new_string( char* src_string )
+{
+ return strdup(src_string);
+}
+
+void
+_mmcamcorder_conf_init( int type, camera_conf** configure_info )
+{
+ int i = 0;
+ int info_table_size = sizeof( conf_info_table );
+
+ _mmcam_dbg_log( "Entered..." );
+
+ if( type == CONFIGURE_TYPE_MAIN )
+ {
+ conf_main_info_table[CONFIGURE_CATEGORY_MAIN_GENERAL] = conf_main_general_table;
+ conf_main_info_table[CONFIGURE_CATEGORY_MAIN_VIDEO_INPUT] = conf_main_video_input_table;
+ conf_main_info_table[CONFIGURE_CATEGORY_MAIN_AUDIO_INPUT] = conf_main_audio_input_table;
+ conf_main_info_table[CONFIGURE_CATEGORY_MAIN_VIDEO_OUTPUT] = conf_main_video_output_table;
+ conf_main_info_table[CONFIGURE_CATEGORY_MAIN_CAPTURE] = conf_main_capture_table;
+ conf_main_info_table[CONFIGURE_CATEGORY_MAIN_RECORD] = conf_main_record_table;
+ conf_main_info_table[CONFIGURE_CATEGORY_MAIN_VIDEO_ENCODER] = conf_main_video_encoder_table;
+ conf_main_info_table[CONFIGURE_CATEGORY_MAIN_AUDIO_ENCODER] = conf_main_audio_encoder_table;
+ conf_main_info_table[CONFIGURE_CATEGORY_MAIN_IMAGE_ENCODER] = conf_main_image_encoder_table;
+ conf_main_info_table[CONFIGURE_CATEGORY_MAIN_MUX] = conf_main_mux_table;
+
+ conf_main_category_size[CONFIGURE_CATEGORY_MAIN_GENERAL] = sizeof( conf_main_general_table ) / info_table_size;
+ conf_main_category_size[CONFIGURE_CATEGORY_MAIN_VIDEO_INPUT] = sizeof( conf_main_video_input_table ) / info_table_size;
+ conf_main_category_size[CONFIGURE_CATEGORY_MAIN_AUDIO_INPUT] = sizeof( conf_main_audio_input_table ) / info_table_size;
+ conf_main_category_size[CONFIGURE_CATEGORY_MAIN_VIDEO_OUTPUT] = sizeof( conf_main_video_output_table ) / info_table_size;
+ conf_main_category_size[CONFIGURE_CATEGORY_MAIN_CAPTURE] = sizeof( conf_main_capture_table ) / info_table_size;
+ conf_main_category_size[CONFIGURE_CATEGORY_MAIN_RECORD] = sizeof( conf_main_record_table ) / info_table_size;
+ conf_main_category_size[CONFIGURE_CATEGORY_MAIN_VIDEO_ENCODER] = sizeof( conf_main_video_encoder_table ) / info_table_size;
+ conf_main_category_size[CONFIGURE_CATEGORY_MAIN_AUDIO_ENCODER] = sizeof( conf_main_audio_encoder_table ) / info_table_size;
+ conf_main_category_size[CONFIGURE_CATEGORY_MAIN_IMAGE_ENCODER] = sizeof( conf_main_image_encoder_table ) / info_table_size;
+ conf_main_category_size[CONFIGURE_CATEGORY_MAIN_MUX] = sizeof( conf_main_mux_table ) / info_table_size;
+
+ (*configure_info)->info = (conf_info**)g_malloc0( sizeof( conf_info* ) * CONFIGURE_CATEGORY_MAIN_NUM );
+
+ for( i = 0 ; i < CONFIGURE_CATEGORY_MAIN_NUM ; i++ )
+ {
+ (*configure_info)->info[i] = NULL;
+ }
+ }
+ else
+ {
+ conf_ctrl_info_table[CONFIGURE_CATEGORY_CTRL_CAMERA] = conf_ctrl_camera_table;
+ conf_ctrl_info_table[CONFIGURE_CATEGORY_CTRL_STROBE] = conf_ctrl_strobe_table;
+ conf_ctrl_info_table[CONFIGURE_CATEGORY_CTRL_EFFECT] = conf_ctrl_effect_table;
+ conf_ctrl_info_table[CONFIGURE_CATEGORY_CTRL_PHOTOGRAPH] = conf_ctrl_photograph_table;
+ conf_ctrl_info_table[CONFIGURE_CATEGORY_CTRL_CAPTURE] = conf_ctrl_capture_table;
+ conf_ctrl_info_table[CONFIGURE_CATEGORY_CTRL_DETECT] = conf_ctrl_detect_table;
+
+ conf_ctrl_category_size[CONFIGURE_CATEGORY_CTRL_CAMERA] = sizeof( conf_ctrl_camera_table ) / info_table_size;
+ conf_ctrl_category_size[CONFIGURE_CATEGORY_CTRL_STROBE] = sizeof( conf_ctrl_strobe_table ) / info_table_size;
+ conf_ctrl_category_size[CONFIGURE_CATEGORY_CTRL_EFFECT] = sizeof( conf_ctrl_effect_table ) / info_table_size;
+ conf_ctrl_category_size[CONFIGURE_CATEGORY_CTRL_PHOTOGRAPH] = sizeof( conf_ctrl_photograph_table ) / info_table_size;
+ conf_ctrl_category_size[CONFIGURE_CATEGORY_CTRL_CAPTURE] = sizeof( conf_ctrl_capture_table ) / info_table_size;
+ conf_ctrl_category_size[CONFIGURE_CATEGORY_CTRL_DETECT] = sizeof( conf_ctrl_detect_table ) / info_table_size;
+
+ (*configure_info)->info = (conf_info**)g_malloc0( sizeof( conf_info* ) * CONFIGURE_CATEGORY_CTRL_NUM );
+
+ for( i = 0 ; i < CONFIGURE_CATEGORY_CTRL_NUM ; i++ )
+ {
+ (*configure_info)->info[i] = NULL;
+ }
+ }
+
+ _mmcam_dbg_log( "Done." );
+
+}
+
+
+int
+_mmcamcorder_conf_get_info( int type, char* ConfFile, camera_conf** configure_info )
+{
+ int ret = MM_ERROR_NONE;
+ FILE* fd = NULL;
+ char* conf_path = NULL;
+
+ _mmcam_dbg_log( "Opening...[%s]", ConfFile );
+
+ mmf_return_val_if_fail( ConfFile, FALSE );
+
+ conf_path = (char*)malloc( strlen(ConfFile)+strlen(CONFIGURE_PATH)+3 );
+
+ if( conf_path == NULL )
+ {
+ _mmcam_dbg_err( "malloc failed." );
+ return MM_ERROR_CAMCORDER_LOW_MEMORY;
+ }
+
+ snprintf( conf_path, strlen(ConfFile)+strlen(CONFIGURE_PATH)+2, "%s/%s", CONFIGURE_PATH, ConfFile );
+ _mmcam_dbg_log( "Try open Configure File[%s]", conf_path );
+
+ fd = fopen( conf_path, "r" );
+ if( fd == NULL )
+ {
+ _mmcam_dbg_warn( "File open failed.[%s] retry...", conf_path );
+ snprintf( conf_path, strlen(ConfFile)+strlen(CONFIGURE_PATH_RETRY)+2, "%s/%s", CONFIGURE_PATH_RETRY, ConfFile );
+ _mmcam_dbg_log( "Try open Configure File[%s]", conf_path );
+ fd = fopen( conf_path, "r" );
+ if( fd == NULL )
+ {
+ _mmcam_dbg_warn( "File open failed.[%s] But keep going... All value will be returned as default.Type[%d]",
+ conf_path, type );
+ }
+ }
+
+ if( fd != NULL )
+ {
+ ret = _mmcamcorder_conf_parse_info( type, fd, configure_info );
+ fclose( fd );
+ }
+ else
+ {
+ ret = MM_ERROR_CAMCORDER_CREATE_CONFIGURE;
+ }
+
+ if( conf_path != NULL )
+ {
+ free( conf_path );
+ conf_path = NULL;
+ }
+
+ _mmcam_dbg_log( "Leave..." );
+
+ return ret;
+}
+
+int
+_mmcamcorder_conf_parse_info( int type, FILE* fd, camera_conf** configure_info )
+{
+ const unsigned int BUFFER_NUM_DETAILS = 256;
+ const unsigned int BUFFER_NUM_TOKEN = 20;
+ size_t BUFFER_LENGTH_STRING = 256;
+ const char* delimiters = " |=,\t\n";
+
+ int category = 0;
+ int count_main_category = 0;
+ int count_details = 0;
+ int length_read = 0;
+ int count_token = 0;
+ int read_main = 0;
+
+ char *buffer_string = (char*)g_malloc0(sizeof(char)*BUFFER_LENGTH_STRING);
+ char *buffer_details[BUFFER_NUM_DETAILS];
+ char *buffer_token[BUFFER_NUM_TOKEN];
+ char *token = NULL;
+ char *category_name = NULL;
+ char *detail_string = NULL;
+ char *user_ptr = NULL;
+
+ _mmcam_dbg_log( "" );
+
+ camera_conf* new_conf = (camera_conf*)g_malloc0(sizeof(camera_conf));
+
+ if( new_conf == NULL )
+ {
+ _mmcam_dbg_err( "Failed to create new configure structure.type[%d]", type );
+ *configure_info = NULL;
+
+ return MM_ERROR_CAMCORDER_LOW_MEMORY;
+ }
+
+ new_conf->type = type;
+ *configure_info = new_conf;
+
+ _mmcamcorder_conf_init( type, &new_conf );
+
+ mmf_return_val_if_fail( fd > 0, MM_ERROR_CAMCORDER_INVALID_ARGUMENT );
+
+ read_main = 0;
+ count_main_category = 0;
+
+ while( !feof( fd ) )
+ {
+ if( read_main == 0 )
+ {
+ length_read = getline( &buffer_string, &BUFFER_LENGTH_STRING, fd );
+ /*_mmcam_dbg_log( "Read Line : [%s]", buffer_string );*/
+
+ count_token = 0;
+ token = strtok_r( buffer_string, delimiters, &user_ptr );
+
+ if ((token) && (token[0] == ';'))
+ {
+ /*_mmcam_dbg_log( "Comment - Nothing to do" );*/
+ continue;
+ }
+
+ while( token )
+ {
+ /*_mmcam_dbg_log( "token : [%s]", token );*/
+ buffer_token[count_token] = token;
+ count_token++;
+ token = strtok_r( NULL, delimiters, &user_ptr );
+ }
+
+ if( count_token == 0 )
+ {
+ continue;
+ }
+ }
+
+ read_main = 0;
+
+ /* Comment */
+ if( *buffer_token[0] == ';' )
+ {
+ /*_mmcam_dbg_log( "Comment - Nothing to do" );*/
+ }
+ /* 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 );
+ /*_mmcam_dbg_log( "Read Detail Line : [%s], read length : [%d]", buffer_string, length_read );*/
+
+ detail_string = get_new_string( buffer_string );
+
+ token = strtok_r( buffer_string, delimiters, &user_ptr );
+
+ if( token && token[0] != ';' && length_read > -1 )
+ {
+ /*_mmcam_dbg_log( "token : [%s]", token );*/
+ if( token[0] == '[' )
+ {
+ read_main = 1;
+ buffer_token[0] = token;
+ SAFE_FREE( detail_string );
+ break;
+ }
+
+ buffer_details[count_details++] = detail_string;
+ }
+ else
+ {
+ SAFE_FREE( detail_string );
+ }
+ }
+
+ _mmcam_dbg_log( "type : %d, category_name : %s, count : [%d]", type, category_name, count_details );
+
+ if( count_details == 0 )
+ {
+ _mmcam_dbg_warn( "category %s has no detail value... skip this category...", category_name );
+ continue;
+ }
+
+ category = -1;
+
+ /* Details */
+ if( type == CONFIGURE_TYPE_MAIN )
+ {
+ if( !strcmp( "[General]", category_name ) )
+ {
+ category = CONFIGURE_CATEGORY_MAIN_GENERAL;
+ }
+ else if( !strcmp( "[VideoInput]", category_name ) )
+ {
+ category = CONFIGURE_CATEGORY_MAIN_VIDEO_INPUT;
+ }
+ else if( !strcmp( "[AudioInput]", category_name ) )
+ {
+ category = CONFIGURE_CATEGORY_MAIN_AUDIO_INPUT;
+ }
+ else if( !strcmp( "[VideoOutput]", category_name ) )
+ {
+ category = CONFIGURE_CATEGORY_MAIN_VIDEO_OUTPUT;
+ }
+ else if( !strcmp( "[Capture]", category_name ) )
+ {
+ category = CONFIGURE_CATEGORY_MAIN_CAPTURE;
+ }
+ else if( !strcmp( "[Record]", category_name ) )
+ {
+ category = CONFIGURE_CATEGORY_MAIN_RECORD;
+ }
+ else if( !strcmp( "[VideoEncoder]", category_name ) )
+ {
+ category = CONFIGURE_CATEGORY_MAIN_VIDEO_ENCODER;
+ }
+ else if( !strcmp( "[AudioEncoder]", category_name ) )
+ {
+ category = CONFIGURE_CATEGORY_MAIN_AUDIO_ENCODER;
+ }
+ else if( !strcmp( "[ImageEncoder]", category_name ) )
+ {
+ category = CONFIGURE_CATEGORY_MAIN_IMAGE_ENCODER;
+ }
+ else if( !strcmp( "[Mux]", category_name ) )
+ {
+ category = CONFIGURE_CATEGORY_MAIN_MUX;
+ }
+ }
+ else
+ {
+ if( !strcmp( "[Camera]", category_name ) )
+ {
+ category = CONFIGURE_CATEGORY_CTRL_CAMERA;
+ }
+ else if( !strcmp( "[Strobe]", category_name ) )
+ {
+ category = CONFIGURE_CATEGORY_CTRL_STROBE;
+ }
+ else if( !strcmp( "[Effect]", category_name ) )
+ {
+ category = CONFIGURE_CATEGORY_CTRL_EFFECT;
+ }
+ else if( !strcmp( "[Photograph]", category_name ) )
+ {
+ category = CONFIGURE_CATEGORY_CTRL_PHOTOGRAPH;
+ }
+ else if( !strcmp( "[Capture]", category_name ) )
+ {
+ category = CONFIGURE_CATEGORY_CTRL_CAPTURE;
+ }
+ else if( !strcmp( "[Detect]", category_name ) )
+ {
+ category = CONFIGURE_CATEGORY_CTRL_DETECT;
+ }
+ }
+
+ if( category != -1 )
+ {
+ _mmcamcorder_conf_add_info( type, &(new_conf->info[category]),
+ buffer_details, category, count_details );
+ }
+ else
+ {
+ _mmcam_dbg_warn( "No matched category[%s],type[%d]... check it.", category_name, type );
+ }
+
+ // Free memory
+ {
+ int i;
+
+ for( i = 0 ; i < count_details ; i++ )
+ {
+ SAFE_FREE( buffer_details[i] );
+ }
+ }
+ }
+
+ if( category_name )
+ {
+ SAFE_FREE( category_name );
+ }
+ }
+
+ //(*configure_info) = new_conf;
+
+ SAFE_FREE( buffer_string );
+
+ _mmcam_dbg_log( "Done." );
+
+ return MM_ERROR_NONE;
+}
+
+
+void
+_mmcamcorder_conf_release_info( camera_conf** configure_info )
+{
+ int i, j, k, type, count, category_num;
+ camera_conf* temp_conf = (*configure_info);
+
+ type_int* temp_int;
+ type_int_range* temp_int_range;
+ type_int_array* temp_int_array;
+ type_int_pair_array* temp_int_pair_array;
+ type_string* temp_string;
+ type_string_array* temp_string_array;
+ type_element* temp_element;
+
+ _mmcam_dbg_log( "Entered..." );
+
+ mmf_return_if_fail( temp_conf );
+
+ if( (*configure_info)->type == CONFIGURE_TYPE_MAIN )
+ {
+ category_num = CONFIGURE_CATEGORY_MAIN_NUM;
+ }
+ else
+ {
+ category_num = CONFIGURE_CATEGORY_CTRL_NUM;
+ }
+
+ for( i = 0 ; i < category_num ; i++ )
+ {
+ if( temp_conf->info[i] )
+ {
+ for( j = 0 ; j < temp_conf->info[i]->count ; j++ )
+ {
+ if( temp_conf->info[i]->detail_info[j] == NULL )
+ {
+ continue;
+ }
+
+ if( _mmcamcorder_conf_get_value_type( temp_conf->type, i, ((type_element*)(temp_conf->info[i]->detail_info[j]))->name, &type ) )
+ {
+ switch( type )
+ {
+ case CONFIGURE_VALUE_INT:
+ {
+ temp_int = (type_int*)(temp_conf->info[i]->detail_info[j]);
+ SAFE_FREE( temp_int->name );
+ }
+ break;
+ case CONFIGURE_VALUE_INT_RANGE:
+ {
+ temp_int_range = (type_int_range*)(temp_conf->info[i]->detail_info[j]);
+ SAFE_FREE( temp_int_range->name );
+ }
+ break;
+ case CONFIGURE_VALUE_INT_ARRAY:
+ {
+ temp_int_array = (type_int_array*)(temp_conf->info[i]->detail_info[j]);
+ SAFE_FREE( temp_int_array->name );
+ SAFE_FREE( temp_int_array->value );
+ }
+ break;
+ case CONFIGURE_VALUE_INT_PAIR_ARRAY:
+ {
+ temp_int_pair_array = (type_int_pair_array*)(temp_conf->info[i]->detail_info[j]);
+ SAFE_FREE( temp_int_pair_array->name );
+ SAFE_FREE( temp_int_pair_array->value[0] );
+ SAFE_FREE( temp_int_pair_array->value[1] );
+ }
+ break;
+ case CONFIGURE_VALUE_STRING:
+ {
+ temp_string = (type_string*)(temp_conf->info[i]->detail_info[j]);
+ SAFE_FREE( temp_string->name );
+ SAFE_FREE( temp_string->value );
+ }
+ break;
+ case CONFIGURE_VALUE_STRING_ARRAY:
+ {
+ temp_string_array = (type_string_array*)(temp_conf->info[i]->detail_info[j]);
+ SAFE_FREE( temp_string_array->name );
+
+ count = temp_string_array->count;
+ for( k = 0 ; k < count ; k++ )
+ {
+ SAFE_FREE( temp_string_array->value[k] );
+ }
+ SAFE_FREE( temp_string_array->value );
+
+ SAFE_FREE( temp_string_array->default_value );
+ }
+ break;
+ case CONFIGURE_VALUE_ELEMENT:
+ {
+ temp_element = (type_element*)(temp_conf->info[i]->detail_info[j]);
+ SAFE_FREE( temp_element->name );
+ SAFE_FREE( temp_element->element_name );
+
+ count = temp_element->count_int;
+ for( k = 0 ; k < count ; k++ )
+ {
+ SAFE_FREE( temp_element->value_int[k]->name );
+ SAFE_FREE( temp_element->value_int[k] );
+ }
+ SAFE_FREE( temp_element->value_int );
+
+ count = temp_element->count_string;
+ for( k = 0 ; k < count ; k++ )
+ {
+ SAFE_FREE( temp_element->value_string[k]->name );
+ SAFE_FREE( temp_element->value_string[k]->value );
+ SAFE_FREE( temp_element->value_string[k] );
+ }
+ SAFE_FREE( temp_element->value_string );
+ }
+ break;
+ }
+ }
+
+ SAFE_FREE( temp_conf->info[i]->detail_info[j] );
+ temp_conf->info[i]->detail_info[j] = NULL;
+ }
+
+ SAFE_FREE( temp_conf->info[i]->detail_info );
+ temp_conf->info[i]->detail_info = NULL;
+
+ SAFE_FREE( temp_conf->info[i] );
+ temp_conf->info[i] = NULL;
+ }
+ }
+
+ SAFE_FREE( (*configure_info)->info );
+ SAFE_FREE( (*configure_info) );
+
+ _mmcam_dbg_log( "Done." );
+}
+
+int
+_mmcamcorder_conf_get_value_type( int type, int category, char* name, int* value_type )
+{
+ int i = 0;
+ 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;
+ }
+
+ /*_mmcam_dbg_log( "Number of value : [%d]", count_value );*/
+
+ if( type == CONFIGURE_TYPE_MAIN )
+ {
+ for( i = 0 ; i < count_value ; i++ )
+ {
+ if( !strcmp( conf_main_info_table[category][i].name, name ) )
+ {
+ *value_type = conf_main_info_table[category][i].value_type;
+ /*_mmcam_dbg_log( "Category[%d],Name[%s],Type[%d]", category, name, *value_type );*/
+ return TRUE;
+ }
+ }
+ }
+ else
+ {
+ for( i = 0 ; i < count_value ; i++ )
+ {
+ if( !strcmp( conf_ctrl_info_table[category][i].name, name ) )
+ {
+ *value_type = conf_ctrl_info_table[category][i].value_type;
+ /*_mmcam_dbg_log( "Category[%d],Name[%s],Type[%d]", category, name, *value_type );*/
+ return TRUE;
+ }
+ }
+ }
+
+ return FALSE;
+}
+
+
+int
+_mmcamcorder_conf_add_info( int type, conf_info** info, char** buffer_details, int category, int count_details )
+{
+ const int BUFFER_NUM_TOKEN = 256;
+
+ int i = 0;
+ int j = 0;
+ int count_token;
+ int value_type;
+ char *token = NULL;
+ char *buffer_token[BUFFER_NUM_TOKEN];
+ char *user_ptr = NULL;
+
+ const char *delimiters = " |=,\t\n";
+ const char *delimiters_sub = " |\t\n";
+ const char *delimiters_3rd = "|\n";
+
+ mmf_return_val_if_fail( buffer_details, FALSE );
+
+ (*info) = (conf_info*)g_malloc0( sizeof(conf_info) );
+ (*info)->detail_info = (void**)g_malloc0(sizeof(void*) * count_details);
+ (*info)->count = count_details;
+
+ for ( i = 0 ; i < count_details ; i++ ) {
+ /*_mmcam_dbg_log("Read line\"%s\"", buffer_details[i]);*/
+ count_token = 0;
+ token = strtok_r( buffer_details[i], delimiters, &user_ptr );
+
+ if (token) {
+ buffer_token[count_token] = token;
+ count_token++;
+ } else {
+ (*info)->detail_info[i] = NULL;
+ _mmcam_dbg_warn( "No token... check it.[%s]", buffer_details[i] );
+ continue;
+ }
+
+ if (!_mmcamcorder_conf_get_value_type(type, category, buffer_token[0], &value_type)) {
+ (*info)->detail_info[i] = NULL;
+ _mmcam_dbg_warn( "Failed to get value type... check it. Category[%d],Name[%s]", category, buffer_token[0] );
+ continue;
+ }
+
+ if (value_type != CONFIGURE_VALUE_STRING && value_type != CONFIGURE_VALUE_STRING_ARRAY) {
+ token = strtok_r( NULL, delimiters, &user_ptr );
+ while (token) {
+ buffer_token[count_token] = token;
+ /*_mmcam_dbg_log("token : [%s]", buffer_token[count_token]);*/
+ count_token++;
+ token = strtok_r( NULL, delimiters, &user_ptr );
+ }
+
+ if (count_token < 2) {
+ (*info)->detail_info[i] = NULL;
+ _mmcam_dbg_warn( "Number of token is too small... check it.[%s]", buffer_details[i] );
+ continue;
+ }
+ } else { /* CONFIGURE_VALUE_STRING or CONFIGURE_VALUE_STRING_ARRAY */
+ /* skip "=" */
+ strtok_r( NULL, delimiters_sub, &user_ptr );
+
+ if (value_type == CONFIGURE_VALUE_STRING_ARRAY) {
+ token = strtok_r( NULL, delimiters_sub, &user_ptr );
+ while (token) {
+ buffer_token[count_token] = token;
+ /*_mmcam_dbg_log("token : [%s]", buffer_token[count_token]);*/
+ count_token++;
+ token = strtok_r( NULL, delimiters_sub, &user_ptr );
+ }
+ } else { /* CONFIGURE_VALUE_STRING */
+ token = strtok_r( NULL, delimiters_3rd, &user_ptr );
+ if (token) {
+ g_strchug( token );
+ buffer_token[count_token] = token;
+ /*_mmcam_dbg_log("token : [%s]", buffer_token[count_token]);*/
+ count_token++;
+ }
+ }
+
+ if (count_token < 2) {
+ (*info)->detail_info[i] = NULL;
+ _mmcam_dbg_warn( "No string value... check it.[%s]", buffer_details[i] );
+ continue;
+ }
+ }
+
+ switch (value_type)
+ {
+ case CONFIGURE_VALUE_INT:
+ {
+ type_int* new_int;
+
+ new_int = (type_int*)g_malloc0( sizeof(type_int) );
+ new_int->name = get_new_string( buffer_token[0] );
+ new_int->value = atoi( buffer_token[1] );
+ (*info)->detail_info[i] = (void*)new_int;
+ /*_mmcam_dbg_log("INT - name[%s],value[%d]", new_int->name, new_int->value);*/
+ break;
+ }
+ case CONFIGURE_VALUE_INT_RANGE:
+ {
+ type_int_range* new_int_range;
+
+ new_int_range = (type_int_range*)g_malloc0( sizeof(type_int_range) );
+ new_int_range->name = get_new_string( buffer_token[0] );
+ new_int_range->min = atoi( buffer_token[1] );
+ new_int_range->max = atoi( buffer_token[2] );
+ new_int_range->default_value = atoi( buffer_token[3] );
+ (*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->max,
+ new_int_range->default_value);
+ */
+ break;
+ }
+ case CONFIGURE_VALUE_INT_ARRAY:
+ {
+ int count_value = count_token - 2;
+ type_int_array* new_int_array;
+
+ new_int_array = (type_int_array*)g_malloc0( sizeof(type_int_array) );
+ new_int_array->name = get_new_string( buffer_token[0] );
+ new_int_array->value = (int*)g_malloc0( sizeof(int)*count_value );
+ new_int_array->count = count_value;
+
+ /*_mmcam_dbg_log("INT ARRAY - name[%s]", new_int_array->name);*/
+ for ( j = 0 ; j < count_value ; j++ ) {
+ new_int_array->value[j] = atoi( buffer_token[j+1] );
+ /*_mmcam_dbg_log(" index[%d] - value[%d]", j, new_int_array->value[j]);*/
+ }
+
+ 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;
+ }
+ case CONFIGURE_VALUE_INT_PAIR_ARRAY:
+ {
+ int count_value = ( count_token - 3 ) >> 1;
+ type_int_pair_array* new_int_pair_array;
+
+ new_int_pair_array = (type_int_pair_array*)g_malloc0( sizeof(type_int_pair_array) );
+ new_int_pair_array->name = get_new_string( buffer_token[0] );
+ new_int_pair_array->value[0] = (int*)g_malloc( sizeof(int)*(count_value) );
+ new_int_pair_array->value[1] = (int*)g_malloc( sizeof(int)*(count_value) );
+ new_int_pair_array->count = count_value;
+
+ /*_mmcam_dbg_log("INT PAIR ARRAY - name[%s],count[%d]", new_int_pair_array->name, count_value);*/
+ for ( j = 0 ; j < count_value ; j++ ) {
+ new_int_pair_array->value[0][j] = atoi( buffer_token[(j<<1)+1] );
+ new_int_pair_array->value[1][j] = atoi( buffer_token[(j<<1)+2] );
+ /*
+ _mmcam_dbg_log(" index[%d] - value[%d,%d]", j,
+ new_int_pair_array->value[0][j],
+ new_int_pair_array->value[1][j]);
+ */
+ }
+
+ new_int_pair_array->default_value[0] = atoi( buffer_token[count_token-2] );
+ new_int_pair_array->default_value[1] = atoi( buffer_token[count_token-1] );
+ /*
+ _mmcam_dbg_log(" default value[%d,%d]",
+ new_int_pair_array->default_value[0],
+ new_int_pair_array->default_value[1]);
+ */
+ (*info)->detail_info[i] = (void*)new_int_pair_array;
+ break;
+ }
+ case CONFIGURE_VALUE_STRING:
+ {
+ type_string* new_string;
+
+ new_string = (type_string*)g_malloc0( sizeof(type_string) );
+ 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;
+ }
+ case CONFIGURE_VALUE_STRING_ARRAY:
+ {
+ int count_value = count_token - 2;
+ type_string_array* new_string_array;
+
+ new_string_array = (type_string_array*)g_malloc0( sizeof(type_string_array) );
+ new_string_array->name = get_new_string( buffer_token[0] );
+ new_string_array->count = count_value;
+ new_string_array->value = (char**)g_malloc0( sizeof(char*)*count_value );;
+
+ /*_mmcam_dbg_log("STRING ARRAY - name[%s]", new_string_array->name);*/
+ for ( j = 0 ; j < count_value ; j++ ) {
+ new_string_array->value[j] = get_new_string( buffer_token[j+1] );
+ /*_mmcam_dbg_log(" index[%d] - value[%s]", j, new_string_array->value[j]);*/
+ }
+
+ new_string_array->default_value = get_new_string( buffer_token[count_token-1] );
+ /*_mmcam_dbg_log(" default value[%s]", new_string_array->default_value);*/
+ (*info)->detail_info[i] = (void*)new_string_array;
+ break;
+ }
+ case CONFIGURE_VALUE_ELEMENT:
+ {
+ type_element* new_element;
+
+ new_element = (type_element*)g_malloc0( sizeof(type_element) );
+ new_element->name = get_new_string( buffer_token[0] );
+ new_element->element_name = get_new_string( buffer_token[1] );
+ new_element->count_int = atoi( buffer_token[2] );
+ new_element->value_int = NULL;
+ new_element->count_string = atoi( buffer_token[3] );
+ new_element->value_string = NULL;
+ /*
+ _mmcam_dbg_log("Element - name[%s],element_name[%s],count_int[%d],count_string[%d]",
+ new_element->name, new_element->element_name, new_element->count_int, new_element->count_string);
+ */
+
+ /* add int values */
+ if ( new_element->count_int > 0 ) {
+ new_element->value_int = (type_int**)g_malloc0( sizeof(type_int*)*(new_element->count_int) );
+
+ for ( j = 0 ; j < new_element->count_int ; j++ ) {
+ new_element->value_int[j] = (type_int*)g_malloc( sizeof(type_int) );
+ new_element->value_int[j]->name = get_new_string( buffer_token[4+(j<<1)] );
+ new_element->value_int[j]->value = atoi( buffer_token[5+(j<<1)] );
+ /*
+ _mmcam_dbg_log(" Element INT[%d] - name[%s],value[%d]",
+ j, new_element->value_int[j]->name, new_element->value_int[j]->value);
+ */
+ }
+ }
+ else
+ {
+ new_element->value_int = NULL;
+ }
+
+ /* add string values */
+ if ( new_element->count_string > 0 ) {
+ new_element->value_string = (type_string**)g_malloc0( sizeof(type_string*)*(new_element->count_string) );
+ for ( ; j < new_element->count_string + new_element->count_int ; j++ ) {
+ new_element->value_string[j-new_element->count_int] = (type_string*)g_malloc0( sizeof(type_string) );
+ new_element->value_string[j-new_element->count_int]->name = get_new_string( buffer_token[4+(j<<1)] );
+ new_element->value_string[j-new_element->count_int]->value = get_new_string( buffer_token[5+(j<<1)] );
+ /*
+ _mmcam_dbg_log(" Element STRING[%d] - name[%s],value[%s]",
+ j-new_element->count_int, new_element->value_string[j-new_element->count_int]->name, new_element->value_string[j-new_element->count_int]->value);
+ */
+ }
+ } else {
+ new_element->value_string = NULL;
+ }
+
+ (*info)->detail_info[i] = (void*)new_element;
+ break;
+ }
+ default:
+ break;
+ }
+ }
+
+ return TRUE;
+}
+
+
+int
+_mmcamcorder_conf_add_info_with_caps( int type, conf_info** info, char** buffer_details, int category, int count_details )
+{
+ const int BUFFER_NUM_TOKEN = 256;
+
+ int i = 0;
+ int j = 0;
+ int count_token = 0;
+ int value_type = 0;
+ char *token = NULL;
+ char *buffer_token[BUFFER_NUM_TOKEN];
+ char *user_ptr = NULL;
+
+ const char* delimiters = " |=,\t\n";
+ const char* delimiters_sub = " |\t\n";
+ const char* delimiters_3rd = "|\n";
+
+ //_mmcam_dbg_log( "" );
+
+ mmf_return_val_if_fail( buffer_details, FALSE );
+
+ (*info) = (conf_info*)g_malloc0( sizeof(conf_info) );
+ (*info)->detail_info = (void**)g_malloc0( sizeof(void*)*count_details );
+ (*info)->count = count_details;
+
+ //g_print( "Count[%d]\n", (*info)->count );
+ //g_print( "Pointer[%x]\n", (*info) );
+
+ for( i = 0 ; i < count_details ; i++ )
+ {
+ //_mmcam_dbg_log( "Read line\"%s\"", buffer_details[i] );
+
+ count_token = 0;
+ token = strtok_r( buffer_details[i], delimiters, &user_ptr );
+
+ if( token )
+ {
+ buffer_token[count_token] = token;
+ count_token++;
+ }
+ else
+ {
+ (*info)->detail_info[i] = NULL;
+ _mmcam_dbg_warn( "No token... check it.[%s]", buffer_details[i] );
+ continue;
+ }
+
+ if( !_mmcamcorder_conf_get_value_type( type, category, buffer_token[0], &value_type ) )
+ {
+ (*info)->detail_info[i] = NULL;
+ _mmcam_dbg_warn( "Failed to get value type... check it. Category[%d],Name[%s]", category, buffer_token[0] );
+ continue;
+ }
+
+ if( value_type != CONFIGURE_VALUE_STRING && value_type != CONFIGURE_VALUE_STRING_ARRAY )
+ {
+ token = strtok_r( NULL, delimiters, &user_ptr );
+
+ while( token )
+ {
+ buffer_token[count_token] = token;
+ //_mmcam_dbg_log( "token : [%s]", buffer_token[count_token] );
+ count_token++;
+ token = strtok_r( NULL, delimiters, &user_ptr );
+ }
+
+ if( count_token < 2 )
+ {
+ (*info)->detail_info[i] = NULL;
+ _mmcam_dbg_warn( "Number of token is too small... check it.[%s]", buffer_details[i] );
+ continue;
+ }
+ }
+ else // CONFIGURE_VALUE_STRING or CONFIGURE_VALUE_STRING_ARRAY
+ {
+ // skip "="
+ strtok_r( NULL, delimiters_sub, &user_ptr );
+
+ if( value_type == CONFIGURE_VALUE_STRING_ARRAY )
+ {
+ token = strtok_r( NULL, delimiters_sub, &user_ptr );
+
+ while( token )
+ {
+ buffer_token[count_token] = token;
+ //_mmcam_dbg_log( "token : [%s]", buffer_token[count_token] );
+ count_token++;
+ token = strtok_r( NULL, delimiters_sub, &user_ptr );
+ }
+ }
+ else // CONFIGURE_VALUE_STRING
+ {
+ token = strtok_r( NULL, delimiters_3rd, &user_ptr );
+
+ if( token )
+ {
+ g_strchug( token );
+ buffer_token[count_token] = token;
+ //_mmcam_dbg_log( "token : [%s]", buffer_token[count_token] );
+ count_token++;
+ }
+ }
+
+ if( count_token < 2 )
+ {
+ (*info)->detail_info[i] = NULL;
+ _mmcam_dbg_warn( "No string value... check it.[%s]", buffer_details[i] );
+ continue;
+ }
+ }
+
+ switch( value_type )
+ {
+ case CONFIGURE_VALUE_INT:
+ {
+ type_int* new_int;
+
+ new_int = (type_int*)g_malloc0( sizeof(type_int) );
+ new_int->name = get_new_string( buffer_token[0] );
+ new_int->value = atoi( buffer_token[1] );
+ (*info)->detail_info[i] = (void*)new_int;
+
+ //_mmcam_dbg_log( "INT - name[%s],value[%d]", new_int->name, new_int->value );
+ break;
+ }
+ case CONFIGURE_VALUE_INT_RANGE:
+ {
+ type_int_range* new_int_range;
+
+ new_int_range = (type_int_range*)g_malloc0( sizeof(type_int_range) );
+ new_int_range->name = get_new_string( buffer_token[0] );
+ new_int_range->min = atoi( buffer_token[1] );
+ new_int_range->max = atoi( buffer_token[2] );
+ new_int_range->default_value = atoi( buffer_token[3] );
+ (*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->max,
+ new_int_range->default_value );
+ */
+ break;
+ }
+ case CONFIGURE_VALUE_INT_ARRAY:
+ {
+ int count_value = count_token - 2;
+ type_int_array* new_int_array;
+
+ new_int_array = (type_int_array*)g_malloc0( sizeof(type_int_array) );
+ new_int_array->name = get_new_string( buffer_token[0] );
+ new_int_array->value = (int*)g_malloc0( sizeof(int)*count_value );
+ new_int_array->count = count_value;
+
+ //_mmcam_dbg_log( "INT ARRAY - name[%s]", new_int_array->name );
+ for( j = 0 ; j < count_value ; j++ )
+ {
+ new_int_array->value[j] = atoi( buffer_token[j+1] );
+ //_mmcam_dbg_log( " index[%d] - value[%d]", j, new_int_array->value[j] );
+ }
+
+ 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;
+ }
+ case CONFIGURE_VALUE_INT_PAIR_ARRAY:
+ {
+ int count_value = ( count_token - 3 ) >> 1;
+ type_int_pair_array* new_int_pair_array;
+
+ new_int_pair_array = (type_int_pair_array*)g_malloc0( sizeof(type_int_pair_array) );
+ new_int_pair_array->name = get_new_string( buffer_token[0] );
+ new_int_pair_array->value[0] = (int*)g_malloc( sizeof(int)*(count_value) );
+ new_int_pair_array->value[1] = (int*)g_malloc( sizeof(int)*(count_value) );
+ new_int_pair_array->count = count_value;
+
+ //_mmcam_dbg_log( "INT PAIR ARRAY - name[%s],count[%d]", new_int_pair_array->name, count_value );
+ for( j = 0 ; j < count_value ; j++ )
+ {
+ new_int_pair_array->value[0][j] = atoi( buffer_token[(j<<1)+1] );
+ new_int_pair_array->value[1][j] = atoi( buffer_token[(j<<1)+2] );
+ /*
+ _mmcam_dbg_log( " index[%d] - value[%d,%d]", j,
+ new_int_pair_array->value[0][j],
+ new_int_pair_array->value[1][j] );
+ */
+ }
+
+ new_int_pair_array->default_value[0] = atoi( buffer_token[count_token-2] );
+ new_int_pair_array->default_value[1] = atoi( buffer_token[count_token-1] );
+
+ /*
+ _mmcam_dbg_log( " default value[%d,%d]",
+ new_int_pair_array->default_value[0],
+ new_int_pair_array->default_value[1] );
+ */
+
+
+ (*info)->detail_info[i] = (void*)new_int_pair_array;
+ break;
+ }
+ case CONFIGURE_VALUE_STRING:
+ {
+ type_string* new_string;
+
+ new_string = (type_string*)g_malloc0( sizeof(type_string) );
+ 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;
+ }
+ case CONFIGURE_VALUE_STRING_ARRAY:
+ {
+ int count_value = count_token - 2;
+ type_string_array* new_string_array;
+
+ new_string_array = (type_string_array*)g_malloc0( sizeof(type_string_array) );
+ new_string_array->name = get_new_string( buffer_token[0] );
+ new_string_array->count = count_value;
+ new_string_array->value = (char**)g_malloc0( sizeof(char*)*count_value );;
+
+ //_mmcam_dbg_log( "STRING ARRAY - name[%s]", new_string_array->name );
+ for( j = 0 ; j < count_value ; j++ )
+ {
+ new_string_array->value[j] = get_new_string( buffer_token[j+1] );
+ //_mmcam_dbg_log( " index[%d] - value[%s]", j, new_string_array->value[j] );
+ }
+
+ new_string_array->default_value = get_new_string( buffer_token[count_token-1] );
+ //_mmcam_dbg_log( " default value[%s]", new_string_array->default_value );
+
+ (*info)->detail_info[i] = (void*)new_string_array;
+ break;
+ }
+ case CONFIGURE_VALUE_ELEMENT:
+ {
+ type_element* new_element;
+
+ new_element = (type_element*)g_malloc0( sizeof(type_element) );
+ new_element->name = get_new_string( buffer_token[0] );
+ new_element->element_name = get_new_string( buffer_token[1] );
+ new_element->count_int = atoi( buffer_token[2] );
+ new_element->value_int = NULL;
+ new_element->count_string = atoi( buffer_token[3] );
+ new_element->value_string = NULL;
+
+ //_mmcam_dbg_log( "Element - name[%s],element_name[%s],count_int[%d],count_string[%d]", new_element->name, new_element->element_name, new_element->count_int, new_element->count_string );
+
+ /* add int values */
+ if( new_element->count_int > 0 )
+ {
+ new_element->value_int = (type_int**)g_malloc0( sizeof(type_int*)*(new_element->count_int) );
+
+ for( j = 0 ; j < new_element->count_int ; j++ )
+ {
+ new_element->value_int[j] = (type_int*)g_malloc( sizeof(type_int) );
+ new_element->value_int[j]->name = get_new_string( buffer_token[4+(j<<1)] );
+ new_element->value_int[j]->value = atoi( buffer_token[5+(j<<1)] );
+ //_mmcam_dbg_log( " Element INT[%d] - name[%s],value[%d]", j, new_element->value_int[j]->name, new_element->value_int[j]->value );
+ }
+ }
+ else
+ {
+ new_element->value_int = NULL;
+ }
+
+ /* add string values */
+ if( new_element->count_string > 0 )
+ {
+ new_element->value_string = (type_string**)g_malloc0( sizeof(type_string*)*(new_element->count_string) );
+
+ for( ; j < new_element->count_string + new_element->count_int ; j++ )
+ {
+ new_element->value_string[j-new_element->count_int] = (type_string*)g_malloc0( sizeof(type_string) );
+ new_element->value_string[j-new_element->count_int]->name = get_new_string( buffer_token[4+(j<<1)] );
+ new_element->value_string[j-new_element->count_int]->value = get_new_string( buffer_token[5+(j<<1)] );
+ //_mmcam_dbg_log( " Element STRING[%d] - name[%s],value[%s]", j-new_element->count_int, new_element->value_string[j-new_element->count_int]->name, new_element->value_string[j-new_element->count_int]->value );
+ }
+ }
+ else
+ {
+ new_element->value_string = NULL;
+ }
+
+ (*info)->detail_info[i] = (void*)new_element;
+ break;
+ }
+ default:
+ break;
+ }
+ }
+
+ //_mmcam_dbg_log( "Done." );
+
+ return TRUE;
+}
+
+
+int
+_mmcamcorder_conf_get_value_int( camera_conf* configure_info, int category, char* name, int* value )
+{
+ int i, count;
+ conf_info* 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];
+
+ 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;
+ //_mmcam_dbg_log( "Get[%s] int[%d]", name, *value );
+ return TRUE;
+ }
+ }
+ }
+
+ if( _mmcamcorder_conf_get_default_value_int( configure_info->type, category, name, value ) )
+ {
+ //_mmcam_dbg_log( "Get[%s] int[%d]", name, *value );
+ return TRUE;
+ }
+
+ _mmcam_dbg_warn( "Faild to get int... check it...Category[%d],Name[%s]", category, name );
+
+ return FALSE;
+}
+
+int
+_mmcamcorder_conf_get_value_int_range( camera_conf* configure_info, int category, char* name, type_int_range** value )
+{
+ int i, count;
+ conf_info* 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];
+
+ 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]",
+ name, (*value)->min, (*value)->max, (*value)->default_value );
+ */
+ return TRUE;
+ }
+ }
+ }
+
+ *value = NULL;
+
+ _mmcam_dbg_warn( "Faild to get int range... check it...Category[%d],Name[%s]", category, name );
+
+ return FALSE;
+}
+
+int
+_mmcamcorder_conf_get_value_int_array( camera_conf* configure_info, int category, char* name, type_int_array** value )
+{
+ int i, count;
+ conf_info* 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];
+
+ for( i = 0 ; i < count ; i++ )
+ {
+ if( info->detail_info[i] == NULL )
+ {
+ 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]",
+ name, (*value)->value, (*value)->count, (*value)->default_value );
+ */
+ return TRUE;
+ }
+ }
+ }
+
+ *value = NULL;
+
+ _mmcam_dbg_warn( "Faild to get int array... check it...Category[%d],Name[%s]", category, name );
+
+ return FALSE;
+}
+
+int
+_mmcamcorder_conf_get_value_int_pair_array( camera_conf* configure_info, int category, char* name, type_int_pair_array** value )
+{
+ int i, count;
+ conf_info* 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];
+
+ 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,
+ (*value)->default_value[0], (*value)->default_value[1] );
+ */
+ return TRUE;
+ }
+ }
+ }
+
+ *value = NULL;
+
+ _mmcam_dbg_warn( "Faild to get int pair array... check it...Category[%d],Name[%s]", category, name );
+
+ return FALSE;
+}
+
+int
+_mmcamcorder_conf_get_value_string( camera_conf* configure_info, int category, char* name, char** value )
+{
+ int i, count;
+ conf_info* 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];
+
+ 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;
+ //_mmcam_dbg_log( "Get[%s] string[%s]", name, *value );
+ return TRUE;
+ }
+ }
+ }
+
+ if( _mmcamcorder_conf_get_default_value_string( configure_info->type, category, name, value ) )
+ {
+ //_mmcam_dbg_log( "Get[%s]string[%s]", name, *value );
+ return TRUE;
+ }
+
+ _mmcam_dbg_warn( "Faild to get string... check it...Category[%d],Name[%s]", category, name );
+
+ return FALSE;
+}
+
+int
+_mmcamcorder_conf_get_value_string_array ( camera_conf* configure_info, int category, char* name, type_string_array** value )
+{
+ int i, count;
+ conf_info* 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];
+
+ for( i = 0 ; i < count ; i++ )
+ {
+ if( info->detail_info[i] == NULL )
+ {
+ 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]",
+ name, (*value)->value, (*value)->count, (*value)->default_value );
+ */
+ return TRUE;
+ }
+ }
+ }
+
+ *value = NULL;
+
+ _mmcam_dbg_warn( "Faild to get string array... check it...Category[%d],Name[%s]", category, name );
+
+ return FALSE;
+}
+
+int
+_mmcamcorder_conf_get_element( camera_conf* configure_info, int category, char* name, type_element** element )
+{
+ int i, count;
+ conf_info* 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];
+
+ 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]);
+ //_mmcam_dbg_log( "Get[%s] element[%x]", name, *element );
+ return TRUE;
+ }
+ }
+ }
+
+ if( _mmcamcorder_conf_get_default_element( configure_info->type, category, name, element ) )
+ {
+ //_mmcam_dbg_log( "Get[%s] element[%x]", name, *element );
+ return TRUE;
+ }
+
+ _mmcam_dbg_warn( "Faild to get element name... check it...Category[%d],Name[%s]", category, name );
+
+ return FALSE;
+}
+
+int
+_mmcamcorder_conf_get_value_element_name( type_element* element, char** value )
+{
+ //_mmcam_dbg_log( "Entered..." );
+
+ mmf_return_val_if_fail( element, FALSE );
+
+ *value = element->element_name;
+
+ //_mmcam_dbg_log( "Get element name : [%s]", *value );
+
+ return TRUE;
+}
+
+int
+_mmcamcorder_conf_get_value_element_int( type_element* element, char* name, int* value )
+{
+ int i;
+
+ //_mmcam_dbg_log( "Entered..." );
+
+ mmf_return_val_if_fail( element, FALSE );
+ mmf_return_val_if_fail( name, FALSE );
+
+ for( i = 0 ; i < element->count_int ; i++ )
+ {
+ if( !strcmp( element->value_int[i]->name , name ) )
+ {
+ *value = element->value_int[i]->value;
+ //_mmcam_dbg_log( "Get[%s] element int[%d]", name, *value );
+ return TRUE;
+ }
+ }
+
+ _mmcam_dbg_warn( "Faild to get int in element... ElementName[%p],Name[%s],Count[%d]",
+ element->name, name, element->count_int );
+
+ return FALSE;
+}
+
+int
+_mmcamcorder_conf_get_value_element_string( type_element* element, char* name, char** value )
+{
+ int i;
+
+ //_mmcam_dbg_log( "Entered..." );
+
+ mmf_return_val_if_fail( element, FALSE );
+ mmf_return_val_if_fail( name, FALSE );
+
+ for( i = 0 ; i < element->count_string ; i++ )
+ {
+ if( !strcmp( element->value_string[i]->name , name ) )
+ {
+ *value = element->value_string[i]->value;
+ //_mmcam_dbg_log( "Get[%s] element string[%s]", name, *value );
+ return TRUE;
+ }
+ }
+
+ _mmcam_dbg_warn( "Faild to get int in element... ElementName[%p],Name[%s],Count[%d]",
+ element->name, name, element->count_string );
+
+ return FALSE;
+}
+
+int
+_mmcamcorder_conf_set_value_element_property( GstElement* gst, type_element* element )
+{
+ int i;
+
+ //_mmcam_dbg_log( "Entered..." );
+
+ mmf_return_val_if_fail( gst, FALSE );
+ mmf_return_val_if_fail( element, FALSE );
+
+ if( element->count_int == 0 )
+ {
+ _mmcam_dbg_log( "There is no integer property to set in INI file[%s].", element->name );
+ }
+ else
+ {
+ if( element->value_int == NULL )
+ {
+ _mmcam_dbg_warn( "count_int[%d] is NOT zero, but value_int is NULL", element->count_int );
+ return FALSE;
+ }
+
+ for( i = 0 ; i < element->count_int ; i++ )
+ {
+ MMCAMCORDER_G_OBJECT_SET( gst, element->value_int[i]->name, element->value_int[i]->value );
+
+ _mmcam_dbg_log( "Element[%s] Set[%s] -> integer[%d]",
+ element->element_name,
+ element->value_int[i]->name,
+ element->value_int[i]->value );
+ }
+ }
+
+ if( element->count_string == 0 )
+ {
+ _mmcam_dbg_log( "There is no string property to set in INI file[%s].", element->name );
+ }
+ else
+ {
+ if( element->value_string == NULL )
+ {
+ _mmcam_dbg_warn( "count_string[%d] is NOT zero, but value_string is NULL", element->count_string );
+ return FALSE;
+ }
+
+ for( i = 0 ; i < element->count_string ; i++ )
+ {
+ MMCAMCORDER_G_OBJECT_SET( gst, element->value_string[i]->name, element->value_string[i]->value );
+
+ _mmcam_dbg_log( "Element[%s] Set[%s] -> string[%s]",
+ element->element_name,
+ element->value_string[i]->name,
+ element->value_string[i]->value );
+ }
+ }
+
+ //_mmcam_dbg_log( "Done." );
+
+ return TRUE;
+}
+
+int
+_mmcamcorder_conf_get_default_value_int( int type, int category, char* name, int* value )
+{
+ int i = 0;
+ 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;
+ }
+
+ if( type == CONFIGURE_TYPE_MAIN )
+ {
+ for( i = 0 ; i < count_value ; i++ )
+ {
+ if( !strcmp( conf_main_info_table[category][i].name, name ) )
+ {
+ *value = conf_main_info_table[category][i].value_int;
+ return TRUE;
+ }
+ }
+ }
+ else
+ {
+ for( i = 0 ; i < count_value ; i++ )
+ {
+ if( !strcmp( conf_ctrl_info_table[category][i].name, name ) )
+ {
+ *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 );
+
+ return FALSE;
+}
+
+int
+_mmcamcorder_conf_get_default_value_string( int type, int category, char* name, char** value )
+{
+ int i = 0;
+ 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;
+ }
+
+ if( type == CONFIGURE_TYPE_MAIN )
+ {
+ for( i = 0 ; i < count_value ; i++ )
+ {
+ if( !strcmp( conf_main_info_table[category][i].name, name ) )
+ {
+ *value = conf_main_info_table[category][i].value_string;
+ _mmcam_dbg_log( "Get[%s] default string[%s]", name, *value );
+ return TRUE;
+ }
+ }
+ }
+ else
+ {
+ for( i = 0 ; i < count_value ; i++ )
+ {
+ if( !strcmp( conf_ctrl_info_table[category][i].name, name ) )
+ {
+ *value = conf_ctrl_info_table[category][i].value_string;
+ _mmcam_dbg_log( "Get[%s] default string[%s]", name, *value );
+ return TRUE;
+ }
+ }
+ }
+
+ _mmcam_dbg_warn( "Failed to get default string... check it... Type[%d],Category[%d],Name[%s]", type, category, name );
+
+ return FALSE;
+}
+
+int
+_mmcamcorder_conf_get_default_element( int type, int category, char* name, type_element** element )
+{
+ int i = 0;
+ 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;
+ }
+
+ if( type == CONFIGURE_TYPE_MAIN )
+ {
+ for( i = 0 ; i < count_value ; i++ )
+ {
+ if( !strcmp( conf_main_info_table[category][i].name, name ) )
+ {
+ *element = conf_main_info_table[category][i].value_element;
+ _mmcam_dbg_log( "Get[%s] element[%p]", name, *element );
+ return TRUE;
+ }
+ }
+ }
+ else
+ {
+ for( i = 0 ; i < count_value ; i++ )
+ {
+ if( !strcmp( conf_ctrl_info_table[category][i].name, name ) )
+ {
+ *element = conf_ctrl_info_table[category][i].value_element;
+ _mmcam_dbg_log( "Get[%s] element[%p]", name, *element );
+ return TRUE;
+ }
+ }
+ }
+
+ _mmcam_dbg_warn( "Failed to get default element... check it... Type[%d],Category[%d],Name[%s]", type, category, name );
+
+ return FALSE;
+}
+
+int
+_mmcamcorder_conf_get_category_size( int type, int category, int* size )
+{
+// mmf_return_val_if_fail( conf_main_category_size, FALSE );
+// mmf_return_val_if_fail( conf_ctrl_category_size, FALSE );
+
+ if( type == CONFIGURE_TYPE_MAIN )
+ {
+ mmf_return_val_if_fail( category < CONFIGURE_CATEGORY_MAIN_NUM, FALSE );
+
+ *size = (int)conf_main_category_size[category];
+ }
+ else
+ {
+ mmf_return_val_if_fail( category < CONFIGURE_CATEGORY_CTRL_NUM, FALSE );
+
+ *size = (int)conf_ctrl_category_size[category];
+ }
+
+ return TRUE;
+}
+
+void
+_mmcamcorder_conf_print_info( camera_conf** configure_info )
+{
+ int i, j, k, type, category_type;
+
+ type_int *temp_int;
+ type_int_range *temp_int_range;
+ type_int_array *temp_int_array;
+ type_int_pair_array *temp_int_pair_array;
+ type_string *temp_string;
+ type_element *temp_element;
+
+ g_print( "[ConfigureInfoPrint] : Entered.\n" );
+
+ mmf_return_if_fail( *configure_info );
+
+ if( (*configure_info)->type == CONFIGURE_TYPE_MAIN )
+ {
+ category_type = CONFIGURE_CATEGORY_MAIN_NUM;
+ }
+ else
+ {
+ category_type = CONFIGURE_CATEGORY_CTRL_NUM;
+ }
+
+ for( i = 0 ; i < category_type ; i++ )
+ {
+ if( (*configure_info)->info[i] )
+ {
+ g_print( "[ConfigureInfo] : Category [%d]\n", i );
+ for( j = 0 ; j < (*configure_info)->info[i]->count ; j++ )
+ {
+ if( _mmcamcorder_conf_get_value_type( (*configure_info)->type, i, ((type_int*)((*configure_info)->info[i]->detail_info[j]))->name, &type ) )
+ {
+ switch( type )
+ {
+ case CONFIGURE_VALUE_INT:
+ temp_int = (type_int*)((*configure_info)->info[i]->detail_info[j]);
+ g_print( "[ConfigureInfo] : INT - Name[%s],Value [%d]\n", temp_int->name, temp_int->value );
+ break;
+ case CONFIGURE_VALUE_INT_RANGE:
+ temp_int_range = (type_int_range*)((*configure_info)->info[i]->detail_info[j]);
+ g_print( "[ConfigureInfo] : INT_RANGE - Name[%s],Value [%d]~[%d], default [%d]\n",
+ temp_int_range->name, temp_int_range->min, temp_int_range->max, temp_int_range->default_value );
+ break;
+ case CONFIGURE_VALUE_INT_ARRAY:
+ temp_int_array = (type_int_array*)((*configure_info)->info[i]->detail_info[j]);
+ g_print( "[ConfigureInfo] : INT_ARRAY - Name[%s], default [%d]\n - ",
+ temp_int_array->name, temp_int_array->default_value );
+ for( k = 0 ; k < temp_int_array->count ; k++ )
+ {
+ g_print( "[%d] ", temp_int_array->value[k] );
+ }
+ g_print( "\n" );
+ break;
+ case CONFIGURE_VALUE_INT_PAIR_ARRAY:
+ temp_int_pair_array = (type_int_pair_array*)((*configure_info)->info[i]->detail_info[j]);
+ g_print( "[ConfigureInfo] : INT_PAIR_ARRAY - Name[%s], default [%d][%d]\n - ",
+ temp_int_pair_array->name, temp_int_pair_array->default_value[0], temp_int_pair_array->default_value[0] );
+ for( k = 0 ; k < temp_int_pair_array->count ; k++ )
+ {
+ g_print( "[%d,%d] ", temp_int_pair_array->value[0][k], temp_int_pair_array->value[1][k] );
+ }
+ g_print( "\n" );
+ break;
+ case CONFIGURE_VALUE_STRING:
+ temp_string = (type_string*)((*configure_info)->info[i]->detail_info[j]);
+ g_print( "[ConfigureInfo] : STRING - Name[%s],Value[%s]\n", temp_string->name, temp_string->value );
+ break;
+ case CONFIGURE_VALUE_ELEMENT:
+ temp_element = (type_element*)((*configure_info)->info[i]->detail_info[j]);
+ g_print( "[ConfigureInfo] : Element - Name[%s],Element_Name[%s]\n", temp_element->name, temp_element->element_name );
+ for( k = 0 ; k < temp_element->count_int ; k++ )
+ {
+ g_print( " - INT[%d] Name[%s],Value[%d]\n", k, temp_element->value_int[k]->name, temp_element->value_int[k]->value );
+ }
+ 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 );
+ break;
+ }
+ }
+ else
+ {
+ g_print( "[ConfigureInfo] : Failed to get value type." );
+ }
+ }
+ }
+ }
+
+ g_print( "[ConfigureInfoPrint] : Done.\n" );
+}
+
+
+static type_element *
+__mmcamcorder_get_audio_codec_element(MMHandleType handle)
+{
+ type_element *telement = NULL;
+ char * codec_type_str = NULL;
+ 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 */
+ mm_camcorder_get_attributes(handle, NULL, MMCAM_AUDIO_ENCODER, &codec_type, NULL);
+
+ switch( codec_type )
+ {
+ case MM_AUDIO_CODEC_AMR:
+ codec_type_str = "AMR";
+ break;
+ case MM_AUDIO_CODEC_G723_1:
+ codec_type_str = "G723_1";
+ break;
+ case MM_AUDIO_CODEC_MP3:
+ codec_type_str = "MP3";
+ break;
+ case MM_AUDIO_CODEC_AAC:
+ codec_type_str = "AAC";
+ break;
+ case MM_AUDIO_CODEC_MMF:
+ codec_type_str = "MMF";
+ break;
+ case MM_AUDIO_CODEC_ADPCM:
+ codec_type_str = "ADPCM";
+ break;
+ case MM_AUDIO_CODEC_WAVE:
+ codec_type_str = "WAVE";
+ break;
+ case MM_AUDIO_CODEC_MIDI:
+ codec_type_str = "MIDI";
+ break;
+ case MM_AUDIO_CODEC_IMELODY:
+ codec_type_str = "IMELODY";
+ break;
+ case MM_AUDIO_CODEC_VORBIS:
+ codec_type_str = "VORBIS";
+ break;
+ default:
+ _mmcam_dbg_err( "Not supported audio codec[%d]", codec_type );
+ return NULL;
+ }
+
+ _mmcamcorder_conf_get_element( hcamcorder->conf_main,
+ CONFIGURE_CATEGORY_MAIN_AUDIO_ENCODER,
+ codec_type_str,
+ &telement );
+
+ return telement;
+}
+
+
+static type_element *
+__mmcamcorder_get_video_codec_element(MMHandleType handle)
+{
+ type_element *telement = NULL;
+ char * codec_type_str = NULL;
+ 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);
+
+ mmf_return_val_if_fail(sc, NULL);
+
+ _mmcam_dbg_log("");
+
+ /* Check element availability */
+ mm_camcorder_get_attributes(handle, NULL, MMCAM_VIDEO_ENCODER, &codec_type, NULL);
+
+ switch( codec_type )
+ {
+ case MM_VIDEO_CODEC_H263:
+ codec_type_str = "H263";
+ break;
+ case MM_VIDEO_CODEC_H264:
+ codec_type_str = "H264";
+ break;
+ case MM_VIDEO_CODEC_H26L:
+ codec_type_str = "H26L";
+ break;
+ case MM_VIDEO_CODEC_MPEG4:
+ codec_type_str = "MPEG4";
+ break;
+ case MM_VIDEO_CODEC_MPEG1:
+ codec_type_str = "MPEG1";
+ break;
+ case MM_VIDEO_CODEC_THEORA: // OGG
+ codec_type_str = "THEORA";
+ break;
+ default:
+ _mmcam_dbg_err( "Not supported video codec[%d]", codec_type );
+ return NULL;
+ }
+
+ _mmcamcorder_conf_get_element( hcamcorder->conf_main,
+ CONFIGURE_CATEGORY_MAIN_VIDEO_ENCODER,
+ codec_type_str,
+ &telement );
+
+ return telement;
+}
+
+
+static type_element *
+__mmcamcorder_get_image_codec_element(MMHandleType handle)
+{
+ type_element *telement = NULL;
+ char * codec_type_str = NULL;
+ 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 */
+ mm_camcorder_get_attributes(handle, NULL, MMCAM_IMAGE_ENCODER, &codec_type, NULL);
+
+ switch( codec_type )
+ {
+ case MM_IMAGE_CODEC_JPEG:
+ codec_type_str = "JPEG";
+ break;
+ case MM_IMAGE_CODEC_SRW:
+ codec_type_str = "SRW";
+ break;
+ case MM_IMAGE_CODEC_JPEG_SRW:
+ codec_type_str = "JPEG_SRW";
+ break;
+ case MM_IMAGE_CODEC_PNG:
+ codec_type_str = "PNG";
+ break;
+ case MM_IMAGE_CODEC_BMP:
+ codec_type_str = "BMP";
+ break;
+ case MM_IMAGE_CODEC_WBMP:
+ codec_type_str = "WBMP";
+ break;
+ case MM_IMAGE_CODEC_TIFF:
+ codec_type_str = "TIFF";
+ break;
+ case MM_IMAGE_CODEC_PCX:
+ codec_type_str = "PCX";
+ break;
+ case MM_IMAGE_CODEC_GIF:
+ codec_type_str = "GIF";
+ break;
+ case MM_IMAGE_CODEC_ICO:
+ codec_type_str = "ICO";
+ break;
+ case MM_IMAGE_CODEC_RAS:
+ codec_type_str = "RAS";
+ break;
+ case MM_IMAGE_CODEC_TGA:
+ codec_type_str = "TGA";
+ break;
+ case MM_IMAGE_CODEC_XBM:
+ codec_type_str = "XBM";
+ break;
+ case MM_IMAGE_CODEC_XPM:
+ codec_type_str = "XPM";
+ break;
+ default:
+ _mmcam_dbg_err( "Not supported image codec[%d]", codec_type );
+ return NULL;
+ }
+
+ _mmcamcorder_conf_get_element( hcamcorder->conf_main,
+ CONFIGURE_CATEGORY_MAIN_IMAGE_ENCODER,
+ codec_type_str,
+ &telement );
+
+ return telement;
+}
+
+
+static type_element *
+__mmcamcorder_get_file_format_element(MMHandleType handle)
+{
+ type_element *telement = NULL;
+ char * mux_type_str = NULL;
+ 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 */
+ mm_camcorder_get_attributes(handle, NULL, MMCAM_FILE_FORMAT, &file_type, NULL);
+
+ switch( file_type )
+ {
+ case MM_FILE_FORMAT_3GP:
+ mux_type_str = "3GP";
+ break;
+ case MM_FILE_FORMAT_AMR:
+ mux_type_str = "AMR";
+ break;
+ case MM_FILE_FORMAT_MP4:
+ mux_type_str = "MP4";
+ break;
+ case MM_FILE_FORMAT_AAC:
+ mux_type_str = "AAC";
+ break;
+ case MM_FILE_FORMAT_MP3:
+ mux_type_str = "MP3";
+ break;
+ case MM_FILE_FORMAT_OGG:
+ mux_type_str = "OGG";
+ break;
+ case MM_FILE_FORMAT_WAV:
+ mux_type_str = "WAV";
+ break;
+ case MM_FILE_FORMAT_AVI:
+ mux_type_str = "AVI";
+ break;
+ case MM_FILE_FORMAT_WMA:
+ mux_type_str = "WMA";
+ break;
+ case MM_FILE_FORMAT_WMV:
+ mux_type_str = "WMV";
+ break;
+ case MM_FILE_FORMAT_MID:
+ mux_type_str = "MID";
+ break;
+ case MM_FILE_FORMAT_MMF:
+ mux_type_str = "MMF";
+ break;
+ case MM_FILE_FORMAT_MATROSKA:
+ mux_type_str = "MATROSKA";
+ break;
+ default:
+ _mmcam_dbg_err( "Not supported file format[%d]", file_type );
+ return NULL;
+ }
+
+ _mmcamcorder_conf_get_element( hcamcorder->conf_main,
+ CONFIGURE_CATEGORY_MAIN_MUX,
+ mux_type_str,
+ &telement );
+
+ return telement;
+}
+
+
+type_element *
+_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:
+ telement = __mmcamcorder_get_audio_codec_element(handle);
+ break;
+ case MM_CAM_VIDEO_ENCODER:
+ telement = __mmcamcorder_get_video_codec_element(handle);
+ break;
+ case MM_CAM_IMAGE_ENCODER:
+ telement = __mmcamcorder_get_image_codec_element(handle);
+ break;
+ case MM_CAM_FILE_FORMAT:
+ telement = __mmcamcorder_get_file_format_element(handle);
+ break;
+ default :
+ _mmcam_dbg_log("Can't get element type form this profile.(%d)", type);
+ }
+
+ return telement;
+}
+
+
+int
+_mmcamcorder_get_audio_codec_format(MMHandleType handle, char * name)
+{
+ int i = 0;
+ char* audio_fmt_type[] = {
+ "AMR", /**< AMR codec*/
+ "G723_1", /**< G723.1 codec*/
+ "MP3", /**< MP3 codec*/
+ "OGG", /**< OGG codec*/
+ "AAC", /**< AAC codec*/
+ "WMA", /**< WMA codec*/
+ "MMF", /**< MMF codec*/
+ "ADPCM", /**< ADPCM codec */
+ "WAVE", /**< WAVE codec */
+ "WAVE_NEW", /**< WAVE codec */
+ "MIDI", /**< MIDI codec */
+ "IMELODY", /**< IMELODY codec */
+ "MXMF",
+ "MPA", /**< MPEG1-Layer1 codec */
+ "MP2", /**< MPEG1-Layer2 codec */
+ "G711", /**< G711 codec */
+ "G722", /**< G722 wideband speech codec */
+ "G722_1", /**< G722.1 codec */
+ "G722_2", /**< G722.2 (AMR-WB) codec */
+ "G723", /**< G723 wideband speech codec */
+ "G726", /**< G726 (ADPCM) codec */
+ "G728", /**< G728 speech codec */
+ "G729", /**< G729 codec */
+ "G729A", /**< G729a codec */
+ "G729_1", /**< G729.1 codec */
+ "REAL", /**< Real audio */
+ "AAC_LC", /**< AAC-Low complexity codec */
+ "AAC_MAIN", /**< AAC-Main profile codec */
+ "AAC_SRS", /**< AAC-Scalable sample rate codec */
+ "AAC_LTP", /**< AAC-Long term prediction codec */
+ "AAC_HE_V1", /**< AAC-High Efficiency v1 codec */
+ "AAC_HE_V2", /**< AAC-High efficiency v2 codec */
+ "AC3", /**< DolbyDigital codec */
+ "ALAC", /**< Apple Lossless audio codec */
+ "ATRAC", /**< Sony audio codec */
+ "SPEEX", /**< SPEEX audio codec */
+ "VORBIS", /**< Vor*/
+ "AIFF", /**< AIFF codec*/
+ "AU", /**< AU codec*/
+ "NONE", /**< None (will be deprecated) */
+ "PCM", /**< PCM codec */
+ "ALAW", /**< ALAW codec */
+ "MULAW", /**< MULAW codec */
+ "MS_ADPCM" /**< MS ADPCM codec */
+ };
+
+ for (i = 0; i < MM_AUDIO_CODEC_NUM; i++)
+ {
+ if (!strcmp(name, audio_fmt_type[i]))
+ {
+// _mmcam_dbg_log( "Audio codec[%d]", i);
+ return i;
+ }
+ }
+
+ _mmcam_dbg_err( "Not supported audio codec[%s]", name);
+ return -1;
+
+}
+
+
+
+int
+_mmcamcorder_get_video_codec_format(MMHandleType handle, char * name)
+{
+ int i = 0;
+ char* video_fmt_type[] = {
+ "NONE", /**< None (will be deprecated) */
+ "H263", /**< H263 codec*/
+ "H264", /**< H264 codec*/
+ "H26L", /**< H26L codec*/
+ "MPEG4", /**< MPEG4 codec*/
+ "MPEG1", /**< MPEG1 codec*/
+ "WMV", /**< WMV codec*/
+ "DIVX", /**< DIVX codec*/
+ "XVID", /**< XVID codec*/
+ "H261", /**< H261 codec*/
+ "H262", /**< H262/MPEG2-part2 codec*/
+ "H263V2", /**< H263v2 codec*/
+ "H263V3", /**< H263v3 codec*/
+ "MJPEG", /**< Motion JPEG Video codec*/
+ "MPEG2", /**< MPEG2 codec*/
+ "MPEG4_SIMPLE", /**< MPEG4 part-2 Simple profile codec*/
+ "MPEG4_ADV_SIMPLE",/**< MPEG4 part-2 Advanced Simple profile codec*/
+ "MPEG4_MAIN", /**< MPEG4 part-2 Main profile codec*/
+ "MPEG4_CORE", /**< MPEG4 part-2 Core profile codec*/
+ "MPEG4_ACE", /**< MPEG4 part-2 Adv Coding Eff profile codec*/
+ "MPEG4_ARTS", /**< MPEG4 part-2 Adv RealTime Simple profile codec*/
+ "MPEG4_AVC", /**< MPEG4 part-10 (h.264) codec*/
+ "REAL", /**< Real video*/
+ "VC1", /**< VC-1 video*/
+ "AVS", /**< AVS video*/
+ "CINEPAK", /**< Cinepak videocodec */
+ "INDEO", /**< Indeo videocodec */
+ "THEORA" /**< Theora videocodec */
+ };
+
+ for (i = 0; i < MM_VIDEO_CODEC_NUM; i++)
+ {
+ if (!strcmp(name, video_fmt_type[i]))
+ {
+// _mmcam_dbg_log( "Video codec[%d]", i);
+ return i;
+ }
+ }
+
+ _mmcam_dbg_err( "Not supported Video codec[%s]", name);
+ return -1;
+
+}
+
+
+
+int
+_mmcamcorder_get_image_codec_format(MMHandleType handle, char * name)
+{
+ int i = 0;
+ char* image_fmt_type[] = {
+ "JPEG", /**< JPEG codec */
+ "PNG", /**< PNG codec */
+ "BMP", /**< BMP codec */
+ "WBMP", /**< WBMP codec */
+ "TIFF", /**< TIFF codec */
+ "PCX", /**< PCX codec */
+ "GIF", /**< GIF codec */
+ "ICO", /**< ICO codec */
+ "RAS", /**< RAS codec */
+ "TGA", /**< TGA codec */
+ "XBM", /**< XBM codec */
+ "XPM" /**< XPM codec */
+ "SRW" /**< SRW (Samsung standard RAW) */
+ "JPEG_SRW" /**< JPEG + SRW */
+ };
+
+ for (i = 0; i < MM_IMAGE_CODEC_NUM; i++)
+ {
+ if (!strcmp(name, image_fmt_type[i]))
+ {
+// _mmcam_dbg_log( "Image codec[%d]", i);
+ return i;
+ }
+ }
+
+ _mmcam_dbg_err( "Not supported Image codec[%s]", name);
+ return -1;
+
+}
+
+
+int
+_mmcamcorder_get_mux_format(MMHandleType handle, char * name)
+{
+ int i = 0;
+ char* mux_fmt_type[] = {
+ "3GP", /**< 3GP file format */
+ "ASF", /**< Advanced Systems File file format */
+ "AVI", /**< Audio Video Interleaved file format */
+ "MATROSKA", /**< MATROSAK file format */
+ "MP4", /**< MP4 file format */
+ "OGG", /**< OGG file format */
+ "NUT", /**< NUT file format */
+ "QT", /**< MOV file format */
+ "REAL", /**< RealMedia file format */
+ "AMR", /**< AMR file format */
+ "AAC", /**< AAC file format */
+ "MP3", /**< MP3 file format */
+ "AIFF", /**< AIFF file format */
+ "AU", /**< Audio file format */
+ "WAV", /**< WAV file format */
+ "MID", /**< MID file format */
+ "MMF", /**< MMF file format */
+ "DIVX", /**< DivX file format */
+ "FLV", /**< Flash video file format */
+ "VOB", /**< DVD-Video Object file format */
+ "IMELODY", /**< IMelody file format */
+ "WMA", /**< WMA file format */
+ "WMV", /**< WMV file format */
+ "JPG" /**< JPEG file format */
+ };
+
+ for (i = 0; i < MM_FILE_FORMAT_NUM; i++)
+ {
+ if (!strcmp(name, mux_fmt_type[i]))
+ {
+// _mmcam_dbg_log( "Mux[%d]", i);
+ return i;
+ }
+ }
+
+ _mmcam_dbg_err( "Not supported Mux[%s]", name);
+ return -1;
+
+}
+
+
+int
+_mmcamcorder_get_format(MMHandleType handle, int conf_category, char * name)
+{
+ int fmt = -1;
+
+ mmf_return_val_if_fail(name, -1);
+
+ switch(conf_category)
+ {
+ case CONFIGURE_CATEGORY_MAIN_AUDIO_ENCODER:
+ fmt = _mmcamcorder_get_audio_codec_format(handle, name);
+ break;
+ case CONFIGURE_CATEGORY_MAIN_VIDEO_ENCODER:
+ fmt = _mmcamcorder_get_video_codec_format(handle, name);
+ break;
+ case CONFIGURE_CATEGORY_MAIN_IMAGE_ENCODER:
+ fmt = _mmcamcorder_get_image_codec_format(handle, name);
+ break;
+ case CONFIGURE_CATEGORY_MAIN_MUX:
+ fmt = _mmcamcorder_get_mux_format(handle, name);
+ break;
+ default :
+ _mmcam_dbg_log("Can't get format from this category.(%d)", conf_category);
+ }
+
+ return fmt;
+}
+
+int
+_mmcamcorder_get_available_format(MMHandleType handle, int conf_category, int ** format)
+{
+ mmf_camcorder_t *hcamcorder= MMF_CAMCORDER(handle);
+ camera_conf* configure_info = NULL;
+ int *arr = NULL;
+ int total_count = 0;
+
+ mmf_return_val_if_fail(hcamcorder, 0);
+
+ _mmcam_dbg_log("conf_category:%d", conf_category);
+
+ configure_info = hcamcorder->conf_main;
+
+ if( configure_info->info[conf_category] )
+ {
+ int count = configure_info->info[conf_category]->count;
+ conf_info* info = configure_info->info[conf_category];
+ int i = 0;
+ int fmt = 0;
+ char* name = NULL;
+
+ _mmcam_dbg_log("count[%d], info[%p]", count, info);
+
+ if ((count <= 0) || (!info))
+ {
+ return total_count;
+ }
+
+ arr = (int*) g_malloc0(count * sizeof(int));
+
+ for( i = 0 ; i < count ; i++ )
+ {
+ if( info->detail_info[i] == NULL )
+ {
+ continue;
+ }
+
+ name = ((type_element*)(info->detail_info[i]))->name;
+
+ if ((fmt = _mmcamcorder_get_format(handle, conf_category, name)) >= 0)
+ {
+ arr[total_count++] = fmt;
+ }
+ _mmcam_dbg_log("name:%s, fmt:%d", name, fmt);
+ }
+ }
+
+ *format = arr;
+
+ return total_count;
+}
+
diff --git a/src/mm_camcorder_exifinfo.c b/src/mm_camcorder_exifinfo.c
new file mode 100644
index 0000000..a1a2f2e
--- /dev/null
+++ b/src/mm_camcorder_exifinfo.c
@@ -0,0 +1,642 @@
+/*
+ * libmm-camcorder
+ *
+ * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: Jeongmo Yang <jm80.yang@samsung.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include "mm_camcorder_exifinfo.h"
+#include "mm_camcorder_exifdef.h"
+
+#include <libexif/exif-loader.h>
+#include <libexif/exif-utils.h>
+#include <libexif/exif-data.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <time.h>
+#include <mm_debug.h>
+#include <mm_error.h>
+#include <glib.h>
+
+#define MM_EXIFINFO_USE_BINARY_EXIFDATA 1
+#define JPEG_MAX_SIZE 20000000
+#define JPEG_THUMBNAIL_MAX_SIZE (128*1024)
+#if MM_EXIFINFO_USE_BINARY_EXIFDATA
+/**
+ * Exif Binary Data.
+ */
+#include <string.h>
+#define _EXIF_BIN_SIZE_ ((unsigned int)174)
+unsigned char g_exif_bin [_EXIF_BIN_SIZE_] = {
+ 0x45 , 0x78 , 0x69 , 0x66 , 0x00 , 0x00 , 0x49 , 0x49 , 0x2a , 0x00 , 0x08 , 0x00 , 0x00 , 0x00 , 0x05 , 0x00
+ , 0x1a , 0x01 , 0x05 , 0x00 , 0x01 , 0x00 , 0x00 , 0x00 , 0x4a , 0x00 , 0x00 , 0x00 , 0x1b , 0x01 , 0x05 , 0x00
+ , 0x01 , 0x00 , 0x00 , 0x00 , 0x52 , 0x00 , 0x00 , 0x00 , 0x28 , 0x01 , 0x03 , 0x00 , 0x01 , 0x00 , 0x00 , 0x00
+ , 0x02 , 0x00 , 0x00 , 0x00 , 0x13 , 0x02 , 0x03 , 0x00 , 0x01 , 0x00 , 0x00 , 0x00 , 0x01 , 0x00 , 0x00 , 0x00
+ , 0x69 , 0x87 , 0x04 , 0x00 , 0x01 , 0x00 , 0x00 , 0x00 , 0x5a , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00
+ , 0x48 , 0x00 , 0x00 , 0x00 , 0x01 , 0x00 , 0x00 , 0x00 , 0x48 , 0x00 , 0x00 , 0x00 , 0x01 , 0x00 , 0x00 , 0x00
+ , 0x06 , 0x00 , 0x00 , 0x90 , 0x07 , 0x00 , 0x04 , 0x00 , 0x00 , 0x00 , 0x30 , 0x32 , 0x31 , 0x30 , 0x01 , 0x91
+ , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0xa0 , 0x07 , 0x00 , 0x04 , 0x00
+ , 0x00 , 0x00 , 0x30 , 0x31 , 0x30 , 0x30 , 0x01 , 0xa0 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00
+ , 0x00 , 0x00 , 0x02 , 0xa0 , 0x04 , 0x00 , 0x01 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x03 , 0xa0
+ , 0x04 , 0x00 , 0x01 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00
+};
+#endif
+
+/**
+ * Structure for exif entry.
+ */
+typedef struct _mm_exif_entry_t
+{
+ ExifTag tag; /**< exif tag*/
+ ExifFormat format; /**< exif format*/
+ unsigned long components; /**< number of components*/
+ unsigned char *data; /**< data*/
+ unsigned int size; /**< size of data*/
+} mm_exif_entry_type;
+
+
+/**
+ * local functions.
+ */
+static void
+_exif_set_uint16 (int is_motorola, void * out, unsigned short in)
+{
+ if (is_motorola) {
+ ((unsigned char *)out)[0] = in & 0x00ff;
+ ((unsigned char *)out)[1] = in >> 8;
+ } else {
+ ((unsigned char *)out)[0] = in >> 8;
+ ((unsigned char *)out)[1] = in & 0x00ff;
+ }
+}
+
+
+static unsigned long
+_exif_get_jpeg_marker_offset (void *jpeg, int jpeg_size, unsigned short marker)
+{
+ unsigned char *p = NULL;
+ unsigned char *src = jpeg;
+ int src_sz = jpeg_size;
+ unsigned char m[2];
+ unsigned long ret;
+ int i;
+
+ // mmf_debug (MMF_DEBUG_LOG, "%s()\n", __func__);
+
+ m[0] = marker >> 8;
+ m[1] = marker & 0x00FF;
+
+ mmf_debug (MMF_DEBUG_LOG,"[%05d][%s] marker: 0x%02X 0x%02X\n\n", __LINE__, __func__,m[0], m[1]);
+
+ if (*src == 0xff && *(src + 1) == 0xd8)
+ {
+ p = src + 2; /* SOI(start of image) */
+ }
+ else
+ {
+ mmf_debug (MMF_DEBUG_ERROR,"[%05d][%s] invalid JPEG file.\n", __LINE__, __func__);
+ return 0UL;
+ }
+
+ for (i = 0; i < src_sz - (1 + 2); i++, p++)
+ {
+ if (*p == 0xff)
+ {
+ /*marker is 0xFFxx*/
+ if (*(p + 1) == m[1])
+ {
+ ret = p - src;
+ mmf_debug (MMF_DEBUG_LOG,"[%05d][%s]marker offset: %lu %p %p.\n", __LINE__, __func__,ret, (p+1), src);
+ return ret;
+ }
+ }
+ }
+ mmf_debug (MMF_DEBUG_ERROR,"[%05d][%s]Marker not found.\n", __LINE__, __func__);
+ return 0UL;
+}
+
+
+ExifData*
+mm_exif_get_exif_data_from_data (mm_exif_info_t *info)
+{
+ ExifData *ed = NULL;
+
+ //mmf_debug (MMF_DEBUG_LOG, "%s()\n", __func__);
+
+ ed = exif_data_new_from_data(info->data, info->size);
+ if( ed == NULL )
+ {
+ mmf_debug (MMF_DEBUG_ERROR,"[%05d][%s]Null exif data. (ed:%p)\n", __LINE__, __func__, ed);
+ }
+
+ return ed;
+}
+
+
+ExifData*
+mm_exif_get_exif_from_info (mm_exif_info_t *info)
+{
+ ExifData *ed = NULL;
+ ExifLoader *loader = NULL;
+
+ unsigned char size[2];
+ unsigned int i;
+
+ //mmf_debug (MMF_DEBUG_LOG, "%s()\n", __func__);
+
+ /*get ExifData from info*/
+ loader = exif_loader_new ();
+
+ size[0] = (unsigned char) (info->size);
+ size[1] = (unsigned char) (info->size >> 8);
+ exif_loader_write (loader, size, 2);
+
+ for (i = 0; i < info->size && exif_loader_write (loader, info->data + i, 1); i++);
+
+ ed = exif_loader_get_data (loader);
+ exif_loader_unref (loader);
+ return ed;
+}
+
+
+int
+mm_exif_set_exif_to_info (mm_exif_info_t *info, ExifData *exif)
+{
+ unsigned char *eb = NULL;
+ unsigned int ebs;
+
+ if (!exif)
+ {
+ mmf_debug (MMF_DEBUG_ERROR,"[%05d][%s]exif Null\n", __LINE__, __func__);
+ return MM_ERROR_CAMCORDER_NOT_INITIALIZED;
+ }
+
+ mmf_debug (MMF_DEBUG_LOG,"[%05d][%s]exif(ifd :%p)\n", __LINE__, __func__, exif->ifd);
+
+ if(info->data)
+ {
+ free (info->data);
+ info->data = NULL;
+ info->size = 0;
+ }
+
+ exif_data_save_data (exif, &eb, &ebs);
+ if(eb==NULL)
+ {
+ mmf_debug (MMF_DEBUG_ERROR,"[%05d][%s]MM_ERROR_CAMCORDER_LOW_MEMORY\n", __LINE__, __func__);
+ return MM_ERROR_CAMCORDER_LOW_MEMORY;
+ }
+ info->data = eb;
+ info->size = ebs;
+ return MM_ERROR_NONE;
+}
+
+
+int
+mm_exif_set_add_entry (ExifData *exif, ExifIfd ifd, ExifTag tag,ExifFormat format,unsigned long components,unsigned char* data)
+{
+// mmf_debug (MMF_DEBUG_LOG, "%s()\n", __func__);
+ ExifData *ed = (ExifData *)exif;
+ ExifEntry *e = NULL;
+
+ if(exif==NULL || format<=0 || components<=0 || data==NULL)
+ {
+ mmf_debug (MMF_DEBUG_ERROR,"[%05d][%s] invalid argument exif=%p format=%d, components=%lu data=%p!\n", __LINE__, __func__,exif,format,components,data);
+ return MM_ERROR_CAMCORDER_INVALID_ARGUMENT;
+ }
+ /*remove same tag in EXIF*/
+ exif_content_remove_entry (ed->ifd[ifd], exif_content_get_entry(ed->ifd[ifd], tag));
+ /*create new tag*/
+ e = exif_entry_new ();
+ if(e==NULL)
+ {
+ mmf_debug (MMF_DEBUG_ERROR,"[%05d][%s] entry create error!\n", __LINE__, __func__);
+ return MM_ERROR_CAMCORDER_LOW_MEMORY;
+ }
+ exif_entry_initialize (e, tag);
+
+ e->tag = tag;
+ e->format = format;
+ e->components = components;
+
+ if(e->size==0)
+ {
+ e->data=NULL;
+ e->data=malloc(exif_format_get_size(format)*e->components);
+ if(!e->data)
+ {
+ exif_entry_unref(e);
+ return MM_ERROR_CAMCORDER_LOW_MEMORY;
+ }
+ if(format==EXIF_FORMAT_ASCII)
+ memset (e->data, '\0', exif_format_get_size(format)*e->components);
+ }
+ e->size = exif_format_get_size(format)*e->components;
+ memcpy(e->data,data,e->size);
+ exif_content_add_entry (ed->ifd[ifd], e);
+ exif_entry_unref(e);
+
+ return MM_ERROR_NONE;
+}
+
+
+
+
+/**
+ * global functions.
+ */
+
+
+int
+mm_exif_create_exif_info (mm_exif_info_t **info)
+{
+ mm_exif_info_t *x = NULL;
+#if (MM_EXIFINFO_USE_BINARY_EXIFDATA == 0)
+ ExifData *ed = NULL;
+ unsigned char *eb = NULL;
+ unsigned int ebs;
+#endif
+
+ mmf_debug (MMF_DEBUG_LOG,"[%05d][%s]\n", __LINE__, __func__);
+
+ x = malloc (sizeof (mm_exif_info_t));
+ if(!x)
+ {
+ mmf_debug (MMF_DEBUG_ERROR,"[%05d][%s]malloc error\n", __LINE__, __func__);
+ return MM_ERROR_CAMCORDER_LOW_MEMORY;
+ }
+#if MM_EXIFINFO_USE_BINARY_EXIFDATA
+ x->data=NULL;
+ x->data = malloc (_EXIF_BIN_SIZE_);
+ if(!x->data)
+ {
+ mmf_debug (MMF_DEBUG_ERROR,"[%05d][%s]malloc error\n", __LINE__, __func__);
+ free(x);
+ return MM_ERROR_CAMCORDER_LOW_MEMORY;
+ }
+ memcpy (x->data, g_exif_bin, _EXIF_BIN_SIZE_);
+ x->size = _EXIF_BIN_SIZE_;
+#else
+ ed = exif_data_new ();
+ if(!ed )
+ {
+ mmf_debug (MMF_DEBUG_ERROR,"[%05d][%s]exif data new error\n", __LINE__, __func__);
+ return MM_ERROR_CAMCORDER_LOW_MEMORY;
+ }
+
+ exif_data_set_byte_order (ed, EXIF_BYTE_ORDER_INTEL);
+ exif_data_set_data_type (ed, EXIF_DATA_TYPE_COMPRESSED);
+ exif_data_set_option (ed, EXIF_DATA_OPTION_FOLLOW_SPECIFICATION);
+
+ exif_data_fix (ed);
+
+ exif_data_save_data (ed, &eb, &ebs);
+ if(eb==NULL)
+ {
+ mmf_debug (MMF_DEBUG_ERROR,"[%05d][%s]exif_data_save_data error\n", __LINE__, __func__);
+ free(x->data);
+ free(x);
+ exif_data_unref (ed);
+ return MM_ERROR_CAMCORDER_INTERNAL;
+ }
+ exif_data_unref (ed);
+
+ x->data = eb;
+ x->size = ebs;
+#endif
+
+ *info = x;
+
+ //mmf_debug (MMF_DEBUG_LOG, "%s() Data:%p Size:%d\n", __func__, x->data, x->size);
+
+ return MM_ERROR_NONE;
+}
+
+void
+mm_exif_destory_exif_info (mm_exif_info_t *info)
+{
+ //mmf_debug (MMF_DEBUG_LOG, "%s()\n", __func__);
+
+#if MM_EXIFINFO_USE_BINARY_EXIFDATA
+ if (info) {
+ if (info->data)
+ free (info->data);
+ free (info);
+ }
+#else
+ if (info) {
+ if (info->data)
+ exif_mem_free (info->data);
+ free (info);
+ }
+#endif
+}
+
+
+int
+mm_exif_add_thumbnail_info (mm_exif_info_t *info, void *thumbnail, int width, int height, int len)
+{
+ ExifData *ed = NULL;
+ static ExifLong elong[10];
+
+ unsigned char *p_compressed = NULL;
+ int ret = MM_ERROR_NONE;
+ int cntl = 0;
+
+ mmf_debug (MMF_DEBUG_LOG,"[%05d][%s] Thumbnail size:%d, width:%d, height:%d\n", __LINE__, __func__, len, width, height);
+
+ if( len > JPEG_THUMBNAIL_MAX_SIZE )
+ {
+ mmf_debug (MMF_DEBUG_ERROR,"[%05d][%s] Thumbnail size[%d] over!!! Skip inserting thumbnail...\n", __LINE__, __func__, len);
+ return MM_ERROR_NONE;
+ }
+
+ /* get ExifData from info*/
+ ed = mm_exif_get_exif_from_info(info);
+ ed->data=thumbnail;
+ ed->size = len;
+
+ /* set thumbnail data */
+ p_compressed = malloc(sizeof(ExifShort));
+ if (p_compressed != NULL) {
+ exif_set_short(p_compressed, exif_data_get_byte_order(ed), 6);
+ ret = mm_exif_set_add_entry(ed, EXIF_IFD_1, EXIF_TAG_COMPRESSION, EXIF_FORMAT_SHORT, 1, p_compressed);
+ if (ret != MM_ERROR_NONE) {
+ goto exit;
+ }
+ } else {
+ ret = MM_ERROR_CAMCORDER_LOW_MEMORY;
+ goto exit;
+ }
+
+ /* set thumbnail size */
+ exif_set_long ((unsigned char *)&elong[cntl], exif_data_get_byte_order(ed), width);
+ ret = mm_exif_set_add_entry(ed, EXIF_IFD_1, EXIF_TAG_IMAGE_WIDTH, EXIF_FORMAT_LONG, 1, (unsigned char*)&elong[cntl++]);
+ if (ret != MM_ERROR_NONE) {
+ goto exit;
+ }
+ exif_set_long ((unsigned char *)&elong[cntl], exif_data_get_byte_order(ed), height);
+ ret = mm_exif_set_add_entry(ed, EXIF_IFD_1, EXIF_TAG_IMAGE_LENGTH, EXIF_FORMAT_LONG, 1, (unsigned char*)&elong[cntl++]);
+ if (ret != MM_ERROR_NONE) {
+ goto exit;
+ }
+
+ ret = mm_exif_set_exif_to_info (info, ed);
+ if (ret != MM_ERROR_NONE) {
+ goto exit;
+ }
+
+ ed->data = NULL;
+ ed->size = 0;
+ exif_data_unref (ed);
+
+exit :
+ if(p_compressed != NULL)
+ free(p_compressed);
+ return ret;
+}
+
+
+int mm_exif_mnote_create (ExifData *exif)
+{
+ ExifData* ed = exif;
+ ExifDataOption o = 0;
+ if(!ed){
+ mmf_debug (MMF_DEBUG_ERROR,"[%05d][%s] invalid argument exif=%p \n", __LINE__, __func__,ed);
+ return MM_ERROR_CAMCORDER_INVALID_ARGUMENT;
+ }
+
+ if(!exif_data_mnote_data_new(ed, MAKER_SAMSUNG, o )){
+ mmf_debug (MMF_DEBUG_ERROR,"[%05d][%s] exif_mnote_data_samsung_new() failed. \n", __LINE__, __func__);
+ return MM_ERROR_CAMCORDER_MNOTE_CREATION;
+ }
+
+ return MM_ERROR_NONE;
+}
+
+
+int mm_exif_mnote_set_add_entry (ExifData *exif, MnoteSamsungTag tag, int index, int subindex1, int subindex2)
+{
+ ExifData *ed = exif;
+ ExifMnoteData *md;
+
+ ExifShort product_id = 32768; //should be modified
+ char serialNum[] = "SerialNum123"; //should be modified
+
+ if(!ed){
+ mmf_debug (MMF_DEBUG_ERROR,"[%05d][%s] invalid argument exif=%p \n", __LINE__, __func__,ed);
+ return MM_ERROR_CAMCORDER_INVALID_ARGUMENT;
+ }
+
+ md = exif_data_get_mnote_data (ed);
+ if(!md){
+ mmf_debug (MMF_DEBUG_ERROR,"[%05d][%s] exif_data_get_mnote_data() failed. \n", __LINE__, __func__);
+ return MM_ERROR_CAMCORDER_MNOTE_CREATION;
+ }
+
+ if(!exif_data_mnote_set_mem_for_adding_entry(md, MAKER_SAMSUNG)){
+ mmf_debug (MMF_DEBUG_ERROR,"[%05d][%s] exif_data_mnote_set_mem_for_adding_entry() failed. \n", __LINE__, __func__);
+ return MM_ERROR_CAMCORDER_MNOTE_MALLOC;
+ }
+
+ exif_mnote_data_set_byte_order(md, (ExifByteOrder) exif_data_get_data_order(ed));
+
+ switch(tag){
+ case MNOTE_SAMSUNG_TAG_MNOTE_VERSION:
+ if(!exif_data_mnote_set_add_entry(md, MAKER_SAMSUNG, tag, EXIF_FORMAT_UNDEFINED, 4, index)){
+ mmf_debug (MMF_DEBUG_ERROR,"[%05d][%s] exif_data_mnote_set_add_entry() failed. \n", __LINE__, __func__);
+ return MM_ERROR_CAMCORDER_MNOTE_ADD_ENTRY;
+ }
+ break;
+ case MNOTE_SAMSUNG_TAG_DEVICE_ID:
+ if(!exif_data_mnote_set_add_entry(md, MAKER_SAMSUNG, tag, EXIF_FORMAT_LONG, 1, index)){
+ mmf_debug (MMF_DEBUG_ERROR,"[%05d][%s] exif_data_mnote_set_add_entry() failed. \n", __LINE__, __func__);
+ return MM_ERROR_CAMCORDER_MNOTE_ADD_ENTRY;
+ }
+ break;
+ case MNOTE_SAMSUNG_TAG_MODEL_ID:
+ if(!exif_data_mnote_set_add_entry_subtag(md, MAKER_SAMSUNG, tag, EXIF_FORMAT_LONG, 1, MNOTE_SAMSUNG_SUBTAG_MODEL_ID_CLASS, subindex1, MNOTE_SAMSUNG_SUBTAG_MODEL_ID_DEVEL, subindex2, product_id )){
+ mmf_debug (MMF_DEBUG_ERROR,"[%05d][%s] exif_data_mnote_set_add_entry_subtag() failed. \n", __LINE__, __func__);
+ return MM_ERROR_CAMCORDER_MNOTE_ADD_ENTRY;
+ }
+ break;
+ case MNOTE_SAMSUNG_TAG_COLOR_INFO:
+ case MNOTE_SAMSUNG_TAG_SERIAL_NUM:
+ if(!exif_data_mnote_set_add_entry_string(md, MAKER_SAMSUNG, tag, EXIF_FORMAT_ASCII, strlen(serialNum), serialNum)){
+ mmf_debug (MMF_DEBUG_ERROR,"[%05d][%s] exif_data_mnote_set_add_entry_string() failed. \n", __LINE__, __func__);
+ return MM_ERROR_CAMCORDER_MNOTE_ADD_ENTRY;
+ }
+ break;
+ case MNOTE_SAMSUNG_TAG_IMAGE_COUNT:
+ case MNOTE_SAMSUNG_TAG_GPS_INFO01:
+ case MNOTE_SAMSUNG_TAG_GPS_INFO02:
+ case MNOTE_SAMSUNG_TAG_PREVIEW_IMAGE:
+ case MNOTE_SAMSUNG_TAG_FAVOR_TAGGING:
+ case MNOTE_SAMSUNG_TAG_SRW_COMPRESS:
+ case MNOTE_SAMSUNG_TAG_COLOR_SPACE:
+ if(!exif_data_mnote_set_add_entry(md, MAKER_SAMSUNG, tag, EXIF_FORMAT_LONG, 1, index)){
+ mmf_debug (MMF_DEBUG_ERROR,"[%05d][%s] exif_data_mnote_set_add_entry() failed. \n", __LINE__, __func__);
+ return MM_ERROR_CAMCORDER_MNOTE_ADD_ENTRY;
+ }
+ break;
+ case MNOTE_SAMSUNG_TAG_AE:
+ case MNOTE_SAMSUNG_TAG_AF:
+ case MNOTE_SAMSUNG_TAG_AWB01:
+ case MNOTE_SAMSUNG_TAG_AWB02:
+ case MNOTE_SAMSUNG_TAG_IPC:
+ case MNOTE_SAMSUNG_TAG_SCENE_RESULT:
+ case MNOTE_SAMSUNG_TAG_SADEBUG_INFO01:
+ case MNOTE_SAMSUNG_TAG_SADEBUG_INFO02:
+ case MNOTE_SAMSUNG_TAG_FACE_DETECTION:
+ if(!exif_data_mnote_set_add_entry(md, MAKER_SAMSUNG, tag, EXIF_FORMAT_LONG, 1, index)){
+ mmf_debug (MMF_DEBUG_ERROR,"[%05d][%s] exif_data_mnote_set_add_entry() failed. \n", __LINE__, __func__);
+ return MM_ERROR_CAMCORDER_MNOTE_ADD_ENTRY;
+ }
+ break;
+ case MNOTE_SAMSUNG_TAG_FACE_FEAT01:
+ case MNOTE_SAMSUNG_TAG_FACE_FEAT02:
+ case MNOTE_SAMSUNG_TAG_FACE_RECOG:
+ case MNOTE_SAMSUNG_TAG_LENS_INFO:
+ case MNOTE_SAMSUNG_TAG_THIRDPARTY:
+ break;
+ default:
+ break;
+ }
+ return MM_ERROR_NONE;
+}
+
+
+int
+mm_exif_write_exif_jpeg_to_file (char *filename, mm_exif_info_t *info, void *jpeg, int jpeg_len)
+{
+ FILE *fp = NULL;
+ unsigned long offset_jpeg_start;
+ unsigned short head[2]={0,};
+ unsigned short head_len=0;
+ unsigned char *eb = NULL;
+ unsigned int ebs;
+
+ mmf_debug (MMF_DEBUG_LOG,"[%05d][%s]\n", __LINE__, __func__);
+
+ eb = info->data;
+ ebs = info->size;
+
+ /*get DQT*/
+ offset_jpeg_start = _exif_get_jpeg_marker_offset (jpeg, jpeg_len, 0xffdb);
+ if (offset_jpeg_start == 0) {
+ return -1;
+ }
+
+ /*create file*/
+ fp = fopen (filename, "wb");
+ if (!fp) {
+ mmf_debug (MMF_DEBUG_ERROR, "%s(), fopen() failed [%s].\n", __func__, filename);
+ return MM_ERROR_IMAGE_FILEOPEN;
+ }
+
+ /*set SOI, APP1*/
+ _exif_set_uint16 (0, &head[0], 0xffd8);
+ _exif_set_uint16 (0, &head[1], 0xffe1);
+ /*set header length*/
+ _exif_set_uint16 (0, &head_len, (unsigned short)(ebs + 2));
+
+ if(head[0]==0 || head[1]==0 || head_len==0)
+ {
+ mmf_debug (MMF_DEBUG_ERROR,"[%05d][%s]setting error\n", __LINE__, __func__);
+ fclose (fp);
+ return -1;
+ }
+
+ fwrite (&head[0], 1, 2, fp); /*SOI marker*/
+ fwrite (&head[1], 1, 2, fp); /*APP1 marker*/
+ fwrite (&head_len, 1, 2, fp); /*length of APP1*/
+ fwrite (eb, 1, ebs, fp); /*EXIF*/
+ fwrite (jpeg + offset_jpeg_start, 1, jpeg_len - offset_jpeg_start, fp); /*IMAGE*/
+
+ fclose (fp);
+
+ return MM_ERROR_NONE;
+}
+
+int
+mm_exif_write_exif_jpeg_to_memory (void **mem, unsigned int *length, mm_exif_info_t *info, void *jpeg, unsigned int jpeg_len)
+{
+ /*output*/
+ unsigned char *m = NULL;
+ int m_len = 0;
+ /**/
+ unsigned long offset_jpeg_start;
+ unsigned short head[2]={0,};
+ unsigned short head_len=0;
+ unsigned char *eb = NULL;
+ unsigned int ebs;
+ mmf_debug (MMF_DEBUG_LOG,"[%05d][%s]\n", __LINE__, __func__);
+
+ if(info==NULL || jpeg==NULL)
+ {
+ mmf_debug (MMF_DEBUG_ERROR, "%s(), MM_ERROR_CAMCORDER_INVALID_ARGUMENT info=%p, jpeg=%p\n", __func__,info,jpeg);
+ return MM_ERROR_CAMCORDER_INVALID_ARGUMENT;
+ }
+
+ if(jpeg_len>JPEG_MAX_SIZE)
+ {
+ mmf_debug (MMF_DEBUG_ERROR, "%s(),jpeg_len is worng jpeg_len=%d\n", __func__,jpeg_len);
+ return MM_ERROR_CAMCORDER_DEVICE_WRONG_JPEG;
+ }
+
+ eb = info->data;
+ ebs = info->size;
+ /*get DQT*/
+ offset_jpeg_start = _exif_get_jpeg_marker_offset (jpeg, (int)jpeg_len, 0xffdb);
+ if (offset_jpeg_start == 0) {
+ return MM_ERROR_CAMCORDER_INVALID_ARGUMENT;
+ }
+
+ /*length of output image*/
+ /*SOI + APP1 + length of APP1 + length of EXIF + IMAGE*/
+ m_len = 2 + 2 + 2 + ebs + (jpeg_len - offset_jpeg_start);
+ /*alloc output image*/
+ m = malloc (m_len);
+ if (!m) {
+ mmf_debug (MMF_DEBUG_ERROR, "%s(), malloc() failed.\n", __func__);
+ return MM_ERROR_CAMCORDER_LOW_MEMORY;
+ }
+
+ /*set SOI, APP1*/
+ _exif_set_uint16 (0, &head[0], 0xffd8);
+ _exif_set_uint16 (0, &head[1], 0xffe1);
+ /*set header length*/
+ _exif_set_uint16 (0, &head_len, (unsigned short)(ebs + 2));
+ if(head[0]==0 || head[1]==0 || head_len==0)
+ {
+ mmf_debug (MMF_DEBUG_ERROR,"[%05d][%s]setting error\n", __LINE__, __func__);
+ free(m);
+ return MM_ERROR_CAMCORDER_INVALID_ARGUMENT;
+ }
+ memcpy (m, &head[0], 2); /*SOI marker*/
+ memcpy (m + 2, &head[1], 2); /*APP1 marker*/
+ memcpy (m + 2 + 2, &head_len, 2); /*length of APP1*/
+ memcpy (m + 2 + 2 + 2, eb, ebs); /*EXIF*/
+ memcpy (m + 2 + 2 + 2 + ebs, jpeg + offset_jpeg_start, jpeg_len - offset_jpeg_start); /*IMAGE*/
+
+ /*set ouput param*/
+ *mem = m;
+ *length = m_len;
+
+ return MM_ERROR_NONE;
+}
diff --git a/src/mm_camcorder_gstcommon.c b/src/mm_camcorder_gstcommon.c
new file mode 100644
index 0000000..b631caf
--- /dev/null
+++ b/src/mm_camcorder_gstcommon.c
@@ -0,0 +1,2243 @@
+/*
+ * libmm-camcorder
+ *
+ * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: Jeongmo Yang <jm80.yang@samsung.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+/*=======================================================================================
+| INCLUDE FILES |
+=======================================================================================*/
+#include <gst/interfaces/xoverlay.h>
+#include <gst/interfaces/cameracontrol.h>
+#include <sys/time.h>
+#include <unistd.h>
+
+#include "mm_camcorder_internal.h"
+#include "mm_camcorder_gstcommon.h"
+
+/*-----------------------------------------------------------------------
+| GLOBAL VARIABLE DEFINITIONS for internal |
+-----------------------------------------------------------------------*/
+/* 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, 0, 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, },
+};
+
+/* 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, },
+};
+
+
+/*-----------------------------------------------------------------------
+| LOCAL VARIABLE DEFINITIONS for internal |
+-----------------------------------------------------------------------*/
+#define USE_AUDIO_CLOCK_TUNE
+#define _MMCAMCORDER_WAIT_EOS_TIME 5.0 //sec
+#define _DPRAM_RAW_PCM_LOCATION "/dev/rawPCM0"
+
+/*-----------------------------------------------------------------------
+| LOCAL FUNCTION PROTOTYPES: |
+-----------------------------------------------------------------------*/
+/* STATIC INTERNAL FUNCTION */
+/**
+ * These functions are preview video data probing function.
+ * If this function is linked with certain pad by gst_pad_add_buffer_probe(),
+ * this function will be called when data stream pass through the pad.
+ *
+ * @param[in] pad probing pad which calls this function.
+ * @param[in] buffer buffer which contains stream data.
+ * @param[in] u_data user data.
+ * @return This function returns true on success, or false value with error
+ * @remarks
+ * @see __mmcamcorder_create_preview_pipeline()
+ */
+static gboolean __mmcamcorder_video_dataprobe_preview(GstPad *pad, GstBuffer *buffer, gpointer u_data);
+static gboolean __mmcamcorder_video_dataprobe_vsink(GstPad *pad, GstBuffer *buffer, gpointer u_data);
+static gboolean __mmcamcorder_video_dataprobe_vsink_drop_by_time(GstPad *pad, GstBuffer *buffer, gpointer u_data);
+
+static int __mmcamcorder_get_amrnb_bitrate_mode(int bitrate);
+
+/*=======================================================================================
+| FUNCTION DEFINITIONS |
+=======================================================================================*/
+/*-----------------------------------------------------------------------
+| GLOBAL FUNCTION DEFINITIONS: |
+-----------------------------------------------------------------------*/
+int _mmcamcorder_create_videosrc_bin(MMHandleType handle)
+{
+ int err = MM_ERROR_NONE;
+ int rotate = 0;
+ int fps = 0;
+ int slow_fps = 0;
+ int hold_af = 0;
+ int UseVideoscale = 0;
+ int PictureFormat = 0;
+ int codectype = 0;
+ int capture_width = 0;
+ int capture_height = 0;
+ char *videosrc_name = NULL;
+ char *err_name = NULL;
+
+ GList *element_list = NULL;
+ GstCaps *caps = NULL;
+ GstPad *video_tee0 = NULL;
+ GstPad *video_tee1 = NULL;
+
+ mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
+ _MMCamcorderSubContext *sc = NULL;
+ type_element *VideosrcElement = NULL;
+ type_int_array *input_index = NULL;
+
+ mmf_return_val_if_fail(hcamcorder, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
+
+ sc = MMF_CAMCORDER_SUBCONTEXT(handle);
+ mmf_return_val_if_fail(sc, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
+ mmf_return_val_if_fail(sc->element, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
+
+ _mmcam_dbg_log("");
+
+ /* Check existence */
+ if (sc->element[_MMCAMCORDER_VIDEOSRC_BIN].gst) {
+ if (((GObject *)sc->element[_MMCAMCORDER_VIDEOSRC_BIN].gst)->ref_count > 0) {
+ gst_object_unref(sc->element[_MMCAMCORDER_VIDEOSRC_BIN].gst);
+ }
+ _mmcam_dbg_log("_MMCAMCORDER_VIDEOSRC_BIN is Already existed.");
+ }
+
+ /* Get video device index info */
+ _mmcamcorder_conf_get_value_int_array(hcamcorder->conf_ctrl,
+ CONFIGURE_CATEGORY_CTRL_CAMERA,
+ "InputIndex",
+ &input_index );
+ if (input_index == NULL) {
+ _mmcam_dbg_err("Failed to get input_index");
+ return MM_ERROR_CAMCORDER_CREATE_CONFIGURE;
+ }
+
+ err = mm_camcorder_get_attributes(handle, &err_name,
+ MMCAM_CAMERA_FORMAT, &PictureFormat,
+ MMCAM_CAMERA_FPS, &fps,
+ "camera-slow-motion-fps", &slow_fps,
+ MMCAM_CAMERA_ROTATION, &rotate,
+ MMCAM_CAPTURE_WIDTH, &capture_width,
+ MMCAM_CAPTURE_HEIGHT, &capture_height,
+ MMCAM_IMAGE_ENCODER, &codectype,
+ "camera-hold-af-after-capturing", &hold_af,
+ NULL);
+ if (err != MM_ERROR_NONE) {
+ _mmcam_dbg_warn("Get attrs fail. (%s:%x)", err_name, err);
+ SAFE_FREE(err_name);
+ return err;
+ }
+
+ /* Get fourcc from picture format */
+ sc->fourcc = _mmcamcorder_get_fourcc(PictureFormat, codectype, hcamcorder->use_zero_copy_format);
+
+ /* Get videosrc element and its name from configure */
+ _mmcamcorder_conf_get_element(hcamcorder->conf_main,
+ CONFIGURE_CATEGORY_MAIN_VIDEO_INPUT,
+ "VideosrcElement",
+ &VideosrcElement);
+ _mmcamcorder_conf_get_value_element_name(VideosrcElement, &videosrc_name);
+
+ /* Create bin element */
+ __ta__(" videosrc_bin",
+ _MMCAMCORDER_BIN_MAKE(sc, _MMCAMCORDER_VIDEOSRC_BIN, "videosrc_bin", err);
+ );
+
+ /* Create child element */
+ __ta__(" videosrc_src",
+ _MMCAMCORDER_ELEMENT_MAKE(sc, _MMCAMCORDER_VIDEOSRC_SRC, videosrc_name, "videosrc_src", element_list, err);
+ );
+ __ta__(" videosrc_capsfilter",
+ _MMCAMCORDER_ELEMENT_MAKE(sc, _MMCAMCORDER_VIDEOSRC_FILT, "capsfilter", "videosrc_filter", element_list, err);
+ );
+
+ sc->is_slow = FALSE;
+ MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst, "high-speed-fps", 0);
+ MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst, "capture-width", capture_width);
+ MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst, "capture-height", capture_height);
+
+ if (hcamcorder->type == MM_CAMCORDER_MODE_VIDEO) {
+ _mmcamcorder_conf_get_value_int(hcamcorder->conf_main,
+ CONFIGURE_CATEGORY_MAIN_VIDEO_INPUT,
+ "UseVideoscale",
+ &UseVideoscale);
+ if (UseVideoscale) {
+ int set_width = 0;
+ int set_height = 0;
+ int scale_width = 0;
+ int scale_height = 0;
+ int scale_method = 0;
+ char *videoscale_name = NULL;
+ type_element *VideoscaleElement = NULL;
+
+ _mmcamcorder_conf_get_element(hcamcorder->conf_main,
+ CONFIGURE_CATEGORY_MAIN_VIDEO_INPUT,
+ "VideoscaleElement",
+ &VideoscaleElement);
+ _mmcamcorder_conf_get_value_element_name(VideoscaleElement, &videoscale_name);
+ __ta__(" videosrc_scale",
+ _MMCAMCORDER_ELEMENT_MAKE(sc, _MMCAMCORDER_VIDEOSRC_SCALE, videoscale_name, "videosrc_scale", element_list, err);
+ );
+ __ta__(" videoscale_capsfilter",
+ _MMCAMCORDER_ELEMENT_MAKE(sc, _MMCAMCORDER_VIDEOSRC_VSFLT, "capsfilter", "videosrc_scalefilter", element_list, err);
+ );
+
+ _mmcamcorder_conf_get_value_element_int(VideoscaleElement, "width", &scale_width);
+ _mmcamcorder_conf_get_value_element_int(VideoscaleElement, "height", &scale_height);
+ _mmcamcorder_conf_get_value_element_int(VideoscaleElement, "method", &scale_method);
+
+ if (rotate == MM_VIDEO_INPUT_ROTATION_90 ||
+ rotate == MM_VIDEO_INPUT_ROTATION_270) {
+ set_width = scale_height;
+ set_height = scale_width;
+ } else {
+ set_width = scale_width;
+ set_height = scale_height;
+ }
+
+ _mmcam_dbg_log("VideoSRC Scale[%dx%d], Method[%d]", set_width, set_height, scale_method);
+
+ caps = gst_caps_new_simple("video/x-raw-yuv",
+ "format", GST_TYPE_FOURCC, sc->fourcc,
+ "width", G_TYPE_INT, set_width,
+ "height", G_TYPE_INT, set_height,
+ NULL);
+ MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_VSFLT].gst, "caps", caps);
+ MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_SCALE].gst, "method", scale_method);
+
+ gst_caps_unref(caps);
+ caps = NULL;
+ }
+
+ if (slow_fps > 0) {
+ sc->is_slow = TRUE;
+ MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst, "high-speed-fps", fps);
+ }
+ }
+
+ __ta__(" tee",
+ _MMCAMCORDER_ELEMENT_MAKE(sc, _MMCAMCORDER_VIDEOSRC_TEE, "tee", "videosrc_tee", element_list, err);
+ );
+
+ /* Set basic infomation of videosrc element */
+ _mmcamcorder_conf_set_value_element_property(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst, VideosrcElement);
+
+ /* Set video device index */
+ MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst, "camera-id", input_index->default_value);
+ MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst, "hold-af-after-capturing", hold_af);
+
+ _mmcam_dbg_log("Current mode[%d]", hcamcorder->type);
+
+ /* Set sensor mode as CAMERA */
+ MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst, "sensor-mode", 0);
+
+ /* Set caps by rotation */
+ _mmcamcorder_set_videosrc_rotation(handle, rotate);
+
+ if (!_mmcamcorder_add_elements_to_bin(GST_BIN(sc->element[_MMCAMCORDER_VIDEOSRC_BIN].gst), element_list)) {
+ _mmcam_dbg_err( "element add error." );
+ err = MM_ERROR_CAMCORDER_RESOURCE_CREATION;
+ goto pipeline_creation_error;
+ }
+
+ if (!_mmcamcorder_link_elements(element_list)) {
+ _mmcam_dbg_err( "element link error." );
+ err = MM_ERROR_CAMCORDER_GST_LINK;
+ goto pipeline_creation_error;
+ }
+
+ video_tee0 = gst_element_get_request_pad(sc->element[_MMCAMCORDER_VIDEOSRC_TEE].gst, "src%d");
+ video_tee1 = gst_element_get_request_pad(sc->element[_MMCAMCORDER_VIDEOSRC_TEE].gst, "src%d");
+
+ MMCAMCORDER_G_OBJECT_SET((sc->element[_MMCAMCORDER_VIDEOSRC_TEE].gst), "alloc-pad", video_tee0);
+
+ /* Ghost pad */
+ if ((gst_element_add_pad( sc->element[_MMCAMCORDER_VIDEOSRC_BIN].gst, gst_ghost_pad_new("src0", video_tee0) )) < 0) {
+ _mmcam_dbg_err("failed to create ghost pad1 on _MMCAMCORDER_VIDEOSRC_BIN.");
+ gst_object_unref(video_tee0);
+ video_tee0 = NULL;
+ gst_object_unref(video_tee1);
+ video_tee1 = NULL;
+ err = MM_ERROR_CAMCORDER_GST_LINK;
+ goto pipeline_creation_error;
+ }
+
+ if ((gst_element_add_pad( sc->element[_MMCAMCORDER_VIDEOSRC_BIN].gst, gst_ghost_pad_new("src1", video_tee1) )) < 0) {
+ _mmcam_dbg_err("failed to create ghost pad2 on _MMCAMCORDER_VIDEOSRC_BIN.");
+ gst_object_unref(video_tee0);
+ video_tee0 = NULL;
+ gst_object_unref(video_tee1);
+ video_tee1 = NULL;
+ err = MM_ERROR_CAMCORDER_GST_LINK;
+ goto pipeline_creation_error;
+ }
+
+ gst_object_unref(video_tee0);
+ video_tee0 = NULL;
+ gst_object_unref(video_tee1);
+ video_tee1 = NULL;
+
+ if (element_list) {
+ g_list_free(element_list);
+ element_list = NULL;
+ }
+
+ return MM_ERROR_NONE;
+
+pipeline_creation_error:
+ _MMCAMCORDER_ELEMENT_REMOVE( sc, _MMCAMCORDER_VIDEOSRC_SRC );
+ _MMCAMCORDER_ELEMENT_REMOVE( sc, _MMCAMCORDER_VIDEOSRC_FILT );
+ _MMCAMCORDER_ELEMENT_REMOVE( sc, _MMCAMCORDER_VIDEOSRC_SCALE );
+ _MMCAMCORDER_ELEMENT_REMOVE( sc, _MMCAMCORDER_VIDEOSRC_VSFLT );
+ _MMCAMCORDER_ELEMENT_REMOVE( sc, _MMCAMCORDER_VIDEOSRC_TEE );
+ _MMCAMCORDER_ELEMENT_REMOVE( sc, _MMCAMCORDER_VIDEOSRC_BIN );
+ if (element_list) {
+ g_list_free(element_list);
+ element_list = NULL;
+ }
+
+ return err;
+}
+
+
+int _mmcamcorder_create_audiosrc_bin(MMHandleType handle)
+{
+ int err = MM_ERROR_NONE;
+ int val = 0;
+ int rate = 0;
+ int format = 0;
+ int channel = 0;
+ int a_enc = MM_AUDIO_CODEC_AMR;
+ int a_dev = MM_AUDIO_DEVICE_MIC;
+ int UseNoiseSuppressor = 0;
+ double volume = 0.0;
+ char *err_name = NULL;
+ char *audiosrc_name = NULL;
+ char *cat_name = NULL;
+
+ GstCaps *caps = NULL;
+ GstPad *pad = NULL;
+ GList *element_list = NULL;
+
+ mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
+ _MMCamcorderSubContext *sc = NULL;
+ _MMCamcorderGstElement *last_element = NULL;
+ type_element *AudiosrcElement = NULL;
+
+ mmf_return_val_if_fail(hcamcorder, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
+
+ sc = MMF_CAMCORDER_SUBCONTEXT(handle);
+ mmf_return_val_if_fail(sc, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
+ mmf_return_val_if_fail(sc->element, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
+
+ _mmcam_dbg_log("");
+
+ err = _mmcamcorder_check_audiocodec_fileformat_compatibility(handle);
+ if (err != MM_ERROR_NONE) {
+ return err;
+ }
+
+ _mmcamcorder_conf_get_value_int(hcamcorder->conf_main,
+ CONFIGURE_CATEGORY_MAIN_RECORD,
+ "UseNoiseSuppressor",
+ &UseNoiseSuppressor);
+
+ err = mm_camcorder_get_attributes(handle, &err_name,
+ MMCAM_AUDIO_DEVICE, &a_dev,
+ MMCAM_AUDIO_ENCODER, &a_enc,
+ MMCAM_AUDIO_ENCODER_BITRATE, &val,
+ MMCAM_AUDIO_SAMPLERATE, &rate,
+ MMCAM_AUDIO_FORMAT, &format,
+ MMCAM_AUDIO_CHANNEL, &channel,
+ MMCAM_AUDIO_VOLUME, &volume,
+ NULL);
+ if (err != MM_ERROR_NONE) {
+ _mmcam_dbg_warn("Get attrs fail. (%s:%x)", err_name, err);
+ SAFE_FREE(err_name);
+ return err;
+ }
+
+ /* Check existence */
+ if (sc->element[_MMCAMCORDER_AUDIOSRC_BIN].gst) {
+ if (((GObject *)sc->element[_MMCAMCORDER_AUDIOSRC_BIN].gst)->ref_count > 0) {
+ gst_object_unref(sc->element[_MMCAMCORDER_AUDIOSRC_BIN].gst);
+ }
+ _mmcam_dbg_log("_MMCAMCORDER_AUDIOSRC_BIN is Already existed. Unref once...");
+ }
+
+ /* Create bin element */
+ __ta__(" audiosource_bin",
+ _MMCAMCORDER_BIN_MAKE(sc, _MMCAMCORDER_AUDIOSRC_BIN, "audiosource_bin", err);
+ );
+
+ if (a_dev == MM_AUDIO_DEVICE_MODEM) {
+ cat_name = strdup("AudiomodemsrcElement");
+ } else {
+ /* MM_AUDIO_DEVICE_MIC or others */
+ cat_name = strdup("AudiosrcElement");
+ }
+
+ if (cat_name == NULL) {
+ _mmcam_dbg_err("strdup failed.");
+ err = MM_ERROR_CAMCORDER_LOW_MEMORY;
+ goto pipeline_creation_error;
+ }
+
+ _mmcamcorder_conf_get_element(hcamcorder->conf_main,
+ CONFIGURE_CATEGORY_MAIN_AUDIO_INPUT,
+ cat_name,
+ &AudiosrcElement);
+ _mmcamcorder_conf_get_value_element_name(AudiosrcElement, &audiosrc_name);
+
+ free(cat_name);
+ cat_name = NULL;
+
+ _mmcam_dbg_log("Audio src name : %s", audiosrc_name);
+
+ __ta__(" audiosrc",
+ _MMCAMCORDER_ELEMENT_MAKE(sc, _MMCAMCORDER_AUDIOSRC_SRC, audiosrc_name, NULL, element_list, err);
+ );
+
+ _mmcamcorder_conf_set_value_element_property(sc->element[_MMCAMCORDER_AUDIOSRC_SRC].gst, AudiosrcElement);
+
+ __ta__(" audiosource_capsfilter",
+ _MMCAMCORDER_ELEMENT_MAKE(sc, _MMCAMCORDER_AUDIOSRC_FILT, "capsfilter", NULL, element_list, err);
+ );
+
+ if (a_enc != MM_AUDIO_CODEC_VORBIS) {
+ __ta__(" audiosource_volume",
+ _MMCAMCORDER_ELEMENT_MAKE(sc, _MMCAMCORDER_AUDIOSRC_VOL, "volume", NULL, element_list, err);
+ );
+ }
+
+ if (UseNoiseSuppressor && a_enc != MM_AUDIO_CODEC_AAC) {
+ __ta__(" noise_suppressor",
+ _MMCAMCORDER_ELEMENT_MAKE(sc, _MMCAMCORDER_AUDIOSRC_NS, "noisesuppressor", "audiofilter", element_list, err);
+ );
+ }
+
+ /* Set basic infomation */
+ if (a_enc != MM_AUDIO_CODEC_VORBIS) {
+ int depth = 0;
+
+ 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. */
+ MMCAMCORDER_G_OBJECT_SET( sc->element[_MMCAMCORDER_AUDIOSRC_VOL].gst, "volume", 1.0);
+ } else {
+ MMCAMCORDER_G_OBJECT_SET( sc->element[_MMCAMCORDER_AUDIOSRC_VOL].gst, "mute", FALSE);
+ MMCAMCORDER_G_OBJECT_SET( sc->element[_MMCAMCORDER_AUDIOSRC_VOL].gst, "volume", volume);
+ }
+
+ if (format == MM_CAMCORDER_AUDIO_FORMAT_PCM_S16_LE) {
+ depth = 16;
+ } else { /* MM_CAMCORDER_AUDIO_FORMAT_PCM_U8 */
+ depth = 8;
+ }
+
+ 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]",
+ rate, channel, depth);
+ } 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]",
+ rate, channel, BYTE_ORDER);
+ }
+
+ MMCAMCORDER_G_OBJECT_SET((sc->element[_MMCAMCORDER_AUDIOSRC_FILT].gst), "caps", caps);
+ gst_caps_unref(caps);
+
+ if (!_mmcamcorder_add_elements_to_bin(GST_BIN(sc->element[_MMCAMCORDER_AUDIOSRC_BIN].gst), element_list)) {
+ _mmcam_dbg_err("element add error.");
+ err = MM_ERROR_CAMCORDER_RESOURCE_CREATION;
+ goto pipeline_creation_error;
+ }
+
+ if (!_mmcamcorder_link_elements(element_list)) {
+ _mmcam_dbg_err( "element link error." );
+ err = MM_ERROR_CAMCORDER_GST_LINK;
+ goto pipeline_creation_error;
+ }
+
+ 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->element[_MMCAMCORDER_AUDIOSRC_BIN].gst, gst_ghost_pad_new("src", pad) )) < 0) {
+ gst_object_unref(pad);
+ pad = NULL;
+ _mmcam_dbg_err("failed to create ghost pad on _MMCAMCORDER_AUDIOSRC_BIN.");
+ err = MM_ERROR_CAMCORDER_GST_LINK;
+ goto pipeline_creation_error;
+ }
+
+ gst_object_unref(pad);
+ pad = NULL;
+
+ if (element_list) {
+ g_list_free(element_list);
+ element_list = NULL;
+ }
+
+ return MM_ERROR_NONE;
+
+pipeline_creation_error:
+ _MMCAMCORDER_ELEMENT_REMOVE(sc, _MMCAMCORDER_AUDIOSRC_SRC);
+ _MMCAMCORDER_ELEMENT_REMOVE(sc, _MMCAMCORDER_AUDIOSRC_FILT);
+ _MMCAMCORDER_ELEMENT_REMOVE(sc, _MMCAMCORDER_AUDIOSRC_VOL);
+ _MMCAMCORDER_ELEMENT_REMOVE(sc, _MMCAMCORDER_AUDIOSRC_QUE);
+ _MMCAMCORDER_ELEMENT_REMOVE(sc, _MMCAMCORDER_AUDIOSRC_CONV);
+ _MMCAMCORDER_ELEMENT_REMOVE(sc, _MMCAMCORDER_AUDIOSRC_ENC);
+ _MMCAMCORDER_ELEMENT_REMOVE(sc, _MMCAMCORDER_AUDIOSRC_BIN);
+ if (element_list) {
+ g_list_free(element_list);
+ element_list = NULL;
+ }
+
+ return err;
+}
+
+
+int _mmcamcorder_create_videosink_bin(MMHandleType handle)
+{
+ int err = MM_ERROR_NONE;
+ int rect_width = 0;
+ int rect_height = 0;
+ int camera_width = 0;
+ int camera_height = 0;
+ int rotate = 0;
+ int camera_format = MM_PIXEL_FORMAT_NV12;
+ int UseVideoscale = 0, EnableConvertedSC = 0;
+ int scale_method = 0;
+ char* videosink_name = NULL;
+ char* videoscale_name = NULL;
+ char* err_name = NULL;
+
+ GstCaps *caps = NULL;
+ GstPad *pad = NULL;
+ GList *element_list = NULL;
+
+ mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
+ _MMCamcorderSubContext *sc = NULL;
+ _MMCamcorderGstElement *first_element = NULL;
+ type_element *VideoscaleElement = NULL;
+
+ mmf_return_val_if_fail(hcamcorder, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
+ sc = MMF_CAMCORDER_SUBCONTEXT(handle);
+
+ mmf_return_val_if_fail(sc, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
+ mmf_return_val_if_fail(sc->element, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
+
+ _mmcam_dbg_log("START");
+
+ /* Get attributes */
+ err = mm_camcorder_get_attributes(handle, &err_name,
+ MMCAM_CAMERA_WIDTH, &camera_width,
+ MMCAM_CAMERA_HEIGHT, &camera_height,
+ MMCAM_CAMERA_FORMAT, &camera_format,
+ MMCAM_DISPLAY_RECT_WIDTH, &rect_width,
+ MMCAM_DISPLAY_RECT_HEIGHT, &rect_height,
+ MMCAM_DISPLAY_ROTATION, &rotate,
+ "enable-converted-stream-callback", &EnableConvertedSC,
+ NULL);
+ if (err != MM_ERROR_NONE) {
+ _mmcam_dbg_warn("Get attrs fail. (%s:%x)", err_name, err);
+ SAFE_FREE(err_name);
+ return err;
+ }
+
+ /* Get videosink name */
+ _mmcamcorder_conf_get_value_element_name(sc->VideosinkElement, &videosink_name);
+
+ /* Check existence */
+ if (sc->element[_MMCAMCORDER_VIDEOSINK_BIN].gst) {
+ if (((GObject *)sc->element[_MMCAMCORDER_VIDEOSINK_BIN].gst)->ref_count > 0) {
+ gst_object_unref(sc->element[_MMCAMCORDER_VIDEOSINK_BIN].gst);
+ }
+ _mmcam_dbg_log("_MMCAMCORDER_VIDEOSINK_BIN is Already existed. Unref once...");
+ }
+
+ /* Create bin element */
+ __ta__(" videosink_bin",
+ _MMCAMCORDER_BIN_MAKE(sc, _MMCAMCORDER_VIDEOSINK_BIN, "videosink_bin", err);
+ );
+
+ _mmcamcorder_conf_get_value_int(hcamcorder->conf_main,
+ CONFIGURE_CATEGORY_MAIN_VIDEO_OUTPUT,
+ "UseVideoscale",
+ &UseVideoscale);
+
+ /* Create child element */
+ if (EnableConvertedSC ||
+ !strcmp(videosink_name, "evasimagesink") ||
+ !strcmp(videosink_name, "ximagesink")) {
+ if (camera_format == MM_PIXEL_FORMAT_NV12 ||
+ camera_format == MM_PIXEL_FORMAT_NV12T) {
+ int set_rotate = 0;
+
+ __ta__(" videosink_fimcconvert",
+ _MMCAMCORDER_ELEMENT_MAKE(sc, _MMCAMCORDER_VIDEOSINK_CLS, "fimcconvert", NULL, element_list, err);
+ );
+
+ if (rotate < MM_DISPLAY_ROTATION_FLIP_HORZ) {
+ set_rotate = rotate * 90;
+ } else {
+ set_rotate = 0;
+ }
+
+ if (rect_width == 0 || rect_height == 0) {
+ _mmcam_dbg_warn("rect_width or height is 0. set camera width and height.");
+
+ if (rotate == MM_DISPLAY_ROTATION_90 ||
+ rotate == MM_DISPLAY_ROTATION_270) {
+ rect_width = camera_height;
+ rect_height = camera_width;
+ } else {
+ rect_width = camera_width;
+ rect_height = camera_height;
+ }
+ }
+
+ _mmcam_dbg_log("Fimcconvert set values - %dx%d, rotate: %d", rect_width, rect_height, set_rotate);
+ MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_CLS].gst, "src-width", rect_width);
+ MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_CLS].gst, "src-height", rect_height);
+ MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_CLS].gst, "rotate", set_rotate);
+ } else {
+ __ta__(" videosink_ffmpegcolorspace",
+ _MMCAMCORDER_ELEMENT_MAKE(sc, _MMCAMCORDER_VIDEOSINK_CLS, "ffmpegcolorspace", NULL, element_list, err);
+ );
+ }
+ } else if(UseVideoscale) {
+ __ta__(" videosink_queue",
+ _MMCAMCORDER_ELEMENT_MAKE(sc, _MMCAMCORDER_VIDEOSINK_QUE, "queue", NULL, element_list, err);
+ );
+
+ _mmcamcorder_conf_get_element(hcamcorder->conf_main,
+ CONFIGURE_CATEGORY_MAIN_VIDEO_OUTPUT,
+ "VideoscaleElement",
+ &VideoscaleElement);
+ _mmcamcorder_conf_get_value_element_name(VideoscaleElement, &videoscale_name);
+
+ __ta__(" videosink_videoscale",
+ _MMCAMCORDER_ELEMENT_MAKE(sc, _MMCAMCORDER_VIDEOSINK_SCALE, videoscale_name, NULL, element_list, err);
+ );
+ __ta__(" videosink_capsfilter",
+ _MMCAMCORDER_ELEMENT_MAKE(sc, _MMCAMCORDER_VIDEOSINK_FILT, "capsfilter", NULL, element_list, err);
+ );
+
+ _mmcamcorder_conf_get_value_element_int(VideoscaleElement, "method", &scale_method);
+ _mmcam_dbg_log("VideoSINK Scale[%dx%d], Method[%d]", rect_width, rect_height, scale_method);
+
+ if (rect_width == 0 || rect_height == 0) {
+ _mmcam_dbg_warn("rect_width or height is 0. set camera width and height.");
+
+ rect_width = camera_width;
+ rect_height = camera_height;
+ }
+
+ caps = gst_caps_new_simple("video/x-raw-yuv",
+ "width", G_TYPE_INT, rect_width,
+ "height", G_TYPE_INT, rect_height,
+ NULL);
+ MMCAMCORDER_G_OBJECT_SET((sc->element[_MMCAMCORDER_VIDEOSINK_FILT].gst), "caps", caps);
+ MMCAMCORDER_G_OBJECT_SET((sc->element[_MMCAMCORDER_VIDEOSINK_SCALE].gst), "method", scale_method);
+ gst_caps_unref(caps);
+ caps = NULL;
+ }
+
+ if (sc->element[_MMCAMCORDER_VIDEOSINK_QUE].gst == NULL) {
+ __ta__(" videosink_queue",
+ _MMCAMCORDER_ELEMENT_MAKE(sc, _MMCAMCORDER_VIDEOSINK_QUE, "queue", "videosink_queue", element_list, err);
+ );
+ }
+
+ __ta__(" videosink",
+ _MMCAMCORDER_ELEMENT_MAKE(sc, _MMCAMCORDER_VIDEOSINK_SINK, videosink_name, NULL, element_list, err);
+ );
+
+ if (!strcmp(videosink_name, "xvimagesink") ||
+ !strcmp(videosink_name, "ximagesink") ||
+ !strcmp(videosink_name, "evasimagesink")) {
+ if (_mmcamcorder_videosink_window_set(handle, sc->VideosinkElement) != MM_ERROR_NONE) {
+ _mmcam_dbg_err("_mmcamcorder_videosink_window_set error");
+ err = MM_ERROR_CAMCORDER_INVALID_ARGUMENT;
+ goto pipeline_creation_error;
+ }
+ }
+
+ _mmcamcorder_conf_set_value_element_property(sc->element[_MMCAMCORDER_VIDEOSINK_SINK].gst, sc->VideosinkElement);
+
+ if (!_mmcamcorder_add_elements_to_bin(GST_BIN(sc->element[_MMCAMCORDER_VIDEOSINK_BIN].gst), element_list)) {
+ _mmcam_dbg_err("element add error.");
+ err = MM_ERROR_CAMCORDER_RESOURCE_CREATION;
+ goto pipeline_creation_error;
+ }
+
+ if (!_mmcamcorder_link_elements(element_list)) {
+ _mmcam_dbg_err("element link error.");
+ err = MM_ERROR_CAMCORDER_GST_LINK;
+ goto pipeline_creation_error;
+ }
+
+ first_element = (_MMCamcorderGstElement*)(element_list->data);
+ __ta__(" gst_element_get_static_pad",
+ pad = gst_element_get_static_pad( first_element->gst, "sink");
+ );
+ if ((gst_element_add_pad( sc->element[_MMCAMCORDER_VIDEOSINK_BIN].gst, gst_ghost_pad_new("sink", pad) )) < 0) {
+ gst_object_unref(pad);
+ pad = NULL;
+ _mmcam_dbg_err("failed to create ghost pad on _MMCAMCORDER_VIDEOSINK_BIN.");
+ err = MM_ERROR_CAMCORDER_GST_LINK;
+ goto pipeline_creation_error;
+ }
+
+ gst_object_unref(pad);
+ pad = NULL;
+
+ if (element_list) {
+ g_list_free(element_list);
+ element_list = NULL;
+ }
+
+ _mmcam_dbg_log("END");
+
+ return MM_ERROR_NONE;
+
+pipeline_creation_error:
+ _MMCAMCORDER_ELEMENT_REMOVE(sc, _MMCAMCORDER_VIDEOSINK_QUE);
+ _MMCAMCORDER_ELEMENT_REMOVE(sc, _MMCAMCORDER_VIDEOSINK_SCALE);
+ _MMCAMCORDER_ELEMENT_REMOVE(sc, _MMCAMCORDER_VIDEOSINK_FILT);
+ _MMCAMCORDER_ELEMENT_REMOVE(sc, _MMCAMCORDER_VIDEOSINK_CLS);
+ _MMCAMCORDER_ELEMENT_REMOVE(sc, _MMCAMCORDER_VIDEOSINK_SINK);
+ _MMCAMCORDER_ELEMENT_REMOVE(sc, _MMCAMCORDER_VIDEOSINK_BIN);
+ if (element_list) {
+ g_list_free(element_list);
+ element_list = NULL;
+ }
+
+ return err;
+}
+
+
+int _mmcamcorder_create_encodesink_bin(MMHandleType handle)
+{
+ int err = MM_ERROR_NONE;
+ int result = 0;
+ int channel = 0;
+ int profile = 0;
+ int audio_enc = 0;
+ int v_bitrate = 0;
+ int a_bitrate = 0;
+ int encodebin_profile = 0;
+ int auto_audio_convert = 0;
+ int auto_audio_resample = 0;
+ int auto_color_space = 0;
+ char *gst_element_venc_name = NULL;
+ char *gst_element_aenc_name = NULL;
+ char *gst_element_ienc_name = NULL;
+ char *gst_element_mux_name = NULL;
+ char *gst_element_rsink_name = NULL;
+ char *str_profile = NULL;
+ char *str_aac = NULL;
+ char *str_aar = NULL;
+ char *str_acs = NULL;
+ char *err_name = NULL;
+
+ GstCaps *caps = NULL;
+ GstPad *pad = NULL;
+ GList *element_list = NULL;
+
+ mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
+ _MMCamcorderSubContext *sc = NULL;
+ type_element *VideoencElement = NULL;
+ type_element *AudioencElement = NULL;
+ type_element *ImageencElement = NULL;
+ type_element *MuxElement = NULL;
+ type_element *RecordsinkElement = NULL;
+
+ mmf_return_val_if_fail(hcamcorder, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
+
+ sc = MMF_CAMCORDER_SUBCONTEXT(handle);
+ mmf_return_val_if_fail(sc, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
+ mmf_return_val_if_fail(sc->element, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
+
+ _mmcam_dbg_log("");
+
+ /* Check existence */
+ if (sc->element[_MMCAMCORDER_ENCSINK_BIN].gst) {
+ if (((GObject *)sc->element[_MMCAMCORDER_ENCSINK_BIN].gst)->ref_count > 0) {
+ gst_object_unref(sc->element[_MMCAMCORDER_ENCSINK_BIN].gst);
+ }
+ _mmcam_dbg_log("_MMCAMCORDER_ENCSINK_BIN is Already existed.");
+ }
+
+ /* Create bin element */
+ __ta__(" encodesink_bin",
+ _MMCAMCORDER_BIN_MAKE(sc, _MMCAMCORDER_ENCSINK_BIN, "encodesink_bin", err);
+ );
+
+ /* Create child element */
+ __ta__(" encodebin",
+ _MMCAMCORDER_ELEMENT_MAKE(sc, _MMCAMCORDER_ENCSINK_ENCBIN, "encodebin", NULL, element_list, err);
+ );
+
+ /* check element availability */
+ err = mm_camcorder_get_attributes(handle, &err_name,
+ MMCAM_MODE, &profile,
+ MMCAM_AUDIO_ENCODER, &audio_enc,
+ MMCAM_AUDIO_CHANNEL, &channel,
+ MMCAM_VIDEO_ENCODER_BITRATE, &v_bitrate,
+ MMCAM_AUDIO_ENCODER_BITRATE, &a_bitrate,
+ NULL);
+ if (err != MM_ERROR_NONE) {
+ _mmcam_dbg_warn("Get attrs fail. (%s:%x)", err_name, err);
+ SAFE_FREE (err_name);
+ return err;
+ }
+
+ _mmcam_dbg_log("Profile[%d]", profile);
+
+ /* Set information */
+ if (profile == MM_CAMCORDER_MODE_VIDEO) {
+ str_profile = "VideoProfile";
+ str_aac = "VideoAutoAudioConvert";
+ str_aar = "VideoAutoAudioResample";
+ str_acs = "VideoAutoColorSpace";
+ } else if (profile == MM_CAMCORDER_MODE_AUDIO) {
+ str_profile = "AudioProfile";
+ str_aac = "AudioAutoAudioConvert";
+ str_aar = "AudioAutoAudioResample";
+ str_acs = "AudioAutoColorSpace";
+ } else if (profile == MM_CAMCORDER_MODE_IMAGE) {
+ str_profile = "ImageProfile";
+ str_aac = "ImageAutoAudioConvert";
+ str_aar = "ImageAutoAudioResample";
+ str_acs = "ImageAutoColorSpace";
+ }
+
+ _mmcamcorder_conf_get_value_int(hcamcorder->conf_main, CONFIGURE_CATEGORY_MAIN_RECORD, str_profile, &encodebin_profile);
+ _mmcamcorder_conf_get_value_int(hcamcorder->conf_main, CONFIGURE_CATEGORY_MAIN_RECORD, str_aac, &auto_audio_convert);
+ _mmcamcorder_conf_get_value_int(hcamcorder->conf_main, CONFIGURE_CATEGORY_MAIN_RECORD, str_aar, &auto_audio_resample);
+ _mmcamcorder_conf_get_value_int(hcamcorder->conf_main, CONFIGURE_CATEGORY_MAIN_RECORD, str_acs, &auto_color_space);
+
+ _mmcam_dbg_log("Profile:%d, AutoAudioConvert:%d, AutoAudioResample:%d, AutoColorSpace:%d",
+ encodebin_profile, auto_audio_convert, auto_audio_resample, auto_color_space);
+
+ MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "profile", encodebin_profile);
+ MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "auto-audio-convert", auto_audio_convert);
+ MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "auto-audio-resample", auto_audio_resample);
+ MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "auto-colorspace", auto_color_space);
+ MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "use-video-toggle", FALSE);
+
+ /* Codec */
+ if (profile == MM_CAMCORDER_MODE_VIDEO) {
+ int use_venc_queue = 0;
+
+ VideoencElement = _mmcamcorder_get_type_element(handle, MM_CAM_VIDEO_ENCODER);
+
+ if (!VideoencElement) {
+ _mmcam_dbg_err("Fail to get type element");
+ err = MM_ERROR_CAMCORDER_RESOURCE_CREATION;
+ goto pipeline_creation_error;
+ }
+
+ _mmcamcorder_conf_get_value_element_name(VideoencElement, &gst_element_venc_name);
+
+ MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "venc-name", gst_element_venc_name);
+ _MMCAMCORDER_ENCODEBIN_ELMGET(sc, _MMCAMCORDER_ENCSINK_VENC, "video-encode", err);
+
+ _mmcamcorder_conf_get_value_int(hcamcorder->conf_main,
+ CONFIGURE_CATEGORY_MAIN_RECORD,
+ "UseVideoEncoderQueue",
+ &use_venc_queue);
+ if (use_venc_queue) {
+ _MMCAMCORDER_ENCODEBIN_ELMGET(sc, _MMCAMCORDER_ENCSINK_VENC_QUE, "use-venc-queue", err);
+ }
+
+ if (!strcmp(gst_element_venc_name, "ari_h263enc")) {
+ MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "auto-colorspace", TRUE);
+ }
+ }
+
+ if (sc->is_slow == FALSE) {
+ if (profile == MM_CAMCORDER_MODE_AUDIO || profile == MM_CAMCORDER_MODE_VIDEO) {
+ int use_aenc_queue =0;
+
+ AudioencElement = _mmcamcorder_get_type_element(handle, MM_CAM_AUDIO_ENCODER);
+ if (!AudioencElement) {
+ _mmcam_dbg_err("Fail to get type element");
+ err = MM_ERROR_CAMCORDER_RESOURCE_CREATION;
+ goto pipeline_creation_error;
+ }
+
+ _mmcamcorder_conf_get_value_element_name(AudioencElement, &gst_element_aenc_name);
+
+ MMCAMCORDER_G_OBJECT_SET(sc->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",
+ "channels", G_TYPE_INT, 1,
+ NULL);
+ MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "auto-audio-convert", TRUE);
+ MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "acaps", caps);
+ gst_caps_unref (caps);
+ caps = NULL;
+ }
+
+ if (audio_enc == MM_AUDIO_CODEC_OGG) {
+ caps = gst_caps_new_simple("audio/x-raw-int",
+ NULL);
+ MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "auto-audio-convert", TRUE);
+ MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "acaps", caps);
+ gst_caps_unref (caps);
+ caps = NULL;
+ _mmcam_dbg_log("***** MM_AUDIO_CODEC_OGG : setting audio/x-raw-int ");
+ }
+
+ _mmcamcorder_conf_get_value_int(hcamcorder->conf_main,
+ CONFIGURE_CATEGORY_MAIN_RECORD,
+ "UseAudioEncoderQueue",
+ &use_aenc_queue);
+ if (use_aenc_queue) {
+ _MMCAMCORDER_ENCODEBIN_ELMGET(sc, _MMCAMCORDER_ENCSINK_AENC_QUE, "use-aenc-queue", err);
+ }
+ }
+ }
+
+ if (profile == MM_CAMCORDER_MODE_IMAGE) {
+ ImageencElement = _mmcamcorder_get_type_element(handle, MM_CAM_IMAGE_ENCODER);
+ if (!ImageencElement) {
+ _mmcam_dbg_err("Fail to get type element");
+ err = MM_ERROR_CAMCORDER_RESOURCE_CREATION;
+ goto pipeline_creation_error;
+ }
+
+ _mmcamcorder_conf_get_value_element_name(ImageencElement, &gst_element_ienc_name);
+
+ MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "ienc-name", gst_element_ienc_name);
+ _MMCAMCORDER_ENCODEBIN_ELMGET(sc, _MMCAMCORDER_ENCSINK_IENC, "image-encode", err);
+ }
+
+ /* Mux */
+ if (profile == MM_CAMCORDER_MODE_AUDIO || profile == MM_CAMCORDER_MODE_VIDEO) {
+ MuxElement = _mmcamcorder_get_type_element(handle, MM_CAM_FILE_FORMAT);
+ if (!MuxElement) {
+ _mmcam_dbg_err("Fail to get type element");
+ err = MM_ERROR_CAMCORDER_RESOURCE_CREATION;
+ goto pipeline_creation_error;
+ }
+
+ _mmcamcorder_conf_get_value_element_name(MuxElement, &gst_element_mux_name);
+
+ __ta__(" mux",
+ MMCAMCORDER_G_OBJECT_SET(sc->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->element[_MMCAMCORDER_ENCSINK_MUX].gst, MuxElement);
+ }
+
+ /* Sink */
+ if (profile == MM_CAMCORDER_MODE_AUDIO || profile == MM_CAMCORDER_MODE_VIDEO) {
+ _mmcamcorder_conf_get_element(hcamcorder->conf_main,
+ CONFIGURE_CATEGORY_MAIN_RECORD,
+ "RecordsinkElement",
+ &RecordsinkElement );
+ _mmcamcorder_conf_get_value_element_name(RecordsinkElement, &gst_element_rsink_name);
+
+ __ta__(" Recordsink_sink",
+ _MMCAMCORDER_ELEMENT_MAKE(sc, _MMCAMCORDER_ENCSINK_SINK, gst_element_rsink_name, NULL, element_list, err);
+ );
+
+ _mmcamcorder_conf_set_value_element_property(sc->element[_MMCAMCORDER_ENCSINK_SINK].gst, RecordsinkElement);
+ } else {
+ /* for stillshot */
+ __ta__(" fakesink",
+ _MMCAMCORDER_ELEMENT_MAKE(sc, _MMCAMCORDER_ENCSINK_SINK, "fakesink", NULL, element_list, err);
+ );
+ }
+
+ if (profile == MM_CAMCORDER_MODE_VIDEO) {
+ /* video encoder attribute setting */
+ if (v_bitrate > 0) {
+ MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_ENCSINK_VENC].gst, "bitrate", v_bitrate);
+ } else {
+ _mmcam_dbg_warn("video bitrate is too small[%d], so skip setting. Use DEFAULT value.", v_bitrate);
+ }
+ /*MMCAMCORDER_G_OBJECT_SET ((sc->element[_MMCAMCORDER_ENCSINK_VENC].gst),"hw-accel", v_hw);*/
+ _mmcamcorder_conf_set_value_element_property(sc->element[_MMCAMCORDER_ENCSINK_VENC].gst, VideoencElement);
+ }
+
+ if (sc->is_slow == FALSE) {
+ if (profile == MM_CAMCORDER_MODE_AUDIO || profile == MM_CAMCORDER_MODE_VIDEO) {
+ /* audio encoder attribute setting */
+ if (a_bitrate > 0) {
+ switch (audio_enc) {
+ case MM_AUDIO_CODEC_AMR:
+ result = __mmcamcorder_get_amrnb_bitrate_mode(a_bitrate);
+
+ _mmcam_dbg_log("Set AMR encoder[%s] mode [%d]", gst_element_aenc_name, result);
+
+ if(!strcmp(gst_element_aenc_name, "ari_amrnbenc")) {
+ MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_ENCSINK_AENC].gst, "mode", result);
+ } else {
+ MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_ENCSINK_AENC].gst, "band-mode", result);
+ }
+ break;
+ case MM_AUDIO_CODEC_AAC:
+ _mmcam_dbg_log("Set AAC encoder[%s] bitrate [%d]", gst_element_aenc_name, a_bitrate);
+ MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_ENCSINK_AENC].gst, "bitrate", a_bitrate);
+ break;
+ default:
+ _mmcam_dbg_log("Audio codec is not AMR or AAC... you need to implement setting function for audio encoder bit-rate");
+ break;
+ }
+ } else {
+ _mmcam_dbg_warn("Setting bitrate is too small, so skip setting. Use DEFAULT value.");
+ }
+ _mmcamcorder_conf_set_value_element_property( sc->element[_MMCAMCORDER_ENCSINK_AENC].gst, AudioencElement );
+ }
+ }
+
+ _mmcam_dbg_log("Element creation complete");
+
+ /* Add element to bin */
+ if (!_mmcamcorder_add_elements_to_bin(GST_BIN(sc->element[_MMCAMCORDER_ENCSINK_BIN].gst), element_list)) {
+ _mmcam_dbg_err("element add error.");
+ err = MM_ERROR_CAMCORDER_RESOURCE_CREATION;
+ goto pipeline_creation_error;
+ }
+
+ _mmcam_dbg_log("Element add complete");
+
+ if (profile == MM_CAMCORDER_MODE_VIDEO) {
+ pad = gst_element_get_request_pad(sc->element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "video");
+ if (gst_element_add_pad(sc->element[_MMCAMCORDER_ENCSINK_BIN].gst, gst_ghost_pad_new("video_sink0", pad)) < 0) {
+ gst_object_unref(pad);
+ pad = NULL;
+ _mmcam_dbg_err("failed to create ghost video_sink0 on _MMCAMCORDER_ENCSINK_BIN.");
+ err = MM_ERROR_CAMCORDER_GST_LINK;
+ goto pipeline_creation_error;
+ }
+ gst_object_unref(pad);
+ pad = NULL;
+
+ if (sc->is_slow == FALSE) {
+ pad = gst_element_get_request_pad(sc->element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "audio");
+ if (gst_element_add_pad(sc->element[_MMCAMCORDER_ENCSINK_BIN].gst, gst_ghost_pad_new("audio_sink0", pad)) < 0) {
+ gst_object_unref(pad);
+ pad = NULL;
+ _mmcam_dbg_err("failed to create ghost audio_sink0 on _MMCAMCORDER_ENCSINK_BIN.");
+ err = MM_ERROR_CAMCORDER_GST_LINK;
+ goto pipeline_creation_error;
+ }
+ gst_object_unref(pad);
+ pad = NULL;
+ }
+ } else if (profile == MM_CAMCORDER_MODE_AUDIO) {
+ pad = gst_element_get_request_pad(sc->element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "audio");
+ if (gst_element_add_pad(sc->element[_MMCAMCORDER_ENCSINK_BIN].gst, gst_ghost_pad_new("audio_sink0", pad)) < 0) {
+ gst_object_unref(pad);
+ pad = NULL;
+ _mmcam_dbg_err("failed to create ghost audio_sink0 on _MMCAMCORDER_ENCSINK_BIN.");
+ err = MM_ERROR_CAMCORDER_GST_LINK;
+ goto pipeline_creation_error;
+ }
+ gst_object_unref(pad);
+ pad = NULL;
+ } else {
+ /* for stillshot */
+ pad = gst_element_get_request_pad(sc->element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "image");
+ if (gst_element_add_pad(sc->element[_MMCAMCORDER_ENCSINK_BIN].gst, gst_ghost_pad_new("image_sink0", pad)) < 0) {
+ gst_object_unref(pad);
+ pad = NULL;
+ _mmcam_dbg_err("failed to create ghost image_sink0 on _MMCAMCORDER_ENCSINK_BIN.");
+ err = MM_ERROR_CAMCORDER_GST_LINK;
+ goto pipeline_creation_error;
+ }
+ gst_object_unref(pad);
+ pad = NULL;
+ }
+
+ _mmcam_dbg_log("Get pad complete");
+
+ /* Link internal element */
+ if (!_mmcamcorder_link_elements(element_list)) {
+ _mmcam_dbg_err("element link error.");
+ err = MM_ERROR_CAMCORDER_GST_LINK;
+ goto pipeline_creation_error;
+ }
+
+ if (element_list) {
+ g_list_free(element_list);
+ element_list = NULL;
+ }
+
+ return MM_ERROR_NONE;
+
+pipeline_creation_error :
+ _MMCAMCORDER_ELEMENT_REMOVE(sc, _MMCAMCORDER_ENCSINK_ENCBIN);
+ _MMCAMCORDER_ELEMENT_REMOVE(sc, _MMCAMCORDER_ENCSINK_VENC);
+ _MMCAMCORDER_ELEMENT_REMOVE(sc, _MMCAMCORDER_ENCSINK_AENC);
+ _MMCAMCORDER_ELEMENT_REMOVE(sc, _MMCAMCORDER_ENCSINK_IENC);
+ _MMCAMCORDER_ELEMENT_REMOVE(sc, _MMCAMCORDER_ENCSINK_MUX);
+ _MMCAMCORDER_ELEMENT_REMOVE(sc, _MMCAMCORDER_ENCSINK_SINK);
+ _MMCAMCORDER_ELEMENT_REMOVE(sc, _MMCAMCORDER_ENCSINK_BIN);
+ if (element_list) {
+ g_list_free(element_list);
+ element_list = NULL;
+ }
+
+ return err;
+}
+
+
+int _mmcamcorder_create_stillshotsink_bin(MMHandleType handle)
+{
+ int err = MM_ERROR_NONE;
+ int capture_width = 0;
+ int capture_height = 0;
+ int UseCaptureMode = 0;
+ char *gst_element_ienc_name = NULL;
+ char *gst_element_videoscale_name = NULL;
+
+ GList *element_list = NULL;
+ GstPad *pad = NULL;
+
+ mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
+ _MMCamcorderSubContext *sc = NULL;
+ _MMCamcorderGstElement *first_element = NULL;
+ type_element* ImageencElement = NULL;
+ type_element* VideoscaleElement = NULL;
+
+ mmf_return_val_if_fail(hcamcorder, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
+
+ sc = MMF_CAMCORDER_SUBCONTEXT(handle);
+ mmf_return_val_if_fail(sc, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
+ mmf_return_val_if_fail(sc->element, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
+
+ _mmcam_dbg_log("");
+
+ /* Check existence */
+ if (sc->element[_MMCAMCORDER_STILLSHOTSINK_BIN].gst) {
+ if (((GObject *)sc->element[_MMCAMCORDER_STILLSHOTSINK_BIN].gst)->ref_count > 0) {
+ gst_object_unref(sc->element[_MMCAMCORDER_STILLSHOTSINK_BIN].gst);
+ }
+ _mmcam_dbg_log("_MMCAMCORDER_STILLSHOTSINK_BIN is Already existed. Unref once...");
+ }
+
+ /* Check element availability */
+ ImageencElement = _mmcamcorder_get_type_element(handle, MM_CAM_IMAGE_ENCODER);
+ if (!ImageencElement) {
+ _mmcam_dbg_err("Fail to get type element");
+ err = MM_ERROR_CAMCORDER_RESOURCE_CREATION;
+ goto pipeline_creation_error;
+ }
+
+ _mmcamcorder_conf_get_value_element_name(ImageencElement, &gst_element_ienc_name);
+
+ _mmcamcorder_conf_get_value_int(hcamcorder->conf_main,
+ CONFIGURE_CATEGORY_MAIN_CAPTURE,
+ "UseCaptureMode",
+ &UseCaptureMode);
+
+ /* Create bin element */
+ __ta__(" stillshotsink_bin",
+ _MMCAMCORDER_BIN_MAKE(sc, _MMCAMCORDER_STILLSHOTSINK_BIN, "stillshotsink_bin", err);
+ );
+
+ /* Create child element */
+ __ta__(" stillshotsink_queue",
+ _MMCAMCORDER_ELEMENT_MAKE(sc, _MMCAMCORDER_STILLSHOTSINK_QUE, "queue", NULL, element_list, err);
+ );
+ __ta__(" stillshotsink_toggle",
+ _MMCAMCORDER_ELEMENT_MAKE(sc, _MMCAMCORDER_STILLSHOTSINK_TOGGLE, "toggle", NULL, element_list, err);
+ );
+
+ if (UseCaptureMode) {
+ _mmcamcorder_conf_get_element(hcamcorder->conf_main,
+ CONFIGURE_CATEGORY_MAIN_CAPTURE,
+ "VideoscaleElement",
+ &VideoscaleElement);
+ _mmcamcorder_conf_get_value_element_name(VideoscaleElement, &gst_element_videoscale_name);
+
+ __ta__(" stillshotsink_videoscale",
+ _MMCAMCORDER_ELEMENT_MAKE(sc, _MMCAMCORDER_STILLSHOTSINK_SCALE, "gst_element_videoscale_name", NULL, element_list, err);
+ );
+ __ta__(" stillshotsink_videocrop",
+ _MMCAMCORDER_ELEMENT_MAKE(sc, _MMCAMCORDER_STILLSHOTSINK_CROP, "videocrop", NULL, element_list, err);
+ );
+ __ta__(" stillshotsink_capsfiltern",
+ _MMCAMCORDER_ELEMENT_MAKE(sc, _MMCAMCORDER_STILLSHOTSINK_FILT, "capsfilter", NULL, element_list, err);
+ );
+ }
+
+ __ta__(" image encoder",
+ _MMCAMCORDER_ELEMENT_MAKE(sc, _MMCAMCORDER_STILLSHOTSINK_ENC, gst_element_ienc_name, NULL, element_list, err);
+ );
+
+ __ta__(" fakesink",
+ _MMCAMCORDER_ELEMENT_MAKE(sc, _MMCAMCORDER_STILLSHOTSINK_SINK, "fakesink", NULL, element_list, err);
+ );
+
+ if (UseCaptureMode) {
+ _mmcamcorder_conf_set_value_element_property(sc->element[_MMCAMCORDER_STILLSHOTSINK_SCALE].gst, VideoscaleElement);
+
+ /* Set property */
+ mm_camcorder_get_attributes(handle, NULL,
+ MMCAM_CAPTURE_WIDTH, &capture_width,
+ MMCAM_CAPTURE_HEIGHT, &capture_height,
+ NULL);
+
+ __ta__(" _mmcamcorder_set_resize_property",
+ err = _mmcamcorder_set_resize_property(handle, capture_width, capture_height);
+ );
+ if (err != MM_ERROR_NONE) {
+ //unref??
+ _mmcam_dbg_log("Set resize property failed.");
+ goto pipeline_creation_error;
+ }
+ }
+
+ if (!_mmcamcorder_add_elements_to_bin(GST_BIN(sc->element[_MMCAMCORDER_STILLSHOTSINK_BIN].gst), element_list)) {
+ _mmcam_dbg_err( "element add error." );
+ err = MM_ERROR_CAMCORDER_RESOURCE_CREATION;
+ goto pipeline_creation_error;
+ }
+
+ if (!_mmcamcorder_link_elements(element_list)) {
+ _mmcam_dbg_err( "element link error." );
+ err = MM_ERROR_CAMCORDER_GST_LINK;
+ goto pipeline_creation_error;
+ }
+
+ first_element = (_MMCamcorderGstElement*)(element_list->data);
+
+ pad = gst_element_get_static_pad(first_element->gst, "sink");
+ if (gst_element_add_pad( sc->element[_MMCAMCORDER_STILLSHOTSINK_BIN].gst, gst_ghost_pad_new("sink", pad)) < 0) {
+ gst_object_unref(pad);
+ pad = NULL;
+ _mmcam_dbg_err("failed to create ghost pad on _MMCAMCORDER_STILLSHOTSINK_BIN.");
+ err = MM_ERROR_CAMCORDER_GST_LINK;
+ goto pipeline_creation_error;
+ }
+ gst_object_unref(pad);
+ pad = NULL;
+
+ if (element_list) {
+ g_list_free(element_list);
+ element_list = NULL;
+ }
+
+ return MM_ERROR_NONE;
+
+pipeline_creation_error :
+ _MMCAMCORDER_ELEMENT_REMOVE(sc, _MMCAMCORDER_STILLSHOTSINK_QUE);
+ _MMCAMCORDER_ELEMENT_REMOVE(sc, _MMCAMCORDER_STILLSHOTSINK_TOGGLE);
+ _MMCAMCORDER_ELEMENT_REMOVE(sc, _MMCAMCORDER_STILLSHOTSINK_CROP);
+ _MMCAMCORDER_ELEMENT_REMOVE(sc, _MMCAMCORDER_STILLSHOTSINK_FILT);
+ _MMCAMCORDER_ELEMENT_REMOVE(sc, _MMCAMCORDER_STILLSHOTSINK_SCALE);
+ _MMCAMCORDER_ELEMENT_REMOVE(sc, _MMCAMCORDER_STILLSHOTSINK_ENC);
+ _MMCAMCORDER_ELEMENT_REMOVE(sc, _MMCAMCORDER_STILLSHOTSINK_SINK);
+ _MMCAMCORDER_ELEMENT_REMOVE(sc, _MMCAMCORDER_STILLSHOTSINK_BIN);
+ if (element_list) {
+ g_list_free(element_list);
+ element_list = NULL;
+ }
+
+ return err;
+}
+
+
+int _mmcamcorder_create_preview_pipeline(MMHandleType handle)
+{
+ int err = MM_ERROR_NONE;
+
+ GstPad *srcpad = NULL;
+ GstPad *sinkpad = NULL;
+ GstBus *bus = 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);
+ mmf_return_val_if_fail(sc, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
+ mmf_return_val_if_fail(sc->element, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
+
+ _mmcam_dbg_log("");
+
+ /** Create gstreamer element **/
+ /* Main pipeline */
+ _MMCAMCORDER_PIPELINE_MAKE(sc, _MMCAMCORDER_MAIN_PIPE, "camcorder_pipeline", err);
+
+ /* Sub pipeline */
+ __ta__(" __mmcamcorder_create_videosrc_bin",
+ err = _mmcamcorder_create_videosrc_bin((MMHandleType)hcamcorder);
+ );
+ if (err != MM_ERROR_NONE ) {
+ goto pipeline_creation_error;
+ }
+
+ __ta__(" _mmcamcorder_create_videosink_bin",
+ err = _mmcamcorder_create_videosink_bin((MMHandleType)hcamcorder);
+ );
+ if (err != MM_ERROR_NONE ) {
+ goto pipeline_creation_error;
+ }
+
+ gst_bin_add_many(GST_BIN(sc->element[_MMCAMCORDER_MAIN_PIPE].gst),
+ sc->element[_MMCAMCORDER_VIDEOSRC_BIN].gst,
+ sc->element[_MMCAMCORDER_VIDEOSINK_BIN].gst,
+ NULL);
+
+ /* Link each element */
+ srcpad = gst_element_get_static_pad(sc->element[_MMCAMCORDER_VIDEOSRC_BIN].gst, "src0");
+ sinkpad = gst_element_get_static_pad(sc->element[_MMCAMCORDER_VIDEOSINK_BIN].gst, "sink");
+ _MM_GST_PAD_LINK_UNREF(srcpad, sinkpad, err, pipeline_creation_error);
+
+ /* Set data probe function */
+ srcpad = gst_element_get_static_pad(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst, "src");
+ MMCAMCORDER_ADD_BUFFER_PROBE(srcpad, _MMCAMCORDER_HANDLER_PREVIEW,
+ __mmcamcorder_video_dataprobe_preview, hcamcorder);
+ gst_object_unref(srcpad);
+ srcpad = NULL;
+
+ if (hcamcorder->type == MM_CAMCORDER_MODE_IMAGE) {
+ sinkpad = gst_element_get_static_pad(sc->element[_MMCAMCORDER_VIDEOSINK_SINK].gst, "sink");
+ MMCAMCORDER_ADD_BUFFER_PROBE(sinkpad, _MMCAMCORDER_HANDLER_PREVIEW,
+ __mmcamcorder_video_dataprobe_vsink, hcamcorder);
+ } else if (hcamcorder->type == MM_CAMCORDER_MODE_VIDEO) {
+ sinkpad = gst_element_get_static_pad(sc->element[_MMCAMCORDER_VIDEOSINK_QUE].gst, "sink");
+ MMCAMCORDER_ADD_BUFFER_PROBE(sinkpad, _MMCAMCORDER_HANDLER_PREVIEW,
+ __mmcamcorder_video_dataprobe_vsink_drop_by_time, hcamcorder);
+ }
+ gst_object_unref(sinkpad);
+ sinkpad = NULL;
+
+ /* Register message callback */
+ bus = gst_pipeline_get_bus(GST_PIPELINE(sc->element[_MMCAMCORDER_MAIN_PIPE].gst));
+ hcamcorder->pipeline_cb_event_id = gst_bus_add_watch(bus, _mmcamcorder_pipeline_cb_message, hcamcorder);
+ 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:
+ _MMCAMCORDER_ELEMENT_REMOVE(sc, _MMCAMCORDER_VIDEOSRC_BIN);
+ _MMCAMCORDER_ELEMENT_REMOVE(sc, _MMCAMCORDER_MAIN_PIPE);
+ return err;
+}
+
+
+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_IMAGE) {
+ _MMCamcorderImageInfo *info = NULL;
+ info = sc->info;
+ if (info->resolution_change == TRUE) {
+ _mmcam_dbg_log("open toggle of stillshot sink.");
+ MMCAMCORDER_G_OBJECT_SET( sc->element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "block", FALSE);
+ info->resolution_change = FALSE;
+ }
+ }
+}
+
+
+int _mmcamcorder_videosink_window_set(MMHandleType handle, type_element* VideosinkElement)
+{
+ int err = MM_ERROR_NONE;
+ int size = 0;
+ int retx = 0;
+ int rety = 0;
+ int retwidth = 0;
+ int retheight = 0;
+ int visible = 0;
+ int rotation = MM_DISPLAY_ROTATION_NONE;
+ int rotation_degree = 0;
+ int display_device = MM_DISPLAY_DEVICE_MAINLCD;
+ int display_mode = 0;
+ int display_geometry_method = MM_DISPLAY_METHOD_LETTER_BOX;
+ int origin_size = 0;
+ int zoom_attr = 0;
+ int zoom_level = 0;
+ int *overlay = NULL;
+ gulong xid;
+ char *err_name = NULL;
+ char *videosink_name = NULL;
+
+ GstElement *vsink = NULL;
+
+ mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
+ _MMCamcorderSubContext *sc = NULL;
+
+ _mmcam_dbg_log("");
+
+ mmf_return_val_if_fail(hcamcorder, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
+
+ sc = MMF_CAMCORDER_SUBCONTEXT(handle);
+ mmf_return_val_if_fail(sc, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
+ mmf_return_val_if_fail(sc->element, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
+ mmf_return_val_if_fail(sc->element[_MMCAMCORDER_VIDEOSINK_SINK].gst, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
+
+ vsink = sc->element[_MMCAMCORDER_VIDEOSINK_SINK].gst;
+
+ /* Get video display information */
+ __ta__(" videosink get attributes",
+ err = mm_camcorder_get_attributes(handle, &err_name,
+ MMCAM_DISPLAY_RECT_X, &retx,
+ MMCAM_DISPLAY_RECT_Y, &rety,
+ MMCAM_DISPLAY_RECT_WIDTH, &retwidth,
+ MMCAM_DISPLAY_RECT_HEIGHT, &retheight,
+ MMCAM_DISPLAY_ROTATION, &rotation,
+ MMCAM_DISPLAY_VISIBLE, &visible,
+ MMCAM_DISPLAY_HANDLE, (void**)&overlay, &size,
+ MMCAM_DISPLAY_DEVICE, &display_device,
+ MMCAM_DISPLAY_GEOMETRY_METHOD, &display_geometry_method,
+ MMCAM_DISPLAY_SCALE, &zoom_attr,
+ NULL);
+ );
+ if (err != MM_ERROR_NONE) {
+ _mmcam_dbg_warn("Get display attrs fail. (%s:%x)", err_name, err);
+ SAFE_FREE(err_name);
+ return err;
+ }
+
+ _mmcam_dbg_log("(overlay=%p, size=%d)", overlay, size);
+
+ _mmcamcorder_conf_get_value_element_name(VideosinkElement, &videosink_name);
+
+ /* Set xid */
+ if (!strcmp(videosink_name, "xvimagesink") || !strcmp(videosink_name, "ximagesink")) {
+ if (overlay) {
+ xid = *overlay;
+ _mmcam_dbg_log("xid = %lu )", xid);
+ gst_x_overlay_set_xwindow_id(GST_X_OVERLAY(vsink), xid);
+ } else {
+ _mmcam_dbg_warn( "Set xid as 0.. but, it's not recommended." );
+ gst_x_overlay_set_xwindow_id(GST_X_OVERLAY(vsink), 0);
+ }
+
+ _mmcam_dbg_log("%s set: display_geometry_method[%d],origin-size[%d],visible[%d],rotate[enum:%d]",
+ videosink_name, display_geometry_method, origin_size, visible, rotation);
+ } else if (!strcmp(videosink_name, "evasimagesink")) {
+ if (overlay) {
+ MMCAMCORDER_G_OBJECT_SET( vsink, "evas-object", overlay );
+ } else {
+ _mmcam_dbg_err("Evas Object pointer is NULL");
+ return MM_ERROR_CAMCORDER_INVALID_ARGUMENT;
+ }
+ } else {
+ _mmcam_dbg_warn("Who are you?? (Videosink: %s)", videosink_name);
+ }
+
+ /* Set attribute */
+ if (!strcmp(videosink_name, "xvimagesink")) {
+ switch (rotation) {
+ case MM_DISPLAY_ROTATION_NONE :
+ rotation_degree = 0;
+ break;
+ case MM_DISPLAY_ROTATION_90 :
+ rotation_degree = 1;
+ break;
+ case MM_DISPLAY_ROTATION_180 :
+ rotation_degree = 2;
+ break;
+ case MM_DISPLAY_ROTATION_270 :
+ rotation_degree = 3;
+ break;
+ default:
+ _mmcam_dbg_warn("Unsupported rotation value. set as default(0).");
+ rotation_degree = 0;
+ break;
+ }
+
+ switch (zoom_attr) {
+ case MM_DISPLAY_SCALE_DEFAULT:
+ zoom_level = 1;
+ break;
+ case MM_DISPLAY_SCALE_DOUBLE_LENGTH:
+ zoom_level = 2;
+ break;
+ case MM_DISPLAY_SCALE_TRIPLE_LENGTH:
+ zoom_level = 3;
+ break;
+ default:
+ _mmcam_dbg_warn("Unsupported zoom value. set as default.");
+ zoom_level = 1;
+ break;
+ }
+
+ switch (display_device) {
+ case MM_DISPLAY_DEVICE_TVOUT:
+ display_mode = 2;
+ break;
+ case MM_DISPLAY_DEVICE_MAINLCD_AND_TVOUT:
+ display_mode = 1;
+ break;
+ case MM_DISPLAY_DEVICE_MAINLCD:
+ case MM_DISPLAY_DEVICE_SUBLCD:
+ case MM_DISPLAY_DEVICE_MAINLCD_AND_SUBLCD:
+ default:
+ display_mode = 3;
+ break;
+ }
+
+ 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, "rotate", rotation_degree);
+ MMCAMCORDER_G_OBJECT_SET(vsink, "zoom", zoom_level);
+
+ if (display_geometry_method == MM_DISPLAY_METHOD_CUSTOM_ROI) {
+ g_object_set(vsink,
+ "dst-roi-x", retx,
+ "dst-roi-y", rety,
+ "dst-roi-w", retwidth,
+ "dst-roi-h", retheight,
+ NULL);
+ }
+ }
+
+ return MM_ERROR_NONE;
+}
+
+
+int _mmcamcorder_vframe_stablize(MMHandleType handle)
+{
+ mmf_camcorder_t *hcamcorder= MMF_CAMCORDER(handle);
+ _MMCamcorderSubContext *sc = NULL;
+
+ _mmcam_dbg_log("%d", _MMCAMCORDER_CAMSTABLE_COUNT);
+
+ mmf_return_val_if_fail(hcamcorder, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
+
+ sc = MMF_CAMCORDER_SUBCONTEXT(handle);
+
+ mmf_return_val_if_fail(sc, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
+
+ if (sc->cam_stability_count != _MMCAMCORDER_CAMSTABLE_COUNT) {
+ sc->cam_stability_count = _MMCAMCORDER_CAMSTABLE_COUNT;
+ }
+
+ return MM_ERROR_NONE;
+}
+
+/* Retreive device information and set them to attributes */
+gboolean _mmcamcorder_get_device_info(MMHandleType handle)
+{
+ mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
+ _MMCamcorderSubContext *sc = NULL;
+ GstCameraControl *control = NULL;
+ GstCameraControlExifInfo exif_info = {0,};
+
+ mmf_return_val_if_fail(hcamcorder, FALSE);
+ sc = MMF_CAMCORDER_SUBCONTEXT(handle);
+
+ if (sc && sc->element) {
+ int err = MM_ERROR_NONE;
+ char *err_name = NULL;
+ double focal_len = 0.0;
+
+ /* Video input device */
+ if (sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst) {
+ /* Exif related information */
+ control = GST_CAMERA_CONTROL(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst);
+ if (control != NULL) {
+ gst_camera_control_get_exif_info(control, &exif_info); //get video input device information
+ focal_len = ((double)exif_info.focal_len_numerator) / ((double) exif_info.focal_len_denominator);
+ } else {
+ _mmcam_dbg_err("Fail to get camera control interface!");
+ focal_len = 0.0;
+ }
+ }
+
+ /* Set values to attributes */
+ err = mm_camcorder_set_attributes(handle, &err_name,
+ MMCAM_CAMERA_FOCAL_LENGTH, focal_len,
+ NULL);
+ if (err != MM_ERROR_NONE) {
+ _mmcam_dbg_err("Set attributes error(%s:%x)!", err_name, err);
+ if (err_name) {
+ free(err_name);
+ err_name = NULL;
+ }
+ return FALSE;
+ }
+ } else {
+ _mmcam_dbg_warn( "Sub context isn't exist.");
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+
+static gboolean __mmcamcorder_video_dataprobe_preview(GstPad *pad, GstBuffer *buffer, gpointer u_data)
+{
+ int current_state = MM_CAMCORDER_STATE_NONE;
+
+ mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(u_data);
+ _MMCamcorderSubContext *sc = NULL;
+ _MMCamcorderKPIMeasure *kpi = NULL;
+
+ mmf_return_val_if_fail(hcamcorder, TRUE);
+
+ sc = MMF_CAMCORDER_SUBCONTEXT(u_data);
+ mmf_return_val_if_fail(sc, TRUE);
+
+ current_state = hcamcorder->state;
+
+ if (sc->drop_vframe > 0) {
+ if (sc->pass_first_vframe > 0) {
+ sc->pass_first_vframe--;
+ _mmcam_dbg_log("Pass video frame by pass_first_vframe");
+ } else {
+ sc->drop_vframe--;
+ _mmcam_dbg_log("Drop video frame by drop_vframe");
+ return FALSE;
+ }
+ } else if (sc->cam_stability_count > 0) {
+ sc->cam_stability_count--;
+ _mmcam_dbg_log("Drop video frame by cam_stability_count");
+ return FALSE;
+ }
+
+ if (current_state >= MM_CAMCORDER_STATE_PREPARE) {
+ int diff_sec;
+ int frame_count = 0;
+ struct timeval current_video_time;
+
+ kpi = &(sc->kpi);
+ if (kpi->init_video_time.tv_sec == kpi->last_video_time.tv_sec &&
+ kpi->init_video_time.tv_usec == kpi->last_video_time.tv_usec &&
+ kpi->init_video_time.tv_usec == 0) {
+ _mmcam_dbg_log("START to measure FPS");
+ gettimeofday(&(kpi->init_video_time), NULL);
+ }
+
+ frame_count = ++(kpi->video_framecount);
+
+ gettimeofday(&current_video_time, NULL);
+ diff_sec = current_video_time.tv_sec - kpi->last_video_time.tv_sec;
+ if (diff_sec != 0) {
+ kpi->current_fps = (frame_count - kpi->last_framecount) / diff_sec;
+ if ((current_video_time.tv_sec - kpi->init_video_time.tv_sec) != 0) {
+ int framecount = kpi->video_framecount;
+ int elased_sec = current_video_time.tv_sec - kpi->init_video_time.tv_sec;
+ kpi->average_fps = framecount / elased_sec;
+ }
+
+ kpi->last_framecount = frame_count;
+ kpi->last_video_time.tv_sec = current_video_time.tv_sec;
+ kpi->last_video_time.tv_usec = current_video_time.tv_usec;
+ /*
+ _mmcam_dbg_log("current fps(%d), average(%d)", kpi->current_fps, kpi->average_fps);
+ */
+ }
+ }
+
+ return TRUE;
+}
+
+
+static gboolean __mmcamcorder_video_dataprobe_vsink(GstPad *pad, GstBuffer *buffer, gpointer u_data)
+{
+ mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(u_data);
+
+ mmf_return_val_if_fail(hcamcorder, FALSE);
+
+ if (buffer == NULL || GST_BUFFER_DATA(buffer) == NULL) {
+ _mmcam_dbg_err("Null buffer!!");
+ return FALSE;
+ }
+
+ if (hcamcorder->vstream_cb && buffer) {
+ GstCaps *caps = NULL;
+ GstStructure *structure = NULL;
+ int state = MM_CAMCORDER_STATE_NULL;
+ unsigned int fourcc = 0;
+ MMCamcorderVideoStreamDataType stream;
+
+ state = _mmcamcorder_get_state((MMHandleType)hcamcorder);
+ if (state < MM_CAMCORDER_STATE_PREPARE) {
+ _mmcam_dbg_warn("Not ready for stream callback");
+ return TRUE;
+ }
+
+ caps = gst_buffer_get_caps(buffer);
+ if (caps == NULL) {
+ _mmcam_dbg_warn( "Caps is NULL." );
+ return TRUE;
+ }
+
+ 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);
+ gst_caps_unref( caps );
+ caps = NULL;
+
+ /*
+ _mmcam_dbg_log( "Call video steramCb, data[%p], Width[%d],Height[%d], Format[%d]",
+ GST_BUFFER_DATA(buffer), stream.width, stream.height, stream.format );
+ */
+
+ if (stream.width == 0 || stream.height == 0) {
+ _mmcam_dbg_warn("Wrong condition!!");
+ return TRUE;
+ }
+
+ stream.data = (void *)GST_BUFFER_DATA(buffer);
+ stream.length = GST_BUFFER_SIZE(buffer);
+ stream.timestamp = (unsigned int)(GST_BUFFER_TIMESTAMP(buffer)/1000000); /* nano sec -> mili sec */
+
+ _MMCAMCORDER_LOCK_VSTREAM_CALLBACK(hcamcorder);
+ if (hcamcorder->vstream_cb) {
+ hcamcorder->vstream_cb(&stream, hcamcorder->vstream_cb_param);
+ }
+ _MMCAMCORDER_UNLOCK_VSTREAM_CALLBACK(hcamcorder);
+ }
+
+ return TRUE;
+}
+
+
+static gboolean __mmcamcorder_video_dataprobe_vsink_drop_by_time(GstPad *pad, GstBuffer *buffer, gpointer u_data)
+{
+ static GstClockTime next_time = 0;
+ static GstClockTime current_time = 0;
+ GstClockTime interval = 30 * GST_MSECOND; //30ms(about 33 fps)
+
+ mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(u_data);
+ _MMCamcorderSubContext *sc = NULL;
+
+ mmf_return_val_if_fail(hcamcorder, TRUE);
+
+ sc = MMF_CAMCORDER_SUBCONTEXT(u_data);
+ mmf_return_val_if_fail(sc, TRUE);
+
+/*
+ _mmcam_dbg_log("VIDEO SRC time stamp : [%" GST_TIME_FORMAT "]", GST_TIME_ARGS(GST_BUFFER_TIMESTAMP(buffer)));
+*/
+
+ /* Call video stream callback */
+ if (__mmcamcorder_video_dataprobe_vsink(pad, buffer, u_data) == FALSE) {
+ _mmcam_dbg_warn( "__mmcamcorder_video_dataprobe_vsink failed." );
+ return FALSE;
+ }
+
+ if (sc->is_slow) {
+ if (GST_BUFFER_TIMESTAMP(buffer) < current_time) {
+ next_time = 0;
+ }
+ current_time = GST_BUFFER_TIMESTAMP(buffer);
+
+ if (current_time >= next_time) {
+ next_time = current_time + interval;
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+ } else {
+ return TRUE;
+ }
+}
+
+
+int __mmcamcorder_get_amrnb_bitrate_mode(int bitrate)
+{
+ int result = MM_CAMCORDER_MR475;
+
+ if (bitrate< 5150) {
+ result = MM_CAMCORDER_MR475; /*AMR475*/
+ } else if (bitrate< 5900) {
+ result = MM_CAMCORDER_MR515; /*AMR515*/
+ } else if (bitrate < 6700) {
+ result = MM_CAMCORDER_MR59; /*AMR59*/
+ } else if (bitrate< 7400) {
+ result = MM_CAMCORDER_MR67; /*AMR67*/
+ } else if (bitrate< 7950) {
+ result = MM_CAMCORDER_MR74; /*AMR74*/
+ } else if (bitrate < 10200) {
+ result = MM_CAMCORDER_MR795; /*AMR795*/
+ } else if (bitrate < 12200) {
+ result = MM_CAMCORDER_MR102; /*AMR102*/
+ } else {
+ result = MM_CAMCORDER_MR122; /*AMR122*/
+ }
+
+ return result;
+}
+
+int _mmcamcorder_get_eos_message(MMHandleType handle)
+{
+ double elapsed = 0.0;
+
+ GstMessage *gMessage = NULL;
+ GstBus *bus = NULL;
+ GstClockTime timeout = 1 * GST_SECOND; /* maximum waiting time */
+ GTimer *timer = 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);
+
+ _mmcam_dbg_log("");
+
+ bus = gst_pipeline_get_bus(GST_PIPELINE(sc->element[_MMCAMCORDER_MAIN_PIPE].gst));
+ timer = g_timer_new();
+
+ if (sc && !(sc->bget_eos)) {
+ while (1) {
+ elapsed = g_timer_elapsed(timer, NULL);
+
+ /*_mmcam_dbg_log("elapsed:%f sec", elapsed);*/
+
+ if (elapsed > _MMCAMCORDER_WAIT_EOS_TIME) {
+ _mmcam_dbg_warn("Timeout. EOS isn't received.");
+ g_timer_destroy(timer);
+ gst_object_unref(bus);
+ return MM_ERROR_CAMCORDER_RESPONSE_TIMEOUT;
+ }
+
+ gMessage = gst_bus_timed_pop (bus, timeout);
+ if (gMessage != NULL) {
+ _mmcam_dbg_log("Get message(%x).", GST_MESSAGE_TYPE(gMessage));
+ _mmcamcorder_pipeline_cb_message(bus, gMessage, (void*)hcamcorder);
+
+ if (GST_MESSAGE_TYPE(gMessage) == GST_MESSAGE_EOS || sc->bget_eos) {
+ gst_message_unref(gMessage);
+ break;
+ }
+ gst_message_unref(gMessage);
+ } else {
+ _mmcam_dbg_log("timeout of gst_bus_timed_pop()");
+ if (sc->bget_eos) {
+ _mmcam_dbg_log("Get EOS in another thread.");
+ break;
+ }
+ }
+ }
+ }
+
+ g_timer_destroy(timer);
+ gst_object_unref(bus);
+
+ _mmcam_dbg_log("END");
+
+ return MM_ERROR_NONE;
+}
+
+
+void _mmcamcorder_remove_element_handle(MMHandleType handle, int first_elem, int last_elem)
+{
+ int i = 0;
+ _MMCamcorderSubContext *sc = NULL;
+
+ mmf_return_if_fail(handle);
+
+ sc = MMF_CAMCORDER_SUBCONTEXT(handle);
+ mmf_return_if_fail(sc);
+ mmf_return_if_fail(sc->element);
+ mmf_return_if_fail((first_elem > 0) && (last_elem > 0) && (last_elem > first_elem));
+
+ _mmcam_dbg_log("");
+
+ for (i = first_elem ; i <= last_elem ; i++) {
+ sc->element[i].gst = NULL;
+ sc->element[i].id = _MMCAMCORDER_NONE;
+ }
+
+ return;
+}
+
+
+int _mmcamcorder_check_audiocodec_fileformat_compatibility(MMHandleType handle)
+{
+ int err = MM_ERROR_NONE;
+ int audio_codec = MM_AUDIO_CODEC_INVALID;
+ int file_format = MM_FILE_FORMAT_INVALID;
+
+ char *err_name = NULL;
+
+ err = mm_camcorder_get_attributes(handle, &err_name,
+ MMCAM_AUDIO_ENCODER, &audio_codec,
+ MMCAM_FILE_FORMAT, &file_format,
+ NULL);
+ if (err != MM_ERROR_NONE) {
+ _mmcam_dbg_warn("Get attrs fail. (%s:%x)", err_name, err);
+ SAFE_FREE(err_name);
+ return err;
+ }
+
+ /* Check compatibility between audio codec and file format */
+ if (audio_codec >= MM_AUDIO_CODEC_INVALID && audio_codec < MM_AUDIO_CODEC_NUM &&
+ file_format >= MM_FILE_FORMAT_INVALID && file_format < MM_FILE_FORMAT_NUM) {
+ if (audiocodec_fileformat_compatibility_table[audio_codec][file_format] == 0) {
+ _mmcam_dbg_err("Audio codec[%d] and file format[%d] compatibility FAILED.",
+ audio_codec, file_format);
+ return MM_ERROR_CAMCORDER_ENCODER_WRONG_TYPE;
+ }
+
+ _mmcam_dbg_log("Audio codec[%d] and file format[%d] compatibility SUCCESS.",
+ audio_codec, file_format);
+ } else {
+ _mmcam_dbg_err("Audio codec[%d] or file format[%d] is INVALID.",
+ audio_codec, file_format);
+ return MM_ERROR_CAMCORDER_ENCODER_WRONG_TYPE;
+ }
+
+ return MM_ERROR_NONE;
+}
+
+
+int _mmcamcorder_check_videocodec_fileformat_compatibility(MMHandleType handle)
+{
+ int err = MM_ERROR_NONE;
+ int video_codec = MM_VIDEO_CODEC_INVALID;
+ int file_format = MM_FILE_FORMAT_INVALID;
+
+ char *err_name = NULL;
+
+ err = mm_camcorder_get_attributes(handle, &err_name,
+ MMCAM_VIDEO_ENCODER, &video_codec,
+ MMCAM_FILE_FORMAT, &file_format,
+ NULL);
+ if (err != MM_ERROR_NONE) {
+ _mmcam_dbg_warn("Get attrs fail. (%s:%x)", err_name, err);
+ SAFE_FREE(err_name);
+ return err;
+ }
+
+ /* Check compatibility between audio codec and file format */
+ if (video_codec >= MM_VIDEO_CODEC_INVALID && video_codec < MM_VIDEO_CODEC_NUM &&
+ file_format >= MM_FILE_FORMAT_INVALID && file_format < MM_FILE_FORMAT_NUM) {
+ if (videocodec_fileformat_compatibility_table[video_codec][file_format] == 0) {
+ _mmcam_dbg_err("Video codec[%d] and file format[%d] compatibility FAILED.",
+ video_codec, file_format);
+ return MM_ERROR_CAMCORDER_ENCODER_WRONG_TYPE;
+ }
+
+ _mmcam_dbg_log("Video codec[%d] and file format[%d] compatibility SUCCESS.",
+ video_codec, file_format);
+ } else {
+ _mmcam_dbg_err("Video codec[%d] or file format[%d] is INVALID.",
+ video_codec, file_format);
+ return MM_ERROR_CAMCORDER_ENCODER_WRONG_TYPE;
+ }
+
+ return MM_ERROR_NONE;
+}
+
+
+bool _mmcamcorder_set_display_rotation(MMHandleType handle, int display_rotate)
+{
+ char* videosink_name = NULL;
+
+ mmf_camcorder_t *hcamcorder = NULL;
+ _MMCamcorderSubContext *sc = NULL;
+
+ hcamcorder = MMF_CAMCORDER(handle);
+ mmf_return_val_if_fail(hcamcorder, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
+
+ sc = MMF_CAMCORDER_SUBCONTEXT(handle);
+ mmf_return_val_if_fail(sc, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
+ mmf_return_val_if_fail(sc->element, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
+
+ if (sc->element[_MMCAMCORDER_VIDEOSINK_SINK].gst) {
+ /* Get videosink name */
+ _mmcamcorder_conf_get_value_element_name(sc->VideosinkElement, &videosink_name);
+ if (!strcmp(videosink_name, "xvimagesink")) {
+ if (display_rotate < MM_DISPLAY_ROTATION_NONE ||
+ display_rotate > MM_DISPLAY_ROTATION_270) {
+ display_rotate = 0;
+ _mmcam_dbg_log( "Rotate: Out of range. set as default(0)...");
+ }
+ MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_SINK].gst,
+ "rotate", display_rotate);
+ _mmcam_dbg_log("Set display-rotate [%d] done.", display_rotate);
+ return TRUE;
+ } else {
+ _mmcam_dbg_warn("videosink[%s] does not support DISPLAY_ROTATION.", videosink_name);
+ return FALSE;
+ }
+ } else {
+ _mmcam_dbg_err("Videosink element is null");
+ return FALSE;
+ }
+}
+
+
+bool _mmcamcorder_set_videosrc_rotation(MMHandleType handle, int videosrc_rotate)
+{
+ int width = 0;
+ int height = 0;
+ int set_width = 0;
+ int set_height = 0;
+ int set_rotate = 0;
+ int fps = 0;
+ int slow_fps = 0;
+ int set_fps = 0;
+ gboolean do_set_caps = FALSE;
+
+ GstCaps *caps = NULL;
+
+ type_int_array *input_index = NULL;
+ mmf_camcorder_t *hcamcorder = NULL;
+ _MMCamcorderSubContext *sc = NULL;
+
+ hcamcorder = MMF_CAMCORDER(handle);
+ mmf_return_val_if_fail(hcamcorder, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
+
+ sc = MMF_CAMCORDER_SUBCONTEXT(handle);
+ mmf_return_val_if_fail(sc, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
+ mmf_return_val_if_fail(sc->element, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
+
+ if (!sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst) {
+ _mmcam_dbg_err("Video src is NULL!");
+ return FALSE;
+ }
+
+ if (!sc->element[_MMCAMCORDER_VIDEOSRC_FILT].gst) {
+ _mmcam_dbg_err("Video filter is NULL!");
+ return FALSE;
+ }
+
+ mm_camcorder_get_attributes(handle, NULL,
+ MMCAM_CAMERA_WIDTH, &width,
+ MMCAM_CAMERA_HEIGHT, &height,
+ MMCAM_CAMERA_FPS, &fps,
+ "camera-slow-motion-fps", &slow_fps,
+ NULL);
+
+ _mmcamcorder_conf_get_value_int_array(hcamcorder->conf_ctrl,
+ CONFIGURE_CATEGORY_CTRL_CAMERA,
+ "InputIndex",
+ &input_index );
+ if (input_index == NULL) {
+ _mmcam_dbg_err("Failed to get input_index");
+ return FALSE;
+ }
+
+ /* Define width, height, rotate and flip in caps */
+ if (input_index->default_value == MM_VIDEO_DEVICE_CAMERA1) {
+ MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst, "vflip", 1);
+ } else {
+ MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst, "vflip", 0);
+ }
+ MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst, "hflip", 0);
+
+ /* This will be applied when rotate is 0, 90, 180, 270 if rear camera.
+ This will be applied when rotate is 0, 180 if front camera. */
+ set_rotate = videosrc_rotate * 90;
+
+ if (videosrc_rotate == MM_VIDEO_INPUT_ROTATION_90 ||
+ videosrc_rotate == MM_VIDEO_INPUT_ROTATION_270) {
+ set_width = height;
+ set_height = width;
+
+ if (input_index->default_value == MM_VIDEO_DEVICE_CAMERA1) {
+ if (videosrc_rotate == MM_VIDEO_INPUT_ROTATION_90) {
+ set_rotate = 270;
+ } else {
+ set_rotate = 90;
+ }
+ }
+ } else {
+ set_width = width;
+ set_height = height;
+
+ if (videosrc_rotate == MM_VIDEO_INPUT_ROTATION_FLIP_HORZ) {
+ set_rotate = 0;
+ MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst, "hflip", 1);
+ } else if (videosrc_rotate == MM_VIDEO_INPUT_ROTATION_FLIP_VERT) {
+ set_rotate = 0;
+ if (input_index->default_value == MM_VIDEO_DEVICE_CAMERA1) {
+ MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst, "vflip", 0);
+ } else {
+ MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst, "vflip", 1);
+ }
+ }
+ }
+
+ set_fps = sc->is_slow ? slow_fps : fps;
+
+ MMCAMCORDER_G_OBJECT_GET(sc->element[_MMCAMCORDER_VIDEOSRC_FILT].gst, "caps", &caps);
+ if (caps) {
+ GstStructure *structure = NULL;
+
+ structure = gst_caps_get_structure(caps, 0);
+ if (structure) {
+ int caps_width = 0;
+ int caps_height = 0;
+ int caps_fps = 0;
+ int caps_rotate = 0;
+
+ gst_structure_get_int(structure, "width", &caps_width);
+ gst_structure_get_int(structure, "height", &caps_height);
+ gst_structure_get_int(structure, "fps", &caps_fps);
+ gst_structure_get_int(structure, "rotate", &caps_rotate);
+ if (set_width == caps_width && set_height == caps_height &&
+ set_rotate == caps_rotate && set_fps == caps_fps) {
+ _mmcam_dbg_log("No need to replace caps.");
+ } else {
+ _mmcam_dbg_log("something is different. set new one...");
+ do_set_caps = TRUE;
+ }
+ } else {
+ _mmcam_dbg_log("can not get structure of caps. set new one...");
+ do_set_caps = TRUE;
+ }
+
+ gst_caps_unref(caps);
+ caps = NULL;
+ } else {
+ _mmcam_dbg_log("No caps. set new one...");
+ do_set_caps = TRUE;
+ }
+
+ if (do_set_caps) {
+ caps = gst_caps_new_simple("video/x-raw-yuv",
+ "format", GST_TYPE_FOURCC, sc->fourcc,
+ "width", G_TYPE_INT, set_width,
+ "height", G_TYPE_INT, set_height,
+ "framerate", GST_TYPE_FRACTION, set_fps, 1,
+ "rotate", G_TYPE_INT, set_rotate,
+ NULL);
+ MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_FILT].gst, "caps", caps);
+ gst_caps_unref(caps);
+ caps = NULL;
+ _mmcam_dbg_log("vidoesrc new caps set. format[%c%c%c%c],width[%d],height[%d],fps[%d],rotate[%d]",
+ (sc->fourcc), (sc->fourcc)>>8, (sc->fourcc)>>16, (sc->fourcc)>>24,
+ set_width, set_height, set_fps, set_rotate);
+ }
+
+ return TRUE;
+}
diff --git a/src/mm_camcorder_internal.c b/src/mm_camcorder_internal.c
new file mode 100644
index 0000000..50528e9
--- /dev/null
+++ b/src/mm_camcorder_internal.c
@@ -0,0 +1,3449 @@
+/*
+ * libmm-camcorder
+ *
+ * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: Jeongmo Yang <jm80.yang@samsung.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+/*=======================================================================================
+| INCLUDE FILES |
+========================================================================================*/
+#include <stdio.h>
+#include <string.h>
+#include <gst/gst.h>
+#include <gst/gstutils.h>
+#include <gst/gstpad.h>
+
+#include <mm_error.h>
+#include "mm_camcorder_internal.h"
+#include <mm_types.h>
+
+#include <gst/interfaces/colorbalance.h>
+#include <gst/interfaces/cameracontrol.h>
+#include <asm/types.h>
+
+#include <mm_session.h>
+#include <mm_session_private.h>
+#include <audio-session-manager.h>
+
+/*---------------------------------------------------------------------------------------
+| GLOBAL VARIABLE DEFINITIONS for internal |
+---------------------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------------------
+| LOCAL VARIABLE DEFINITIONS for internal |
+---------------------------------------------------------------------------------------*/
+
+//#define _MMCAM_USING_CAPTUREMODE
+#define __MMCAMCORDER_CMD_ITERATE_MAX 3
+
+/*---------------------------------------------------------------------------------------
+| LOCAL FUNCTION PROTOTYPES: |
+---------------------------------------------------------------------------------------*/
+/* STATIC INTERNAL FUNCTION */
+static gboolean __mmcamcorder_gstreamer_init(camera_conf * conf);
+
+static gboolean __mmcamcorder_handle_gst_error(MMHandleType handle, GstMessage *message, GError *error);
+static gint __mmcamcorder_gst_handle_stream_error(MMHandleType handle, int code, GstMessage *message);
+static gint __mmcamcorder_gst_handle_resource_error(MMHandleType handle, int code, GstMessage *message);
+static gint __mmcamcorder_gst_handle_library_error(MMHandleType handle, int code, GstMessage *message);
+static gint __mmcamcorder_gst_handle_core_error(MMHandleType handle, int code, GstMessage *message);
+static gint __mmcamcorder_gst_handle_resource_warning(MMHandleType handle, GstMessage *message , GError *error);
+static gboolean __mmcamcorder_handle_gst_warning(MMHandleType handle, GstMessage *message, GError *error);
+
+static int __mmcamcorder_asm_get_event_type(int sessionType);
+static void __mmcamcorder_force_stop(mmf_camcorder_t *hcamcorder);
+static void __mmcamcorder_force_resume(mmf_camcorder_t *hcamcorder);
+ASM_cb_result_t _mmcamcorder_asm_callback(int handle, ASM_event_sources_t event_src,
+ ASM_sound_commands_t command,
+ unsigned int sound_status, void *cb_data);
+
+static gboolean __mmcamcorder_set_attr_to_camsensor_cb(gpointer data);
+
+
+/*=======================================================================================
+| FUNCTION DEFINITIONS |
+=======================================================================================*/
+/*---------------------------------------------------------------------------------------
+| GLOBAL FUNCTION DEFINITIONS: |
+---------------------------------------------------------------------------------------*/
+
+/* Internal command functions {*/
+int _mmcamcorder_create(MMHandleType *handle, MMCamPreset *info)
+{
+ int ret = MM_ERROR_NONE;
+ int UseConfCtrl = 0;
+ int sessionType = MM_SESSION_TYPE_EXCLUSIVE;
+ int errorcode = MM_ERROR_NONE;
+ int rcmd_fmt_capture = MM_PIXEL_FORMAT_YUYV;
+ int rcmd_fmt_recording = MM_PIXEL_FORMAT_NV12;
+ int rcmd_dpy_rotation = MM_DISPLAY_ROTATION_270;
+ char *err_attr_name = NULL;
+ char *ConfCtrlFile = NULL;
+ mmf_camcorder_t *hcamcorder = NULL;
+ ASM_resource_t mm_resource = ASM_RESOURCE_NONE;
+
+ _mmcam_dbg_log("Entered");
+
+ mmf_return_val_if_fail( handle, MM_ERROR_CAMCORDER_INVALID_ARGUMENT );
+
+ /* Create mmf_camcorder_t handle and initialize every variable */
+ hcamcorder = (mmf_camcorder_t *)malloc(sizeof(mmf_camcorder_t));
+ mmf_return_val_if_fail(hcamcorder, MM_ERROR_CAMCORDER_LOW_MEMORY);
+ memset(hcamcorder, 0x00, sizeof(mmf_camcorder_t));
+
+ /* init values */
+ hcamcorder->type=0;
+ hcamcorder->state=MM_CAMCORDER_STATE_NULL;
+ hcamcorder->sub_context=NULL;
+ hcamcorder->target_state=MM_CAMCORDER_STATE_NULL;
+
+ /* 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).state_lock = g_mutex_new();
+ (hcamcorder->mtsafe).gst_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->sound_lock), NULL);
+ pthread_cond_init(&(hcamcorder->sound_cond), NULL);
+
+ /* Sound mutex/cond init */
+ pthread_mutex_init(&(hcamcorder->snd_info.open_mutex), NULL);
+ pthread_cond_init(&(hcamcorder->snd_info.open_cond), NULL);
+
+ if (info->videodev_type < MM_VIDEO_DEVICE_NONE ||
+ info->videodev_type >= MM_VIDEO_DEVICE_NUM) {
+ _mmcam_dbg_err("_mmcamcorder_create::video device type is out of range.");
+ ret = MM_ERROR_CAMCORDER_INVALID_ARGUMENT;
+ goto _ERR_DEFAULT_VALUE_INIT;
+ }
+
+ /* Check and register ASM */
+ if (MM_ERROR_NONE != _mm_session_util_read_type(-1, &sessionType)) {
+ _mmcam_dbg_warn("Read _mm_session_util_read_type failed. use default \"exclusive\" type");
+ sessionType = MM_SESSION_TYPE_EXCLUSIVE;
+ if (MM_ERROR_NONE != mm_session_init(sessionType)) {
+ _mmcam_dbg_err("mm_session_init() failed");
+ ret = MM_ERROR_POLICY_INTERNAL;
+ goto _ERR_DEFAULT_VALUE_INIT;
+ }
+ }
+ if ((sessionType != MM_SESSION_TYPE_CALL) && (sessionType != MM_SESSION_TYPE_VIDEOCALL)) {
+ int asm_session_type = ASM_EVENT_NONE;
+ int asm_handle;
+ int pid = -1; /* process id of itself */
+
+ asm_session_type = __mmcamcorder_asm_get_event_type( sessionType );
+ /* Call will not be interrupted. so does not need callback function */
+ if (!ASM_register_sound(pid, &asm_handle, asm_session_type, ASM_STATE_NONE,
+ (ASM_sound_cb_t)_mmcamcorder_asm_callback,
+ (void*)hcamcorder, mm_resource, &errorcode)) {
+ _mmcam_dbg_err("ASM_register_sound() failed[%x]", errorcode);
+ ret = MM_ERROR_POLICY_INTERNAL;
+ goto _ERR_DEFAULT_VALUE_INIT;
+ }
+ hcamcorder->asm_handle = asm_handle;
+ }
+
+ /* Get Camera Configure information from Camcorder INI file */
+ __ta__( " _mmcamcorder_conf_get_info main",
+ _mmcamcorder_conf_get_info(CONFIGURE_TYPE_MAIN, CONFIGURE_MAIN_FILE, &hcamcorder->conf_main);
+ );
+
+ if (!(hcamcorder->conf_main)) {
+ _mmcam_dbg_err( "Failed to get configure(main) info." );
+
+ ret = MM_ERROR_CAMCORDER_CREATE_CONFIGURE;
+ goto _ERR_AUDIO_BLOCKED;
+ }
+
+ __ta__(" _mmcamcorder_alloc_attribute",
+ hcamcorder->attributes= _mmcamcorder_alloc_attribute((MMHandleType)hcamcorder, info);
+ );
+ if (!(hcamcorder->attributes)) {
+ _mmcam_dbg_err("_mmcamcorder_create::alloc attribute error.");
+
+ ret = MM_ERROR_CAMCORDER_RESOURCE_CREATION;
+ goto _ERR_AUDIO_BLOCKED;
+ }
+
+ if (info->videodev_type != MM_VIDEO_DEVICE_NONE) {
+ _mmcamcorder_conf_get_value_int(hcamcorder->conf_main,
+ CONFIGURE_CATEGORY_MAIN_VIDEO_INPUT,
+ "UseConfCtrl", &UseConfCtrl);
+
+ if (UseConfCtrl) {
+ _mmcam_dbg_log( "Enable Configure Control system." );
+#if 1
+ switch (info->videodev_type) {
+ case MM_VIDEO_DEVICE_CAMERA0:
+ _mmcamcorder_conf_get_value_string(hcamcorder->conf_main,
+ CONFIGURE_CATEGORY_MAIN_VIDEO_INPUT,
+ "ConfCtrlFile0", &ConfCtrlFile);
+ break;
+ case MM_VIDEO_DEVICE_CAMERA1:
+ _mmcamcorder_conf_get_value_string(hcamcorder->conf_main,
+ CONFIGURE_CATEGORY_MAIN_VIDEO_INPUT,
+ "ConfCtrlFile1", &ConfCtrlFile);
+ break;
+ default:
+ _mmcam_dbg_err( "Not supported camera type." );
+ ret = MM_ERROR_CAMCORDER_NOT_SUPPORTED;
+ goto _ERR_ALLOC_ATTRIBUTE;
+ }
+
+ _mmcam_dbg_log("videodev_type : [%d], ConfCtrlPath : [%s]", info->videodev_type, ConfCtrlFile);
+
+ __ta__( " _mmcamcorder_conf_get_info ctrl",
+ _mmcamcorder_conf_get_info(CONFIGURE_TYPE_CTRL, ConfCtrlFile, &hcamcorder->conf_ctrl);
+ );
+/*
+ _mmcamcorder_conf_print_info(&hcamcorder->conf_main);
+ _mmcamcorder_conf_print_info(&hcamcorder->conf_ctrl);
+*/
+#else
+ _mmcamcorder_conf_query_info(CONFIGURE_TYPE_CTRL, info->videodev_type, &hcamcorder->conf_ctrl);
+#endif
+ if (!(hcamcorder->conf_ctrl)) {
+ _mmcam_dbg_err( "Failed to get configure(control) info." );
+ ret = MM_ERROR_CAMCORDER_CREATE_CONFIGURE;
+ goto _ERR_ALLOC_ATTRIBUTE;
+ }
+
+ __ta__( " _mmcamcorder_init_convert_table",
+ ret = _mmcamcorder_init_convert_table((MMHandleType)hcamcorder);
+ );
+ if (ret != MM_ERROR_NONE) {
+ _mmcam_dbg_warn("converting table initialize error!!");
+ }
+
+ __ta__( " _mmcamcorder_init_attr_from_configure",
+ ret = _mmcamcorder_init_attr_from_configure((MMHandleType)hcamcorder);
+ );
+ if (ret != MM_ERROR_NONE) {
+ _mmcam_dbg_warn("converting table initialize error!!");
+ }
+ }
+ else
+ {
+ _mmcam_dbg_log( "Disable Configure Control system." );
+ hcamcorder->conf_ctrl = NULL;
+ }
+ }
+
+ __ta__( " __mmcamcorder_gstreamer_init",
+ ret = __mmcamcorder_gstreamer_init(hcamcorder->conf_main);
+ );
+ if (!ret) {
+ _mmcam_dbg_err( "Failed to initialize gstreamer!!" );
+ ret = MM_ERROR_CAMCORDER_NOT_INITIALIZED;
+ goto _ERR_ALLOC_ATTRIBUTE;
+ }
+
+ /* Get recommend preview format and display rotation from INI */
+ rcmd_fmt_capture = MM_PIXEL_FORMAT_YUYV;
+ rcmd_fmt_recording = MM_PIXEL_FORMAT_NV12;
+ rcmd_dpy_rotation = MM_DISPLAY_ROTATION_270;
+ err_attr_name = NULL;
+
+ _mmcamcorder_conf_get_value_int(hcamcorder->conf_ctrl,
+ CONFIGURE_CATEGORY_CTRL_CAMERA,
+ "RecommendPreviewFormatCapture",
+ &rcmd_fmt_capture);
+
+ _mmcamcorder_conf_get_value_int(hcamcorder->conf_ctrl,
+ CONFIGURE_CATEGORY_CTRL_CAMERA,
+ "RecommendPreviewFormatRecord",
+ &rcmd_fmt_recording);
+
+ _mmcamcorder_conf_get_value_int(hcamcorder->conf_ctrl,
+ CONFIGURE_CATEGORY_CTRL_CAMERA,
+ "RecommendDisplayRotation",
+ &rcmd_dpy_rotation);
+
+ _mmcam_dbg_log("Recommend prv[capture:%d,recording:%d], rot[%d]",
+ rcmd_fmt_capture, rcmd_fmt_recording, rcmd_dpy_rotation);
+
+ ret = mm_camcorder_set_attributes((MMHandleType)hcamcorder, &err_attr_name,
+ MMCAM_RECOMMEND_PREVIEW_FORMAT_FOR_CAPTURE, rcmd_fmt_capture,
+ MMCAM_RECOMMEND_PREVIEW_FORMAT_FOR_RECORDING, rcmd_fmt_recording,
+ MMCAM_RECOMMEND_DISPLAY_ROTATION, rcmd_dpy_rotation,
+ NULL);
+ if (ret != MM_ERROR_NONE) {
+ _mmcam_dbg_err( "Set %s FAILED.", err_attr_name );
+ if (err_attr_name != NULL) {
+ free( err_attr_name );
+ err_attr_name = NULL;
+ }
+
+ goto _ERR_ALLOC_ATTRIBUTE;
+ }
+
+ /* Get UseZeroCopyFormat value from INI */
+ _mmcamcorder_conf_get_value_int(hcamcorder->conf_main,
+ CONFIGURE_CATEGORY_MAIN_VIDEO_INPUT,
+ "UseZeroCopyFormat",
+ &(hcamcorder->use_zero_copy_format));
+ _mmcam_dbg_log("UseZeroCopyFormat : %d", hcamcorder->use_zero_copy_format);
+
+
+ /* Make some attributes as read-only type */
+ __ta__( " _mmcamcorder_lock_readonly_attributes",
+ _mmcamcorder_lock_readonly_attributes((MMHandleType)hcamcorder);
+ );
+
+ /* Disable attributes in each model */
+ __ta__( " _mmcamcorder_set_disabled_attributes",
+ _mmcamcorder_set_disabled_attributes((MMHandleType)hcamcorder);
+ );
+
+ /* Determine state change as sync or async */
+ _mmcamcorder_conf_get_value_int(hcamcorder->conf_main,
+ CONFIGURE_CATEGORY_MAIN_GENERAL,
+ "SyncStateChange",
+ &hcamcorder->sync_state_change );
+ if (!(hcamcorder->sync_state_change)) {
+ _mmcamcorder_create_command_loop((MMHandleType)hcamcorder);
+ }
+
+ /* Set initial state */
+ _mmcamcorder_set_state((MMHandleType)hcamcorder, MM_CAMCORDER_STATE_NULL);
+ _mmcam_dbg_log("_mmcamcorder_set_state");
+
+ *handle = (MMHandleType)hcamcorder;
+
+ return MM_ERROR_NONE;
+
+_ERR_ALLOC_ATTRIBUTE:
+_ERR_AUDIO_BLOCKED:
+ /* unregister audio session manager */
+ {
+ sessionType = MM_SESSION_TYPE_EXCLUSIVE;
+ errorcode = MM_ERROR_NONE;
+ if (MM_ERROR_NONE != _mm_session_util_read_type(-1, &sessionType)) {
+ sessionType = MM_SESSION_TYPE_EXCLUSIVE;
+ }
+
+ if((sessionType != MM_SESSION_TYPE_CALL) && (sessionType != MM_SESSION_TYPE_VIDEOCALL)) {
+ int asm_session_type = __mmcamcorder_asm_get_event_type( sessionType );
+ if (!ASM_unregister_sound(hcamcorder->asm_handle, asm_session_type, &errorcode)) {
+ _mmcam_dbg_err("ASM_unregister_sound() failed(hdl:%p, stype:%d, err:%x)",
+ (void*)hcamcorder->asm_handle, sessionType, errorcode);
+ }
+ }
+ }
+
+_ERR_DEFAULT_VALUE_INIT:
+ g_mutex_free ((hcamcorder->mtsafe).lock);
+ g_cond_free ((hcamcorder->mtsafe).cond);
+ g_mutex_free ((hcamcorder->mtsafe).cmd_lock);
+ g_mutex_free ((hcamcorder->mtsafe).state_lock);
+ g_mutex_free ((hcamcorder->mtsafe).gst_state_lock);
+
+ if (hcamcorder->conf_ctrl) {
+ _mmcamcorder_conf_release_info( &hcamcorder->conf_ctrl );
+ }
+
+ if (hcamcorder->conf_main) {
+ _mmcamcorder_conf_release_info( &hcamcorder->conf_main );
+ }
+
+ return ret;
+}
+
+
+int _mmcamcorder_destroy(MMHandleType handle)
+{
+ int ret = MM_ERROR_NONE;
+ int state = MM_CAMCORDER_STATE_NONE;
+ int state_FROM = MM_CAMCORDER_STATE_NULL;
+ int state_TO = MM_CAMCORDER_STATE_NONE;
+ int asm_session_type = ASM_EVENT_EXCLUSIVE_MMCAMCORDER;
+ int sessionType = MM_SESSION_TYPE_SHARE;
+ int errorcode = MM_ERROR_NONE;
+ mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
+ _MMCamcorderMsgItem msg;
+
+ _mmcam_dbg_log("");
+
+ if (!hcamcorder) {
+ _mmcam_dbg_err("Not initialized");
+ ret = MM_ERROR_CAMCORDER_NOT_INITIALIZED;
+ goto _ERR_CAMCORDER_CMD_PRECON;
+ }
+
+ if (!_MMCAMCORDER_TRYLOCK_CMD(hcamcorder)) {
+ _mmcam_dbg_err("Another command is running.");
+ ret = MM_ERROR_CAMCORDER_CMD_IS_RUNNING;
+ goto _ERR_CAMCORDER_CMD_PRECON;
+ }
+
+ state = _mmcamcorder_get_state(handle);
+ if (state != state_FROM) {
+ _mmcam_dbg_err("Wrong state(%d)", state);
+ ret = MM_ERROR_CAMCORDER_INVALID_STATE;
+ goto _ERR_CAMCORDER_CMD_PRECON_AFTER_LOCK;
+ }
+
+ /* Set async state */
+ ret = _mmcamcorder_set_async_state(handle, state_TO);
+ if (ret < 0) {
+ _mmcam_dbg_err("Can't set async state");
+ goto _ERR_CAMCORDER_CMD_PRECON_AFTER_LOCK;
+ }
+
+ /* Release sound handle */
+ __ta__("_mmcamcorder_sound_finalize",
+ ret = _mmcamcorder_sound_finalize(handle);
+ );
+ _mmcam_dbg_log("sound finalize [%d]", ret);
+
+ /* Release SubContext and pipeline */
+ if (hcamcorder->sub_context) {
+ if (hcamcorder->sub_context->element) {
+ __ta__(" _mmcamcorder_destroy_pipeline",
+ _mmcamcorder_destroy_pipeline(handle, hcamcorder->type);
+ );
+ }
+
+ _mmcamcorder_dealloc_subcontext(hcamcorder->sub_context);
+ hcamcorder->sub_context = NULL;
+ }
+
+ /* Remove idle function which is not called yet */
+ if (hcamcorder->setting_event_id) {
+ _mmcam_dbg_log("Remove remaining idle function");
+ g_source_remove(hcamcorder->setting_event_id);
+ hcamcorder->setting_event_id = 0;
+ }
+
+ /* Remove attributes */
+ if (hcamcorder->attributes) {
+ _mmcamcorder_dealloc_attribute(hcamcorder->attributes);
+ hcamcorder->attributes = 0;
+ }
+
+ /* Remove exif info */
+ if (hcamcorder->exif_info) {
+ mm_exif_destory_exif_info(hcamcorder->exif_info);
+ hcamcorder->exif_info=NULL;
+
+ }
+
+ /* Remove command loop when async state change mode */
+ if (!hcamcorder->sync_state_change) {
+ _mmcamcorder_destroy_command_loop(handle);
+ }
+
+ /* Release configure info */
+ if (hcamcorder->conf_ctrl) {
+ _mmcamcorder_conf_release_info( &hcamcorder->conf_ctrl );
+ }
+ if (hcamcorder->conf_main) {
+ _mmcamcorder_conf_release_info( &hcamcorder->conf_main );
+ }
+
+ /* Remove messages which are not called yet */
+ _mmcamcroder_remove_message_all(handle);
+
+ /* Unregister ASM */
+ if (MM_ERROR_NONE != _mm_session_util_read_type(-1, &sessionType)) {
+ _mmcam_dbg_err("_mm_session_util_read_type Fail");
+ }
+ if ((sessionType != MM_SESSION_TYPE_CALL) && (sessionType != MM_SESSION_TYPE_VIDEOCALL)) {
+ asm_session_type = __mmcamcorder_asm_get_event_type(sessionType);
+ if (!ASM_unregister_sound(hcamcorder->asm_handle, asm_session_type, &errorcode)) {
+ _mmcam_dbg_err("ASM_unregister_sound() failed(hdl:%p, stype:%d, err:%x)",
+ (void*)hcamcorder->asm_handle, sessionType, errorcode);
+ }
+ }
+
+ _MMCAMCORDER_UNLOCK_CMD(hcamcorder);
+
+ /* Release lock, cond */
+ if ((hcamcorder->mtsafe).lock) {
+ g_mutex_free ((hcamcorder->mtsafe).lock);
+ (hcamcorder->mtsafe).lock = NULL;
+ }
+ if ((hcamcorder->mtsafe).cond) {
+ g_cond_free ((hcamcorder->mtsafe).cond);
+ (hcamcorder->mtsafe).cond = NULL;
+ }
+ if ((hcamcorder->mtsafe).cmd_lock) {
+ g_mutex_free ((hcamcorder->mtsafe).cmd_lock);
+ (hcamcorder->mtsafe).cmd_lock = NULL;
+ }
+ if ((hcamcorder->mtsafe).state_lock) {
+ g_mutex_free ((hcamcorder->mtsafe).state_lock);
+ (hcamcorder->mtsafe).state_lock = NULL;
+ }
+ if ((hcamcorder->mtsafe).gst_state_lock) {
+ g_mutex_free ((hcamcorder->mtsafe).gst_state_lock);
+ (hcamcorder->mtsafe).gst_state_lock = NULL;
+ }
+ if ((hcamcorder->mtsafe).message_cb_lock) {
+ g_mutex_free ((hcamcorder->mtsafe).message_cb_lock);
+ (hcamcorder->mtsafe).message_cb_lock = NULL;
+ }
+ if ((hcamcorder->mtsafe).vcapture_cb_lock) {
+ g_mutex_free ((hcamcorder->mtsafe).vcapture_cb_lock);
+ (hcamcorder->mtsafe).vcapture_cb_lock = NULL;
+ }
+ if ((hcamcorder->mtsafe).vstream_cb_lock) {
+ g_mutex_free ((hcamcorder->mtsafe).vstream_cb_lock);
+ (hcamcorder->mtsafe).vstream_cb_lock = NULL;
+ }
+ if ((hcamcorder->mtsafe).astream_cb_lock) {
+ g_mutex_free ((hcamcorder->mtsafe).astream_cb_lock);
+ (hcamcorder->mtsafe).astream_cb_lock = NULL;
+ }
+
+ pthread_mutex_destroy(&(hcamcorder->sound_lock));
+ pthread_cond_destroy(&(hcamcorder->sound_cond));
+ pthread_mutex_destroy(&(hcamcorder->snd_info.open_mutex));
+ pthread_cond_destroy(&(hcamcorder->snd_info.open_cond));
+
+ /* Release handle */
+ memset(hcamcorder, 0x00, sizeof(mmf_camcorder_t));
+ free(hcamcorder);
+
+ return MM_ERROR_NONE;
+
+_ERR_CAMCORDER_CMD_PRECON_AFTER_LOCK:
+ _MMCAMCORDER_UNLOCK_CMD(hcamcorder);
+
+_ERR_CAMCORDER_CMD_PRECON:
+ /*send message*/
+ if (hcamcorder) {
+ _mmcam_dbg_err("Destroy fail (%d, %d)", hcamcorder->type, state);
+ msg.id = MM_MESSAGE_CAMCORDER_STATE_CHANGED;
+ msg.param.state.previous = state;
+ msg.param.state.current = state;
+ msg.param.state.code = ret;
+ _mmcamcroder_send_message(handle, &msg);
+ } else {
+ _mmcam_dbg_err("Destroy fail (%d)", state);
+ }
+
+ return ret;
+}
+
+
+int _mmcamcorder_realize(MMHandleType handle)
+{
+ int ret = MM_ERROR_NONE;
+ int state = MM_CAMCORDER_STATE_NONE;
+ int state_FROM = MM_CAMCORDER_STATE_NULL;
+ int state_TO = MM_CAMCORDER_STATE_READY;
+ int sessionType = MM_SESSION_TYPE_EXCLUSIVE;
+ int errorcode = MM_ERROR_NONE;
+ int display_surface_type = MM_DISPLAY_SURFACE_X;
+ char *videosink_element_type = NULL;
+ char *videosink_name = NULL;
+ _MMCamcorderMsgItem msg;
+ mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
+
+ _mmcam_dbg_log("");
+
+ if (!hcamcorder) {
+ _mmcam_dbg_err("Not initialized");
+ ret = MM_ERROR_CAMCORDER_NOT_INITIALIZED;
+ return ret;
+ }
+
+ /* Check quick-device-close for emergency */
+ if (hcamcorder->quick_device_close) {
+ _mmcam_dbg_err("_mmcamcorder_realize can't be called!!!!");
+ ret = MM_ERROR_CAMCORDER_DEVICE;
+ goto _ERR_CAMCORDER_CMD_PRECON;
+ }
+
+ if (!_MMCAMCORDER_TRYLOCK_CMD(hcamcorder)) {
+ _mmcam_dbg_err("Another command is running.");
+ ret = MM_ERROR_CAMCORDER_CMD_IS_RUNNING;
+ goto _ERR_CAMCORDER_CMD_PRECON;
+ }
+
+ state = _mmcamcorder_get_state(handle);
+ if (state != state_FROM) {
+ _mmcam_dbg_err("Wrong state(%d)", state);
+ ret = MM_ERROR_CAMCORDER_INVALID_STATE;
+ goto _ERR_CAMCORDER_CMD_PRECON_AFTER_LOCK;
+ }
+
+ /* Set async state */
+ ret = _mmcamcorder_set_async_state(handle, state_TO);
+ if (ret < 0) {
+ _mmcam_dbg_err("Can't set async state");
+ goto _ERR_CAMCORDER_CMD_PRECON_AFTER_LOCK;
+ }
+
+ /* Get profile mode */
+ mm_camcorder_get_attributes(handle, NULL, MMCAM_MODE, &hcamcorder->type, NULL);
+ _mmcam_dbg_log("Profile mode set is (%d)", hcamcorder->type);
+
+ /* Check and register ASM */
+ if (MM_ERROR_NONE != _mm_session_util_read_type(-1, &sessionType)) {
+ _mmcam_dbg_warn("Read _mm_session_util_read_type failed. use default \"exclusive\" type");
+ sessionType = MM_SESSION_TYPE_EXCLUSIVE;
+ }
+ if ((sessionType != MM_SESSION_TYPE_CALL) && (sessionType != MM_SESSION_TYPE_VIDEOCALL)) {
+ int asm_session_type = ASM_EVENT_NONE;
+ ASM_resource_t mm_resource = ASM_RESOURCE_NONE;
+
+ asm_session_type = __mmcamcorder_asm_get_event_type(sessionType);
+ switch (hcamcorder->type) {
+ case MM_CAMCORDER_MODE_VIDEO:
+ mm_resource = ASM_RESOURCE_CAMERA | ASM_RESOURCE_VIDEO_OVERLAY | ASM_RESOURCE_HW_ENCODER;
+ break;
+ case MM_CAMCORDER_MODE_AUDIO:
+ mm_resource = ASM_RESOURCE_NONE;
+ break;
+ case MM_CAMCORDER_MODE_IMAGE:
+ default:
+ mm_resource = ASM_RESOURCE_CAMERA | ASM_RESOURCE_VIDEO_OVERLAY;
+ break;
+ }
+
+ if (!ASM_set_sound_state(hcamcorder->asm_handle, asm_session_type,
+ ASM_STATE_PLAYING, mm_resource, &errorcode)) {
+ debug_error("Set state to playing failed 0x%X\n", errorcode);
+ ret = MM_ERROR_POLICY_BLOCKED;
+ goto _ERR_CAMCORDER_CMD_PRECON_AFTER_LOCK;
+ }
+ }
+
+ /* 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;
+ }
+
+ /* Set basic configure information */
+ mm_camcorder_get_attributes(handle, NULL, MMCAM_DISPLAY_SURFACE, &display_surface_type, NULL);
+ switch (display_surface_type) {
+ case MM_DISPLAY_SURFACE_X:
+ videosink_element_type = strdup("VideosinkElementX");
+ break;
+ case MM_DISPLAY_SURFACE_EVAS:
+ videosink_element_type = strdup("VideosinkElementEvas");
+ break;
+ case MM_DISPLAY_SURFACE_GL:
+ videosink_element_type = strdup("VideosinkElementGL");
+ break;
+ case MM_DISPLAY_SURFACE_NULL:
+ videosink_element_type = strdup("VideosinkElementNull");
+ break;
+ default:
+ videosink_element_type = strdup("VideosinkElementX");
+ break;
+ }
+ _mmcamcorder_conf_get_element(hcamcorder->conf_main,
+ CONFIGURE_CATEGORY_MAIN_VIDEO_OUTPUT,
+ videosink_element_type,
+ &hcamcorder->sub_context->VideosinkElement );
+ _mmcamcorder_conf_get_value_element_name( hcamcorder->sub_context->VideosinkElement, &videosink_name );
+ _mmcam_dbg_log( "Videosink name : %s", videosink_name );
+
+ if (videosink_element_type) {
+ free(videosink_element_type);
+ videosink_element_type = NULL;
+ }
+
+ _mmcamcorder_conf_get_value_int(hcamcorder->conf_ctrl,
+ CONFIGURE_CATEGORY_CTRL_CAPTURE,
+ "SensorEncodedCapture",
+ &(hcamcorder->sub_context->SensorEncodedCapture));
+ _mmcam_dbg_log("Support sensor encoded capture : %d", hcamcorder->sub_context->SensorEncodedCapture);
+
+ /* create pipeline */
+ __ta__(" _mmcamcorder_create_pipeline",
+ ret = _mmcamcorder_create_pipeline(handle, hcamcorder->type);
+ );
+ if(ret<0) {
+ _mmcamcorder_dealloc_subcontext(hcamcorder->sub_context);
+ hcamcorder->sub_context = NULL;
+ goto _ERR_CAMCORDER_CMD;
+ }
+
+ /* set command function */
+ ret = _mmcamcorder_set_functions(handle, hcamcorder->type);
+
+ if(ret<0) {
+ _mmcamcorder_destroy_pipeline(handle, hcamcorder->type);
+ _mmcamcorder_dealloc_subcontext(hcamcorder->sub_context);
+ hcamcorder->sub_context = NULL;
+ goto _ERR_CAMCORDER_CMD;
+ }
+
+ _mmcamcorder_set_state(handle, state_TO);
+ _MMCAMCORDER_UNLOCK_CMD(hcamcorder);
+
+ return MM_ERROR_NONE;
+
+_ERR_CAMCORDER_CMD:
+ /* set async state and (set async cancel or set state) are pair. */
+ _mmcamcorder_set_async_cancel(handle);
+
+_ERR_CAMCORDER_CMD_PRECON_AFTER_LOCK:
+ _MMCAMCORDER_UNLOCK_CMD(hcamcorder);
+
+_ERR_CAMCORDER_CMD_PRECON:
+ /* send message */
+ _mmcam_dbg_err("Realize fail (%d, %d, %x)", hcamcorder->type, state, ret);
+
+ msg.id = MM_MESSAGE_CAMCORDER_STATE_CHANGED;
+ msg.param.state.previous = state;
+ msg.param.state.current = state;
+ msg.param.state.code = ret;
+ _mmcamcroder_send_message(handle, &msg);
+
+ return ret;
+}
+
+
+int _mmcamcorder_unrealize(MMHandleType handle)
+{
+ int ret = MM_ERROR_NONE;
+ int state = MM_CAMCORDER_STATE_NONE;
+ int state_FROM = MM_CAMCORDER_STATE_READY;
+ int state_TO = MM_CAMCORDER_STATE_NULL;
+ int sessionType = MM_SESSION_TYPE_SHARE;
+ int asm_session_type = ASM_EVENT_NONE;
+ ASM_resource_t mm_resource = ASM_RESOURCE_NONE;
+ _MMCamcorderMsgItem msg;
+ mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
+
+ _mmcam_dbg_log("");
+
+ if (!hcamcorder) {
+ _mmcam_dbg_err("Not initialized");
+ ret = MM_ERROR_CAMCORDER_NOT_INITIALIZED;
+ return ret;
+ }
+
+ if (!_MMCAMCORDER_TRYLOCK_CMD(hcamcorder)) {
+ _mmcam_dbg_err("Another command is running.");
+ ret = MM_ERROR_CAMCORDER_CMD_IS_RUNNING;
+ goto _ERR_CAMCORDER_CMD_PRECON;
+ }
+
+ state = _mmcamcorder_get_state(handle);
+ if (state != state_FROM) {
+ _mmcam_dbg_err("Wrong state(%d)", state);
+ ret = MM_ERROR_CAMCORDER_INVALID_STATE;
+ goto _ERR_CAMCORDER_CMD_PRECON_AFTER_LOCK;
+ }
+
+ /* set async state */
+ ret = _mmcamcorder_set_async_state(handle, state_TO);
+ if (ret != MM_ERROR_NONE) {
+ _mmcam_dbg_err("Can't set async state");
+ goto _ERR_CAMCORDER_CMD_PRECON_AFTER_LOCK;
+ }
+
+ /* Release sound handle */
+ __ta__("_mmcamcorder_sound_finalize",
+ ret = _mmcamcorder_sound_finalize(handle);
+ );
+ _mmcam_dbg_log("sound finalize [%d]", ret);
+
+ /* Release SubContext */
+ if (hcamcorder->sub_context) {
+ /* destroy pipeline */
+ _mmcamcorder_destroy_pipeline(handle, hcamcorder->type);
+ /* Deallocate SubContext */
+ _mmcamcorder_dealloc_subcontext(hcamcorder->sub_context);
+ hcamcorder->sub_context = NULL;
+ }
+
+ /* Deinitialize main context member */
+
+ hcamcorder->command = NULL;
+
+ if (MM_ERROR_NONE != _mm_session_util_read_type(-1, &sessionType)) {
+ _mmcam_dbg_err("_mm_session_util_read_type Fail\n");
+ }
+
+ if ((sessionType != MM_SESSION_TYPE_CALL) && (sessionType != MM_SESSION_TYPE_VIDEOCALL)) {
+ asm_session_type = ASM_EVENT_NONE;
+ mm_resource = ASM_RESOURCE_NONE;
+ asm_session_type = __mmcamcorder_asm_get_event_type( sessionType );
+
+ switch (hcamcorder->type) {
+ case MM_CAMCORDER_MODE_VIDEO:
+ mm_resource = ASM_RESOURCE_CAMERA | ASM_RESOURCE_VIDEO_OVERLAY | ASM_RESOURCE_HW_ENCODER;
+ break;
+ case MM_CAMCORDER_MODE_AUDIO:
+ mm_resource = ASM_RESOURCE_NONE;
+ break;
+ case MM_CAMCORDER_MODE_IMAGE:
+ default:
+ mm_resource = ASM_RESOURCE_CAMERA | ASM_RESOURCE_VIDEO_OVERLAY;
+ break;
+ }
+
+ /* Call session is not ended here */
+ if (!ASM_set_sound_state(hcamcorder->asm_handle, asm_session_type,
+ ASM_STATE_STOP, mm_resource, &ret)) {
+ _mmcam_dbg_err("Set state to playing failed 0x%X\n", ret);
+ }
+ }
+
+ _mmcamcorder_set_state(handle, state_TO);
+ _MMCAMCORDER_UNLOCK_CMD(hcamcorder);
+
+ return MM_ERROR_NONE;
+
+_ERR_CAMCORDER_CMD_PRECON_AFTER_LOCK:
+ _MMCAMCORDER_UNLOCK_CMD(hcamcorder);
+
+_ERR_CAMCORDER_CMD_PRECON:
+ /* send message */
+ _mmcam_dbg_err("Unrealize fail (%d, %d)", hcamcorder->type, state);
+
+ msg.id = MM_MESSAGE_CAMCORDER_STATE_CHANGED;
+ msg.param.state.previous = state;
+ msg.param.state.current = state;
+ msg.param.state.code = ret;
+ _mmcamcroder_send_message(handle, &msg);
+
+ return ret;
+}
+
+int _mmcamcorder_start(MMHandleType handle)
+{
+ int ret = MM_ERROR_NONE;
+ int state = MM_CAMCORDER_STATE_NONE;
+ int state_FROM = MM_CAMCORDER_STATE_READY;
+ int state_TO =MM_CAMCORDER_STATE_PREPARE;
+ _MMCamcorderMsgItem msg;
+ _MMCamcorderSubContext *sc = NULL;
+ mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
+
+ _mmcam_dbg_log("");
+
+ if (!hcamcorder) {
+ _mmcam_dbg_err("Not initialized");
+ ret = MM_ERROR_CAMCORDER_NOT_INITIALIZED;
+ return ret;
+ }
+
+ sc = MMF_CAMCORDER_SUBCONTEXT(handle);
+ mmf_return_val_if_fail(sc, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
+
+ /* check quick-device-close for emergency */
+ if (hcamcorder->quick_device_close) {
+ _mmcam_dbg_err("_mmcamcorder_start can't be called!!!!");
+ ret = MM_ERROR_CAMCORDER_DEVICE;
+ goto _ERR_CAMCORDER_CMD_PRECON;
+ }
+
+ if (!_MMCAMCORDER_TRYLOCK_CMD(hcamcorder)) {
+ _mmcam_dbg_err("Another command is running.");
+ ret = MM_ERROR_CAMCORDER_CMD_IS_RUNNING;
+ goto _ERR_CAMCORDER_CMD_PRECON;
+ }
+
+ state = _mmcamcorder_get_state(handle);
+ if (state != state_FROM) {
+ _mmcam_dbg_err("Wrong state(%d)", state);
+ ret = MM_ERROR_CAMCORDER_INVALID_STATE;
+ goto _ERR_CAMCORDER_CMD_PRECON_AFTER_LOCK;
+ }
+
+ /* set async state */
+ ret = _mmcamcorder_set_async_state(handle, state_TO);
+ if (ret != MM_ERROR_NONE) {
+ _mmcam_dbg_err("Can't set async state");
+ goto _ERR_CAMCORDER_CMD_PRECON_AFTER_LOCK;
+ }
+
+ ret = hcamcorder->command((MMHandleType)hcamcorder, _MMCamcorder_CMD_PREVIEW_START);
+ if (ret != MM_ERROR_NONE) {
+ goto _ERR_CAMCORDER_CMD;
+ }
+
+ _mmcamcorder_set_state(handle, state_TO);
+
+ if (hcamcorder->type != MM_CAMCORDER_MODE_AUDIO) {
+ _mmcamcorder_set_attribute_to_camsensor(handle);
+ }
+
+ _MMCAMCORDER_UNLOCK_CMD(hcamcorder);
+
+ return MM_ERROR_NONE;
+
+_ERR_CAMCORDER_CMD:
+ /* set async state and (set async cancel or set state) are pair. */
+ _mmcamcorder_set_async_cancel(handle);
+
+_ERR_CAMCORDER_CMD_PRECON_AFTER_LOCK:
+ _MMCAMCORDER_UNLOCK_CMD(hcamcorder);
+
+_ERR_CAMCORDER_CMD_PRECON:
+ /* send message */
+ _mmcam_dbg_err("Start fail (%d, %d)", hcamcorder->type, state);
+
+ msg.id = MM_MESSAGE_CAMCORDER_STATE_CHANGED;
+ msg.param.state.previous = state;
+ msg.param.state.current = state;
+ msg.param.state.code = ret;
+ _mmcamcroder_send_message(handle, &msg);
+
+ return ret;
+}
+
+int _mmcamcorder_stop(MMHandleType handle)
+{
+ int ret = MM_ERROR_NONE;
+ int state = MM_CAMCORDER_STATE_NONE;
+ int state_FROM = MM_CAMCORDER_STATE_PREPARE;
+ int state_TO = MM_CAMCORDER_STATE_READY;
+ int frame_rate = 0;
+ _MMCamcorderMsgItem msg;
+ mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
+
+ _mmcam_dbg_log("");
+
+ if (!hcamcorder) {
+ _mmcam_dbg_err("Not initialized");
+ ret = MM_ERROR_CAMCORDER_NOT_INITIALIZED;
+ return ret;
+ }
+
+ if (!_MMCAMCORDER_TRYLOCK_CMD(hcamcorder)) {
+ _mmcam_dbg_err("Another command is running.");
+ ret = MM_ERROR_CAMCORDER_CMD_IS_RUNNING;
+ goto _ERR_CAMCORDER_CMD_PRECON;
+ }
+
+ state = _mmcamcorder_get_state(handle);
+ if (state != state_FROM) {
+ _mmcam_dbg_err("Wrong state(%d)", state);
+ ret = MM_ERROR_CAMCORDER_INVALID_STATE;
+ goto _ERR_CAMCORDER_CMD_PRECON_AFTER_LOCK;
+ }
+
+ /* set async state */
+ ret = _mmcamcorder_set_async_state(handle, state_TO);
+ if (ret != MM_ERROR_NONE) {
+ _mmcam_dbg_err("Can't set async state");
+ goto _ERR_CAMCORDER_CMD_PRECON_AFTER_LOCK;
+ }
+
+ ret = hcamcorder->command((MMHandleType)hcamcorder, _MMCamcorder_CMD_PREVIEW_STOP);
+ if (ret != MM_ERROR_NONE) {
+ goto _ERR_CAMCORDER_CMD;
+ }
+
+ /* KPI : frame rate */
+ frame_rate=_mmcamcorder_video_average_framerate(handle);
+ __ta__(__tafmt__("MM_CAM_006:: Frame per sec : %d", frame_rate), ;);
+
+ _mmcamcorder_set_state(handle, state_TO);
+ _MMCAMCORDER_UNLOCK_CMD(hcamcorder);
+
+ return MM_ERROR_NONE;
+
+_ERR_CAMCORDER_CMD:
+ /* set async state and (set async cancel or set state) are pair. */
+ _mmcamcorder_set_async_cancel(handle);
+
+_ERR_CAMCORDER_CMD_PRECON_AFTER_LOCK:
+ _MMCAMCORDER_UNLOCK_CMD(hcamcorder);
+
+_ERR_CAMCORDER_CMD_PRECON:
+ /* send message */
+ _mmcam_dbg_err("Stop fail (%d, %d)", hcamcorder->type, state);
+
+ msg.id = MM_MESSAGE_CAMCORDER_STATE_CHANGED;
+ msg.param.state.previous = state;
+ msg.param.state.current = state;
+ msg.param.state.code = ret;
+ _mmcamcroder_send_message(handle, &msg);
+
+ return ret;
+}
+
+
+int _mmcamcorder_capture_start(MMHandleType handle)
+{
+ int ret = MM_ERROR_NONE;
+ int state = MM_CAMCORDER_STATE_NONE;
+ int state_FROM = MM_CAMCORDER_STATE_PREPARE;
+ int state_TO = MM_CAMCORDER_STATE_CAPTURING;
+ char *err_name = NULL;
+
+ _MMCamcorderMsgItem msg;
+ mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
+
+ _mmcam_dbg_log("");
+
+ if (!hcamcorder) {
+ _mmcam_dbg_err("Not initialized");
+ ret = MM_ERROR_CAMCORDER_NOT_INITIALIZED;
+ return ret;
+ }
+
+ if (!_MMCAMCORDER_TRYLOCK_CMD(hcamcorder)) {
+ _mmcam_dbg_err("Another command is running.");
+ ret = MM_ERROR_CAMCORDER_CMD_IS_RUNNING;
+ goto _ERR_CAMCORDER_CMD_PRECON;
+ }
+
+ state = _mmcamcorder_get_state(handle);
+ if (state != state_FROM) {
+ _mmcam_dbg_err("Wrong state(%d)", state);
+ ret = MM_ERROR_CAMCORDER_INVALID_STATE;
+ goto _ERR_CAMCORDER_CMD_PRECON_AFTER_LOCK;
+ }
+
+ /* set async state */
+ ret = _mmcamcorder_set_async_state(handle, state_TO);
+ if (ret != MM_ERROR_NONE) {
+ _mmcam_dbg_err("Can't set async state");
+ goto _ERR_CAMCORDER_CMD_PRECON_AFTER_LOCK;
+ }
+
+ ret = hcamcorder->command((MMHandleType)hcamcorder, _MMCamcorder_CMD_CAPTURE);
+ if (ret != MM_ERROR_NONE) {
+ goto _ERR_CAMCORDER_CMD;
+ }
+
+ _mmcamcorder_set_state(handle, state_TO);
+
+ /* Init break continuous shot attr */
+ mm_camcorder_set_attributes(handle, &err_name, "capture-break-cont-shot", 0, NULL);
+
+ _MMCAMCORDER_UNLOCK_CMD(hcamcorder);
+
+ return MM_ERROR_NONE;
+
+_ERR_CAMCORDER_CMD:
+ /* set async state and (set async cancel or set state) are pair. */
+ _mmcamcorder_set_async_cancel(handle);
+
+_ERR_CAMCORDER_CMD_PRECON_AFTER_LOCK:
+ _MMCAMCORDER_UNLOCK_CMD(hcamcorder);
+
+_ERR_CAMCORDER_CMD_PRECON:
+ /* send message */
+ _mmcam_dbg_err("Capture start fail (%d, %d)", hcamcorder->type, state);
+
+ msg.id = MM_MESSAGE_CAMCORDER_STATE_CHANGED;
+ msg.param.state.previous = state;
+ msg.param.state.current = state;
+ msg.param.state.code = ret;
+ _mmcamcroder_send_message(handle, &msg);
+
+ return ret;
+}
+
+int _mmcamcorder_capture_stop(MMHandleType handle)
+{
+ int ret = MM_ERROR_NONE;
+ int state = MM_CAMCORDER_STATE_NONE;
+ int state_FROM = MM_CAMCORDER_STATE_CAPTURING;
+ int state_TO = MM_CAMCORDER_STATE_PREPARE;
+ _MMCamcorderMsgItem msg;
+ mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
+
+ _mmcam_dbg_log("");
+
+ if (!hcamcorder) {
+ _mmcam_dbg_err("Not initialized");
+ ret = MM_ERROR_CAMCORDER_NOT_INITIALIZED;
+ return ret;
+ }
+
+ if (!_MMCAMCORDER_TRYLOCK_CMD(hcamcorder)) {
+ _mmcam_dbg_err("Another command is running.");
+ ret = MM_ERROR_CAMCORDER_CMD_IS_RUNNING;
+ goto _ERR_CAMCORDER_CMD_PRECON;
+ }
+
+ state = _mmcamcorder_get_state(handle);
+ if (state != state_FROM) {
+ _mmcam_dbg_err("Wrong state(%d)", state);
+ ret = MM_ERROR_CAMCORDER_INVALID_STATE;
+ goto _ERR_CAMCORDER_CMD_PRECON_AFTER_LOCK;
+ }
+
+ /* set async state */
+ ret = _mmcamcorder_set_async_state(handle, state_TO);
+ if (ret != MM_ERROR_NONE) {
+ _mmcam_dbg_err("Can't set async state");
+ goto _ERR_CAMCORDER_CMD_PRECON_AFTER_LOCK;
+ }
+
+ ret = hcamcorder->command((MMHandleType)hcamcorder, _MMCamcorder_CMD_PREVIEW_START);
+ if (ret != MM_ERROR_NONE) {
+ goto _ERR_CAMCORDER_CMD;
+ }
+
+ _mmcamcorder_set_state(handle, state_TO);
+
+ /* Set strobe mode - strobe mode can not be set to driver while captuing */
+{
+ __ta__("Set strobe mode after capture",
+ mmf_attrs_t *attr = (mmf_attrs_t *)MMF_CAMCORDER_ATTRS(handle);
+ if (attr) {
+ mmf_attribute_set_modified(&(attr->items[MM_CAM_STROBE_MODE]));
+ if (mmf_attrs_commit((MMHandleType) attr) == -1) {
+ _mmcam_dbg_warn("Failed to set strobe mode");
+ }
+ }
+ );
+}
+
+ _MMCAMCORDER_UNLOCK_CMD(hcamcorder);
+
+ return MM_ERROR_NONE;
+
+_ERR_CAMCORDER_CMD:
+ /* set async state and (set async cancel or set state) are pair. */
+ _mmcamcorder_set_async_cancel(handle);
+
+_ERR_CAMCORDER_CMD_PRECON_AFTER_LOCK:
+ _MMCAMCORDER_UNLOCK_CMD(hcamcorder);
+
+_ERR_CAMCORDER_CMD_PRECON:
+ /* send message */
+ _mmcam_dbg_err("Capture stop fail (%d, %d)", hcamcorder->type, state);
+
+ msg.id = MM_MESSAGE_CAMCORDER_STATE_CHANGED;
+ msg.param.state.previous = state;
+ msg.param.state.current = state;
+ msg.param.state.code = ret;
+ _mmcamcroder_send_message(handle, &msg);
+
+ return ret;
+}
+
+int _mmcamcorder_record(MMHandleType handle)
+{
+ int ret = MM_ERROR_NONE;
+ int state = MM_CAMCORDER_STATE_NONE;
+ int state_FROM1 = MM_CAMCORDER_STATE_PREPARE;
+ int state_FROM2 = MM_CAMCORDER_STATE_PAUSED;
+ int state_TO = MM_CAMCORDER_STATE_RECORDING;
+ _MMCamcorderMsgItem msg;
+ mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
+
+ _mmcam_dbg_log("");
+
+ if (!hcamcorder) {
+ _mmcam_dbg_err("Not initialized");
+ ret = MM_ERROR_CAMCORDER_NOT_INITIALIZED;
+ return ret;
+ }
+
+ if (!_MMCAMCORDER_TRYLOCK_CMD(hcamcorder)) {
+ _mmcam_dbg_err("Another command is running.");
+ ret = MM_ERROR_CAMCORDER_CMD_IS_RUNNING;
+ goto _ERR_CAMCORDER_CMD_PRECON;
+ }
+
+ state = _mmcamcorder_get_state(handle);
+ if (state != state_FROM1 && state != state_FROM2) {
+ _mmcam_dbg_err("Wrong state(%d)", state);
+ ret = MM_ERROR_CAMCORDER_INVALID_STATE;
+ goto _ERR_CAMCORDER_CMD_PRECON_AFTER_LOCK;
+ }
+
+ /* set async state */
+ ret = _mmcamcorder_set_async_state(handle, state_TO);
+ if (ret != MM_ERROR_NONE) {
+ _mmcam_dbg_err("Can't set async state");
+ goto _ERR_CAMCORDER_CMD_PRECON_AFTER_LOCK;
+ }
+
+ ret = hcamcorder->command((MMHandleType)hcamcorder, _MMCamcorder_CMD_RECORD);
+ if (ret != MM_ERROR_NONE) {
+ goto _ERR_CAMCORDER_CMD;
+ }
+
+ _mmcamcorder_set_state(handle, state_TO);
+ _MMCAMCORDER_UNLOCK_CMD(hcamcorder);
+
+ return MM_ERROR_NONE;
+
+_ERR_CAMCORDER_CMD:
+ /* set async state and (set async cancel or set state) are pair. */
+ _mmcamcorder_set_async_cancel(handle);
+
+_ERR_CAMCORDER_CMD_PRECON_AFTER_LOCK:
+ _MMCAMCORDER_UNLOCK_CMD(hcamcorder);
+
+_ERR_CAMCORDER_CMD_PRECON:
+ /* send message */
+ _mmcam_dbg_err("Record fail (%d, %d)", hcamcorder->type, state);
+
+ msg.id = MM_MESSAGE_CAMCORDER_STATE_CHANGED;
+ msg.param.state.previous = state;
+ msg.param.state.current = state;
+ msg.param.state.code = ret;
+ _mmcamcroder_send_message(handle, &msg);
+
+ return ret;
+}
+
+
+int _mmcamcorder_pause(MMHandleType handle)
+{
+ int ret = MM_ERROR_NONE;
+ int state = MM_CAMCORDER_STATE_NONE;
+ int state_FROM = MM_CAMCORDER_STATE_RECORDING;
+ int state_TO = MM_CAMCORDER_STATE_PAUSED;
+ _MMCamcorderMsgItem msg;
+ mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
+
+ _mmcam_dbg_log("");
+
+ if (!hcamcorder) {
+ _mmcam_dbg_err("Not initialized");
+ ret = MM_ERROR_CAMCORDER_NOT_INITIALIZED;
+ return ret;
+ }
+
+ if (!_MMCAMCORDER_TRYLOCK_CMD(hcamcorder)) {
+ _mmcam_dbg_err("Another command is running.");
+ ret = MM_ERROR_CAMCORDER_CMD_IS_RUNNING;
+ goto _ERR_CAMCORDER_CMD_PRECON;
+ }
+
+ state = _mmcamcorder_get_state(handle);
+ if (state != state_FROM) {
+ _mmcam_dbg_err("Wrong state(%d)", state);
+ ret = MM_ERROR_CAMCORDER_INVALID_STATE;
+ goto _ERR_CAMCORDER_CMD_PRECON_AFTER_LOCK;
+ }
+
+ /* set async state */
+ ret = _mmcamcorder_set_async_state(handle, state_TO);
+ if (ret != MM_ERROR_NONE) {
+ _mmcam_dbg_err("Can't set async state");
+ goto _ERR_CAMCORDER_CMD_PRECON_AFTER_LOCK;
+ }
+
+ ret = hcamcorder->command((MMHandleType)hcamcorder, _MMCamcorder_CMD_PAUSE);
+ if (ret != MM_ERROR_NONE) {
+ goto _ERR_CAMCORDER_CMD;
+ }
+
+ _mmcamcorder_set_state(handle, state_TO);
+ _MMCAMCORDER_UNLOCK_CMD(hcamcorder);
+
+ return MM_ERROR_NONE;
+
+_ERR_CAMCORDER_CMD:
+ /* set async state and (set async cancel or set state) are pair. */
+ _mmcamcorder_set_async_cancel(handle);
+
+_ERR_CAMCORDER_CMD_PRECON_AFTER_LOCK:
+ _MMCAMCORDER_UNLOCK_CMD(hcamcorder);
+
+_ERR_CAMCORDER_CMD_PRECON:
+ /* send message */
+ _mmcam_dbg_err("Pause fail (%d, %d)", hcamcorder->type, state);
+
+ msg.id = MM_MESSAGE_CAMCORDER_STATE_CHANGED;
+ msg.param.state.previous = state;
+ msg.param.state.current = state;
+ msg.param.state.code = ret;
+ _mmcamcroder_send_message(handle, &msg);
+
+ return ret;
+}
+
+
+int _mmcamcorder_commit(MMHandleType handle)
+{
+ int ret = MM_ERROR_NONE;
+ int state = MM_CAMCORDER_STATE_NONE;
+ int state_FROM1 = MM_CAMCORDER_STATE_RECORDING;
+ int state_FROM2 = MM_CAMCORDER_STATE_PAUSED;
+ int state_TO = MM_CAMCORDER_STATE_PREPARE;
+ _MMCamcorderMsgItem msg;
+ mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
+
+ _mmcam_dbg_log("");
+
+ if (!hcamcorder) {
+ _mmcam_dbg_err("Not initialized");
+ ret = MM_ERROR_CAMCORDER_NOT_INITIALIZED;
+ return ret;
+ }
+
+ if (!_MMCAMCORDER_TRYLOCK_CMD(hcamcorder)) {
+ _mmcam_dbg_err("Another command is running.");
+ ret = MM_ERROR_CAMCORDER_CMD_IS_RUNNING;
+ goto _ERR_CAMCORDER_CMD_PRECON;
+ }
+
+ state = _mmcamcorder_get_state(handle);
+ if (state != state_FROM1 && state != state_FROM2) {
+ _mmcam_dbg_err("Wrong state(%d)", state);
+ ret = MM_ERROR_CAMCORDER_INVALID_STATE;
+ goto _ERR_CAMCORDER_CMD_PRECON_AFTER_LOCK;
+ }
+
+ /* set async state */
+ ret = _mmcamcorder_set_async_state(handle, state_TO);
+ if (ret != MM_ERROR_NONE) {
+ _mmcam_dbg_err("Can't set async state");
+ goto _ERR_CAMCORDER_CMD_PRECON_AFTER_LOCK;
+ }
+
+ ret = hcamcorder->command((MMHandleType)hcamcorder, _MMCamcorder_CMD_COMMIT);
+ if (ret != MM_ERROR_NONE) {
+ goto _ERR_CAMCORDER_CMD;
+ }
+
+ _mmcamcorder_set_state(handle,state_TO);
+ _MMCAMCORDER_UNLOCK_CMD(hcamcorder);
+
+ return MM_ERROR_NONE;
+
+_ERR_CAMCORDER_CMD:
+ /* set async state and (set async cancel or set state) are pair. */
+ _mmcamcorder_set_async_cancel(handle);
+
+_ERR_CAMCORDER_CMD_PRECON_AFTER_LOCK:
+ _MMCAMCORDER_UNLOCK_CMD(hcamcorder);
+
+_ERR_CAMCORDER_CMD_PRECON:
+ /* send message */
+ _mmcam_dbg_err("Commit fail (%d, %d)", hcamcorder->type, state);
+
+ msg.id = MM_MESSAGE_CAMCORDER_STATE_CHANGED;
+ msg.param.state.previous = state;
+ msg.param.state.current = state;
+ msg.param.state.code = ret;
+ _mmcamcroder_send_message(handle, &msg);
+
+ return ret;
+}
+
+
+int _mmcamcorder_cancel(MMHandleType handle)
+{
+ int ret = MM_ERROR_NONE;
+ int state = MM_CAMCORDER_STATE_NONE;
+ int state_FROM1 = MM_CAMCORDER_STATE_RECORDING;
+ int state_FROM2 = MM_CAMCORDER_STATE_PAUSED;
+ int state_TO = MM_CAMCORDER_STATE_PREPARE;
+ _MMCamcorderMsgItem msg;
+ mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
+
+ _mmcam_dbg_log("");
+
+ if (!hcamcorder) {
+ _mmcam_dbg_err("Not initialized");
+ ret = MM_ERROR_CAMCORDER_NOT_INITIALIZED;
+ return ret;
+ }
+
+ if (!_MMCAMCORDER_TRYLOCK_CMD(hcamcorder)) {
+ _mmcam_dbg_err("Another command is running.");
+ ret = MM_ERROR_CAMCORDER_CMD_IS_RUNNING;
+ goto _ERR_CAMCORDER_CMD_PRECON;
+ }
+
+ state = _mmcamcorder_get_state(handle);
+ if (state != state_FROM1 && state != state_FROM2) {
+ _mmcam_dbg_err("Wrong state(%d)", state);
+ ret = MM_ERROR_CAMCORDER_INVALID_STATE;
+ goto _ERR_CAMCORDER_CMD_PRECON_AFTER_LOCK;
+ }
+
+ /* set async state */
+ ret = _mmcamcorder_set_async_state(handle, state_TO);
+ if (ret != MM_ERROR_NONE) {
+ _mmcam_dbg_err("Can't set async state");
+ goto _ERR_CAMCORDER_CMD_PRECON_AFTER_LOCK;
+ }
+
+ ret = hcamcorder->command((MMHandleType)hcamcorder, _MMCamcorder_CMD_CANCEL);
+ if (ret != MM_ERROR_NONE) {
+ goto _ERR_CAMCORDER_CMD;
+ }
+
+ _mmcamcorder_set_state(handle, state_TO);
+ _MMCAMCORDER_UNLOCK_CMD(hcamcorder);
+
+ return MM_ERROR_NONE;
+
+_ERR_CAMCORDER_CMD:
+ /* set async state and (set async cancel or set state) are pair. */
+ _mmcamcorder_set_async_cancel(handle);
+
+_ERR_CAMCORDER_CMD_PRECON_AFTER_LOCK:
+ _MMCAMCORDER_UNLOCK_CMD(hcamcorder);
+
+_ERR_CAMCORDER_CMD_PRECON:
+ /* send message */
+ _mmcam_dbg_err("Cancel fail (%d, %d)", hcamcorder->type, state);
+
+ msg.id = MM_MESSAGE_CAMCORDER_STATE_CHANGED;
+ msg.param.state.previous = state;
+ msg.param.state.current = state;
+ msg.param.state.code = ret;
+ _mmcamcroder_send_message(handle, &msg);
+
+ return ret;
+}
+/* } Internal command functions */
+
+
+int _mmcamcorder_commit_async_end(MMHandleType handle)
+{
+ _mmcam_dbg_log("");
+
+ _mmcam_dbg_warn("_mmcamcorder_commit_async_end : MM_CAMCORDER_STATE_PREPARE");
+ _mmcamcorder_set_state(handle, MM_CAMCORDER_STATE_PREPARE);
+
+ return MM_ERROR_NONE;
+}
+
+
+int _mmcamcorder_set_message_callback(MMHandleType handle, MMMessageCallback callback, void *user_data)
+{
+ mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
+
+ _mmcam_dbg_log("%p", hcamcorder);
+
+ mmf_return_val_if_fail(hcamcorder, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
+
+ if (callback == NULL) {
+ _mmcam_dbg_warn("Message Callback is disabled, because application sets it to NULL");
+ }
+
+ if (!_MMCAMCORDER_TRYLOCK_MESSAGE_CALLBACK(hcamcorder)) {
+ _mmcam_dbg_warn("Application's message callback is running now");
+ return MM_ERROR_CAMCORDER_INVALID_CONDITION;
+ }
+
+ /* set message callback to message handle */
+ hcamcorder->msg_cb = callback;
+ hcamcorder->msg_cb_param = user_data;
+
+ _MMCAMCORDER_UNLOCK_MESSAGE_CALLBACK(hcamcorder);
+
+ return MM_ERROR_NONE;
+}
+
+
+int _mmcamcorder_set_video_stream_callback(MMHandleType handle, mm_camcorder_video_stream_callback callback, void *user_data)
+{
+ mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
+
+ _mmcam_dbg_log("");
+
+ mmf_return_val_if_fail(hcamcorder, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
+
+ if (callback == NULL) {
+ _mmcam_dbg_warn("Video Stream Callback is disabled, because application sets it to NULL");
+ }
+
+ if (!_MMCAMCORDER_TRYLOCK_VSTREAM_CALLBACK(hcamcorder)) {
+ _mmcam_dbg_warn("Application's video stream callback is running now");
+ return MM_ERROR_CAMCORDER_INVALID_CONDITION;
+ }
+
+ hcamcorder->vstream_cb = callback;
+ hcamcorder->vstream_cb_param = user_data;
+
+ _MMCAMCORDER_UNLOCK_VSTREAM_CALLBACK(hcamcorder);
+
+ return MM_ERROR_NONE;
+}
+
+
+int _mmcamcorder_set_audio_stream_callback(MMHandleType handle, mm_camcorder_audio_stream_callback callback, void *user_data)
+{
+ mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
+
+ _mmcam_dbg_log("");
+
+ mmf_return_val_if_fail(hcamcorder, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
+
+ if (callback == NULL) {
+ _mmcam_dbg_warn("Audio Stream Callback is disabled, because application sets it to NULL");
+ }
+
+ if (!_MMCAMCORDER_TRYLOCK_ASTREAM_CALLBACK(hcamcorder)) {
+ _mmcam_dbg_warn("Application's audio stream callback is running now");
+ return MM_ERROR_CAMCORDER_INVALID_CONDITION;
+ }
+
+ hcamcorder->astream_cb = callback;
+ hcamcorder->astream_cb_param = user_data;
+
+ _MMCAMCORDER_UNLOCK_ASTREAM_CALLBACK(hcamcorder);
+
+ return MM_ERROR_NONE;
+}
+
+
+int _mmcamcorder_set_video_capture_callback(MMHandleType handle, mm_camcorder_video_capture_callback callback, void *user_data)
+{
+ mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
+
+ _mmcam_dbg_log("");
+
+ mmf_return_val_if_fail(hcamcorder, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
+
+ if (callback == NULL) {
+ _mmcam_dbg_warn("Video Capture Callback is disabled, because application sets it to NULLL");
+ }
+
+ if (!_MMCAMCORDER_TRYLOCK_VCAPTURE_CALLBACK(hcamcorder)) {
+ _mmcam_dbg_warn("Application's video capture callback is running now");
+ return MM_ERROR_CAMCORDER_INVALID_CONDITION;
+ }
+
+ hcamcorder->vcapture_cb = callback;
+ hcamcorder->vcapture_cb_param = user_data;
+
+ _MMCAMCORDER_UNLOCK_VCAPTURE_CALLBACK(hcamcorder);
+
+ return MM_ERROR_NONE;
+}
+
+int _mmcamcorder_get_current_state(MMHandleType handle)
+{
+ mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
+
+ _mmcam_dbg_log("");
+
+ mmf_return_val_if_fail(hcamcorder, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
+
+ return _mmcamcorder_get_state(handle);
+}
+
+int _mmcamcorder_init_focusing(MMHandleType handle)
+{
+ int ret = 0;
+ int state = MM_CAMCORDER_STATE_NONE;
+ int focus_mode = MM_CAMCORDER_FOCUS_MODE_NONE;
+ int af_range = MM_CAMCORDER_AUTO_FOCUS_NORMAL;
+ int sensor_focus_mode = 0;
+ int sensor_af_range = 0;
+ mmf_camcorder_t *hcamcorder = NULL;
+ _MMCamcorderSubContext *sc = NULL;
+ mmf_attrs_t *attr = NULL;
+ GstCameraControl *control = NULL;
+
+ _mmcam_dbg_log("");
+
+ hcamcorder = MMF_CAMCORDER(handle);
+ mmf_return_val_if_fail(handle, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
+
+ sc = MMF_CAMCORDER_SUBCONTEXT(hcamcorder);
+ mmf_return_val_if_fail(sc, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
+
+ if (!_MMCAMCORDER_TRYLOCK_CMD(hcamcorder)) {
+ _mmcam_dbg_err("Another command is running.");
+ return MM_ERROR_CAMCORDER_CMD_IS_RUNNING;
+ }
+
+ state = _mmcamcorder_get_state(handle);
+
+ if (state == MM_CAMCORDER_STATE_CAPTURING ||
+ state < MM_CAMCORDER_STATE_PREPARE) {
+ _mmcam_dbg_err( "Not proper state. state[%d]", state );
+ _MMCAMCORDER_UNLOCK_CMD(hcamcorder);
+ return MM_ERROR_CAMCORDER_INVALID_STATE;
+ }
+
+ if (!GST_IS_CAMERA_CONTROL(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst)) {
+ _mmcam_dbg_log("Can't cast Video source into camera control.");
+ _MMCAMCORDER_UNLOCK_CMD(hcamcorder);
+ return MM_ERROR_NONE;
+ }
+ control = GST_CAMERA_CONTROL (sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst);
+
+ ret = gst_camera_control_stop_auto_focus(control);
+ if (!ret) {
+ _mmcam_dbg_err("Auto focusing stop fail.");
+ _MMCAMCORDER_UNLOCK_CMD(hcamcorder);
+ return MM_ERROR_CAMCORDER_DEVICE_IO;
+ }
+
+ /* Initialize lens position */
+ attr = (mmf_attrs_t *)MMF_CAMCORDER_ATTRS(handle);
+ mm_camcorder_get_attributes(handle, NULL,
+ MMCAM_CAMERA_FOCUS_MODE, &focus_mode,
+ MMCAM_CAMERA_AF_SCAN_RANGE, &af_range,
+ NULL);
+ sensor_af_range = _mmcamcorder_convert_msl_to_sensor(MM_CAM_CAMERA_AF_SCAN_RANGE, af_range);
+ sensor_focus_mode = _mmcamcorder_convert_msl_to_sensor(MM_CAM_CAMERA_FOCUS_MODE, focus_mode);
+
+ ret = gst_camera_control_set_focus(control, sensor_focus_mode, sensor_af_range);
+
+ _MMCAMCORDER_UNLOCK_CMD(hcamcorder);
+
+ if (ret) {
+ _mmcam_dbg_log("Lens init success.");
+ return MM_ERROR_NONE;
+ } else {
+ _mmcam_dbg_err("Lens init fail.");
+ return MM_ERROR_CAMCORDER_DEVICE_IO;
+ }
+}
+
+int _mmcamcorder_adjust_focus(MMHandleType handle, int direction)
+{
+ int state;
+ int focus_mode = MM_CAMCORDER_FOCUS_MODE_NONE;
+ int ret = MM_ERROR_UNKNOWN;
+ char *err_attr_name = NULL;
+
+ mmf_return_val_if_fail(handle, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
+ mmf_return_val_if_fail(direction, MM_ERROR_CAMCORDER_INVALID_ARGUMENT);
+
+ _mmcam_dbg_log("");
+
+ state = _mmcamcorder_get_state(handle);
+ if (state == MM_CAMCORDER_STATE_CAPTURING ||
+ state < MM_CAMCORDER_STATE_PREPARE) {
+ _mmcam_dbg_err("Not proper state. state[%d]", state);
+ return MM_ERROR_CAMCORDER_INVALID_STATE;
+ }
+
+ /* TODO : call a auto or manual focus function */
+ ret = mm_camcorder_get_attributes(handle, &err_attr_name,
+ MMCAM_CAMERA_FOCUS_MODE, &focus_mode,
+ NULL);
+ if (ret != MM_ERROR_NONE) {
+ _mmcam_dbg_warn("Get focus-mode fail. (%s:%x)", err_attr_name, ret);
+ SAFE_FREE (err_attr_name);
+ return ret;
+ }
+
+ if (focus_mode == MM_CAMCORDER_FOCUS_MODE_MANUAL) {
+ return _mmcamcorder_adjust_manual_focus(handle, direction);
+ } else if (focus_mode == MM_CAMCORDER_FOCUS_MODE_AUTO ||
+ focus_mode == MM_CAMCORDER_FOCUS_MODE_TOUCH_AUTO ||
+ focus_mode == MM_CAMCORDER_FOCUS_MODE_CONTINUOUS) {
+ return _mmcamcorder_adjust_auto_focus(handle);
+ } else {
+ _mmcam_dbg_err("It doesn't adjust focus. Focusing mode(%d)", focus_mode);
+ return MM_ERROR_CAMCORDER_NOT_SUPPORTED;
+ }
+}
+
+int _mmcamcorder_adjust_manual_focus(MMHandleType handle, int direction)
+{
+ int max_level = 0;
+ int min_level = 0;
+ int cur_level = 0;
+ int focus_level = 0;
+ float unit_level = 0;
+ GstCameraControl *control = NULL;
+ _MMCamcorderSubContext *sc = NULL;
+ mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
+
+ _mmcam_dbg_log("");
+
+ mmf_return_val_if_fail(hcamcorder, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
+ mmf_return_val_if_fail(_MMFCAMCORDER_FOCUS_TOTAL_LEVEL != 1, MM_ERROR_CAMCORDER_NOT_SUPPORTED);
+ mmf_return_val_if_fail((direction >= MM_CAMCORDER_MF_LENS_DIR_FORWARD) &&
+ (direction <= MM_CAMCORDER_MF_LENS_DIR_BACKWARD),
+ MM_ERROR_CAMCORDER_INVALID_ARGUMENT );
+
+ sc = MMF_CAMCORDER_SUBCONTEXT(hcamcorder);
+ mmf_return_val_if_fail(sc, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
+
+ if (!GST_IS_CAMERA_CONTROL(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst)) {
+ _mmcam_dbg_log("Can't cast Video source into camera control.");
+ return MM_ERROR_NONE;
+ }
+ control = GST_CAMERA_CONTROL (sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst);
+
+ /* TODO : get max, min level */
+ if (max_level - min_level + 1 < _MMFCAMCORDER_FOCUS_TOTAL_LEVEL) {
+ _mmcam_dbg_warn("Total level of manual focus of MMF is greater than that of the camera driver.");
+ }
+
+ unit_level = ((float)max_level - (float)min_level)/(float)(_MMFCAMCORDER_FOCUS_TOTAL_LEVEL - 1);
+
+ if (!gst_camera_control_get_focus_level(control, &cur_level)) {
+ _mmcam_dbg_err("Can't get current level of manual focus.");
+ return MM_ERROR_CAMCORDER_DEVICE_IO;
+ }
+
+ //TODO : adjust unit level value
+ if (direction == MM_CAMCORDER_MF_LENS_DIR_FORWARD) {
+ focus_level = cur_level + unit_level;
+ } else if (direction == MM_CAMCORDER_MF_LENS_DIR_BACKWARD) {
+ focus_level = cur_level - unit_level;
+ }
+
+ if (focus_level > max_level) {
+ focus_level = max_level;
+ } else if (focus_level < min_level) {
+ focus_level = min_level;
+ }
+
+ if (!gst_camera_control_set_focus_level(control, focus_level)) {
+ _mmcam_dbg_err("Manual focusing fail.");
+ return MM_ERROR_CAMCORDER_DEVICE_IO;
+ }
+
+ return MM_ERROR_NONE;
+}
+
+
+int _mmcamcorder_adjust_auto_focus(MMHandleType handle)
+{
+ int af_mode = MM_CAMCORDER_FOCUS_MODE_AUTO;
+ gboolean ret;
+ mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
+ GstCameraControl *control = NULL;
+ _MMCamcorderSubContext *sc = NULL;
+
+ mmf_return_val_if_fail(handle, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
+
+ _mmcam_dbg_log("");
+
+ sc = MMF_CAMCORDER_SUBCONTEXT(hcamcorder);
+
+ if (!GST_IS_CAMERA_CONTROL(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst)) {
+ _mmcam_dbg_log("Can't cast Video source into camera control.");
+ return MM_ERROR_NONE;
+ }
+ control = GST_CAMERA_CONTROL (sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst);
+
+ /* Start AF */
+ ret = gst_camera_control_start_auto_focus(control);
+ if (ret) {
+ mm_camcorder_get_attributes(handle, NULL, MMCAM_CAMERA_FOCUS_MODE, &af_mode, NULL);
+ if (af_mode == MM_CAMCORDER_FOCUS_MODE_CONTINUOUS) {
+ sc->now_continuous_af = TRUE;
+ _mmcam_dbg_log("Set now_continuous_af as TRUE");
+ }
+ _mmcam_dbg_log("Auto focusing start success.");
+ return MM_ERROR_NONE;
+ } else {
+ _mmcam_dbg_err("Auto focusing start fail.");
+ return MM_ERROR_CAMCORDER_DEVICE_IO;
+ }
+}
+
+int _mmcamcorder_stop_focusing(MMHandleType handle)
+{
+ mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
+ _MMCamcorderSubContext *sc = NULL;
+
+ int ret, state;
+ GstCameraControl *control = NULL;
+
+ mmf_return_val_if_fail(handle, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
+
+ _mmcam_dbg_log("");
+
+ sc = MMF_CAMCORDER_SUBCONTEXT(hcamcorder);
+
+ if (!_MMCAMCORDER_TRYLOCK_CMD(hcamcorder)) {
+ _mmcam_dbg_err("Another command is running.");
+ return MM_ERROR_CAMCORDER_CMD_IS_RUNNING;
+ }
+
+ state = _mmcamcorder_get_state(handle);
+ if (state == MM_CAMCORDER_STATE_CAPTURING ||
+ state < MM_CAMCORDER_STATE_PREPARE) {
+ _mmcam_dbg_err( "Not proper state. state[%d]", state );
+ _MMCAMCORDER_UNLOCK_CMD(hcamcorder);
+ return MM_ERROR_CAMCORDER_INVALID_STATE;
+ }
+
+ if (!GST_IS_CAMERA_CONTROL(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst)) {
+ _mmcam_dbg_log("Can't cast Video source into camera control.");
+ _MMCAMCORDER_UNLOCK_CMD(hcamcorder);
+ return MM_ERROR_NONE;
+ }
+ control = GST_CAMERA_CONTROL(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst);
+
+ ret = gst_camera_control_stop_auto_focus(control);
+ sc->now_continuous_af = FALSE;
+ _mmcam_dbg_log("Set now_continuous_af as FALSE");
+
+ _MMCAMCORDER_UNLOCK_CMD(hcamcorder);
+
+ if (ret) {
+ _mmcam_dbg_log("Auto focusing stop success.");
+ return MM_ERROR_NONE;
+ } else {
+ _mmcam_dbg_err("Auto focusing stop fail.");
+ return MM_ERROR_CAMCORDER_DEVICE_IO;
+ }
+}
+
+
+/*-----------------------------------------------
+| CAMCORDER INTERNAL LOCAL |
+-----------------------------------------------*/
+static gboolean
+__mmcamcorder_gstreamer_init(camera_conf * conf)
+{
+ static const int max_argc = 10;
+ int i = 0;
+ int cnt_str = 0;
+ gint *argc = NULL;
+ gchar **argv = NULL;
+ GError *err = NULL;
+ gboolean ret = FALSE;
+ type_string_array *GSTInitOption = NULL;
+
+ mmf_return_val_if_fail(conf, FALSE);
+
+ _mmcam_dbg_log("");
+
+ /* alloc */
+ argc = malloc(sizeof(int));
+ argv = malloc(sizeof(gchar *) * max_argc);
+
+ if (!argc || !argv) {
+ goto ERROR;
+ }
+
+ memset(argv, 0, sizeof(gchar *) * max_argc);
+
+ /* add initial */
+ *argc = 1;
+ argv[0] = g_strdup("mmcamcorder");
+
+ /* add gst_param */
+ _mmcamcorder_conf_get_value_string_array(conf,
+ CONFIGURE_CATEGORY_MAIN_GENERAL,
+ "GSTInitOption",
+ &GSTInitOption);
+ if (GSTInitOption != NULL && GSTInitOption->value) {
+ cnt_str = GSTInitOption->count;
+ for( ; *argc < max_argc && *argc <= cnt_str ; (*argc)++ )
+ {
+ argv[*argc] = g_strdup(GSTInitOption->value[(*argc)-1]);
+ }
+ }
+
+ _mmcam_dbg_log("initializing gstreamer with following parameter[argc:%d]", *argc);
+
+ for (i = 0; i < *argc; i++) {
+ _mmcam_dbg_log("argv[%d] : %s", i, argv[i]);
+ }
+
+ /* initializing gstreamer */
+ __ta__(" gst_init_check",
+ ret = gst_init_check (argc, &argv, &err);
+ );
+
+ if (!ret) {
+ _mmcam_dbg_err("Could not initialize GStreamer: %s\n",
+ err ? err->message : "unknown error occurred");
+ if (err) {
+ g_error_free (err);
+ }
+ }
+
+ /* release */
+ for (i = 0; i < *argc; i++) {
+ if (argv[i]) {
+ free(argv[i]);
+ argv[i] = NULL;
+ }
+ }
+
+ if (argv) {
+ free(argv);
+ argv = NULL;
+ }
+
+ if (argc) {
+ free(argc);
+ argc = NULL;
+ }
+
+ return ret;
+
+ERROR:
+ _mmcam_dbg_err("failed to initialize gstreamer");
+
+ if (argv) {
+ free(argv);
+ argv = NULL;
+ }
+
+ if (argc) {
+ free(argc);
+ argc = NULL;
+ }
+
+ return FALSE;
+}
+
+
+int _mmcamcorder_get_state(MMHandleType handle)
+{
+ int state;
+ mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
+
+ mmf_return_val_if_fail(hcamcorder, -1);
+
+ _MMCAMCORDER_LOCK_STATE(handle);
+
+ state = hcamcorder->state;
+ _mmcam_dbg_log("state=%d",state);
+
+ _MMCAMCORDER_UNLOCK_STATE(handle);
+
+ return state;
+}
+
+
+void _mmcamcorder_set_state(MMHandleType handle, int state)
+{
+ int old_state;
+ mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
+ _MMCamcorderMsgItem msg;
+
+ mmf_return_if_fail(hcamcorder);
+
+ _mmcam_dbg_log("");
+
+ _MMCAMCORDER_LOCK_STATE(handle);
+
+ old_state = hcamcorder->state;
+ if(old_state != state) {
+ hcamcorder->state = state;
+ hcamcorder->target_state = state;
+
+ _mmcam_dbg_log("set state[%d] and send state-changed message", state);
+
+ /* To discern who changes the state */
+ switch (hcamcorder->state_change_by_system) {
+ case _MMCAMCORDER_STATE_CHANGE_BY_ASM:
+ msg.id = MM_MESSAGE_CAMCORDER_STATE_CHANGED_BY_ASM;
+ msg.param.state.code = hcamcorder->asm_event_code;
+ break;
+ default:
+ msg.id = MM_MESSAGE_CAMCORDER_STATE_CHANGED;
+ msg.param.state.code = MM_ERROR_NONE;
+ break;
+ }
+
+ 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);
+ }
+
+ _MMCAMCORDER_UNLOCK_STATE(handle);
+
+ return;
+}
+
+
+int _mmcamcorder_get_async_state(MMHandleType handle)
+{
+ int state;
+ mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
+
+ _MMCAMCORDER_LOCK_STATE(handle);
+ state = hcamcorder->target_state;
+
+ _MMCAMCORDER_UNLOCK_STATE(handle);
+
+ return state;
+}
+
+int _mmcamcorder_set_async_state(MMHandleType handle, int target_state)
+{
+ int error = MM_ERROR_NONE;
+ mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
+
+ mmf_return_val_if_fail(hcamcorder, MM_ERROR_CAMCORDER_INVALID_CONDITION);
+
+ _mmcam_dbg_log("");
+
+ if (hcamcorder->sync_state_change) {
+ return error;
+ }
+
+ _MMCAMCORDER_LOCK_STATE(handle);
+
+ /* check changing state */
+ if (hcamcorder->state != hcamcorder->target_state) {
+ _mmcam_dbg_warn("State is changing now.");
+ error = MM_ERROR_CAMCORDER_CMD_IS_RUNNING;
+ goto _SET_ASYNC_END;
+ }
+
+ /* check already set */
+ if (hcamcorder->state == target_state) {
+ _mmcam_dbg_log("Target state already set.");
+ error = MM_ERROR_CAMCORDER_INVALID_STATE;
+ goto _SET_ASYNC_END;
+ }
+
+ hcamcorder->target_state = target_state;
+
+ _mmcam_dbg_log("Done");
+
+_SET_ASYNC_END:
+ _MMCAMCORDER_UNLOCK_STATE(handle);
+ return error;
+}
+
+
+gboolean _mmcamcorder_set_async_cancel(MMHandleType handle)
+{
+ mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
+
+ mmf_return_val_if_fail(hcamcorder, FALSE);
+
+ _mmcam_dbg_log("");
+
+ if (hcamcorder->sync_state_change) {
+ return TRUE;
+ }
+
+ _MMCAMCORDER_LOCK_STATE(handle);
+
+ if (hcamcorder->target_state != hcamcorder->state) {
+ hcamcorder->target_state = hcamcorder->state;
+ _mmcam_dbg_log("Async state change is canceled.");
+ _MMCAMCORDER_UNLOCK_STATE(handle);
+ return TRUE;
+ } else {
+ _mmcam_dbg_log("Nothing to be cancel or Already processed.");
+ }
+
+ _MMCAMCORDER_UNLOCK_STATE(handle);
+
+ return FALSE;
+}
+
+
+gboolean _mmcamcorder_is_state_changing(MMHandleType handle)
+{
+ mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
+
+ mmf_return_val_if_fail(hcamcorder, FALSE);
+
+ _mmcam_dbg_log("(%d)", (hcamcorder->target_state != hcamcorder->state));
+
+ if (hcamcorder->sync_state_change) {
+ return FALSE;
+ }
+
+ _MMCAMCORDER_LOCK_STATE(handle);
+
+ if (hcamcorder->target_state != hcamcorder->state) {
+ _MMCAMCORDER_UNLOCK_STATE(handle);
+ return TRUE;
+ }
+
+ _MMCAMCORDER_UNLOCK_STATE(handle);
+
+ return FALSE;
+}
+
+
+_MMCamcorderSubContext *_mmcamcorder_alloc_subcontext(int type)
+{
+ int i;
+ _MMCamcorderSubContext *sc = NULL;
+
+ _mmcam_dbg_log("");
+
+ /* alloc container */
+ sc = (_MMCamcorderSubContext *)malloc(sizeof(_MMCamcorderSubContext));
+ mmf_return_val_if_fail(sc != NULL, NULL);
+
+ /* init members */
+ memset(sc, 0x00, sizeof(_MMCamcorderSubContext));
+
+ sc->element_num = _MMCamcorder_PIPELINE_ELEMENT_NUM;
+
+ /* alloc info for each mode */
+ switch (type) {
+ case MM_CAMCORDER_MODE_IMAGE:
+ sc->info = malloc( sizeof(_MMCamcorderImageInfo));
+ if(sc->info == NULL) {
+ _mmcam_dbg_err("Failed to alloc info structure");
+ free(sc);
+ return NULL;
+ }
+ memset(sc->info, 0x00, sizeof(_MMCamcorderImageInfo));
+ break;
+ case MM_CAMCORDER_MODE_AUDIO:
+ sc->info = malloc( sizeof(_MMCamcorderAudioInfo));
+ if(sc->info == NULL) {
+ _mmcam_dbg_err("Failed to alloc info structure");
+ free(sc);
+ return NULL;
+ }
+ memset(sc->info, 0x00, sizeof(_MMCamcorderAudioInfo));
+ break;
+ case MM_CAMCORDER_MODE_VIDEO:
+ sc->info = malloc( sizeof(_MMCamcorderVideoInfo));
+ if(sc->info == NULL) {
+ _mmcam_dbg_err("Failed to alloc info structure");
+ free(sc);
+ return NULL;
+ }
+ memset(sc->info, 0x00, sizeof(_MMCamcorderVideoInfo));
+ break;
+ default:
+ _mmcam_dbg_err("unknown type[%d]", type);
+ free(sc);
+ return NULL;
+ }
+
+ /* alloc element array */
+ sc->element = (_MMCamcorderGstElement *)malloc(sizeof(_MMCamcorderGstElement) * sc->element_num);
+ if(!sc->element) {
+ _mmcam_dbg_err("Failed to alloc element structure");
+ free(sc->info);
+ free(sc);
+ return NULL;
+ }
+
+ for (i = 0; i< sc->element_num; i++) {
+ sc->element[i].id = _MMCAMCORDER_NONE;
+ sc->element[i].gst = NULL;
+ }
+
+ sc->fourcc = 0x80000000;
+
+ sc->cam_stability_count = 0;
+ sc->drop_vframe = 0;
+ sc->pass_first_vframe = 0;
+
+ return sc;
+}
+
+
+void _mmcamcorder_dealloc_subcontext(_MMCamcorderSubContext *sc)
+{
+ _mmcam_dbg_log("");
+
+ if (sc) {
+ if (sc->element) {
+ free(sc->element);
+ sc->element = NULL;
+ }
+
+ if (sc->info) {
+ free(sc->info);
+ sc->info = NULL;
+ }
+
+ free(sc);
+ sc = NULL;
+ }
+
+ return;
+}
+
+
+int _mmcamcorder_set_functions(MMHandleType handle, int type)
+{
+ mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
+
+ _mmcam_dbg_log("");
+
+ switch (type) {
+ case MM_CAMCORDER_MODE_VIDEO:
+ hcamcorder->command = _mmcamcorder_video_command;
+ break;
+ case MM_CAMCORDER_MODE_AUDIO:
+ hcamcorder->command = _mmcamcorder_audio_command;
+ break;
+ case MM_CAMCORDER_MODE_IMAGE:
+ hcamcorder->command = _mmcamcorder_image_command;
+ break;
+ default:
+ return MM_ERROR_CAMCORDER_INTERNAL;
+ break;
+ }
+
+ return MM_ERROR_NONE;
+}
+
+
+gboolean _mmcamcorder_pipeline_cb_message(GstBus *bus, GstMessage *message, gpointer data)
+{
+ mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(data);
+ _MMCamcorderMsgItem msg;
+ _MMCamcorderSubContext *sc = NULL;
+
+ mmf_return_val_if_fail(hcamcorder, FALSE);
+ mmf_return_val_if_fail(message, FALSE);
+ //_mmcam_dbg_log("message type=(%d)", GST_MESSAGE_TYPE(message));
+
+ switch (GST_MESSAGE_TYPE(message)) {
+ case GST_MESSAGE_UNKNOWN:
+ _mmcam_dbg_log("GST_MESSAGE_UNKNOWN");
+ break;
+ case GST_MESSAGE_EOS:
+ {
+ _mmcam_dbg_log ("Got EOS from element \"%s\".",
+ GST_STR_NULL(GST_ELEMENT_NAME(GST_MESSAGE_SRC(message))));
+
+ sc = MMF_CAMCORDER_SUBCONTEXT(hcamcorder);
+ mmf_return_val_if_fail(sc, TRUE);
+ mmf_return_val_if_fail(sc->info, TRUE);
+
+ if (hcamcorder->type == MM_CAMCORDER_MODE_VIDEO) {
+ _MMCamcorderVideoInfo *info = sc->info;
+ if (info->b_commiting) {
+ _mmcamcorder_video_handle_eos((MMHandleType)hcamcorder);
+ }
+ } else if (hcamcorder->type == MM_CAMCORDER_MODE_AUDIO) {
+ _MMCamcorderAudioInfo *info = sc->info;
+ if (info->b_commiting) {
+ _mmcamcorder_audio_handle_eos((MMHandleType)hcamcorder);
+ }
+ }
+
+ sc->bget_eos = TRUE;
+
+ break;
+ }
+ case GST_MESSAGE_ERROR:
+ {
+ GError *err;
+ gchar *debug;
+ gst_message_parse_error(message, &err, &debug);
+
+ _mmcam_dbg_err ("GSTERR: %s", err->message);
+ _mmcam_dbg_err ("Error Debug: %s", debug);
+
+ __mmcamcorder_handle_gst_error((MMHandleType)hcamcorder, message, err);
+
+ g_error_free (err);
+ g_free (debug);
+ break;
+ }
+ case GST_MESSAGE_WARNING:
+ {
+ GError *err;
+ gchar *debug;
+ gst_message_parse_warning (message, &err, &debug);
+
+ _mmcam_dbg_warn("GSTWARN: %s", err->message);
+
+ __mmcamcorder_handle_gst_warning((MMHandleType)hcamcorder, message, err);
+
+ g_error_free (err);
+ g_free (debug);
+ break;
+ }
+ case GST_MESSAGE_INFO:
+ _mmcam_dbg_log("GST_MESSAGE_INFO");
+ break;
+ case GST_MESSAGE_TAG:
+ _mmcam_dbg_log("GST_MESSAGE_TAG");
+ break;
+ case GST_MESSAGE_BUFFERING:
+ _mmcam_dbg_log("GST_MESSAGE_BUFFERING");
+ break;
+ case GST_MESSAGE_STATE_CHANGED:
+ {
+ GValue *vnewstate;
+ GstState newstate;
+ GstElement *pipeline = NULL;
+
+ sc = MMF_CAMCORDER_SUBCONTEXT(hcamcorder);
+ if ((sc) && (sc->element)) {
+ if (sc->element[_MMCAMCORDER_MAIN_PIPE].gst) {
+ pipeline = sc->element[_MMCAMCORDER_MAIN_PIPE].gst;
+ if (message->src == (GstObject*)pipeline) {
+ vnewstate = (GValue*)gst_structure_get_value(message->structure, "new-state");
+ newstate = (GstState)vnewstate->data[0].v_int;
+ _mmcam_dbg_log("GST_MESSAGE_STATE_CHANGED[%s]",gst_element_state_get_name(newstate));
+ }
+ }
+ }
+ break;
+ }
+ case GST_MESSAGE_STATE_DIRTY:
+ _mmcam_dbg_log("GST_MESSAGE_STATE_DIRTY");
+ break;
+ case GST_MESSAGE_STEP_DONE:
+ _mmcam_dbg_log("GST_MESSAGE_STEP_DONE");
+ break;
+ case GST_MESSAGE_CLOCK_PROVIDE:
+ _mmcam_dbg_log("GST_MESSAGE_CLOCK_PROVIDE");
+ break;
+ case GST_MESSAGE_CLOCK_LOST:
+ _mmcam_dbg_log("GST_MESSAGE_CLOCK_LOST");
+ break;
+ case GST_MESSAGE_NEW_CLOCK:
+ {
+ GstClock *clock;
+ gst_message_parse_new_clock(message, &clock);
+ _mmcam_dbg_log("GST_MESSAGE_NEW_CLOCK : %s", (clock ? GST_OBJECT_NAME (clock) : "NULL"));
+ break;
+ }
+ case GST_MESSAGE_STRUCTURE_CHANGE:
+ _mmcam_dbg_log("GST_MESSAGE_STRUCTURE_CHANGE");
+ break;
+ case GST_MESSAGE_STREAM_STATUS:
+ _mmcam_dbg_log("GST_MESSAGE_STREAM_STATUS");
+ break;
+ case GST_MESSAGE_APPLICATION:
+ _mmcam_dbg_log("GST_MESSAGE_APPLICATION");
+ break;
+ case GST_MESSAGE_ELEMENT:
+ _mmcam_dbg_log("GST_MESSAGE_ELEMENT");
+
+ if (gst_structure_has_name(message->structure, "avsysvideosrc-AF") ||
+ gst_structure_has_name(message->structure, "camerasrc-AF")) {
+ int focus_state = 0;
+
+ gst_structure_get_int(message->structure, "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);
+ }
+ break;
+ case GST_MESSAGE_SEGMENT_START:
+ _mmcam_dbg_log("GST_MESSAGE_SEGMENT_START");
+ break;
+ case GST_MESSAGE_SEGMENT_DONE:
+ _mmcam_dbg_log("GST_MESSAGE_SEGMENT_DONE");
+ break;
+ case GST_MESSAGE_DURATION:
+ _mmcam_dbg_log("GST_MESSAGE_DURATION");
+ break;
+ case GST_MESSAGE_LATENCY:
+ _mmcam_dbg_log("GST_MESSAGE_LATENCY");
+ break;
+ case GST_MESSAGE_ASYNC_START:
+ _mmcam_dbg_log("GST_MESSAGE_ASYNC_START");
+ break;
+ case GST_MESSAGE_ASYNC_DONE:
+ _mmcam_dbg_log("GST_MESSAGE_ASYNC_DONE");
+ break;
+ case GST_MESSAGE_ANY:
+ _mmcam_dbg_log("GST_MESSAGE_ANY");
+ break;
+ default:
+ _mmcam_dbg_log("not handled message type=(%d)", GST_MESSAGE_TYPE(message));
+ break;
+ }
+
+ return TRUE;
+}
+
+
+static int __mmcamcorder_asm_get_event_type(int sessionType)
+{
+ switch (sessionType) {
+ case MM_SESSION_TYPE_SHARE:
+ return ASM_EVENT_SHARE_MMCAMCORDER;
+ case MM_SESSION_TYPE_EXCLUSIVE:
+ return ASM_EVENT_EXCLUSIVE_MMCAMCORDER;
+ case MM_SESSION_TYPE_NOTIFY:
+ return ASM_EVENT_NOTIFY;
+ case MM_SESSION_TYPE_CALL:
+ return ASM_EVENT_CALL;
+ case MM_SESSION_TYPE_VIDEOCALL:
+ return ASM_EVENT_VIDEOCALL;
+ case MM_SESSION_TYPE_ALARM:
+ return ASM_EVENT_ALARM;
+ default:
+ return ASM_EVENT_SHARE_MMCAMCORDER;
+ }
+}
+
+ASM_cb_result_t _mmcamcorder_asm_callback(int handle, ASM_event_sources_t event_src,
+ ASM_sound_commands_t command,
+ unsigned int sound_status, void* cb_data)
+{
+ mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(cb_data);
+ int current_state = MM_CAMCORDER_STATE_NONE;
+ ASM_cb_result_t cb_res = ASM_CB_RES_NONE;
+
+ mmf_return_val_if_fail((MMHandleType)hcamcorder, ASM_CB_RES_NONE);
+
+ current_state = _mmcamcorder_get_state((MMHandleType)hcamcorder);
+ if (current_state <= MM_CAMCORDER_STATE_NONE ||
+ current_state >= MM_CAMCORDER_STATE_NUM) {
+ _mmcam_dbg_err("Abnormal state. Or null handle. (%p, %d, %d)", hcamcorder, command, current_state);
+ }
+
+ /* set value to inform a status is changed by asm */
+ hcamcorder->state_change_by_system = _MMCAMCORDER_STATE_CHANGE_BY_ASM;
+ /* set ASM event code for sending it to application */
+ hcamcorder->asm_event_code = event_src;
+
+ switch (command) {
+ case ASM_COMMAND_STOP:
+ case ASM_COMMAND_PAUSE:
+ _mmcam_dbg_log("Got msg from asm to Stop or Pause(%d, %d)", command, current_state);
+
+ __mmcamcorder_force_stop(hcamcorder);
+ cb_res = ASM_CB_RES_STOP;
+
+ _mmcam_dbg_log("Finish opeartion. Camera is released.(%d)", cb_res);
+ break;
+ case ASM_COMMAND_PLAY:
+ _mmcam_dbg_log("Got msg from asm to Play(%d, %d)", command, current_state);
+
+ if (current_state >= MM_CAMCORDER_STATE_PREPARE) {
+ _mmcam_dbg_log("Already start previewing");
+ return ASM_CB_RES_PLAYING;
+ }
+
+ __mmcamcorder_force_resume(hcamcorder);
+ cb_res = ASM_CB_RES_PLAYING;
+
+ _mmcam_dbg_log("Finish opeartion. Preview is started.(%d)", cb_res);
+ break;
+ case ASM_COMMAND_RESUME:
+ {
+ _MMCamcorderMsgItem msg;
+
+ _mmcam_dbg_log("Got msg from asm to Resume(%d, %d)", command, current_state);
+
+ msg.id = MM_MESSAGE_READY_TO_RESUME;
+ _mmcamcroder_send_message((MMHandleType)hcamcorder, &msg);
+ cb_res = ASM_CB_RES_PLAYING;
+
+ _mmcam_dbg_log("Finish opeartion.(%d)", cb_res);
+ break;
+ }
+ default: /* should not be reached here */
+ cb_res = ASM_CB_RES_PLAYING;
+ _mmcam_dbg_err("Command err.");
+ break;
+ }
+
+ /* restore value */
+ hcamcorder->state_change_by_system = _MMCAMCORDER_STATE_CHANGE_NORMAL;
+
+ return cb_res;
+}
+
+
+int _mmcamcorder_create_pipeline(MMHandleType handle, int type)
+{
+ int ret = MM_ERROR_NONE;
+ mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
+ _MMCamcorderSubContext *sc = NULL;
+ GstElement *pipeline = NULL;
+
+ _mmcam_dbg_log("handle : %x, type : %d", handle, type);
+
+ mmf_return_val_if_fail(hcamcorder, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
+
+ sc = MMF_CAMCORDER_SUBCONTEXT(handle);
+ mmf_return_val_if_fail(sc, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
+
+ switch (type) {
+ case MM_CAMCORDER_MODE_IMAGE:
+ __ta__(" _mmcamcorder_create_preview_pipeline",
+ ret = _mmcamcorder_create_preview_pipeline(handle);
+ );
+ if (ret != MM_ERROR_NONE) {
+ return ret;
+ }
+
+ __ta__(" _mmcamcorder_add_stillshot_pipeline",
+ ret = _mmcamcorder_add_stillshot_pipeline(handle);
+ );
+ if (ret != MM_ERROR_NONE) {
+ return ret;
+ }
+ break;
+ case MM_CAMCORDER_MODE_AUDIO:
+ __ta__(" _mmcamcorder_create_audio_pipeline",
+ ret = _mmcamcorder_create_audio_pipeline(handle);
+ );
+ if (ret != MM_ERROR_NONE) {
+ return ret;
+ }
+ break;
+ case MM_CAMCORDER_MODE_VIDEO:
+ __ta__(" _mmcamcorder_create_preview_pipeline",
+ ret = _mmcamcorder_create_preview_pipeline(handle);
+ );
+ if (ret != MM_ERROR_NONE) {
+ return ret;
+ }
+ break;
+ default:
+ return MM_ERROR_CAMCORDER_INTERNAL;
+ }
+
+ pipeline = sc->element[_MMCAMCORDER_MAIN_PIPE].gst;
+ if (type != MM_CAMCORDER_MODE_AUDIO) {
+ if (hcamcorder->sync_state_change) {
+ ret = _mmcamcorder_gst_set_state(handle, pipeline, GST_STATE_READY);
+ } else {
+ ret = _mmcamcorder_gst_set_state_async(handle, pipeline, GST_STATE_READY);
+ if (ret == GST_STATE_CHANGE_FAILURE) {
+ return MM_ERROR_CAMCORDER_GST_STATECHANGE;
+ }
+ }
+ }
+
+ if (!_mmcamcorder_get_device_info(handle)) {
+ _mmcam_dbg_err("Getting device information error!!");
+ }
+
+ _mmcam_dbg_log("ret[%x]", ret);
+ return ret;
+}
+
+
+void _mmcamcorder_destroy_pipeline(MMHandleType handle, int type)
+{
+ mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
+ _MMCamcorderSubContext *sc = NULL;
+ gint i = 0;
+ GstBus *bus = NULL;
+
+ mmf_return_if_fail(hcamcorder);
+
+ sc = MMF_CAMCORDER_SUBCONTEXT(handle);
+ mmf_return_if_fail(sc);
+
+ _mmcam_dbg_log("");
+
+ bus = gst_pipeline_get_bus(GST_PIPELINE(sc->element[_MMCAMCORDER_MAIN_PIPE].gst));
+
+ /* Inside each pipeline destroy function, Set GST_STATE_NULL to Main pipeline */
+ switch (type) {
+ case MM_CAMCORDER_MODE_IMAGE:
+ _mmcamcorder_destroy_image_pipeline(handle);
+ break;
+ case MM_CAMCORDER_MODE_AUDIO:
+ _mmcamcorder_destroy_audio_pipeline(handle);
+ break;
+ case MM_CAMCORDER_MODE_VIDEO:
+ _mmcamcorder_destroy_video_pipeline(handle);
+ break;
+ default:
+ break;
+ }
+
+ _mmcam_dbg_log("Pipeline clear!!");
+
+ /* Remove pipeline message callback */
+ g_source_remove(hcamcorder->pipeline_cb_event_id);
+
+ /* Remove remained message in bus */
+ if (bus != NULL) {
+ GstMessage *gst_msg = NULL;
+ while ((gst_msg = gst_bus_pop(bus)) != NULL) {
+ _mmcamcorder_pipeline_cb_message(bus, gst_msg, (gpointer)hcamcorder);
+ gst_message_unref( gst_msg );
+ gst_msg = NULL;
+ }
+ gst_object_unref( bus );
+ bus = NULL;
+ }
+
+ /* checking unreleased element */
+ for (i = 0 ; i < _MMCamcorder_PIPELINE_ELEMENT_NUM ; i++ ) {
+ if (sc->element[i].gst) {
+ if (GST_IS_ELEMENT(sc->element[i].gst)) {
+ _mmcam_dbg_warn("Still alive element - ID[%d], name [%s], ref count[%d], status[%s]",
+ sc->element[i].id,
+ GST_OBJECT_NAME(sc->element[i].gst),
+ GST_OBJECT_REFCOUNT_VALUE(sc->element[i].gst),
+ gst_element_state_get_name (GST_STATE (sc->element[i].gst)));
+ g_object_weak_unref(G_OBJECT(sc->element[i].gst), (GWeakNotify)_mmcamcorder_element_release_noti, sc);
+ } else {
+ _mmcam_dbg_warn("The element[%d] is still aliving, check it", sc->element[i].id);
+ }
+
+ sc->element[i].id = _MMCAMCORDER_NONE;
+ sc->element[i].gst = NULL;
+ }
+ }
+}
+
+
+int _mmcamcorder_gst_set_state_async(MMHandleType handle, GstElement *pipeline, GstState target_state)
+{
+ GstStateChangeReturn setChangeReturn = GST_STATE_CHANGE_FAILURE;
+
+ _MMCAMCORDER_LOCK_GST_STATE(handle);
+ setChangeReturn = gst_element_set_state(pipeline, target_state);
+ _MMCAMCORDER_UNLOCK_GST_STATE(handle);
+
+ return setChangeReturn;
+}
+
+
+static gboolean __mmcamcorder_set_attr_to_camsensor_cb(gpointer data)
+{
+ mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(data);
+
+ mmf_return_val_if_fail(hcamcorder, FALSE);
+
+ _mmcam_dbg_log("");
+
+ _mmcamcorder_set_attribute_to_camsensor((MMHandleType)hcamcorder);
+
+ /* initialize */
+ hcamcorder->setting_event_id = 0;
+
+ _mmcam_dbg_log("Done");
+
+ /* once */
+ return FALSE;
+}
+
+
+int _mmcamcorder_gst_set_state (MMHandleType handle, GstElement *pipeline, GstState target_state)
+{
+ unsigned int k = 0;
+ GstState pipeline_state = GST_STATE_VOID_PENDING;
+ GstStateChangeReturn setChangeReturn = GST_STATE_CHANGE_FAILURE;
+ GstStateChangeReturn getChangeReturn = GST_STATE_CHANGE_FAILURE;
+ GstClockTime get_timeout = 3 * GST_SECOND;
+
+ mmf_return_val_if_fail(handle, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
+
+ _mmcam_dbg_log("Set state to %d", target_state);
+
+ _MMCAMCORDER_LOCK_GST_STATE(handle);
+
+ for (k = 0; k < _MMCAMCORDER_STATE_SET_COUNT; k++) {
+ setChangeReturn = gst_element_set_state(pipeline, target_state);
+ if (setChangeReturn != GST_STATE_CHANGE_FAILURE) {
+ getChangeReturn = gst_element_get_state(pipeline, &pipeline_state, NULL, get_timeout);
+ switch (getChangeReturn) {
+ case GST_STATE_CHANGE_NO_PREROLL:
+ _mmcam_dbg_log("status=GST_STATE_CHANGE_NO_PREROLL.");
+ case GST_STATE_CHANGE_SUCCESS:
+ /* if we reached the final target state, exit */
+ if (pipeline_state == target_state) {
+ _MMCAMCORDER_UNLOCK_GST_STATE(handle);
+ return MM_ERROR_NONE;
+ }
+ break;
+ case GST_STATE_CHANGE_ASYNC:
+ _mmcam_dbg_log("status=GST_STATE_CHANGE_ASYNC.");
+ break;
+ default :
+ _MMCAMCORDER_UNLOCK_GST_STATE(handle);
+ _mmcam_dbg_log("status=GST_STATE_CHANGE_FAILURE.");
+ return MM_ERROR_CAMCORDER_GST_STATECHANGE;
+ }
+
+ _MMCAMCORDER_UNLOCK_GST_STATE(handle);
+ _mmcam_dbg_err("timeout of gst_element_get_state()!!");
+ return MM_ERROR_CAMCORDER_RESPONSE_TIMEOUT;
+ }
+ usleep(_MMCAMCORDER_STATE_CHECK_INTERVAL);
+ }
+
+ _MMCAMCORDER_UNLOCK_GST_STATE(handle);
+
+ _mmcam_dbg_err("Failure. gst_element_set_state timeout!!");
+
+ return MM_ERROR_CAMCORDER_RESPONSE_TIMEOUT;
+}
+
+
+/* For performance check */
+int _mmcamcorder_video_current_framerate(MMHandleType handle)
+{
+ mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
+ _MMCamcorderSubContext *sc = NULL;
+
+ mmf_return_val_if_fail(hcamcorder, -1);
+
+ sc = MMF_CAMCORDER_SUBCONTEXT(handle);
+ mmf_return_val_if_fail(sc, -1);
+
+ return sc->kpi.current_fps;
+}
+
+
+int _mmcamcorder_video_average_framerate(MMHandleType handle)
+{
+ mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
+ _MMCamcorderSubContext *sc = NULL;
+
+ mmf_return_val_if_fail(hcamcorder, -1);
+
+ sc = MMF_CAMCORDER_SUBCONTEXT(handle);
+ mmf_return_val_if_fail(sc, -1);
+
+ return sc->kpi.average_fps;
+}
+
+
+void _mmcamcorder_video_current_framerate_init(MMHandleType handle)
+{
+ mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
+ _MMCamcorderSubContext *sc = NULL;
+
+ mmf_return_if_fail(hcamcorder);
+
+ sc = MMF_CAMCORDER_SUBCONTEXT(handle);
+ mmf_return_if_fail(sc);
+
+ memset(&(sc->kpi), 0x00, sizeof(_MMCamcorderKPIMeasure));
+
+ return;
+}
+
+/* Async state change */
+void _mmcamcorder_delete_command_info(__MMCamcorderCmdInfo *cmdinfo)
+{
+ if (cmdinfo) {
+ g_free(cmdinfo);
+ }
+}
+
+static void __mmcamcorder_force_stop(mmf_camcorder_t *hcamcorder)
+{
+ int i = 0;
+ int loop = 0;
+ int itr_cnt = 0;
+ int result = MM_ERROR_NONE;
+ int current_state = MM_CAMCORDER_STATE_NONE;
+
+ mmf_return_if_fail(hcamcorder);
+
+ current_state = _mmcamcorder_get_state((MMHandleType)hcamcorder);
+
+ _mmcam_dbg_log( "Force STOP MMFW Camcorder" );
+
+ for (loop = 0 ; current_state > MM_CAMCORDER_STATE_NULL && loop < __MMCAMCORDER_CMD_ITERATE_MAX * 3 ; loop++) {
+ itr_cnt = __MMCAMCORDER_CMD_ITERATE_MAX;
+ switch (current_state) {
+ case MM_CAMCORDER_STATE_CAPTURING:
+ {
+ _MMCamcorderSubContext *sc = MMF_CAMCORDER_SUBCONTEXT(hcamcorder);
+ _MMCamcorderImageInfo *info = NULL;
+
+ mmf_return_if_fail(sc);
+ mmf_return_if_fail((info = sc->info));
+
+ _mmcam_dbg_log("Stop capturing.");
+
+ /* if caturing isn't finished, waiting for 2 sec to finish real capture operation. check 'info->capturing'. */
+ mm_camcorder_set_attributes((MMHandleType)hcamcorder, NULL,
+ MMCAM_CAPTURE_BREAK_CONTINUOUS_SHOT, TRUE,
+ NULL);
+
+ for (i = 0; i < 20 && info->capturing; i++) {
+ usleep(100000);
+ }
+
+ if (i == 20) {
+ _mmcam_dbg_err("Timeout. Can't check stop capturing.");
+ }
+
+ while ((itr_cnt--) && ((result = _mmcamcorder_capture_stop((MMHandleType)hcamcorder)) != MM_ERROR_NONE)) {
+ _mmcam_dbg_warn("Can't stop capturing.(%x)", result);
+ }
+
+ break;
+ }
+ case MM_CAMCORDER_STATE_RECORDING:
+ case MM_CAMCORDER_STATE_PAUSED:
+ {
+ _mmcam_dbg_log("Stop recording.");
+
+ while ((itr_cnt--) && ((result = _mmcamcorder_commit((MMHandleType)hcamcorder)) != MM_ERROR_NONE)) {
+ _mmcam_dbg_warn("Can't commit.(%x)", result);
+ }
+ break;
+ }
+ case MM_CAMCORDER_STATE_PREPARE:
+ {
+ _mmcam_dbg_log("Stop preview.");
+
+ while ((itr_cnt--) && ((result = _mmcamcorder_stop((MMHandleType)hcamcorder)) != MM_ERROR_NONE)) {
+ _mmcam_dbg_warn("Can't stop preview.(%x)", result);
+ }
+ break;
+ }
+ case MM_CAMCORDER_STATE_READY:
+ {
+ _mmcam_dbg_log("unrealize");
+
+ if ((result = _mmcamcorder_unrealize((MMHandleType)hcamcorder)) != MM_ERROR_NONE) {
+ _mmcam_dbg_warn("Can't unrealize.(%x)", result);
+ }
+ break;
+ }
+ case MM_CAMCORDER_STATE_NULL:
+ default:
+ _mmcam_dbg_log("Already stopped.");
+ break;
+ }
+
+ current_state = _mmcamcorder_get_state((MMHandleType)hcamcorder);
+ }
+
+ _mmcam_dbg_log( "Done." );
+
+ return;
+}
+
+
+static void __mmcamcorder_force_resume(mmf_camcorder_t *hcamcorder)
+{
+ int loop = 0;
+ int result = MM_ERROR_NONE;
+ int itr_cnt = 0;
+ int current_state = MM_CAMCORDER_STATE_NONE;
+
+ mmf_return_if_fail(hcamcorder);
+
+ _mmcam_dbg_log("Force RESUME MMFW Camcorder");
+
+ current_state = _mmcamcorder_get_state((MMHandleType)hcamcorder);
+
+ for (loop = 0 ; current_state < MM_CAMCORDER_STATE_PREPARE && loop < __MMCAMCORDER_CMD_ITERATE_MAX * 3 ; loop++) {
+ itr_cnt = __MMCAMCORDER_CMD_ITERATE_MAX;
+
+ switch (current_state) {
+ case MM_CAMCORDER_STATE_NULL:
+ _mmcam_dbg_log("Realize");
+ while ((itr_cnt--) && ((result = _mmcamcorder_realize((MMHandleType)hcamcorder)) != MM_ERROR_NONE)) {
+ _mmcam_dbg_warn("Can't realize.(%x)", result);
+ }
+ break;
+ case MM_CAMCORDER_STATE_READY:
+ _mmcam_dbg_log("Start previewing");
+
+ while ((itr_cnt--) && ((result = _mmcamcorder_start((MMHandleType)hcamcorder)) != MM_ERROR_NONE)) {
+ _mmcam_dbg_warn("Can't start previewing.(%x)", result);
+ }
+ break;
+ default:
+ _mmcam_dbg_log("Abnormal state.");
+ break;
+ }
+
+ current_state = _mmcamcorder_get_state((MMHandleType)hcamcorder);
+ }
+
+ _mmcam_dbg_log( "Done." );
+
+ return;
+}
+
+int _mmcamcorder_create_command_loop(MMHandleType handle)
+{
+ mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
+ _MMCamcorderCommand *cmd;
+
+ mmf_return_val_if_fail(hcamcorder, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
+
+ _mmcam_dbg_log("");
+
+ cmd = (_MMCamcorderCommand *)&(hcamcorder->cmd);
+ cmd->cmd_queue = g_queue_new();
+ mmf_return_val_if_fail(cmd->cmd_queue, MM_ERROR_CAMCORDER_INVALID_CONDITION);
+
+ sem_init(&cmd->sema, 0, 0);
+
+ if (pthread_create(&cmd->pCommandThread, NULL, _mmcamcorder_command_loop_thread, hcamcorder)) {
+ perror("Make Command Thread Fail");
+ return MM_ERROR_COMMON_UNKNOWN;
+ }
+
+ return MM_ERROR_NONE;
+}
+
+
+int _mmcamcorder_destroy_command_loop(MMHandleType handle)
+{
+ mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
+ _MMCamcorderCommand *cmd;
+
+ mmf_return_val_if_fail(hcamcorder, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
+ _mmcam_dbg_log("");
+
+ cmd = (_MMCamcorderCommand *)&(hcamcorder->cmd);
+ mmf_return_val_if_fail(cmd->cmd_queue, MM_ERROR_CAMCORDER_INVALID_CONDITION);
+
+ _mmcamcorder_append_simple_command(handle, _MMCAMCORDER_CMD_QUIT);
+
+ sem_post(&cmd->sema); /* why is this needed? */
+
+ _mmcam_dbg_log("wait for pthread join");
+
+ pthread_join(cmd->pCommandThread, NULL);
+
+ _mmcam_dbg_log("pthread join!!");
+
+ sem_destroy(&cmd->sema);
+
+ while (!g_queue_is_empty(cmd->cmd_queue)) {
+ __MMCamcorderCmdInfo *info = NULL;
+ info = g_queue_pop_head(cmd->cmd_queue);
+ _mmcamcorder_delete_command_info(info);
+ }
+ g_queue_free(cmd->cmd_queue);
+
+ _mmcam_dbg_log("Command loop clear.");
+
+ return MM_ERROR_NONE;
+}
+
+
+int _mmcamcorder_append_command(MMHandleType handle, __MMCamcorderCmdInfo *info)
+{
+ int value = 0;
+ mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
+ _MMCamcorderCommand *cmd;
+
+ mmf_return_val_if_fail(hcamcorder, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
+
+ _mmcam_dbg_log("");
+
+ cmd = (_MMCamcorderCommand *)&(hcamcorder->cmd);
+ mmf_return_val_if_fail(cmd->cmd_queue, MM_ERROR_CAMCORDER_INVALID_CONDITION);
+
+ g_queue_push_tail (cmd->cmd_queue, (gpointer)info);
+
+ sem_getvalue(&cmd->sema, &value);
+
+ if (value == 0) {
+ sem_post(&cmd->sema);
+ } else {
+ /* Don't need to post. */
+ }
+
+ return MM_ERROR_NONE;
+}
+
+
+int _mmcamcorder_append_simple_command(MMHandleType handle, _MMCamcorderCommandType type)
+{
+ mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
+ __MMCamcorderCmdInfo *info = NULL;
+
+ mmf_return_val_if_fail(hcamcorder, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
+
+ _mmcam_dbg_log("Command Type=%d", type);
+
+ info = (__MMCamcorderCmdInfo*)malloc(sizeof(__MMCamcorderCmdInfo));
+
+ info->handle = handle;
+ info->type = type;
+
+ _mmcamcorder_append_command(handle, info);
+
+ return MM_ERROR_NONE;
+}
+
+
+void *_mmcamcorder_command_loop_thread(void *arg)
+{
+ gboolean bExit_loop = FALSE;
+ mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(arg);
+ _MMCamcorderCommand *cmd = NULL;
+ __MMCamcorderCmdInfo *cmdinfo = NULL;
+
+ mmf_return_val_if_fail(hcamcorder, NULL);
+
+ cmd = (_MMCamcorderCommand *)&(hcamcorder->cmd);
+ mmf_return_val_if_fail(cmd->cmd_queue, NULL);
+
+ _mmcam_dbg_log("");
+
+ while (!bExit_loop) {
+ sem_wait(&cmd->sema);
+
+ /* send command */
+ while (!g_queue_is_empty (cmd->cmd_queue)) {
+ int bRet = MM_ERROR_NONE;
+
+ cmdinfo = g_queue_pop_head(cmd->cmd_queue);
+ if (cmdinfo->handle == (MMHandleType)NULL) {
+ _mmcam_dbg_log("Handle in cmdinfo is Null.");
+ bRet = MM_ERROR_CAMCORDER_NOT_INITIALIZED;
+ } else {
+ switch (cmdinfo->type) {
+ case _MMCAMCORDER_CMD_CREATE:
+ case _MMCAMCORDER_CMD_DESTROY:
+ case _MMCAMCORDER_CMD_CAPTURESTART:
+ case _MMCAMCORDER_CMD_CAPTURESTOP:
+ case _MMCAMCORDER_CMD_RECORD:
+ case _MMCAMCORDER_CMD_PAUSE:
+ case _MMCAMCORDER_CMD_COMMIT:
+ __ta__("_mmcamcorder_commit",
+ bRet = _mmcamcorder_commit(cmdinfo->handle);
+ );
+ break;
+ case _MMCAMCORDER_CMD_CANCEL:
+ //Not used yet.
+ break;
+ case _MMCAMCORDER_CMD_REALIZE:
+ __ta__("_mmcamcorder_realize",
+ bRet = _mmcamcorder_realize(cmdinfo->handle);
+ );
+ break;
+ case _MMCAMCORDER_CMD_UNREALIZE:
+ __ta__("_mmcamcorder_unrealize",
+ bRet = _mmcamcorder_unrealize(cmdinfo->handle);
+ );
+ break;
+ case _MMCAMCORDER_CMD_START:
+ __ta__("_mmcamcorder_start",
+ bRet = _mmcamcorder_start(cmdinfo->handle);
+ );
+ break;
+ case _MMCAMCORDER_CMD_STOP:
+ __ta__("_mmcamcorder_stop",
+ bRet = _mmcamcorder_stop(cmdinfo->handle);
+ );
+ break;
+ case _MMCAMCORDER_CMD_QUIT:
+ _mmcam_dbg_log("Exit command loop!!");
+ bExit_loop = TRUE;
+ break;
+ default:
+ _mmcam_dbg_log("Wrong command type!!!");
+ break;
+ }
+ }
+
+ if (bRet != MM_ERROR_NONE) {
+ _mmcam_dbg_log("Error on command process!(%x)", bRet);
+ /* Do something? */
+ }
+
+ _mmcamcorder_delete_command_info(cmdinfo);
+
+ if (bExit_loop) {
+ break;
+ }
+ usleep(1);
+ }
+ }
+
+ return NULL;
+}
+
+
+static gboolean __mmcamcorder_handle_gst_error(MMHandleType handle, GstMessage *message, GError *error)
+{
+ mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
+ _MMCamcorderMsgItem msg;
+ gchar *msg_src_element;
+ _MMCamcorderSubContext *sc = NULL;
+
+ return_val_if_fail(hcamcorder, FALSE);
+ return_val_if_fail(error, FALSE);
+ sc = MMF_CAMCORDER_SUBCONTEXT(handle);
+ mmf_return_val_if_fail(sc, FALSE);
+
+ _mmcam_dbg_log("");
+
+ /* filtering filesink related errors */
+ if (hcamcorder->state == MM_CAMCORDER_STATE_RECORDING &&
+ (error->code == GST_RESOURCE_ERROR_WRITE || error->code == GST_RESOURCE_ERROR_SEEK)) {
+ if (sc->ferror_count == 2 && sc->ferror_send == FALSE) {
+ sc->ferror_send = TRUE;
+ msg.param.code = __mmcamcorder_gst_handle_resource_error(handle, error->code, message);
+ } else {
+ sc->ferror_count++;
+ _mmcam_dbg_warn("Skip error");
+ return TRUE;
+ }
+ }
+
+ if (error->domain == GST_CORE_ERROR) {
+ msg.param.code = __mmcamcorder_gst_handle_core_error(handle, error->code, message);
+ } else if (error->domain == GST_LIBRARY_ERROR) {
+ msg.param.code = __mmcamcorder_gst_handle_library_error(handle, error->code, message);
+ } else if (error->domain == GST_RESOURCE_ERROR) {
+ msg.param.code = __mmcamcorder_gst_handle_resource_error(handle, error->code, message);
+ } else if (error->domain == GST_STREAM_ERROR) {
+ msg.param.code = __mmcamcorder_gst_handle_stream_error(handle, error->code, message);
+ } else {
+ debug_warning("This error domain is not defined.\n");
+
+ /* we treat system error as an internal error */
+ msg.param.code = MM_ERROR_CAMCORDER_INTERNAL;
+ }
+
+ if (message->src) {
+ msg_src_element = GST_ELEMENT_NAME(GST_ELEMENT_CAST(message->src));
+ debug_error("-Msg src : [%s] Domain : [%s] Error : [%s] Code : [%d] is tranlated to error code : [0x%x]\n",
+ msg_src_element, g_quark_to_string (error->domain), error->message, error->code, msg.param.code);
+ } else {
+ debug_error("Domain : [%s] Error : [%s] Code : [%d] is tranlated to error code : [0x%x]\n",
+ g_quark_to_string (error->domain), error->message, error->code, msg.param.code);
+ }
+
+ /* Check whether send this error to application */
+ if (msg.param.code == MM_ERROR_CAMCORDER_GST_FLOW_ERROR) {
+ _mmcam_dbg_log("We got the error. But skip it.");
+ return TRUE;
+ }
+
+ /* post error to application */
+ sc->error_occurs = TRUE;
+ msg.id = MM_MESSAGE_CAMCORDER_ERROR;
+ _mmcamcroder_send_message(handle, &msg);
+
+ return TRUE;
+}
+
+
+static gint __mmcamcorder_gst_handle_core_error(MMHandleType handle, int code, GstMessage *message)
+{
+ mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
+ _MMCamcorderSubContext *sc = NULL;
+ GstElement *element = NULL;
+
+ _mmcam_dbg_log("");
+
+ mmf_return_val_if_fail(hcamcorder, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
+
+ sc = MMF_CAMCORDER_SUBCONTEXT(handle);
+ mmf_return_val_if_fail(sc, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
+
+ /* Specific plugin - video encoder plugin */
+ element = GST_ELEMENT_CAST(sc->element[_MMCAMCORDER_ENCSINK_VENC].gst);
+
+ if (GST_ELEMENT_CAST(message->src) == element) {
+ if (code == GST_CORE_ERROR_NEGOTIATION) {
+ return MM_ERROR_CAMCORDER_GST_NEGOTIATION;
+ } else {
+ return MM_ERROR_CAMCORDER_ENCODER;
+ }
+ }
+
+ /* General */
+ switch (code)
+ {
+ case GST_CORE_ERROR_STATE_CHANGE:
+ return MM_ERROR_CAMCORDER_GST_STATECHANGE;
+ case GST_CORE_ERROR_NEGOTIATION:
+ return MM_ERROR_CAMCORDER_GST_NEGOTIATION;
+ case GST_CORE_ERROR_MISSING_PLUGIN:
+ case GST_CORE_ERROR_SEEK:
+ case GST_CORE_ERROR_NOT_IMPLEMENTED:
+ case GST_CORE_ERROR_FAILED:
+ case GST_CORE_ERROR_TOO_LAZY:
+ case GST_CORE_ERROR_PAD:
+ case GST_CORE_ERROR_THREAD:
+ case GST_CORE_ERROR_EVENT:
+ case GST_CORE_ERROR_CAPS:
+ case GST_CORE_ERROR_TAG:
+ case GST_CORE_ERROR_CLOCK:
+ case GST_CORE_ERROR_DISABLED:
+ default:
+ return MM_ERROR_CAMCORDER_GST_CORE;
+ break;
+ }
+}
+
+static gint __mmcamcorder_gst_handle_library_error(MMHandleType handle, int code, GstMessage *message)
+{
+ mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
+ return_val_if_fail(hcamcorder, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
+
+ _mmcam_dbg_log("");
+
+ /* Specific plugin - NONE */
+
+ /* General */
+ switch (code) {
+ case GST_LIBRARY_ERROR_FAILED:
+ case GST_LIBRARY_ERROR_TOO_LAZY:
+ case GST_LIBRARY_ERROR_INIT:
+ case GST_LIBRARY_ERROR_SHUTDOWN:
+ case GST_LIBRARY_ERROR_SETTINGS:
+ case GST_LIBRARY_ERROR_ENCODE:
+ default:
+ _mmcam_dbg_err("Library error(%d)", code);
+ return MM_ERROR_CAMCORDER_GST_LIBRARY;
+ }
+}
+
+
+static gint __mmcamcorder_gst_handle_resource_error(MMHandleType handle, int code, GstMessage *message)
+{
+ mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
+ _MMCamcorderSubContext *sc = NULL;
+ GstElement *element =NULL;
+
+ mmf_return_val_if_fail(hcamcorder, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
+
+ sc = MMF_CAMCORDER_SUBCONTEXT(handle);
+ mmf_return_val_if_fail(sc, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
+
+ _mmcam_dbg_log("");
+
+ /* Specific plugin */
+ /* video source */
+ element = GST_ELEMENT_CAST(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst);
+ if (GST_ELEMENT_CAST(message->src) == element) {
+ switch (code) {
+ case GST_RESOURCE_ERROR_BUSY:
+ _mmcam_dbg_err("Video device [busy]");
+ return MM_ERROR_CAMCORDER_DEVICE_BUSY;
+ case GST_RESOURCE_ERROR_FAILED:
+ _mmcam_dbg_err("Video device [working failed].");
+ return MM_ERROR_CAMCORDER_DEVICE_IO;
+ case GST_RESOURCE_ERROR_TOO_LAZY:
+ _mmcam_dbg_err("Video device [timeout]");
+ return MM_ERROR_CAMCORDER_DEVICE_TIMEOUT;
+ case GST_RESOURCE_ERROR_OPEN_READ:
+ _mmcam_dbg_err("Video device [open failed]");
+ return MM_ERROR_CAMCORDER_DEVICE_OPEN;
+ case GST_RESOURCE_ERROR_SETTINGS:
+ _mmcam_dbg_err("Video device [Not supported]");
+ return MM_ERROR_CAMCORDER_NOT_SUPPORTED;
+ case GST_RESOURCE_ERROR_NOT_FOUND:
+ _mmcam_dbg_err("Video device [Register trouble]");
+ return MM_ERROR_CAMCORDER_DEVICE_REG_TROUBLE;
+ default:
+ _mmcam_dbg_err("Video device [General(%d)]", code);
+ return MM_ERROR_CAMCORDER_DEVICE;
+ }
+ }
+
+ /* video sink */
+ element = GST_ELEMENT_CAST(sc->element[_MMCAMCORDER_VIDEOSINK_SINK].gst);
+ if (GST_ELEMENT_CAST(message->src) == element) {
+ if (code == GST_RESOURCE_ERROR_WRITE) {
+ _mmcam_dbg_err("Display device [Off]");
+ return MM_ERROR_CAMCORDER_DISPLAY_DEVICE_OFF;
+ } else {
+ _mmcam_dbg_err("Display device [General(%d)]", code);
+ }
+ }
+
+ /* encodebin */
+ element = GST_ELEMENT_CAST(sc->element[_MMCAMCORDER_ENCSINK_VENC].gst);
+ if (GST_ELEMENT_CAST(message->src) == element) {
+ if (code == GST_RESOURCE_ERROR_FAILED) {
+ _mmcam_dbg_err("Encoder [Resource error]");
+ return MM_ERROR_CAMCORDER_ENCODER_BUFFER;
+ } else {
+ _mmcam_dbg_err("Encoder [General(%d)]", code);
+ return MM_ERROR_CAMCORDER_ENCODER;
+ }
+ }
+
+ /* General */
+ switch (code) {
+ case GST_RESOURCE_ERROR_WRITE:
+ _mmcam_dbg_err("File write error");
+ return MM_ERROR_FILE_WRITE;
+ case GST_RESOURCE_ERROR_NO_SPACE_LEFT:
+ _mmcam_dbg_err("No left space");
+ return MM_MESSAGE_CAMCORDER_NO_FREE_SPACE;
+ case GST_RESOURCE_ERROR_OPEN_WRITE:
+ _mmcam_dbg_err("Out of storage");
+ return MM_ERROR_OUT_OF_STORAGE;
+ case GST_RESOURCE_ERROR_SEEK:
+ _mmcam_dbg_err("File read(seek)");
+ return MM_ERROR_FILE_READ;
+ case GST_RESOURCE_ERROR_NOT_FOUND:
+ case GST_RESOURCE_ERROR_FAILED:
+ case GST_RESOURCE_ERROR_TOO_LAZY:
+ case GST_RESOURCE_ERROR_BUSY:
+ case GST_RESOURCE_ERROR_OPEN_READ:
+ case GST_RESOURCE_ERROR_OPEN_READ_WRITE:
+ case GST_RESOURCE_ERROR_CLOSE:
+ case GST_RESOURCE_ERROR_READ:
+ case GST_RESOURCE_ERROR_SYNC:
+ case GST_RESOURCE_ERROR_SETTINGS:
+ default:
+ _mmcam_dbg_err("Resource error(%d)", code);
+ return MM_ERROR_CAMCORDER_GST_RESOURCE;
+ }
+}
+
+
+static gint __mmcamcorder_gst_handle_stream_error(MMHandleType handle, int code, GstMessage *message)
+{
+ mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
+ _MMCamcorderSubContext *sc = NULL;
+ GstElement *element =NULL;
+
+ mmf_return_val_if_fail( hcamcorder, MM_ERROR_CAMCORDER_NOT_INITIALIZED );
+
+ sc = MMF_CAMCORDER_SUBCONTEXT(handle);
+ mmf_return_val_if_fail(sc, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
+
+ _mmcam_dbg_log("");
+
+ /* Specific plugin */
+ /* video encoder */
+ element = GST_ELEMENT_CAST(sc->element[_MMCAMCORDER_ENCSINK_VENC].gst);
+ if (GST_ELEMENT_CAST(message->src) == element) {
+ switch (code) {
+ case GST_STREAM_ERROR_WRONG_TYPE:
+ _mmcam_dbg_err("Video encoder [wrong stream type]");
+ return MM_ERROR_CAMCORDER_ENCODER_WRONG_TYPE;
+ case GST_STREAM_ERROR_ENCODE:
+ _mmcam_dbg_err("Video encoder [encode error]");
+ return MM_ERROR_CAMCORDER_ENCODER_WORKING;
+ case GST_STREAM_ERROR_FAILED:
+ _mmcam_dbg_err("Video encoder [stream failed]");
+ return MM_ERROR_CAMCORDER_ENCODER_WORKING;
+ default:
+ _mmcam_dbg_err("Video encoder [General(%d)]", code);
+ return MM_ERROR_CAMCORDER_ENCODER;
+ }
+ }
+
+ /* General plugin */
+ switch (code) {
+ case GST_STREAM_ERROR_FORMAT:
+ _mmcam_dbg_err("General [negotiation error(%d)]", code);
+ return MM_ERROR_CAMCORDER_GST_NEGOTIATION;
+ case GST_STREAM_ERROR_FAILED:
+ _mmcam_dbg_err("General [flow error(%d)]", code);
+ return MM_ERROR_CAMCORDER_GST_FLOW_ERROR;
+ case GST_STREAM_ERROR_TYPE_NOT_FOUND:
+ case GST_STREAM_ERROR_DECODE:
+ case GST_STREAM_ERROR_CODEC_NOT_FOUND:
+ case GST_STREAM_ERROR_NOT_IMPLEMENTED:
+ case GST_STREAM_ERROR_TOO_LAZY:
+ case GST_STREAM_ERROR_ENCODE:
+ case GST_STREAM_ERROR_DEMUX:
+ case GST_STREAM_ERROR_MUX:
+ case GST_STREAM_ERROR_DECRYPT:
+ case GST_STREAM_ERROR_DECRYPT_NOKEY:
+ case GST_STREAM_ERROR_WRONG_TYPE:
+ default:
+ _mmcam_dbg_err("General [error(%d)]", code);
+ return MM_ERROR_CAMCORDER_GST_STREAM;
+ }
+}
+
+
+static gboolean __mmcamcorder_handle_gst_warning (MMHandleType handle, GstMessage *message, GError *error)
+{
+ mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
+ gchar *debug = NULL;
+ GError *err = NULL;
+
+ return_val_if_fail(hcamcorder, FALSE);
+ return_val_if_fail(error, FALSE);
+
+ _mmcam_dbg_log("");
+
+ gst_message_parse_warning(message, &err, &debug);
+
+ if (error->domain == GST_CORE_ERROR) {
+ _mmcam_dbg_warn("GST warning: GST_CORE domain");
+ } else if (error->domain == GST_LIBRARY_ERROR) {
+ _mmcam_dbg_warn("GST warning: GST_LIBRARY domain");
+ } else if (error->domain == GST_RESOURCE_ERROR) {
+ _mmcam_dbg_warn("GST warning: GST_RESOURCE domain");
+ __mmcamcorder_gst_handle_resource_warning(handle, message, error);
+ } else if (error->domain == GST_STREAM_ERROR ) {
+ _mmcam_dbg_warn("GST warning: GST_STREAM domain");
+ } else {
+ _mmcam_dbg_warn("This error domain(%d) is not defined.", error->domain);
+ }
+
+ if (err != NULL) {
+ g_error_free(err);
+ err = NULL;
+ }
+ if (debug != NULL) {
+ _mmcam_dbg_err ("Debug: %s", debug);
+ g_free(debug);
+ debug = NULL;
+ }
+
+ return TRUE;
+}
+
+
+static gint __mmcamcorder_gst_handle_resource_warning(MMHandleType handle, GstMessage *message , GError *error)
+{
+ mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
+ _MMCamcorderSubContext *sc = NULL;
+ GstElement *element =NULL;
+ gchar *msg_src_element;
+
+ mmf_return_val_if_fail( hcamcorder, MM_ERROR_CAMCORDER_NOT_INITIALIZED );
+
+ sc = MMF_CAMCORDER_SUBCONTEXT(handle);
+ mmf_return_val_if_fail(sc, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
+
+ _mmcam_dbg_log("");
+
+ /* Special message handling */
+ /* video source */
+ element = GST_ELEMENT_CAST(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst);
+ if (GST_ELEMENT_CAST(message->src) == element) {
+ if (error->code == GST_RESOURCE_ERROR_FAILED) {
+ msg_src_element = GST_ELEMENT_NAME(GST_ELEMENT_CAST(message->src));
+ _mmcam_dbg_warn("-Msg src:[%s] Domain:[%s] Error:[%s]",
+ msg_src_element, g_quark_to_string(error->domain), error->message);
+ return MM_ERROR_NONE;
+ }
+ }
+
+ /* General plugin */
+ switch (error->code) {
+ case GST_RESOURCE_ERROR_WRITE:
+ case GST_RESOURCE_ERROR_NO_SPACE_LEFT:
+ case GST_RESOURCE_ERROR_SEEK:
+ case GST_RESOURCE_ERROR_NOT_FOUND:
+ case GST_RESOURCE_ERROR_FAILED:
+ case GST_RESOURCE_ERROR_TOO_LAZY:
+ case GST_RESOURCE_ERROR_BUSY:
+ case GST_RESOURCE_ERROR_OPEN_READ:
+ case GST_RESOURCE_ERROR_OPEN_WRITE:
+ case GST_RESOURCE_ERROR_OPEN_READ_WRITE:
+ case GST_RESOURCE_ERROR_CLOSE:
+ case GST_RESOURCE_ERROR_READ:
+ case GST_RESOURCE_ERROR_SYNC:
+ case GST_RESOURCE_ERROR_SETTINGS:
+ default:
+ _mmcam_dbg_warn("General GST warning(%d)", error->code);
+ break;
+ }
+
+ return MM_ERROR_NONE;
+}
diff --git a/src/mm_camcorder_platform.c b/src/mm_camcorder_platform.c
new file mode 100644
index 0000000..3497ab5
--- /dev/null
+++ b/src/mm_camcorder_platform.c
@@ -0,0 +1,977 @@
+/*
+ * libmm-camcorder
+ *
+ * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: Jeongmo Yang <jm80.yang@samsung.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+/*===========================================================================================
+| |
+| INCLUDE FILES |
+| |
+========================================================================================== */
+#include "mm_camcorder_internal.h"
+#include "mm_camcorder_platform.h"
+#include "mm_camcorder_configure.h"
+
+/*---------------------------------------------------------------------------
+| GLOBAL VARIABLE DEFINITIONS for internal |
+---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------
+| LOCAL VARIABLE DEFINITIONS for internal |
+---------------------------------------------------------------------------*/
+#define MM_CAMCORDER_ATTR_NONE -1
+
+
+// Rule 1. 1:1 match except NONE.
+// Rule 2. MSL should be Superset.
+// Rule 3. sensor value should not be same as _MMCAMCORDER_SENSOR_ENUM_NONE.
+
+static int __enum_conv_whitebalance[MM_CAMCORDER_WHITE_BALANCE_NUM] ;
+
+_MMCamcorderEnumConvert _mmcamcorder_enum_conv_whitebalance =
+{
+ MM_CAMCORDER_WHITE_BALANCE_NUM,
+ __enum_conv_whitebalance,
+ CONFIGURE_CATEGORY_CTRL_EFFECT,
+ "WhiteBalance"
+};
+
+
+static int __enum_conv_colortone[MM_CAMCORDER_COLOR_TONE_NUM];
+
+_MMCamcorderEnumConvert _mmcamcorder_enum_conv_colortone =
+{
+ MM_CAMCORDER_COLOR_TONE_NUM,
+ __enum_conv_colortone,
+ CONFIGURE_CATEGORY_CTRL_EFFECT,
+ "ColorTone"
+};
+
+
+static int __enum_conv_iso[MM_CAMCORDER_ISO_NUM];
+
+_MMCamcorderEnumConvert _mmcamcorder_enum_conv_iso =
+{
+ MM_CAMCORDER_ISO_NUM,
+ __enum_conv_iso,
+ CONFIGURE_CATEGORY_CTRL_PHOTOGRAPH,
+ "ISO"
+};
+
+
+static int __enum_conv_prgrm[MM_CAMCORDER_SCENE_MODE_NUM];
+
+_MMCamcorderEnumConvert _mmcamcorder_enum_conv_prgrm =
+{
+ MM_CAMCORDER_SCENE_MODE_NUM,
+ __enum_conv_prgrm,
+ CONFIGURE_CATEGORY_CTRL_PHOTOGRAPH,
+ "ProgramMode"
+};
+
+
+static int __enum_conv_focus_mode[MM_CAMCORDER_FOCUS_MODE_NUM];
+
+_MMCamcorderEnumConvert _mmcamcorder_enum_conv_focus_mode =
+{
+ MM_CAMCORDER_FOCUS_MODE_NUM,
+ __enum_conv_focus_mode,
+ CONFIGURE_CATEGORY_CTRL_PHOTOGRAPH,
+ "FocusMode"
+};
+
+
+static int __enum_conv_focus_type[MM_CAMCORDER_AUTO_FOCUS_NUM];
+
+_MMCamcorderEnumConvert _mmcamcorder_enum_conv_focus_type =
+{
+ MM_CAMCORDER_AUTO_FOCUS_NUM,
+ __enum_conv_focus_type,
+ CONFIGURE_CATEGORY_CTRL_PHOTOGRAPH,
+ "AFType"
+};
+
+
+static int __enum_conv_ae_type[MM_CAMCORDER_AUTO_EXPOSURE_NUM];
+
+_MMCamcorderEnumConvert _mmcamcorder_enum_conv_ae_type =
+{
+ MM_CAMCORDER_AUTO_EXPOSURE_NUM,
+ __enum_conv_ae_type,
+ CONFIGURE_CATEGORY_CTRL_PHOTOGRAPH,
+ "AEType"
+};
+
+
+static int __enum_conv_strobe_ctrl[MM_CAMCORDER_STROBE_CONTROL_NUM];
+
+_MMCamcorderEnumConvert _mmcamcorder_enum_conv_strobe_ctrl =
+{
+ MM_CAMCORDER_STROBE_CONTROL_NUM,
+ __enum_conv_strobe_ctrl,
+ CONFIGURE_CATEGORY_CTRL_STROBE,
+ "StrobeControl"
+};
+
+
+static int __enum_conv_strobe_mode[MM_CAMCORDER_STROBE_MODE_NUM];
+
+_MMCamcorderEnumConvert _mmcamcorder_enum_conv_strobe_mode =
+{
+ MM_CAMCORDER_STROBE_MODE_NUM,
+ __enum_conv_strobe_mode,
+ CONFIGURE_CATEGORY_CTRL_STROBE,
+ "StrobeMode"
+};
+
+
+static int __enum_conv_wdr_ctrl[MM_CAMCORDER_WDR_NUM];
+
+_MMCamcorderEnumConvert _mmcamcorder_enum_conv_wdr_ctrl =
+{
+ MM_CAMCORDER_WDR_NUM,
+ __enum_conv_wdr_ctrl,
+ CONFIGURE_CATEGORY_CTRL_EFFECT,
+ "WDR"
+};
+
+
+static int __enum_conv_ahs[MM_CAMCORDER_AHS_NUM];
+
+_MMCamcorderEnumConvert _mmcamcorder_enum_conv_ahs =
+{
+ MM_CAMCORDER_AHS_NUM,
+ __enum_conv_ahs,
+ CONFIGURE_CATEGORY_CTRL_PHOTOGRAPH,
+ "AntiHandshake"
+};
+
+static int __enum_conv_picture_format[MM_PIXEL_FORMAT_NUM];
+
+_MMCamcorderEnumConvert _mmcamcorder_enum_conv_picture_format =
+{
+ MM_PIXEL_FORMAT_NUM,
+ __enum_conv_picture_format,
+ CONFIGURE_CATEGORY_CTRL_CAMERA,
+ "PictureFormat"
+};
+
+static int __enum_conv_vid_dev[MM_VIDEO_DEVICE_NUM] =
+{
+ //{Enum of (Plugin or Kernel) , Enum of MSL Camcorder}
+ 2, //MM_VIDEO_DEVICE_CAMERA0
+ 1, //MM_VIDEO_DEVICE_CAMERA1
+};
+
+_MMCamcorderEnumConvert _mmcamcorder_enum_conv_vid_dev =
+{
+ MM_VIDEO_DEVICE_NUM,
+ __enum_conv_vid_dev,
+ 0,
+ NULL
+};
+
+
+/**
+ * Matching table of caminfo index with category enum of attribute.
+ * If predefined item is changed, this static variables should be changed.
+ * For detail information, refer below documents.
+ *
+ */
+static _MMCamcorderInfoConverting g_display_info[] = {
+ {
+ CONFIGURE_TYPE_MAIN,
+ CONFIGURE_CATEGORY_MAIN_VIDEO_OUTPUT,
+ MM_CAM_DISPLAY_DEVICE,
+ MM_CAMCORDER_ATTR_NONE,
+ "DisplayDevice",
+ MM_CAMCONVERT_TYPE_INT_ARRAY,
+ NULL,
+ },
+ {
+ CONFIGURE_TYPE_MAIN,
+ CONFIGURE_CATEGORY_MAIN_VIDEO_OUTPUT,
+ MM_CAM_DISPLAY_SURFACE,
+ MM_CAMCORDER_ATTR_NONE,
+ "Videosink",
+ MM_CAMCONVERT_TYPE_INT_ARRAY,
+ NULL,
+ },
+};
+
+static _MMCamcorderInfoConverting g_caminfo_convert[] = {
+ {
+ CONFIGURE_TYPE_CTRL,
+ CONFIGURE_CATEGORY_CTRL_CAMERA,
+ MM_CAM_CAMERA_DEVICE,
+ MM_CAMCORDER_ATTR_NONE,
+ "InputIndex",
+ MM_CAMCONVERT_TYPE_INT_ARRAY,
+ &_mmcamcorder_enum_conv_vid_dev,
+ },
+ {
+ CONFIGURE_TYPE_CTRL,
+ CONFIGURE_CATEGORY_CTRL_CAMERA,
+ MM_CAM_CAMERA_DEVICE_NAME,
+ MM_CAMCORDER_ATTR_NONE,
+ "DeviceName",
+ MM_CAMCONVERT_TYPE_STRING,
+ NULL,
+ },
+ {
+ CONFIGURE_TYPE_CTRL,
+ CONFIGURE_CATEGORY_CTRL_CAMERA,
+ MM_CAM_CAMERA_WIDTH,
+ MM_CAM_CAMERA_HEIGHT,
+ "PreviewResolution",
+ MM_CAMCONVERT_TYPE_INT_PAIR_ARRAY,
+ NULL,
+ },
+ {
+ CONFIGURE_TYPE_CTRL,
+ CONFIGURE_CATEGORY_CTRL_CAMERA,
+ MM_CAM_CAPTURE_WIDTH,
+ MM_CAM_CAPTURE_HEIGHT,
+ "CaptureResolution",
+ MM_CAMCONVERT_TYPE_INT_PAIR_ARRAY,
+ NULL,
+ },
+ {
+ CONFIGURE_TYPE_CTRL,
+ CONFIGURE_CATEGORY_CTRL_CAMERA,
+ MM_CAM_CAMERA_FPS,
+ MM_CAMCORDER_ATTR_NONE,
+ "FPS",
+ MM_CAMCONVERT_TYPE_INT_ARRAY,
+ NULL,
+ },
+ {
+ CONFIGURE_TYPE_CTRL,
+ CONFIGURE_CATEGORY_CTRL_CAMERA,
+ MM_CAM_CAMERA_FORMAT,
+ MM_CAMCORDER_ATTR_NONE,
+ "PictureFormat",
+ MM_CAMCONVERT_TYPE_INT_ARRAY,
+ NULL,
+ },
+ {
+ CONFIGURE_TYPE_CTRL,
+ CONFIGURE_CATEGORY_CTRL_STROBE,
+ MM_CAM_STROBE_CONTROL,
+ MM_CAMCORDER_ATTR_NONE,
+ "StrobeControl",
+ MM_CAMCONVERT_TYPE_INT_ARRAY,
+ &_mmcamcorder_enum_conv_strobe_ctrl,
+ },
+ {
+ CONFIGURE_TYPE_CTRL,
+ CONFIGURE_CATEGORY_CTRL_STROBE,
+ MM_CAM_STROBE_CAPABILITIES,
+ MM_CAMCORDER_ATTR_NONE,
+ "StrobeCapabilities",
+ MM_CAMCONVERT_TYPE_INT_ARRAY,
+ NULL,
+ },
+ {
+ CONFIGURE_TYPE_CTRL,
+ CONFIGURE_CATEGORY_CTRL_STROBE,
+ MM_CAM_STROBE_MODE,
+ MM_CAMCORDER_ATTR_NONE,
+ "StrobeMode",
+ MM_CAMCONVERT_TYPE_INT_ARRAY,
+ &_mmcamcorder_enum_conv_strobe_mode,
+ },
+ {
+ CONFIGURE_TYPE_CTRL,
+ CONFIGURE_CATEGORY_CTRL_EFFECT,
+ MM_CAM_FILTER_BRIGHTNESS,
+ MM_CAMCORDER_ATTR_NONE,
+ "Brightness",
+ MM_CAMCONVERT_TYPE_INT_RANGE,
+ NULL,
+ },
+ {
+ CONFIGURE_TYPE_CTRL,
+ CONFIGURE_CATEGORY_CTRL_EFFECT,
+ MM_CAM_FILTER_CONTRAST,
+ MM_CAMCORDER_ATTR_NONE,
+ "Contrast",
+ MM_CAMCONVERT_TYPE_INT_RANGE,
+ NULL,
+ },
+ {
+ CONFIGURE_TYPE_CTRL,
+ CONFIGURE_CATEGORY_CTRL_EFFECT,
+ MM_CAM_FILTER_SATURATION,
+ MM_CAMCORDER_ATTR_NONE,
+ "Saturation",
+ MM_CAMCONVERT_TYPE_INT_RANGE,
+ NULL,
+ },
+ {
+ CONFIGURE_TYPE_CTRL,
+ CONFIGURE_CATEGORY_CTRL_EFFECT,
+ MM_CAM_FILTER_HUE,
+ MM_CAMCORDER_ATTR_NONE,
+ "Hue",
+ MM_CAMCONVERT_TYPE_INT_RANGE,
+ NULL,
+ },
+ {
+ CONFIGURE_TYPE_CTRL,
+ CONFIGURE_CATEGORY_CTRL_EFFECT,
+ MM_CAM_FILTER_SHARPNESS,
+ MM_CAMCORDER_ATTR_NONE,
+ "Sharpness",
+ MM_CAMCONVERT_TYPE_INT_RANGE,
+ NULL,
+ },
+ {
+ CONFIGURE_TYPE_CTRL,
+ CONFIGURE_CATEGORY_CTRL_EFFECT,
+ MM_CAM_FILTER_WB,
+ MM_CAMCORDER_ATTR_NONE,
+ "WhiteBalance",
+ MM_CAMCONVERT_TYPE_INT_ARRAY,
+ &_mmcamcorder_enum_conv_whitebalance,
+ },
+ {
+ CONFIGURE_TYPE_CTRL,
+ CONFIGURE_CATEGORY_CTRL_EFFECT,
+ MM_CAM_FILTER_COLOR_TONE,
+ MM_CAMCORDER_ATTR_NONE,
+ "ColorTone",
+ MM_CAMCONVERT_TYPE_INT_ARRAY,
+ &_mmcamcorder_enum_conv_colortone,
+ },
+ {
+ CONFIGURE_TYPE_CTRL,
+ CONFIGURE_CATEGORY_CTRL_EFFECT,
+ MM_CAM_CAMERA_WDR,
+ MM_CAMCORDER_ATTR_NONE,
+ "WDR",
+ MM_CAMCONVERT_TYPE_INT_ARRAY,
+ &_mmcamcorder_enum_conv_wdr_ctrl,
+ },
+ {
+ CONFIGURE_TYPE_CTRL,
+ CONFIGURE_CATEGORY_CTRL_PHOTOGRAPH,
+ MM_CAM_CAMERA_DIGITAL_ZOOM,
+ MM_CAMCORDER_ATTR_NONE,
+ "DigitalZoom",
+ MM_CAMCONVERT_TYPE_INT_RANGE,
+ NULL,
+ },
+ {
+ CONFIGURE_TYPE_CTRL,
+ CONFIGURE_CATEGORY_CTRL_PHOTOGRAPH,
+ MM_CAM_CAMERA_OPTICAL_ZOOM,
+ MM_CAMCORDER_ATTR_NONE,
+ "OpticalZoom",
+ MM_CAMCONVERT_TYPE_INT_RANGE,
+ NULL,
+ },
+ {
+ CONFIGURE_TYPE_CTRL,
+ CONFIGURE_CATEGORY_CTRL_PHOTOGRAPH,
+ MM_CAM_CAMERA_FOCUS_MODE,
+ MM_CAMCORDER_ATTR_NONE,
+ "FocusMode",
+ MM_CAMCONVERT_TYPE_INT_ARRAY,
+ &_mmcamcorder_enum_conv_focus_mode,
+ },
+ {
+ CONFIGURE_TYPE_CTRL,
+ CONFIGURE_CATEGORY_CTRL_PHOTOGRAPH,
+ MM_CAM_CAMERA_AF_SCAN_RANGE,
+ MM_CAMCORDER_ATTR_NONE,
+ "AFType",
+ MM_CAMCONVERT_TYPE_INT_ARRAY,
+ &_mmcamcorder_enum_conv_focus_type,
+ },
+ {
+ CONFIGURE_TYPE_CTRL,
+ CONFIGURE_CATEGORY_CTRL_PHOTOGRAPH,
+ MM_CAM_CAMERA_EXPOSURE_MODE,
+ MM_CAMCORDER_ATTR_NONE,
+ "AEType",
+ MM_CAMCONVERT_TYPE_INT_ARRAY,
+ &_mmcamcorder_enum_conv_ae_type,
+ },
+ {
+ CONFIGURE_TYPE_CTRL,
+ CONFIGURE_CATEGORY_CTRL_PHOTOGRAPH,
+ MM_CAM_CAMERA_EXPOSURE_VALUE,
+ MM_CAMCORDER_ATTR_NONE,
+ "ExposureValue",
+ MM_CAMCONVERT_TYPE_INT_RANGE,
+ NULL,
+ },
+ {
+ CONFIGURE_TYPE_CTRL,
+ CONFIGURE_CATEGORY_CTRL_PHOTOGRAPH,
+ MM_CAM_CAMERA_F_NUMBER,
+ MM_CAMCORDER_ATTR_NONE,
+ "FNumber",
+ MM_CAMCONVERT_TYPE_INT_ARRAY,
+ NULL,
+ },
+ {
+ CONFIGURE_TYPE_CTRL,
+ CONFIGURE_CATEGORY_CTRL_PHOTOGRAPH,
+ MM_CAM_CAMERA_SHUTTER_SPEED,
+ MM_CAMCORDER_ATTR_NONE,
+ "ShutterSpeed",
+ MM_CAMCONVERT_TYPE_INT_ARRAY,
+ NULL,
+ },
+ {
+ CONFIGURE_TYPE_CTRL,
+ CONFIGURE_CATEGORY_CTRL_PHOTOGRAPH,
+ MM_CAM_CAMERA_ISO,
+ MM_CAMCORDER_ATTR_NONE,
+ "ISO",
+ MM_CAMCONVERT_TYPE_INT_ARRAY,
+ &_mmcamcorder_enum_conv_iso,
+ },
+ {
+ CONFIGURE_TYPE_CTRL,
+ CONFIGURE_CATEGORY_CTRL_PHOTOGRAPH,
+ MM_CAM_FILTER_SCENE_MODE,
+ MM_CAMCORDER_ATTR_NONE,
+ "ProgramMode",
+ MM_CAMCONVERT_TYPE_INT_ARRAY,
+ &_mmcamcorder_enum_conv_prgrm,
+ },
+ {
+ CONFIGURE_TYPE_CTRL,
+ CONFIGURE_CATEGORY_CTRL_PHOTOGRAPH,
+ MM_CAM_CAMERA_ANTI_HANDSHAKE,
+ MM_CAMCORDER_ATTR_NONE,
+ "AntiHandshake",
+ MM_CAMCONVERT_TYPE_INT_ARRAY,
+ &_mmcamcorder_enum_conv_ahs,
+ },
+ {
+ CONFIGURE_TYPE_CTRL,
+ CONFIGURE_CATEGORY_CTRL_CAPTURE,
+ MM_CAM_CAPTURE_FORMAT,
+ MM_CAMCORDER_ATTR_NONE,
+ "OutputMode",
+ MM_CAMCONVERT_TYPE_INT_ARRAY,
+ NULL,
+ },
+ {
+ CONFIGURE_TYPE_CTRL,
+ CONFIGURE_CATEGORY_CTRL_CAPTURE,
+ MM_CAM_IMAGE_ENCODER_QUALITY,
+ MM_CAMCORDER_ATTR_NONE,
+ "JpegQuality",
+ MM_CAMCONVERT_TYPE_INT_RANGE,
+ NULL,
+ },
+ {
+ CONFIGURE_TYPE_CTRL,
+ CONFIGURE_CATEGORY_CTRL_CAPTURE,
+ MM_CAM_CAPTURE_COUNT,
+ MM_CAMCORDER_ATTR_NONE,
+ "MultishotNumber",
+ MM_CAMCONVERT_TYPE_INT_RANGE,
+ NULL,
+ },
+ {
+ CONFIGURE_TYPE_CTRL,
+ CONFIGURE_CATEGORY_CTRL_DETECT,
+ MM_CAM_DETECT_MODE,
+ MM_CAMCORDER_ATTR_NONE,
+ "DetectMode",
+ MM_CAMCONVERT_TYPE_INT_ARRAY,
+ NULL,
+ },
+ {
+ CONFIGURE_TYPE_CTRL,
+ CONFIGURE_CATEGORY_CTRL_DETECT,
+ MM_CAM_DETECT_NUMBER,
+ MM_CAMCORDER_ATTR_NONE,
+ "DetectNumber",
+ MM_CAMCONVERT_TYPE_INT_RANGE,
+ NULL,
+ },
+ {
+ CONFIGURE_TYPE_CTRL,
+ CONFIGURE_CATEGORY_CTRL_DETECT,
+ MM_CAM_DETECT_FOCUS_SELECT,
+ MM_CAMCORDER_ATTR_NONE,
+ "DetectFocusSelect",
+ MM_CAMCONVERT_TYPE_INT_RANGE,
+ NULL,
+ },
+ {
+ CONFIGURE_TYPE_CTRL,
+ CONFIGURE_CATEGORY_CTRL_DETECT,
+ MM_CAM_DETECT_SELECT_NUMBER,
+ MM_CAMCORDER_ATTR_NONE,
+ "DetectSelectNumber",
+ MM_CAMCONVERT_TYPE_INT_RANGE,
+ NULL,
+ },
+ {
+ CONFIGURE_TYPE_CTRL,
+ CONFIGURE_CATEGORY_CTRL_DETECT,
+ MM_CAM_DETECT_STATUS,
+ MM_CAMCORDER_ATTR_NONE,
+ "DetectStatus",
+ MM_CAMCONVERT_TYPE_INT_ARRAY,
+ NULL,
+ },
+};
+
+/*---------------------------------------------------------------------------
+| LOCAL FUNCTION PROTOTYPES: |
+---------------------------------------------------------------------------*/
+/* STATIC INTERNAL FUNCTION */
+static int __mmcamcorder_set_info_to_attr( MMHandleType handle, _MMCamcorderInfoConverting *info, int table_size );
+static int __mmcamcorder_get_valid_array(int * original_array, int original_count, int ** valid_array, int * valid_default );
+
+/*===========================================================================================
+| |
+| FUNCTION DEFINITIONS |
+| |
+========================================================================================== */
+/*---------------------------------------------------------------------------
+| GLOBAL FUNCTION DEFINITIONS: |
+---------------------------------------------------------------------------*/
+//convert MSL value to sensor value
+int _mmcamcorder_convert_msl_to_sensor( int attr_idx, int mslval )
+{
+ _MMCamcorderInfoConverting *info = NULL;
+ int i =0;
+ int size = sizeof(g_caminfo_convert) / sizeof(_MMCamcorderInfoConverting);
+
+ //_mmcam_dbg_log("attr_idx(%d), mslval(%d)", attr_idx, mslval);
+
+ info = g_caminfo_convert;
+
+ for (i = 0; i < size; i++)
+ {
+ if (info[i].attr_idx == attr_idx)
+ {
+ _MMCamcorderEnumConvert * enum_convert = NULL;
+ enum_convert = info[i].enum_convert;
+
+ if (enum_convert == NULL)
+ {
+ //_mmcam_dbg_log("enum_convert is NULL. Just return the original value.");
+ return mslval;
+ }
+
+ if (enum_convert->enum_arr == NULL)
+ {
+ _mmcam_dbg_warn("Unexpected error. Array pointer of enum_convert is NULL. Just return the original value.");
+ return mslval;
+ }
+
+ if( enum_convert->total_enum_num > mslval && mslval >= 0 )
+ {
+ //_mmcam_dbg_log("original value(%d) -> converted value(%d)", mslval, enum_convert->enum_arr[mslval]);
+ return enum_convert->enum_arr[mslval];
+ }
+ else
+ {
+ _mmcam_dbg_warn( "Input mslval[%d] is invalid(out of array[idx:%d,size:%d]), so can not convert. Just return the original value.", mslval, attr_idx, enum_convert->total_enum_num );
+ return mslval;
+ }
+ }
+ }
+
+ _mmcam_dbg_warn("There is no category to match. Just return the original value.");
+ return mslval;
+}
+
+//convert sensor value to MSL value
+int _mmcamcorder_convert_sensor_to_msl(int attr_idx, int sensval)
+{
+ int i = 0, j = 0;
+ int size = sizeof(g_caminfo_convert) / sizeof(_MMCamcorderInfoConverting);
+
+ _MMCamcorderInfoConverting *info = NULL;
+
+ info = g_caminfo_convert;
+
+ for( i = 0 ; i < size ; i++ )
+ {
+ if( info[i].attr_idx == attr_idx )
+ {
+ _MMCamcorderEnumConvert * enum_convert = NULL;
+ enum_convert = info[i].enum_convert;
+
+ if( enum_convert == NULL )
+ {
+ //_mmcam_dbg_log("enum_convert is NULL. Just return the original value.");
+ return sensval;
+ }
+
+ if( enum_convert->enum_arr == NULL )
+ {
+ _mmcam_dbg_warn("Unexpected error. Array pointer of enum_convert is NULL. Just return the original value.");
+ return sensval;
+ }
+
+ for( j = 0 ; j < enum_convert->total_enum_num ; j++ )
+ {
+ if( sensval == enum_convert->enum_arr[j] )
+ {
+ //_mmcam_dbg_log("original value(%d) -> converted value(%d)", sensval, j);
+ return j;
+ }
+ }
+
+ _mmcam_dbg_warn("There is no sensor value matched with input param. Just return the original value.");
+ return sensval;
+
+ }
+ }
+
+ _mmcam_dbg_log("There is no category to match. Just return the original value.");
+ return sensval;
+}
+
+static int
+__mmcamcorder_get_valid_array(int * original_array, int original_count, int ** valid_array, int * valid_default )
+{
+ 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++;
+ }
+
+ if (valid_count > 0)
+ {
+ *valid_array = (int*)malloc(sizeof(int) * valid_count);
+
+ valid_count = 0;
+ for (i = 0; i < original_count; i++)
+ {
+ if (original_array[i] != _MMCAMCORDER_SENSOR_ENUM_NONE)
+ {
+ (*valid_array)[valid_count++] = i;
+ //_mmcam_dbg_log( "valid_array[%d] = %d", valid_count-1, (*valid_array)[valid_count-1] );
+
+ if( original_array[i] == *valid_default )
+ {
+ new_default = i;
+ //_mmcam_dbg_log( "converted MSL default[%d]", new_default );
+ }
+ }
+ }
+ }
+
+ if( new_default != _MMCAMCORDER_SENSOR_ENUM_NONE )
+ {
+ *valid_default = new_default;
+ }
+
+ return valid_count;
+}
+
+
+int _mmcamcorder_init_attr_from_configure(MMHandleType handle)
+{
+ _MMCamcorderInfoConverting *info = NULL;
+
+ int table_size = 0;
+ int ret = MM_ERROR_NONE;
+
+ _mmcam_dbg_log("");
+
+ /* Initialize attribute related to camera control */
+ info = g_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 );
+ 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 );
+
+ return ret;
+}
+
+static int
+__mmcamcorder_set_info_to_attr( MMHandleType handle, _MMCamcorderInfoConverting *info, int table_size )
+{
+ mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
+ MMHandleType attrs = 0;
+
+ int i;
+
+ mmf_return_val_if_fail(hcamcorder, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
+
+ attrs = MMF_CAMCORDER_ATTRS (handle);
+ mmf_return_val_if_fail(attrs, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
+
+ camera_conf *conf_info = NULL;
+
+ for (i = 0; i < table_size ; i++ )
+ {
+ int ret = MM_ERROR_NONE;
+
+ /*
+ _mmcam_dbg_log( "%d,%d,%d,%d,%s,%d",
+ info[i].type,
+ info[i].category,
+ info[i].attr_idx,
+ info[i].attr_idx_sub,
+ info[i].keyword,
+ info[i].conv_type );
+ */
+
+ if( info[i].type == CONFIGURE_TYPE_MAIN )
+ {
+ conf_info = hcamcorder->conf_main;
+ _mmcam_dbg_log( "MAIN configure [%s]", info[i].keyword );
+ }
+ else
+ {
+ conf_info = hcamcorder->conf_ctrl;
+ _mmcam_dbg_log( "CTRL configure [%s]", info[i].keyword );
+ }
+
+ switch(info[i].conv_type)
+ {
+ case MM_CAMCONVERT_TYPE_INT:
+ {
+ int iarray = (int)NULL;
+
+ if (!_mmcamcorder_conf_get_value_int( conf_info, info[i].category, info[i].keyword, &iarray ))
+ {
+ ret = MM_ERROR_CAMCORDER_CREATE_CONFIGURE;
+ break; //skip to set
+ }
+
+ ret = mm_attrs_set_int(MMF_CAMCORDER_ATTRS(hcamcorder), info[i].attr_idx, iarray);
+
+ //_mmcam_dbg_log("INT . m:%d, s:%d, arr=%d", info[i].main_key, info[i].sub_key1, iarray);
+ break;
+ }
+ case MM_CAMCONVERT_TYPE_INT_ARRAY:
+ {
+ int *iarray = NULL;
+ int iarray_size = 0;
+ int idefault = 0;
+ type_int_array *tarray = NULL;
+
+ if (!_mmcamcorder_conf_get_value_int_array( conf_info, info[i].category, info[i].keyword, &tarray ))
+ {
+ ret = MM_ERROR_CAMCORDER_CREATE_CONFIGURE;
+ break; //skip to set
+ }
+
+ if( tarray )
+ {
+ idefault = tarray->default_value;
+
+ if( info[i].enum_convert )
+ {
+ iarray_size = __mmcamcorder_get_valid_array(tarray->value, tarray->count, &iarray, &idefault);
+ }
+ else
+ {
+ iarray = tarray->value;
+ iarray_size = tarray->count;
+ }
+
+ if( iarray_size > 0 )
+ {
+ /*
+ _mmcam_dbg_log("INT Array. m:%d, s:%d, arr=%x, size=%d, default=%d",
+ info[i].main_key, info[i].sub_key1, iarray, iarray_size, idefault);
+ */
+
+ mmf_attrs_set_valid_type (attrs, info[i].attr_idx, MM_ATTRS_VALID_TYPE_INT_ARRAY);
+ mmf_attrs_set_valid_array (attrs, info[i].attr_idx, iarray, iarray_size);
+ }
+
+ ret = mm_attrs_set_int(MMF_CAMCORDER_ATTRS(hcamcorder), info[i].attr_idx, idefault);
+ }
+
+ if (iarray && iarray != tarray->value )
+ free(iarray);
+
+ break;
+ }
+ case MM_CAMCONVERT_TYPE_INT_RANGE:
+ {
+ type_int_range *irange = NULL;
+
+ if (!_mmcamcorder_conf_get_value_int_range(conf_info, info[i].category, info[i].keyword, &irange))
+ {
+ ret = MM_ERROR_CAMCORDER_CREATE_CONFIGURE;
+ break; //skip to set
+ }
+
+ if( irange )
+ {
+ //_mmcam_dbg_log("INT Range. m:%d, s:%d, min=%d, max=%d", info[i].main_key, info[i].sub_key1, irange->min, irange->max);
+
+ mmf_attrs_set_valid_type (attrs, info[i].attr_idx, MM_ATTRS_VALID_TYPE_INT_RANGE);
+ mmf_attrs_set_valid_range(attrs, info[i].attr_idx, irange->min, irange->max);
+
+ ret = mm_attrs_set_int(MMF_CAMCORDER_ATTRS(hcamcorder), info[i].attr_idx, irange->default_value);
+ }
+
+ break;
+ }
+ case MM_CAMCONVERT_TYPE_STRING:
+ {
+ char* cString = NULL;
+ unsigned int iString_len = 0;
+
+ if (!_mmcamcorder_conf_get_value_string(conf_info, info[i].category, info[i].keyword, &cString ))
+ {
+ ret = MM_ERROR_CAMCORDER_CREATE_CONFIGURE;
+ break; //skip to set
+ }
+
+ //_mmcam_dbg_log("String. m:%d, s:%d, cString=%s", info[i].main_key, info[i].sub_key1, cString);
+ //strlen makes a crash when null pointer is passed.
+ if (cString)
+ iString_len = strlen(cString);
+ else
+ iString_len = 0;
+
+ ret = mm_attrs_set_string(attrs, info[i].attr_idx, cString, iString_len);
+ break;
+ }
+ case MM_CAMCONVERT_TYPE_INT_PAIR_ARRAY:
+ {
+ 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);
+
+ if (!_mmcamcorder_conf_get_value_int_pair_array(conf_info, info[i].category, info[i].keyword, &pair_array))
+ {
+ ret = MM_ERROR_CAMCORDER_CREATE_CONFIGURE;
+ break; //skip to set
+ }
+
+ if( pair_array && pair_array->count > 0 )
+ {
+ mmf_attrs_set_valid_type (attrs, info[i].attr_idx, MM_ATTRS_VALID_TYPE_INT_ARRAY);
+ mmf_attrs_set_valid_array (attrs, info[i].attr_idx, pair_array->value[0], pair_array->count);
+ mmf_attrs_set_valid_type (attrs, info[i].attr_idx_pair, MM_ATTRS_VALID_TYPE_INT_ARRAY);
+ mmf_attrs_set_valid_array (attrs, info[i].attr_idx_pair, pair_array->value[1], pair_array->count);
+
+ mm_attrs_set_int(MMF_CAMCORDER_ATTRS(hcamcorder), info[i].attr_idx, pair_array->default_value[0]);
+ mm_attrs_set_int(MMF_CAMCORDER_ATTRS(hcamcorder), info[i].attr_idx_pair, pair_array->default_value[1]);
+ }
+ break;
+ }
+
+ case MM_CAMCONVERT_TYPE_USER:
+ default:
+ _mmcam_dbg_log("default : s:%d", info[i].attr_idx);
+ break;
+ }
+
+ if (ret != MM_ERROR_NONE)
+ {
+ _mmcam_dbg_warn("Setting error. ( s:%d, ret:%x)", info[i].attr_idx, ret);
+ }
+ }
+
+ if (mmf_attrs_commit(attrs) == -1)
+ return MM_ERROR_CAMCORDER_INVALID_ARGUMENT;
+ else
+ return MM_ERROR_NONE;
+}
+
+
+int _mmcamcorder_set_converted_value(MMHandleType handle, _MMCamcorderEnumConvert * convert)
+{
+ mmf_camcorder_t* hcamcorder = MMF_CAMCORDER(handle);
+ type_int_array *array = NULL;
+
+ mmf_return_val_if_fail(hcamcorder, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
+
+ _mmcamcorder_conf_get_value_int_array( hcamcorder->conf_ctrl, convert->category, convert->keyword, &array );
+
+ if( array )
+ {
+ convert->enum_arr = array->value;
+ }
+
+ return MM_ERROR_NONE;
+}
+
+
+int _mmcamcorder_init_convert_table(MMHandleType handle)
+{
+ mmf_return_val_if_fail(handle, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
+
+ _mmcamcorder_set_converted_value(handle, &_mmcamcorder_enum_conv_whitebalance);
+ _mmcamcorder_set_converted_value(handle, &_mmcamcorder_enum_conv_colortone);
+ _mmcamcorder_set_converted_value(handle, &_mmcamcorder_enum_conv_iso);
+ _mmcamcorder_set_converted_value(handle, &_mmcamcorder_enum_conv_prgrm);
+ _mmcamcorder_set_converted_value(handle, &_mmcamcorder_enum_conv_focus_mode);
+ _mmcamcorder_set_converted_value(handle, &_mmcamcorder_enum_conv_focus_type);
+ _mmcamcorder_set_converted_value(handle, &_mmcamcorder_enum_conv_ae_type);
+// _mmcamcorder_set_converted_value(handle, &_mmcamcorder_enum_conv_pcolor_mode);
+// _mmcamcorder_set_converted_value(handle, &_mmcamcorder_enum_conv_flip);
+// _mmcamcorder_set_converted_value(handle, &_mmcamcorder_enum_conv_pcolor);
+ _mmcamcorder_set_converted_value(handle, &_mmcamcorder_enum_conv_strobe_mode);
+ _mmcamcorder_set_converted_value(handle, &_mmcamcorder_enum_conv_wdr_ctrl);
+ _mmcamcorder_set_converted_value(handle, &_mmcamcorder_enum_conv_ahs);
+// _mmcamcorder_set_converted_value(handle, &_mmcamcorder_enum_conv_picture_format);
+
+ return MM_ERROR_NONE;
+}
+
+
+double _mmcamcorder_convert_volume(int mslVal)
+{
+ double newVal = -1;
+ switch (mslVal)
+ {
+ case 0:
+ newVal = 0;
+ break;
+ case 1:
+ newVal = 1;
+ break;
+ default:
+ _mmcam_dbg_warn("out of range");
+ break;
+ }
+
+ return newVal;
+}
+
+
+
diff --git a/src/mm_camcorder_sound.c b/src/mm_camcorder_sound.c
new file mode 100644
index 0000000..c582349
--- /dev/null
+++ b/src/mm_camcorder_sound.c
@@ -0,0 +1,491 @@
+/*
+ * libmm-camcorder
+ *
+ * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: Jeongmo Yang <jm80.yang@samsung.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+/*=======================================================================================
+| INCLUDE FILES |
+=======================================================================================*/
+#include <mm_sound.h>
+#include <mm_sound_private.h>
+#include <audio-session-manager.h>
+#include "mm_camcorder_internal.h"
+#include "mm_camcorder_sound.h"
+
+/*---------------------------------------------------------------------------------------
+| GLOBAL VARIABLE DEFINITIONS for internal |
+---------------------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------------------
+| LOCAL VARIABLE DEFINITIONS for internal |
+---------------------------------------------------------------------------------------*/
+#define BLOCK_SIZE 2048
+
+/*---------------------------------------------------------------------------------------
+| LOCAL FUNCTION PROTOTYPES: |
+---------------------------------------------------------------------------------------*/
+static gboolean __prepare_buffer(SOUND_INFO *info, char *filename);
+static gboolean __cleanup_buffer(SOUND_INFO *info);
+static void *__sound_open_thread_func(void *data);
+static void *__sound_write_thread_func(void *data);
+static void __solo_sound_callback(void *data);
+
+static gboolean __prepare_buffer(SOUND_INFO *info, char *filename)
+{
+ mmf_return_val_if_fail(info, FALSE);
+ mmf_return_val_if_fail(filename, FALSE);
+
+ info->infile = sf_open(filename, SFM_READ, &info->sfinfo);
+ if (!(info->infile)) {
+ _mmcam_dbg_err("failed to open file [%s]", filename);
+ return FALSE;
+ }
+
+ _mmcam_dbg_log("SOUND: frame = %lld", info->sfinfo.frames);
+ _mmcam_dbg_log("SOUND: sameplerate = %d", info->sfinfo.samplerate);
+ _mmcam_dbg_log("SOUND: channel = %d", info->sfinfo.channels);
+ _mmcam_dbg_log("SOUND: format = 0x%x", info->sfinfo.format);
+
+ info->pcm_size = info->sfinfo.frames * info->sfinfo.channels * 2;
+ info->pcm_buf = (short *)malloc(info->pcm_size);
+ if (info->pcm_buf == NULL) {
+ _mmcam_dbg_err("pcm_buf malloc failed");
+ sf_close(info->infile);
+ info->infile = NULL;
+ return FALSE;
+ }
+ sf_read_short(info->infile, info->pcm_buf, info->pcm_size);
+
+ return TRUE;
+}
+
+
+static gboolean __cleanup_buffer(SOUND_INFO *info)
+{
+ mmf_return_val_if_fail(info, FALSE);
+
+ if (info->infile) {
+ sf_close(info->infile);
+ info->infile = NULL;
+ }
+
+ if (info->pcm_buf) {
+ free(info->pcm_buf);
+ info->pcm_buf = NULL;
+ }
+
+ _mmcam_dbg_log("Done");
+
+ return TRUE;
+}
+
+
+static void *__sound_open_thread_func(void *data)
+{
+ int ret = 0;
+ system_audio_route_t route = SYSTEM_AUDIO_ROUTE_POLICY_HANDSET_ONLY;
+ SOUND_INFO *info = NULL;
+ mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(data);
+
+ mmf_return_val_if_fail(hcamcorder, NULL);
+
+ MMTA_ACUM_ITEM_BEGIN(" __sound_open_thread_func", FALSE);
+
+ info = &(hcamcorder->snd_info);
+
+ __ta__(" __prepare_buffer",
+ ret = __prepare_buffer(info, info->filename);
+ );
+ if (ret == FALSE) {
+ goto EXIT_FUNC;
+ }
+
+ __ta__(" mm_sound_pcm_play_open",
+ ret = mm_sound_pcm_play_open_ex(&(info->handle), info->sfinfo.samplerate,
+ (info->sfinfo.channels == 1) ? MMSOUND_PCM_MONO : MMSOUND_PCM_STEREO,
+ MMSOUND_PCM_S16_LE, VOLUME_TYPE_FIXED, ASM_EVENT_EXCLUSIVE_MMSOUND);
+ );
+ if (ret < 0) {
+ /* error */
+ _mmcam_dbg_err("mm_sound_pcm_play_open failed [%x]", ret);
+ __cleanup_buffer(info);
+ goto EXIT_FUNC;
+ } else {
+ /* success */
+ info->state = _MMCAMCORDER_SOUND_STATE_PREPARE;
+ _mmcam_dbg_log("mm_sound_pcm_play_open succeeded. state [%d]", info->state);
+ }
+
+ ret = mm_sound_route_get_system_policy(&route);
+ if (ret != MM_ERROR_NONE) {
+ _mmcam_dbg_err("mm_sound_route_get_system_policy failed [%x]", ret);
+ goto POLICY_ERROR;
+ }
+
+ _mmcam_dbg_log("current policy [%d]", route);
+
+ if (route != SYSTEM_AUDIO_ROUTE_POLICY_HANDSET_ONLY) {
+ ret = mm_sound_route_set_system_policy(SYSTEM_AUDIO_ROUTE_POLICY_HANDSET_ONLY);
+ if (ret != MM_ERROR_NONE) {
+ _mmcam_dbg_err("mm_sound_route_set_system_policy failed [%x]", ret);
+ goto POLICY_ERROR;
+ }
+
+ info->route_policy_backup = route;
+ }
+
+EXIT_FUNC:
+ pthread_cond_signal(&(info->open_cond));
+ pthread_mutex_unlock(&(info->open_mutex));
+
+ _mmcam_dbg_log("Done");
+
+ MMTA_ACUM_ITEM_END(" __sound_open_thread_func", FALSE);
+
+ return NULL;
+
+POLICY_ERROR:
+ pthread_mutex_unlock(&(info->open_mutex));
+ _mmcamcorder_sound_finalize((MMHandleType)hcamcorder);
+
+ return NULL;
+}
+
+
+static void *__sound_write_thread_func(void *data)
+{
+ int ret = 0;
+ int bytes_to_write = 0;
+ int remain_bytes = 0;
+ system_audio_route_t route = SYSTEM_AUDIO_ROUTE_POLICY_HANDSET_ONLY;
+ char *buffer_to_write = NULL;
+ SOUND_INFO *info = NULL;
+ mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(data);
+
+ mmf_return_val_if_fail(hcamcorder, NULL);
+
+ info = &(hcamcorder->snd_info);
+
+ _mmcam_dbg_log("RUN sound write thread");
+
+ pthread_mutex_lock(&(info->play_mutex));
+
+ do {
+ pthread_cond_wait(&(info->play_cond), &(info->play_mutex));
+
+ _mmcam_dbg_log("Signal received. Play sound.");
+
+ if (info->thread_run == FALSE) {
+ _mmcam_dbg_log("Exit thread command is detected");
+ break;
+ }
+
+ ret = mm_sound_route_get_system_policy(&route);
+ if (ret != MM_ERROR_NONE) {
+ _mmcam_dbg_err("get_system_policy failed [%x]. skip sound play.", ret);
+ break;
+ }
+
+ _mmcam_dbg_log("current policy [%d]", route);
+
+ if (route != SYSTEM_AUDIO_ROUTE_POLICY_HANDSET_ONLY) {
+ ret = mm_sound_route_set_system_policy(SYSTEM_AUDIO_ROUTE_POLICY_HANDSET_ONLY);
+ if (ret != MM_ERROR_NONE) {
+ _mmcam_dbg_err("set_system_policy failed. skip sound play.");
+ break;
+ }
+
+ info->route_policy_backup = route;
+ }
+
+ buffer_to_write = (char *)info->pcm_buf;
+ remain_bytes = info->pcm_size;
+ bytes_to_write = 0;
+
+ while (remain_bytes) {
+ bytes_to_write = (remain_bytes >= BLOCK_SIZE) ? BLOCK_SIZE : remain_bytes;
+ ret = mm_sound_pcm_play_write(info->handle, buffer_to_write, bytes_to_write);
+ if (ret != bytes_to_write) {
+ _mmcam_dbg_err("pcm write error [%x]", ret);
+ }
+ remain_bytes -= bytes_to_write;
+ buffer_to_write += bytes_to_write;
+ }
+ } while (TRUE);
+
+ pthread_mutex_unlock(&(info->play_mutex));
+
+ _mmcam_dbg_log("END sound write thread");
+
+ return NULL;
+}
+
+
+gboolean _mmcamcorder_sound_init(MMHandleType handle, char *filename)
+{
+ int ret = 0;
+ mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
+ SOUND_INFO *info = NULL;
+
+ mmf_return_val_if_fail(hcamcorder, FALSE);
+
+ info = &(hcamcorder->snd_info);
+
+ pthread_mutex_lock(&(info->open_mutex));
+
+ if (info->state > _MMCAMCORDER_SOUND_STATE_NONE) {
+ _mmcam_dbg_warn("already initialized [%d]", info->state);
+ pthread_mutex_unlock(&(info->open_mutex));
+ return FALSE;
+ }
+
+ if (info->filename) {
+ free(info->filename);
+ info->filename = NULL;
+ }
+
+ info->filename = strdup(filename);
+ if (info->filename == NULL) {
+ _mmcam_dbg_err("strdup failed");
+ ret = FALSE;
+ } else {
+ pthread_mutex_init(&(info->play_mutex), NULL);
+ pthread_cond_init(&(info->play_cond), NULL);
+ if (pthread_create(&(info->thread), NULL, __sound_write_thread_func, (void *)handle) == 0) {
+ info->thread_run = TRUE;
+ info->state = _MMCAMCORDER_SOUND_STATE_INIT;
+ info->route_policy_backup = -1;
+ _mmcam_dbg_log("write thread created");
+ ret = TRUE;
+ } else {
+ _mmcam_dbg_err("failed to create write thread");
+ free(info->filename);
+ info->filename = NULL;
+ ret = FALSE;
+ }
+ }
+
+ pthread_mutex_unlock(&(info->open_mutex));
+
+ return ret;
+}
+
+
+gboolean _mmcamcorder_sound_prepare(MMHandleType handle)
+{
+ int ret = FALSE;
+ pthread_t open_thread;
+ mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
+ SOUND_INFO *info = NULL;
+
+ mmf_return_val_if_fail(hcamcorder, FALSE);
+
+ info = &(hcamcorder->snd_info);
+
+ pthread_mutex_lock(&(info->open_mutex));
+
+ if (info->state == _MMCAMCORDER_SOUND_STATE_INIT) {
+ if (pthread_create(&open_thread, NULL, __sound_open_thread_func, (void *)handle) == 0) {
+ _mmcam_dbg_log("open thread created");
+ ret = TRUE;
+ } else {
+ _mmcam_dbg_err("failed to create open thread");
+ ret = FALSE;
+ pthread_mutex_unlock(&(info->open_mutex));
+ }
+ } else {
+ _mmcam_dbg_warn("Wrong state [%d]", info->state);
+ ret = FALSE;
+ pthread_mutex_unlock(&(info->open_mutex));
+ }
+
+ return ret;
+}
+
+
+gboolean _mmcamcorder_sound_play(MMHandleType handle)
+{
+ mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
+ SOUND_INFO *info = NULL;
+
+ mmf_return_val_if_fail(hcamcorder, FALSE);
+
+ info = &(hcamcorder->snd_info);
+
+ pthread_mutex_lock(&(info->open_mutex));
+
+ if (info->state < _MMCAMCORDER_SOUND_STATE_PREPARE) {
+ _mmcam_dbg_log("not initialized state:[%d]", info->state);
+ pthread_mutex_unlock(&(info->open_mutex));
+ return FALSE;
+ }
+
+ _mmcam_dbg_log("Play start");
+
+ pthread_mutex_lock(&(info->play_mutex));
+ pthread_cond_signal(&(info->play_cond));
+ pthread_mutex_unlock(&(info->play_mutex));
+
+ pthread_mutex_unlock(&(info->open_mutex));
+
+ _mmcam_dbg_log("Done");
+
+ return TRUE;
+}
+
+
+gboolean _mmcamcorder_sound_finalize(MMHandleType handle)
+{
+ mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
+ SOUND_INFO *info = NULL;
+
+ mmf_return_val_if_fail(hcamcorder, FALSE);
+
+ info = &(hcamcorder->snd_info);
+
+ pthread_mutex_lock(&(info->open_mutex));
+
+ if (info->state < _MMCAMCORDER_SOUND_STATE_INIT) {
+ _mmcam_dbg_warn("not initialized");
+ pthread_mutex_unlock(&(info->open_mutex));
+ return FALSE;
+ }
+
+ info->thread_run = 0;
+ pthread_cond_signal(&(info->play_cond));
+
+ if (info->thread) {
+ _mmcam_dbg_log("wait for sound write thread join");
+ pthread_join(info->thread, NULL);
+ _mmcam_dbg_log("join done");
+ }
+
+ if (info->state == _MMCAMCORDER_SOUND_STATE_PREPARE) {
+ _mmcam_dbg_log("restore route policy [%d]", info->route_policy_backup);
+
+ if (info->route_policy_backup != -1) {
+ mm_sound_route_set_system_policy(info->route_policy_backup);
+ }
+
+ mm_sound_pcm_play_close(info->handle);
+ __cleanup_buffer(info);
+ }
+
+ if (info->filename) {
+ free(info->filename);
+ info->filename = NULL;
+ }
+
+ info->state = _MMCAMCORDER_SOUND_STATE_NONE;
+ info->route_policy_backup = -1;
+
+ pthread_mutex_destroy(&(info->play_mutex));
+ pthread_cond_destroy(&(info->play_cond));
+
+ pthread_mutex_unlock(&(info->open_mutex));
+
+ _mmcam_dbg_log("Done");
+
+ return TRUE;
+}
+
+
+void _mmcamcorder_sound_solo_play(MMHandleType handle, const char* filepath, gboolean sync)
+{
+ mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
+
+ int sound_handle = 0;
+ int ret = 0;
+ int sound_enable = TRUE;
+
+ mmf_return_if_fail( filepath );
+
+ _mmcam_dbg_log( "START" );
+
+ ret = mm_camcorder_get_attributes((MMHandleType)hcamcorder, NULL,
+ "capture-sound-enable", &sound_enable,
+ NULL);
+ if (ret == MM_ERROR_NONE) {
+ if (sound_enable == FALSE) {
+ _mmcam_dbg_log("Capture sound DISABLED.");
+ return;
+ }
+ } else {
+ _mmcam_dbg_warn("capture-sound-enable get FAILED.[%x]", ret);
+ }
+
+ ret = pthread_mutex_trylock(&(hcamcorder->sound_lock));
+ if (ret != 0) {
+ _mmcam_dbg_warn("g_mutex_trylock failed.[%s]", strerror(ret));
+ return;
+ }
+
+ MMTA_ACUM_ITEM_BEGIN("CAPTURE SOUND:mm_sound_play_loud_solo_sound", FALSE);
+
+ ret = mm_sound_play_loud_solo_sound(filepath, VOLUME_TYPE_FIXED, __solo_sound_callback,
+ (void*)hcamcorder, &sound_handle);
+ if (ret != MM_ERROR_NONE) {
+ _mmcam_dbg_err( "Capture sound play FAILED.[%x]", ret );
+ } else {
+ if (sync) {
+ struct timespec timeout;
+ struct timeval tv;
+
+ gettimeofday( &tv, NULL );
+ timeout.tv_sec = tv.tv_sec + 2;
+ timeout.tv_nsec = tv.tv_usec * 1000;
+
+ _mmcam_dbg_log("Wait for signal");
+
+ if (!pthread_cond_timedwait(&(hcamcorder->sound_cond), &(hcamcorder->sound_lock), &timeout)) {
+ _mmcam_dbg_log("signal received.");
+ } else {
+ _mmcam_dbg_warn("capture sound play timeout.");
+ if (sound_handle > 0) {
+ mm_sound_stop_sound(sound_handle);
+ }
+ }
+ }
+ }
+
+ MMTA_ACUM_ITEM_END("CAPTURE SOUND:mm_sound_play_loud_solo_sound", FALSE);
+
+ pthread_mutex_unlock(&(hcamcorder->sound_lock));
+
+ _mmcam_dbg_log("DONE");
+
+ return;
+}
+
+static void __solo_sound_callback(void *data)
+{
+ mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(data);
+
+ mmf_return_if_fail(hcamcorder);
+
+ _mmcam_dbg_log("START");
+
+ _mmcam_dbg_log("Signal SEND");
+ pthread_cond_broadcast(&(hcamcorder->sound_cond));
+
+ _mmcam_dbg_log("DONE");
+
+ return;
+}
+
diff --git a/src/mm_camcorder_stillshot.c b/src/mm_camcorder_stillshot.c
new file mode 100644
index 0000000..f6ef4fe
--- /dev/null
+++ b/src/mm_camcorder_stillshot.c
@@ -0,0 +1,2815 @@
+/*
+ * libmm-camcorder
+ *
+ * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: Jeongmo Yang <jm80.yang@samsung.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+/*=======================================================================================
+| INCLUDE FILES |
+=======================================================================================*/
+#include <sys/time.h>
+#include <sys/times.h>
+#include <gst/interfaces/cameracontrol.h>
+#include "mm_camcorder_internal.h"
+#include "mm_camcorder_stillshot.h"
+#include "mm_camcorder_exifinfo.h"
+#include "mm_camcorder_exifdef.h"
+
+/*---------------------------------------------------------------------------------------
+| GLOBAL VARIABLE DEFINITIONS for internal |
+---------------------------------------------------------------------------------------*/
+#define EXIF_SET_ERR( return_type,tag_id) \
+ _mmcam_dbg_err("error=%x,tag=%x",return_type,tag_id); \
+ if (return_type == MM_ERROR_CAMCORDER_LOW_MEMORY) { \
+ goto exit; \
+ }
+
+/*---------------------------------------------------------------------------------------
+| LOCAL VARIABLE DEFINITIONS for internal |
+---------------------------------------------------------------------------------------*/
+
+
+/*---------------------------------------------------------------------------------------
+| LOCAL FUNCTION PROTOTYPES: |
+---------------------------------------------------------------------------------------*/
+/** STATIC INTERNAL FUNCTION **/
+/* Functions for JPEG capture without Encode bin */
+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);
+
+/* Functions for JPEG capture with Encode bin */
+int _mmcamcorder_image_cmd_capture_with_encbin(MMHandleType handle);
+int _mmcamcorder_image_cmd_preview_start_with_encbin(MMHandleType handle);
+int _mmcamcorder_image_cmd_preview_stop_with_encbin(MMHandleType handle);
+static gboolean __mmcamcorder_encodesink_handoff_callback(GstElement *fakesink, GstBuffer *buffer, GstPad *pad, gpointer u_data);
+
+/*=======================================================================================
+| FUNCTION DEFINITIONS |
+=======================================================================================*/
+
+/*---------------------------------------------------------------------------------------
+| GLOBAL FUNCTION DEFINITIONS: |
+---------------------------------------------------------------------------------------*/
+
+
+int _mmcamcorder_add_stillshot_pipeline(MMHandleType handle)
+{
+ int err = MM_ERROR_UNKNOWN;
+
+ GstPad *srcpad = NULL;
+ GstPad *sinkpad = NULL;
+
+ mmf_camcorder_t *hcamcorder= MMF_CAMCORDER(handle);
+ _MMCamcorderSubContext *sc = NULL;
+ _MMCamcorderImageInfo *info = NULL;
+
+ mmf_return_val_if_fail(hcamcorder, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
+
+ sc = MMF_CAMCORDER_SUBCONTEXT(handle);
+ mmf_return_val_if_fail(sc && sc->info && sc->element, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
+
+ info = sc->info;
+
+ _mmcam_dbg_log("");
+
+ //Create gstreamer element
+ //Check main pipeline
+ if (!sc->element[_MMCAMCORDER_MAIN_PIPE].gst) {
+ _mmcam_dbg_err( "Main Pipeline is not existed." );
+ err = MM_ERROR_CAMCORDER_RESOURCE_CREATION;
+ goto pipeline_creation_error;
+ }
+
+ _mmcamcorder_conf_get_value_int(hcamcorder->conf_main,
+ CONFIGURE_CATEGORY_MAIN_CAPTURE,
+ "UseEncodebin",
+ &sc->bencbin_capture);
+
+ if (sc->bencbin_capture) {
+ _mmcam_dbg_log("Using Encodebin for capturing");
+ __ta__(" _mmcamcorder_create_encodesink_bin",
+ err = _mmcamcorder_create_encodesink_bin((MMHandleType)hcamcorder);
+ );
+ if (err != MM_ERROR_NONE) {
+ return err;
+ }
+
+ gst_bin_add_many(GST_BIN(sc->element[_MMCAMCORDER_MAIN_PIPE].gst),
+ sc->element[_MMCAMCORDER_ENCSINK_BIN].gst,
+ NULL);
+
+ /* Link each element */
+ srcpad = gst_element_get_static_pad(sc->element[_MMCAMCORDER_VIDEOSRC_BIN].gst, "src1");
+ sinkpad = gst_element_get_static_pad(sc->element[_MMCAMCORDER_ENCSINK_BIN].gst, "image_sink0");
+ _MM_GST_PAD_LINK_UNREF(srcpad, sinkpad, err, element_link_error)
+
+ MMCAMCORDER_SIGNAL_CONNECT(sc->element[_MMCAMCORDER_ENCSINK_SINK].gst,
+ _MMCAMCORDER_HANDLER_STILLSHOT, "handoff",
+ G_CALLBACK(__mmcamcorder_encodesink_handoff_callback),
+ hcamcorder);
+ } else {
+ _mmcam_dbg_log("NOT using Encodebin for capturing");
+
+ /*set video source element*/
+ MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst, "signal-still-capture", TRUE);
+
+ MMCAMCORDER_SIGNAL_CONNECT(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst,
+ _MMCAMCORDER_HANDLER_STILLSHOT, "still-capture",
+ G_CALLBACK(__mmcamcorder_image_capture_cb),
+ hcamcorder);
+ }
+
+ return MM_ERROR_NONE;
+
+element_link_error:
+ if (sc->bencbin_capture) {
+ _mmcam_dbg_err("Link encodebin failed!");
+
+ if (sc->element[_MMCAMCORDER_ENCSINK_BIN].gst != NULL) {
+ int ret = MM_ERROR_NONE;
+
+ __ta__( " EncodeBin Set NULL",
+ ret = _mmcamcorder_gst_set_state(handle, sc->element[_MMCAMCORDER_ENCSINK_BIN].gst, GST_STATE_NULL);
+ );
+ if (ret != MM_ERROR_NONE) {
+ _mmcam_dbg_err("Faile to change encode bin state[%d]", ret);
+ /* Can't return here. */
+ /* return ret; */
+ }
+
+ gst_bin_remove(GST_BIN(sc->element[_MMCAMCORDER_MAIN_PIPE].gst),
+ sc->element[_MMCAMCORDER_ENCSINK_BIN].gst);
+
+ _mmcamcorder_remove_element_handle(handle, _MMCAMCORDER_ENCSINK_BIN, _MMCAMCORDER_ENCSINK_SINK);
+
+ _mmcam_dbg_log("Encodebin removed");
+ }
+ }
+
+ return MM_ERROR_CAMCORDER_GST_LINK;
+
+pipeline_creation_error:
+ return err;
+}
+
+
+int _mmcamcorder_remove_stillshot_pipeline(MMHandleType handle)
+{
+ mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
+ _MMCamcorderSubContext *sc = NULL;
+ _MMCamcorderImageInfo *info = NULL;
+
+ mmf_return_val_if_fail(hcamcorder, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
+
+ sc = MMF_CAMCORDER_SUBCONTEXT(handle);
+ mmf_return_val_if_fail(sc && sc->info && sc->element, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
+
+ info = sc->info;
+
+ _mmcam_dbg_log("");
+
+ /* Check pipeline */
+ if (sc->element[_MMCAMCORDER_MAIN_PIPE].gst) {
+ _mmcamcorder_remove_all_handlers(handle, _MMCAMCORDER_HANDLER_STILLSHOT);
+
+ if (sc->bencbin_capture) {
+ GstPad *srcpad = NULL, *sinkpad = NULL;
+ if (!sc->element[_MMCAMCORDER_ENCSINK_BIN].gst) {
+ _mmcam_dbg_log("ENCSINK_BIN is already removed");
+ } else {
+ /* Unlink each element */
+ srcpad = gst_element_get_static_pad(sc->element[_MMCAMCORDER_VIDEOSRC_BIN].gst, "src1");
+ sinkpad = gst_element_get_static_pad(sc->element[_MMCAMCORDER_ENCSINK_BIN].gst, "image_sink0");
+ _MM_GST_PAD_UNLINK_UNREF(srcpad, sinkpad);
+
+ gst_bin_remove(GST_BIN(sc->element[_MMCAMCORDER_MAIN_PIPE].gst),
+ sc->element[_MMCAMCORDER_ENCSINK_BIN].gst);
+
+ _mmcamcorder_remove_element_handle(handle, _MMCAMCORDER_ENCSINK_BIN, _MMCAMCORDER_ENCSINK_SINK);
+ }
+ }
+ } else {
+ _mmcam_dbg_log("MAIN_PIPE is already removed");
+ }
+
+ return MM_ERROR_NONE;
+}
+
+
+void _mmcamcorder_destroy_image_pipeline(MMHandleType handle)
+{
+ GstPad *reqpad1 = NULL;
+ GstPad *reqpad2 = NULL;
+
+ mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
+ _MMCamcorderSubContext *sc = NULL;
+
+ mmf_return_if_fail(hcamcorder);
+
+ sc = MMF_CAMCORDER_SUBCONTEXT(handle);
+ mmf_return_if_fail(sc && sc->element);
+
+ _mmcam_dbg_log("");
+
+ if (sc->element[_MMCAMCORDER_MAIN_PIPE].gst) {
+ 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_NULL);
+
+ _mmcamcorder_remove_all_handlers(handle, _MMCAMCORDER_HANDLER_CATEGORY_ALL);
+
+ reqpad1 = gst_element_get_static_pad(sc->element[_MMCAMCORDER_VIDEOSRC_TEE].gst, "src0");
+ reqpad2 = gst_element_get_static_pad(sc->element[_MMCAMCORDER_VIDEOSRC_TEE].gst, "src1");
+ gst_element_release_request_pad(sc->element[_MMCAMCORDER_VIDEOSRC_TEE].gst, reqpad1);
+ gst_element_release_request_pad(sc->element[_MMCAMCORDER_VIDEOSRC_TEE].gst, reqpad2);
+ gst_object_unref(reqpad1);
+ gst_object_unref(reqpad2);
+
+ if (sc->bencbin_capture) {
+ if (sc->element[_MMCAMCORDER_ENCSINK_ENCBIN].gst) {
+ GstPad *reqpad0 = NULL;
+ reqpad0 = gst_element_get_static_pad(sc->element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "image");
+ gst_element_release_request_pad(sc->element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, reqpad0);
+ gst_object_unref(reqpad0);
+ }
+ }
+
+ gst_object_unref(sc->element[_MMCAMCORDER_MAIN_PIPE].gst);
+ /* Why is this commented? */
+ /* sc->element[_MMCAMCORDER_MAIN_PIPE].gst = NULL; */
+ }
+}
+
+
+int _mmcamcorder_image_cmd_capture(MMHandleType handle)
+{
+ int ret = MM_ERROR_NONE;
+ int UseCaptureMode = 0;
+ int width = 0;
+ int height = 0;
+ int fps = 0;
+ int cap_format = MM_PIXEL_FORMAT_NV12;
+ int cap_jpeg_quality = 0;
+ int image_encoder = MM_IMAGE_CODEC_JPEG;
+ unsigned int cap_fourcc = 0;
+
+ char *err_name = NULL;
+ char *videosrc_name = NULL;
+
+ GstElement *pipeline = NULL;
+ GstCameraControl *control = NULL;
+ GstCaps *caps = NULL;
+ GstClock *clock = NULL;
+
+ mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
+ _MMCamcorderImageInfo *info = NULL;
+ _MMCamcorderSubContext *sc = NULL;
+ type_element *VideosrcElement = NULL;
+
+ mmf_return_val_if_fail(hcamcorder, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
+
+ sc = MMF_CAMCORDER_SUBCONTEXT(handle);
+ mmf_return_val_if_fail(sc && sc->info && sc->element, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
+
+ _mmcam_dbg_log("");
+
+ pipeline = sc->element[_MMCAMCORDER_MAIN_PIPE].gst;
+ info = sc->info;
+
+ _mmcamcorder_conf_get_value_int(hcamcorder->conf_main,
+ CONFIGURE_CATEGORY_MAIN_CAPTURE,
+ "UseCaptureMode",
+ &UseCaptureMode);
+
+ _mmcamcorder_conf_get_element(hcamcorder->conf_main,
+ CONFIGURE_CATEGORY_MAIN_VIDEO_INPUT,
+ "VideosrcElement",
+ &VideosrcElement);
+
+ _mmcamcorder_conf_get_value_element_name(VideosrcElement, &videosrc_name);
+
+ if (info->capturing) {
+ ret = MM_ERROR_CAMCORDER_DEVICE_BUSY;
+ goto cmd_error;
+ }
+
+ MMTA_ACUM_ITEM_BEGIN("Real First Capture Start",false);
+
+ /* set capture flag */
+ info->capturing = TRUE;
+
+ ret = mm_camcorder_get_attributes(handle, &err_name,
+ MMCAM_IMAGE_ENCODER_QUALITY, &cap_jpeg_quality,
+ MMCAM_IMAGE_ENCODER, &image_encoder,
+ MMCAM_CAMERA_WIDTH, &width,
+ MMCAM_CAMERA_HEIGHT, &height,
+ MMCAM_CAMERA_FPS, &fps,
+ MMCAM_CAPTURE_FORMAT, &cap_format,
+ MMCAM_CAPTURE_WIDTH, &info->width,
+ MMCAM_CAPTURE_HEIGHT, &info->height,
+ MMCAM_CAPTURE_COUNT, &info->count,
+ MMCAM_CAPTURE_INTERVAL, &info->interval,
+ NULL);
+ if (ret != MM_ERROR_NONE) {
+ _mmcam_dbg_warn("Get attrs fail. (%s:%x)", err_name, ret);
+ SAFE_FREE (err_name);
+ goto cmd_error;
+ }
+
+ if (info->count < 1) {
+ _mmcam_dbg_err("capture count[%d] is invalid", info->count);
+ ret = MM_ERROR_CAMCORDER_INVALID_ARGUMENT;
+ goto cmd_error;
+ } else if (info->count == 1) {
+ info->type = _MMCamcorder_SINGLE_SHOT;
+ } else {
+ info->type = _MMCamcorder_MULTI_SHOT;
+ info->next_shot_time = 0;
+ info->multi_shot_stop = FALSE;
+ }
+
+ info->capture_cur_count = 0;
+ info->capture_send_count = 0;
+
+ _mmcam_dbg_log("videosource(%dx%d), capture(%dx%d), count(%d)",
+ width, height, info->width, info->height, info->count);
+
+ sc->internal_encode = FALSE;
+
+ if (!strcmp(videosrc_name, "avsysvideosrc") || !strcmp(videosrc_name, "camerasrc")) {
+ /* Check encoding method */
+ if (cap_format == MM_PIXEL_FORMAT_ENCODED) {
+ if (sc->SensorEncodedCapture && info->type == _MMCamcorder_SINGLE_SHOT) {
+ cap_fourcc = _mmcamcorder_get_fourcc(cap_format, image_encoder, hcamcorder->use_zero_copy_format);
+ _mmcam_dbg_log("Sensor JPEG Capture");
+ } else {
+ int raw_capture_format = MM_PIXEL_FORMAT_I420;
+
+ ret = mm_camcorder_get_attributes(handle, &err_name,
+ MMCAM_RECOMMEND_PREVIEW_FORMAT_FOR_CAPTURE, &raw_capture_format,
+ NULL );
+ if (ret != MM_ERROR_NONE) {
+ _mmcam_dbg_warn("Get Recommend capture format failed.");
+ SAFE_FREE(err_name);
+ goto cmd_error;
+ }
+
+ cap_fourcc = _mmcamcorder_get_fourcc(raw_capture_format, image_encoder, hcamcorder->use_zero_copy_format);
+ sc->internal_encode = TRUE;
+
+ _mmcam_dbg_log("MSL JPEG Capture");
+ }
+ } else {
+ cap_fourcc = _mmcamcorder_get_fourcc(cap_format, MM_IMAGE_CODEC_INVALID, hcamcorder->use_zero_copy_format);
+ if (info->type == _MMCamcorder_SINGLE_SHOT && !strcmp(videosrc_name, "camerasrc")) {
+ MMCAMCORDER_G_OBJECT_SET( sc->element[_MMCAMCORDER_VIDEOSINK_QUE].gst, "empty-buffers", TRUE );
+ MMCAMCORDER_G_OBJECT_SET( sc->element[_MMCAMCORDER_VIDEOSINK_SINK].gst, "stop-video", TRUE );
+ }
+ }
+
+ _mmcam_dbg_log("capture format (%d), jpeg quality (%d)", cap_format, cap_jpeg_quality);
+
+ /* Note: width/height of capture is set in commit function of attribute or in create function of pipeline */
+ MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst, "capture-fourcc", cap_fourcc);
+ MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst, "capture-interval", info->interval);
+ MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst, "capture-count", info->count);
+ MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst, "capture-jpg-quality", cap_jpeg_quality);
+
+ 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;
+ }
+
+ control = GST_CAMERA_CONTROL(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst);
+ gst_camera_control_set_capture_command(control, GST_CAMERA_CONTROL_CAPTURE_COMMAND_START);
+ } else {
+ int need_change = 0;
+ int set_width = 0;
+ int set_height = 0;
+
+ if (UseCaptureMode) {
+ if (width != MMFCAMCORDER_HIGHQUALITY_WIDTH || height != MMFCAMCORDER_HIGHQUALITY_HEIGHT) {
+ need_change = 1;
+ }
+ } else {
+ if (width != info->width || height != info->height) {
+ need_change = 1;
+ }
+ }
+
+ if (need_change) {
+ _mmcam_dbg_log("Need to change resolution");
+
+ if (UseCaptureMode) {
+ set_width = MMFCAMCORDER_HIGHQUALITY_WIDTH;
+ set_height = MMFCAMCORDER_HIGHQUALITY_HEIGHT;
+ } else {
+ set_width = info->width;
+ set_height = info->height;
+ }
+
+ caps = gst_caps_new_simple("video/x-raw-yuv",
+ "format", GST_TYPE_FOURCC, sc->fourcc,
+ "width", G_TYPE_INT, set_width,
+ "height", G_TYPE_INT, set_height,
+ "framerate", GST_TYPE_FRACTION, fps, 1,
+ "rotate", G_TYPE_INT, 0,
+ NULL);
+ if (caps == NULL) {
+ _mmcam_dbg_err("failed to create caps");
+ ret = MM_ERROR_CAMCORDER_LOW_MEMORY;
+ goto cmd_error;
+ }
+
+ info->resolution_change = TRUE;
+ MMCAMCORDER_G_OBJECT_SET( sc->element[_MMCAMCORDER_VIDEOSRC_FILT].gst, "caps", caps);
+ gst_caps_unref(caps);
+
+ /*MMCAMCORDER_G_OBJECT_SET( sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst, "num-buffers", info->count);*/
+ MMCAMCORDER_G_OBJECT_SET( sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst, "req-negotiation",TRUE);
+
+ /* FIXME: consider delay */
+ clock = gst_pipeline_get_clock(GST_PIPELINE(pipeline));
+ sc->stillshot_time = gst_clock_get_time(clock) - gst_element_get_base_time(GST_ELEMENT(pipeline));
+ MMCAMCORDER_G_OBJECT_SET( sc->element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "block", FALSE);
+
+ _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.");
+ MMCAMCORDER_G_OBJECT_SET( sc->element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "block", FALSE);
+ }
+ }
+
+ /* Play capture sound here if single capture */
+ if (info->type == _MMCamcorder_SINGLE_SHOT) {
+ _mmcamcorder_sound_solo_play(handle, _MMCAMCORDER_FILEPATH_CAPTURE_SND, FALSE);
+ }
+
+cmd_error:
+ return ret;
+}
+
+
+int _mmcamcorder_image_cmd_preview_start(MMHandleType handle)
+{
+ int ret = MM_ERROR_NONE;
+ int width = 0;
+ int height = 0;
+ int fps = 0;
+ int cap_width = 0;
+ int cap_height = 0;
+ int rotation = 0;
+ int input_index = 0;
+ int set_width = 0;
+ int set_height = 0;
+ int set_rotate = 0;
+ int current_framecount = 0;
+ gboolean fps_auto = FALSE;
+ char *err_name = NULL;
+ char *videosrc_name = NULL;
+
+ GstState state;
+ GstCaps *caps = NULL;
+ GstElement *pipeline = NULL;
+ GstCameraControl *control = NULL;
+
+ mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
+ _MMCamcorderImageInfo *info = NULL;
+ _MMCamcorderSubContext *sc = NULL;
+ type_element *VideosrcElement = NULL;
+
+ mmf_return_val_if_fail(hcamcorder, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
+
+ sc = MMF_CAMCORDER_SUBCONTEXT(handle);
+ mmf_return_val_if_fail(sc && sc->info && sc->element, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
+
+ _mmcam_dbg_log("");
+
+ pipeline = sc->element[_MMCAMCORDER_MAIN_PIPE].gst;
+ info = sc->info;
+
+ MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_QUE].gst, "empty-buffers", TRUE);
+
+ _mmcamcorder_conf_get_element(hcamcorder->conf_main,
+ CONFIGURE_CATEGORY_MAIN_VIDEO_INPUT,
+ "VideosrcElement",
+ &VideosrcElement);
+
+ _mmcamcorder_conf_get_value_element_name(VideosrcElement, &videosrc_name);
+
+ sc->display_interval = 0;
+ sc->previous_slot_time = 0;
+
+ /* Image info */
+ info->capture_cur_count = 0;
+ info->capture_send_count = 0;
+ info->next_shot_time = 0;
+ info->multi_shot_stop = TRUE;
+ info->capturing = FALSE;
+
+ _mmcamcorder_vframe_stablize(handle);
+
+ if (!strcmp(videosrc_name, "avsysvideosrc") || !strcmp(videosrc_name, "camerasrc")) {
+ _mmcam_dbg_log("Capture Preview start : avsysvideosrc - No need to set new caps.");
+
+ ret = mm_camcorder_get_attributes(handle, &err_name,
+ MMCAM_CAMERA_FPS_AUTO, &fps_auto,
+ NULL);
+ if (ret != MM_ERROR_NONE) {
+ _mmcam_dbg_warn("Get attrs fail. (%s:%x)", err_name, ret);
+ SAFE_FREE (err_name);
+ goto cmd_error;
+ }
+
+ MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst, "fps-auto", fps_auto);
+
+ if (_mmcamcorder_get_state(handle) == MM_CAMCORDER_STATE_CAPTURING) {
+ 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;
+ }
+
+ control = GST_CAMERA_CONTROL(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst);
+ gst_camera_control_set_capture_command(control, GST_CAMERA_CONTROL_CAPTURE_COMMAND_STOP);
+
+ current_framecount = sc->kpi.video_framecount;
+ MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_SINK].gst, "stop-video", FALSE);
+ if (info->type == _MMCamcorder_SINGLE_SHOT) {
+ MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_QUE].gst, "empty-buffers", FALSE);
+ }
+ }
+ } else {
+ /* check if resolution need to rollback */
+ ret = mm_camcorder_get_attributes(handle, &err_name,
+ MMCAM_CAMERA_DEVICE, &input_index,
+ MMCAM_CAMERA_WIDTH, &width,
+ MMCAM_CAMERA_HEIGHT, &height,
+ MMCAM_CAMERA_FPS, &fps,
+ MMCAM_CAMERA_FPS_AUTO, &fps_auto,
+ MMCAM_CAMERA_ROTATION, &rotation,
+ MMCAM_CAPTURE_WIDTH, &cap_width,
+ MMCAM_CAPTURE_HEIGHT, &cap_height,
+ NULL);
+ if (ret != MM_ERROR_NONE) {
+ _mmcam_dbg_warn("Get attrs fail. (%s:%x)", err_name, ret);
+ SAFE_FREE (err_name);
+ goto cmd_error;
+ }
+
+ if (_mmcamcorder_get_state((MMHandleType)hcamcorder) == MM_CAMCORDER_STATE_CAPTURING) {
+ switch (rotation) {
+ case MM_VIDEO_INPUT_ROTATION_90:
+ set_width = height;
+ set_height = width;
+ set_rotate = 90;
+ break;
+ case MM_VIDEO_INPUT_ROTATION_180:
+ set_width = width;
+ set_height = height;
+ set_rotate = 180;
+ break;
+ case MM_VIDEO_INPUT_ROTATION_270:
+ set_width = height;
+ set_height = width;
+ set_rotate = 270;
+ break;
+ case MM_VIDEO_INPUT_ROTATION_NONE:
+ default:
+ set_width = width;
+ set_height = height;
+ set_rotate = 0;
+ break;
+ }
+
+ caps = gst_caps_new_simple("video/x-raw-yuv",
+ "format", GST_TYPE_FOURCC, sc->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);
+ if (caps != NULL) {
+ MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_FILT].gst, "caps", caps);
+ gst_caps_unref(caps);
+ _mmcam_dbg_log("Rollback to original resolution(%d, %d)", width, height);
+ } else {
+ _mmcam_dbg_err("failed to create caps");
+ ret = MM_ERROR_CAMCORDER_LOW_MEMORY;
+ goto cmd_error;
+ }
+ }
+ }
+
+ gst_element_get_state(pipeline, &state, NULL, -1);
+
+ if (state == GST_STATE_PLAYING) {
+ if (!strcmp(videosrc_name, "avsysvideosrc") || !strcmp(videosrc_name, "camerasrc")) {
+ int try_count = 0;
+
+ __ta__( " Wait preview frame after capture",
+ while (current_framecount >= sc->kpi.video_framecount &&
+ try_count++ < _MMCAMCORDER_CAPTURE_STOP_CHECK_COUNT) {
+ usleep(_MMCAMCORDER_CAPTURE_STOP_CHECK_INTERVAL);
+ }
+ );
+
+ if (info->type == _MMCamcorder_MULTI_SHOT) {
+ MMCAMCORDER_G_OBJECT_SET( sc->element[_MMCAMCORDER_VIDEOSINK_QUE].gst, "empty-buffers", FALSE);
+ }
+
+ _mmcam_dbg_log("Wait Frame Done. count before[%d],after[%d], try_count[%d]",
+ current_framecount, sc->kpi.video_framecount, try_count);
+ } else {
+ ret = _mmcamcorder_gst_set_state(handle, pipeline, GST_STATE_READY);
+ MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_QUE].gst, "empty-buffers", FALSE);
+
+ if (ret != MM_ERROR_NONE) {
+ goto cmd_error;
+ }
+
+ ret = _mmcamcorder_gst_set_state(handle, pipeline, GST_STATE_PLAYING);
+ if (ret != MM_ERROR_NONE) {
+ goto cmd_error;
+ }
+ }
+ } else {
+ int cap_count = 0;
+ int sound_ret = FALSE;
+
+ MMCAMCORDER_G_OBJECT_SET( sc->element[_MMCAMCORDER_VIDEOSINK_QUE].gst, "empty-buffers", FALSE);
+
+ __ta__(" _MMCamcorder_CMD_PREVIEW_START:GST_STATE_PLAYING",
+ ret = _mmcamcorder_gst_set_state(handle, pipeline, GST_STATE_PLAYING);
+ );
+ if (ret != MM_ERROR_NONE) {
+ goto cmd_error;
+ }
+
+ mm_camcorder_get_attributes(handle, NULL, MMCAM_CAPTURE_COUNT, &cap_count, NULL);
+ if (cap_count > 1) {
+ __ta__("_mmcamcorder_sound_init",
+ sound_ret = _mmcamcorder_sound_init(handle, _MMCAMCORDER_FILEPATH_CAPTURE2_SND);
+ );
+ if (sound_ret) {
+ __ta__("_mmcamcorder_sound_prepare",
+ sound_ret = _mmcamcorder_sound_prepare(handle);
+ );
+ _mmcam_dbg_log("sound prepare [%d]", sound_ret);
+ }
+ }
+ }
+
+cmd_error:
+ return ret;
+}
+
+
+int _mmcamcorder_image_cmd_preview_stop(MMHandleType handle)
+{
+ int ret = MM_ERROR_NONE;
+
+ GstElement *pipeline = NULL;
+
+ _MMCamcorderSubContext *sc = NULL;
+
+ _mmcam_dbg_log("");
+
+ mmf_return_val_if_fail(handle, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
+
+ sc = MMF_CAMCORDER_SUBCONTEXT(handle);
+ mmf_return_val_if_fail(sc && sc->info && sc->element, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
+
+ pipeline = sc->element[_MMCAMCORDER_MAIN_PIPE].gst;
+
+ MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_QUE].gst, "empty-buffers", TRUE);
+ ret = _mmcamcorder_gst_set_state(handle, pipeline, GST_STATE_READY);
+ MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_QUE].gst, "empty-buffers", FALSE);
+
+ return ret;
+}
+
+
+int _mmcamcorder_image_cmd_capture_with_encbin(MMHandleType handle)
+{
+ int ret = MM_ERROR_NONE;
+ int UseCaptureMode = 0;
+ int width = 0;
+ int height = 0;
+ int fps = 0;
+ int cap_format = MM_PIXEL_FORMAT_ENCODED;
+ int cap_jpeg_quality = 0;
+ int image_encoder = MM_IMAGE_CODEC_JPEG;
+ unsigned int cap_fourcc = GST_MAKE_FOURCC('J','P','E','G');
+ char *err_name = NULL;
+ char *videosrc_name = NULL;
+
+ GstCaps *caps = NULL;
+ GstClock *clock = NULL;
+ GstElement *pipeline = NULL;
+ GstCameraControl *control = NULL;
+
+ mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
+ _MMCamcorderImageInfo *info = NULL;
+ _MMCamcorderSubContext *sc = NULL;
+ type_element *VideosrcElement = NULL;
+
+ mmf_return_val_if_fail(hcamcorder, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
+
+ sc = MMF_CAMCORDER_SUBCONTEXT(hcamcorder);
+ mmf_return_val_if_fail(sc && sc->info && sc->element, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
+
+ _mmcam_dbg_log("");
+
+ pipeline = sc->element[_MMCAMCORDER_MAIN_PIPE].gst;
+ info = sc->info;
+
+ _mmcamcorder_conf_get_value_int(hcamcorder->conf_main,
+ CONFIGURE_CATEGORY_MAIN_CAPTURE,
+ "UseCaptureMode",
+ &UseCaptureMode);
+
+ _mmcamcorder_conf_get_element(hcamcorder->conf_main,
+ CONFIGURE_CATEGORY_MAIN_VIDEO_INPUT,
+ "VideosrcElement",
+ &VideosrcElement);
+
+ _mmcamcorder_conf_get_value_element_name(VideosrcElement, &videosrc_name);
+
+ if (info->capturing) {
+ ret = MM_ERROR_CAMCORDER_DEVICE_BUSY;
+ goto cmd_error;
+ }
+
+ MMTA_ACUM_ITEM_BEGIN("Real First Capture Start",false);
+
+ info->capturing = TRUE;
+
+ ret = mm_camcorder_get_attributes(handle, &err_name,
+ MMCAM_IMAGE_ENCODER_QUALITY, &cap_jpeg_quality,
+ MMCAM_IMAGE_ENCODER, &image_encoder,
+ MMCAM_CAMERA_WIDTH, &width,
+ MMCAM_CAMERA_HEIGHT, &height,
+ MMCAM_CAMERA_FPS, &fps,
+ MMCAM_CAPTURE_FORMAT, &cap_format,
+ MMCAM_CAPTURE_WIDTH, &info->width,
+ MMCAM_CAPTURE_HEIGHT, &info->height,
+ MMCAM_CAPTURE_COUNT, &info->count,
+ MMCAM_CAPTURE_INTERVAL, &info->interval,
+ NULL);
+ if (ret != MM_ERROR_NONE) {
+ _mmcam_dbg_err("Get attrs fail. (%s:%x)", err_name, ret);
+ SAFE_FREE (err_name);
+ goto cmd_error;
+ }
+
+ if (info->count < 1) {
+ _mmcam_dbg_err("capture count[%d] is invalid", info->count);
+ ret = MM_ERROR_CAMCORDER_INVALID_ARGUMENT;
+ goto cmd_error;
+ } else if (info->count == 1) {
+ info->type = _MMCamcorder_SINGLE_SHOT;
+ } else {
+ info->type = _MMCamcorder_MULTI_SHOT;
+ info->capture_cur_count = 0;
+ info->capture_send_count = 0;
+ info->next_shot_time = 0;
+ info->multi_shot_stop = FALSE;
+ }
+
+ _mmcam_dbg_log("videosource(%dx%d), capture(%dx%d), count(%d)",
+ width, height, info->width, info->height, info->count);
+
+ if (!strcmp(videosrc_name, "avsysvideosrc") || !strcmp(videosrc_name, "camerasrc")) {
+ cap_fourcc = _mmcamcorder_get_fourcc(cap_format, image_encoder, hcamcorder->use_zero_copy_format);
+ _mmcam_dbg_log("capture format (%d), jpeg quality (%d)", cap_format, cap_jpeg_quality);
+
+ MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst, "capture-fourcc", cap_fourcc);
+ MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst, "capture-interval", info->interval);
+ MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst, "capture-width", info->width);
+ MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst, "capture-height", info->height);
+ MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst, "capture-count", info->count);
+ MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst, "capture-jpg-quality", cap_jpeg_quality);
+
+ 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;
+ }
+
+ control = GST_CAMERA_CONTROL( sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst );
+ gst_camera_control_set_capture_command( control, GST_CAMERA_CONTROL_CAPTURE_COMMAND_START );
+ } else {
+ int need_change = 0;
+ int set_width = 0;
+ int set_height = 0;
+
+ if (UseCaptureMode) {
+ if (width != MMFCAMCORDER_HIGHQUALITY_WIDTH || height != MMFCAMCORDER_HIGHQUALITY_HEIGHT) {
+ need_change = 1;
+ }
+ } else {
+ if (width != info->width || height != info->height) {
+ need_change = 1;
+ }
+ }
+
+ if (need_change) {
+ _mmcam_dbg_log("Need to change resolution");
+
+ if (UseCaptureMode) {
+ set_width = MMFCAMCORDER_HIGHQUALITY_WIDTH;
+ set_height = MMFCAMCORDER_HIGHQUALITY_HEIGHT;
+ } else {
+ set_width = info->width;
+ set_height = info->height;
+ }
+
+ caps = gst_caps_new_simple("video/x-raw-yuv",
+ "format", GST_TYPE_FOURCC, sc->fourcc,
+ "width", G_TYPE_INT, set_width,
+ "height", G_TYPE_INT, set_height,
+ "framerate", GST_TYPE_FRACTION, fps, 1,
+ "rotate", G_TYPE_INT, 0,
+ NULL);
+ if (caps == NULL) {
+ _mmcam_dbg_err("failed to create caps");
+ ret = MM_ERROR_CAMCORDER_LOW_MEMORY;
+ goto cmd_error;
+ }
+
+ info->resolution_change = TRUE;
+ MMCAMCORDER_G_OBJECT_SET( sc->element[_MMCAMCORDER_VIDEOSRC_FILT].gst, "caps", caps);
+ gst_caps_unref(caps);
+
+ MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst, "req-negotiation",TRUE);
+
+ /* FIXME: consider delay */
+ clock = gst_pipeline_get_clock(GST_PIPELINE(pipeline));
+ sc->stillshot_time = gst_clock_get_time(clock) - gst_element_get_base_time(GST_ELEMENT(pipeline));
+ _mmcam_dbg_log("Change to target resolution(%d, %d)", info->width, info->height);
+ MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_ENCSINK_SINK].gst,"signal-handoffs",TRUE);
+ MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "block", FALSE);
+
+ } else {
+ _mmcam_dbg_log("No need to change resolution. Open toggle now.");
+ MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_ENCSINK_SINK].gst,"signal-handoffs",TRUE);
+ MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "block", FALSE);
+ }
+ }
+
+ /* Play capture sound here if single capture */
+ if (info->type == _MMCamcorder_SINGLE_SHOT) {
+ _mmcamcorder_sound_solo_play(handle, _MMCAMCORDER_FILEPATH_CAPTURE_SND, FALSE);
+ }
+
+cmd_error:
+ return ret;
+}
+
+
+int _mmcamcorder_image_cmd_preview_start_with_encbin(MMHandleType handle)
+{
+ int ret = MM_ERROR_NONE;
+ int width = 0;
+ int height = 0;
+ int fps = 0;
+ int cap_width = 0;
+ int cap_height = 0;
+ int rotation = 0;
+ int input_index = 0;
+ int set_width = 0;
+ int set_height = 0;
+ int set_rotate = 0;
+ int current_framecount = 0;
+ int current_state = MM_CAMCORDER_STATE_NONE;
+ gboolean fps_auto = FALSE;
+ char *err_name = NULL;
+ char *videosrc_name = NULL;
+
+ GstState state = GST_STATE_NULL;
+ GstCaps *caps = NULL;
+ GstElement *pipeline = NULL;
+ GstCameraControl *control = NULL;
+
+ mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
+ _MMCamcorderImageInfo *info = NULL;
+ _MMCamcorderSubContext *sc = NULL;
+ type_element *VideosrcElement = NULL;
+
+ mmf_return_val_if_fail(hcamcorder, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
+
+ sc = MMF_CAMCORDER_SUBCONTEXT(hcamcorder);
+ mmf_return_val_if_fail(sc && sc->info && sc->element, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
+
+ _mmcam_dbg_log("");
+
+ info = sc->info;
+ pipeline = sc->element[_MMCAMCORDER_MAIN_PIPE].gst;
+
+ _mmcamcorder_conf_get_element(hcamcorder->conf_main,
+ CONFIGURE_CATEGORY_MAIN_VIDEO_INPUT,
+ "VideosrcElement",
+ &VideosrcElement);
+
+ _mmcamcorder_conf_get_value_element_name(VideosrcElement, &videosrc_name);
+
+ sc->display_interval = 0;
+ sc->previous_slot_time = 0;
+
+ /* init image info */
+ info->capture_cur_count = 0;
+ info->capture_send_count = 0;
+ info->next_shot_time = 0;
+ info->multi_shot_stop = TRUE;
+ info->capturing = FALSE;
+
+ _mmcamcorder_vframe_stablize(handle);
+
+ current_state = _mmcamcorder_get_state(handle);
+ _mmcam_dbg_log("current state [%d]", current_state);
+
+ if (!strcmp(videosrc_name, "avsysvideosrc") || !strcmp(videosrc_name, "camerasrc")) {
+ _mmcam_dbg_log("Capture Preview start : %s - No need to set new caps.", videosrc_name);
+
+ ret = mm_camcorder_get_attributes(handle, &err_name,
+ MMCAM_CAMERA_FPS_AUTO, &fps_auto,
+ NULL);
+ if (ret != MM_ERROR_NONE) {
+ _mmcam_dbg_warn("Get attrs fail. (%s:%x)", err_name, ret);
+ SAFE_FREE (err_name);
+ goto cmd_error;
+ }
+
+ /* set fps-auto to videosrc */
+ MMCAMCORDER_G_OBJECT_SET( sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst, "fps-auto", fps_auto);
+
+ if (current_state == MM_CAMCORDER_STATE_CAPTURING) {
+ 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;
+ }
+
+ current_framecount = sc->kpi.video_framecount;
+
+ control = GST_CAMERA_CONTROL(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst);
+ gst_camera_control_set_capture_command(control, GST_CAMERA_CONTROL_CAPTURE_COMMAND_STOP);
+ }
+ } else {
+ /* check if resolution need to roll back */
+ ret = mm_camcorder_get_attributes(handle, &err_name,
+ MMCAM_CAMERA_DEVICE, &input_index,
+ MMCAM_CAMERA_WIDTH, &width,
+ MMCAM_CAMERA_HEIGHT, &height,
+ MMCAM_CAMERA_FPS, &fps,
+ MMCAM_CAMERA_FPS_AUTO, &fps_auto,
+ MMCAM_CAMERA_ROTATION, &rotation,
+ MMCAM_CAPTURE_WIDTH, &cap_width,
+ MMCAM_CAPTURE_HEIGHT, &cap_height,
+ NULL);
+ if (ret != MM_ERROR_NONE) {
+ _mmcam_dbg_warn("Get attrs fail. (%s:%x)", err_name, ret);
+ SAFE_FREE (err_name);
+ goto cmd_error;
+ }
+
+ if (current_state == MM_CAMCORDER_STATE_CAPTURING) {
+ switch (rotation) {
+ case MM_VIDEO_INPUT_ROTATION_90:
+ set_width = height;
+ set_height = width;
+ set_rotate = 90;
+ break;
+ case MM_VIDEO_INPUT_ROTATION_180:
+ set_width = width;
+ set_height = height;
+ set_rotate = 180;
+ break;
+ case MM_VIDEO_INPUT_ROTATION_270:
+ set_width = height;
+ set_height = width;
+ set_rotate = 270;
+ break;
+ case MM_VIDEO_INPUT_ROTATION_NONE:
+ default:
+ set_width = width;
+ set_height = height;
+ set_rotate = 0;
+ break;
+ }
+
+ caps = gst_caps_new_simple("video/x-raw-yuv",
+ "format", GST_TYPE_FOURCC, sc->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);
+ if (caps == NULL) {
+ _mmcam_dbg_err("failed to create caps");
+ ret = MM_ERROR_CAMCORDER_LOW_MEMORY;
+ goto cmd_error;
+ }
+
+ MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_FILT].gst, "caps", caps);
+ gst_caps_unref(caps);
+ caps = NULL;
+ _mmcam_dbg_log("Rollback to original resolution(%d, %d)", width, height);
+ }
+ }
+
+ MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_QUE].gst, "empty-buffers", FALSE);
+
+ gst_element_get_state(pipeline, &state, NULL, -1);
+
+ if (state == GST_STATE_PLAYING) {
+ if (!strcmp(videosrc_name, "avsysvideosrc") || !strcmp(videosrc_name, "camerasrc")) {
+ __ta__( " Wait preview frame after capture",
+ while (current_framecount == sc->kpi.video_framecount) {
+ usleep(_MMCAMCORDER_CAPTURE_STOP_CHECK_INTERVAL);
+ }
+ );
+
+ _mmcam_dbg_log("Wait Frame Done. count before[%d],after[%d]",
+ current_framecount, sc->kpi.video_framecount);
+ } else {
+#if 1
+ MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_QUE].gst, "empty-buffers", TRUE);
+ ret = _mmcamcorder_gst_set_state(handle, pipeline, GST_STATE_READY);
+ MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_QUE].gst, "empty-buffers", FALSE);
+ MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "block", FALSE);
+#else /* This code wasn't work. So rollback to previous code. Plz tell me why. It's weired. */
+ MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "block", FALSE);
+ MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_QUE].gst, "empty-buffers", FALSE);
+ ret = _mmcamcorder_gst_set_state(handle, pipeline, GST_STATE_READY);
+#endif
+ if (ret != MM_ERROR_NONE) {
+ goto cmd_error;
+ }
+
+ ret = _mmcamcorder_gst_set_state(handle, pipeline, GST_STATE_PLAYING);
+ if (ret != MM_ERROR_NONE) {
+ goto cmd_error;
+ }
+ MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "block", TRUE);
+ }
+ } else {
+ __ta__(" _MMCamcorder_CMD_PREVIEW_START:GST_STATE_PLAYING",
+ ret = _mmcamcorder_gst_set_state(handle, pipeline, GST_STATE_PLAYING);
+ );
+ if (ret != MM_ERROR_NONE) {
+ goto cmd_error;
+ }
+ }
+
+cmd_error:
+ MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_ENCSINK_SINK].gst,"signal-handoffs",FALSE);
+ MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "block", TRUE);
+ return ret;
+}
+
+
+int _mmcamcorder_image_cmd_preview_stop_with_encbin(MMHandleType handle)
+{
+ int ret = MM_ERROR_NONE;
+
+ GstElement *pipeline = NULL;
+
+ _MMCamcorderSubContext *sc = NULL;
+
+ _mmcam_dbg_log("");
+
+ mmf_return_val_if_fail(handle, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
+
+ sc = MMF_CAMCORDER_SUBCONTEXT(handle);
+ mmf_return_val_if_fail(sc && sc->info && sc->element, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
+
+ pipeline = sc->element[_MMCAMCORDER_MAIN_PIPE].gst;
+
+ /* set signal handler off */
+ MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_ENCSINK_SINK].gst,"signal-handoffs",FALSE);
+
+ MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "block", FALSE);
+ MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_QUE].gst, "empty-buffers", FALSE);
+ ret = _mmcamcorder_gst_set_state(handle, pipeline, GST_STATE_READY);
+ if (ret != MM_ERROR_NONE) {
+ goto cmd_error;
+ }
+
+cmd_error:
+ return ret;
+}
+
+
+int _mmcamcorder_image_command(MMHandleType handle, int command)
+{
+ int ret = MM_ERROR_NONE;
+
+ 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);
+ mmf_return_val_if_fail(sc && sc->element, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
+
+ _mmcam_dbg_log("command=%d", command);
+
+ switch (command) {
+ case _MMCamcorder_CMD_CAPTURE:
+ if (!sc->bencbin_capture) {
+ ret = _mmcamcorder_image_cmd_capture(handle);
+ } else {
+ ret = _mmcamcorder_image_cmd_capture_with_encbin(handle);
+ }
+ break;
+ case _MMCamcorder_CMD_CAPTURE_CANCEL:
+ /* TODO: Is this needed? */
+ break;
+ case _MMCamcorder_CMD_PREVIEW_START:
+ if (!sc->bencbin_capture) {
+ ret = _mmcamcorder_image_cmd_preview_start(handle);
+ } else {
+ ret = _mmcamcorder_image_cmd_preview_start_with_encbin(handle);
+ }
+ /* I place this function last because it miscalculates a buffer that sents in GST_STATE_PAUSED */
+ _mmcamcorder_video_current_framerate_init(handle);
+ break;
+ case _MMCamcorder_CMD_PREVIEW_STOP:
+ if (!sc->bencbin_capture) {
+ ret = _mmcamcorder_image_cmd_preview_stop(handle);
+ } else {
+ ret = _mmcamcorder_image_cmd_preview_stop_with_encbin(handle);
+ }
+ break;
+ default:
+ ret = MM_ERROR_CAMCORDER_INVALID_ARGUMENT;
+ break;
+ }
+
+ if (ret != MM_ERROR_NONE && sc->element && sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst) {
+ int op_status = 0;
+ MMCAMCORDER_G_OBJECT_GET (sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst, "operation-status", &op_status);
+ _mmcam_dbg_err("Current Videosrc status[0x%x]", op_status);
+ }
+
+ return ret;
+}
+
+
+void __mmcamcorder_init_stillshot_info (MMHandleType handle)
+{
+ int type = _MMCamcorder_SINGLE_SHOT;
+
+ mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
+ _MMCamcorderSubContext *sc = NULL;
+ _MMCamcorderImageInfo *info = NULL;
+
+ mmf_return_if_fail(hcamcorder);
+
+ sc = MMF_CAMCORDER_SUBCONTEXT(hcamcorder);
+ mmf_return_if_fail(sc && sc->info);
+
+ info = sc->info;
+ type = info->type;
+
+ _mmcam_dbg_log("capture type[%d], capture send count[%d]", type, info->capture_send_count);
+
+ if (type ==_MMCamcorder_SINGLE_SHOT || info->capture_send_count == info->count) {
+ info->capture_cur_count = 0;
+ info->capture_send_count = 0;
+ info->multi_shot_stop = TRUE;
+ info->next_shot_time = 0;
+ info->type = _MMCamcorder_SINGLE_SHOT;
+
+ /* capturing flag set to FALSE here */
+ info->capturing = FALSE;
+ MMTA_ACUM_ITEM_END("Real First Capture Start", FALSE);
+ }
+
+ return;
+}
+
+
+gboolean __mmcamcorder_capture_save_exifinfo(MMHandleType handle, MMCamcorderCaptureDataType *original, MMCamcorderCaptureDataType *thumbnail)
+{
+ int ret = MM_ERROR_NONE;
+ unsigned char *data = NULL;
+ unsigned int datalen = 0;
+
+ mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
+
+ mmf_return_val_if_fail(hcamcorder, FALSE);
+
+ _mmcam_dbg_log("");
+
+ if (!original || original->data == NULL || original->length == 0) {
+ _mmcam_dbg_err("original=%p, data=%p, length=%d", original, original->data, original->length);
+ return FALSE;
+ } else {
+ /* original is input/output param. save original values to local var. */
+ data = original->data;
+ datalen = original->length;
+ }
+
+ /* exif 090227 */
+ ret = mm_exif_create_exif_info(&(hcamcorder->exif_info));
+ if (hcamcorder->exif_info == NULL || ret != MM_ERROR_NONE) {
+ _MMCamcorderMsgItem msg;
+
+ msg.id = MM_MESSAGE_CAMCORDER_ERROR;
+ msg.param.code = ret;
+ _mmcamcroder_send_message(handle, &msg);
+
+ _mmcam_dbg_err("Failed to create exif_info [%x]", ret);
+ return FALSE;
+ }
+
+ /* add basic exif info */
+ _mmcam_dbg_log("add basic exif info");
+ __ta__(" __mmcamcorder_set_exif_basic_info",
+ ret = __mmcamcorder_set_exif_basic_info(handle);
+ );
+ if (ret != MM_ERROR_NONE) {
+ _MMCamcorderMsgItem msg;
+
+ msg.id = MM_MESSAGE_CAMCORDER_ERROR;
+ msg.param.code = ret;
+ _mmcamcroder_send_message(handle, &msg);
+
+ _mmcam_dbg_err("Failed to set_exif_basic_info [%x]", ret);
+ }
+
+ if (thumbnail != NULL) {
+ int bthumbnail = TRUE;
+
+ /* check whether thumbnail should be included */
+ mm_camcorder_get_attributes(handle, NULL, "capture-thumbnail", &bthumbnail, NULL);
+
+ if (thumbnail->data && thumbnail->length >0 && bthumbnail) {
+ _mmcam_dbg_log("thumbnail is added!thumbnail->data=%p thumbnail->width=%d ,thumbnail->height=%d",
+ thumbnail->data, thumbnail->width, thumbnail->height);
+
+ /* add thumbnail exif info */
+ __ta__(" mm_exif_add_thumbnail_info",
+ ret = mm_exif_add_thumbnail_info(hcamcorder->exif_info, thumbnail->data,thumbnail->width, thumbnail->height, thumbnail->length);
+ );
+ if (ret != MM_ERROR_NONE) {
+ _MMCamcorderMsgItem msg;
+
+ msg.id = MM_MESSAGE_CAMCORDER_ERROR;
+ msg.param.code = ret;
+ _mmcamcroder_send_message(handle, &msg);
+
+ _mmcam_dbg_err("Failed to set_exif_thumbnail [%x]",ret);
+ }
+ } else {
+ _mmcam_dbg_err("Skip adding thumbnail (data=%p, length=%d, capture-thumbnail=%d)",
+ thumbnail->data, thumbnail->length , bthumbnail);
+ }
+ }
+
+ /* write jpeg with exif */
+ ret = mm_exif_write_exif_jpeg_to_memory(&original->data, &original->length ,hcamcorder->exif_info, data, datalen);
+
+ if (ret != MM_ERROR_NONE) {
+ _MMCamcorderMsgItem msg;
+
+ msg.id = MM_MESSAGE_CAMCORDER_ERROR;
+ msg.param.code = ret;
+ _mmcamcroder_send_message(handle, &msg);
+
+ _mmcam_dbg_err("mm_exif_write_exif_jpeg_to_memory error! [%x]",ret);
+ }
+
+ /* destroy exif info */
+ mm_exif_destory_exif_info(hcamcorder->exif_info);
+ hcamcorder->exif_info = NULL;
+
+ _mmcam_dbg_log("END");
+
+ if (ret != MM_ERROR_NONE) {
+ return FALSE;
+ } else {
+ return TRUE;
+ }
+}
+
+
+gboolean __mmcamcorder_capture_send_msg(MMHandleType handle, int type, int count)
+{
+ mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
+ _MMCamcorderImageInfo *info = NULL;
+ _MMCamcorderSubContext *sc = NULL;
+ _MMCamcorderMsgItem msg;
+
+ mmf_return_val_if_fail(hcamcorder, FALSE);
+
+ sc = MMF_CAMCORDER_SUBCONTEXT(hcamcorder);
+ mmf_return_val_if_fail(sc && sc->info, FALSE);
+
+ info = sc->info;
+
+ _mmcam_dbg_log("type [%d], capture count [%d]", type, count);
+
+ msg.id = MM_MESSAGE_CAMCORDER_CAPTURED;
+ msg.param.code = count;
+
+ _mmcamcroder_send_message((MMHandleType)hcamcorder, &msg);
+
+ _mmcam_dbg_log("END");
+ return TRUE;
+}
+
+
+void __mmcamcorder_get_capture_data_from_buffer(MMCamcorderCaptureDataType *capture_data, int pixtype, GstBuffer *buffer)
+{
+ GstCaps *caps = NULL;
+ const GstStructure *structure;
+
+ mmf_return_if_fail(capture_data && buffer);
+
+ caps = gst_buffer_get_caps(buffer);
+ if (caps == NULL) {
+ _mmcam_dbg_err("failed to get caps");
+ goto GET_FAILED;
+ }
+
+ structure = gst_caps_get_structure(caps, 0);
+ if (caps == NULL) {
+ _mmcam_dbg_err("failed to get structure");
+ goto GET_FAILED;
+ }
+
+ capture_data->data = GST_BUFFER_DATA(buffer);
+ 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);
+
+ _mmcam_dbg_err("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;
+
+ return;
+
+GET_FAILED:
+ capture_data->data = NULL;
+ capture_data->format = MM_PIXEL_FORMAT_INVALID;
+ capture_data->length = 0;
+
+ return;
+}
+
+
+gboolean __mmcamcorder_set_jpeg_data(MMHandleType handle, MMCamcorderCaptureDataType *dest, MMCamcorderCaptureDataType *thumbnail)
+{
+ int tag_enable = 0;
+ int provide_exif = FALSE;
+
+ mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
+ _MMCamcorderSubContext *sc = NULL;
+
+ mmf_return_val_if_fail(hcamcorder, FALSE);
+ mmf_return_val_if_fail(dest, FALSE);
+
+ sc = MMF_CAMCORDER_SUBCONTEXT(hcamcorder);
+ mmf_return_val_if_fail(sc, FALSE);
+
+ _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 enable[%d], provide exif[%d]", tag_enable, provide_exif);
+
+ /* if tag enable and doesn't provide exif, we make it */
+ if (tag_enable && !provide_exif) {
+ _mmcam_dbg_log("Add exif information if existed(thumbnail[%p])", thumbnail);
+ if (thumbnail && thumbnail->data) {
+ if (!__mmcamcorder_capture_save_exifinfo(handle, dest, thumbnail)) {
+ return FALSE;
+ }
+ } else {
+ if (!__mmcamcorder_capture_save_exifinfo(handle, dest, NULL)) {
+ return FALSE;
+ }
+ }
+ }
+
+ return TRUE;
+}
+
+
+void __mmcamcorder_release_jpeg_data(MMHandleType handle, MMCamcorderCaptureDataType *dest)
+{
+ int tag_enable = 0;
+ int provide_exif = FALSE;
+
+ mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
+ _MMCamcorderSubContext *sc = NULL;
+
+ mmf_return_if_fail(hcamcorder);
+ mmf_return_if_fail(dest);
+
+ 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);
+
+ /* if dest->data is allocated in MSL, release it */
+ if (tag_enable && !provide_exif) {
+ if (dest->data) {
+ free(dest->data);
+ dest->length = 0;
+ dest->data = NULL;
+ _mmcam_dbg_log("Jpeg is released!");
+ }
+ } else {
+ _mmcam_dbg_log("No need to release");
+ }
+
+ return;
+}
+
+
+static void __mmcamcorder_image_capture_cb(GstElement *element, GstBuffer *buffer1, GstBuffer *buffer2, GstBuffer *buffer3, gpointer u_data)
+{
+ int ret = MM_ERROR_NONE;
+ int pixtype = MM_PIXEL_FORMAT_INVALID;
+ int pixtype_sub = MM_PIXEL_FORMAT_INVALID;
+ int codectype = MM_IMAGE_CODEC_JPEG;
+ int type = _MMCamcorder_SINGLE_SHOT;
+ int attr_index = 0;
+ int count = 0;
+ int stop_cont_shot = 0;
+ gboolean send_msg = FALSE;
+
+ mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(u_data);
+ _MMCamcorderImageInfo *info = NULL;
+ _MMCamcorderSubContext *sc = NULL;
+ MMCamcorderCaptureDataType dest = {0,};
+ MMCamcorderCaptureDataType thumb = {0,};
+ MMCamcorderCaptureDataType scrnail = {0,};
+
+ mmf_attrs_t *attrs = NULL;
+ mmf_attribute_t *item = NULL;
+
+ void *encoded_data = NULL;
+ char *err_attr_name = NULL;
+
+ mmf_return_if_fail(hcamcorder);
+
+ sc = MMF_CAMCORDER_SUBCONTEXT(hcamcorder);
+ mmf_return_if_fail(sc && sc->info);
+
+ info = sc->info;
+
+ _mmcam_dbg_err("START");
+
+ MMTA_ACUM_ITEM_BEGIN(" MSL capture callback", FALSE);
+
+ /* check capture state */
+ if (info->type == _MMCamcorder_MULTI_SHOT && info->capture_send_count > 0) {
+ mm_camcorder_get_attributes((MMHandleType)hcamcorder, NULL, "capture-break-cont-shot", &stop_cont_shot, NULL);
+ if (stop_cont_shot == TRUE) {
+ _mmcam_dbg_warn("capture stop command already come. skip this...");
+ MMTA_ACUM_ITEM_END( " MSL capture callback", FALSE );
+ goto error;
+ }
+ }
+
+ if (!info->capturing) {
+ _mmcam_dbg_err("It's Not capturing now.");
+ goto error;
+ }
+
+ /* play capture sound here if multi capture */
+ if (info->type == _MMCamcorder_MULTI_SHOT) {
+ _mmcamcorder_sound_play((MMHandleType)hcamcorder);
+ }
+
+ /* Prepare main, thumbnail buffer */
+ pixtype = _mmcamcorder_get_pixel_format(buffer1);
+ if (pixtype == MM_PIXEL_FORMAT_INVALID) {
+ _mmcam_dbg_err("Unsupported pixel type");
+ goto error;
+ }
+
+ /* Main image buffer */
+ if (buffer1 && GST_BUFFER_DATA(buffer1) && (GST_BUFFER_SIZE(buffer1) !=0)) {
+ __mmcamcorder_get_capture_data_from_buffer(&dest, pixtype, buffer1);
+ } else {
+ _mmcam_dbg_err("buffer1 has wrong pointer. (buffer1=%p)",buffer1);
+ goto error;
+ }
+
+ /* Encode JPEG */
+ if (sc->internal_encode) {
+ int capture_quality = 0;
+ ret = mm_camcorder_get_attributes((MMHandleType)hcamcorder, &err_attr_name,
+ MMCAM_IMAGE_ENCODER_QUALITY, &capture_quality,
+ NULL);
+ if (ret != MM_ERROR_NONE) {
+ _mmcam_dbg_err("Get attribute failed[%s][%x]", err_attr_name, ret);
+ SAFE_FREE(err_attr_name);
+ goto error;
+ }
+
+ __ta__(" _mmcamcorder_encode_jpeg",
+ ret = _mmcamcorder_encode_jpeg(GST_BUFFER_DATA(buffer1), dest.width, dest.height,
+ pixtype, dest.length, capture_quality, &(dest.data), &(dest.length));
+ );
+ if (ret == FALSE) {
+ goto error;
+ }
+
+ encoded_data = dest.data;
+ dest.format = MM_PIXEL_FORMAT_ENCODED;
+ }
+
+ /* Thumbnail image buffer */
+ if (buffer2 && GST_BUFFER_DATA(buffer2) && (GST_BUFFER_SIZE(buffer2) !=0)) {
+ pixtype_sub = _mmcamcorder_get_pixel_format(buffer2);
+ _mmcam_dbg_log("Thumnail (buffer2=%p)",buffer2);
+
+ __mmcamcorder_get_capture_data_from_buffer(&thumb, pixtype_sub, buffer2);
+ } else {
+ _mmcam_dbg_log("buffer2 has wrong pointer. Not Error. (buffer2=%p)",buffer2);
+ }
+
+ /* Screennail image buffer */
+ attrs = (mmf_attrs_t*)MMF_CAMCORDER_ATTRS(hcamcorder);
+ mm_attrs_get_index((MMHandleType)attrs, "captured-screennail", &attr_index);
+ item = &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));
+
+ pixtype_sub = _mmcamcorder_get_pixel_format(buffer3);
+ __mmcamcorder_get_capture_data_from_buffer(&scrnail, pixtype_sub, buffer3);
+
+ /* Set screennail attribute for application */
+ mmf_attribute_set_data(item, &scrnail, sizeof(scrnail));
+ } else {
+ mmf_attribute_set_data(item, NULL, 0);
+
+ _mmcam_dbg_log("buffer3 has wrong pointer. Not Error. (buffer3=%p)",buffer3);
+ }
+
+ mmf_attrs_commit_err((MMHandleType)attrs, &err_attr_name);
+
+ /* Set extra data for jpeg */
+ if (dest.format == MM_PIXEL_FORMAT_ENCODED) {
+ int err = 0;
+ char *err_attr_name = NULL;
+
+ err = mm_camcorder_get_attributes((MMHandleType)hcamcorder, &err_attr_name,
+ MMCAM_IMAGE_ENCODER, &codectype,
+ NULL);
+ if (err != MM_ERROR_NONE) {
+ _mmcam_dbg_warn("Getting codectype failed. (%s:%x)", err_attr_name, err);
+ SAFE_FREE (err_attr_name);
+ goto error;
+ }
+
+ switch (codectype) {
+ case MM_IMAGE_CODEC_JPEG:
+ case MM_IMAGE_CODEC_SRW:
+ case MM_IMAGE_CODEC_JPEG_SRW:
+ __ta__( " __mmcamcorder_set_jpeg_data",
+ ret = __mmcamcorder_set_jpeg_data((MMHandleType)hcamcorder, &dest, &thumb);
+ );
+ if (!ret) {
+ _mmcam_dbg_err("Error on setting extra data to jpeg");
+ goto error;
+ }
+ break;
+ default:
+ _mmcam_dbg_err("The codectype is not supported. (%d)", codectype);
+ goto error;
+ }
+ }
+
+ /* Handle Capture Callback */
+ _MMCAMCORDER_LOCK_VCAPTURE_CALLBACK(hcamcorder);
+
+ if (hcamcorder->vcapture_cb) {
+ _mmcam_dbg_log("APPLICATION CALLBACK START");
+ MMTA_ACUM_ITEM_BEGIN(" Application capture callback", 0);
+ if (thumb.data) {
+ ret = hcamcorder->vcapture_cb(&dest, &thumb, hcamcorder->vcapture_cb_param);
+ } else {
+ ret = hcamcorder->vcapture_cb(&dest, NULL, hcamcorder->vcapture_cb_param);
+ }
+ MMTA_ACUM_ITEM_END(" Application capture callback", 0);
+ _mmcam_dbg_log("APPLICATION CALLBACK END");
+ } else {
+ _mmcam_dbg_err("Capture callback is NULL.");
+ goto err_release_exif;
+ }
+
+ /* Set send msg flag and capture count */
+ send_msg = TRUE;
+ type = info->type;
+ count = ++(info->capture_send_count);
+
+err_release_exif:
+ _MMCAMCORDER_UNLOCK_VCAPTURE_CALLBACK(hcamcorder);
+
+ /* Release jpeg data */
+ if (pixtype == MM_PIXEL_FORMAT_ENCODED) {
+ __ta__( " __mmcamcorder_release_jpeg_data",
+ __mmcamcorder_release_jpeg_data((MMHandleType)hcamcorder, &dest);
+ );
+ }
+
+error:
+ /* Check end condition and set proper value */
+ __mmcamcorder_init_stillshot_info((MMHandleType)hcamcorder);
+
+ /* send captured message if no problem */
+ if (send_msg) {
+ __mmcamcorder_capture_send_msg((MMHandleType)hcamcorder, type, count);
+ }
+
+ /* release internal allocated data */
+ if (encoded_data) {
+ if (dest.data == encoded_data) {
+ dest.data = NULL;
+ }
+
+ free(encoded_data);
+ encoded_data = NULL;
+ }
+
+ /*free GstBuffer*/
+ if (buffer1) {
+ gst_buffer_unref(buffer1);
+ }
+ if (buffer2) {
+ gst_buffer_unref(buffer2);
+ }
+ if (buffer3) {
+ gst_buffer_unref(buffer3);
+ }
+
+ MMTA_ACUM_ITEM_END( " MSL capture callback", FALSE );
+
+ _mmcam_dbg_err("END");
+
+ return;
+}
+
+
+static gboolean __mmcamcorder_encodesink_handoff_callback(GstElement *fakesink, GstBuffer *buffer, GstPad *pad, gpointer u_data)
+{
+ mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(u_data);
+ _MMCamcorderSubContext *sc = NULL;
+
+ mmf_return_val_if_fail(hcamcorder, FALSE);
+
+ sc = MMF_CAMCORDER_SUBCONTEXT(hcamcorder);
+ mmf_return_val_if_fail(sc && sc->element, FALSE);
+
+ _mmcam_dbg_log("");
+
+ /* FIXME. How could you get a thumbnail? */
+ __mmcamcorder_image_capture_cb(fakesink, buffer, NULL, NULL, u_data);
+
+ if (sc->element[_MMCAMCORDER_ENCSINK_ENCBIN].gst) {
+ MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_ENCSINK_SINK].gst, "signal-handoffs", FALSE);
+ MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "block", TRUE);
+ }
+
+ return TRUE;
+}
+
+
+/* Take a picture with capture mode */
+int _mmcamcorder_set_resize_property(MMHandleType handle, int capture_width, int capture_height)
+{
+ int ELEMENT_CROP = 0;
+ int ELEMENT_FILTER = 0;
+
+ mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
+ _MMCamcorderSubContext *sc = NULL;
+
+ _mmcam_dbg_log("");
+
+ mmf_return_val_if_fail(hcamcorder, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
+
+ sc = MMF_CAMCORDER_SUBCONTEXT(handle);
+ mmf_return_val_if_fail(sc && sc->element, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
+
+ ELEMENT_CROP = _MMCAMCORDER_ENCSINK_ICROP;
+ ELEMENT_FILTER = _MMCAMCORDER_ENCSINK_IFILT;
+
+ /*TODO: this is not needed now. */
+
+ return MM_ERROR_NONE;
+}
+
+
+int __mmcamcorder_set_exif_basic_info(MMHandleType handle)
+{
+ int ret = MM_ERROR_NONE;
+ int value;
+ int str_val_len = 0;
+ int gps_enable = TRUE;
+ int cntl = 0;
+ int cnts = 0;
+ double f_latitude = INVALID_GPS_VALUE;
+ double f_longitude = INVALID_GPS_VALUE;
+ double f_altitude = INVALID_GPS_VALUE;
+ char *str_value = NULL;
+ char *maker = NULL;
+ char *user_comment = NULL;
+ char *err_name = NULL;
+ ExifData *ed = NULL;
+ ExifLong config;
+ ExifLong ExifVersion;
+ static ExifShort eshort[20];
+ static ExifLong elong[10];
+
+ GstCameraControl *control = NULL;
+ GstCameraControlExifInfo avsys_exif_info = {0,};
+
+ mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
+ _MMCamcorderSubContext *sc = NULL;
+
+ _mmcam_dbg_log("");
+
+ mmf_return_val_if_fail(hcamcorder, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
+
+ sc = MMF_CAMCORDER_SUBCONTEXT(handle);
+ mmf_return_val_if_fail(sc && sc->element, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
+
+ if (!GST_IS_CAMERA_CONTROL(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst)) {
+ _mmcam_dbg_err("Can't cast Video source into camera control. Just return true.");
+ return MM_ERROR_NONE;
+ }
+
+ control = GST_CAMERA_CONTROL(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst);
+ /* get device information */
+ gst_camera_control_get_exif_info(control, &avsys_exif_info);
+
+ /* 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));
+ return MM_ERROR_INVALID_HANDLE;
+ }
+
+ /* Receive attribute info */
+
+ /* START INSERT IFD_0 */
+
+ /*0. EXIF_TAG_EXIF_VERSION */
+ ExifVersion = MM_EXIF_VERSION;
+ ret = mm_exif_set_add_entry(ed, EXIF_IFD_EXIF, EXIF_TAG_EXIF_VERSION,
+ EXIF_FORMAT_UNDEFINED, 4, (unsigned char *)&ExifVersion);
+ if (ret != MM_ERROR_NONE) {
+ EXIF_SET_ERR(ret, EXIF_TAG_EXIF_VERSION);
+ }
+
+ /*1. EXIF_TAG_IMAGE_WIDTH */ /*EXIF_TAG_PIXEL_X_DIMENSION*/
+ mm_camcorder_get_attributes(handle, NULL, MMCAM_CAPTURE_WIDTH, &value, NULL);
+
+ exif_set_long((unsigned char *)&elong[cntl], exif_data_get_byte_order(ed), value);
+ ret = mm_exif_set_add_entry(ed, EXIF_IFD_0, EXIF_TAG_IMAGE_WIDTH,
+ EXIF_FORMAT_LONG, 1, (unsigned char *)&elong[cntl]);
+ if (ret != MM_ERROR_NONE) {
+ EXIF_SET_ERR(ret, EXIF_TAG_IMAGE_WIDTH);
+ }
+
+ ret = mm_exif_set_add_entry(ed, EXIF_IFD_EXIF, EXIF_TAG_PIXEL_X_DIMENSION,
+ EXIF_FORMAT_LONG, 1, (unsigned char *)&elong[cntl++]);
+ if (ret != MM_ERROR_NONE) {
+ EXIF_SET_ERR(ret, EXIF_TAG_PIXEL_X_DIMENSION);
+ }
+ _mmcam_dbg_log("width[%d]", value);
+
+ /*2. EXIF_TAG_IMAGE_LENGTH*/ /*EXIF_TAG_PIXEL_Y_DIMENSION*/
+ mm_camcorder_get_attributes(handle, NULL, MMCAM_CAPTURE_HEIGHT, &value, NULL);
+
+ exif_set_long((unsigned char *)&elong[cntl], exif_data_get_byte_order (ed), value);
+ ret = mm_exif_set_add_entry(ed, EXIF_IFD_0, EXIF_TAG_IMAGE_LENGTH,
+ EXIF_FORMAT_LONG, 1, (unsigned char *)&elong[cntl]);
+ if (ret != MM_ERROR_NONE) {
+ EXIF_SET_ERR(ret, EXIF_TAG_IMAGE_LENGTH);
+ }
+
+ ret = mm_exif_set_add_entry(ed, EXIF_IFD_EXIF, EXIF_TAG_PIXEL_Y_DIMENSION,
+ EXIF_FORMAT_LONG, 1, (unsigned char *)&elong[cntl++]);
+ if (ret != MM_ERROR_NONE) {
+ EXIF_SET_ERR(ret, EXIF_TAG_PIXEL_Y_DIMENSION);
+ }
+ _mmcam_dbg_log("height[%d]", value);
+
+ /*4. EXIF_TAG_DATE_TIME */
+
+ /*12. EXIF_TAG_DATE_TIME_ORIGINAL */
+
+ /*13. EXIF_TAG_DATE_TIME_DIGITIZED*/
+ {
+ unsigned char *b;
+ time_t t;
+ struct tm tm;
+
+ b = malloc(20 * sizeof(unsigned char));
+ if (b == NULL) {
+ _mmcam_dbg_err("failed to alloc b");
+ ret = MM_ERROR_CAMCORDER_LOW_MEMORY;
+ EXIF_SET_ERR(ret, EXIF_TAG_DATE_TIME);
+ }
+
+ memset(b, '\0', 20);
+
+ t = time(NULL);
+ tzset();
+ localtime_r(&t, &tm);
+
+ snprintf((char *)b, 20, "%04i:%02i:%02i %02i:%02i:%02i",
+ tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
+ tm.tm_hour, tm.tm_min, tm.tm_sec);
+
+ ret = mm_exif_set_add_entry(ed, EXIF_IFD_0, EXIF_TAG_DATE_TIME, EXIF_FORMAT_ASCII, 20, b);
+ if (ret != MM_ERROR_NONE) {
+ if (ret == MM_ERROR_CAMCORDER_LOW_MEMORY) {
+ free(b);
+ }
+ EXIF_SET_ERR(ret, EXIF_TAG_DATE_TIME);
+ }
+
+ ret = mm_exif_set_add_entry(ed, EXIF_IFD_EXIF, EXIF_TAG_DATE_TIME_ORIGINAL, EXIF_FORMAT_ASCII, 20, b);
+ if (ret != MM_ERROR_NONE) {
+ if (ret == MM_ERROR_CAMCORDER_LOW_MEMORY) {
+ free(b);
+ }
+ EXIF_SET_ERR(ret, EXIF_TAG_DATE_TIME_ORIGINAL);
+ }
+
+ ret = mm_exif_set_add_entry(ed, EXIF_IFD_EXIF, EXIF_TAG_DATE_TIME_DIGITIZED, EXIF_FORMAT_ASCII, 20, b);
+ if (ret != MM_ERROR_NONE) {
+ if (ret == MM_ERROR_CAMCORDER_LOW_MEMORY) {
+ free(b);
+ }
+ EXIF_SET_ERR(ret, EXIF_TAG_DATE_TIME_DIGITIZED);
+ }
+
+ free(b);
+ }
+
+ /*5. EXIF_TAG_MAKE */
+ maker = strdup(MM_MAKER_NAME);
+ if (maker) {
+ _mmcam_dbg_log("maker [%s]", maker);
+ ret = mm_exif_set_add_entry(ed, EXIF_IFD_0, EXIF_TAG_MAKE,
+ EXIF_FORMAT_ASCII, strlen(maker), (unsigned char *)maker);
+ free(maker);
+ if (ret != MM_ERROR_NONE) {
+ EXIF_SET_ERR(ret, EXIF_TAG_MAKE);
+ }
+ } else {
+ ret = MM_ERROR_CAMCORDER_LOW_MEMORY;
+ EXIF_SET_ERR(ret, EXIF_TAG_MAKE);
+ }
+
+ /*6. EXIF_TAG_MODEL */
+ _mmcamcorder_conf_get_value_string(hcamcorder->conf_main,
+ CONFIGURE_CATEGORY_MAIN_GENERAL,
+ "ModelName",
+ &str_value);
+ _mmcam_dbg_log("model_name [%s]", str_value);
+ if (str_value) {
+ char *model = strdup(str_value);
+ mm_exif_set_add_entry(ed,EXIF_IFD_0,EXIF_TAG_MODEL,EXIF_FORMAT_ASCII,strlen(model)+1, (unsigned char*)model);
+ free(model);
+ str_value = NULL;
+ if (ret != MM_ERROR_NONE) {
+ EXIF_SET_ERR(ret, EXIF_TAG_MODEL);
+ }
+ } else {
+ _mmcam_dbg_warn("failed to get model name");
+ }
+
+ /*6. EXIF_TAG_IMAGE_DESCRIPTION */
+ mm_camcorder_get_attributes(handle, NULL, MMCAM_TAG_IMAGE_DESCRIPTION, &str_value, &str_val_len, NULL);
+ _mmcam_dbg_log("desctiption [%s]", str_value);
+ if (str_value && str_val_len > 0) {
+ char *description = strdup(str_value);
+ ret = mm_exif_set_add_entry(ed, EXIF_IFD_0, EXIF_TAG_IMAGE_DESCRIPTION,
+ EXIF_FORMAT_ASCII, strlen(description), (unsigned char *)description);
+ free(description);
+ str_value = NULL;
+ str_val_len = 0;
+ if (ret != MM_ERROR_NONE) {
+ EXIF_SET_ERR(ret, EXIF_TAG_IMAGE_DESCRIPTION);
+ }
+ } else {
+ _mmcam_dbg_warn("failed to get description");
+ }
+
+ /*7. EXIF_TAG_SOFTWARE*/
+/*
+ {
+ char software[50] = {0,};
+ unsigned int len = 0;
+
+ len = snprintf(software, sizeof(software), "%x.%x ", avsys_exif_info.software_used>>8,(avsys_exif_info.software_used & 0xff));
+ _mmcam_dbg_log("software [%s], len [%d]", software, len);
+ ret = mm_exif_set_add_entry(ed, EXIF_IFD_0, EXIF_TAG_SOFTWARE,
+ EXIF_FORMAT_ASCII, len, software);
+ if (ret != MM_ERROR_NONE) {
+ EXIF_SET_ERR(ret, EXIF_TAG_SOFTWARE);
+ }
+ }
+*/
+
+ /*8. EXIF_TAG_ORIENTATION */
+ mm_camcorder_get_attributes(handle, NULL, MMCAM_TAG_ORIENTATION, &value, NULL);
+
+ _mmcam_dbg_log("orientation [%d]",value);
+ if (value == 0) {
+ value = MM_EXIF_ORIENTATION;
+ }
+
+ exif_set_short((unsigned char *)&eshort[cnts], exif_data_get_byte_order(ed), value);
+ ret = mm_exif_set_add_entry(ed, EXIF_IFD_0, EXIF_TAG_ORIENTATION,
+ EXIF_FORMAT_SHORT, 1, (unsigned char*)&eshort[cnts++]);
+ if (ret != MM_ERROR_NONE) {
+ EXIF_SET_ERR(ret, EXIF_TAG_ORIENTATION);
+ }
+
+ /* START INSERT EXIF_IFD */
+
+ /*3. User Comment*/
+ /*FIXME : get user comment from real user */
+ user_comment = strdup(MM_USER_COMMENT);
+ if (user_comment) {
+ _mmcam_dbg_log("user_comment=%s",user_comment);
+ ret = mm_exif_set_add_entry(ed, EXIF_IFD_EXIF, EXIF_TAG_USER_COMMENT,
+ EXIF_FORMAT_ASCII, strlen(user_comment), (unsigned char *)user_comment);
+ free(user_comment);
+ if (ret != MM_ERROR_NONE) {
+ EXIF_SET_ERR(ret, EXIF_TAG_USER_COMMENT);
+ }
+ } else {
+ ret = MM_ERROR_CAMCORDER_LOW_MEMORY;
+ EXIF_SET_ERR(ret, EXIF_TAG_USER_COMMENT);
+ }
+
+ /*9. EXIF_TAG_COLOR_SPACE */
+ exif_set_short((unsigned char *)&eshort[cnts], exif_data_get_byte_order(ed), avsys_exif_info.colorspace);
+ ret = mm_exif_set_add_entry(ed, EXIF_IFD_EXIF, EXIF_TAG_COLOR_SPACE,
+ EXIF_FORMAT_SHORT, 1, (unsigned char *)&eshort[cnts++]);
+ if (ret != MM_ERROR_NONE) {
+ EXIF_SET_ERR(ret, EXIF_TAG_COLOR_SPACE);
+ }
+
+ /*10. EXIF_TAG_COMPONENTS_CONFIGURATION */
+ config = avsys_exif_info.component_configuration;
+ _mmcam_dbg_log("EXIF_TAG_COMPONENTS_CONFIGURATION [%4x] ",config);
+ ret = mm_exif_set_add_entry(ed, EXIF_IFD_EXIF, EXIF_TAG_COMPONENTS_CONFIGURATION,
+ EXIF_FORMAT_UNDEFINED, 4, (unsigned char *)&config);
+ if (ret != MM_ERROR_NONE) {
+ EXIF_SET_ERR(ret, EXIF_TAG_COMPONENTS_CONFIGURATION);
+ }
+
+ /*11. EXIF_TAG_COMPRESSED_BITS_PER_PIXEL */
+ /* written the device_info */
+
+ /*12. EXIF_TAG_DATE_TIME_ORIGINAL */
+ /*13. EXIF_TAG_DATE_TIME_DIGITIZED*/
+ /*14. EXIF_TAG_EXPOSURE_TIME*/
+ if (avsys_exif_info.exposure_time_numerator && avsys_exif_info.exposure_time_denominator) {
+ unsigned char *b = NULL;
+ ExifRational rData;
+
+ _mmcam_dbg_log("EXIF_TAG_EXPOSURE_TIME numerator [%d], denominator [%d]",
+ avsys_exif_info.exposure_time_numerator, avsys_exif_info.exposure_time_denominator)
+
+ b = malloc(sizeof(ExifRational));
+ if (b) {
+ rData.numerator = avsys_exif_info.exposure_time_numerator;
+ rData.denominator = avsys_exif_info.exposure_time_denominator;
+
+ exif_set_rational(b, exif_data_get_byte_order(ed), rData);
+ ret = mm_exif_set_add_entry(ed, EXIF_IFD_EXIF, EXIF_TAG_EXPOSURE_TIME,
+ EXIF_FORMAT_RATIONAL, 1, b);
+ free(b);
+ if (ret != MM_ERROR_NONE) {
+ EXIF_SET_ERR(ret, EXIF_TAG_EXPOSURE_TIME);
+ }
+ } else {
+ _mmcam_dbg_warn("malloc failed.");
+ }
+ } else {
+ _mmcam_dbg_log("Skip set EXIF_TAG_EXPOSURE_TIME numerator [%d], denominator [%d]",
+ avsys_exif_info.exposure_time_numerator, avsys_exif_info.exposure_time_denominator);
+ }
+
+ /*15. EXIF_TAG_FNUMBER */
+ if (avsys_exif_info.aperture_f_num_numerator && avsys_exif_info.aperture_f_num_denominator) {
+ unsigned char *b = NULL;
+ ExifRational rData;
+
+ _mmcam_dbg_log("EXIF_TAG_FNUMBER numerator [%d], denominator [%d]",
+ avsys_exif_info.aperture_f_num_numerator, avsys_exif_info.aperture_f_num_denominator);
+
+ b = malloc(sizeof(ExifRational));
+ if (b) {
+ rData.numerator = avsys_exif_info.aperture_f_num_numerator;
+ rData.denominator = avsys_exif_info.aperture_f_num_denominator;
+ exif_set_rational(b, exif_data_get_byte_order(ed), rData);
+ ret = mm_exif_set_add_entry(ed, EXIF_IFD_EXIF, EXIF_TAG_FNUMBER,
+ EXIF_FORMAT_RATIONAL, 1, b);
+ free(b);
+ if(ret != MM_ERROR_NONE) {
+ EXIF_SET_ERR(ret, EXIF_TAG_FNUMBER);
+ }
+ } else {
+ _mmcam_dbg_warn( "malloc failed." );
+ }
+ } else {
+ _mmcam_dbg_log("Skip set EXIF_TAG_FNUMBER numerator [%d], denominator [%d]",
+ avsys_exif_info.aperture_f_num_numerator, avsys_exif_info.aperture_f_num_denominator);
+ }
+
+ /*16. EXIF_TAG_EXPOSURE_PROGRAM*/
+ /*FIXME*/
+ value = MM_EXPOSURE_PROGRAM;
+ exif_set_short((unsigned char *)&eshort[cnts], exif_data_get_byte_order(ed), value);
+ ret = mm_exif_set_add_entry(ed, EXIF_IFD_EXIF, EXIF_TAG_EXPOSURE_PROGRAM,
+ EXIF_FORMAT_SHORT, 1, (unsigned char *)&eshort[cnts++]);
+ if (ret != MM_ERROR_NONE) {
+ EXIF_SET_ERR(ret, EXIF_TAG_EXPOSURE_PROGRAM);
+ }
+
+ /*17. EXIF_TAG_ISO_SPEED_RATINGS*/
+ if (avsys_exif_info.iso) {
+ _mmcam_dbg_log("EXIF_TAG_ISO_SPEED_RATINGS [%d]", avsys_exif_info.iso);
+ exif_set_short((unsigned char *)&eshort[cnts], exif_data_get_byte_order(ed), avsys_exif_info.iso);
+ ret = mm_exif_set_add_entry(ed, EXIF_IFD_EXIF, EXIF_TAG_ISO_SPEED_RATINGS,
+ EXIF_FORMAT_SHORT, 1, (unsigned char *)&eshort[cnts++]);
+ if (ret != MM_ERROR_NONE) {
+ EXIF_SET_ERR(ret, EXIF_TAG_ISO_SPEED_RATINGS);
+ }
+ }
+
+ /*18. EXIF_TAG_SHUTTER_SPEED_VALUE*/
+ if (avsys_exif_info.shutter_speed_numerator && avsys_exif_info.shutter_speed_denominator) {
+ unsigned char *b = NULL;
+ ExifSRational rsData;
+
+ _mmcam_dbg_log("EXIF_TAG_SHUTTER_SPEED_VALUE numerator [%d], denominator [%d]",
+ avsys_exif_info.shutter_speed_numerator, avsys_exif_info.shutter_speed_denominator);
+
+ b = malloc(sizeof(ExifSRational));
+ if (b) {
+ rsData.numerator = avsys_exif_info.shutter_speed_numerator;
+ rsData.denominator = avsys_exif_info.shutter_speed_denominator;
+ exif_set_srational(b, exif_data_get_byte_order(ed), rsData);
+ ret = mm_exif_set_add_entry(ed, EXIF_IFD_EXIF, EXIF_TAG_SHUTTER_SPEED_VALUE,
+ EXIF_FORMAT_SRATIONAL, 1, b);
+ free(b);
+ if (ret != MM_ERROR_NONE) {
+ EXIF_SET_ERR(ret, EXIF_TAG_SHUTTER_SPEED_VALUE);
+ }
+ } else {
+ _mmcam_dbg_warn("malloc failed.");
+ }
+ } else {
+ _mmcam_dbg_log("Skip set EXIF_TAG_SHUTTER_SPEED_VALUE numerator [%d], denominator [%d]",
+ avsys_exif_info.shutter_speed_numerator, avsys_exif_info.shutter_speed_denominator);
+ }
+
+ /*19. EXIF_TAG_APERTURE_VALUE*/
+ if (avsys_exif_info.aperture_in_APEX) {
+ unsigned char *b = NULL;
+ ExifRational rData;
+
+ _mmcam_dbg_log("EXIF_TAG_APERTURE_VALUE [%d]", avsys_exif_info.aperture_in_APEX);
+
+ b = malloc(sizeof(ExifRational));
+ if (b) {
+ rData.numerator = avsys_exif_info.aperture_in_APEX;
+ rData.denominator = 1;
+ exif_set_rational(b, exif_data_get_byte_order(ed), rData);
+ ret = mm_exif_set_add_entry(ed, EXIF_IFD_EXIF, EXIF_TAG_APERTURE_VALUE,
+ EXIF_FORMAT_RATIONAL, 1, b);
+ free(b);
+ if(ret != MM_ERROR_NONE) {
+ EXIF_SET_ERR(ret, EXIF_TAG_APERTURE_VALUE);
+ }
+ } else {
+ _mmcam_dbg_warn("malloc failed.");
+ }
+ } else {
+ _mmcam_dbg_log("Skip set EXIF_TAG_APERTURE_VALUE [%d]", avsys_exif_info.aperture_in_APEX);
+ }
+
+ /*20. EXIF_TAG_BRIGHTNESS_VALUE*/
+ if (avsys_exif_info.brigtness_numerator && avsys_exif_info.brightness_denominator) {
+ unsigned char *b = NULL;
+ ExifSRational rsData;
+
+ _mmcam_dbg_log("EXIF_TAG_BRIGHTNESS_VALUE numerator [%d], denominator [%d]",
+ avsys_exif_info.brigtness_numerator, avsys_exif_info.brightness_denominator);
+
+ b = malloc(sizeof(ExifSRational));
+ if (b) {
+ rsData.numerator = avsys_exif_info.brigtness_numerator;
+ rsData.denominator = avsys_exif_info.brightness_denominator;
+ exif_set_srational(b, exif_data_get_byte_order(ed), rsData);
+ ret = mm_exif_set_add_entry(ed, EXIF_IFD_EXIF, EXIF_TAG_BRIGHTNESS_VALUE,
+ EXIF_FORMAT_SRATIONAL, 1, b);
+ free(b);
+ if (ret != MM_ERROR_NONE) {
+ EXIF_SET_ERR(ret, EXIF_TAG_BRIGHTNESS_VALUE);
+ }
+ } else {
+ _mmcam_dbg_warn( "malloc failed." );
+ }
+ } else {
+ _mmcam_dbg_log("Skip set EXIF_TAG_BRIGHTNESS_VALUE numerator [%d], denominatorr [%d]",
+ avsys_exif_info.brigtness_numerator, avsys_exif_info.brightness_denominator);
+ }
+
+ /*21. EXIF_TAG_EXPOSURE_BIAS_VALUE*/
+ value = 0;
+ ret = mm_camcorder_get_attributes(handle, NULL, MMCAM_FILTER_BRIGHTNESS, &value, NULL);
+ if (ret == MM_ERROR_NONE) {
+ unsigned char *b = NULL;
+ ExifSRational rsData;
+
+ _mmcam_dbg_log("EXIF_TAG_BRIGHTNESS_VALUE %d",value);
+
+ b = malloc(sizeof(ExifSRational));
+ if (b) {
+ rsData.numerator = value - 5;
+ rsData.denominator = 10;
+ exif_set_srational(b, exif_data_get_byte_order(ed), rsData);
+ ret = mm_exif_set_add_entry(ed, EXIF_IFD_EXIF, EXIF_TAG_EXPOSURE_BIAS_VALUE,
+ EXIF_FORMAT_SRATIONAL, 1, b);
+ free(b);
+ if (ret != MM_ERROR_NONE) {
+ EXIF_SET_ERR(ret, EXIF_TAG_EXPOSURE_BIAS_VALUE);
+ }
+ } else {
+ _mmcam_dbg_warn("malloc failed.");
+ }
+ } else {
+ _mmcam_dbg_log("failed to get MMCAM_FILTER_BRIGHTNESS [%x]", ret);
+ }
+
+ /*22 EXIF_TAG_MAX_APERTURE_VALUE*/
+/*
+ if (avsys_exif_info.max_lens_aperture_in_APEX) {
+ unsigned char *b = NULL;
+ ExifRational rData;
+
+ _mmcam_dbg_log("EXIF_TAG_MAX_APERTURE_VALUE [%d]", avsys_exif_info.max_lens_aperture_in_APEX);
+
+ b = malloc(sizeof(ExifRational));
+ if (b) {
+ rData.numerator = avsys_exif_info.max_lens_aperture_in_APEX;
+ rData.denominator = 1;
+ exif_set_rational(b, exif_data_get_byte_order(ed), rData);
+ ret = mm_exif_set_add_entry(ed, EXIF_IFD_EXIF, EXIF_TAG_MAX_APERTURE_VALUE,
+ EXIF_FORMAT_RATIONAL, 1, b);
+ free(b);
+ if (ret != MM_ERROR_NONE) {
+ EXIF_SET_ERR(ret, EXIF_TAG_MAX_APERTURE_VALUE);
+ }
+ } else {
+ _mmcam_dbg_warn("failed to alloc for MAX aperture value");
+ }
+ }
+*/
+
+ /*23. EXIF_TAG_SUBJECT_DISTANCE*/
+ /* defualt : none */
+
+ /*24. EXIF_TAG_METERING_MODE */
+ exif_set_short((unsigned char *)&eshort[cnts], exif_data_get_byte_order(ed),avsys_exif_info.metering_mode);
+ _mmcam_dbg_log("EXIF_TAG_METERING_MODE [%d]", avsys_exif_info.metering_mode);
+ ret = mm_exif_set_add_entry(ed, EXIF_IFD_EXIF, EXIF_TAG_METERING_MODE,
+ EXIF_FORMAT_SHORT, 1, (unsigned char *)&eshort[cnts++]);
+ if (ret != MM_ERROR_NONE) {
+ EXIF_SET_ERR(ret, EXIF_TAG_METERING_MODE);
+ }
+
+ /*25. EXIF_TAG_LIGHT_SOURCE*/
+
+ /*26. EXIF_TAG_FLASH*/
+ exif_set_short((unsigned char *)&eshort[cnts], exif_data_get_byte_order (ed),avsys_exif_info.flash);
+ _mmcam_dbg_log("EXIF_TAG_FLASH [%d]", avsys_exif_info.flash);
+ ret = mm_exif_set_add_entry(ed, EXIF_IFD_EXIF, EXIF_TAG_FLASH,
+ EXIF_FORMAT_SHORT, 1, (unsigned char *)&eshort[cnts++]);
+ if (ret != MM_ERROR_NONE) {
+ EXIF_SET_ERR(ret, EXIF_TAG_FLASH);
+ }
+
+ /*27. EXIF_TAG_FOCAL_LENGTH*/
+ if (avsys_exif_info.focal_len_numerator && avsys_exif_info.focal_len_denominator) {
+ unsigned char *b = NULL;
+ ExifRational rData;
+
+ _mmcam_dbg_log("EXIF_TAG_FOCAL_LENGTH numerator [%d], denominator [%d]",
+ avsys_exif_info.focal_len_numerator, avsys_exif_info.focal_len_denominator);
+
+ b = malloc(sizeof(ExifRational));
+ if (b) {
+ rData.numerator = avsys_exif_info.focal_len_numerator;
+ rData.denominator = avsys_exif_info.focal_len_denominator;
+ exif_set_rational(b, exif_data_get_byte_order(ed), rData);
+ ret = mm_exif_set_add_entry(ed, EXIF_IFD_EXIF, EXIF_TAG_FOCAL_LENGTH,
+ EXIF_FORMAT_RATIONAL, 1, b);
+ free(b);
+ if (ret != MM_ERROR_NONE) {
+ EXIF_SET_ERR(ret, EXIF_TAG_FOCAL_LENGTH);
+ }
+ } else {
+ _mmcam_dbg_warn("malloc failed.");
+ }
+ } else {
+ _mmcam_dbg_log("Skip set EXIF_TAG_FOCAL_LENGTH numerator [%d], denominator [%d]",
+ avsys_exif_info.focal_len_numerator, avsys_exif_info.focal_len_denominator);
+ }
+
+ /*28. EXIF_TAG_SENSING_METHOD*/
+ /*FIXME*/
+ value = MM_SENSING_MODE;
+ exif_set_short((unsigned char *)&eshort[cnts], exif_data_get_byte_order (ed),value);
+ ret = mm_exif_set_add_entry(ed, EXIF_IFD_EXIF, EXIF_TAG_SENSING_METHOD,
+ EXIF_FORMAT_SHORT, 1, (unsigned char *)&eshort[cnts++]);
+ if (ret != MM_ERROR_NONE) {
+ EXIF_SET_ERR(ret, EXIF_TAG_SENSING_METHOD);
+ }
+
+ /*29. EXIF_TAG_FILE_SOURCE*/
+/*
+ value = MM_FILE_SOURCE;
+ exif_set_long(&elong[cntl], exif_data_get_byte_order(ed),value);
+ ret = mm_exif_set_add_entry(ed, EXIF_IFD_EXIF, EXIF_TAG_FILE_SOURCE,
+ EXIF_FORMAT_UNDEFINED, 4, (unsigned char *)&elong[cntl++]);
+ if (ret != MM_ERROR_NONE) {
+ EXIF_SET_ERR(ret, EXIF_TAG_FILE_SOURCE);
+ }
+*/
+
+ /*30. EXIF_TAG_SCENE_TYPE*/
+/*
+ value = MM_SCENE_TYPE;
+ exif_set_long(&elong[cntl], exif_data_get_byte_order(ed),value);
+ ret = mm_exif_set_add_entry(ed, EXIF_IFD_EXIF, EXIF_TAG_SCENE_TYPE,
+ EXIF_FORMAT_UNDEFINED, 4, (unsigned char *)&elong[cntl++]);
+ if (ret != MM_ERROR_NONE) {
+ EXIF_SET_ERR(ret, EXIF_TAG_SCENE_TYPE);
+ }
+*/
+
+ /*31. EXIF_TAG_EXPOSURE_MODE*/
+ /*FIXME*/
+ value = MM_EXPOSURE_MODE;
+ exif_set_short((unsigned char *)&eshort[cnts], exif_data_get_byte_order(ed),value);
+ ret = mm_exif_set_add_entry(ed, EXIF_IFD_EXIF, EXIF_TAG_EXPOSURE_MODE,
+ EXIF_FORMAT_SHORT, 1, (unsigned char *)&eshort[cnts++]);
+ if (ret != MM_ERROR_NONE) {
+ EXIF_SET_ERR(ret, EXIF_TAG_EXPOSURE_MODE);
+ }
+
+
+ /*32. EXIF_TAG_WHITE_BALANCE*/
+ ret = mm_camcorder_get_attributes(handle, NULL, MMCAM_FILTER_WB, &value, NULL);
+ if (ret == MM_ERROR_NONE) {
+ int set_value = 0;
+ _mmcam_dbg_log("WHITE BALANCE [%d]", value);
+
+ if (value == MM_CAMCORDER_WHITE_BALANCE_AUTOMATIC) {
+ set_value = 0;
+ } else {
+ set_value = 1;
+ }
+
+ exif_set_short((unsigned char *)&eshort[cnts], exif_data_get_byte_order(ed), set_value);
+ ret = mm_exif_set_add_entry(ed, EXIF_IFD_EXIF, EXIF_TAG_WHITE_BALANCE,
+ EXIF_FORMAT_SHORT, 1, (unsigned char *)&eshort[cnts++]);
+ if (ret != MM_ERROR_NONE) {
+ EXIF_SET_ERR(ret, EXIF_TAG_WHITE_BALANCE);
+ }
+ } else {
+ _mmcam_dbg_warn("failed to get white balance [%x]", ret);
+ }
+
+ /*33. EXIF_TAG_DIGITAL_ZOOM_RATIO*/
+/*
+ ret = mm_camcorder_get_attributes(handle, NULL, MMCAM_CAMERA_DIGITAL_ZOOM, &value, NULL);
+ if (ret == MM_ERROR_NONE) {
+ _mmcam_dbg_log("DIGITAL ZOOM [%d]", value);
+
+ exif_set_long(&elong[cntl], exif_data_get_byte_order(ed), value);
+ ret = mm_exif_set_add_entry(ed, EXIF_IFD_EXIF, EXIF_TAG_DIGITAL_ZOOM_RATIO,
+ EXIF_FORMAT_LONG, 1, (unsigned char *)&elong[cntl++]);
+ if (ret != MM_ERROR_NONE) {
+ EXIF_SET_ERR(ret, EXIF_TAG_DIGITAL_ZOOM_RATIO);
+ }
+ } else {
+ _mmcam_dbg_warn("failed to get digital zoom [%x]", ret);
+ }
+*/
+
+ /*34. EXIF_TAG_FOCAL_LENGTH_IN_35MM_FILM*/
+ /*FIXME*/
+/*
+ value = MM_FOCAL_LENGTH_35MMFILM;
+ exif_set_short(&eshort[cnts], exif_data_get_byte_order(ed),value);
+ ret = mm_exif_set_add_entry(ed, EXIF_IFD_EXIF, EXIF_TAG_FOCAL_LENGTH_IN_35MM_FILM,
+ EXIF_FORMAT_SHORT, 1, (unsigned char *)&eshort[cnts++]);
+ if (ret != MM_ERROR_NONE) {
+ EXIF_SET_ERR(ret, EXIF_TAG_FOCAL_LENGTH_IN_35MM_FILM);
+ }
+*/
+
+ /*35. EXIF_TAG_SCENE_CAPTURE_TYPE*/
+ {
+ int scene_capture_type;
+
+ ret = mm_camcorder_get_attributes(handle, NULL, MMCAM_FILTER_SCENE_MODE, &value, NULL);
+ if (ret == MM_ERROR_NONE) {
+ _mmcam_dbg_log("Scene mode(program mode) [%d]", value);
+
+ if (value == MM_CAMCORDER_SCENE_MODE_NORMAL) {
+ scene_capture_type = 0; /* standard */
+ } else if (value == MM_CAMCORDER_SCENE_MODE_PORTRAIT) {
+ scene_capture_type = 2; /* portrait */
+ } else if (value == MM_CAMCORDER_SCENE_MODE_LANDSCAPE) {
+ scene_capture_type = 1; /* landscape */
+ } else if (value == MM_CAMCORDER_SCENE_MODE_NIGHT_SCENE) {
+ scene_capture_type = 3; /* night scene */
+ } else {
+ scene_capture_type = 4; /* Others */
+ }
+
+ exif_set_short((unsigned char *)&eshort[cnts], exif_data_get_byte_order(ed), scene_capture_type);
+ ret = mm_exif_set_add_entry(ed, EXIF_IFD_EXIF, EXIF_TAG_SCENE_CAPTURE_TYPE,
+ EXIF_FORMAT_SHORT, 1, (unsigned char *)&eshort[cnts++]);
+ if (ret != MM_ERROR_NONE) {
+ EXIF_SET_ERR(ret, EXIF_TAG_SCENE_CAPTURE_TYPE);
+ }
+ } else {
+ _mmcam_dbg_warn("failed to get scene mode [%x]", ret);
+ }
+ }
+
+ /*36. EXIF_TAG_GAIN_CONTROL*/
+ /*FIXME*/
+/*
+ value = MM_GAIN_CONTROL;
+ exif_set_long(&elong[cntl], exif_data_get_byte_order(ed), value);
+ ret = mm_exif_set_add_entry(ed, EXIF_IFD_EXIF, EXIF_TAG_GAIN_CONTROL,
+ EXIF_FORMAT_LONG, 1, (unsigned char *)&elong[cntl++]);
+ if (ret != MM_ERROR_NONE) {
+ EXIF_SET_ERR(ret, EXIF_TAG_GAIN_CONTROL);
+ }
+*/
+
+
+ /*37. EXIF_TAG_CONTRAST */
+ {
+ type_int_range *irange = NULL;
+ int level = 0;
+
+ _mmcamcorder_conf_get_value_int_range(hcamcorder->conf_ctrl,
+ CONFIGURE_CATEGORY_CTRL_EFFECT,
+ "Contrast",
+ &irange);
+ if (irange != NULL) {
+ mm_camcorder_get_attributes(handle, NULL, MMCAM_FILTER_CONTRAST, &value, NULL);
+
+ _mmcam_dbg_log("CONTRAST currentt [%d], default [%d]", value, irange->default_value);
+
+ if (value == irange->default_value) {
+ level = MM_VALUE_NORMAL;
+ } else if (value < irange->default_value) {
+ level = MM_VALUE_LOW;
+ } else {
+ level = MM_VALUE_HARD;
+ }
+
+ exif_set_short((unsigned char *)&eshort[cnts], exif_data_get_byte_order(ed), level);
+ ret = mm_exif_set_add_entry(ed, EXIF_IFD_EXIF, EXIF_TAG_CONTRAST,
+ EXIF_FORMAT_SHORT, 1, (unsigned char *)&eshort[cnts++]);
+ if (ret != MM_ERROR_NONE) {
+ EXIF_SET_ERR(ret, EXIF_TAG_CONTRAST);
+ }
+ } else {
+ _mmcam_dbg_warn("failed to get range of contrast");
+ }
+ }
+
+ /*38. EXIF_TAG_SATURATION*/
+ {
+ type_int_range *irange = NULL;
+ int level = 0;
+
+ _mmcamcorder_conf_get_value_int_range(hcamcorder->conf_ctrl,
+ CONFIGURE_CATEGORY_CTRL_EFFECT,
+ "Saturation",
+ &irange);
+ if (irange != NULL) {
+ mm_camcorder_get_attributes(handle, NULL, MMCAM_FILTER_SATURATION, &value, NULL);
+
+ _mmcam_dbg_log("SATURATION current [%d], default [%d]", value, irange->default_value);
+
+ if (value == irange->default_value) {
+ level = MM_VALUE_NORMAL;
+ } else if (value < irange->default_value) {
+ level = MM_VALUE_LOW;
+ } else {
+ level=MM_VALUE_HARD;
+ }
+
+ exif_set_short((unsigned char *)&eshort[cnts], exif_data_get_byte_order(ed), level);
+ ret = mm_exif_set_add_entry(ed, EXIF_IFD_EXIF, EXIF_TAG_SATURATION,
+ EXIF_FORMAT_SHORT, 1, (unsigned char *)&eshort[cnts++]);
+ if (ret != MM_ERROR_NONE) {
+ EXIF_SET_ERR(ret, EXIF_TAG_SATURATION);
+ }
+ } else {
+ _mmcam_dbg_warn("failed to get range of saturation");
+ }
+ }
+
+ /*39. EXIF_TAG_SHARPNESS*/
+ {
+ type_int_range *irange = NULL;
+ int level = 0;
+
+ _mmcamcorder_conf_get_value_int_range(hcamcorder->conf_ctrl,
+ CONFIGURE_CATEGORY_CTRL_EFFECT,
+ "Sharpness",
+ &irange);
+ if (irange != NULL) {
+ mm_camcorder_get_attributes(handle, NULL, MMCAM_FILTER_SHARPNESS, &value, NULL);
+
+ _mmcam_dbg_log("SHARPNESS current [%d], default [%d]", value, irange->default_value);
+
+ if (value == irange->default_value) {
+ level = MM_VALUE_NORMAL;
+ } else if (value < irange->default_value) {
+ level = MM_VALUE_LOW;
+ } else {
+ level = MM_VALUE_HARD;
+ }
+
+ exif_set_short((unsigned char *)&eshort[cnts], exif_data_get_byte_order(ed), level);
+ ret = mm_exif_set_add_entry(ed, EXIF_IFD_EXIF, EXIF_TAG_SHARPNESS,
+ EXIF_FORMAT_SHORT, 1, (unsigned char *)&eshort[cnts++]);
+ if (ret != MM_ERROR_NONE) {
+ EXIF_SET_ERR(ret, EXIF_TAG_SHARPNESS);
+ }
+ } else {
+ _mmcam_dbg_warn("failed to get range of sharpness");
+ }
+ }
+
+ /*40. EXIF_TAG_SUBJECT_DISTANCE_RANGE*/
+ /*FIXME*/
+ value = MM_SUBJECT_DISTANCE_RANGE;
+ _mmcam_dbg_log("DISTANCE_RANGE [%d]", value);
+ exif_set_short((unsigned char *)&eshort[cnts], exif_data_get_byte_order(ed), value);
+ ret = mm_exif_set_add_entry(ed, EXIF_IFD_EXIF, EXIF_TAG_SUBJECT_DISTANCE_RANGE,
+ EXIF_FORMAT_SHORT, 1, (unsigned char *)&eshort[cnts++]);
+ if (ret != MM_ERROR_NONE) {
+ EXIF_SET_ERR(ret, EXIF_TAG_SUBJECT_DISTANCE_RANGE);
+ }
+
+ /* GPS information */
+ ret = mm_camcorder_get_attributes(handle, NULL, MMCAM_TAG_GPS_ENABLE, &gps_enable, NULL);
+ if (ret == MM_ERROR_NONE && gps_enable) {
+ ExifByte GpsVersion[4]={2,2,0,0};
+
+ _mmcam_dbg_log("Tag for GPS is ENABLED.");
+
+ ret = mm_exif_set_add_entry(ed, EXIF_IFD_GPS, EXIF_TAG_GPS_VERSION_ID,
+ EXIF_FORMAT_BYTE, 4, (unsigned char *)&GpsVersion);
+ if (ret != MM_ERROR_NONE) {
+ EXIF_SET_ERR(ret, EXIF_TAG_GPS_VERSION_ID);
+ }
+
+ /*41. Latitude*/
+ ret = mm_camcorder_get_attributes(handle, &err_name,
+ MMCAM_TAG_LATITUDE, &f_latitude,
+ MMCAM_TAG_LONGITUDE, &f_longitude,
+ MMCAM_TAG_ALTITUDE, &f_altitude, NULL);
+ if (ret != MM_ERROR_NONE) {
+ _mmcam_dbg_err("failed to get gps info [%x][%s]", ret, err_name);
+ SAFE_FREE(err_name);
+ goto exit;
+ }
+
+ _mmcam_dbg_log("f_latitude [%f]", f_latitude);
+ if (f_latitude != INVALID_GPS_VALUE) {
+ unsigned char *b = NULL;
+ unsigned int deg;
+ unsigned int min;
+ unsigned int sec;
+ ExifRational rData;
+
+ if (f_latitude < 0) {
+ ret = mm_exif_set_add_entry(ed, EXIF_IFD_GPS, EXIF_TAG_GPS_LATITUDE_REF,
+ EXIF_FORMAT_ASCII, 2, (unsigned char *)"S");
+ if (ret != MM_ERROR_NONE) {
+ EXIF_SET_ERR(ret, EXIF_TAG_GPS_LATITUDE_REF);
+ }
+ f_latitude = -f_latitude;
+ } else if (f_latitude > 0) {
+ ret = mm_exif_set_add_entry(ed, EXIF_IFD_GPS, EXIF_TAG_GPS_LATITUDE_REF,
+ EXIF_FORMAT_ASCII, 2, (unsigned char *)"N");
+ if (ret != MM_ERROR_NONE) {
+ EXIF_SET_ERR(ret, EXIF_TAG_GPS_LATITUDE_REF);
+ }
+ }
+
+ deg = (unsigned int)(f_latitude);
+ min = (unsigned int)((f_latitude-deg)*60);
+ sec = (unsigned int)(((f_latitude-deg)*3600)-min*60);
+
+ _mmcam_dbg_log("f_latitude deg[%d], min[%d], sec[%d]", deg, min, sec);
+ b = malloc(3 * sizeof(ExifRational));
+ if (b) {
+ rData.numerator = deg;
+ rData.denominator = 1;
+ exif_set_rational(b, exif_data_get_byte_order(ed), rData);
+ rData.numerator = min;
+ exif_set_rational(b+8, exif_data_get_byte_order(ed), rData);
+ rData.numerator = sec;
+ exif_set_rational(b+16, exif_data_get_byte_order(ed), rData);
+
+ ret = mm_exif_set_add_entry(ed, EXIF_IFD_GPS, EXIF_TAG_GPS_LATITUDE,
+ EXIF_FORMAT_RATIONAL, 3, (unsigned char *)b);
+ free(b);
+ if (ret != MM_ERROR_NONE) {
+ EXIF_SET_ERR(ret, EXIF_TAG_GPS_LATITUDE);
+ }
+ } else {
+ _mmcam_dbg_warn("malloc failed");
+ }
+ }
+
+ /*42. Longitude*/
+ _mmcam_dbg_log("f_longitude [%f]", f_longitude);
+ if (f_longitude != INVALID_GPS_VALUE) {
+ unsigned char *b = NULL;
+ unsigned int deg;
+ unsigned int min;
+ unsigned int sec;
+ ExifRational rData;
+
+ if (f_longitude < 0) {
+ ret = mm_exif_set_add_entry(ed, EXIF_IFD_GPS, EXIF_TAG_GPS_LONGITUDE_REF,
+ EXIF_FORMAT_ASCII, 2, (unsigned char *)"W");
+ if (ret != MM_ERROR_NONE) {
+ EXIF_SET_ERR(ret, EXIF_TAG_GPS_LONGITUDE_REF);
+ }
+ f_longitude = -f_longitude;
+ } else if (f_longitude > 0) {
+ ret = mm_exif_set_add_entry(ed, EXIF_IFD_GPS, EXIF_TAG_GPS_LONGITUDE_REF,
+ EXIF_FORMAT_ASCII, 2, (unsigned char *)"E");
+ if (ret != MM_ERROR_NONE) {
+ EXIF_SET_ERR(ret, EXIF_TAG_GPS_LONGITUDE_REF);
+ }
+ }
+
+ deg = (unsigned int)(f_longitude);
+ min = (unsigned int)((f_longitude-deg)*60);
+ sec = (unsigned int)(((f_longitude-deg)*3600)-min*60);
+
+ _mmcam_dbg_log("f_longitude deg[%d], min[%d], sec[%d]", deg, min, sec);
+ b = malloc(3 * sizeof(ExifRational));
+ if (b) {
+ rData.numerator = deg;
+ rData.denominator = 1;
+ exif_set_rational(b, exif_data_get_byte_order(ed), rData);
+ rData.numerator = min;
+ exif_set_rational(b+8, exif_data_get_byte_order(ed), rData);
+ rData.numerator = sec;
+ exif_set_rational(b+16, exif_data_get_byte_order(ed), rData);
+ ret = mm_exif_set_add_entry(ed, EXIF_IFD_GPS, EXIF_TAG_GPS_LONGITUDE,
+ EXIF_FORMAT_RATIONAL, 3, (unsigned char *)b);
+ free(b);
+ if (ret != MM_ERROR_NONE) {
+ EXIF_SET_ERR(ret, EXIF_TAG_GPS_LONGITUDE);
+ }
+ } else {
+ _mmcam_dbg_warn("malloc failed");
+ }
+ }
+
+ /*43. Altitude*/
+ _mmcam_dbg_log("f_altitude [%f]", f_altitude);
+ if (f_altitude != INVALID_GPS_VALUE) {
+ ExifByte alt_ref = 0;
+ unsigned char *b = NULL;
+ ExifRational rData;
+ b = malloc(sizeof(ExifRational));
+ if (b) {
+ if (f_altitude < 0) {
+ alt_ref = 1;
+ f_altitude = -f_altitude;
+ }
+
+ ret = mm_exif_set_add_entry(ed, EXIF_IFD_GPS, EXIF_TAG_GPS_ALTITUDE_REF,
+ EXIF_FORMAT_BYTE, 1, (unsigned char *)&alt_ref);
+ if (ret != MM_ERROR_NONE) {
+ _mmcam_dbg_err("error [%x], tag [%x]", ret, EXIF_TAG_GPS_ALTITUDE_REF);
+ if (ret == MM_ERROR_CAMCORDER_LOW_MEMORY) {
+ free(b);
+ b = NULL;
+ goto exit;
+ }
+ }
+
+ rData.numerator = (unsigned int)(f_altitude + 0.5)*100;
+ rData.denominator = 100;
+ exif_set_rational(b, exif_data_get_byte_order(ed), rData);
+ ret = mm_exif_set_add_entry(ed, EXIF_IFD_GPS, EXIF_TAG_GPS_ALTITUDE,
+ EXIF_FORMAT_RATIONAL, 1, (unsigned char *)b);
+ free(b);
+ if (ret != MM_ERROR_NONE) {
+ EXIF_SET_ERR(ret, EXIF_TAG_GPS_ALTITUDE);
+ }
+ } else {
+ _mmcam_dbg_warn("malloc failed");
+ }
+ }
+
+ /*44. EXIF_TAG_GPS_TIME_STAMP*/
+ {
+ double gps_timestamp = INVALID_GPS_VALUE;
+ mm_camcorder_get_attributes(handle, NULL, "tag-gps-time-stamp", &gps_timestamp, NULL);
+ _mmcam_dbg_log("Gps timestamp [%f]", gps_timestamp);
+ if (gps_timestamp > 0.0) {
+ unsigned char *b = NULL;
+ unsigned int hour;
+ unsigned int min;
+ unsigned int microsec;
+ ExifRational rData;
+
+ hour = (unsigned int)(gps_timestamp / 3600);
+ min = (unsigned int)((gps_timestamp - 3600 * hour) / 60);
+ microsec = (unsigned int)(((double)((double)gps_timestamp -(double)(3600 * hour)) -(double)(60 * min)) * 1000000);
+
+ _mmcam_dbg_log("Gps timestamp hour[%d], min[%d], microsec[%d]", hour, min, microsec);
+ b = malloc(3 * sizeof(ExifRational));
+ if (b) {
+ rData.numerator = hour;
+ rData.denominator = 1;
+ exif_set_rational(b, exif_data_get_byte_order(ed), rData);
+
+ rData.numerator = min;
+ rData.denominator = 1;
+ exif_set_rational(b + 8, exif_data_get_byte_order(ed), rData);
+
+ rData.numerator = microsec;
+ rData.denominator = 1000000;
+ exif_set_rational(b + 16, exif_data_get_byte_order(ed), rData);
+
+ ret = mm_exif_set_add_entry(ed, EXIF_IFD_GPS, EXIF_TAG_GPS_TIME_STAMP,
+ EXIF_FORMAT_RATIONAL, 3, b);
+ free(b);
+ if (ret != MM_ERROR_NONE) {
+ EXIF_SET_ERR(ret, EXIF_TAG_GPS_TIME_STAMP);
+ }
+ } else {
+ _mmcam_dbg_warn( "malloc failed." );
+ }
+ }
+ }
+
+ /*45. EXIF_TAG_GPS_DATE_STAMP*/
+ {
+ unsigned char *date_stamp = NULL;
+ int date_stamp_len = 0;
+
+ mm_camcorder_get_attributes(handle, NULL, "tag-gps-date-stamp", &date_stamp, &date_stamp_len, NULL);
+
+ if (date_stamp) {
+ _mmcam_dbg_log("Date stamp [%s]", date_stamp);
+
+ /* cause it should include NULL char */
+ ret = mm_exif_set_add_entry(ed, EXIF_IFD_GPS, EXIF_TAG_GPS_DATE_STAMP,
+ EXIF_FORMAT_ASCII, date_stamp_len + 1, date_stamp);
+ if (ret != MM_ERROR_NONE) {
+ EXIF_SET_ERR(ret, EXIF_TAG_GPS_DATE_STAMP);
+ }
+ }
+ }
+
+ /*46. EXIF_TAG_GPS_PROCESSING_METHOD */
+ {
+ unsigned char *processing_method = NULL;
+ int processing_method_len = 0;
+
+ mm_camcorder_get_attributes(handle, NULL, "tag-gps-processing-method", &processing_method, &processing_method_len, NULL);
+
+ if (processing_method) {
+ _mmcam_dbg_log("Processing method [%s]", processing_method);
+
+ ret = mm_exif_set_add_entry(ed, EXIF_IFD_GPS, EXIF_TAG_GPS_PROCESSING_METHOD,
+ EXIF_FORMAT_UNDEFINED, processing_method_len, processing_method);
+ if (ret != MM_ERROR_NONE) {
+ EXIF_SET_ERR(ret, EXIF_TAG_GPS_PROCESSING_METHOD);
+ }
+ }
+ }
+ } else {
+ _mmcam_dbg_log( "Tag for GPS is DISABLED." );
+ }
+
+
+ /*47. EXIF_TAG_MAKER_NOTE*/
+ ret = mm_exif_set_add_entry(ed, EXIF_IFD_EXIF, EXIF_TAG_MAKER_NOTE,
+ EXIF_FORMAT_UNDEFINED, 8, (unsigned char *)"SAMSUNG");
+ if (ret != MM_ERROR_NONE) {
+ EXIF_SET_ERR(ret, EXIF_TAG_MAKER_NOTE);
+ }
+
+ /* create and link samsung maker note */
+ ret = mm_exif_mnote_create(ed);
+ if (ret != MM_ERROR_NONE){
+ EXIF_SET_ERR(ret, EXIF_TAG_MAKER_NOTE);
+ } else {
+ _mmcam_dbg_log("Samsung makernote created");
+
+ /* add samsung maker note entries (param : data, tag, index, subtag index1, subtag index2) */
+ ret = mm_exif_mnote_set_add_entry(ed, MNOTE_SAMSUNG_TAG_MNOTE_VERSION, 0, _MNOTE_VALUE_NONE, _MNOTE_VALUE_NONE);
+ if (ret != MM_ERROR_NONE) {
+ _mmcam_dbg_err("mm_exif_mnote_set_add_entry error! [%x]", ret);
+ }
+ /*
+ ret = mm_exif_mnote_set_add_entry(ed, MNOTE_SAMSUNG_TAG_DEVICE_ID, 2, _MNOTE_VALUE_NONE, _MNOTE_VALUE_NONE);
+ if (ret != MM_ERROR_NONE) {
+ _mmcam_dbg_err("mm_exif_mnote_set_add_entry error! [%x]", ret);
+ }
+
+ ret = mm_exif_mnote_set_add_entry(ed, MNOTE_SAMSUNG_TAG_SERIAL_NUM, _MNOTE_VALUE_NONE, _MNOTE_VALUE_NONE, _MNOTE_VALUE_NONE);
+ if (ret != MM_ERROR_NONE) {
+ _mmcam_dbg_err("mm_exif_mnote_set_add_entry error! [%x]", ret);
+ }
+
+ ret = mm_exif_mnote_set_add_entry(ed, MNOTE_SAMSUNG_TAG_COLOR_SPACE, 1, _MNOTE_VALUE_NONE, _MNOTE_VALUE_NONE);
+ if (ret != MM_ERROR_NONE) {
+ _mmcam_dbg_err("mm_exif_mnote_set_add_entry error! [%x]", ret);
+ }
+ */
+ ret = mm_exif_mnote_set_add_entry(ed, MNOTE_SAMSUNG_TAG_FACE_DETECTION, 0, _MNOTE_VALUE_NONE, _MNOTE_VALUE_NONE);
+ if (ret != MM_ERROR_NONE) {
+ _mmcam_dbg_err("mm_exif_mnote_set_add_entry error! ret=%x", ret);
+ }
+ /*
+ ret = mm_exif_mnote_set_add_entry(ed, MNOTE_SAMSUNG_TAG_MODEL_ID, _MNOTE_VALUE_NONE, 3, 2);
+ if (ret != MM_ERROR_NONE) {
+ _mmcam_dbg_err("mm_exif_mnote_set_add_entry error! [%x]", ret);
+ }
+ */
+ }
+
+ _mmcam_dbg_log("");
+
+ ret = mm_exif_set_exif_to_info(hcamcorder->exif_info, ed);
+ if (ret != MM_ERROR_NONE) {
+ _mmcam_dbg_err("mm_exif_set_exif_to_info err!! [%x]", ret);
+ }
+
+exit:
+ _mmcam_dbg_log("finished!! [%x]", ret);
+
+ if (ed) {
+ exif_data_unref (ed);
+ }
+
+ return ret;
+}
diff --git a/src/mm_camcorder_util.c b/src/mm_camcorder_util.c
new file mode 100644
index 0000000..688cc31
--- /dev/null
+++ b/src/mm_camcorder_util.c
@@ -0,0 +1,1092 @@
+/*
+ * libmm-camcorder
+ *
+ * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: Jeongmo Yang <jm80.yang@samsung.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+/*===========================================================================================
+| |
+| INCLUDE FILES |
+| |
+========================================================================================== */
+#include <stdio.h>
+#include <stdarg.h>
+#include <camsrcjpegenc.h>
+#include <sys/vfs.h> /* struct statfs */
+
+#include "mm_camcorder_internal.h"
+#include "mm_camcorder_util.h"
+
+/*---------------------------------------------------------------------------
+| GLOBAL VARIABLE DEFINITIONS for internal |
+---------------------------------------------------------------------------*/
+
+/*---------------------------------------------------------------------------
+| LOCAL VARIABLE DEFINITIONS for internal |
+---------------------------------------------------------------------------*/
+#define TIME_STRING_MAX_LEN 64
+#define FPUTC_CHECK(x_char, x_file)\
+{\
+ if (fputc(x_char, x_file) == EOF) \
+ {\
+ _mmcam_dbg_err("[Critical] fputc() returns fail.\n"); \
+ return FALSE;\
+ }\
+}
+#define FPUTS_CHECK(x_str, x_file)\
+{\
+ if (fputs(x_str, x_file) == EOF) \
+ {\
+ _mmcam_dbg_err("[Critical] fputs() returns fail.\n");\
+ SAFE_FREE(str); \
+ return FALSE;\
+ }\
+}
+
+/*---------------------------------------------------------------------------
+| 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);
+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);
+
+/*===========================================================================================
+| |
+| FUNCTION DEFINITIONS |
+| |
+========================================================================================== */
+/*---------------------------------------------------------------------------
+| GLOBAL FUNCTION DEFINITIONS: |
+---------------------------------------------------------------------------*/
+
+gint32 _mmcamcorder_double_to_fix(gdouble d_number)
+{
+ return (gint32) (d_number * 65536.0);
+}
+
+// find top level tag only, do not use this function for finding sub level tags
+gint _mmcamcorder_find_tag(FILE *f, guint32 tag_fourcc)
+{
+ guchar buf[8];
+
+ rewind(f);
+
+ while(fread(&buf, sizeof(guchar), 8, f)>0)
+ {
+ gulong buf_size = 0;
+ guint32 buf_fourcc = MMCAM_FOURCC(buf[4], buf[5],buf[6],buf[7]);
+
+ if(tag_fourcc == buf_fourcc)
+ {
+ _mmcam_dbg_log("find tag : %c%c%c%c", MMCAM_FOURCC_ARGS(tag_fourcc));
+ return 1;
+ }
+ else
+ {
+ _mmcam_dbg_log("skip [%c%c%c%c] tag", MMCAM_FOURCC_ARGS(buf_fourcc));
+ buf_size = _mmcamcorder_get_container_size(buf);
+ if(fseek(f, buf_size-8, SEEK_CUR) != 0)
+ {
+ _mmcam_dbg_err("fseek() fail");
+ return 0;
+ }
+ }
+ }
+ _mmcam_dbg_log("cannot find tag : %c%c%c%c", MMCAM_FOURCC_ARGS(tag_fourcc));
+ return 0;
+}
+
+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)
+ {
+ _mmcam_dbg_err("fseek() fail");
+ return FALSE;
+ }
+
+ if (!write_to_32(f, curr_pos -prev_pos))
+ return FALSE;
+
+ if(fseek(f, curr_pos, SEEK_SET) != 0)
+ {
+ _mmcam_dbg_err("fseek() fail");
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+gboolean _mmcamcorder_write_loci(FILE *f, _MMCamcorderLocationInfo info)
+{
+ gint64 current_pos, pos;
+ gchar *str = NULL;
+
+ _mmcam_dbg_log("");
+
+ if((pos = ftell(f))<0)
+ {
+ _mmcam_dbg_err("ftell() returns negative value");
+ return FALSE;
+ }
+
+ if(!write_to_32(f, 0)) //size
+ return FALSE;
+
+ 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)
+ {
+ _mmcam_dbg_err("ftell() returns negative value");
+ return FALSE;
+ }
+
+ if(! _mmcamcorder_update_size(f, pos, current_pos))
+ return FALSE;
+
+ return TRUE;
+}
+
+gboolean _mmcamcorder_write_udta(FILE *f, _MMCamcorderLocationInfo info)
+{
+ gint64 current_pos, pos;
+
+ _mmcam_dbg_log("");
+
+ if((pos = ftell(f))<0)
+ {
+ _mmcam_dbg_err("ftell() returns negative value");
+ return FALSE;
+ }
+
+ if(!write_to_32(f, 0)) //size
+ return FALSE;
+
+ if(!write_tag(f, "udta")) // type
+ return FALSE;
+
+ if(! _mmcamcorder_write_loci(f, info))
+ return FALSE;
+
+ if((current_pos = ftell(f))<0)
+ {
+ _mmcam_dbg_err("ftell() returns negative value");
+ return FALSE;
+ }
+
+ if(! _mmcamcorder_update_size(f, pos, current_pos))
+ return FALSE;
+
+
+ return TRUE;
+}
+
+
+gulong _mmcamcorder_get_container_size(const guchar *size)
+{
+ gulong result = 0;
+ gulong temp = 0;
+ temp = size[0];
+ result = temp << 24;
+ temp = size[1];
+ result = result | (temp << 16);
+ temp = size[2];
+ result = result | (temp << 8);
+ result = result | size[3];
+ return result;
+}
+
+
+int _mmcamcorder_get_freespace(const gchar *path, guint64 *free_space)
+{
+ struct statfs fs;
+
+ g_assert(path);
+
+ 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 (-1 == statfs(path, &fs)) {
+ _mmcam_dbg_log("Getting free space is failed.(%s)", path);
+ return -1;
+ }
+
+ *free_space = (guint64)fs.f_bsize * fs.f_bavail;
+ return 1;
+}
+
+
+int _mmcamcorder_get_file_size(const char *filename, guint64 *size)
+{
+ struct stat buf;
+
+ if (stat(filename, &buf) != 0)
+ return -1;
+ *size = (guint64)buf.st_size;
+ return 1;
+}
+
+
+void _mmcamcorder_remove_buffer_probe(MMHandleType handle, _MMCamcorderHandlerCategory category)
+{
+ mmf_camcorder_t* hcamcorder = MMF_CAMCORDER(handle);
+ GList *list = NULL;
+ MMCamcorderHandlerItem *item = NULL;
+
+ mmf_return_if_fail(hcamcorder);
+
+ if(!hcamcorder->buffer_probes)
+ {
+ _mmcam_dbg_err("Fail to remove buffer probe, list for buffer probe is NULL");
+ }
+
+ list = hcamcorder->buffer_probes;
+
+ while(list)
+ {
+ item = list->data;
+
+ if(!item)
+ {
+ _mmcam_dbg_err("Remove buffer probe faild, the item is NULL");
+ list = g_list_next(list);
+ continue;
+ }
+
+ if(item->category & category)
+ {
+
+ 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);
+ }
+ else
+ {
+ _mmcam_dbg_warn("Remove buffer probe faild, the pad is null or not pad, just remove item from list and free it");
+ }
+
+ list = g_list_next(list);
+ hcamcorder->buffer_probes = g_list_remove(hcamcorder->buffer_probes, item);
+ SAFE_FREE(item);
+ }
+ else
+ {
+ _mmcam_dbg_log("Skip item : [ID : %lu], [Category : %x] ", item->handler_id, item->category);
+ list = g_list_next(list);
+ }
+ }
+
+ if( category == _MMCAMCORDER_HANDLER_CATEGORY_ALL)
+ {
+ g_list_free(hcamcorder->buffer_probes);
+ hcamcorder->buffer_probes = NULL;
+ }
+}
+
+void _mmcamcorder_remove_event_probe(MMHandleType handle, _MMCamcorderHandlerCategory category)
+{
+ mmf_camcorder_t* hcamcorder = MMF_CAMCORDER(handle);
+ GList *list = NULL;
+ MMCamcorderHandlerItem *item = NULL;
+
+ mmf_return_if_fail(hcamcorder);
+
+ if(!hcamcorder->event_probes)
+ {
+ _mmcam_dbg_err("Fail to remove event probe, list for event probe is NULL");
+ }
+
+ list = hcamcorder->event_probes;
+
+ while(list)
+ {
+ item = list->data;
+
+ if(!item)
+ {
+ _mmcam_dbg_err("Remove event probe faild, the item is NULL");
+ list = g_list_next(list);
+ continue;
+ }
+
+ if(item->category & category)
+ {
+
+ 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);
+ }
+ else
+ {
+ _mmcam_dbg_warn("Remove event probe faild, the pad is null or not pad, just remove item from list and free it");
+ }
+
+ list = g_list_next(list);
+ hcamcorder->event_probes = g_list_remove(hcamcorder->event_probes, item);
+ SAFE_FREE(item);
+ }
+ else
+ {
+ _mmcam_dbg_log("Skip item : [ID : %lu], [Category : %x] ", item->handler_id, item->category);
+ list = g_list_next(list);
+ }
+ }
+
+ if( category == _MMCAMCORDER_HANDLER_CATEGORY_ALL)
+ {
+ g_list_free(hcamcorder->event_probes);
+ hcamcorder->event_probes = NULL;
+ }
+}
+
+void _mmcamcorder_remove_data_probe(MMHandleType handle, _MMCamcorderHandlerCategory category)
+{
+ mmf_camcorder_t* hcamcorder = MMF_CAMCORDER(handle);
+ GList *list = NULL;
+ MMCamcorderHandlerItem *item = NULL;
+
+ mmf_return_if_fail(hcamcorder);
+
+ if(!hcamcorder->data_probes)
+ {
+ _mmcam_dbg_err("Fail to remove data probe, list for data probe is NULL");
+ }
+
+ list = hcamcorder->data_probes;
+
+ while(list)
+ {
+ item = list->data;
+
+ if(!item)
+ {
+ _mmcam_dbg_err("Remove data probe faild, the item is NULL");
+ list = g_list_next(list);
+ continue;
+ }
+
+ if(item->category & category)
+ {
+
+ if(item->object && GST_IS_PAD(item->object))
+ {
+ _mmcam_dbg_log("Remove data probe on [%s:%s] - [ID : %lu], [Category : %x]",
+ GST_DEBUG_PAD_NAME(item->object), item->handler_id, item->category);
+ gst_pad_remove_data_probe(GST_PAD(item->object), item->handler_id);
+ }
+ else
+ {
+ _mmcam_dbg_warn("Remove data probe faild, the pad is null or not pad, just remove item from list and free it");
+ }
+
+ list = g_list_next(list);
+ hcamcorder->data_probes = g_list_remove(hcamcorder->data_probes, item);
+ SAFE_FREE(item);
+ }
+ else
+ {
+ _mmcam_dbg_log("Skip item : [ID : %lu], [Category : %x] ", item->handler_id, item->category);
+ list = g_list_next(list);
+ }
+ }
+
+ if( category == _MMCAMCORDER_HANDLER_CATEGORY_ALL)
+ {
+ g_list_free(hcamcorder->data_probes);
+ hcamcorder->data_probes = NULL;
+ }
+}
+
+void _mmcamcorder_disconnect_signal(MMHandleType handle, _MMCamcorderHandlerCategory category)
+{
+ mmf_camcorder_t* hcamcorder = MMF_CAMCORDER(handle);
+ GList *list = NULL;
+ MMCamcorderHandlerItem *item = NULL;
+
+ mmf_return_if_fail(hcamcorder);
+
+ if(!hcamcorder->signals)
+ {
+ _mmcam_dbg_err("Fail to disconnect signals, list for signal is NULL");
+ }
+
+ list = hcamcorder->signals;
+
+ while(list)
+ {
+ item = list->data;
+
+ if(!item)
+ {
+ _mmcam_dbg_err("Fail to Disconnecting signal, the item is NULL");
+ list = g_list_next(list);
+ continue;
+ }
+
+ if(item->category & category)
+ {
+
+ if(item->object && GST_IS_ELEMENT(item->object))
+ {
+ if ( g_signal_handler_is_connected ( item->object, item->handler_id ) )
+ {
+ _mmcam_dbg_log("Disconnect signal from [%s] : [ID : %lu], [Category : %x]",
+ GST_OBJECT_NAME(item->object), item->handler_id, item->category);
+ g_signal_handler_disconnect ( item->object, item->handler_id );
+ }
+ else
+ {
+ _mmcam_dbg_warn("Signal was not connected, cannot disconnect it : [%s] [ID : %lu], [Category : %x]",
+ GST_OBJECT_NAME(item->object), item->handler_id, item->category);
+ }
+
+ }
+ else
+ {
+ _mmcam_dbg_err("Fail to Disconnecting signal, the element is null or not element, just remove item from list and free it");
+ }
+
+ list = g_list_next(list);
+ hcamcorder->signals = g_list_remove(hcamcorder->signals, item);
+ SAFE_FREE(item);
+ }
+ else
+ {
+ _mmcam_dbg_log("Skip item : [ID : %lu], [Category : %x] ", item->handler_id, item->category);
+ list = g_list_next(list);
+ }
+ }
+
+ if( category == _MMCAMCORDER_HANDLER_CATEGORY_ALL)
+ {
+ g_list_free(hcamcorder->signals);
+ hcamcorder->signals = NULL;
+ }
+}
+
+void _mmcamcorder_remove_all_handlers(MMHandleType handle, _MMCamcorderHandlerCategory category)
+{
+ mmf_camcorder_t* hcamcorder = MMF_CAMCORDER(handle);
+
+ _mmcam_dbg_log("ENTER");
+
+ if(hcamcorder->signals)
+ _mmcamcorder_disconnect_signal((MMHandleType)hcamcorder, category);
+ if(hcamcorder->data_probes)
+ _mmcamcorder_remove_data_probe((MMHandleType)hcamcorder, category);
+ if(hcamcorder->event_probes)
+ _mmcamcorder_remove_event_probe((MMHandleType)hcamcorder, category);
+ if(hcamcorder->buffer_probes)
+ _mmcamcorder_remove_buffer_probe((MMHandleType)hcamcorder, category);
+
+ _mmcam_dbg_log("LEAVE");
+}
+
+void _mmcamcorder_element_release_noti(gpointer data, GObject *where_the_object_was)
+{
+ int i=0;
+ _MMCamcorderSubContext *sc = (_MMCamcorderSubContext *)data;
+ mmf_return_if_fail(sc);
+ mmf_return_if_fail(sc->element);
+
+ for(i=0;i< _MMCamcorder_PIPELINE_ELEMENT_NUM; i++)
+ {
+ if(sc->element[i].gst && (G_OBJECT(sc->element[i].gst) == where_the_object_was))
+ {
+ _mmcam_dbg_log("The element[%d][%p] is finalized", sc->element[i].id, sc->element[i].gst);
+ sc->element[i].gst = NULL;
+ sc->element[i].id = _MMCAMCORDER_NONE;
+ break;
+ }
+ }
+}
+
+
+gboolean
+_mmcamcroder_msg_callback(void *data)
+{
+ _MMCamcorderMsgItem * item = (_MMCamcorderMsgItem*)data;
+ mmf_camcorder_t *hcamcorder= NULL;
+ mmf_return_val_if_fail( item, FALSE );
+
+ hcamcorder = MMF_CAMCORDER(item->handle);
+ mmf_return_val_if_fail( hcamcorder, FALSE );
+
+// _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_MESSAGE_CALLBACK( hcamcorder );
+
+ if ((hcamcorder) && (hcamcorder->msg_cb)) {
+ hcamcorder->msg_cb(item->id, (MMMessageParamType*)(&(item->param)), hcamcorder->msg_cb_param);
+ }
+
+ _MMCAMCORDER_UNLOCK_MESSAGE_CALLBACK( hcamcorder );
+
+ _MMCAMCORDER_LOCK((MMHandleType)hcamcorder);
+
+ if (hcamcorder->msg_data)
+ hcamcorder->msg_data = g_list_remove(hcamcorder->msg_data, item);
+
+ SAFE_FREE(item);
+
+ _MMCAMCORDER_UNLOCK((MMHandleType)hcamcorder);
+
+ return FALSE; //For not being called again
+}
+
+
+gboolean
+_mmcamcroder_send_message(MMHandleType handle, _MMCamcorderMsgItem *data)
+{
+ mmf_camcorder_t* hcamcorder = MMF_CAMCORDER(handle);
+ _MMCamcorderMsgItem *item = NULL;
+
+ mmf_return_val_if_fail(hcamcorder, FALSE);
+ mmf_return_val_if_fail(data, FALSE);
+
+ switch (data->id)
+ {
+ case MM_MESSAGE_CAMCORDER_STATE_CHANGED:
+ case MM_MESSAGE_CAMCORDER_STATE_CHANGED_BY_ASM:
+ data->param.union_type = MM_MSG_UNION_STATE;
+ break;
+ case MM_MESSAGE_CAMCORDER_RECORDING_STATUS:
+ data->param.union_type = MM_MSG_UNION_RECORDING_STATUS;
+ break;
+ case MM_MESSAGE_CAMCORDER_FIRMWARE_UPDATE:
+ data->param.union_type = MM_MSG_UNION_FIRMWARE;
+ break;
+ case MM_MESSAGE_CAMCORDER_CURRENT_VOLUME:
+ data->param.union_type = MM_MSG_UNION_REC_VOLUME_DB;
+ break;
+ case MM_MESSAGE_CAMCORDER_TIME_LIMIT:
+ case MM_MESSAGE_CAMCORDER_MAX_SIZE:
+ case MM_MESSAGE_CAMCORDER_NO_FREE_SPACE:
+ case MM_MESSAGE_CAMCORDER_ERROR:
+ case MM_MESSAGE_CAMCORDER_FOCUS_CHANGED:
+ case MM_MESSAGE_CAMCORDER_CAPTURED:
+ case MM_MESSAGE_READY_TO_RESUME:
+ default:
+ data->param.union_type = MM_MSG_UNION_CODE;
+ break;
+ }
+
+ item = g_malloc(sizeof(_MMCamcorderMsgItem));
+ memcpy(item, data, sizeof(_MMCamcorderMsgItem));
+ item->handle = handle;
+
+ _MMCAMCORDER_LOCK(handle);
+ hcamcorder->msg_data = g_list_append(hcamcorder->msg_data, item);
+// _mmcam_dbg_log("item[%p]", item);
+
+ g_idle_add(_mmcamcroder_msg_callback, item);
+
+ _MMCAMCORDER_UNLOCK(handle);
+
+ return TRUE;
+}
+
+
+void
+_mmcamcroder_remove_message_all(MMHandleType handle)
+{
+ mmf_camcorder_t* hcamcorder = MMF_CAMCORDER(handle);
+ _MMCamcorderMsgItem *item = NULL;
+ gboolean ret = TRUE;
+ GList *list = NULL;
+
+ mmf_return_if_fail(hcamcorder);
+
+ _MMCAMCORDER_LOCK(handle);
+
+ if(!hcamcorder->msg_data)
+ {
+ _mmcam_dbg_log("No message data is remained.");
+ }
+ else
+ {
+ list = hcamcorder->msg_data;
+
+ while(list)
+ {
+ item = list->data;
+ list = g_list_next(list);
+
+ if(!item)
+ {
+ _mmcam_dbg_err("Fail to remove message. The item is NULL");
+ }
+ else
+ {
+ ret = g_idle_remove_by_data (item);
+ _mmcam_dbg_log("Remove item[%p]. ret[%d]", item, ret);
+
+ hcamcorder->msg_data = g_list_remove(hcamcorder->msg_data, item);
+
+ SAFE_FREE(item);
+ }
+ }
+
+ g_list_free(hcamcorder->msg_data);
+ hcamcorder->msg_data = NULL;
+ }
+
+ _MMCAMCORDER_UNLOCK(handle);
+
+ return;
+}
+
+
+void
+_mmcamcorder_err_trace_write( char *str_filename, char *func_name, int line_num, char *fmt, ... )
+{
+ FILE *f = NULL;
+ va_list ap = {0};
+ char time_string[TIME_STRING_MAX_LEN] = {'\0',};
+
+ time_t current_time;
+ struct tm new_time;
+
+ mmf_return_if_fail( str_filename );
+
+ current_time = time( NULL );
+ localtime_r( &current_time, &new_time );
+
+ f = fopen( str_filename, "a" );
+ if( f == NULL )
+ {
+ _mmcam_dbg_warn( "Failed to open file.[%s]", str_filename );
+ return;
+ }
+
+ asctime_r(&new_time, time_string);
+ fprintf( f, "[%.19s][%05d][%s]", time_string, line_num, func_name );
+
+ va_start( ap, fmt );
+ vfprintf( f, fmt, ap );
+ va_end( ap );
+
+ fprintf( f, "\n" );
+
+ fclose( f );
+}
+
+int
+_mmcamcorder_get_pixel_format(GstBuffer *buffer)
+{
+ GstCaps *caps = NULL;
+ const GstStructure *structure;
+ const char *media_type;
+ MMPixelFormatType type = 0;
+ unsigned int fourcc = 0;
+
+ mmf_return_val_if_fail( buffer != NULL, MM_PIXEL_FORMAT_INVALID );
+
+ caps = gst_buffer_get_caps (buffer);
+ structure = gst_caps_get_structure (caps, 0);
+ media_type = gst_structure_get_name (structure);
+
+ 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"))
+ {
+ _mmcam_dbg_log("It is yuv.");
+ gst_structure_get_fourcc (structure, "format", &fourcc);
+ type = _mmcamcorder_get_pixtype(fourcc);
+ }
+ else
+ {
+ _mmcam_dbg_err("Not supported format");
+ type = MM_PIXEL_FORMAT_INVALID;
+ }
+
+ _mmcam_dbg_log( "Type [%d]", type );
+
+ gst_caps_unref( caps );
+ caps = NULL;
+
+ return type;
+}
+
+unsigned int _mmcamcorder_get_fourcc(int pixtype, int codectype, int use_zero_copy_format)
+{
+ unsigned int fourcc = 0;
+
+ _mmcam_dbg_log("pixtype(%d)", pixtype);
+
+ switch (pixtype) {
+ case MM_PIXEL_FORMAT_NV12:
+ if (use_zero_copy_format) {
+ fourcc = GST_MAKE_FOURCC ('S', 'N', '1', '2');
+ } else {
+ fourcc = GST_MAKE_FOURCC ('N', 'V', '1', '2');
+ }
+ break;
+ case MM_PIXEL_FORMAT_YUYV:
+ if (use_zero_copy_format) {
+ fourcc = GST_MAKE_FOURCC ('S', 'U', 'Y', 'V');
+ } else {
+ fourcc = GST_MAKE_FOURCC ('Y', 'U', 'Y', '2');
+ }
+ break;
+ case MM_PIXEL_FORMAT_UYVY:
+ if (use_zero_copy_format) {
+ fourcc = GST_MAKE_FOURCC ('S', 'Y', 'V', 'Y');
+ } else {
+ fourcc = GST_MAKE_FOURCC ('U', 'Y', 'V', 'Y');
+ }
+ break;
+ case MM_PIXEL_FORMAT_I420:
+ if (use_zero_copy_format) {
+ fourcc = GST_MAKE_FOURCC ('S', '4', '2', '0');
+ } else {
+ fourcc = GST_MAKE_FOURCC ('I', '4', '2', '0');
+ }
+ break;
+ case MM_PIXEL_FORMAT_YV12:
+ fourcc = GST_MAKE_FOURCC ('Y', 'V', '1', '2');
+ break;
+ case MM_PIXEL_FORMAT_422P:
+ fourcc = GST_MAKE_FOURCC ('4', '2', '2', 'P');
+ break;
+ case MM_PIXEL_FORMAT_RGB565:
+ fourcc = GST_MAKE_FOURCC ('R', 'G', 'B', 'P');
+ break;
+ case MM_PIXEL_FORMAT_RGB888:
+ fourcc = GST_MAKE_FOURCC ('R', 'G', 'B', '3');
+ break;
+ case MM_PIXEL_FORMAT_ENCODED:
+ if (codectype == MM_IMAGE_CODEC_JPEG) {
+ fourcc = GST_MAKE_FOURCC ('J', 'P', 'E', 'G');
+ } else if (codectype == MM_IMAGE_CODEC_JPEG_SRW) {
+ fourcc = GST_MAKE_FOURCC ('J', 'P', 'E', 'G'); /*TODO: JPEG+SamsungRAW format */
+ } else if (codectype == MM_IMAGE_CODEC_SRW) {
+ fourcc = GST_MAKE_FOURCC ('J', 'P', 'E', 'G'); /*TODO: SamsungRAW format */
+ } else if (codectype == MM_IMAGE_CODEC_PNG) {
+ fourcc = GST_MAKE_FOURCC ('P', 'N', 'G', ' ');
+ } else {
+ /* Please let us know what other fourcces are. ex) BMP, GIF?*/
+ fourcc = GST_MAKE_FOURCC ('J', 'P', 'E', 'G');
+ }
+ break;
+ default:
+ _mmcam_dbg_log("Not proper pixel type. Set default.");
+ fourcc = GST_MAKE_FOURCC ('S', '4', '2', '0');
+ break;
+ }
+
+ return fourcc;
+}
+
+
+int _mmcamcorder_get_pixtype(unsigned int fourcc)
+{
+ int pixtype = MM_PIXEL_FORMAT_INVALID;
+ char *pfourcc = (char*)&fourcc;
+ _mmcam_dbg_log("fourcc(%c%c%c%c)", pfourcc[0], pfourcc[1], pfourcc[2], pfourcc[3]);
+
+ switch (fourcc) {
+ case GST_MAKE_FOURCC ('S', 'N', '1', '2'):
+ case GST_MAKE_FOURCC ('N', 'V', '1', '2'):
+ pixtype = MM_PIXEL_FORMAT_NV12;
+ break;
+ case GST_MAKE_FOURCC ('S', 'U', 'Y', 'V'):
+ case GST_MAKE_FOURCC ('Y', 'U', 'Y', 'V'):
+ case GST_MAKE_FOURCC ('Y', 'U', 'Y', '2'):
+ pixtype = MM_PIXEL_FORMAT_YUYV;
+ break;
+ case GST_MAKE_FOURCC ('S', 'Y', 'V', 'Y'):
+ case GST_MAKE_FOURCC ('U', 'Y', 'V', 'Y'):
+ pixtype = MM_PIXEL_FORMAT_UYVY;
+ break;
+ case GST_MAKE_FOURCC ('S', '4', '2', '0'):
+ case GST_MAKE_FOURCC ('I', '4', '2', '0'):
+ pixtype = MM_PIXEL_FORMAT_I420;
+ break;
+ case GST_MAKE_FOURCC ('Y', 'V', '1', '2'):
+ pixtype = MM_PIXEL_FORMAT_YV12;
+ break;
+ case GST_MAKE_FOURCC ('4', '2', '2', 'P'):
+ pixtype = MM_PIXEL_FORMAT_422P;
+ break;
+ case GST_MAKE_FOURCC ('R', 'G', 'B', 'P'):
+ pixtype = MM_PIXEL_FORMAT_RGB565;
+ break;
+ case GST_MAKE_FOURCC ('R', 'G', 'B', '3'):
+ pixtype = MM_PIXEL_FORMAT_RGB888;
+ break;
+ case GST_MAKE_FOURCC ('A', 'R', 'G', 'B'):
+ case GST_MAKE_FOURCC ('x', 'R', 'G', 'B'):
+ pixtype = MM_PIXEL_FORMAT_ARGB;
+ break;
+ case GST_MAKE_FOURCC ('B', 'G', 'R', 'A'):
+ case GST_MAKE_FOURCC ('B', 'G', 'R', 'x'):
+ pixtype = MM_PIXEL_FORMAT_RGBA;
+ break;
+ case GST_MAKE_FOURCC ('J', 'P', 'E', 'G'):
+ case GST_MAKE_FOURCC ('P', 'N', 'G', ' '):
+ pixtype = MM_PIXEL_FORMAT_ENCODED;
+ break;
+ default:
+ _mmcam_dbg_log("Not supported fourcc type(%x)", fourcc);
+ pixtype = MM_PIXEL_FORMAT_INVALID;
+ break;
+ }
+
+ return pixtype;
+}
+
+
+gboolean
+_mmcamcorder_add_elements_to_bin( GstBin *bin, GList *element_list )
+{
+ GList *local_list = element_list;
+ _MMCamcorderGstElement *element = NULL;
+
+ mmf_return_val_if_fail( bin && local_list, FALSE );
+
+ while( local_list )
+ {
+ element = (_MMCamcorderGstElement*)local_list->data;
+ if( element && element->gst )
+ {
+ if( !gst_bin_add( bin, GST_ELEMENT(element->gst) ) )
+ {
+ _mmcam_dbg_err( "Add element [%s] to bin [%s] FAILED",
+ GST_ELEMENT_NAME(GST_ELEMENT(element->gst)),
+ GST_ELEMENT_NAME(GST_ELEMENT(bin)) );
+ return FALSE;
+ }
+ else
+ {
+ _mmcam_dbg_log( "Add element [%s] to bin [%s] OK",
+ GST_ELEMENT_NAME(GST_ELEMENT(element->gst)),
+ GST_ELEMENT_NAME(GST_ELEMENT(bin)) );
+ }
+ }
+
+ local_list = local_list->next;
+ }
+
+ return TRUE;
+}
+
+gboolean
+_mmcamcorder_link_elements( GList *element_list )
+{
+ GList *local_list = element_list;
+ _MMCamcorderGstElement *element = NULL;
+ _MMCamcorderGstElement *pre_element = NULL;
+
+ mmf_return_val_if_fail( local_list, FALSE );
+
+ pre_element = (_MMCamcorderGstElement*)local_list->data;
+ local_list = local_list->next;
+
+ while( local_list )
+ {
+ element = (_MMCamcorderGstElement*)local_list->data;
+ if( element && element->gst )
+ {
+ if( _MM_GST_ELEMENT_LINK( GST_ELEMENT(pre_element->gst), GST_ELEMENT(element->gst) ) )
+ {
+ _mmcam_dbg_log( "Link [%s] to [%s] OK",
+ GST_ELEMENT_NAME(GST_ELEMENT(pre_element->gst)),
+ GST_ELEMENT_NAME(GST_ELEMENT(element->gst)) );
+ }
+ else
+ {
+ _mmcam_dbg_err( "Link [%s] to [%s] FAILED",
+ GST_ELEMENT_NAME(GST_ELEMENT(pre_element->gst)),
+ GST_ELEMENT_NAME(GST_ELEMENT(element->gst)) );
+ return FALSE;
+ }
+ }
+
+ pre_element = element;
+ local_list = local_list->next;
+ }
+
+ return TRUE;
+}
+
+
+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 ret = 0;
+ int i = 0;
+ guint32 src_fourcc = 0;
+ gboolean do_encode = FALSE;
+ jpegenc_parameter enc_param;
+ static jpegenc_info enc_info = {-1,};
+
+ _mmcam_dbg_log("START");
+
+ mmf_return_val_if_fail(src_data && result_data && result_length, FALSE);
+
+ CLEAR(enc_param);
+
+ if (enc_info.sw_support == -1) {
+ CLEAR(enc_info);
+ __ta__("camsrcjpegenc_get_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 &&
+ enc_info.sw_support == TRUE) {
+ /* 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_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;
+
+ __ta__(" camsrcjpegenc_encode",
+ ret = camsrcjpegenc_encode(&enc_info, JPEG_ENCODER_SOFTWARE, &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);
+
+ return TRUE;
+ } else {
+ _mmcam_dbg_err("camsrcjpegenc_encode failed(%x)", ret);
+ return FALSE;
+ }
+ } else {
+ _mmcam_dbg_err("S/W JPEG codec does NOT support format [%d]", src_format);
+ return FALSE;
+ }
+ } else {
+ _mmcam_dbg_err("Not Supported FOURCC(format:%d) or There is NO S/W encoder(%d)",
+ src_format, enc_info.sw_support);
+ 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);
+}
+
+static gchar * str_to_utf8(const gchar *str)
+{
+ return g_convert (str, -1, "UTF-8", "ASCII", NULL, NULL, NULL);
+}
+
+static inline gboolean write_tag(FILE *f, const gchar *tag)
+{
+ while(*tag)
+ FPUTC_CHECK(*tag++, f);
+
+ return TRUE;
+}
+
+static inline gboolean write_to_32(FILE *f, guint val)
+{
+ FPUTC_CHECK(val >> 24, f);
+ FPUTC_CHECK(val >> 16, f);
+ FPUTC_CHECK(val >> 8, f);
+ FPUTC_CHECK(val, f);
+ return TRUE;
+}
+
+static inline gboolean write_to_16(FILE *f, guint val)
+{
+ FPUTC_CHECK(val >> 8, f);
+ FPUTC_CHECK(val, f);
+ return TRUE;
+}
+
+static inline gboolean write_to_24(FILE *f, guint val)
+{
+ write_to_16(f, val >> 8);
+ FPUTC_CHECK(val, f);
+ return TRUE;
+}
diff --git a/src/mm_camcorder_videorec.c b/src/mm_camcorder_videorec.c
new file mode 100644
index 0000000..631f389
--- /dev/null
+++ b/src/mm_camcorder_videorec.c
@@ -0,0 +1,1496 @@
+/*
+ * libmm-camcorder
+ *
+ * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact: Jeongmo Yang <jm80.yang@samsung.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+/*=======================================================================================
+| INCLUDE FILES |
+=======================================================================================*/
+#include "mm_camcorder_internal.h"
+#include "mm_camcorder_videorec.h"
+
+/*---------------------------------------------------------------------------------------
+| GLOBAL VARIABLE DEFINITIONS for internal |
+---------------------------------------------------------------------------------------*/
+#define _MMCAMCORDER_LOCATION_INFO // for add gps information
+
+/*---------------------------------------------------------------------------------------
+| LOCAL VARIABLE DEFINITIONS for internal |
+---------------------------------------------------------------------------------------*/
+#define _MMCAMCORDER_MINIMUM_FRAME 10
+#define _MMCAMCORDER_RETRIAL_COUNT 10
+#define _MMCAMCORDER_FRAME_WAIT_TIME 200000 /* ms */
+#define _MMCAMCORDER_FREE_SPACE_CHECK_INTERVAL 5
+
+/*---------------------------------------------------------------------------------------
+| LOCAL FUNCTION PROTOTYPES: |
+---------------------------------------------------------------------------------------*/
+/* STATIC INTERNAL FUNCTION */
+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_slow(GstPad *pad, GstBuffer *buffer, gpointer u_data);
+static gboolean __mmcamcorder_audio_dataprobe_audio_mute(GstPad *pad, GstBuffer *buffer, gpointer u_data);
+static gboolean __mmcamcorder_add_locationinfo(MMHandleType handle, int fileformat);
+static gboolean __mmcamcorder_add_locationinfo_mp4(MMHandleType handle);
+static gboolean __mmcamcorder_eventprobe_monitor(GstPad *pad, GstEvent *event, gpointer u_data);
+
+/*=======================================================================================
+| FUNCTION DEFINITIONS |
+=======================================================================================*/
+/*---------------------------------------------------------------------------------------
+| GLOBAL FUNCTION DEFINITIONS: |
+---------------------------------------------------------------------------------------*/
+int _mmcamcorder_add_recorder_pipeline(MMHandleType handle)
+{
+ int err = MM_ERROR_NONE;
+ char* gst_element_rsink_name = NULL;
+
+ GstPad *srcpad = NULL;
+ GstPad *sinkpad = NULL;
+
+ mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
+ _MMCamcorderSubContext *sc = NULL;
+
+ type_element *RecordsinkElement = NULL;
+
+ mmf_return_val_if_fail(hcamcorder, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
+
+ sc = MMF_CAMCORDER_SUBCONTEXT(handle);
+ mmf_return_val_if_fail(sc, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
+ mmf_return_val_if_fail(sc->element, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
+
+ _mmcam_dbg_log("");
+
+ err = _mmcamcorder_check_videocodec_fileformat_compatibility( handle );
+ if( err != MM_ERROR_NONE )
+ {
+ return err;
+ }
+
+ /* Create gstreamer element */
+ /* Check main pipeline */
+ if (!sc->element[_MMCAMCORDER_MAIN_PIPE].gst) {
+ err = MM_ERROR_CAMCORDER_RESOURCE_CREATION;
+ goto pipeline_creation_error;
+ }
+
+ if (sc->is_slow == FALSE) {
+ /* Sub pipeline */
+ __ta__(" __mmcamcorder_create_audiosrc_bin",
+ err = _mmcamcorder_create_audiosrc_bin((MMHandleType)hcamcorder);
+ );
+ if (err != MM_ERROR_NONE) {
+ return err;
+ }
+
+ gst_bin_add(GST_BIN(sc->element[_MMCAMCORDER_MAIN_PIPE].gst),
+ sc->element[_MMCAMCORDER_AUDIOSRC_BIN].gst);
+ }
+
+ __ta__(" _mmcamcorder_create_encodesink_bin",
+ err = _mmcamcorder_create_encodesink_bin((MMHandleType)hcamcorder);
+ );
+ if (err != MM_ERROR_NONE) {
+ return err;
+ }
+
+ gst_bin_add(GST_BIN(sc->element[_MMCAMCORDER_MAIN_PIPE].gst),
+ sc->element[_MMCAMCORDER_ENCSINK_BIN].gst);
+
+ /* Link each element */
+ srcpad = gst_element_get_static_pad(sc->element[_MMCAMCORDER_VIDEOSRC_BIN].gst, "src1");
+ sinkpad = gst_element_get_static_pad(sc->element[_MMCAMCORDER_ENCSINK_BIN].gst, "video_sink0");
+ _MM_GST_PAD_LINK_UNREF(srcpad, sinkpad, err, pipeline_creation_error);
+
+ if (sc->is_slow == FALSE) {
+ srcpad = gst_element_get_static_pad (sc->element[_MMCAMCORDER_AUDIOSRC_BIN].gst, "src");
+ sinkpad = gst_element_get_static_pad (sc->element[_MMCAMCORDER_ENCSINK_BIN].gst, "audio_sink0");
+ _MM_GST_PAD_LINK_UNREF(srcpad, sinkpad, err, pipeline_creation_error);
+ }
+
+ _mmcamcorder_conf_get_element(hcamcorder->conf_main,
+ CONFIGURE_CATEGORY_MAIN_RECORD,
+ "RecordsinkElement",
+ &RecordsinkElement);
+ _mmcamcorder_conf_get_value_element_name(RecordsinkElement, &gst_element_rsink_name);
+
+ /* set data probe function */
+
+ /* register message cb */
+
+ /* set data probe function for audio */
+
+ if (sc->is_slow == FALSE) {
+ sinkpad = gst_element_get_static_pad(sc->element[_MMCAMCORDER_ENCSINK_AENC].gst, "sink");
+ MMCAMCORDER_ADD_BUFFER_PROBE(sinkpad, _MMCAMCORDER_HANDLER_VIDEOREC,
+ __mmcamcorder_audioque_dataprobe, hcamcorder);
+ gst_object_unref(sinkpad);
+ sinkpad = NULL;
+
+ /* for voice mute */
+ srcpad = gst_element_get_static_pad(sc->element[_MMCAMCORDER_AUDIOSRC_SRC].gst, "src");
+ MMCAMCORDER_ADD_BUFFER_PROBE(srcpad, _MMCAMCORDER_HANDLER_VIDEOREC,
+ __mmcamcorder_audio_dataprobe_audio_mute, hcamcorder);
+ gst_object_unref(srcpad);
+ srcpad = NULL;
+
+ if (sc->element[_MMCAMCORDER_ENCSINK_AENC_QUE].gst) {
+ srcpad = gst_element_get_static_pad(sc->element[_MMCAMCORDER_ENCSINK_AENC_QUE].gst, "src");
+ MMCAMCORDER_ADD_EVENT_PROBE(srcpad, _MMCAMCORDER_HANDLER_VIDEOREC,
+ __mmcamcorder_eventprobe_monitor, hcamcorder);
+ gst_object_unref(srcpad);
+ srcpad = NULL;
+ }
+ }
+
+ if (sc->element[_MMCAMCORDER_ENCSINK_VENC_QUE].gst) {
+ srcpad = gst_element_get_static_pad(sc->element[_MMCAMCORDER_ENCSINK_VENC_QUE].gst, "src");
+ MMCAMCORDER_ADD_EVENT_PROBE(srcpad, _MMCAMCORDER_HANDLER_VIDEOREC,
+ __mmcamcorder_eventprobe_monitor, hcamcorder);
+ gst_object_unref(srcpad);
+ srcpad = NULL;
+ }
+
+ if (sc->is_slow) {
+ sinkpad = gst_element_get_static_pad(sc->element[_MMCAMCORDER_ENCSINK_VENC].gst, "sink");
+ MMCAMCORDER_ADD_BUFFER_PROBE(sinkpad, _MMCAMCORDER_HANDLER_VIDEOREC,
+ __mmcamcorder_video_dataprobe_slow, hcamcorder);
+ gst_object_unref(sinkpad);
+ sinkpad = NULL;
+ }
+
+ if (!strcmp(gst_element_rsink_name, "filesink")) {
+ srcpad = gst_element_get_static_pad(sc->element[_MMCAMCORDER_ENCSINK_VENC].gst, "src");
+ MMCAMCORDER_ADD_BUFFER_PROBE(srcpad, _MMCAMCORDER_HANDLER_VIDEOREC,
+ __mmcamcorder_video_dataprobe_record, hcamcorder);
+ gst_object_unref(srcpad);
+ srcpad = NULL;
+
+ srcpad = gst_element_get_static_pad(sc->element[_MMCAMCORDER_ENCSINK_AENC].gst, "src");
+ MMCAMCORDER_ADD_BUFFER_PROBE(srcpad, _MMCAMCORDER_HANDLER_VIDEOREC,
+ __mmcamcorder_audio_dataprobe_check, hcamcorder);
+ gst_object_unref(srcpad);
+ srcpad = NULL;
+ }
+
+ return MM_ERROR_NONE;
+
+pipeline_creation_error:
+ return err;
+}
+
+
+int _mmcamcorder_remove_audio_pipeline(MMHandleType handle)
+{
+ int ret = MM_ERROR_NONE;
+ GstPad *srcpad = NULL;
+ GstPad *sinkpad = 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);
+ mmf_return_val_if_fail(sc, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
+ mmf_return_val_if_fail(sc->element, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
+
+ _mmcam_dbg_log("");
+
+ if (sc->element[_MMCAMCORDER_AUDIOSRC_BIN].gst != NULL) {
+ __ta__( " AudiosrcBin Set NULL",
+ ret = _mmcamcorder_gst_set_state(handle, sc->element[_MMCAMCORDER_AUDIOSRC_BIN].gst, GST_STATE_NULL);
+ );
+ if (ret != MM_ERROR_NONE) {
+ _mmcam_dbg_err("Faile to change audio source state[%d]", ret);
+ return ret;
+ }
+
+ srcpad = gst_element_get_static_pad(sc->element[_MMCAMCORDER_AUDIOSRC_BIN].gst, "src");
+ sinkpad = gst_element_get_static_pad(sc->element[_MMCAMCORDER_ENCSINK_BIN].gst, "audio_sink0");
+ _MM_GST_PAD_UNLINK_UNREF(srcpad, sinkpad);
+
+ gst_bin_remove(GST_BIN(sc->element[_MMCAMCORDER_MAIN_PIPE].gst),
+ sc->element[_MMCAMCORDER_AUDIOSRC_BIN].gst);
+
+ /*
+ To avoid conflicting between old elements and newly created elements,
+ I clean element handles here. Real elements object will be finalized as the 'unref' process goes on.
+ This is a typical problem of unref. Even though I unref bin here, it takes much time to finalize each elements.
+ So I clean handles first, make them unref later. Audio recording, however, isn't needed this process.
+ It's because the pipeline of audio recording destroys at the same time,
+ and '_mmcamcorder_element_release_noti' will perfom removing handle.
+ */
+ _mmcamcorder_remove_element_handle(handle, _MMCAMCORDER_AUDIOSRC_BIN, _MMCAMCORDER_AUDIOSRC_NS);
+
+ _mmcam_dbg_log("Audio pipeline removed");
+ }
+
+ return MM_ERROR_NONE;
+}
+
+
+int _mmcamcorder_remove_encoder_pipeline(MMHandleType handle)
+{
+ int ret = MM_ERROR_NONE;
+ GstPad *srcpad = NULL;
+ GstPad *sinkpad = NULL;
+ 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);
+ mmf_return_val_if_fail(sc, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
+ mmf_return_val_if_fail(sc->element, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
+
+ _mmcam_dbg_log("");
+
+ if (sc->element[_MMCAMCORDER_ENCSINK_BIN].gst != NULL) {
+ __ta__( " EncodeBin Set NULL",
+ ret = _mmcamcorder_gst_set_state(handle, sc->element[_MMCAMCORDER_ENCSINK_BIN].gst, GST_STATE_NULL);
+ );
+ if (ret != MM_ERROR_NONE) {
+ _mmcam_dbg_err("Faile to change encode bin state[%d]", ret);
+ return ret;
+ }
+
+ srcpad = gst_element_get_static_pad(sc->element[_MMCAMCORDER_VIDEOSRC_BIN].gst, "src1");
+ sinkpad = gst_element_get_static_pad(sc->element[_MMCAMCORDER_ENCSINK_BIN].gst, "video_sink0");
+ _MM_GST_PAD_UNLINK_UNREF(srcpad, sinkpad);
+
+ /* release request pad */
+ reqpad = gst_element_get_static_pad(sc->element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "audio");
+ if (reqpad) {
+ gst_element_release_request_pad(sc->element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, reqpad);
+ gst_object_unref(reqpad);
+ reqpad = NULL;
+ }
+
+ reqpad = gst_element_get_static_pad(sc->element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "video");
+ if (reqpad) {
+ gst_element_release_request_pad(sc->element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, reqpad);
+ gst_object_unref(reqpad);
+ reqpad = NULL;
+ }
+
+ gst_bin_remove(GST_BIN(sc->element[_MMCAMCORDER_MAIN_PIPE].gst),
+ sc->element[_MMCAMCORDER_ENCSINK_BIN].gst);
+
+ /*
+ To avoid conflicting between old elements and newly created elements,
+ I clean element handles here. Real elements object will be finalized as the 'unref' process goes on.
+ This is a typical problem of unref. Even though I unref bin here, it takes much time to finalize each elements.
+ So I clean handles first, make them unref later. Audio recording, however, isn't needed this process.
+ It's because the pipeline of audio recording destroys at the same time,
+ and '_mmcamcorder_element_release_noti' will perfom removing handle.
+ */
+ _mmcamcorder_remove_element_handle(handle, _MMCAMCORDER_AUDIOSRC_QUE, _MMCAMCORDER_AUDIOSRC_ENC); /* Encode bin has audio encoder too. */
+ _mmcamcorder_remove_element_handle(handle, _MMCAMCORDER_ENCSINK_BIN, _MMCAMCORDER_ENCSINK_SINK);
+
+ _mmcam_dbg_log("Encoder pipeline removed");
+ }
+
+ return MM_ERROR_NONE;
+}
+
+
+int _mmcamcorder_remove_recorder_pipeline(MMHandleType handle)
+{
+ int ret = MM_ERROR_NONE;
+ 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);
+ mmf_return_val_if_fail(sc, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
+
+ _mmcam_dbg_log("");
+
+ if (!sc->element[_MMCAMCORDER_MAIN_PIPE].gst) {
+ _mmcam_dbg_warn("pipeline is not existed.");
+ return MM_ERROR_NONE;
+ }
+
+ _mmcamcorder_remove_all_handlers((MMHandleType)hcamcorder, _MMCAMCORDER_HANDLER_VIDEOREC);
+
+ ret = _mmcamcorder_remove_encoder_pipeline(handle);
+ if (ret != MM_ERROR_NONE) {
+ _mmcam_dbg_err("Fail to remove encoder pipeline");
+ return ret;
+ }
+
+ ret = _mmcamcorder_remove_audio_pipeline(handle);
+ if (ret != MM_ERROR_NONE) {
+ _mmcam_dbg_err("Fail to remove audio pipeline");
+ return ret;
+ }
+
+ return ret;
+}
+
+
+void _mmcamcorder_destroy_video_pipeline(MMHandleType handle)
+{
+ mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
+ _MMCamcorderSubContext *sc = NULL;
+ GstPad *reqpad1 = NULL;
+ GstPad *reqpad2 = NULL;
+
+ mmf_return_if_fail(hcamcorder);
+ sc = MMF_CAMCORDER_SUBCONTEXT(handle);
+
+ mmf_return_if_fail(sc);
+ mmf_return_if_fail(sc->element);
+
+ _mmcam_dbg_log("");
+
+ if (sc->element[_MMCAMCORDER_MAIN_PIPE].gst) {
+ 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_NULL);
+
+ _mmcamcorder_remove_all_handlers((MMHandleType)hcamcorder, _MMCAMCORDER_HANDLER_CATEGORY_ALL);
+
+ reqpad1 = gst_element_get_static_pad(sc->element[_MMCAMCORDER_VIDEOSRC_TEE].gst, "src0");
+ reqpad2 = gst_element_get_static_pad(sc->element[_MMCAMCORDER_VIDEOSRC_TEE].gst, "src1");
+ gst_element_release_request_pad(sc->element[_MMCAMCORDER_VIDEOSRC_TEE].gst, reqpad1);
+ gst_element_release_request_pad(sc->element[_MMCAMCORDER_VIDEOSRC_TEE].gst, reqpad2);
+ gst_object_unref(reqpad1);
+ gst_object_unref(reqpad2);
+
+ /* object disposing problem happen. */
+ _mmcam_dbg_log("Reference count of pipeline(%d)", GST_OBJECT_REFCOUNT_VALUE(sc->element[_MMCAMCORDER_MAIN_PIPE].gst));
+ gst_object_unref(sc->element[_MMCAMCORDER_MAIN_PIPE].gst);
+ }
+}
+
+
+int _mmcamcorder_video_command(MMHandleType handle, int command)
+{
+ int size = 0;
+ int fileformat = 0;
+ int ret = MM_ERROR_NONE;
+ char *temp_filename = NULL;
+ char *err_name = NULL;
+
+ gint fps = 0;
+ gint slow_fps = 0;
+ GstElement *pipeline = NULL;
+ GstPad *pad = NULL;
+
+ _MMCamcorderVideoInfo *info = NULL;
+ _MMCamcorderSubContext *sc = NULL;
+ mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
+
+ mmf_return_val_if_fail(hcamcorder, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
+
+ sc = MMF_CAMCORDER_SUBCONTEXT(handle);
+ mmf_return_val_if_fail(sc, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
+ mmf_return_val_if_fail(sc->info, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
+ mmf_return_val_if_fail(sc->element, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
+
+ info = sc->info;
+
+ _mmcam_dbg_log("Command(%d)", command);
+
+ pipeline = sc->element[_MMCAMCORDER_MAIN_PIPE].gst;
+
+ switch (command) {
+ case _MMCamcorder_CMD_RECORD:
+ {
+ if (_mmcamcorder_get_state((MMHandleType)hcamcorder) != MM_CAMCORDER_STATE_PAUSED) {
+ guint imax_time = 0;
+
+ /* Play record start sound */
+ _mmcamcorder_sound_solo_play(handle, _MMCAMCORDER_FILEPATH_REC_START_SND, TRUE);
+
+ /* Recording */
+ _mmcam_dbg_log("Record Start");
+
+ ret = _mmcamcorder_gst_set_state(handle, pipeline, GST_STATE_PAUSED);
+ if (ret != MM_ERROR_NONE) {
+ goto _ERR_CAMCORDER_VIDEO_COMMAND;
+ }
+
+ _mmcamcorder_conf_get_value_int(hcamcorder->conf_main,
+ CONFIGURE_CATEGORY_MAIN_RECORD,
+ "DropVideoFrame",
+ &(sc->drop_vframe));
+
+ _mmcamcorder_conf_get_value_int(hcamcorder->conf_main,
+ CONFIGURE_CATEGORY_MAIN_RECORD,
+ "PassFirstVideoFrame",
+ &(sc->pass_first_vframe));
+
+ _mmcam_dbg_log("Drop video frame count[%d], Pass fisrt video frame count[%d]",
+ sc->drop_vframe, sc->pass_first_vframe);
+
+ ret = mm_camcorder_get_attributes(handle, &err_name,
+ MMCAM_CAMERA_FPS, &fps,
+ "camera-slow-motion-fps", &slow_fps,
+ MMCAM_FILE_FORMAT, &fileformat,
+ MMCAM_TARGET_FILENAME, &temp_filename, &size,
+ MMCAM_TARGET_TIME_LIMIT, &imax_time,
+ MMCAM_FILE_FORMAT, &(info->fileformat),
+ NULL);
+ if (ret != MM_ERROR_NONE) {
+ _mmcam_dbg_warn("Get attrs fail. (%s:%x)", err_name, ret);
+ SAFE_FREE (err_name);
+ goto _ERR_CAMCORDER_VIDEO_COMMAND;
+ }
+
+ /* set max time */
+ if (imax_time <= 0) {
+ info->max_time = 0; /* do not check */
+ } else {
+ info->max_time = ((guint64)imax_time) * 1000; /* to millisecond */
+ }
+
+ if (sc->is_slow) {
+ info->multiple_fps = fps/slow_fps;
+ _mmcam_dbg_log("high speed recording fps:%d,slow_fps:%d,multiple_fps:%d",
+ fps, slow_fps, info->multiple_fps);
+ }
+
+ MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst, "hold-af-after-capturing", TRUE);
+ MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst, "req-negotiation", TRUE);
+
+ ret =_mmcamcorder_add_recorder_pipeline((MMHandleType)hcamcorder);
+ if (ret != MM_ERROR_NONE) {
+ goto _ERR_CAMCORDER_VIDEO_COMMAND;
+ }
+
+ info->filename = strdup(temp_filename);
+ if (!info->filename) {
+ _mmcam_dbg_err("strdup was failed");
+ goto _ERR_CAMCORDER_VIDEO_COMMAND;
+ }
+
+ _mmcam_dbg_log("Record start : set file name using attribute - %s ",info->filename);
+
+ MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_ENCSINK_SINK].gst, "location", info->filename);
+ MMCAMCORDER_G_OBJECT_SET( sc->element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "block", 0);
+
+ /* Adjust display FPS */
+ sc->display_interval = 0;
+ sc->previous_slot_time = 0;
+
+ /* gst_element_set_base_time(GST_ELEMENT(pipeline), (GstClockTime)0);
+ if you want to use audio clock, enable this block
+ for change recorder_pipeline state to paused. */
+ __ta__(" _MMCamcorder_CMD_RECORD:GST_STATE_PAUSED2",
+ ret = _mmcamcorder_gst_set_state(handle, pipeline, GST_STATE_PAUSED);
+ );
+ if (ret != MM_ERROR_NONE) {
+ /* Remove recorder pipeline and recording file which size maybe zero */
+ __ta__(" record fail:remove_recorder_pipeline",
+ _mmcamcorder_remove_recorder_pipeline((MMHandleType)hcamcorder);
+ );
+ if (info->filename) {
+ _mmcam_dbg_log("file delete(%s)", info->filename);
+ unlink(info->filename);
+ g_free(info->filename);
+ info->filename = NULL;
+ }
+ goto _ERR_CAMCORDER_VIDEO_COMMAND;
+ }
+
+ /**< To fix video recording hanging
+ 1. use gst_element_set_start_time() instead of gst_pipeline_set_new_stream_time()
+ 2. Set (GstClockTime)1 instead of (GstClockTime)0. Because of strict check in gstreamer 0.25,
+ basetime wouldn't change if you set (GstClockTime)0.
+ 3. Move set start time position below PAUSED of pipeline.
+ */
+ gst_element_set_start_time(GST_ELEMENT(pipeline), (GstClockTime)1);
+ info->video_frame_count = 0;
+ info->audio_frame_count = 0;
+ info->filesize = 0;
+ sc->ferror_send = FALSE;
+ sc->ferror_count = 0;
+ sc->error_occurs = FALSE;
+ sc->bget_eos = FALSE;
+
+ __ta__(" _MMCamcorder_CMD_RECORD:GST_STATE_PLAYING2",
+ ret = _mmcamcorder_gst_set_state(handle, pipeline, GST_STATE_PLAYING);
+ );
+ if (ret != MM_ERROR_NONE) {
+ /* Remove recorder pipeline and recording file which size maybe zero */
+ __ta__(" record fail:remove_recorder_pipeline",
+ _mmcamcorder_remove_recorder_pipeline((MMHandleType)hcamcorder);
+ );
+ if (info->filename) {
+ _mmcam_dbg_log("file delete(%s)", info->filename);
+ unlink(info->filename);
+ g_free(info->filename);
+ info->filename = NULL;
+ }
+ goto _ERR_CAMCORDER_VIDEO_COMMAND;
+ }
+ } else {
+ /* Resume case */
+ int video_enc = 0;
+
+ MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "runtime-pause", FALSE);
+
+ mm_camcorder_get_attributes(handle, NULL, MMCAM_VIDEO_ENCODER, &video_enc, NULL);
+ if (video_enc == MM_VIDEO_CODEC_MPEG4) {
+ MMCAMCORDER_G_OBJECT_SET( sc->element[_MMCAMCORDER_ENCSINK_VENC].gst, "force-intra", TRUE);
+ }
+
+ _mmcam_dbg_log("Object property settings done");
+ }
+ }
+ 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;
+ }
+
+ for (count = 0 ; count <= _MMCAMCORDER_RETRIAL_COUNT ; count++) {
+ if (sc->is_slow) {
+ /* check only video frame */
+ 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 "",
+ 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 "",
+ count, info->video_frame_count);
+ }
+
+ 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) {
+ break;
+ } else if (count == _MMCAMCORDER_RETRIAL_COUNT) {
+ _mmcam_dbg_err("Pause fail, frame count VIDEO[%" G_GUINT64_FORMAT "], AUDIO [%" G_GUINT64_FORMAT "]",
+ 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 "]",
+ count, info->video_frame_count, info->audio_frame_count);
+ }
+
+ usleep(_MMCAMCORDER_FRAME_WAIT_TIME);
+ }
+ }
+ /* tee block */
+ MMCAMCORDER_G_OBJECT_SET( sc->element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "runtime-pause", TRUE);
+
+ break;
+ }
+ case _MMCamcorder_CMD_CANCEL:
+ {
+ if (info->b_commiting) {
+ _mmcam_dbg_warn("now on commiting previous file!!(command : %d)", command);
+ return MM_ERROR_CAMCORDER_CMD_IS_RUNNING;
+ }
+
+ MMCAMCORDER_G_OBJECT_SET( sc->element[_MMCAMCORDER_VIDEOSINK_QUE].gst, "empty-buffers", TRUE);
+ MMCAMCORDER_G_OBJECT_SET( sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst, "hold-af-after-capturing", FALSE);
+
+ if (sc->now_continuous_af) {
+ sc->now_continuous_af = FALSE;
+ _mmcam_dbg_log("Set now_continuous_af as FALSE when CANCEL recording");
+ }
+
+ __ta__(" _MMCamcorder_CMD_CANCEL:GST_STATE_READY",
+ ret =_mmcamcorder_gst_set_state(handle, pipeline, GST_STATE_READY);
+ );
+ MMCAMCORDER_G_OBJECT_SET( sc->element[_MMCAMCORDER_VIDEOSINK_QUE].gst, "empty-buffers", FALSE);
+ if (ret != MM_ERROR_NONE) {
+ goto _ERR_CAMCORDER_VIDEO_COMMAND;
+ }
+
+ __ta__(" __mmcamcorder_remove_recorder_pipeline",
+ _mmcamcorder_remove_recorder_pipeline((MMHandleType)hcamcorder);
+ );
+
+ /* remove target file */
+ if (info->filename) {
+ _mmcam_dbg_log("file delete(%s)", info->filename);
+ unlink(info->filename);
+ g_free(info->filename);
+ info->filename = NULL;
+ }
+
+ sc->isMaxsizePausing = FALSE;
+ sc->isMaxtimePausing = FALSE;
+
+ sc->display_interval = 0;
+ sc->previous_slot_time = 0;
+ info->video_frame_count = 0;
+ info->audio_frame_count = 0;
+ info->filesize =0;
+
+ __ta__(" _MMCamcorder_CMD_CANCEL:GST_STATE_PLAYING",
+ ret =_mmcamcorder_gst_set_state(handle, pipeline, GST_STATE_PLAYING);
+ );
+ if (ret != MM_ERROR_NONE) {
+ goto _ERR_CAMCORDER_VIDEO_COMMAND;
+ }
+
+ 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;
+ } else {
+ _mmcam_dbg_log("_MMCamcorder_CMD_COMMIT : start");
+ info->b_commiting = TRUE;
+ }
+
+ for (count = 0 ; count <= _MMCAMCORDER_RETRIAL_COUNT ; count++) {
+ if (sc->is_slow) {
+ /* check only video frame */
+ if (info->video_frame_count >= _MMCAMCORDER_MINIMUM_FRAME) {
+ 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;
+ } else {
+ _mmcam_dbg_warn("Waiting for enough video frame, retrial [%d], frame %" G_GUINT64_FORMAT "",
+ count, info->video_frame_count);
+ }
+
+ 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) {
+ 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);
+
+ 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);
+ }
+
+ usleep(_MMCAMCORDER_FRAME_WAIT_TIME);
+ }
+ }
+
+ MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst, "hold-af-after-capturing", FALSE);
+
+ if (sc->now_continuous_af) {
+ sc->now_continuous_af = FALSE;
+ _mmcam_dbg_log("Set now_continuous_af as FALSE when COMMIT recording");
+ }
+
+ if (sc->error_occurs) {
+ GstPad *video= NULL;
+ GstPad *audio = NULL;
+ int ret = 0;
+
+ _mmcam_dbg_err("Committing Error case");
+
+ video = gst_element_get_static_pad(sc->element[_MMCAMCORDER_VIDEOSINK_SINK].gst, "sink");
+ ret = gst_pad_send_event (video, gst_event_new_eos());
+ _mmcam_dbg_err("Sending EOS video sink : %d", ret);
+ gst_object_unref(video);
+
+ video = gst_element_get_static_pad(sc->element[_MMCAMCORDER_ENCSINK_VENC].gst, "src");
+ gst_pad_push_event (video, gst_event_new_flush_start());
+ gst_pad_push_event (video, gst_event_new_flush_stop());
+ ret = gst_pad_push_event (video, gst_event_new_eos());
+ _mmcam_dbg_err("Sending EOS video encoder src pad : %d", ret);
+ gst_object_unref(video);
+
+ if (!sc->is_slow) {
+ audio = gst_element_get_static_pad(sc->element[_MMCAMCORDER_ENCSINK_AENC].gst, "src");
+ gst_pad_push_event (audio, gst_event_new_flush_start());
+ gst_pad_push_event (audio, gst_event_new_flush_stop());
+ ret = gst_element_send_event(sc->element[_MMCAMCORDER_AUDIOSRC_SRC].gst, gst_event_new_eos());
+ _mmcam_dbg_err("Sending EOS audio encoder src pad : %d", ret);
+ gst_object_unref(audio);
+ }
+ } else {
+ if (sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst != NULL) {
+ ret = gst_element_send_event(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst, gst_event_new_eos());
+ _mmcam_dbg_warn("send eos to videosrc result : %d", ret);
+ }
+
+ if (sc->element[_MMCAMCORDER_AUDIOSRC_SRC].gst != NULL) {
+ pad = gst_element_get_static_pad(sc->element[_MMCAMCORDER_AUDIOSRC_SRC].gst, "src");
+ ret = gst_element_send_event(sc->element[_MMCAMCORDER_AUDIOSRC_SRC].gst, gst_event_new_eos());
+ gst_object_unref(pad);
+ pad = NULL;
+
+ _mmcam_dbg_warn("send eos to audiosrc result : %d", ret);
+ }
+ }
+
+ if (hcamcorder->quick_device_close) {
+ _mmcam_dbg_warn("quick_device_close");
+ /* close device quickly */
+ MMCAMCORDER_G_OBJECT_SET( sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst, "quick-device-close",TRUE);
+ }
+
+ /* sc */
+ sc->display_interval = 0;
+ sc->previous_slot_time = 0;
+
+ /* Wait EOS */
+ _mmcam_dbg_log("Start to wait EOS");
+ ret =_mmcamcorder_get_eos_message(handle);
+ if (ret != MM_ERROR_NONE) {
+ goto _ERR_CAMCORDER_VIDEO_COMMAND;
+ }
+ }
+ break;
+ case _MMCamcorder_CMD_PREVIEW_START:
+ {
+ int fps_auto = 0;
+
+ _mmcamcorder_vframe_stablize((MMHandleType)hcamcorder);
+
+ /* sc */
+ sc->display_interval = 0;
+ sc->previous_slot_time = 0;
+
+ mm_camcorder_get_attributes(handle, NULL, MMCAM_CAMERA_FPS_AUTO, &fps_auto, NULL);
+
+ MMCAMCORDER_G_OBJECT_SET( sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst, "fps-auto", fps_auto);
+
+ __ta__(" _MMCamcorder_CMD_PREVIEW_START:GST_STATE_PLAYING",
+ ret =_mmcamcorder_gst_set_state(handle, pipeline, GST_STATE_PLAYING);
+ );
+ if (ret != MM_ERROR_NONE) {
+ goto _ERR_CAMCORDER_VIDEO_COMMAND;
+ }
+
+ /* I place this function last because it miscalculates a buffer that sents in GST_STATE_PAUSED */
+ _mmcamcorder_video_current_framerate_init(handle);
+ }
+ break;
+ case _MMCamcorder_CMD_PREVIEW_STOP:
+ MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_QUE].gst, "empty-buffers", TRUE);
+ ret = _mmcamcorder_gst_set_state(handle, sc->element[_MMCAMCORDER_MAIN_PIPE].gst, GST_STATE_READY);
+ MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_QUE].gst, "empty-buffers", FALSE);
+ if (ret != MM_ERROR_NONE) {
+ goto _ERR_CAMCORDER_VIDEO_COMMAND;
+ }
+
+ if (sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst) {
+ int op_status = 0;
+ MMCAMCORDER_G_OBJECT_GET(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst, "operation-status", &op_status);
+ _mmcam_dbg_err("Current Videosrc status[0x%x]", op_status);
+ }
+
+ break;
+ default:
+ ret = MM_ERROR_CAMCORDER_INVALID_ARGUMENT;
+ goto _ERR_CAMCORDER_VIDEO_COMMAND;
+ }
+
+ return MM_ERROR_NONE;
+
+_ERR_CAMCORDER_VIDEO_COMMAND:
+ if (ret != MM_ERROR_NONE && sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst != NULL) {
+ int op_status = 0;
+ MMCAMCORDER_G_OBJECT_GET(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst, "operation-status", &op_status);
+ _mmcam_dbg_err("Current Videosrc status[0x%x]", op_status);
+ }
+
+ return ret;
+}
+
+
+int _mmcamcorder_video_handle_eos(MMHandleType handle)
+{
+ int ret = MM_ERROR_NONE;
+ int enabletag = 0;
+ int camcorder_rotate = MM_VIDEO_INPUT_ROTATION_NONE;
+ int camera_rotate = MM_VIDEO_INPUT_ROTATION_NONE;
+ int display_rotate = MM_DISPLAY_ROTATION_NONE;
+ guint64 file_size = 0;
+
+ GstPad *pad = NULL;
+ GstElement *pipeline = NULL;
+
+ mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
+ _MMCamcorderSubContext *sc = NULL;
+ _MMCamcorderVideoInfo *info = NULL;
+ _MMCamcorderMsgItem msg;
+ MMCamRecordingReport *report = NULL;
+
+ mmf_return_val_if_fail(hcamcorder, FALSE);
+
+ sc = MMF_CAMCORDER_SUBCONTEXT(handle);
+ mmf_return_val_if_fail(sc, FALSE);
+ mmf_return_val_if_fail(sc->info, FALSE);
+
+ info = sc->info;
+
+ _mmcam_dbg_err("");
+
+ MMTA_ACUM_ITEM_BEGIN(" _mmcamcorder_video_handle_eos", 0);
+
+ pipeline = sc->element[_MMCAMCORDER_MAIN_PIPE].gst;
+
+ /* remove blocking part */
+ MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "block", FALSE);
+ MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_VIDEOSINK_QUE].gst, "empty-buffers", TRUE);
+
+ _mmcam_dbg_log("Set state of pipeline as PAUSED");
+ __ta__(" _MMCamcorder_CMD_COMMIT:GST_STATE_PAUSED",
+ ret = _mmcamcorder_gst_set_state(handle, pipeline, GST_STATE_PAUSED);
+ );
+ if (ret != MM_ERROR_NONE) {
+ _mmcam_dbg_warn("_MMCamcorder_CMD_COMMIT:GST_STATE_PAUSED failed. error[%x]", ret);
+ }
+
+ MMCAMCORDER_G_OBJECT_SET( sc->element[_MMCAMCORDER_VIDEOSINK_QUE].gst, "empty-buffers", FALSE);
+
+ __ta__(" _MMCamcorder_CMD_COMMIT:__mmcamcorder_remove_recorder_pipeline",
+ ret = _mmcamcorder_remove_recorder_pipeline((MMHandleType)hcamcorder);
+ );
+ if (ret != MM_ERROR_NONE) {
+ _mmcam_dbg_warn("_MMCamcorder_CMD_COMMIT:__mmcamcorder_remove_recorder_pipeline failed. error[%x]", ret);
+ }
+
+ if (enabletag && !(sc->ferror_send)) {
+ __ta__( " _MMCamcorder_CMD_COMMIT:__mmcamcorder_add_locationinfo",
+ ret = __mmcamcorder_add_locationinfo((MMHandleType)hcamcorder, info->fileformat);
+ );
+ if (ret) {
+ _mmcam_dbg_log("Writing location information SUCCEEDED !!");
+ } else {
+ _mmcam_dbg_err("Writing location information FAILED !!");
+ }
+ }
+
+ /* Recovering camera-rotation and display-rotation when start recording */
+ if (camcorder_rotate != camera_rotate &&
+ camera_rotate < MM_VIDEO_INPUT_ROTATION_FLIP_HORZ) {
+ _mmcamcorder_set_videosrc_rotation(handle, camera_rotate);
+ _mmcamcorder_set_display_rotation(handle, display_rotate);
+ _mmcam_dbg_log("## Recovering camcorder rotation is done. camcorder_rotate=%d, camera_rotate=%d, display_rotate=%d",
+ camcorder_rotate,camera_rotate,display_rotate);
+ } else {
+ _mmcam_dbg_log("## No need to recover camcorder rotation. camcorder_rotate=%d, camera_rotate=%d, display_rotate=%d",
+ camcorder_rotate,camera_rotate,display_rotate);
+
+ /* Flush EOS event to avoid pending pipeline */
+ pad = gst_element_get_static_pad(sc->element[_MMCAMCORDER_VIDEOSINK_SINK].gst, "sink");
+ gst_pad_push_event(pad, gst_event_new_flush_start());
+ gst_pad_push_event(pad, gst_event_new_flush_stop());
+ gst_object_unref(pad);
+ pad = NULL;
+
+ pad = gst_element_get_static_pad(sc->element[_MMCAMCORDER_VIDEOSRC_SRC].gst, "src");
+ gst_pad_push_event(pad, gst_event_new_flush_start());
+ gst_pad_push_event(pad, gst_event_new_flush_stop());
+ gst_object_unref(pad);
+ pad = NULL;
+ }
+
+ _mmcam_dbg_log("Set state as PLAYING");
+ __ta__(" _MMCamcorder_CMD_COMMIT:GST_STATE_PLAYING",
+ ret =_mmcamcorder_gst_set_state(handle, pipeline, GST_STATE_PLAYING);
+ );
+ /* Do not return when error is occurred.
+ Recording file was created successfully, but starting pipeline failed */
+ if (ret != MM_ERROR_NONE) {
+ msg.id = MM_MESSAGE_CAMCORDER_ERROR;
+ msg.param.code = ret;
+ _mmcamcroder_send_message((MMHandleType)hcamcorder, &msg);
+ _mmcam_dbg_err("Failed to set state PLAYING[%x]", ret);
+ }
+
+ if (hcamcorder->state_change_by_system != _MMCAMCORDER_STATE_CHANGE_BY_ASM) {
+ /* Play record stop sound */
+ __ta__(" _MMCamcorder_CMD_COMMIT:_mmcamcorder_sound_solo_play",
+ _mmcamcorder_sound_solo_play(handle, _MMCAMCORDER_FILEPATH_REC_STOP_SND, TRUE);
+ );
+ } else {
+ _mmcam_dbg_log("Do NOT play recording stop sound because of ASM stop");
+ }
+
+ /* Send recording report to application */
+ msg.id = MM_MESSAGE_CAMCORDER_CAPTURED;
+ report = (MMCamRecordingReport *)malloc(sizeof(MMCamRecordingReport));
+ if (!report) {
+ _mmcam_dbg_err("Recording report fail(%s). Out of memory.", info->filename);
+ } else {
+ report->recording_filename = strdup(info->filename);
+ msg.param.data= report;
+ msg.param.code = 1;
+ _mmcamcroder_send_message((MMHandleType)hcamcorder, &msg);
+ }
+
+ /* Finishing */
+ sc->pipeline_time = 0;
+ sc->pause_time = 0;
+ sc->isMaxsizePausing = FALSE; /*In async function, this variable should set in callback function. */
+ sc->isMaxtimePausing = FALSE;
+ sc->error_occurs = FALSE;
+
+ info->video_frame_count = 0;
+ info->audio_frame_count = 0;
+ info->filesize = 0;
+ g_free(info->filename);
+ info->filename = NULL;
+ info->b_commiting = FALSE;
+
+ MMTA_ACUM_ITEM_END(" _mmcamcorder_video_handle_eos", 0);
+ MMTA_ACUM_ITEM_END("Real Commit Time", 0);
+
+ _mmcam_dbg_err("_MMCamcorder_CMD_COMMIT : end");
+
+ return TRUE;
+}
+
+/**
+ * This function is record video data probing function.
+ * If this function is linked with certain pad by gst_pad_add_buffer_probe(),
+ * this function will be called when data stream pass through the pad.
+ *
+ * @param[in] pad probing pad which calls this function.
+ * @param[in] buffer buffer which contains stream data.
+ * @param[in] u_data user data.
+ * @return This function returns true on success, or false value with error
+ * @remarks
+ * @see
+ */
+static gboolean __mmcamcorder_eventprobe_monitor(GstPad *pad, GstEvent *event, gpointer u_data)
+{
+ switch (GST_EVENT_TYPE(event)) {
+ case GST_EVENT_UNKNOWN:
+ /* upstream events */
+ case GST_EVENT_QOS:
+ case GST_EVENT_SEEK:
+ case GST_EVENT_NAVIGATION:
+ case GST_EVENT_LATENCY:
+ /* downstream serialized events */
+ case GST_EVENT_NEWSEGMENT :
+ 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));
+ break;
+ case GST_EVENT_EOS:
+ _mmcam_dbg_warn("[%s:%s] gots %s", GST_DEBUG_PAD_NAME(pad), GST_EVENT_TYPE_NAME(event));
+ break;
+ /* bidirectional events */
+ case GST_EVENT_FLUSH_START:
+ case GST_EVENT_FLUSH_STOP:
+ _mmcam_dbg_err("[%s:%s] gots %s", GST_DEBUG_PAD_NAME(pad), GST_EVENT_TYPE_NAME(event));
+ break;
+ default:
+ _mmcam_dbg_log("[%s:%s] gots %s", GST_DEBUG_PAD_NAME(pad), GST_EVENT_TYPE_NAME(event));
+ break;
+ }
+
+ return TRUE;
+}
+
+
+static gboolean __mmcamcorder_audio_dataprobe_check(GstPad *pad, GstBuffer *buffer, gpointer u_data)
+{
+ mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(u_data);
+ _MMCamcorderSubContext *sc = NULL;
+ _MMCamcorderVideoInfo * info = NULL;
+
+ mmf_return_val_if_fail(hcamcorder, TRUE);
+ mmf_return_val_if_fail(buffer, FALSE);
+ sc = MMF_CAMCORDER_SUBCONTEXT(hcamcorder);
+
+ mmf_return_val_if_fail(sc && sc->info, TRUE);
+ info = sc->info;
+
+ /*_mmcam_dbg_err("[%" GST_TIME_FORMAT "]", GST_TIME_ARGS(GST_BUFFER_TIMESTAMP(buffer)));*/
+
+ if (info->audio_frame_count == 0) {
+ info->filesize += (guint64)GST_BUFFER_SIZE(buffer);
+ info->audio_frame_count++;
+ return TRUE;
+ }
+
+ if (sc->ferror_send || sc->isMaxsizePausing) {
+ _mmcam_dbg_warn("Recording is paused, drop frames");
+ return FALSE;
+ }
+
+ info->filesize += (guint64)GST_BUFFER_SIZE(buffer);
+ info->audio_frame_count++;
+
+ return TRUE;
+}
+
+
+static gboolean __mmcamcorder_video_dataprobe_record(GstPad *pad, GstBuffer *buffer, gpointer u_data)
+{
+ static int count = 0;
+ gint ret = 0;
+ guint vq_size = 0;
+ guint aq_size = 0;
+ guint64 free_space = 0;
+ guint64 buffer_size = 0;
+ guint64 trailer_size = 0;
+ guint64 queued_buffer = 0;
+ char *filename = NULL;
+
+ mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(u_data);
+ _MMCamcorderMsgItem msg;
+ _MMCamcorderSubContext *sc = NULL;
+ _MMCamcorderVideoInfo *info = NULL;
+
+ mmf_return_val_if_fail(hcamcorder, TRUE);
+ mmf_return_val_if_fail(buffer, FALSE);
+
+ sc = MMF_CAMCORDER_SUBCONTEXT(hcamcorder);
+ mmf_return_val_if_fail(sc && sc->info, TRUE);
+ info = sc->info;
+
+ /*_mmcam_dbg_log("[%" GST_TIME_FORMAT "]", GST_TIME_ARGS(GST_BUFFER_TIMESTAMP(buffer)));*/
+ if (sc->ferror_send) {
+ _mmcam_dbg_warn("file write error, drop frames");
+ return FALSE;
+ }
+
+ info->video_frame_count++;
+ if (info->video_frame_count <= (guint64)_MMCAMCORDER_MINIMUM_FRAME) {
+ /* _mmcam_dbg_log("Pass minimum frame: info->video_frame_count: %" G_GUINT64_FORMAT " ",
+ info->video_frame_count); */
+ info->filesize += (guint64)GST_BUFFER_SIZE(buffer);
+ return TRUE;
+ }
+
+ buffer_size = GST_BUFFER_SIZE(buffer);
+
+ if (sc->now_continuous_af) {
+ _mmcam_dbg_log("Start continuous AF when START recording");
+ __ta__(" _MMCamcorder_CMD_RECORD:START CAF",
+ ret = _mmcamcorder_adjust_auto_focus((MMHandleType)hcamcorder);
+ );
+ sc->now_continuous_af = FALSE;
+ if (ret != MM_ERROR_NONE) {
+ _mmcam_dbg_warn("Failed continuous AF when START recording");
+ }
+ }
+
+ /* get trailer size */
+ if (info->fileformat == MM_FILE_FORMAT_3GP || info->fileformat == MM_FILE_FORMAT_MP4) {
+ MMCAMCORDER_G_OBJECT_GET(sc->element[_MMCAMCORDER_ENCSINK_MUX].gst, "expected-trailer-size", &trailer_size);
+ } else {
+ trailer_size = 0;
+ }
+
+ /* to minimizing free space check overhead */
+ count = count % _MMCAMCORDER_FREE_SPACE_CHECK_INTERVAL;
+ if (count++ == 0) {
+ filename = info->filename;
+ ret = _mmcamcorder_get_freespace(filename, &free_space);
+
+ /*_mmcam_dbg_log("check free space for recording");*/
+
+ switch (ret) {
+ case -2: /* file not exist */
+ case -1: /* failed to get free space */
+ _mmcam_dbg_err("Error occured. [%d]", ret);
+ if (sc->ferror_count == 2 && sc->ferror_send == FALSE) {
+ sc->ferror_send = TRUE;
+ msg.id = MM_MESSAGE_CAMCORDER_ERROR;
+ if (ret == -2) {
+ msg.param.code = MM_ERROR_FILE_NOT_FOUND;
+ } else {
+ msg.param.code = MM_ERROR_FILE_READ;
+ }
+ _mmcamcroder_send_message((MMHandleType)hcamcorder, &msg);
+ } else {
+ sc->ferror_count++;
+ }
+
+ return FALSE; /* skip this buffer */
+ break;
+ default: /* succeeded to get free space */
+ /* check free space for recording */
+ /* get queued buffer size */
+ MMCAMCORDER_G_OBJECT_GET(sc->element[_MMCAMCORDER_ENCSINK_AENC_QUE].gst, "current-level-bytes", &aq_size);
+ MMCAMCORDER_G_OBJECT_GET(sc->element[_MMCAMCORDER_ENCSINK_VENC_QUE].gst, "current-level-bytes", &vq_size);
+ queued_buffer = aq_size + vq_size;
+
+ /* check free space */
+ if (free_space < (_MMCAMCORDER_MINIMUM_SPACE + buffer_size + trailer_size + queued_buffer)) {
+ _mmcam_dbg_warn("No more space for recording!!! Recording is paused.");
+ _mmcam_dbg_warn("Free Space : [%" G_GUINT64_FORMAT "], trailer size : [%" G_GUINT64_FORMAT "]," \
+ " buffer size : [%" G_GUINT64_FORMAT "], queued buffer size : [%" G_GUINT64_FORMAT "]", \
+ free_space, trailer_size, buffer_size, queued_buffer);
+
+ if (!sc->isMaxsizePausing) {
+ MMCAMCORDER_G_OBJECT_SET( sc->element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "block", TRUE);
+ sc->isMaxsizePausing = TRUE;
+
+ msg.id = MM_MESSAGE_CAMCORDER_NO_FREE_SPACE;
+ _mmcamcroder_send_message((MMHandleType)hcamcorder, &msg);
+ }
+
+ return FALSE;
+ }
+ break;
+ }
+ }
+
+ info->filesize += (guint64)buffer_size;
+
+ return TRUE;
+}
+
+
+static gboolean __mmcamcorder_video_dataprobe_slow(GstPad *pad, GstBuffer *buffer, gpointer u_data)
+{
+ guint min_fps = 15;
+ guint64 trailer_size = 0;
+ static guint count = 0;
+
+ GstClockTime b_time;
+
+ mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(u_data);
+ _MMCamcorderMsgItem msg;
+ _MMCamcorderSubContext *sc = NULL;
+ _MMCamcorderVideoInfo *info = NULL;
+
+ mmf_return_val_if_fail(buffer, FALSE);
+ mmf_return_val_if_fail(hcamcorder, TRUE);
+
+ sc = MMF_CAMCORDER_SUBCONTEXT(u_data);
+ mmf_return_val_if_fail(sc, TRUE);
+ mmf_return_val_if_fail(sc->info, TRUE);
+
+ info = sc->info;
+ count %= min_fps;
+ b_time = GST_BUFFER_TIMESTAMP(buffer);
+
+ if (!count) {
+ if (info->fileformat == MM_FILE_FORMAT_3GP || info->fileformat == MM_FILE_FORMAT_MP4) {
+ MMCAMCORDER_G_OBJECT_GET(sc->element[_MMCAMCORDER_ENCSINK_MUX].gst, "expected-trailer-size", &trailer_size);
+ } else {
+ trailer_size = 0;
+ }
+
+ msg.id = MM_MESSAGE_CAMCORDER_RECORDING_STATUS;
+ msg.param.recording_status.elapsed = (unsigned int)GST_TIME_AS_MSECONDS(b_time);
+ msg.param.recording_status.filesize = (unsigned int)((info->filesize + trailer_size) >> 10);
+ _mmcamcroder_send_message((MMHandleType)hcamcorder, &msg);
+ }
+
+ count++;
+
+ GST_BUFFER_TIMESTAMP(buffer) = b_time * (info->multiple_fps);
+
+ return TRUE;
+}
+
+
+static gboolean __mmcamcorder_audioque_dataprobe(GstPad *pad, GstBuffer *buffer, gpointer u_data)
+{
+ _MMCamcorderMsgItem msg;
+ guint64 trailer_size = 0;
+ guint64 rec_pipe_time = 0;
+ _MMCamcorderSubContext *sc = NULL;
+ GstElement *pipeline = NULL;
+ mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(u_data);
+ _MMCamcorderVideoInfo *info = NULL;
+
+ mmf_return_val_if_fail(buffer, FALSE);
+ mmf_return_val_if_fail(hcamcorder, TRUE);
+ sc = MMF_CAMCORDER_SUBCONTEXT(u_data);
+
+ mmf_return_val_if_fail(sc, TRUE);
+ mmf_return_val_if_fail(sc->info, TRUE);
+ mmf_return_val_if_fail(sc->element, TRUE);
+
+ info = sc->info;
+ pipeline = sc->element[_MMCAMCORDER_MAIN_PIPE].gst;
+
+ if (!GST_CLOCK_TIME_IS_VALID(GST_BUFFER_TIMESTAMP(buffer))) {
+ _mmcam_dbg_err( "Buffer timestamp is invalid, check it");
+ return TRUE;
+ }
+
+ rec_pipe_time = GST_TIME_AS_MSECONDS(GST_BUFFER_TIMESTAMP(buffer));
+
+ if (info->fileformat == MM_FILE_FORMAT_3GP || info->fileformat == MM_FILE_FORMAT_MP4) {
+ MMCAMCORDER_G_OBJECT_GET(sc->element[_MMCAMCORDER_ENCSINK_MUX].gst, "expected-trailer-size", &trailer_size);
+ } else {
+ trailer_size = 0;
+ }
+
+ if (info->max_time > 0 && rec_pipe_time > info->max_time) {
+ _mmcam_dbg_warn("Current time : [%" G_GUINT64_FORMAT "], Maximum time : [%" G_GUINT64_FORMAT "]", \
+ rec_pipe_time, info->max_time);
+
+ if (!sc->isMaxtimePausing) {
+ MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_ENCSINK_ENCBIN].gst, "block", TRUE);
+
+ sc->isMaxtimePausing = TRUE;
+
+ msg.id = MM_MESSAGE_CAMCORDER_RECORDING_STATUS;
+ msg.param.recording_status.elapsed = (unsigned int)rec_pipe_time;
+ msg.param.recording_status.filesize = (unsigned int)((info->filesize + trailer_size) >> 10);
+ _mmcamcroder_send_message((MMHandleType)hcamcorder, &msg);
+
+ msg.id = MM_MESSAGE_CAMCORDER_TIME_LIMIT;
+ _mmcamcroder_send_message((MMHandleType)hcamcorder, &msg);
+ }
+
+ return FALSE;
+ }
+
+ /*_mmcam_dbg_log("_mmcamcorder_audioque_dataprobe :: time [%" GST_TIME_FORMAT "], size [%d]",
+ GST_TIME_ARGS(rec_pipe_time), (info->filesize + trailer_size) >> 10);*/
+
+ msg.id = MM_MESSAGE_CAMCORDER_RECORDING_STATUS;
+ msg.param.recording_status.elapsed = (unsigned int)rec_pipe_time;
+ msg.param.recording_status.filesize = (unsigned int)((info->filesize + trailer_size) >> 10);
+ _mmcamcroder_send_message((MMHandleType)hcamcorder, &msg);
+
+ return TRUE;
+}
+
+
+static gboolean __mmcamcorder_audio_dataprobe_audio_mute(GstPad *pad, GstBuffer *buffer, gpointer u_data)
+{
+ mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(u_data);
+ double volume = 0.0;
+ int format = 0;
+ int channel = 0;
+ int err = MM_ERROR_UNKNOWN;
+ char *err_name = NULL;
+
+ mmf_return_val_if_fail(buffer, FALSE);
+ mmf_return_val_if_fail(hcamcorder, FALSE);
+
+ /*_mmcam_dbg_log("AUDIO SRC time stamp : [%" GST_TIME_FORMAT "] \n", GST_TIME_ARGS(GST_BUFFER_TIMESTAMP(buffer)));*/
+ err = mm_camcorder_get_attributes((MMHandleType)hcamcorder, &err_name,
+ MMCAM_AUDIO_VOLUME, &volume,
+ MMCAM_AUDIO_FORMAT, &format,
+ MMCAM_AUDIO_CHANNEL, &channel,
+ NULL);
+ if (err != MM_ERROR_NONE) {
+ _mmcam_dbg_warn("Get attrs fail. (%s:%x)", err_name, err);
+ SAFE_FREE(err_name);
+ return err;
+ }
+
+ /* Set audio stream NULL */
+ if (volume == 0.0) {
+ memset(GST_BUFFER_DATA(buffer), 0, GST_BUFFER_SIZE(buffer));
+ }
+
+ /* CALL audio stream callback */
+ if (hcamcorder->astream_cb && buffer && GST_BUFFER_DATA(buffer)) {
+ MMCamcorderAudioStreamDataType stream;
+
+ if (_mmcamcorder_get_state((MMHandleType)hcamcorder) < MM_CAMCORDER_STATE_PREPARE) {
+ _mmcam_dbg_warn("Not ready for stream callback");
+ return TRUE;
+ }
+
+ /*_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.format = format;
+ stream.channel = channel;
+ stream.length = GST_BUFFER_SIZE(buffer);
+ stream.timestamp = (unsigned int)(GST_BUFFER_TIMESTAMP(buffer)/1000000); /* nano -> milli second */
+
+ _MMCAMCORDER_LOCK_ASTREAM_CALLBACK(hcamcorder);
+
+ if (hcamcorder->astream_cb) {
+ hcamcorder->astream_cb(&stream, hcamcorder->astream_cb_param);
+ }
+
+ _MMCAMCORDER_UNLOCK_ASTREAM_CALLBACK(hcamcorder);
+ }
+
+ return TRUE;
+}
+
+
+static gboolean __mmcamcorder_add_locationinfo(MMHandleType handle, int fileformat)
+{
+ gboolean bret = FALSE;
+
+ switch (fileformat) {
+ case MM_FILE_FORMAT_3GP:
+ case MM_FILE_FORMAT_MP4:
+ bret = __mmcamcorder_add_locationinfo_mp4(handle);
+ break;
+ default:
+ _mmcam_dbg_warn("Unsupported fileformat to insert location info (%d)", fileformat);
+ break;
+ }
+
+ return bret;
+}
+
+
+static gboolean __mmcamcorder_add_locationinfo_mp4(MMHandleType handle)
+{
+ FILE *f = NULL;
+ guchar buf[4];
+ guint64 udta_size = 0;
+ gint64 current_pos = 0;
+ gint64 moov_pos = 0;
+ gint64 udta_pos = 0;
+ gdouble longitude = 0;
+ gdouble latitude = 0;
+ gdouble altitude = 0;
+ int err = 0;
+ char *err_name = NULL;
+ _MMCamcorderLocationInfo location_info = {0,};
+
+ _MMCamcorderVideoInfo *info = 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);
+
+ mmf_return_val_if_fail(sc, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
+ mmf_return_val_if_fail(sc->info, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
+
+ _mmcam_dbg_log("");
+
+ info = sc->info;
+
+ f = fopen(info->filename, "rb+");
+ if (f == NULL) {
+ return FALSE;
+ }
+
+ err = mm_camcorder_get_attributes(handle, &err_name,
+ MMCAM_TAG_LATITUDE, &latitude,
+ MMCAM_TAG_LONGITUDE, &longitude,
+ MMCAM_TAG_ALTITUDE, &altitude,
+ NULL);
+ if (err != MM_ERROR_NONE) {
+ _mmcam_dbg_warn("Get tag attrs fail. (%s:%x)", err_name, err);
+ SAFE_FREE (err_name);
+ fclose(f);
+ f = NULL;
+ return FALSE;
+ }
+
+ location_info.longitude = _mmcamcorder_double_to_fix(longitude);
+ location_info.latitude = _mmcamcorder_double_to_fix(latitude);
+ location_info.altitude = _mmcamcorder_double_to_fix(altitude);
+
+ /* find udta container.
+ if, there are udta container, write loci box after that
+ else, make udta container and write loci box. */
+ if (_mmcamcorder_find_tag(f, MMCAM_FOURCC('u','d','t','a'))) {
+ _mmcam_dbg_log("find udta container");
+
+ /* read size */
+ if (fseek(f, -8L, SEEK_CUR) != 0) {
+ goto fail;
+ }
+
+ udta_pos = ftell(f);
+ if (udta_pos < 0) {
+ goto ftell_fail;
+ }
+
+ fread(&buf, sizeof(char), sizeof(buf), f);
+ udta_size = _mmcamcorder_get_container_size(buf);
+
+ /* goto end of udta and write 'loci' box */
+ if (fseek(f, (udta_size-4L), SEEK_CUR) != 0) {
+ goto fail;
+ }
+
+ if (!_mmcamcorder_write_loci(f, location_info)) {
+ goto fail;
+ }
+
+ current_pos = ftell(f);
+ if (current_pos < 0) {
+ goto ftell_fail;
+ }
+
+ if (!_mmcamcorder_update_size(f, udta_pos, current_pos)) {
+ goto fail;
+ }
+ } else {
+ _mmcam_dbg_log("No udta container");
+ if (fseek(f, 0, SEEK_END) != 0) {
+ goto fail;
+ }
+
+ if (!_mmcamcorder_write_udta(f, location_info)) {
+ goto fail;
+ }
+ }
+
+ /* find moov container.
+ update moov container size. */
+ if((current_pos = ftell(f))<0)
+ goto ftell_fail;
+
+ if (_mmcamcorder_find_tag(f, MMCAM_FOURCC('m','o','o','v'))) {
+ _mmcam_dbg_log("find moov container");
+ if (fseek(f, -8L, SEEK_CUR) !=0) {
+ goto fail;
+ }
+
+ moov_pos = ftell(f);
+ if (moov_pos < 0) {
+ goto ftell_fail;
+ }
+
+ if (!_mmcamcorder_update_size(f, moov_pos, current_pos)) {
+ goto fail;
+ }
+ } else {
+ _mmcam_dbg_err("No 'moov' container");
+ goto fail;
+ }
+
+ fclose(f);
+ return TRUE;
+
+fail:
+ fclose(f);
+ return FALSE;
+
+ftell_fail:
+ _mmcam_dbg_err("ftell() returns negative value.");
+ fclose(f);
+ return FALSE;
+}