From 235c811494b7fcc70c9575df92cc69990352f888 Mon Sep 17 00:00:00 2001 From: Kibum Kim Date: Mon, 27 Feb 2012 21:16:21 +0900 Subject: [PATCH] tizen beta release --- LICENSE | 206 ++ Makefile.am | 8 + TC/_export_env.sh | 16 + TC/_export_target_env.sh | 15 + TC/build.sh | 34 + TC/execute.sh | 32 + TC/making_new_tet_scen.py | 69 + TC/tet_scen | 26 + TC/tetbuild.cfg | 6 + TC/tetclean.cfg | 6 + TC/tetexec.cfg | 6 + TC/utc/.cproject | 210 ++ TC/utc/.project | 79 + TC/utc/Makefile | 131 + TC/utc/tslist | 21 + TC/utc/uts_mm_camcorder_cancel.c | 128 + TC/utc/uts_mm_camcorder_cancel.h | 36 + TC/utc/uts_mm_camcorder_capture_start.c | 130 + TC/utc/uts_mm_camcorder_capture_start.h | 36 + TC/utc/uts_mm_camcorder_capture_stop.c | 132 + TC/utc/uts_mm_camcorder_capture_stop.h | 36 + TC/utc/uts_mm_camcorder_commit.c | 131 + TC/utc/uts_mm_camcorder_commit.h | 36 + TC/utc/uts_mm_camcorder_create.c | 201 + TC/utc/uts_mm_camcorder_create.h | 38 + TC/utc/uts_mm_camcorder_destroy.c | 115 + TC/utc/uts_mm_camcorder_destroy.h | 36 + TC/utc/uts_mm_camcorder_get_attr_info.c | 176 + TC/utc/uts_mm_camcorder_get_attr_info.h | 38 + TC/utc/uts_mm_camcorder_get_attrs.c | 376 ++ TC/utc/uts_mm_camcorder_get_attrs.h | 43 + TC/utc/uts_mm_camcorder_get_state.c | 298 ++ TC/utc/uts_mm_camcorder_get_state.h | 37 + TC/utc/uts_mm_camcorder_pause.c | 138 + TC/utc/uts_mm_camcorder_pause.h | 36 + TC/utc/uts_mm_camcorder_realize.c | 146 + TC/utc/uts_mm_camcorder_realize.h | 36 + TC/utc/uts_mm_camcorder_record.c | 129 + TC/utc/uts_mm_camcorder_record.h | 36 + TC/utc/uts_mm_camcorder_set_attrs.c | 374 ++ TC/utc/uts_mm_camcorder_set_attrs.h | 44 + TC/utc/uts_mm_camcorder_set_message_callback.c | 434 +++ TC/utc/uts_mm_camcorder_set_message_callback.h | 42 + .../uts_mm_camcorder_set_video_capture_callback.c | 435 +++ .../uts_mm_camcorder_set_video_capture_callback.h | 43 + .../uts_mm_camcorder_set_video_stream_callback.c | 434 +++ .../uts_mm_camcorder_set_video_stream_callback.h | 43 + TC/utc/uts_mm_camcorder_start.c | 147 + TC/utc/uts_mm_camcorder_start.h | 36 + TC/utc/uts_mm_camcorder_start_focusing.c | 154 + TC/utc/uts_mm_camcorder_start_focusing.h | 36 + TC/utc/uts_mm_camcorder_stop.c | 148 + TC/utc/uts_mm_camcorder_stop.h | 36 + TC/utc/uts_mm_camcorder_stop_focusing.c | 161 + TC/utc/uts_mm_camcorder_stop_focusing.h | 36 + TC/utc/uts_mm_camcorder_unrealize.c | 149 + TC/utc/uts_mm_camcorder_unrealize.h | 36 + TC/utc/uts_mm_camcorder_utils.c | 911 +++++ TC/utc/uts_mm_camcorder_utils.h | 159 + autogen.sh | 7 + config.guess | 1517 ++++++++ config.sub | 1760 +++++++++ configure.ac | 112 + debian/changelog | 8 + debian/compat | 1 + debian/control | 27 + debian/copyright | 16 + debian/dirs | 2 + debian/docs | 0 debian/libmm-camcorder-dev.install.in | 5 + debian/libmm-camcorder.install.in | 5 + debian/rules | 138 + depcomp | 589 +++ image/camcorder_state.png | Bin 0 -> 33655 bytes install-sh | 519 +++ m4/lt~obsolete.m4 | 92 + missing | 367 ++ mm-camcorder.pc.in | 11 + packaging/libmm-camcorder.spec | 71 + sounds/af_fail.wav | Bin 0 -> 9748 bytes sounds/af_succeed.wav | Bin 0 -> 7102 bytes sounds/capture_shutter_01.wav | Bin 0 -> 31228 bytes sounds/capture_shutter_02.wav | Bin 0 -> 24152 bytes sounds/no_sound.wav | Bin 0 -> 116 bytes sounds/recording_start_01.wav | Bin 0 -> 26584 bytes sounds/recording_stop_01.wav | Bin 0 -> 26584 bytes src/Makefile.am | 69 + src/include/mm_camcorder.h | 2925 +++++++++++++++ src/include/mm_camcorder_attribute.h | 365 ++ src/include/mm_camcorder_audiorec.h | 103 + src/include/mm_camcorder_configure.h | 366 ++ src/include/mm_camcorder_exifdef.h | 99 + src/include/mm_camcorder_exifinfo.h | 161 + src/include/mm_camcorder_gstcommon.h | 183 + src/include/mm_camcorder_internal.h | 1072 ++++++ src/include/mm_camcorder_platform.h | 223 ++ src/include/mm_camcorder_sound.h | 103 + src/include/mm_camcorder_stillshot.h | 134 + src/include/mm_camcorder_util.h | 246 ++ src/include/mm_camcorder_videorec.h | 139 + src/mm_camcorder.c | 428 +++ src/mm_camcorder_attribute.c | 3882 ++++++++++++++++++++ src/mm_camcorder_audiorec.c | 1050 ++++++ src/mm_camcorder_configure.c | 3276 +++++++++++++++++ src/mm_camcorder_exifinfo.c | 642 ++++ src/mm_camcorder_gstcommon.c | 2243 +++++++++++ src/mm_camcorder_internal.c | 3449 +++++++++++++++++ src/mm_camcorder_platform.c | 977 +++++ src/mm_camcorder_sound.c | 491 +++ src/mm_camcorder_stillshot.c | 2815 ++++++++++++++ src/mm_camcorder_util.c | 1092 ++++++ src/mm_camcorder_videorec.c | 1496 ++++++++ symbols | 695 ++++ test/Makefile.am | 24 + test/mm_camcorder_testsuite.c | 3054 +++++++++++++++ 115 files changed, 44316 insertions(+) create mode 100644 LICENSE create mode 100644 Makefile.am create mode 100755 TC/_export_env.sh create mode 100755 TC/_export_target_env.sh create mode 100755 TC/build.sh create mode 100755 TC/execute.sh create mode 100755 TC/making_new_tet_scen.py create mode 100755 TC/tet_scen create mode 100644 TC/tetbuild.cfg create mode 100644 TC/tetclean.cfg create mode 100644 TC/tetexec.cfg create mode 100755 TC/utc/.cproject create mode 100755 TC/utc/.project create mode 100755 TC/utc/Makefile create mode 100644 TC/utc/tslist create mode 100644 TC/utc/uts_mm_camcorder_cancel.c create mode 100644 TC/utc/uts_mm_camcorder_cancel.h create mode 100644 TC/utc/uts_mm_camcorder_capture_start.c create mode 100644 TC/utc/uts_mm_camcorder_capture_start.h create mode 100644 TC/utc/uts_mm_camcorder_capture_stop.c create mode 100644 TC/utc/uts_mm_camcorder_capture_stop.h create mode 100644 TC/utc/uts_mm_camcorder_commit.c create mode 100644 TC/utc/uts_mm_camcorder_commit.h create mode 100644 TC/utc/uts_mm_camcorder_create.c create mode 100644 TC/utc/uts_mm_camcorder_create.h create mode 100644 TC/utc/uts_mm_camcorder_destroy.c create mode 100644 TC/utc/uts_mm_camcorder_destroy.h create mode 100644 TC/utc/uts_mm_camcorder_get_attr_info.c create mode 100644 TC/utc/uts_mm_camcorder_get_attr_info.h create mode 100644 TC/utc/uts_mm_camcorder_get_attrs.c create mode 100644 TC/utc/uts_mm_camcorder_get_attrs.h create mode 100644 TC/utc/uts_mm_camcorder_get_state.c create mode 100644 TC/utc/uts_mm_camcorder_get_state.h create mode 100644 TC/utc/uts_mm_camcorder_pause.c create mode 100644 TC/utc/uts_mm_camcorder_pause.h create mode 100644 TC/utc/uts_mm_camcorder_realize.c create mode 100644 TC/utc/uts_mm_camcorder_realize.h create mode 100644 TC/utc/uts_mm_camcorder_record.c create mode 100644 TC/utc/uts_mm_camcorder_record.h create mode 100644 TC/utc/uts_mm_camcorder_set_attrs.c create mode 100644 TC/utc/uts_mm_camcorder_set_attrs.h create mode 100644 TC/utc/uts_mm_camcorder_set_message_callback.c create mode 100644 TC/utc/uts_mm_camcorder_set_message_callback.h create mode 100644 TC/utc/uts_mm_camcorder_set_video_capture_callback.c create mode 100644 TC/utc/uts_mm_camcorder_set_video_capture_callback.h create mode 100644 TC/utc/uts_mm_camcorder_set_video_stream_callback.c create mode 100644 TC/utc/uts_mm_camcorder_set_video_stream_callback.h create mode 100644 TC/utc/uts_mm_camcorder_start.c create mode 100644 TC/utc/uts_mm_camcorder_start.h create mode 100644 TC/utc/uts_mm_camcorder_start_focusing.c create mode 100644 TC/utc/uts_mm_camcorder_start_focusing.h create mode 100644 TC/utc/uts_mm_camcorder_stop.c create mode 100644 TC/utc/uts_mm_camcorder_stop.h create mode 100644 TC/utc/uts_mm_camcorder_stop_focusing.c create mode 100644 TC/utc/uts_mm_camcorder_stop_focusing.h create mode 100644 TC/utc/uts_mm_camcorder_unrealize.c create mode 100644 TC/utc/uts_mm_camcorder_unrealize.h create mode 100644 TC/utc/uts_mm_camcorder_utils.c create mode 100644 TC/utc/uts_mm_camcorder_utils.h create mode 100755 autogen.sh create mode 100755 config.guess create mode 100755 config.sub create mode 100644 configure.ac create mode 100644 debian/changelog create mode 100644 debian/compat create mode 100644 debian/control create mode 100644 debian/copyright create mode 100644 debian/dirs create mode 100644 debian/docs create mode 100644 debian/libmm-camcorder-dev.install.in create mode 100644 debian/libmm-camcorder.install.in create mode 100755 debian/rules create mode 100755 depcomp create mode 100755 image/camcorder_state.png create mode 100755 install-sh create mode 100644 m4/lt~obsolete.m4 create mode 100755 missing create mode 100644 mm-camcorder.pc.in create mode 100644 packaging/libmm-camcorder.spec create mode 100644 sounds/af_fail.wav create mode 100644 sounds/af_succeed.wav create mode 100644 sounds/capture_shutter_01.wav create mode 100644 sounds/capture_shutter_02.wav create mode 100644 sounds/no_sound.wav create mode 100644 sounds/recording_start_01.wav create mode 100644 sounds/recording_stop_01.wav create mode 100644 src/Makefile.am create mode 100644 src/include/mm_camcorder.h create mode 100644 src/include/mm_camcorder_attribute.h create mode 100644 src/include/mm_camcorder_audiorec.h create mode 100644 src/include/mm_camcorder_configure.h create mode 100644 src/include/mm_camcorder_exifdef.h create mode 100644 src/include/mm_camcorder_exifinfo.h create mode 100644 src/include/mm_camcorder_gstcommon.h create mode 100644 src/include/mm_camcorder_internal.h create mode 100644 src/include/mm_camcorder_platform.h create mode 100644 src/include/mm_camcorder_sound.h create mode 100644 src/include/mm_camcorder_stillshot.h create mode 100644 src/include/mm_camcorder_util.h create mode 100644 src/include/mm_camcorder_videorec.h create mode 100644 src/mm_camcorder.c create mode 100644 src/mm_camcorder_attribute.c create mode 100644 src/mm_camcorder_audiorec.c create mode 100644 src/mm_camcorder_configure.c create mode 100644 src/mm_camcorder_exifinfo.c create mode 100644 src/mm_camcorder_gstcommon.c create mode 100644 src/mm_camcorder_internal.c create mode 100644 src/mm_camcorder_platform.c create mode 100644 src/mm_camcorder_sound.c create mode 100644 src/mm_camcorder_stillshot.c create mode 100644 src/mm_camcorder_util.c create mode 100644 src/mm_camcorder_videorec.c create mode 100644 symbols create mode 100755 test/Makefile.am create mode 100644 test/mm_camcorder_testsuite.c diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..bbe9d02 --- /dev/null +++ b/LICENSE @@ -0,0 +1,206 @@ +Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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. + + + diff --git a/Makefile.am b/Makefile.am new file mode 100644 index 0000000..e01f755 --- /dev/null +++ b/Makefile.am @@ -0,0 +1,8 @@ +ACLOCAL_AMFLAGS='-I m4' + +SUBDIRS = src test + +pcfiles = mm-camcorder.pc +pkgconfigdir = $(libdir)/pkgconfig +pkgconfig_DATA = $(pcfiles) +EXTRA_DIST = $(pcfiles) diff --git a/TC/_export_env.sh b/TC/_export_env.sh new file mode 100755 index 0000000..3089986 --- /dev/null +++ b/TC/_export_env.sh @@ -0,0 +1,16 @@ +#!/bin/sh +export ARCH=target + +export TET_INSTALL_PATH=/scratchbox/tetware +export TET_TARGET_PATH=$TET_INSTALL_PATH/tetware-target +export PATH=$TET_TARGET_PATH/bin:$PATH +export LD_LIBRARY_PATH=$TET_TARGET_PATH/lib/tet3:$LD_LIBRARY_PATH + +export TET_ROOT=$TET_TARGET_PATH + +set $(pwd) +export TET_SUITE_ROOT=$1 + +set $(date +%s) +FILE_NAME_EXTENSION=$1 + diff --git a/TC/_export_target_env.sh b/TC/_export_target_env.sh new file mode 100755 index 0000000..afeb412 --- /dev/null +++ b/TC/_export_target_env.sh @@ -0,0 +1,15 @@ +export ARCH=target + +export TET_INSTALL_PATH=/mnt/nfs/tetware +export TET_TARGET_PATH=$TET_INSTALL_PATH/tetware-target +export PATH=$TET_TARGET_PATH/bin:$PATH +export LD_LIBRARY_PATH=$TET_TARGET_PATH/lib/tet3:$LD_LIBRARY_PATH + +export TET_ROOT=$TET_TARGET_PATH + +set $(pwd) +export TET_SUITE_ROOT=$1 + +set $(data +s) +FILE_NAME_EXTENSION=$1 + diff --git a/TC/build.sh b/TC/build.sh new file mode 100755 index 0000000..2761b14 --- /dev/null +++ b/TC/build.sh @@ -0,0 +1,34 @@ +#!/bin/sh +#./_export_env.sh +export ARCH=target + +export TET_INSTALL_PATH=/scratchbox/tetware +export TET_TARGET_PATH=$TET_INSTALL_PATH/tetware-target +export PATH=$TET_TARGET_PATH/bin:$PATH +export LD_LIBRARY_PATH=$TET_TARGET_PATH/lib/tet3:$LD_LIBRARY_PATH + +export TET_ROOT=$TET_TARGET_PATH + +set $(pwd) +export TET_SUITE_ROOT=$1 + +set $(date +%s) +FILE_NAME_EXTENSION=$1 + +echo PATH=$PATH +echo LD_LIBRARY_PATH=$LD_LIBRARY_PATH +echo TET_ROOT=$TET_ROOT +echo TET_SUITE_ROOT=$TET_SUITE_ROOT +echo ARCH=$ARCH + +RESULT_DIR=results-$ARCH +HTML_RESULT=$RESULT_DIR/build-tar-result-$FILE_NAME_EXTENSION.html +JOURNAL_RESULT=$RESULT_DIR/build-tar-result-$FILE_NAME_EXTENSION.journal + +mkdir $RESULT_DIR +mkdir $TET_SUITE_ROOT/utc/tet_xres + +tcc -c -p ./ +tcc -b -j $JOURNAL_RESULT -p ./ +grw -c 3 -f chtml -o $HTML_RESULT $JOURNAL_RESULT + diff --git a/TC/execute.sh b/TC/execute.sh new file mode 100755 index 0000000..078a91c --- /dev/null +++ b/TC/execute.sh @@ -0,0 +1,32 @@ +#!/bin/sh +#./_export_target_env.sh +export ARCH=target + +export TET_INSTALL_PATH=/mnt/nfs/tetware +export TET_TARGET_PATH=$TET_INSTALL_PATH/tetware-target +export PATH=$TET_TARGET_PATH/bin:$PATH +export LD_LIBRARY_PATH=$TET_TARGET_PATH/lib/tet3:$LD_LIBRARY_PATH + +export TET_ROOT=$TET_TARGET_PATH + +set $(pwd) +export TET_SUITE_ROOT=$1 + +set $(date +%s) +FILE_NAME_EXTENSION=$1 + +echo PATH=$PATH +echo LD_LIBRARY_PATH=$LD_LIBRARY_PATH +echo TET_ROOT=$TET_ROOT +echo TET_SUITE_ROOT=$TET_SUITE_ROOT +echo ARCH=$ARCH + +RESULT_DIR=results-$ARCH +HTML_RESULT=$RESULT_DIR/exec-tar-result-$FILE_NAME_EXTENSION.html +JOURNAL_RESULT=$RESULT_DIR/exec-tar-result-$FILE_NAME_EXTENSION.journal + +mkdir $RESULT_DIR + +tcc -e -j $JOURNAL_RESULT -p ./ +grw -c 3 -f chtml -o $HTML_RESULT $JOURNAL_RESULT + diff --git a/TC/making_new_tet_scen.py b/TC/making_new_tet_scen.py new file mode 100755 index 0000000..6c5b845 --- /dev/null +++ b/TC/making_new_tet_scen.py @@ -0,0 +1,69 @@ +#!/usr/bin/python + +############################################# +# tet_scen auto generator +# +# ** argv[1] = TC root +############################################# + +import sys,string,os + + +write_file = open("tet_scen", 'w') + +# +# making new tet_scen +# +def making_tet_scen (filename): + #tmp_list = filename.strip().split('/') + n_filename = filename.replace(' ', '\\ ') + #print n_filename + #new_path = "/"+ sys.argv[1] +"/"+n_filename[2:-6] + new_path = "/"+n_filename[:-6] + #print new_path + file = open(filename, 'r') + lines = file.readlines() + for line in lines: + if len(line.strip()) > 1: + list = line.strip().split('/') + #print new_path + list[-1] + write_file.write("\t"+new_path+list[-1]+"\n") + +# +# usage() +# +def usage(): + print(" ") + print("./making_new_tet_scen.py tc_root") + print("Put the Test Case's root directory.") + print("Do not include '/' at the end") + print(" ") + +# +# main() +# +def main(): + if len(sys.argv) < 2: + usage() + sys.exit(0) + + os.system('find '+ sys.argv[1] +' -name "tslist" > tslist.txt') + + #write_file = open("tetscen", w) + write_file.write("# auto generated tet_scen\n") + write_file.write("all\n") + write_file.write("\t\"Starting Full Test Suite\"\n") + + for file in open("tslist.txt", 'r'): + #print file.strip() + making_tet_scen(file.strip()) + + write_file.write("\t\"Completed Full Test Suite\"\n") + write_file.write("# EOF\n") + write_file.close() + print(" ") + print("==============================") + print("New tet_scen file is made~~~~") + print("==============================") + print(" ") +main() diff --git a/TC/tet_scen b/TC/tet_scen new file mode 100755 index 0000000..38366c3 --- /dev/null +++ b/TC/tet_scen @@ -0,0 +1,26 @@ +# auto generated tet_scen +all + "Starting MMFW Camcorder APIs test" + /utc/uts_mm_camcorder_cancel + /utc/uts_mm_camcorder_capture_start + /utc/uts_mm_camcorder_capture_stop + /utc/uts_mm_camcorder_commit + /utc/uts_mm_camcorder_create + /utc/uts_mm_camcorder_destroy + /utc/uts_mm_camcorder_get_attrs + /utc/uts_mm_camcorder_get_state + /utc/uts_mm_camcorder_pause + /utc/uts_mm_camcorder_realize + /utc/uts_mm_camcorder_record + /utc/uts_mm_camcorder_set_attrs + /utc/uts_mm_camcorder_set_message_callback + /utc/uts_mm_camcorder_set_video_capture_callback + /utc/uts_mm_camcorder_set_video_stream_callback + /utc/uts_mm_camcorder_start + /utc/uts_mm_camcorder_start_focusing + /utc/uts_mm_camcorder_stop + /utc/uts_mm_camcorder_stop_focusing + /utc/uts_mm_camcorder_unrealize + /utc/uts_mm_camcorder_get_attr_info + "Completed MMFW Camcorder APIs test" +# EOF diff --git a/TC/tetbuild.cfg b/TC/tetbuild.cfg new file mode 100644 index 0000000..d947407 --- /dev/null +++ b/TC/tetbuild.cfg @@ -0,0 +1,6 @@ +TET_OUTPUT_CAPTURE=True +TET_BUILD_TOOL=make +TET_BUILD_FILE=-f Makefile +TET_API_COMPLIANT=True +TET_PASS_TC_NAME=True + diff --git a/TC/tetclean.cfg b/TC/tetclean.cfg new file mode 100644 index 0000000..97c71c7 --- /dev/null +++ b/TC/tetclean.cfg @@ -0,0 +1,6 @@ +TET_OUTPUT_CAPTURE=True +TET_BUILD_TOOL=make clean +TET_BUILD_FILE=Makefile +TET_API_COMPLIANT=True +TET_PASS_TC_NAME=True + diff --git a/TC/tetexec.cfg b/TC/tetexec.cfg new file mode 100644 index 0000000..ed4e15d --- /dev/null +++ b/TC/tetexec.cfg @@ -0,0 +1,6 @@ +TET_OUTPUT_CAPTURE=True +TET_BUILD_TOOL= +TET_BUILD_FILE= +TET_API_COMPLIANT=True +TET_PASS_TC_NAME=True + diff --git a/TC/utc/.cproject b/TC/utc/.cproject new file mode 100755 index 0000000..1dadf26 --- /dev/null +++ b/TC/utc/.cproject @@ -0,0 +1,210 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/TC/utc/.project b/TC/utc/.project new file mode 100755 index 0000000..c1905de --- /dev/null +++ b/TC/utc/.project @@ -0,0 +1,79 @@ + + + utc + + + + + + org.eclipse.cdt.managedbuilder.core.genmakebuilder + clean,full,incremental, + + + ?name? + + + + org.eclipse.cdt.make.core.append_environment + true + + + org.eclipse.cdt.make.core.autoBuildTarget + all + + + org.eclipse.cdt.make.core.buildArguments + + + + org.eclipse.cdt.make.core.buildCommand + make + + + org.eclipse.cdt.make.core.cleanBuildTarget + clean + + + org.eclipse.cdt.make.core.contents + org.eclipse.cdt.make.core.activeConfigSettings + + + org.eclipse.cdt.make.core.enableAutoBuild + false + + + org.eclipse.cdt.make.core.enableCleanBuild + true + + + org.eclipse.cdt.make.core.enableFullBuild + true + + + org.eclipse.cdt.make.core.fullBuildTarget + all + + + org.eclipse.cdt.make.core.stopOnError + true + + + org.eclipse.cdt.make.core.useDefaultBuildCmd + true + + + + + org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder + full,incremental, + + + + + + org.eclipse.cdt.core.cnature + org.eclipse.cdt.core.ccnature + org.eclipse.cdt.managedbuilder.core.managedBuildNature + org.eclipse.cdt.managedbuilder.core.ScannerConfigNature + + diff --git a/TC/utc/Makefile b/TC/utc/Makefile new file mode 100755 index 0000000..17c28c1 --- /dev/null +++ b/TC/utc/Makefile @@ -0,0 +1,131 @@ +ifeq ($(ARCH),target) + PKG_CONFIG_PATH=/usr/lib/pkgconfig + export PKG_CONFIG_PATH + CC=arm-linux-gcc -Wall + CXX=arm-linux-g++ -Wall +else + PKG_CONFIG_PATH=/usr/lib/pkgconfig + export PKG_CONFIG_PATH + CC=gcc -Wall + CXX=gcc -Wall +endif + +TS1=uts_mm_camcorder_cancel +TS2=uts_mm_camcorder_capture_start +TS3=uts_mm_camcorder_capture_stop +TS4=uts_mm_camcorder_commit +TS5=uts_mm_camcorder_create +TS6=uts_mm_camcorder_destroy +TS7=uts_mm_camcorder_get_attrs +TS8=uts_mm_camcorder_get_state +TS9=uts_mm_camcorder_pause +TS10=uts_mm_camcorder_realize +TS11=uts_mm_camcorder_record +TS12=uts_mm_camcorder_set_attrs +TS13=uts_mm_camcorder_set_message_callback +TS14=uts_mm_camcorder_set_video_capture_callback +TS15=uts_mm_camcorder_set_video_stream_callback +TS16=uts_mm_camcorder_start +TS17=uts_mm_camcorder_start_focusing +TS18=uts_mm_camcorder_stop +TS19=uts_mm_camcorder_stop_focusing +TS20=uts_mm_camcorder_unrealize +TS21=uts_mm_camcorder_get_attr_info + +LIBS = `pkg-config --libs mm-camcorder` + +LIBS +=-L/usr/lib/:/usr/lib/pkgconfig + +#LIBS +=/scratchbox/tetware/tetware-target/lib/tet3/tcm_s.o +#LIBS +=-L/scratchbox/tetware/tetware-target/lib/lib/tet3 -ltcm_s +#LIBS +=-L/scratchbox/tetware/tetware-target/lib/lib/tet3/ -lapi_s +LIBS +=$(TET_ROOT)/lib/tet3/tcm_s.o +LIBS +=-L$(TET_ROOT)/lib/tet3 -ltcm_s +LIBS +=-L$(TET_ROOT)/lib/tet3/ -lapi_s +#LIBS +=/scratchbox/users/root/home/share/work_box/TETware3.7/tetware-target/src/tet3/apishlib/libapi_s.so +#/scratchbox/TETware3.7/tetware-simulator/lib/tet3 + +INCS = -I. `pkg-config --cflags mm-camcorder` + + +#INCS += -I/scratchbox/tetware/tetware-target/lib/inc/tet3 +INCS += -I$(TET_ROOT)/inc/tet3 +#INCS += -I/usr/include/mmf -I/scratchbox/tetware/tetware-target/src/tet3/inc -I/scratchbox/tetware/tetware-target/inc/tet3 +INCS += -I/usr/include/mmf + +CFLAGS = $(INCS) +CC += $(CFLAGS) +LDFLAGS = $(LIBS) + + +all: $(TS1) $(TS2) $(TS3) $(TS4) $(TS5) $(TS6) $(TS7) $(TS8) $(TS9) $(TS10) $(TS11) $(TS12) $(TS13) $(TS14) $(TS15) $(TS16) $(TS17) $(TS18) $(TS19) $(TS20) $(TS21) $(TS22) $(TS23) $(TS24) + + +$(TS1): uts_mm_camcorder_cancel.[ch] uts_mm_camcorder_utils.[ch] + $(CC) -o $(TS1) uts_mm_camcorder_utils.c uts_mm_camcorder_cancel.c $(LDFLAGS) + +$(TS2): uts_mm_camcorder_capture_start.[ch] uts_mm_camcorder_utils.[ch] + $(CC) -o $(TS2) uts_mm_camcorder_utils.c uts_mm_camcorder_capture_start.c $(LDFLAGS) + +$(TS3): uts_mm_camcorder_capture_stop.[ch] uts_mm_camcorder_utils.[ch] + $(CC) -o $(TS3) uts_mm_camcorder_utils.c uts_mm_camcorder_capture_stop.c $(LDFLAGS) + +$(TS4): uts_mm_camcorder_commit.[ch] uts_mm_camcorder_utils.[ch] + $(CC) -o $(TS4) uts_mm_camcorder_utils.c uts_mm_camcorder_commit.c $(LDFLAGS) + +$(TS5): uts_mm_camcorder_create.[ch] uts_mm_camcorder_utils.[ch] + $(CC) -o $(TS5) uts_mm_camcorder_utils.c uts_mm_camcorder_create.c $(LDFLAGS) + +$(TS6): uts_mm_camcorder_destroy.[ch] uts_mm_camcorder_utils.[ch] + $(CC) -o $(TS6) uts_mm_camcorder_utils.c uts_mm_camcorder_destroy.c $(LDFLAGS) + +$(TS7): uts_mm_camcorder_get_attrs.[ch] uts_mm_camcorder_utils.[ch] + $(CC) -o $(TS7) uts_mm_camcorder_utils.c uts_mm_camcorder_get_attrs.c $(LDFLAGS) + +$(TS8): uts_mm_camcorder_get_state.[ch] uts_mm_camcorder_utils.[ch] + $(CC) -o $(TS8) uts_mm_camcorder_utils.c uts_mm_camcorder_get_state.c $(LDFLAGS) + +$(TS9): uts_mm_camcorder_pause.[ch] uts_mm_camcorder_utils.[ch] + $(CC) -o $(TS9) uts_mm_camcorder_utils.c uts_mm_camcorder_pause.c $(LDFLAGS) + +$(TS10): uts_mm_camcorder_realize.[ch] uts_mm_camcorder_utils.[ch] + $(CC) -o $(TS10) uts_mm_camcorder_utils.c uts_mm_camcorder_realize.c $(LDFLAGS) + +$(TS11): uts_mm_camcorder_record.[ch] uts_mm_camcorder_utils.[ch] + $(CC) -o $(TS11) uts_mm_camcorder_utils.c uts_mm_camcorder_record.c $(LDFLAGS) + +$(TS12): uts_mm_camcorder_set_attrs.[ch] uts_mm_camcorder_utils.[ch] + $(CC) -o $(TS12) uts_mm_camcorder_utils.c uts_mm_camcorder_set_attrs.c $(LDFLAGS) + +$(TS13): uts_mm_camcorder_set_message_callback.[ch] uts_mm_camcorder_utils.[ch] + $(CC) -o $(TS13) uts_mm_camcorder_utils.c uts_mm_camcorder_set_message_callback.c $(LDFLAGS) + +$(TS14): uts_mm_camcorder_set_video_capture_callback.[ch] uts_mm_camcorder_utils.[ch] + $(CC) -o $(TS14) uts_mm_camcorder_utils.c uts_mm_camcorder_set_video_capture_callback.c $(LDFLAGS) + +$(TS15): uts_mm_camcorder_set_video_stream_callback.[ch] uts_mm_camcorder_utils.[ch] + $(CC) -o $(TS15) uts_mm_camcorder_utils.c uts_mm_camcorder_set_video_stream_callback.c $(LDFLAGS) + +$(TS16): uts_mm_camcorder_start.[ch] uts_mm_camcorder_utils.[ch] + $(CC) -o $(TS16) uts_mm_camcorder_utils.c uts_mm_camcorder_start.c $(LDFLAGS) + +$(TS17): uts_mm_camcorder_start_focusing.[ch] uts_mm_camcorder_utils.[ch] + $(CC) -o $(TS17) uts_mm_camcorder_utils.c uts_mm_camcorder_start_focusing.c $(LDFLAGS) + +$(TS18): uts_mm_camcorder_stop.[ch] uts_mm_camcorder_utils.[ch] + $(CC) -o $(TS18) uts_mm_camcorder_utils.c uts_mm_camcorder_stop.c $(LDFLAGS) + +$(TS19): uts_mm_camcorder_stop_focusing.[ch] uts_mm_camcorder_utils.[ch] + $(CC) -o $(TS19) uts_mm_camcorder_utils.c uts_mm_camcorder_stop_focusing.c $(LDFLAGS) + +$(TS20): uts_mm_camcorder_unrealize.[ch] uts_mm_camcorder_utils.[ch] + $(CC) -o $(TS20) uts_mm_camcorder_utils.c uts_mm_camcorder_unrealize.c $(LDFLAGS) + +$(TS21): uts_mm_camcorder_get_attr_info.[ch] uts_mm_camcorder_utils.[ch] + $(CC) -o $(TS21) uts_mm_camcorder_utils.c uts_mm_camcorder_get_attr_info.c $(LDFLAGS) + +clean: + rm -rf *~ *.o $(TS1) $(TS2) $(TS3) $(TS4) $(TS5) $(TS6) $(TS7) $(TS8) $(TS9) $(TS10) $(TS11) $(TS12) $(TS13) $(TS14) $(TS15) $(TS16) $(TS17) $(TS18) $(TS19) $(TS20) $(TS21) + + + diff --git a/TC/utc/tslist b/TC/utc/tslist new file mode 100644 index 0000000..5dd41c4 --- /dev/null +++ b/TC/utc/tslist @@ -0,0 +1,21 @@ +uts_mm_camcorder_cancel +uts_mm_camcorder_capture_start +uts_mm_camcorder_capture_stop +uts_mm_camcorder_commit +uts_mm_camcorder_create +uts_mm_camcorder_destroy +uts_mm_camcorder_get_attrs +uts_mm_camcorder_get_state +uts_mm_camcorder_pause +uts_mm_camcorder_realize +uts_mm_camcorder_record +uts_mm_camcorder_set_attrs +uts_mm_camcorder_set_message_callback +uts_mm_camcorder_set_video_capture_callback +uts_mm_camcorder_set_video_stream_callback +uts_mm_camcorder_start +uts_mm_camcorder_start_focusing +uts_mm_camcorder_stop +uts_mm_camcorder_stop_focusing +uts_mm_camcorder_unrealize +uts_mm_camcorder_get_attr_info diff --git a/TC/utc/uts_mm_camcorder_cancel.c b/TC/utc/uts_mm_camcorder_cancel.c new file mode 100644 index 0000000..414b2ce --- /dev/null +++ b/TC/utc/uts_mm_camcorder_cancel.c @@ -0,0 +1,128 @@ +/* + * libmm-camcorder TC + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Jeongmo Yang + * + * 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. + * + */ + +/** +* @ingroup Camcorder_API +* @addtogroup CAMCORDER Camcorder +*/ + +/** +* @ingroup CAMCORDER Camcorder +* @addtogroup UTS_CAMCORDER Unit +*/ + +/** +* @ingroup UTS_CAMCORDER Unit +* @addtogroup UTS_MM_CAMCORDER_CANCEL Uts_Mm_Camcorder_Cancel +* @{ +*/ + +/** +* @file uts_mm_camcorder_cancel.c +* @brief This is a suite of unit test cases to test mm_camcorder_cancel API. +* @author Kishor Reddy (p.kishor@samsung.com) +* @version Initial Creation V0.1 +* @date 2008.11.27 +*/ + +#include "uts_mm_camcorder_cancel.h" +#include "uts_mm_camcorder_utils.h" + +struct tet_testlist tet_testlist[] = { + {utc_camcorder_cancel_001,1}, + {utc_camcorder_cancel_002,2}, + {NULL,0} +}; + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * @brief This tests mm_camcorder_cancel API in normal conditions + * @par ID: + * UTC_CAMCORDER_CANCEL_001 + * @param [in] camcorder = Valid Camcorder Handle + * @param [out] None + * @pre Camcorder should be in RECORDING state. + * @post Camcorder should come to PREPARE state. + * @returns MM_ERROR_NONE + */ +void utc_camcorder_cancel_001() +{ + tet_printf("\n ======================utc_camcorder_cancel_001====================== \n"); + + gint errorValue = -1; + gboolean bReturnValue = false; + MMHandleType camcorder = 0; + int mode = VIDEO_MODE; + MMCamPreset info; + info.videodev_type = MM_VIDEO_DEVICE_CAMERA0; + + bReturnValue = StartCamcorder(&camcorder, &info, mode); + if (true != bReturnValue) { + tet_printf("\n Failed in utc_camcorder_cancel_001 while starting the camcorder \n"); + tet_result(TET_UNTESTED); + return; + } + + errorValue = mm_camcorder_record(camcorder); + if (MM_ERROR_NONE != errorValue) { + tet_printf("\n Failed in utc_camcorder_cancel_001 while recording with error %x \n", errorValue); + tet_result(TET_UNTESTED); + return; + } + + errorValue = mm_camcorder_cancel(camcorder); + + bReturnValue = StopCamcorder(camcorder); + + dts_check_eq( "utc_camcorder_cancel_001", errorValue, MM_ERROR_NONE, + "Failed in utc_camcorder_cancel_001 while canceling the camcorder recording with error %x", errorValue ); + + if (true != bReturnValue) { + tet_printf("\n Failed in utc_camcorder_cancel_001 while stoping the camcorder \n"); + return; + } + + return; +} +//////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * @brief This tests mm_camcorder_cancel API with invalid camcorder. + * @par ID: + * UTC_CAMCORDER_CANCEL_002 + * @param [in] Invalid handle + * @param [out] None + * @returns Error code + */ +void utc_camcorder_cancel_002() +{ + tet_printf("\n ======================utc_camcorder_cancel_002====================== \n"); + gint errorValue = -1; + errorValue = mm_camcorder_cancel(0); + + dts_check_ne( "mm_camcorder_cancel", errorValue, MM_ERROR_NONE, + "Failed in utc_camcorder_cancel_002 while canceling the camcorder recording with error %x", errorValue ); + + return; +} +/////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** @} */ + + diff --git a/TC/utc/uts_mm_camcorder_cancel.h b/TC/utc/uts_mm_camcorder_cancel.h new file mode 100644 index 0000000..72c6a83 --- /dev/null +++ b/TC/utc/uts_mm_camcorder_cancel.h @@ -0,0 +1,36 @@ +/* + * libmm-camcorder TC + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Jeongmo Yang + * + * 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. + * + */ + +/** +* @file uts_mm_camcorder_cancel.h +* @brief This file declares the camcorder cancel test cases. +* @author Kishor Reddy (p.kishor@samsung.com) +* @version Initial Creation V0.1 +* @date 2008.11.27 +*/ + +#ifndef UTS_CAMCORDER_CANCEL_H +#define UTS_CAMCORDER_CANCEL_H + +void utc_camcorder_cancel_001(); +void utc_camcorder_cancel_002(); + +#endif /* UTS_CAMCORDER_CANCEL_H */ diff --git a/TC/utc/uts_mm_camcorder_capture_start.c b/TC/utc/uts_mm_camcorder_capture_start.c new file mode 100644 index 0000000..3c5d5cb --- /dev/null +++ b/TC/utc/uts_mm_camcorder_capture_start.c @@ -0,0 +1,130 @@ +/* + * libmm-camcorder TC + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Jeongmo Yang + * + * 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. + * + */ + +/** +* @ingroup Camcorder_API +* @addtogroup CAMCORDER Camcorder +*/ + +/** +* @ingroup CAMCORDER Camcorder +* @addtogroup UTS_CAMCORDER Unit +*/ + +/** +* @ingroup UTS_CAMCORDER Unit +* @addtogroup UTS_MM_CAMCORDER_CAPTURE_START Uts_Mm_Camcorder_Capture_Start +* @{ +*/ + +/** +* @file uts_mm_camcorder_capture_start.c +* @brief This is a suite of unit test cases to test mm_camcorder_capture_start API. +* @author Kishor Reddy (p.kishor@samsung.com) +* @version Initial Creation V0.1 +* @date 2008.11.27 +*/ + +#include "uts_mm_camcorder_capture_start.h" +#include "uts_mm_camcorder_utils.h" + +struct tet_testlist tet_testlist[] = { + {utc_camcorder_capture_start_001,1}, + {utc_camcorder_capture_start_002,2}, + {NULL,0} +}; + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * @brief This tests mm_camcorder_capture_start API in normal conditions + * @par ID: + * UTC_CAMCORDER_CAPTURE_START_001 + * @param [in] camcorder = Valid Camcorder Handle + * @param [out] None + * @pre Camcorder should be in PREPARED state. + * @post Camcorder should come to CAPTURING state. + * @return MM_ERROR_NONE + */ +void utc_camcorder_capture_start_001() +{ + tet_printf("\n ======================utc_camcorder_capture_start_001====================== \n"); + + gint errorValue = -1; + gint errorValue_check = -1; + gboolean bReturnValue = false; + MMHandleType camcorder = 0; + int mode = IMAGE_MODE; + MMCamPreset info; + info.videodev_type = MM_VIDEO_DEVICE_CAMERA0; + + bReturnValue = StartCamcorder(&camcorder, &info, mode); + if (true != bReturnValue) { + tet_printf("\n Failed in utc_camcorder_capture_start_001 while starting the camcorder \n"); + tet_result(TET_UNTESTED); + return; + } + + errorValue_check = mm_camcorder_capture_start(camcorder); + + sleep(5); + + errorValue = mm_camcorder_capture_stop(camcorder); + if (MM_ERROR_NONE != errorValue) { + tet_printf("\n Failed in utc_camcorder_capture_start_001 while stoping the capturing with error %x \n", errorValue); + return; + } + + bReturnValue = StopCamcorder(camcorder); + + dts_check_eq( "mm_camcorder_capture_start", errorValue_check, MM_ERROR_NONE, + "Failed in utc_camcorder_capture_start_001 while starting the capturing with error %x", errorValue ); + + if (true != bReturnValue) { + tet_printf("\n Failed in utc_camcorder_capture_start_001 while stoping the camcorder \n"); + return; + } + + return; +} +//////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * @brief This tests mm_camcorder_capture_start API with invalid camcorder. + * @par ID: + * UTC_CAMCORDER_CAPTURE_START_002 + * @param [in] Invalid handle + * @param [out] None + * @return Error code + */ +void utc_camcorder_capture_start_002() +{ + tet_printf("\n ======================utc_camcorder_capture_start_002====================== \n"); + + gint errorValue = -1; + + errorValue = mm_camcorder_capture_start(0); + + dts_check_ne( "mm_camcorder_capture_start", errorValue, MM_ERROR_NONE, + "Failed in utc_camcorder_capture_start_002 while starting the capturing with error %x", errorValue ); + + return; +} +/////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** @} */ diff --git a/TC/utc/uts_mm_camcorder_capture_start.h b/TC/utc/uts_mm_camcorder_capture_start.h new file mode 100644 index 0000000..389506d --- /dev/null +++ b/TC/utc/uts_mm_camcorder_capture_start.h @@ -0,0 +1,36 @@ +/* + * libmm-camcorder TC + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Jeongmo Yang + * + * 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. + * + */ + +/** +* @file uts_mm_camcorder_capture_start.h +* @brief This file declares the camcorder capture start test cases. +* @author Kishor Reddy (p.kishor@samsung.com) +* @version Initial Creation V0.1 +* @date 2008.11.27 +*/ + +#ifndef UTS_CAMCORDER_CAPTURE_START_H +#define UTS_CAMCORDER_CAPTURE_START_H + +void utc_camcorder_capture_start_001(); +void utc_camcorder_capture_start_002(); + +#endif /* UTS_CAMCORDER_CAPTURE_START_H */ diff --git a/TC/utc/uts_mm_camcorder_capture_stop.c b/TC/utc/uts_mm_camcorder_capture_stop.c new file mode 100644 index 0000000..d4776eb --- /dev/null +++ b/TC/utc/uts_mm_camcorder_capture_stop.c @@ -0,0 +1,132 @@ +/* + * libmm-camcorder TC + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Jeongmo Yang + * + * 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. + * + */ + +/** +* @ingroup Camcorder_API +* @addtogroup CAMCORDER Camcorder +*/ + +/** +* @ingroup CAMCORDER Camcorder +* @addtogroup UTS_CAMCORDER Unit +*/ + +/** +* @ingroup UTS_CAMCORDER Unit +* @addtogroup UTS_MM_CAMCORDER_CAPTURE_STOP Uts_Mm_Camcorder_Capture_Stop +* @{ +*/ + +/** +* @file uts_mm_camcorder_capture_stop.c +* @brief This is a suite of unit test cases to test mm_camcorder_capture_stop API. +* @author Kishor Reddy (p.kishor@samsung.com) +* @version Initial Creation V0.1 +* @date 2008.11.27 +*/ + +#include "uts_mm_camcorder_capture_stop.h" +#include "uts_mm_camcorder_utils.h" + + +struct tet_testlist tet_testlist[] = { + {utc_camcorder_capture_stop_001,1}, + {utc_camcorder_capture_stop_002,2}, + {NULL,0} +}; + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * @brief This tests mm_camcorder_capture_stop API in normal conditions + * @par ID: + * UTC_CAMCORDER_CAPTURE_STOP_001 + * @param [in] camcorder = Valid Camcorder Handle + * @param [out] None + * @pre Camcorder should be in CAPTURING state. + * @post Camcorder should come to PREPARED state. + * @return MM_ERROR_NONE + */ +void utc_camcorder_capture_stop_001() +{ + tet_printf("\n ======================utc_camcorder_capture_stop_001====================== \n"); + + gint errorValue = -1; + gboolean bReturnValue = false; + MMHandleType camcorder = 0; + int mode = IMAGE_MODE; + MMCamPreset info; + + info.videodev_type = MM_VIDEO_DEVICE_CAMERA0; + + bReturnValue = StartCamcorder(&camcorder, &info, mode); + if (true != bReturnValue) { + tet_printf("\n Failed in utc_camcorder_capture_stop_001 while starting the camcorder \n"); + tet_result(TET_UNTESTED); + return; + } + + errorValue = mm_camcorder_capture_start(camcorder); + if (MM_ERROR_NONE != errorValue) { + tet_printf("\n Failed in utc_camcorder_capture_stop_001 while starting the capturing with error %x \n", errorValue); + tet_result(TET_UNTESTED); + return; + } + + sleep(5); + + errorValue = mm_camcorder_capture_stop(camcorder); + + bReturnValue = StopCamcorder(camcorder); + + dts_check_eq( "mm_camcorder_capture_stop", errorValue, MM_ERROR_NONE, + "Failed in utc_camcorder_capture_stop_001 while stoping the capturing with error %x", errorValue ); + + if (true != bReturnValue) { + tet_printf("\n Failed in utc_camcorder_capture_stop_001 while stoping the camcorder \n"); + return ; + } + + return; +} +//////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * @brief This tests mm_camcorder_capture_stop API with invalid camcorder. + * @par ID: + * UTC_CAMCORDER_CAPTURE_STOP_002 + * @param [in] Invalid handle + * @param [out] None + * @return Error code + */ +void utc_camcorder_capture_stop_002() +{ + tet_printf("\n ======================utc_camcorder_capture_stop_002====================== \n"); + + gint errorValue = -1; + + errorValue = mm_camcorder_capture_stop(0); + + dts_check_ne( "mm_camcorder_capture_stop", errorValue, MM_ERROR_NONE, + "Failed in utc_camcorder_capture_stop_002 while stoping the capturing with error %x", errorValue ); + + return; +} +/////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** @} */ diff --git a/TC/utc/uts_mm_camcorder_capture_stop.h b/TC/utc/uts_mm_camcorder_capture_stop.h new file mode 100644 index 0000000..cdb72cb --- /dev/null +++ b/TC/utc/uts_mm_camcorder_capture_stop.h @@ -0,0 +1,36 @@ +/* + * libmm-camcorder TC + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Jeongmo Yang + * + * 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. + * + */ + +/** +* @file uts_mm_camcorder_capture_stop.h +* @brief This file declares the camcorder capture stop test cases. +* @author Kishor Reddy (p.kishor@samsung.com) +* @version Initial Creation V0.1 +* @date 2008.11.27 +*/ + +#ifndef UTS_CAMCORDER_CAPTURE_STOP_H +#define UTS_CAMCORDER_CAPTURE_STOP_H + +void utc_camcorder_capture_stop_001(); +void utc_camcorder_capture_stop_002(); + +#endif /* UTS_CAMCORDER_CAPTURE_STOP_H */ diff --git a/TC/utc/uts_mm_camcorder_commit.c b/TC/utc/uts_mm_camcorder_commit.c new file mode 100644 index 0000000..5ee6e41 --- /dev/null +++ b/TC/utc/uts_mm_camcorder_commit.c @@ -0,0 +1,131 @@ +/* + * libmm-camcorder TC + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Jeongmo Yang + * + * 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. + * + */ + +/** +* @ingroup Camcorder_API +* @addtogroup CAMCORDER Camcorder +*/ + +/** +* @ingroup CAMCORDER Camcorder +* @addtogroup UTS_CAMCORDER Unit +*/ + +/** +* @ingroup UTS_CAMCORDER Unit +* @addtogroup UTS_MM_CAMCORDER_COMMIT Uts_Mm_Camcorder_Commit +* @{ +*/ + +/** +* @file uts_mm_camcorder_commit.c +* @brief This is a suite of unit test cases to test mm_camcorder_commit API. +* @author Kishor Reddy (p.kishor@samsung.com) +* @version Initial Creation V0.1 +* @date 2008.11.27 +*/ + +#include "uts_mm_camcorder_commit.h" +#include "uts_mm_camcorder_utils.h" + +struct tet_testlist tet_testlist[] = { + {utc_camcorder_commit_001,1}, + {utc_camcorder_commit_002,2}, + {NULL,0} +}; + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * @brief This tests mm_camcorder_commit API in normal conditions + * @par ID: + * UTC_CAMCORDER_COMMIT_001 + * @param [in] camcorder = Valid Camcorder Handle + * @param [out] None + * @pre Camcorder should be in RECORDING state. + * @post Camcorder should come to PREPARED state. + * @return MM_ERROR_NONE + */ +void utc_camcorder_commit_001() +{ + tet_printf("\n ======================utc_camcorder_commit_001====================== \n"); + + gint errorValue = -1; + gboolean bReturnValue = false; + MMHandleType camcorder = 0; + int mode = VIDEO_MODE; + MMCamPreset info; + + info.videodev_type = MM_VIDEO_DEVICE_CAMERA0; + + bReturnValue = StartCamcorder(&camcorder, &info, mode); + if (true != bReturnValue) { + tet_printf("\n Failed in utc_camcorder_commit_001 while starting the camcorder \n"); + tet_result(TET_UNTESTED); + return; + } + + errorValue = mm_camcorder_record(camcorder); + if (MM_ERROR_NONE != errorValue) { + tet_printf("\n Failed in utc_camcorder_commit_001 while recording with error %x \n", errorValue); + tet_result(TET_UNTESTED); + return; + } + + sleep(5); + + errorValue = mm_camcorder_commit(camcorder); + + bReturnValue = StopCamcorder(camcorder); + + dts_check_eq( "mm_camcorder_commit", errorValue, MM_ERROR_NONE, + "Failed in utc_camcorder_commit_001 while commiting with error %x", errorValue ); + + if (true != bReturnValue) { + tet_printf("\n Failed in utc_camcorder_commit_001 while stoping the camcorder \n"); + return; + } + + return; +} +//////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * @brief This tests mm_camcorder_commit API with invalid camcorder. + * @par ID: + * UTC_CAMCORDER_COMMIT_002 + * @param [in] Invalid handle + * @param [out] None + * @return MM_ERROR_NONE + */ +void utc_camcorder_commit_002() +{ + tet_printf("\n ======================utc_camcorder_commit_002====================== \n"); + + gint errorValue = -1; + + errorValue = mm_camcorder_commit(0); + + dts_check_ne( "mm_camcorder_commit", errorValue, MM_ERROR_NONE, + "Failed in utc_camcorder_commit_002 while commiting the camcorder with error %x", errorValue ); + + return; +} +/////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** @} */ diff --git a/TC/utc/uts_mm_camcorder_commit.h b/TC/utc/uts_mm_camcorder_commit.h new file mode 100644 index 0000000..73fb314 --- /dev/null +++ b/TC/utc/uts_mm_camcorder_commit.h @@ -0,0 +1,36 @@ +/* + * libmm-camcorder TC + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Jeongmo Yang + * + * 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. + * + */ + +/** +* @file uts_mm_camcorder_commit.h +* @brief This file declares the camcorder capture stop test cases. +* @author Kishor Reddy (p.kishor@samsung.com) +* @version Initial Creation V0.1 +* @date 2008.11.27 +*/ + +#ifndef UTS_CAMCORDER_COMMIT_H +#define UTS_CAMCORDER_COMMIT_H + +void utc_camcorder_commit_001(); +void utc_camcorder_commit_002(); + +#endif /* UTS_CAMCORDER_COMMIT_H */ diff --git a/TC/utc/uts_mm_camcorder_create.c b/TC/utc/uts_mm_camcorder_create.c new file mode 100644 index 0000000..3c4e0a0 --- /dev/null +++ b/TC/utc/uts_mm_camcorder_create.c @@ -0,0 +1,201 @@ +/* + * libmm-camcorder TC + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Jeongmo Yang + * + * 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. + * + */ + +/** +* @ingroup Camcorder_API +* @addtogroup CAMCORDER Camcorder +*/ + +/** +* @ingroup CAMCORDER Camcorder +* @addtogroup UTS_CAMCORDER Unit +*/ + +/** +* @ingroup UTS_CAMCORDER Unit +* @addtogroup UTS_MM_CAMCORDER_CREATE Uts_Mm_Camcorder_Create +* @{ +*/ + +/** +* @file uts_mm_camcorder_create.c +* @brief This is a suite of unit test cases to test mm_camcorder_create API. +* @author Kishor Reddy (p.kishor@samsung.com) +* @version Initial Creation V0.1 +* @date 2008.11.27 +*/ + +#include "uts_mm_camcorder_create.h" +#include "uts_mm_camcorder_utils.h" + +struct tet_testlist tet_testlist[] = { + {utc_camcorder_create_001,1}, + {utc_camcorder_create_002,2}, + {utc_camcorder_create_003,3}, + {utc_camcorder_create_004,4}, + {NULL,0} +}; + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * @brief This tests mm_camcorder_create API in normal conditions with primary camera. + * @par ID: + * UTC_CAMCORDER_CREATE_001 + * @param [in] info + * @code + MMCamPreset info; + info.videodev_type = MM_VIDEO_DEVICE_CAMERA0; + * @endcode + * @param [out] camcorder + * @pre None. + * @post Camcorder should come to NULL state. + * @return MM_ERROR_NONE + */ +void utc_camcorder_create_001() +{ + tet_printf("\n ======================utc_camcorder_create_001====================== \n"); + + gint errorValue = -1; + gint errorValue_check = -1; + MMHandleType camcorder = 0; + MMCamPreset info; + + info.videodev_type = MM_VIDEO_DEVICE_CAMERA0; + + errorValue_check = mm_camcorder_create(&camcorder, &info); + errorValue = mm_camcorder_destroy(camcorder); + + dts_check_eq( "mm_camcorder_create", errorValue_check, MM_ERROR_NONE, + "Failed in utc_camcorder_create_001 while creating the camcorder with error %x", errorValue ); + + if (MM_ERROR_NONE != errorValue) { + tet_printf("\n Failed in utc_camcorder_create_001 while destroying the camcorder with error %x but mm_camcorder_create API was passed \n", errorValue); + return; + } + + return; +} +//////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * @brief This tests mm_camcorder_create API with invalid output parameter. + * @par ID: + * UTC_CAMCORDER_CREATE_002 + * @param [in] info + * @code + MMCamPreset info; + info.videodev_type = MM_VIDEO_DEVICE_CAMERA0; + * @endcode + * @param [out] pCamcorder + * @code +MMHandleType *pCamcorder = NULL; + * @endcode + * @return Error code + */ +void utc_camcorder_create_002() +{ + tet_printf("\n ======================utc_camcorder_create_002====================== \n"); + + gint errorValue = -1; + MMHandleType *pCamcorder = NULL; + MMCamPreset info; + + info.videodev_type = MM_VIDEO_DEVICE_CAMERA0; + + errorValue = mm_camcorder_create(pCamcorder, &info); + + dts_check_ne( "mm_camcorder_create", errorValue, MM_ERROR_NONE, + "Failed in utc_camcorder_create_002 while creating the camcorder with error %x", errorValue ); + + return; +} +/////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * @brief This tests mm_camcorder_create API in normal conditions with secondary camera. + * @par ID: + * UTC_CAMCORDER_CREATE_003 + * @param [in] info + * @code + MMCamPreset info; + info.videodev_type = MM_VIDEO_DEVICE_CAMERA1; + * @endcode + * @param [out] camcorder + * @pre None. + * @post Camcorder should come to NULL state. + * @return MM_ERROR_NONE + */ + void utc_camcorder_create_003() +{ + tet_printf("\n ======================utc_camcorder_create_003====================== \n"); + + gint errorValue = -1; + gint errorValue_check = -1; + MMHandleType camcorder = 0; + MMCamPreset info; + + info.videodev_type = MM_VIDEO_DEVICE_CAMERA1; + + errorValue_check = mm_camcorder_create(&camcorder, &info); + errorValue = mm_camcorder_destroy(camcorder); + + dts_check_eq( "mm_camcorder_create", errorValue_check, MM_ERROR_NONE, + "Failed in utc_camcorder_create_003 while creating the camcorder with error %x", errorValue ); + + if (MM_ERROR_NONE != errorValue) { + tet_printf("\n Failed in utc_camcorder_create_003 while destroying the camcorder with error %x but mm_camcorder_create API was passed \n", errorValue); + return; + } + + return; +} +/////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /** + * @brief This tests mm_camcorder_create API with invalid preset information. + * @par ID: + * UTC_CAMCORDER_CREATE_004 + * @param [in] info + * @code + MMCamPreset info; + info.videodev_type = MM_VIDEO_DEVICE_NUM; + * @endcode + * @param [out] camcorder + * @pre None. + * @post Camcorder should come to NULL state. + * @return MM_ERROR_NONE + */ +void utc_camcorder_create_004() +{ + tet_printf("\n ======================utc_camcorder_create_004====================== \n"); + + gint errorValue = -1; + MMHandleType camcorder = 0; + MMCamPreset info; + + info.videodev_type = MM_VIDEO_DEVICE_NUM; + + errorValue = mm_camcorder_create(&camcorder, &info); + + dts_check_ne( "mm_camcorder_create", errorValue, MM_ERROR_NONE, + "Failed in utc_camcorder_create_004 while creating the camcorder with error %x", errorValue ); + + return; +} +/////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** @} */ diff --git a/TC/utc/uts_mm_camcorder_create.h b/TC/utc/uts_mm_camcorder_create.h new file mode 100644 index 0000000..3589ec5 --- /dev/null +++ b/TC/utc/uts_mm_camcorder_create.h @@ -0,0 +1,38 @@ +/* + * libmm-camcorder TC + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Jeongmo Yang + * + * 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. + * + */ + +/** +* @file uts_mm_camcorder_create.h +* @brief This file declares the camcorder create test cases. +* @author Kishor Reddy (p.kishor@samsung.com) +* @version Initial Creation V0.1 +* @date 2008.11.27 +*/ + +#ifndef UTS_CAMCORDER_CREATE_H +#define UTS_CAMCORDER_CREATE_H + +void utc_camcorder_create_001(); +void utc_camcorder_create_002(); +void utc_camcorder_create_003(); +void utc_camcorder_create_004(); + +#endif /* UTS_CAMCORDER_CREATE_H */ diff --git a/TC/utc/uts_mm_camcorder_destroy.c b/TC/utc/uts_mm_camcorder_destroy.c new file mode 100644 index 0000000..a169802 --- /dev/null +++ b/TC/utc/uts_mm_camcorder_destroy.c @@ -0,0 +1,115 @@ +/* + * libmm-camcorder TC + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Jeongmo Yang + * + * 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. + * + */ + +/** +* @ingroup Camcorder_API +* @addtogroup CAMCORDER Camcorder +*/ + +/** +* @ingroup CAMCORDER Camcorder +* @addtogroup UTS_CAMCORDER Unit +*/ + +/** +* @ingroup UTS_CAMCORDER Unit +* @addtogroup UTS_MM_CAMCORDER_DESTROY Uts_Mm_Camcorder_Destroy +* @{ +*/ + + +/** +* @file uts_mm_camcorder_destroy.c +* @brief This is a suite of unit test cases to test mm_camcorder_destroy API. +* @author Kishor Reddy (p.kishor@samsung.com) +* @version Initial Creation V0.1 +* @date 2008.11.27 +*/ + +#include "uts_mm_camcorder_destroy.h" +#include "uts_mm_camcorder_utils.h" + +struct tet_testlist tet_testlist[] = { + {utc_camcorder_destroy_001,1}, + {utc_camcorder_destroy_002,2}, + {NULL,0} +}; + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * @brief This tests mm_camcorder_destroy API in normal conditions + * @par ID: + * UTC_CAMCORDER_DESTROY_001 + * @param [in] camcorder = Valid Camcorder Handle + * @param [out] None + * @pre Camcorder should be in NULL state. + * @post None + * @return MM_ERROR_NONE + */ +void utc_camcorder_destroy_001() +{ + tet_printf("\n ======================utc_camcorder_destroy_001====================== \n"); + + gint errorValue = -1; + gboolean bReturnValue = false; + MMHandleType camcorder = 0; + MMCamPreset info; + + info.videodev_type = MM_VIDEO_DEVICE_CAMERA0; + + bReturnValue = CreateCamcorder(&camcorder, &info); + if (true != bReturnValue) { + tet_printf("\n Failed in utc_camcorder_destroy_001 while creating the camcorder with error \n"); + tet_result(TET_UNTESTED); + return; + } + + errorValue = mm_camcorder_destroy(camcorder); + + dts_check_eq( "mm_camcorder_destroy", errorValue, MM_ERROR_NONE, + "Failed in utc_camcorder_destroy_001 while destroying the camcorder with error %x but mm_camcorder_create API was passed", errorValue ); + + return; +} +//////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * @brief This tests mm_camcorder_destroy API with invalid camcorder. + * @par ID: + * UTC_CAMCORDER_DESTROY_002 + * @param [in] Invalid handle + * @param [out] None + * @return Error code + */ +void utc_camcorder_destroy_002() +{ + tet_printf("\n ======================utc_camcorder_destroy_002====================== \n"); + + gint errorValue = -1; + + errorValue = mm_camcorder_destroy(0); + + dts_check_ne( "mm_camcorder_destroy", errorValue, MM_ERROR_NONE, + "Failed in utc_camcorder_destroy_002 while destroying the camcorder with error %x", errorValue ); + + return; +} +/////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** @} */ diff --git a/TC/utc/uts_mm_camcorder_destroy.h b/TC/utc/uts_mm_camcorder_destroy.h new file mode 100644 index 0000000..d46e173 --- /dev/null +++ b/TC/utc/uts_mm_camcorder_destroy.h @@ -0,0 +1,36 @@ +/* + * libmm-camcorder TC + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Jeongmo Yang + * + * 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. + * + */ + +/** +* @file uts_mm_camcorder_destroy.h +* @brief This file declares the camcorder destroy test cases. +* @author Kishor Reddy (p.kishor@samsung.com) +* @version Initial Creation V0.1 +* @date 2008.11.27 +*/ + +#ifndef UTS_CAMCORDER_DESTROY_H +#define UTS_CAMCORDER_DESTROY_H + +void utc_camcorder_destroy_001(); +void utc_camcorder_destroy_002(); + +#endif /* UTS_CAMCORDER_DESTROY_H */ diff --git a/TC/utc/uts_mm_camcorder_get_attr_info.c b/TC/utc/uts_mm_camcorder_get_attr_info.c new file mode 100644 index 0000000..0b0992a --- /dev/null +++ b/TC/utc/uts_mm_camcorder_get_attr_info.c @@ -0,0 +1,176 @@ +/* + * libmm-camcorder TC + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Jeongmo Yang + * + * 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. + * + */ + +/** +* @ingroup Camcorder_API +* @addtogroup CAMCORDER Camcorder +*/ + +/** +* @ingroup CAMCORDER Camcorder +* @addtogroup UTS_CAMCORDER Unit +*/ + +/** +* @ingroup UTS_CAMCORDER Unit +* @addtogroup UTS_MM_CAMCORDER_GET_ATTR_INFO Uts_Mm_Camcorder_Get_Attr_Info +* @{ +*/ + +/** +* @file uts_mm_camcorder_get_attr_info.c +* @brief This is a suite of unit test cases to test mmcam_get_attr_info API. +* @author Priyanka Aggarwal (priyanka.a@samsung.com) +* @version Initial Creation V0.1 +* @date 2010.06.10 +*/ + +#include "uts_mm_camcorder_get_attr_info.h" +#include "uts_mm_camcorder_utils.h" + +struct tet_testlist tet_testlist[] = { + {utc_camcorder_get_attr_info_001,1}, + {utc_camcorder_get_attr_info_002,2}, + {utc_camcorder_get_attr_info_003,3}, + {utc_camcorder_get_attr_info_004,4}, + {NULL,0} +}; + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void utc_camcorder_get_attr_info_001() +{ + tet_printf("\n ======================utc_camcorder_get_attr_info_001====================== \n"); + + gint errorValue = -1; + MMHandleType camcorder = 0; + gboolean bErrorValue = false; + MMCamAttrsInfo attr_info; + MMCamPreset info; + + info.videodev_type = MM_VIDEO_DEVICE_CAMERA0; + + bErrorValue = CreateCamcorder(&camcorder, &info); + if (false == bErrorValue) { + tet_printf("\n Failed in utc_camcorder_get_attr_info_001 while creating the camcorder \n"); + tet_result(TET_UNTESTED); + return; + } + + errorValue = mm_camcorder_get_attribute_info(camcorder, MMCAM_DISPLAY_DEVICE, &attr_info); + + bErrorValue = DestroyCamcorder(camcorder); + + dts_check_eq( "mm_camcorder_get_attribute_info", errorValue, MM_ERROR_NONE, + "Failed in utc_camcorder_get_attr_info_001 while getting attributes of the camcorder [%x]", errorValue ); + + if (false == bErrorValue) { + tet_printf("\n Failed in utc_camcorder_get_attr_info_001 while destroying the camcorder \n"); + } + + return; +} +//////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void utc_camcorder_get_attr_info_002() +{ + tet_printf("\n ======================utc_camcorder_get_attr_info_002====================== \n"); + + gint errorValue = -1; + MMHandleType camcorder = 0; + //gboolean bErrorValue = false; + MMCamAttrsInfo info; + + errorValue = mm_camcorder_get_attribute_info(camcorder, MMCAM_DISPLAY_DEVICE, &info); + + dts_check_ne( "mm_camcorder_get_attribute_info", errorValue, MM_ERROR_NONE, + "Failed in utc_camcorder_get_attr_info_002 while getting attributes of the camcorder" ); + + return; +} +//////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void utc_camcorder_get_attr_info_003() +{ + tet_printf("\n ======================utc_camcorder_get_attr_info_003====================== \n"); + + gint errorValue = -1; + MMHandleType camcorder = 0; + gboolean bErrorValue = false; + MMCamAttrsInfo attr_info; + MMCamPreset info; + + info.videodev_type = MM_VIDEO_DEVICE_CAMERA0; + + bErrorValue = CreateCamcorder(&camcorder, &info); + if (false == bErrorValue) { + tet_printf("\n Failed in utc_camcorder_get_attr_info_003 while creating the camcorder \n"); + tet_result(TET_UNTESTED); + return; + } + + errorValue = mm_camcorder_get_attribute_info(camcorder, NULL, &attr_info); + + bErrorValue = DestroyCamcorder(camcorder); + + dts_check_ne( "mm_camcorder_get_attribute_info", errorValue, MM_ERROR_NONE, + "Failed in utc_camcorder_get_attr_info_003 while getting attributes of the camcorder" ); + + if (false == bErrorValue) { + tet_printf("\n Failed in utc_camcorder_get_attr_info_003 while destroying the camcorder \n"); + } + + return; +} +//////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void utc_camcorder_get_attr_info_004() +{ + tet_printf("\n ======================utc_camcorder_get_attr_info_004====================== \n"); + + gint errorValue = -1; + MMHandleType camcorder = 0; + gboolean bErrorValue = false; + MMCamPreset info; + + info.videodev_type = MM_VIDEO_DEVICE_CAMERA0; + + bErrorValue = CreateCamcorder(&camcorder, &info); + if (false == bErrorValue) { + tet_printf("\n Failed in utc_camcorder_get_attr_info_004 while creating the camcorder \n"); + tet_result(TET_UNTESTED); + return; + } + + errorValue = mm_camcorder_get_attribute_info(camcorder, MMCAM_DISPLAY_DEVICE, NULL); + + bErrorValue = DestroyCamcorder(camcorder); + + dts_check_ne( "mm_camcorder_get_attribute_info", errorValue, MM_ERROR_NONE, + "Failed in utc_camcorder_get_attr_info_004 while getting attributes of the camcorder" ); + + if (false == bErrorValue) { + tet_printf("\n Failed in utc_camcorder_get_attr_info_004 while destroying the camcorder \n"); + } + + return; +} +//////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + +/** @} */ diff --git a/TC/utc/uts_mm_camcorder_get_attr_info.h b/TC/utc/uts_mm_camcorder_get_attr_info.h new file mode 100644 index 0000000..ee818cc --- /dev/null +++ b/TC/utc/uts_mm_camcorder_get_attr_info.h @@ -0,0 +1,38 @@ +/* + * libmm-camcorder TC + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Jeongmo Yang + * + * 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. + * + */ + +/** +* @file uts_mm_camcorder_get_attr_info.h +* @brief This file declares the camcorder get attr info test cases. +* @author Priyanka Aggarwal(priyanka.a@samsung.com) +* @version Initial Creation V0.1 +* @date 2010.06.10 +*/ + +#ifndef UTS_CAMCORDER_GET_ATTR_INFO_H +#define UTS_CAMCORDER_GET_ATTR_INFO_H + +void utc_camcorder_get_attr_info_001(); +void utc_camcorder_get_attr_info_002(); +void utc_camcorder_get_attr_info_003(); +void utc_camcorder_get_attr_info_004(); + +#endif /* UTS_CAMCORDER_GET_ATTR_INFO_H */ diff --git a/TC/utc/uts_mm_camcorder_get_attrs.c b/TC/utc/uts_mm_camcorder_get_attrs.c new file mode 100644 index 0000000..7172361 --- /dev/null +++ b/TC/utc/uts_mm_camcorder_get_attrs.c @@ -0,0 +1,376 @@ +/* + * libmm-camcorder TC + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Jeongmo Yang + * + * 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. + * + */ + +/** +* @ingroup Camcorder_API +* @addtogroup CAMCORDER Camcorder +*/ + +/** +* @ingroup CAMCORDER Camcorder +* @addtogroup UTS_CAMCORDER Unit +*/ + +/** +* @ingroup UTS_CAMCORDER Unit +* @addtogroup UTS_MM_CAMCORDER_GET_ATTRS Uts_Mm_Camcorder_Get_Attrs +* @{ +*/ + +/** +* @file uts_mm_camcorder_get_attrs.c +* @brief This is a suite of unit test cases to test mmcam_get_attrs API. +* @author Kishor Reddy (p.kishor@samsung.com) +* @version Initial Creation V0.1 +* @date 2008.11.27 +*/ + +#include "uts_mm_camcorder_get_attrs.h" +#include "uts_mm_camcorder_utils.h" + +#define MM_CAMCORDER_BRIGHTNESS_LEVEL1 1 +#define MM_CAMCORDER_BRIGHTNESS_LEVEL9 9 + +struct tet_testlist tet_testlist[] = { + {utc_camcorder_get_attrs_001,1}, + {utc_camcorder_get_attrs_002,2}, + {utc_camcorder_get_attrs_003,3}, + {utc_camcorder_get_attrs_004,4}, + {utc_camcorder_get_attrs_005,5}, + {utc_camcorder_get_attrs_006,6}, + {utc_camcorder_get_attrs_007,7}, + {utc_camcorder_get_attrs_008,8}, + {utc_camcorder_get_attrs_009,9}, + {NULL,0} +}; + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void utc_camcorder_get_attrs_001() +{ + tet_printf("\n ======================utc_camcorder_get_attrs_001====================== \n"); + + gint errorValue = -1; + MMHandleType camcorder = 0; + gboolean bErrorValue = false; + int AttrsValue = -1; + char* err_attr_name = (char*)malloc(50); + MMCamPreset info; + + info.videodev_type = MM_VIDEO_DEVICE_CAMERA0; + + bErrorValue = CreateCamcorder(&camcorder, &info); + if (false == bErrorValue) { + tet_printf("\n Failed in utc_camcorder_get_attrs_001 while creating the camcorder \n"); + tet_result(TET_UNTESTED); + return; + } + + errorValue = mm_camcorder_get_attributes(camcorder, &err_attr_name, MMCAM_MODE, &AttrsValue, NULL); + + bErrorValue = DestroyCamcorder(camcorder); + + dts_check_eq( "mm_camcorder_get_attributes", errorValue, MM_ERROR_NONE, + "Failed in utc_camcorder_get_attrs_001 while getting attributes of the camcorder [%x]", errorValue ); + + if (false == bErrorValue) { + tet_printf("\n Failed in utc_camcorder_get_attrs_001 while destroying the camcorder \n"); + } + + return; +} +//////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void utc_camcorder_get_attrs_002() +{ + tet_printf("\n ======================utc_camcorder_get_attrs_002====================== \n"); + + gint errorValue = -1; + MMHandleType camcorder = 0; + gboolean bErrorValue = false; + int AttrsValue = -1; + char* err_attr_name = (char*)malloc(50); + MMCamPreset info; + + info.videodev_type = MM_VIDEO_DEVICE_CAMERA0; + + bErrorValue = CreateCamcorder(&camcorder, &info); + if (false == bErrorValue) { + tet_printf("\n Failed in utc_camcorder_get_attrs_002 while creating the camcorder \n"); + tet_result(TET_UNTESTED); + return; + } + + errorValue = mm_camcorder_get_attributes(camcorder, &err_attr_name, MMCAM_DISPLAY_DEVICE, &AttrsValue, NULL); + + bErrorValue = DestroyCamcorder(camcorder); + + dts_check_eq( "mm_camcorder_get_attributes", errorValue, MM_ERROR_NONE, + "Failed in utc_camcorder_get_attrs_002 while getting attributes of the camcorder [%x]", errorValue ); + + if (false == bErrorValue) { + tet_printf("\n Failed in utc_camcorder_get_attrs_002 while destroying the camcorder \n"); + } + + return; +} +//////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void utc_camcorder_get_attrs_003() +{ + tet_printf("\n ======================utc_camcorder_get_attrs_003====================== \n"); + + gint errorValue = -1; + MMHandleType camcorder = 0; + gboolean bErrorValue = false; + int AttrsValue = -1; + char* err_attr_name = (char*)malloc(50); + MMCamPreset info; + + info.videodev_type = MM_VIDEO_DEVICE_CAMERA0; + + bErrorValue = CreateCamcorder(&camcorder, &info); + if (false == bErrorValue) { + tet_printf("\n Failed in utc_camcorder_get_attrs_003 while creating the camcorder \n"); + tet_result(TET_UNTESTED); + return; + } + + errorValue = mm_camcorder_get_attributes(camcorder, &err_attr_name, MMCAM_CAPTURE_COUNT, &AttrsValue, NULL); + + bErrorValue = DestroyCamcorder(camcorder); + + dts_check_eq( "mm_camcorder_get_attributes", errorValue, MM_ERROR_NONE, + "Failed in utc_camcorder_get_attrs_003 while getting attributes of the camcorder [%x]", errorValue ); + + if (false == bErrorValue) { + tet_printf("\n Failed in utc_camcorder_get_attrs_003 while destroying the camcorder \n"); + } + + return; +} +//////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void utc_camcorder_get_attrs_004() +{ + tet_printf("\n ======================utc_camcorder_get_attrs_004====================== \n"); + + gint errorValue = -1; + MMHandleType camcorder = 0; + gboolean bErrorValue = false; + int AttrsValue = -1; + char* err_attr_name = (char*)malloc(50); + MMCamPreset info; + + info.videodev_type = MM_VIDEO_DEVICE_CAMERA0; + + bErrorValue = CreateCamcorder(&camcorder, &info); + if (false == bErrorValue) { + tet_printf("\n Failed in utc_camcorder_get_attrs_004 while creating the camcorder \n"); + tet_result(TET_UNTESTED); + return; + } + + errorValue = mm_camcorder_get_attributes(camcorder, &err_attr_name, MMCAM_CAMERA_WIDTH, &AttrsValue, NULL); + + bErrorValue = DestroyCamcorder(camcorder); + + dts_check_eq( "mm_camcorder_get_attributes", errorValue, MM_ERROR_NONE, + "Failed in utc_camcorder_get_attrs_004 while getting attributes of the camcorder [%x]", errorValue ); + + if (false == bErrorValue) { + tet_printf("\n Failed in utc_camcorder_get_attrs_004 while destroying the camcorder \n"); + } + + return; +} +//////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void utc_camcorder_get_attrs_005() +{ + tet_printf("\n ======================utc_camcorder_get_attrs_005====================== \n"); + + gint errorValue = -1; + MMHandleType camcorder = 0; + //gboolean bErrorValue = false; + int AttrsValue = -1; + char* err_attr_name = (char*)malloc(50); + MMCamPreset info; + + info.videodev_type = MM_VIDEO_DEVICE_CAMERA0; + /* + bErrorValue = CreateCamcorder(&camcorder, &info); + if (false == bErrorValue) { + tet_printf("\n Failed in utc_camcorder_get_attrs_005 while creating the camcorder \n"); + tet_result(TET_UNTESTED); + return; + } + */ + + errorValue = mm_camcorder_get_attributes(camcorder, &err_attr_name, MMCAM_MODE, &AttrsValue, NULL); + + dts_check_ne( "mm_camcorder_get_attributes", errorValue, MM_ERROR_NONE, + "Failed in utc_camcorder_get_attrs_005 while getting attributes of the camcorder" ); + + /* + bErrorValue = DestroyCamcorder(camcorder); + if (false == bErrorValue) { + tet_printf("\n Failed in utc_camcorder_get_attrs_005 while destroying the camcorder \n"); + } + */ + + return; +} +//////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void utc_camcorder_get_attrs_006() +{ + tet_printf("\n ======================utc_camcorder_get_attrs_006====================== \n"); + + gint errorValue = -1; + MMHandleType camcorder = 0; + gboolean bErrorValue = false; + int AttrsValue = -1; + //char* err_attr_name = (char*)malloc(50); + MMCamPreset info; + + info.videodev_type = MM_VIDEO_DEVICE_CAMERA0; + + bErrorValue = CreateCamcorder(&camcorder, &info); + if (false == bErrorValue) { + tet_printf("\n Failed in utc_camcorder_get_attrs_006 while creating the camcorder \n"); + tet_result(TET_UNTESTED); + return; + } + + errorValue = mm_camcorder_get_attributes(camcorder, NULL, MMCAM_MODE, &AttrsValue, NULL); + + bErrorValue = DestroyCamcorder(camcorder); + + dts_check_eq( "mm_camcorder_get_attributes", errorValue, MM_ERROR_NONE, + "Failed in utc_camcorder_get_attrs_006 while getting attributes of the camcorder [%x]", errorValue ); + + if (false == bErrorValue) { + tet_printf("\n Failed in utc_camcorder_get_attrs_006 while destroying the camcorder \n"); + } + + return; +} +//////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void utc_camcorder_get_attrs_007() +{ + tet_printf("\n ======================utc_camcorder_get_attrs_007====================== \n"); + + gint errorValue = -1; + MMHandleType camcorder = 0; + gboolean bErrorValue = false; + int AttrsValue = -1; + char* err_attr_name = (char*)malloc(50); + MMCamPreset info; + + info.videodev_type = MM_VIDEO_DEVICE_CAMERA0; + + bErrorValue = CreateCamcorder(&camcorder, &info); + if (false == bErrorValue) { + tet_printf("\n Failed in utc_camcorder_get_attrs_007 while creating the camcorder \n"); + tet_result(TET_UNTESTED); + return; + } + + errorValue = mm_camcorder_get_attributes(camcorder, &err_attr_name, NULL, &AttrsValue, NULL); + + bErrorValue = DestroyCamcorder(camcorder); + + dts_check_ne( "mm_camcorder_get_attributes", errorValue, MM_ERROR_NONE, + "Failed in utc_camcorder_get_attrs_007 while getting attributes of the camcorder" ); + + if (false == bErrorValue) { + tet_printf("\n Failed in utc_camcorder_get_attrs_007 while destroying the camcorder \n"); + } + + return; +} +//////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void utc_camcorder_get_attrs_008() +{ + tet_printf("\n ======================utc_camcorder_get_attrs_008====================== \n"); + + gint errorValue = -1; + MMHandleType camcorder = 0; + gboolean bErrorValue = false; + //int AttrsValue = -1; + char* err_attr_name = (char*)malloc(50); + MMCamPreset info; + + info.videodev_type = MM_VIDEO_DEVICE_CAMERA0; + + bErrorValue = CreateCamcorder(&camcorder, &info); + if (false == bErrorValue) { + tet_printf("\n Failed in utc_camcorder_get_attrs_008 while creating the camcorder \n"); + tet_result(TET_UNTESTED); + return; + } + + errorValue = mm_camcorder_get_attributes(camcorder, &err_attr_name, MMCAM_MODE, NULL); + + bErrorValue = DestroyCamcorder(camcorder); + + dts_check_ne( "mm_camcorder_get_attributes", errorValue, MM_ERROR_NONE, + "Failed in utc_camcorder_get_attrs_008 while getting attributes of the camcorder" ); + + if (false == bErrorValue) { + tet_printf("\n Failed in utc_camcorder_get_attrs_008 while destroying the camcorder \n"); + } + + return; +} +//////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void utc_camcorder_get_attrs_009() +{ + tet_printf("\n ======================utc_camcorder_get_attrs_009====================== \n"); + + gint errorValue = -1; + MMHandleType camcorder = 0; + gboolean bErrorValue = false; + int AttrsValue = -1; + char* err_attr_name = (char*)malloc(50); + MMCamPreset info; + + info.videodev_type = MM_VIDEO_DEVICE_CAMERA0; + + bErrorValue = CreateCamcorder(&camcorder, &info); + if (false == bErrorValue) { + tet_printf("\n Failed in utc_camcorder_get_attrs_009 while creating the camcorder \n"); + tet_result(TET_UNTESTED); + return; + } + + errorValue = mm_camcorder_get_attributes(camcorder, &err_attr_name, MMCAM_VIDEO_ENCODER, &AttrsValue, NULL); + + bErrorValue = DestroyCamcorder(camcorder); + + dts_check_eq( "mm_camcorder_get_attributes", errorValue, MM_ERROR_NONE, + "Failed in utc_camcorder_get_attrs_009 while getting attributes of the camcorder [%x]", errorValue ); + + if (false == bErrorValue) { + tet_printf("\n Failed in utc_camcorder_get_attrs_009 while destroying the camcorder \n"); + } + + return; +} +//////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + +/** @} */ diff --git a/TC/utc/uts_mm_camcorder_get_attrs.h b/TC/utc/uts_mm_camcorder_get_attrs.h new file mode 100644 index 0000000..75033d1 --- /dev/null +++ b/TC/utc/uts_mm_camcorder_get_attrs.h @@ -0,0 +1,43 @@ +/* + * libmm-camcorder TC + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Jeongmo Yang + * + * 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. + * + */ + +/** +* @file uts_mm_camcorder_get_attrs.h +* @brief This file declares the camcorder get attrs test cases. +* @author Kishor Reddy (p.kishor@samsung.com) +* @version Initial Creation V0.1 +* @date 2008.11.27 +*/ + +#ifndef UTS_CAMCORDER_GET_ATTRS_H +#define UTS_CAMCORDER_GET_ATTRS_H + +void utc_camcorder_get_attrs_001(); +void utc_camcorder_get_attrs_002(); +void utc_camcorder_get_attrs_003(); +void utc_camcorder_get_attrs_004(); +void utc_camcorder_get_attrs_005(); +void utc_camcorder_get_attrs_006(); +void utc_camcorder_get_attrs_007(); +void utc_camcorder_get_attrs_008(); +void utc_camcorder_get_attrs_009(); + +#endif /* UTS_CAMCORDER_GET_ATTRS_H */ diff --git a/TC/utc/uts_mm_camcorder_get_state.c b/TC/utc/uts_mm_camcorder_get_state.c new file mode 100644 index 0000000..d43a707 --- /dev/null +++ b/TC/utc/uts_mm_camcorder_get_state.c @@ -0,0 +1,298 @@ +/* + * libmm-camcorder TC + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Jeongmo Yang + * + * 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. + * + */ + +/** +* @ingroup Camcorder_API +* @addtogroup CAMCORDER Camcorder +*/ + +/** +* @ingroup CAMCORDER Camcorder +* @addtogroup UTS_CAMCORDER Unit +*/ + +/** +* @ingroup UTS_CAMCORDER Unit +* @addtogroup UTS_MM_CAMCORDER_GET_STATE Uts_Mm_Camcorder_Get_State +* @{ +*/ + +/** +* @file uts_mm_camcorder_get_state.c +* @brief This is a suite of unit test cases to test mm_camcorder_get_state API. +* @author Kishor Reddy (p.kishor@samsung.com) +* @version Initial Creation V0.1 +* @date 2008.11.27 +*/ + +#include "uts_mm_camcorder_get_state.h" +#include "uts_mm_camcorder_utils.h" + +struct tet_testlist tet_testlist[] = { + {utc_camcorder_get_state_001,1}, + {utc_camcorder_get_state_002,2}, + {utc_camcorder_get_state_003,3}, + {NULL,0} +}; + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * @brief This tests mm_camcorder_get_state API in normal conditions. + * @par ID: + * UTC_CAMCORDER_GET_STATE_001 + * @par Description: In order to get each and every state we called mm_camcorder_create,mm_camcorder_realize,mm_camcorder_start,mm_camcorder_capture_start,mm_camcorder_capture_stop APIs. + * @param [in] camcorder = Valid Camcorder Handle + * @code + errorValue = mm_camcorder_create(&camcorder); + errorValue = mm_camcorder_get_state(camcorder); + + errorValue = mm_camcorder_realize(camcorder); + errorValue = mm_camcorder_get_state(camcorder); + + errorValue = mm_camcorder_start(camcorder); + errorValue = mm_camcorder_get_state(camcorder); + + errorValue = mm_camcorder_capture_start(camcorder); + errorValue = mm_camcorder_get_state(camcorder); + + errorValue = mm_camcorder_capture_stop(camcorder); + errorValue = mm_camcorder_get_state(camcorder); + * @param [out] None + * @param [out] None + * @return State of the camcorder + */ +void utc_camcorder_get_state_001() +{ + tet_printf("\n ======================utc_camcorder_get_state_001====================== \n"); + + gint errorValue = -1; + gboolean bReturnValue = false; + MMCamcorderStateType state = MM_CAMCORDER_STATE_NUM; + int mode = IMAGE_MODE; + MMHandleType camcorder = 0; + MMCamPreset info; + + info.videodev_type = MM_VIDEO_DEVICE_CAMERA0; + + errorValue = mm_camcorder_create(&camcorder, &info); + if (MM_ERROR_NONE != errorValue) { + tet_printf("\n Failed in utc_camcorder_get_state_001 while creating the camcorder with error %x but mmcam_init API was passed \n", errorValue); + tet_result(TET_UNTESTED); + return; + } + + bReturnValue = SetDefaultAttributes(camcorder, mode); + if (true != bReturnValue) { + tet_printf("\n Failed in utc_camcorder_get_state_001 while setting default attributes to the camcorder \n"); + tet_result(TET_UNTESTED); + return; + } + + errorValue = mm_camcorder_get_state(camcorder, &state); + if (MM_CAMCORDER_STATE_NULL != state) { + tet_printf("\n Failed in utc_camcorder_get_state_001 while getting the NULL state from the camcorder with error %x \n", errorValue); + tet_result(TET_FAIL); + return; + } + + errorValue = mm_camcorder_realize(camcorder); + if (MM_ERROR_NONE != errorValue) { + tet_printf("\n Failed in utc_camcorder_get_state_001 while realizing the camcorder with error %x but mm_camcorder_create API was passed \n", errorValue); + tet_result(TET_UNTESTED); + return; + } + + errorValue = mm_camcorder_get_state(camcorder, &state); + if (MM_CAMCORDER_STATE_READY != state) { + tet_printf("\n Failed in utc_camcorder_get_state_001 while getting the READY state from the camcorder with error %x \n", errorValue); + tet_result(TET_FAIL); + return; + } + + errorValue = mm_camcorder_start(camcorder); + if (MM_ERROR_NONE != errorValue) { + tet_printf("\n Failed in utc_camcorder_get_state_001 while starting the camcorder with error %x but mm_camcorder_realize API was passed \n", errorValue); + tet_result(TET_UNTESTED); + return; + } + + errorValue = mm_camcorder_get_state(camcorder, &state); + if (MM_CAMCORDER_STATE_PREPARE != state) { + tet_printf("\n Failed in utc_camcorder_get_state_001 while getting the PREPARED state from the camcorder with error %x \n", errorValue); + tet_result(TET_FAIL); + return; + } + + if(IMAGE_MODE == mode) { + errorValue = mm_camcorder_capture_start(camcorder); + if (MM_ERROR_NONE != errorValue) { + tet_printf("\n Failed in utc_camcorder_get_state_001 while starting the capture mode of the camcorder with error %x but mm_camcorder_start API was passed \n", errorValue); + tet_result(TET_UNTESTED); + return; + } + + errorValue = mm_camcorder_get_state(camcorder, &state); + if (MM_CAMCORDER_STATE_CAPTURING != state) { + tet_printf("\n Failed in utc_camcorder_get_state_001 while getting the CAPTURING state from the camcorder with error %x \n", errorValue); + tet_result(TET_FAIL); + return; + } +/* + errorValue = mm_camcorder_pause(camcorder); + if (MM_ERROR_NONE != errorValue) { + tet_printf("\n Failed in utc_camcorder_get_state_001 while pausing the capture mode of the camcorder with error %x but mm_camcorder_start API was passed \n", errorValue); + tet_result(TET_UNTESTED); + return; + } + + errorValue = mm_camcorder_get_state(camcorder); + if (MM_CAMCORDER_STATE_PAUSED != errorValue) { + tet_printf("\n Failed in utc_camcorder_get_state_001 while getting the PAUSE state from the camcorder with error %x \n", errorValue); + tet_result(TET_FAIL); + return; + } +*/ + sleep(5); + + errorValue = mm_camcorder_capture_stop(camcorder); + if (MM_ERROR_NONE != errorValue) { + tet_printf("\n Failed in utc_camcorder_get_state_001 while stoping the capture mode of the camcorder with error %x but mm_camcorder_start API was passed \n", errorValue); + tet_result(TET_UNTESTED); + return; + } + } + else if (VIDEO_MODE == mode) { + errorValue = mm_camcorder_record(camcorder); + if (MM_ERROR_NONE != errorValue) { + tet_printf("\n Failed in utc_camcorder_get_state_001 while recording in the camcorder with error %x but mm_camcorder_start API was passed \n", errorValue); + tet_result(TET_UNTESTED); + return; + } + + errorValue = mm_camcorder_get_state(camcorder, &state); + if (MM_CAMCORDER_STATE_RECORDING != state) { + tet_printf("\n Failed in utc_camcorder_get_state_001 while getting the RECORDING state from the camcorder with error %x \n", errorValue); + tet_result(TET_FAIL); + return; + } + + errorValue = mm_camcorder_pause(camcorder); + if (MM_ERROR_NONE != errorValue) { + tet_printf("\n Failed in utc_camcorder_get_state_001 while pausing the recording mode of the camcorder with error %x but mm_camcorder_capture_start API was passed \n", errorValue); + tet_result(TET_UNTESTED); + return; + } + + errorValue = mm_camcorder_get_state(camcorder, &state); + if (MM_CAMCORDER_STATE_PAUSED != state) { + tet_printf("\n Failed in utc_camcorder_get_state_001 while getting the PAUSE state from the camcorder with error %x \n", errorValue); + tet_result(TET_FAIL); + return; + } + + errorValue = mm_camcorder_cancel(camcorder); + if (MM_ERROR_NONE != errorValue) { + tet_printf("\n Failed in utc_camcorder_get_state_001 while stoping the recording mode of the camcorder with error %x but mm_camcorder_record API was passed \n", errorValue); + return; + } + } + + tet_result(TET_PASS); + + errorValue = mm_camcorder_stop(camcorder); + if (MM_ERROR_NONE != errorValue) { + tet_printf("\n Failed in utc_camcorder_get_state_001 while stoping the camcorder with error %x but mm_camcorder_start API was passed \n", errorValue); + return; + } + + errorValue = mm_camcorder_unrealize(camcorder); + if (MM_ERROR_NONE != errorValue) { + tet_printf("\n Failed in utc_camcorder_get_state_001 while unrealizing the camcorder with error %x but mm_camcorder_realize API was passed \n", errorValue); + return; + } + + errorValue = mm_camcorder_destroy(camcorder); + if (MM_ERROR_NONE != errorValue) { + tet_printf("\n Failed in utc_camcorder_get_state_001 while destroying the camcorder with error %x but mm_camcorder_unrealize API was passed \n", errorValue); + return; + } + + return; +} +//////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * @brief This tests mm_camcorder_get_state API with invalid camcorder. + * @par ID: + * UTC_CAMCORDER_GET_STATE_002 + * @param [in] Invalid handle + * @param [out] None + * @return Error code + */ +void utc_camcorder_get_state_002() +{ + tet_printf("\n ======================utc_camcorder_stop_002====================== \n"); + + gint errorValue = -1; + MMCamcorderStateType state = MM_CAMCORDER_STATE_NUM; + + errorValue = mm_camcorder_get_state(0, &state); + + dts_check_ne( "mm_camcorder_get_state", errorValue, MM_ERROR_NONE, + "Failed in utc_camcorder_get_state_002 while getting the camcorder with error %x", errorValue ); + + return; +} +/////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * @brief This tests mm_camcorder_get_state API with invalid camcorder. + * @par ID: + * UTC_CAMCORDER_GET_STATE_003 + * @param [in] Invalid handle + * @param [out] None + * @return Error code + */ +void utc_camcorder_get_state_003() +{ + tet_printf("\n ======================utc_camcorder_stop_002====================== \n"); + + gint errorValue = -1; + MMCamcorderStateType *state = NULL; + MMHandleType camcorder = 0; + MMCamPreset info; + + info.videodev_type = MM_VIDEO_DEVICE_NUM; + + errorValue = mm_camcorder_create(&camcorder, &info); + if (MM_ERROR_NONE == errorValue) { + tet_printf("\n Failed in utc_camcorder_get_state_003 while creating the camcorder with error %x but mmcam_init API was passed \n", errorValue); + tet_result(TET_UNTESTED); + return; + } + + errorValue = mm_camcorder_get_state(camcorder, state); + + dts_check_ne( "mm_camcorder_get_state", errorValue, MM_ERROR_NONE, + "Failed in utc_camcorder_get_state_003 while getting the camcorder with error %x", errorValue ); + + return; +} +/////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** @} */ diff --git a/TC/utc/uts_mm_camcorder_get_state.h b/TC/utc/uts_mm_camcorder_get_state.h new file mode 100644 index 0000000..5dc0010 --- /dev/null +++ b/TC/utc/uts_mm_camcorder_get_state.h @@ -0,0 +1,37 @@ +/* + * libmm-camcorder TC + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Jeongmo Yang + * + * 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. + * + */ + +/** +* @file uts_mm_camcorder_get_state.h +* @brief This file declares the camcorder get state test cases. +* @author Kishor Reddy (p.kishor@samsung.com) +* @version Initial Creation V0.1 +* @date 2008.11.27 +*/ + +#ifndef UTS_CAMCORDER_GET_STATE_H +#define UTS_CAMCORDER_GET_STATE_H + +void utc_camcorder_get_state_001(); +void utc_camcorder_get_state_002(); +void utc_camcorder_get_state_003(); + +#endif /* UTS_CAMCORDER_GET_STATE_H */ diff --git a/TC/utc/uts_mm_camcorder_pause.c b/TC/utc/uts_mm_camcorder_pause.c new file mode 100644 index 0000000..618d506 --- /dev/null +++ b/TC/utc/uts_mm_camcorder_pause.c @@ -0,0 +1,138 @@ +/* + * libmm-camcorder TC + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Jeongmo Yang + * + * 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. + * + */ + +/** +* @ingroup Camcorder_API +* @addtogroup CAMCORDER Camcorder +*/ + +/** +* @ingroup CAMCORDER Camcorder +* @addtogroup UTS_CAMCORDER Unit +*/ + +/** +* @ingroup UTS_CAMCORDER Unit +* @addtogroup UTS_MM_CAMCORDER_PAUSE Uts_Mm_Camcorder_Pause +* @{ +*/ + +/** +* @file uts_mm_camcorder_pause.c +* @brief This is a suite of unit test cases to test mm_camcorder_pause API. +* @author Kishor Reddy (p.kishor@samsung.com) +* @version Initial Creation V0.1 +* @date 2008.11.27 +*/ + +#include "uts_mm_camcorder_pause.h" +#include "uts_mm_camcorder_utils.h" + +struct tet_testlist tet_testlist[] = { + {utc_camcorder_pause_001,1}, + {utc_camcorder_pause_002,2}, + {NULL,0} +}; + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * @brief This tests mm_camcorder_pause API in normal conditions. + * @par ID: + * UTC_CAMCORDER_PAUSE_001 + * @param [in] camcorder = Valid Camcorder Handle + * @param [out] None + * @pre Camcorder should be in RECORDING state. + * @post Camcorder should come to PAUSE state. + * @return MM_ERROR_NONE + */ +void utc_camcorder_pause_001() +{ + tet_printf("\n ======================utc_camcorder_pause_001====================== \n"); + + gint errorValue = -1; + gint errorValue_check = -1; + gboolean bReturnValue = false; + MMHandleType camcorder = 0; + int mode = VIDEO_MODE; + MMCamPreset info; + + info.videodev_type = MM_VIDEO_DEVICE_CAMERA0; + + bReturnValue = StartCamcorder(&camcorder, &info, mode); + if (true != bReturnValue) { + tet_printf("\n Failed in utc_camcorder_pause_001 while starting the camcorder \n"); + tet_result(TET_UNTESTED); + return; + } + + errorValue = mm_camcorder_record(camcorder); + if (MM_ERROR_NONE != errorValue) { + tet_printf("\n Failed in utc_camcorder_pause_001 while recording with error %x \n", errorValue); + tet_result(TET_UNTESTED); + return; + } + + sleep(5); + + errorValue_check = mm_camcorder_pause(camcorder); + + errorValue = mm_camcorder_cancel(camcorder); + if (MM_ERROR_NONE != errorValue) { + tet_printf("\n Failed in utc_camcorder_pause_001 while canceling the recording in the camcorder with error %x \n", errorValue); + return; + } + + bReturnValue = StopCamcorder(camcorder); + + dts_check_eq( "mm_camcorder_pause", errorValue_check, MM_ERROR_NONE, + "Failed in utc_camcorder_pause_001 while pausing the camcorder with error %x", errorValue ); + + if (true != bReturnValue) { + tet_printf("\n Failed in utc_camcorder_pause_001 while stoping the camcorder \n"); + return; + } + + return; +} +//////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * @brief This tests mm_camcorder_pause API with invalid camcorder. + * @par ID: + * UTC_CAMCORDER_PAUSE_002 + * @param [in] Invalid handle + * @param [out] None + * @return Error code + */ +void utc_camcorder_pause_002() +{ + tet_printf("\n ======================utc_camcorder_pause_002====================== \n"); + + gint errorValue = -1; + + errorValue = mm_camcorder_pause(0); + + dts_check_ne( "mm_camcorder_pause", errorValue, MM_ERROR_NONE, + "Failed in utc_camcorder_pause_002 while pausing the camcorder with error %x", errorValue ); + + return; +} +/////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** @} */ diff --git a/TC/utc/uts_mm_camcorder_pause.h b/TC/utc/uts_mm_camcorder_pause.h new file mode 100644 index 0000000..6340c5e --- /dev/null +++ b/TC/utc/uts_mm_camcorder_pause.h @@ -0,0 +1,36 @@ +/* + * libmm-camcorder TC + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Jeongmo Yang + * + * 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. + * + */ + +/** +* @file uts_mm_camcorder_pause.h +* @brief This file declares the camcorder pause test cases. +* @author Kishor Reddy (p.kishor@samsung.com) +* @version Initial Creation V0.1 +* @date 2008.11.27 +*/ + +#ifndef UTS_CAMCORDER_PAUSE_H +#define UTS_CAMCORDER_PAUSE_H + +void utc_camcorder_pause_001(); +void utc_camcorder_pause_002(); + +#endif /* UTS_CAMCORDER_PAUSE_H */ diff --git a/TC/utc/uts_mm_camcorder_realize.c b/TC/utc/uts_mm_camcorder_realize.c new file mode 100644 index 0000000..ebb044a --- /dev/null +++ b/TC/utc/uts_mm_camcorder_realize.c @@ -0,0 +1,146 @@ +/* + * libmm-camcorder TC + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Jeongmo Yang + * + * 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. + * + */ + +/** +* @ingroup Camcorder_API +* @addtogroup CAMCORDER Camcorder +*/ + +/** +* @ingroup CAMCORDER Camcorder +* @addtogroup UTS_CAMCORDER Unit +*/ + +/** +* @ingroup UTS_CAMCORDER Unit +* @addtogroup UTS_MM_CAMCORDER_REALIZE Uts_Mm_Camcorder_Realize +* @{ +*/ + +/** +* @file uts_mm_camcorder_realize.c +* @brief This is a suite of unit test cases to test mm_camcorder_realize API. +* @author Kishor Reddy (p.kishor@samsung.com) +* @version Initial Creation V0.1 +* @date 2008.11.27 +*/ + +#include "uts_mm_camcorder_realize.h" +#include "uts_mm_camcorder_utils.h" + +struct tet_testlist tet_testlist[] = { + {utc_camcorder_realize_001,1}, + {utc_camcorder_realize_002,2}, + {NULL,0} +}; + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * @brief This tests mm_camcorder_realize API in normal conditions. + * @par ID: + * UTC_CAMCORDER_REALIZE_001 + * @param [in] camcorder = Valid Camcorder Handle + * @param [out] None + * @pre Camcorder should be in NULL state. + * @post Camcorder should come to READY state. + * @return MM_ERROR_NONE + */ +void utc_camcorder_realize_001() +{ + tet_printf("\n ======================utc_camcorder_realize_001====================== \n"); + + gint errorValue = -1; + gint errorValue_check = -1; + gboolean bReturnValue = false; + MMHandleType camcorder = 0; + MMCamPreset info; + + info.videodev_type = MM_VIDEO_DEVICE_CAMERA0; + + bReturnValue = CreateCamcorder(&camcorder, &info); + if (true != bReturnValue) { + tet_printf("\n Failed in utc_camcorder_realize_001 while creating the camcorder \n"); + tet_result(TET_UNTESTED); + return; + } + + bReturnValue = SetDefaultAttributes(camcorder,IMAGE_MODE); + if (true != bReturnValue) { + tet_printf("\n Failed in utc_camcorder_realize_001 while setting default attributes to the camcorder \n"); + tet_result(TET_UNTESTED); + return; + } + + errorValue_check = mm_camcorder_realize(camcorder); + + errorValue = mm_camcorder_start(camcorder); + if (MM_ERROR_NONE != errorValue) { + tet_printf("\n Failed in utc_camcorder_realize_001 while starting the camcorder with error %x but mm_camcorder_realize API was passed \n", errorValue); + return; + } + + sleep(2); + + errorValue = mm_camcorder_stop(camcorder); + if (MM_ERROR_NONE != errorValue) { + tet_printf("\n Failed in utc_camcorder_realize_001 while stopping the camcorder with error %x but mm_camcorder_realize API was passed \n", errorValue); + return; + } + + errorValue = mm_camcorder_unrealize(camcorder); + if (MM_ERROR_NONE != errorValue) { + tet_printf("\n Failed in utc_camcorder_realize_001 while unrealizing the camcorder with error %x but mm_camcorder_realize API was passed \n", errorValue); + return; + } + + bReturnValue = DestroyCamcorder(camcorder); + + dts_check_eq("mm_camcorder_realize", errorValue_check, MM_ERROR_NONE, "Failed in utc_camcorder_realize_001 while realizing the camcorder with error %x but mm_camcorder_create API was passed \n", errorValue); + + if (true != bReturnValue) { + tet_printf("\n Failed in utc_camcorder_realize_001 while destroying the camcorder \n"); + return; + } + + return; +} +/////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * @brief This tests mm_camcorder_realize API with invalid camcorder. + * @par ID: + * UTC_CAMCORDER_REALIZE_002 + * @param [in] Invalid handle + * @param [out] None + * @return Error code + */ +void utc_camcorder_realize_002() +{ + tet_printf("\n ======================utc_camcorder_realize_002====================== \n"); + + gint errorValue = -1; + + errorValue = mm_camcorder_realize(0); + dts_check_ne("mm_camcorder_realize", errorValue, MM_ERROR_NONE, "Failed in utc_camcorder_realize_002 while realizing the camcorder with error %x \n", errorValue); + + return; +} +/////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** @} */ diff --git a/TC/utc/uts_mm_camcorder_realize.h b/TC/utc/uts_mm_camcorder_realize.h new file mode 100644 index 0000000..e1c223f --- /dev/null +++ b/TC/utc/uts_mm_camcorder_realize.h @@ -0,0 +1,36 @@ +/* + * libmm-camcorder TC + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Jeongmo Yang + * + * 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. + * + */ + +/** +* @file uts_mm_camcorder_realize.h +* @brief This file declares the camcorder realize test cases. +* @author Kishor Reddy (p.kishor@samsung.com) +* @version Initial Creation V0.1 +* @date 2008.11.27 +*/ + +#ifndef UTS_CAMCORDER_REALIZE_H +#define UTS_CAMCORDER_REALIZE_H + +void utc_camcorder_realize_001(); +void utc_camcorder_realize_002(); + +#endif /* UTS_CAMCORDER_REALIZE_H */ diff --git a/TC/utc/uts_mm_camcorder_record.c b/TC/utc/uts_mm_camcorder_record.c new file mode 100644 index 0000000..301ac17 --- /dev/null +++ b/TC/utc/uts_mm_camcorder_record.c @@ -0,0 +1,129 @@ +/* + * libmm-camcorder TC + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Jeongmo Yang + * + * 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. + * + */ + +/** +* @ingroup Camcorder_API +* @addtogroup CAMCORDER Camcorder +*/ + +/** +* @ingroup CAMCORDER Camcorder +* @addtogroup UTS_CAMCORDER Unit +*/ + +/** +* @ingroup UTS_CAMCORDER Unit +* @addtogroup UTS_MM_CAMCORDER_RECORD Uts_Mm_Camcorder_Record +* @{ +*/ + +/** +* @file uts_mm_camcorder_record.c +* @brief This is a suite of unit test cases to test MMCamcorderRecord API. +* @author Kishor Reddy (p.kishor@samsung.com) +* @version Initial Creation V0.1 +* @date 2008.11.27 +*/ + +#include "uts_mm_camcorder_record.h" +#include "uts_mm_camcorder_utils.h" + +struct tet_testlist tet_testlist[] = { + {utc_camcorder_record_001,1}, + {utc_camcorder_record_002,2}, + {NULL,0} +}; + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * @brief This tests MMCamcorderRecord API in normal conditions. + * @par ID: + * UTC_CAMCORDER_RECORD_001 + * @param [in] camcorder = Valid Camcorder Handle + * @param [out] None + * @pre Camcorder should be in PREPARE state. + * @post Camcorder should come to RECORDING state. + * @return MM_ERROR_NONE + */ +void utc_camcorder_record_001() +{ + tet_printf("\n ======================utc_camcorder_record_001====================== \n"); + + gint errorValue = -1; + gint errorValue_check = -1; + gboolean bReturnValue = false; + MMHandleType camcorder = 0; + int mode = VIDEO_MODE; + MMCamPreset info; + + info.videodev_type = MM_VIDEO_DEVICE_CAMERA0; + + bReturnValue = StartCamcorder(&camcorder, &info, mode); + if (true != bReturnValue) { + tet_printf("\n Failed in utc_camcorder_record_001 while starting the camcorder \n"); + tet_result(TET_UNTESTED); + return; + } + + errorValue_check = mm_camcorder_record(camcorder); + + sleep(2); + + errorValue = mm_camcorder_cancel(camcorder); + if (MM_ERROR_NONE != errorValue) { + tet_printf("\n Failed in utc_camcorder_record_001 while recording with error %x \n", errorValue); + tet_result(TET_FAIL); + return; + } + + bReturnValue = StopCamcorder(camcorder); + + dts_check_eq("mm_camcorder_record", errorValue_check, MM_ERROR_NONE, "Failed in utc_camcorder_record_001 while recording with error %x \n", errorValue); + + if (true != bReturnValue) { + tet_printf("\n Failed in utc_camcorder_record_001 while stoping the camcorder \n"); + return; + } + + return; +} +//////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * @brief This tests MMCamcorderRecord API with invalid camcorder. + * @par ID: + * UTC_CAMCORDER_RECORD_002 + * @param [in] Invalid handle + * @param [out] None + * @return Error code + */ +void utc_camcorder_record_002() +{ + tet_printf("\n ======================utc_camcorder_record_002====================== \n"); + + gint errorValue = -1; + + errorValue = mm_camcorder_record(0); + dts_check_ne("mm_camcorder_record", errorValue, MM_ERROR_NONE, "Failed in utc_camcorder_record_002 while recording the camcorder with error %x \n", errorValue); + + return; +} +/////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** @} */ diff --git a/TC/utc/uts_mm_camcorder_record.h b/TC/utc/uts_mm_camcorder_record.h new file mode 100644 index 0000000..c442d81 --- /dev/null +++ b/TC/utc/uts_mm_camcorder_record.h @@ -0,0 +1,36 @@ +/* + * libmm-camcorder TC + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Jeongmo Yang + * + * 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. + * + */ + +/** +* @file uts_mm_camcorder_record.h +* @brief This file declares the camcorder record test cases. +* @author Kishor Reddy (p.kishor@samsung.com) +* @version Initial Creation V0.1 +* @date 2008.11.27 +*/ + +#ifndef UTS_CAMCORDER_RECORD_H +#define UTS_CAMCORDER_RECORD_H + +void utc_camcorder_record_001(); +void utc_camcorder_record_002(); + +#endif /* UTS_CAMCORDER_RECORD_H */ diff --git a/TC/utc/uts_mm_camcorder_set_attrs.c b/TC/utc/uts_mm_camcorder_set_attrs.c new file mode 100644 index 0000000..c8cd014 --- /dev/null +++ b/TC/utc/uts_mm_camcorder_set_attrs.c @@ -0,0 +1,374 @@ +/* + * libmm-camcorder TC + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Jeongmo Yang + * + * 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. + * + */ + +/** +* @ingroup CAMCORDER +* @addtogroup UTS_CAMCORDER Unit +*/ + +/** +* @ingroup UTS_CAMCORDER +* @addtogroup UTS_mm_camcorder_set_attributes Uts_Mm_CamcorderSetAttrs +* @{ +*/ + +/** +* @file uts_mm_camcorder_set_attrs.c +* @brief This is a suite of unit test cases to test mm_camcorder_set_attributes API. +* @author Kishor Reddy (p.kishor@samsung.com) +* @version Initial Creation V0.1 +* @date 2008.11.27 +*/ + +#include "uts_mm_camcorder_set_attrs.h" +#include "uts_mm_camcorder_utils.h" +#define MM_CAMCORDER_BRIGHTNESS_LEVEL1 1 +#define MM_CAMCORDER_BRIGHTNESS_LEVEL9 9 + +struct tet_testlist tet_testlist[] = { + {utc_camcorder_set_attrs_001,1}, + {utc_camcorder_set_attrs_002,2}, + {utc_camcorder_set_attrs_003,3}, + {utc_camcorder_set_attrs_004,4}, + {utc_camcorder_set_attrs_005,5}, + {utc_camcorder_set_attrs_006,6}, + {utc_camcorder_set_attrs_007,7}, + {utc_camcorder_set_attrs_008,8}, + {utc_camcorder_set_attrs_009,9}, + {NULL,0} +}; + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void utc_camcorder_set_attrs_001() +{ + tet_printf("\n ======================utc_camcorder_set_attrs_001====================== \n"); + + gint errorValue = -1; + MMHandleType camcorder = 0; + gboolean bErrorValue = false; + int AttrsValue = MM_CAMCORDER_MODE_VIDEO; + char* err_attr_name = (char*)malloc(50); + MMCamPreset info; + + info.videodev_type = MM_VIDEO_DEVICE_CAMERA0; + + bErrorValue = CreateCamcorder(&camcorder, &info); + if (false == bErrorValue) { + tet_printf("\n Failed in utc_camcorder_set_attrs_001 while creating the camcorder \n"); + tet_result(TET_UNTESTED); + return; + } + + errorValue = mm_camcorder_set_attributes(camcorder, &err_attr_name, MMCAM_MODE, AttrsValue, NULL); + + bErrorValue = DestroyCamcorder(camcorder); + + dts_check_eq("mm_camcorder_set_attributes", errorValue, MM_ERROR_NONE, "Failed in utc_camcorder_set_attrs_001 while setting attributes of the camcorder \n"); + tet_printf("\n Passed in utc_camcorder_set_attrs_001 while setting attributes of the camcorder \n"); + + if (false == bErrorValue) { + tet_printf("\n Failed in utc_camcorder_set_attrs_001 while destroying the camcorder \n"); + } + + return; +} +//////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void utc_camcorder_set_attrs_002() +{ + tet_printf("\n ======================utc_camcorder_set_attrs_002====================== \n"); + + gint errorValue = -1; + MMHandleType camcorder = 0; + gboolean bErrorValue = false; + int AttrsValue = DISPLAY_ID; + char* err_attr_name = (char*)malloc(50); + MMCamPreset info; + + info.videodev_type = MM_VIDEO_DEVICE_CAMERA0; + + bErrorValue = CreateCamcorder(&camcorder, &info); + if (false == bErrorValue) { + tet_printf("\n Failed in utc_camcorder_set_attrs_002 while creating the camcorder \n"); + tet_result(TET_UNTESTED); + return; + } + + errorValue = mm_camcorder_set_attributes(camcorder, &err_attr_name, MMCAM_DISPLAY_SURFACE, AttrsValue, NULL); + + bErrorValue = DestroyCamcorder(camcorder); + + dts_check_eq("mm_camcorder_set_attributes", errorValue, MM_ERROR_NONE, "Failed in utc_camcorder_set_attrs_002 while setting attributes of the camcorder \n"); + tet_printf("\n Passed in utc_camcorder_set_attrs_002 while setting attributes of the camcorder \n"); + + if (false == bErrorValue) { + tet_printf("\n Failed in utc_camcorder_set_attrs_002 while destroying the camcorder \n"); + } + + return; +} +//////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void utc_camcorder_set_attrs_003() +{ + tet_printf("\n ======================utc_camcorder_set_attrs_003====================== \n"); + + gint errorValue = -1; + MMHandleType camcorder = 0; + gboolean bErrorValue = false; + int AttrsValue = IMAGE_CAPTURE_COUNT_STILL; + char* err_attr_name = (char*)malloc(50); + MMCamPreset info; + + info.videodev_type = MM_VIDEO_DEVICE_CAMERA0; + + bErrorValue = CreateCamcorder(&camcorder, &info); + if (false == bErrorValue) { + tet_printf("\n Failed in utc_camcorder_set_attrs_003 while creating the camcorder \n"); + tet_result(TET_UNTESTED); + return; + } + + errorValue = mm_camcorder_set_attributes(camcorder, &err_attr_name, MMCAM_CAPTURE_COUNT, AttrsValue, NULL); + + bErrorValue = DestroyCamcorder(camcorder); + + dts_check_eq("mm_camcorder_set_attributes", errorValue, MM_ERROR_NONE, "Failed in utc_camcorder_set_attrs_003 while setting attributes of the camcorder \n"); + tet_printf("\n Passed in utc_camcorder_set_attrs_003 while setting attributes of the camcorder \n"); + + if (false == bErrorValue) { + tet_printf("\n Failed in utc_camcorder_set_attrs_003 while destroying the camcorder \n"); + } + + return; +} +//////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void utc_camcorder_set_attrs_004() +{ + tet_printf("\n ======================utc_camcorder_set_attrs_004====================== \n"); + + gint errorValue = -1; + MMHandleType camcorder = 0; + gboolean bErrorValue = false; + int width = SRC_W_320; + int height = SRC_H_240; + char* err_attr_name = (char*)malloc(50); + MMCamPreset info; + + info.videodev_type = MM_VIDEO_DEVICE_CAMERA0; + + bErrorValue = CreateCamcorder(&camcorder, &info); + if (false == bErrorValue) { + tet_printf("\n Failed in utc_camcorder_set_attrs_004 while creating the camcorder \n"); + tet_result(TET_UNTESTED); + return; + } + + errorValue = mm_camcorder_set_attributes(camcorder, &err_attr_name, + MMCAM_CAMERA_WIDTH, width, + MMCAM_CAMERA_HEIGHT, height, + NULL); + + bErrorValue = DestroyCamcorder(camcorder); + + dts_check_eq("mm_camcorder_set_attributes", errorValue, MM_ERROR_NONE, "Failed in utc_camcorder_set_attrs_004 while setting attributes of the camcorder \n"); + tet_printf("\n Passed in utc_camcorder_set_attrs_004 while setting attributes of the camcorder \n"); + + if (false == bErrorValue) { + tet_printf("\n Failed in utc_camcorder_set_attrs_004 while destroying the camcorder \n"); + } + + return; +} +//////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void utc_camcorder_set_attrs_005() +{ + tet_printf("\n ======================utc_camcorder_set_attrs_005====================== \n"); + + gint errorValue = -1; + MMHandleType camcorder = 0; + //gboolean bErrorValue = false; + int AttrsValue = MM_CAMCORDER_MODE_VIDEO; + char* err_attr_name = (char*)malloc(50); + MMCamPreset info; + + info.videodev_type = MM_VIDEO_DEVICE_CAMERA0; + + /* + bErrorValue = CreateCamcorder(&camcorder, &info); + if (false == bErrorValue) { + tet_printf("\n Failed in utc_camcorder_set_attrs_005 while creating the camcorder \n"); + tet_result(TET_UNTESTED); + return; + } + */ + + errorValue = mm_camcorder_set_attributes(camcorder, &err_attr_name, MMCAM_MODE, AttrsValue, NULL); + dts_check_ne("mm_camcorder_set_attributes", errorValue, MM_ERROR_NONE, "Failed in utc_camcorder_set_attrs_005 while setting attributes of the camcorder \n"); + tet_printf("\n Passed in utc_camcorder_set_attrs_005 while setting attributes of the camcorder \n"); + + /* + bErrorValue = DestroyCamcorder(camcorder); + if (false == bErrorValue) { + tet_printf("\n Failed in utc_camcorder_set_attrs_005 while destroying the camcorder \n"); + } + */ + + return; +} +//////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void utc_camcorder_set_attrs_006() +{ + tet_printf("\n ======================utc_camcorder_set_attrs_006====================== \n"); + + gint errorValue = -1; + MMHandleType camcorder = 0; + gboolean bErrorValue = false; + int AttrsValue = MM_CAMCORDER_MODE_VIDEO; + //char* err_attr_name = (char*)malloc(50); + MMCamPreset info; + + info.videodev_type = MM_VIDEO_DEVICE_CAMERA0; + + bErrorValue = CreateCamcorder(&camcorder, &info); + if (false == bErrorValue) { + tet_printf("\n Failed in utc_camcorder_set_attrs_006 while creating the camcorder \n"); + tet_result(TET_UNTESTED); + return; + } + + errorValue = mm_camcorder_set_attributes(camcorder, NULL, MMCAM_MODE, AttrsValue, NULL); + + bErrorValue = DestroyCamcorder(camcorder); + + dts_check_eq("mm_camcorder_set_attributes", errorValue, MM_ERROR_NONE, "Failed in utc_camcorder_set_attrs_006 while setting attributes of the camcorder \n"); + tet_printf("\n Passed in utc_camcorder_set_attrs_006 while setting attributes of the camcorder \n"); + + if (false == bErrorValue) { + tet_printf("\n Failed in utc_camcorder_set_attrs_006 while destroying the camcorder \n"); + } + + return; +} +//////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void utc_camcorder_set_attrs_007() +{ + tet_printf("\n ======================utc_camcorder_set_attrs_007====================== \n"); + + gint errorValue = -1; + MMHandleType camcorder = 0; + gboolean bErrorValue = false; + int AttrsValue = 1; + char* err_attr_name = (char*)malloc(50); + MMCamPreset info; + + info.videodev_type = MM_VIDEO_DEVICE_CAMERA0; + + bErrorValue = CreateCamcorder(&camcorder, &info); + if (false == bErrorValue) { + tet_printf("\n Failed in utc_camcorder_set_attrs_007 while creating the camcorder \n"); + tet_result(TET_UNTESTED); + return; + } + + errorValue = mm_camcorder_set_attributes(camcorder, &err_attr_name, NULL, AttrsValue, NULL); + + bErrorValue = DestroyCamcorder(camcorder); + + dts_check_ne("mm_camcorder_set_attributes", errorValue, MM_ERROR_NONE, "Failed in utc_camcorder_set_attrs_007 while setting attributes of the camcorder \n"); + tet_printf("\n Passed in utc_camcorder_set_attrs_007 while setting attributes of the camcorder \n"); + + if (false == bErrorValue) { + tet_printf("\n Failed in utc_camcorder_set_attrs_007 while destroying the camcorder \n"); + } + + return; +} +//////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void utc_camcorder_set_attrs_008() +{ + tet_printf("\n ======================utc_camcorder_set_attrs_008====================== \n"); + + gint errorValue = -1; + MMHandleType camcorder = 0; + gboolean bErrorValue = false; + //int AttrsValue = -1; + char* err_attr_name = (char*)malloc(50); + MMCamPreset info; + + info.videodev_type = MM_VIDEO_DEVICE_CAMERA0; + + bErrorValue = CreateCamcorder(&camcorder, &info); + if (false == bErrorValue) { + tet_printf("\n Failed in utc_camcorder_set_attrs_008 while creating the camcorder \n"); + tet_result(TET_UNTESTED); + return; + } + + errorValue = mm_camcorder_set_attributes(camcorder, &err_attr_name, MMCAM_MODE, -1, NULL); + + bErrorValue = DestroyCamcorder(camcorder); + + dts_check_ne("mm_camcorder_set_attributes", errorValue, MM_ERROR_NONE, "Failed in utc_camcorder_set_attrs_008 while setting attributes of the camcorder \n"); + tet_printf("\n Passed in utc_camcorder_set_attrs_008 while setting attributes of the camcorder \n"); + + if (false == bErrorValue) { + tet_printf("\n Failed in utc_camcorder_set_attrs_008 while destroying the camcorder \n"); + } + + return; +} +//////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void utc_camcorder_set_attrs_009() +{ + tet_printf("\n ======================utc_camcorder_set_attrs_009====================== \n"); + + gint errorValue = -1; + MMHandleType camcorder = 0; + gboolean bErrorValue = false; + //int AttrsValue = -1; + char* err_attr_name = (char*)malloc(50); + MMCamPreset info; + + info.videodev_type = MM_VIDEO_DEVICE_CAMERA0; + + bErrorValue = CreateCamcorder(&camcorder, &info); + if (false == bErrorValue) { + tet_printf("\n Failed in utc_camcorder_set_attrs_009 while creating the camcorder \n"); + tet_result(TET_UNTESTED); + return; + } + + errorValue = mm_camcorder_set_attributes(camcorder, &err_attr_name, MMCAM_VIDEO_ENCODER, MM_VIDEO_CODEC_MPEG4, NULL); + + bErrorValue = DestroyCamcorder(camcorder); + + dts_check_eq("mm_camcorder_set_attributes", errorValue, MM_ERROR_NONE, "Failed in utc_camcorder_set_attrs_009 while setting attributes of the camcorder \n"); + tet_printf("\n Passed in utc_camcorder_set_attrs_009 while setting attributes of the camcorder \n"); + + if (false == bErrorValue) { + tet_printf("\n Failed in utc_camcorder_set_attrs_009 while destroying the camcorder \n"); + } + + return; +} +//////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/** @} */ diff --git a/TC/utc/uts_mm_camcorder_set_attrs.h b/TC/utc/uts_mm_camcorder_set_attrs.h new file mode 100644 index 0000000..e6e0223 --- /dev/null +++ b/TC/utc/uts_mm_camcorder_set_attrs.h @@ -0,0 +1,44 @@ +/* + * libmm-camcorder TC + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Jeongmo Yang + * + * 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. + * + */ + +/** +* @file uts_mm_camcorder_set_attrs.h +* @brief This file declares the camcorder set attrs test cases. +* @author Kishor Reddy (p.kishor@samsung.com) +* @version Initial Creation V0.1 +* @date 2008.11.27 +*/ + +#ifndef UTS_CAMCORDER_SET_ATTRS_H +#define UTS_CAMCORDER_SET_ATTRS_H + +void utc_camcorder_set_attrs_001(); +void utc_camcorder_set_attrs_002(); +void utc_camcorder_set_attrs_003(); +void utc_camcorder_set_attrs_004(); +void utc_camcorder_set_attrs_005(); +void utc_camcorder_set_attrs_006(); +void utc_camcorder_set_attrs_007(); +void utc_camcorder_set_attrs_008(); +void utc_camcorder_set_attrs_009(); + + +#endif /* UTS_CAMCORDER_SET_ATTRS_H */ diff --git a/TC/utc/uts_mm_camcorder_set_message_callback.c b/TC/utc/uts_mm_camcorder_set_message_callback.c new file mode 100644 index 0000000..d0985ce --- /dev/null +++ b/TC/utc/uts_mm_camcorder_set_message_callback.c @@ -0,0 +1,434 @@ +/* + * libmm-camcorder TC + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Jeongmo Yang + * + * 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. + * + */ + +/** +* @ingroup Camcorder_API +* @addtogroup CAMCORDER Camcorder +*/ + +/** +* @ingroup CAMCORDER Camcorder +* @addtogroup UTS_CAMCORDER Unit +*/ + +/** +* @ingroup UTS_CAMCORDER Unit +* @addtogroup UTS_MM_CAMCORDER_SET_MESSAGE_CALLBACK Uts_Mm_Camcorder_Set_Message_Callback +* @{ +*/ + + +/** +* @file uts_mm_camcorder_set_message_callback.c +* @brief This is a suite of unit test cases to test mm_camcorder_set_message_callback API. +* @author Kishor Reddy (p.kishor@samsung.com) +* @version Initial Creation V0.1 +* @date 2008.11.27 +*/ + +#include "uts_mm_camcorder_set_message_callback.h" +#include "uts_mm_camcorder_utils.h" + +struct tet_testlist tet_testlist[] = { + {utc_camcorder_set_message_callback_001,1}, + {utc_camcorder_set_message_callback_002,2}, + {utc_camcorder_set_message_callback_003,3}, + {utc_camcorder_set_message_callback_004,4}, + {utc_camcorder_set_message_callback_005,5}, + {utc_camcorder_set_message_callback_006,6}, + {utc_camcorder_set_message_callback_007,7}, + {utc_camcorder_set_message_callback_008,8}, + {NULL,0} +}; +//////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * @brief This tests mm_camcorder_set_message_callback API in normal conditions. + * @par ID: + * UTC_CAMCORDER_SET_MESSAGE_CALLBACK_001 + * @param [in] camcorder = Valid Camcorder Handle + * @param [in] MessageCallbackFunctionCalledByCamcorder (This itself is a function) + * @param [in] gCamcorderCallbackParameters + * @code + gCamcorderCallbackParameters->camcorder = *camcorder; + gCamcorderCallbackParameters->mode = IMAGE_MODE; + gCamcorderCallbackParameters->isMultishot = false; + gCamcorderCallbackParameters->stillshot_count = 0; + gCamcorderCallbackParameters->multishot_count = 0; + gCamcorderCallbackParameters->stillshot_filename = "stillshot_file";; + gCamcorderCallbackParameters->multishot_filename = "multishot_file";; + * @endcode + * @param [out] None + * @return MM_ERROR_NONE + */ +void utc_camcorder_set_message_callback_001() +{ + tet_printf("\n ======================utc_camcorder_set_message_callback_001====================== \n"); + + gint errorValue = -1; + gboolean bReturnValue = false; + MMHandleType camcorder = 0; + MMCamPreset info; + + info.videodev_type = MM_VIDEO_DEVICE_CAMERA0; + + bReturnValue = CreateCamcorder(&camcorder, &info); + if (true != bReturnValue) { + tet_printf("\n Failed in utc_camcorder_set_message_callback_001 while starting the camcorder \n"); + tet_result(TET_UNTESTED); + return; + } + + errorValue = mm_camcorder_set_message_callback(camcorder, MessageCallbackFunctionCalledByCamcorder, gCamcorderCallbackParameters); + + bReturnValue = DestroyCamcorder(camcorder); + + dts_check_eq("mm_camcorder_set_message_callback", errorValue, MM_ERROR_NONE, "Failed in utc_camcorder_set_message_callback_001 while setting message callback function with error %x \n", errorValue); + + if (true != bReturnValue) { + tet_printf("\n Failed in utc_camcorder_set_message_callback_001 while destroying the camcorder \n"); + return; + } + + return; +} +//////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * @brief This tests mm_camcorder_set_message_callback API with NULL user parameter. + * @par ID: + * UTC_CAMCORDER_SET_MESSAGE_CALLBACK_002 + * @param [in] camcorder = Valid Camcorder Handle + * @param [in] MessageCallbackFunctionCalledByCamcorder (This itself is a function) + * @param [in] Invalid handle + * @param [out] None + * @return MM_ERROR_NONE + */ +void utc_camcorder_set_message_callback_002() +{ + tet_printf("\n ======================utc_camcorder_set_message_callback_002====================== \n"); + + gint errorValue = -1; + gboolean bReturnValue = false; + MMHandleType camcorder = 0; + MMCamPreset info; + + info.videodev_type = MM_VIDEO_DEVICE_CAMERA0; + + bReturnValue = CreateCamcorder(&camcorder, &info); + if (true != bReturnValue) { + tet_printf("\n Failed in utc_camcorder_set_message_callback_002 while starting the camcorder \n"); + tet_result(TET_UNTESTED); + return; + } + + errorValue = mm_camcorder_set_message_callback(camcorder, MessageCallbackFunctionCalledByCamcorder, NULL); + + bReturnValue = DestroyCamcorder(camcorder); + + dts_check_eq("mm_camcorder_set_message_callback", errorValue, MM_ERROR_NONE, "Failed in utc_camcorder_set_message_callback_002 while setting message callback function with error %x \n", errorValue); + + if (true != bReturnValue) { + tet_printf("\n Failed in utc_camcorder_set_message_callback_002 while destroying the camcorder \n"); + return; + } + + return; +} +//////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * @brief This tests mm_camcorder_set_message_callback API with NULL callback function. + * @par ID: + * UTC_CAMCORDER_SET_MESSAGE_CALLBACK_003 + * @param [in] camcorder = Valid Camcorder Handle + * @param [in] Invalid handle + * @param [in] gCamcorderCallbackParameters + * @code + gCamcorderCallbackParameters->camcorder = *camcorder; + gCamcorderCallbackParameters->mode = IMAGE_MODE; + gCamcorderCallbackParameters->isMultishot = false; + gCamcorderCallbackParameters->stillshot_count = 0; + gCamcorderCallbackParameters->multishot_count = 0; + gCamcorderCallbackParameters->stillshot_filename = "stillshot_file";; + gCamcorderCallbackParameters->multishot_filename = "multishot_file";; + * @endcode + * @param [out] None + * @return Error code + */ +void utc_camcorder_set_message_callback_003() +{ + tet_printf("\n ======================utc_camcorder_set_message_callback_003====================== \n"); + + gint errorValue = -1; + gboolean bReturnValue = false; + MMHandleType camcorder = 0; + MMCamPreset info; + + info.videodev_type = MM_VIDEO_DEVICE_CAMERA0; + + bReturnValue = CreateCamcorder(&camcorder, &info); + if (true != bReturnValue) { + tet_printf("\n Failed in utc_camcorder_set_message_callback_003 while starting the camcorder \n"); + tet_result(TET_UNTESTED); + return; + } + + errorValue = mm_camcorder_set_message_callback(camcorder, NULL, gCamcorderCallbackParameters); + + bReturnValue = DestroyCamcorder(camcorder); + + dts_check_eq("mm_camcorder_set_message_callback", errorValue, MM_ERROR_NONE, "Failed in utc_camcorder_set_message_callback_003 while setting message callback function with error %x \n", errorValue); + + if (true != bReturnValue) { + tet_printf("\n Failed in utc_camcorder_set_message_callback_003 while destroying the camcorder \n"); + return; + } + + return; +} +//////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * @brief This tests mm_camcorder_set_message_callback API with NULL callback function and NULL user parameter. + * @par ID: + * UTC_CAMCORDER_SET_MESSAGE_CALLBACK_004 + * @param [in] camcorder = Valid Camcorder Handle + * @param [in] Invalid handle + * @param [in] Invalid handle + * @param [out] None + * @return Error code + */ +void utc_camcorder_set_message_callback_004() +{ + tet_printf("\n ======================utc_camcorder_set_message_callback_004====================== \n"); + + gint errorValue = -1; + gboolean bReturnValue = false; + MMHandleType camcorder = 0; + MMCamPreset info; + + info.videodev_type = MM_VIDEO_DEVICE_CAMERA0; + + bReturnValue = CreateCamcorder(&camcorder, &info); + if (true != bReturnValue) { + tet_printf("\n Failed in utc_camcorder_set_message_callback_004 while starting the camcorder \n"); + tet_result(TET_UNTESTED); + return; + } + + errorValue = mm_camcorder_set_message_callback(camcorder, NULL, NULL); + + bReturnValue = DestroyCamcorder(camcorder); + + dts_check_eq("mm_camcorder_set_message_callback", errorValue, MM_ERROR_NONE, "Failed in utc_camcorder_set_message_callback_004 while setting message callback function with error %x \n", errorValue); + + if (true != bReturnValue) { + tet_printf("\n Failed in utc_camcorder_set_message_callback_004 while destroying the camcorder \n"); + return; + } + + return; +} +//////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * @brief This tests mm_camcorder_set_message_callback API with invalid camcorder. + * @par ID: + * UTC_CAMCORDER_SET_MESSAGE_CALLBACK_005 + * @param [in] Invalid handle + * @param [in] MessageCallbackFunctionCalledByCamcorder (This itself is function) + * @param [in] gCamcorderCallbackParameters + * @code + gCamcorderCallbackParameters->camcorder = *camcorder; + gCamcorderCallbackParameters->mode = IMAGE_MODE; + gCamcorderCallbackParameters->isMultishot = false; + gCamcorderCallbackParameters->stillshot_count = 0; + gCamcorderCallbackParameters->multishot_count = 0; + gCamcorderCallbackParameters->stillshot_filename = "stillshot_file";; + gCamcorderCallbackParameters->multishot_filename = "multishot_file";; + * @endcode + * @param [out] None + * @return Error code + */ +void utc_camcorder_set_message_callback_005() +{ + tet_printf("\n ======================utc_camcorder_set_message_callback_005====================== \n"); + + gint errorValue = -1; + gboolean bReturnValue = false; + MMHandleType camcorder = 0; + MMCamPreset info; + + info.videodev_type = MM_VIDEO_DEVICE_CAMERA0; + + bReturnValue = CreateCamcorder(&camcorder, &info); + if (true != bReturnValue) { + tet_printf("\n Failed in utc_camcorder_set_message_callback_005 while starting the camcorder \n"); + tet_result(TET_UNTESTED); + return; + } + + errorValue = mm_camcorder_set_message_callback(0, MessageCallbackFunctionCalledByCamcorder, gCamcorderCallbackParameters); + + bReturnValue = DestroyCamcorder(camcorder); + + dts_check_ne("mm_camcorder_set_message_callback", errorValue, MM_ERROR_NONE, "Failed in utc_camcorder_set_message_callback_005 while setting message callback function with error %x \n", errorValue); + + if (true != bReturnValue) { + tet_printf("\n Failed in utc_camcorder_set_message_callback_005 while destroying the camcorder \n"); + return; + } + + return; +} +//////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * @brief This tests mm_camcorder_set_message_callback API with invalid camcorder as well as with NULL user parameter. + * @par ID: + * UTC_CAMCORDER_SET_MESSAGE_CALLBACK_006 + * @param [in] Invalid handle + * @param [in] MessageCallbackFunctionCalledByCamcorder (This itself is a function) + * @param [in] Invalid handle + * @param [out] None + * @return Error code + */ +void utc_camcorder_set_message_callback_006() +{ + tet_printf("\n ======================utc_camcorder_set_message_callback_006====================== \n"); + + gint errorValue = -1; + gboolean bReturnValue = false; + MMHandleType camcorder = 0; + MMCamPreset info; + + info.videodev_type = MM_VIDEO_DEVICE_CAMERA0; + + bReturnValue = CreateCamcorder(&camcorder, &info); + if (true != bReturnValue) { + tet_printf("\n Failed in utc_camcorder_set_message_callback_006 while starting the camcorder \n"); + tet_result(TET_UNTESTED); + return; + } + + errorValue = mm_camcorder_set_message_callback(0, MessageCallbackFunctionCalledByCamcorder, NULL); + + bReturnValue = DestroyCamcorder(camcorder); + + dts_check_ne("mm_camcorder_set_message_callback", errorValue, MM_ERROR_NONE, "Failed in utc_camcorder_set_message_callback_006 while setting filename callback function with error %x \n", errorValue); + + if (true != bReturnValue) { + tet_printf("\n Failed in utc_camcorder_set_message_callback_006 while destroying the camcorder \n"); + return; + } + + return; +} +//////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * @brief This tests mm_camcorder_set_message_callback API with invalid camcorder as well as with NULL callback function. + * @par ID: + * UTC_CAMCORDER_SET_MESSAGE_CALLBACK_007 + * @param [in] Invalid handle + * @param [in] Invalid handle + * @param [in] gCamcorderCallbackParameters + * @code + gCamcorderCallbackParameters->camcorder = *camcorder; + gCamcorderCallbackParameters->mode = IMAGE_MODE; + gCamcorderCallbackParameters->isMultishot = false; + gCamcorderCallbackParameters->stillshot_count = 0; + gCamcorderCallbackParameters->multishot_count = 0; + gCamcorderCallbackParameters->stillshot_filename = "stillshot_file";; + gCamcorderCallbackParameters->multishot_filename = "multishot_file";; + * @endcode + * @param [out] None + * @return Error code + */ +void utc_camcorder_set_message_callback_007() +{ + tet_printf("\n ======================utc_camcorder_set_message_callback_007====================== \n"); + + gint errorValue = -1; + gboolean bReturnValue = false; + MMHandleType camcorder = 0; + MMCamPreset info; + + info.videodev_type = MM_VIDEO_DEVICE_CAMERA0; + + bReturnValue = CreateCamcorder(&camcorder, &info); + if (true != bReturnValue) { + tet_printf("\n Failed in utc_camcorder_set_message_callback_007 while starting the camcorder \n"); + tet_result(TET_UNTESTED); + return; + } + + errorValue = mm_camcorder_set_message_callback(0, NULL, gCamcorderCallbackParameters); + + bReturnValue = DestroyCamcorder(camcorder); + + dts_check_ne("mm_camcorder_set_message_callback", errorValue, MM_ERROR_NONE, "Failed in utc_camcorder_set_message_callback_007 while setting message callback function with error %x \n", errorValue); + + if (true != bReturnValue) { + tet_printf("\n Failed in utc_camcorder_set_message_callback_007 while destroying the camcorder \n"); + return; + } + + return; +} +//////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * @brief This tests mm_camcorder_set_message_callback API with invalid camcorder as well as with NULL callback function and NULL user parameter. + * @par ID: + * UTC_CAMCORDER_SET_MESSAGE_CALLBACK_008 + * @param [in] Invalid handle + * @param [in] Invalid handle + * @param [in] Invalid handle + * @param [out] None + * @return Error code + */ +void utc_camcorder_set_message_callback_008() +{ + tet_printf("\n ======================utc_camcorder_set_message_callback_008====================== \n"); + + gint errorValue = -1; + gboolean bReturnValue = false; + MMHandleType camcorder = 0; + MMCamPreset info; + + info.videodev_type = MM_VIDEO_DEVICE_CAMERA0; + + bReturnValue = CreateCamcorder(&camcorder, &info); + if (true != bReturnValue) { + tet_printf("\n Failed in utc_camcorder_set_message_callback_008 while starting the camcorder \n"); + tet_result(TET_UNTESTED); + return; + } + + errorValue = mm_camcorder_set_message_callback(0, NULL, NULL); + + bReturnValue = DestroyCamcorder(camcorder); + + dts_check_ne("mm_camcorder_set_message_callback", errorValue, MM_ERROR_NONE, "Failed in utc_camcorder_set_message_callback_008 while setting message callback function with error %x \n", errorValue); + + if (true != bReturnValue) { + tet_printf("\n Failed in utc_camcorder_set_message_callback_008 while destroying the camcorder \n"); + return; + } + + return; +} +//////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** @} */ diff --git a/TC/utc/uts_mm_camcorder_set_message_callback.h b/TC/utc/uts_mm_camcorder_set_message_callback.h new file mode 100644 index 0000000..272fcc0 --- /dev/null +++ b/TC/utc/uts_mm_camcorder_set_message_callback.h @@ -0,0 +1,42 @@ +/* + * libmm-camcorder TC + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Jeongmo Yang + * + * 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. + * + */ + +/** +* @file uts_mm_camcorder_set_message_callback.h +* @brief This file declares the camcorder set message callback test cases. +* @author Kishor Reddy (p.kishor@samsung.com) +* @version Initial Creation V0.1 +* @date 2008.11.27 +*/ + +#ifndef UTS_MM_CAMCORDER_SET_MESSAGE_CALLBACK_H +#define UTS_MM_CAMCORDER_SET_MESSAGE_CALLBACK_H + +void utc_camcorder_set_message_callback_001(); +void utc_camcorder_set_message_callback_002(); +void utc_camcorder_set_message_callback_003(); +void utc_camcorder_set_message_callback_004(); +void utc_camcorder_set_message_callback_005(); +void utc_camcorder_set_message_callback_006(); +void utc_camcorder_set_message_callback_007(); +void utc_camcorder_set_message_callback_008(); + +#endif /* UTS_MM_CAMCORDER_SET_MESSAGE_CALLBACK_H */ diff --git a/TC/utc/uts_mm_camcorder_set_video_capture_callback.c b/TC/utc/uts_mm_camcorder_set_video_capture_callback.c new file mode 100644 index 0000000..6ce205f --- /dev/null +++ b/TC/utc/uts_mm_camcorder_set_video_capture_callback.c @@ -0,0 +1,435 @@ +/* + * libmm-camcorder TC + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Jeongmo Yang + * + * 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. + * + */ + +/** +* @ingroup Camcorder_API +* @addtogroup CAMCORDER Camcorder +*/ + +/** +* @ingroup CAMCORDER Camcorder +* @addtogroup UTS_CAMCORDER Unit +*/ + +/** +* @ingroup UTS_CAMCORDER Unit +* @addtogroup UTS_MM_CAMCORDER_SET_VIDEO_CAPTURE_CALLBACK Uts_Mm_Camcorder_Set_Video_Capture_Callback +* @{ +*/ + + +/** +* @file uts_mm_camcorder_set_video_capture_callback.c +* @brief This is a suite of unit test cases to test mm_camcorder_set_video_capture_callback API. +* @author Kishor Reddy (p.kishor@samsung.com) +* @version Initial Creation V0.1 +* @date 2008.03.04 +*/ + +#include "uts_mm_camcorder_set_video_capture_callback.h" +#include "uts_mm_camcorder_utils.h" + +struct tet_testlist tet_testlist[] = { + {utc_camcorder_set_video_capture_callback_001,1}, + {utc_camcorder_set_video_capture_callback_002,2}, + {utc_camcorder_set_video_capture_callback_003,3}, + {utc_camcorder_set_video_capture_callback_004,4}, + {utc_camcorder_set_video_capture_callback_005,5}, + {utc_camcorder_set_video_capture_callback_006,6}, + {utc_camcorder_set_video_capture_callback_007,7}, + {utc_camcorder_set_video_capture_callback_008,8}, + {NULL,0} +}; +//////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * @brief This tests mm_camcorder_set_video_capture_callback API in normal conditions. + * @par ID: + * UTC_CAMCORDER_SET_VIDEO_CAPTURE_CALLBACK_001 + * @param [in] camcorder = Valid Camcorder Handle + * @param [in] VideoCaptureCallbackFunctionCalledByCamcorder (This itself is a function) + * @param [in] gCamcorderCallbackParameters + * @code + gCamcorderCallbackParameters->camcorder = *camcorder; + gCamcorderCallbackParameters->mode = IMAGE_MODE; + gCamcorderCallbackParameters->isMultishot = false; + gCamcorderCallbackParameters->stillshot_count = 0; + gCamcorderCallbackParameters->multishot_count = 0; + gCamcorderCallbackParameters->stillshot_filename = "stillshot_file";; + gCamcorderCallbackParameters->multishot_filename = "multishot_file";; + * @endcode + * @param [out] None + * @return MM_ERROR_NONE + */ +void utc_camcorder_set_video_capture_callback_001() +{ + tet_printf("\n ======================utc_camcorder_set_video_capture_callback_001====================== \n"); + + gint errorValue = -1; + gboolean bReturnValue = false; + MMHandleType camcorder = 0; + MMCamPreset info; + + info.videodev_type = MM_VIDEO_DEVICE_CAMERA0; + + bReturnValue = CreateCamcorder(&camcorder, &info); + if (true != bReturnValue) { + tet_printf("\n Failed in utc_camcorder_set_video_capture_callback_001 while starting the camcorder \n"); + tet_result(TET_UNTESTED); + return; + } + + errorValue = mm_camcorder_set_video_capture_callback(camcorder, VideoCaptureCallbackFunctionCalledByCamcorder, gCamcorderCallbackParameters); + + bReturnValue = DestroyCamcorder(camcorder); + + dts_check_eq("mm_camcorder_set_video_capture_callback", errorValue, MM_ERROR_NONE, "Failed in utc_camcorder_set_video_capture_callback_001 while setting video stream callback function with error %x \n", errorValue); + + if (true != bReturnValue) { + tet_printf("\n Failed in utc_camcorder_set_video_capture_callback_001 while destroying the camcorder \n"); + return; + } + + return; +} +//////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * @brief This tests mm_camcorder_set_video_capture_callback API with NULL user parameter. + * @par ID: + * UTC_CAMCORDER_SET_VIDEO_CAPTURE_CALLBACK_002 + * @param [in] camcorder = Valid Camcorder Handle + * @param [in] VideoCaptureCallbackFunctionCalledByCamcorder (This itself is a function) + * @param [in] Invalid handle + * @param [out] None + * @return MM_ERROR_NONE + */ +void utc_camcorder_set_video_capture_callback_002() +{ + tet_printf("\n ======================utc_camcorder_set_video_capture_callback_002====================== \n"); + + gint errorValue = -1; + gboolean bReturnValue = false; + MMHandleType camcorder = 0; + MMCamPreset info; + + info.videodev_type = MM_VIDEO_DEVICE_CAMERA0; + + bReturnValue = CreateCamcorder(&camcorder, &info); + if (true != bReturnValue) { + tet_printf("\n Failed in utc_camcorder_set_video_capture_callback_002 while starting the camcorder \n"); + tet_result(TET_UNTESTED); + return; + } + + errorValue = mm_camcorder_set_video_capture_callback(camcorder, VideoCaptureCallbackFunctionCalledByCamcorder, NULL); + + bReturnValue = DestroyCamcorder(camcorder); + + dts_check_eq("mm_camcorder_set_video_capture_callback", errorValue, MM_ERROR_NONE, "Failed in utc_camcorder_set_video_capture_callback_002 while setting video stream callback function with error %x \n", errorValue); + + if (true != bReturnValue) { + tet_printf("\n Failed in utc_camcorder_set_video_capture_callback_002 while destroying the camcorder \n"); + return; + } + + return; +} +//////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * @brief This tests mm_camcorder_set_video_capture_callback API with NULL callback function. + * @par ID: + * UTC_CAMCORDER_SET_VIDEO_CAPTURE_CALLBACK_003 + * @param [in] camcorder = Valid Camcorder Handle + * @param [in] Invalid handle + * @param [in] gCamcorderCallbackParameters + * @code + gCamcorderCallbackParameters->camcorder = *camcorder; + gCamcorderCallbackParameters->mode = IMAGE_MODE; + gCamcorderCallbackParameters->isMultishot = false; + gCamcorderCallbackParameters->stillshot_count = 0; + gCamcorderCallbackParameters->multishot_count = 0; + gCamcorderCallbackParameters->stillshot_filename = "stillshot_file";; + gCamcorderCallbackParameters->multishot_filename = "multishot_file";; + * @endcode + * @param [out] None + * @return Error code + */ +void utc_camcorder_set_video_capture_callback_003() +{ + tet_printf("\n ======================utc_camcorder_set_video_capture_callback_003====================== \n"); + + gint errorValue = -1; + gboolean bReturnValue = false; + MMHandleType camcorder = 0; + MMCamPreset info; + + info.videodev_type = MM_VIDEO_DEVICE_CAMERA0; + + bReturnValue = CreateCamcorder(&camcorder, &info); + if (true != bReturnValue) { + tet_printf("\n Failed in utc_camcorder_set_video_capture_callback_003 while starting the camcorder \n"); + tet_result(TET_UNTESTED); + return; + } + + errorValue = mm_camcorder_set_video_capture_callback(camcorder, NULL, gCamcorderCallbackParameters); + + bReturnValue = DestroyCamcorder(camcorder); + + dts_check_eq("mm_camcorder_set_video_capture_callback", errorValue, MM_ERROR_NONE, "Failed in utc_camcorder_set_video_capture_callback_003 while setting video stream callback function with error %x \n", errorValue); + + if (true != bReturnValue) { + tet_printf("\n Failed in utc_camcorder_set_video_capture_callback_003 while destroying the camcorder \n"); + return; + } + + return; +} +//////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * @brief This tests mm_camcorder_set_video_capture_callback API with NULL callback function as well as NULL user parameter. + * @par ID: + * UTC_CAMCORDER_SET_VIDEO_CAPTURE_CALLBACK_004 + * @param [in] camcorder = Valid Camcorder Handle + * @param [in] Invalid handle + * @param [in] Invalid handle + * @param [out] None + * @return Error code + */ +void utc_camcorder_set_video_capture_callback_004() +{ + tet_printf("\n ======================utc_camcorder_set_video_capture_callback_004====================== \n"); + + gint errorValue = -1; + gboolean bReturnValue = false; + MMHandleType camcorder = 0; + MMCamPreset info; + + info.videodev_type = MM_VIDEO_DEVICE_CAMERA0; + + bReturnValue = CreateCamcorder(&camcorder, &info); + if (true != bReturnValue) { + tet_printf("\n Failed in utc_camcorder_set_video_capture_callback_004 while starting the camcorder \n"); + tet_result(TET_UNTESTED); + return; + } + + errorValue = mm_camcorder_set_video_capture_callback(camcorder, NULL, NULL); + + bReturnValue = DestroyCamcorder(camcorder); + + dts_check_eq("mm_camcorder_set_video_capture_callback", errorValue, MM_ERROR_NONE, "Failed in utc_camcorder_set_video_capture_callback_004 while setting video stream callback function with error %x \n", errorValue); + + if (true != bReturnValue) { + tet_printf("\n Failed in utc_camcorder_set_video_capture_callback_004 while destroying the camcorder \n"); + return; + } + + return; +} +//////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * @brief This tests mm_camcorder_set_video_capture_callback API with invalid camcorder. + * @par ID: + * UTC_CAMCORDER_SET_VIDEO_CAPTURE_CALLBACK_005 + * @param [in] Invalid handle + * @param [in] VideoCaptureCallbackFunctionCalledByCamcorder (This itself is a function) + * @param [in] gCamcorderCallbackParameters + * @code + gCamcorderCallbackParameters->camcorder = *camcorder; + gCamcorderCallbackParameters->mode = IMAGE_MODE; + gCamcorderCallbackParameters->isMultishot = false; + gCamcorderCallbackParameters->stillshot_count = 0; + gCamcorderCallbackParameters->multishot_count = 0; + gCamcorderCallbackParameters->stillshot_filename = "stillshot_file";; + gCamcorderCallbackParameters->multishot_filename = "multishot_file";; + * @endcode + * @param [out] None + * @return Error code + */ +void utc_camcorder_set_video_capture_callback_005() +{ + tet_printf("\n ======================utc_camcorder_set_video_capture_callback_005====================== \n"); + + gint errorValue = -1; + gboolean bReturnValue = false; + MMHandleType camcorder = 0; + MMCamPreset info; + + info.videodev_type = MM_VIDEO_DEVICE_CAMERA0; + + bReturnValue = CreateCamcorder(&camcorder, &info); + if (true != bReturnValue) { + tet_printf("\n Failed in utc_camcorder_set_video_capture_callback_005 while starting the camcorder \n"); + tet_result(TET_UNTESTED); + return; + } + + errorValue = mm_camcorder_set_video_capture_callback(0, VideoCaptureCallbackFunctionCalledByCamcorder, gCamcorderCallbackParameters); + + bReturnValue = DestroyCamcorder(camcorder); + + dts_check_ne("mm_camcorder_set_video_capture_callback", errorValue, MM_ERROR_NONE, "Failed in utc_camcorder_set_video_capture_callback_005 while setting video stream callback function with error %x \n", errorValue); + + if (true != bReturnValue) { + tet_printf("\n Failed in utc_camcorder_set_video_capture_callback_005 while destroying the camcorder \n"); + return; + } + + return; +} +//////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * @brief This tests mm_camcorder_set_video_capture_callback API with invalid camcorder as well as with NULL user parameter. + * @par ID: + * UTC_CAMCORDER_SET_VIDEO_CAPTURE_CALLBACK_006 + * @param [in] Invalid handle + * @param [in] VideoCaptureCallbackFunctionCalledByCamcorder (This itself is a function) + * @param [in] Invalid handle + * @param [out] None + * @return Error code + */ +void utc_camcorder_set_video_capture_callback_006() +{ + tet_printf("\n ======================utc_camcorder_set_video_capture_callback_006====================== \n"); + + gint errorValue = -1; + gboolean bReturnValue = false; + MMHandleType camcorder = 0; + MMCamPreset info; + + info.videodev_type = MM_VIDEO_DEVICE_CAMERA0; + + bReturnValue = CreateCamcorder(&camcorder, &info); + if (true != bReturnValue) { + tet_printf("\n Failed in utc_camcorder_set_video_capture_callback_006 while starting the camcorder \n"); + tet_result(TET_UNTESTED); + return; + } + + errorValue = mm_camcorder_set_video_capture_callback(0, VideoCaptureCallbackFunctionCalledByCamcorder, NULL); + + bReturnValue = DestroyCamcorder(camcorder); + + dts_check_ne("mm_camcorder_set_video_capture_callback", errorValue, MM_ERROR_NONE, "Failed in utc_camcorder_set_video_capture_callback_006 while setting video stream callback function with error %x \n", errorValue); + + if (true != bReturnValue) { + tet_printf("\n Failed in utc_camcorder_set_video_capture_callback_006 while destroying the camcorder \n"); + return; + } + + return; +} +//////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * @brief This tests mm_camcorder_set_video_capture_callback API with invalid camcorder as well as with NULL callback function. + * @par ID: + * UTC_CAMCORDER_SET_VIDEO_CAPTURE_CALLBACK_007 + * @param [in] Invalid handle + * @param [in] Invalid handle + * @param [in] gCamcorderCallbackParameters + * @code + gCamcorderCallbackParameters->camcorder = *camcorder; + gCamcorderCallbackParameters->mode = IMAGE_MODE; + gCamcorderCallbackParameters->isMultishot = false; + gCamcorderCallbackParameters->stillshot_count = 0; + gCamcorderCallbackParameters->multishot_count = 0; + gCamcorderCallbackParameters->stillshot_filename = "stillshot_file";; + gCamcorderCallbackParameters->multishot_filename = "multishot_file";; + * @endcode + * @param [out] None + * @return Error code + */ +void utc_camcorder_set_video_capture_callback_007() +{ + tet_printf("\n ======================utc_camcorder_set_video_capture_callback_007====================== \n"); + + gint errorValue = -1; + gboolean bReturnValue = false; + MMHandleType camcorder = 0; + MMCamPreset info; + + info.videodev_type = MM_VIDEO_DEVICE_CAMERA0; + + bReturnValue = CreateCamcorder(&camcorder, &info); + if (true != bReturnValue) { + tet_printf("\n Failed in utc_camcorder_set_video_capture_callback_007 while starting the camcorder \n"); + tet_result(TET_UNTESTED); + return; + } + + errorValue = mm_camcorder_set_video_capture_callback(0, NULL, gCamcorderCallbackParameters); + + bReturnValue = DestroyCamcorder(camcorder); + + dts_check_ne("mm_camcorder_set_video_capture_callback", errorValue, MM_ERROR_NONE, "Failed in utc_camcorder_set_video_capture_callback_007 while setting video stream callback function with error %x \n", errorValue); + + if (true != bReturnValue) { + tet_printf("\n Failed in utc_camcorder_set_video_capture_callback_007 while destroying the camcorder \n"); + return; + } + + return; +} +//////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * @brief This tests mm_camcorder_set_video_capture_callback API with invalid camcorder as well as with NULL callback function and NULL user parameter. + * @par ID: + * UTC_CAMCORDER_SET_VIDEO_CAPTURE_CALLBACK_008 + * @param [in] Invalid handle + * @param [in] Invalid handle + * @param [in] Invalid handle + * @param [out] None + * @return Error code + */ +void utc_camcorder_set_video_capture_callback_008() +{ + tet_printf("\n ======================utc_camcorder_set_video_capture_callback_008====================== \n"); + + gint errorValue = -1; + gboolean bReturnValue = false; + MMHandleType camcorder = 0; + MMCamPreset info; + + info.videodev_type = MM_VIDEO_DEVICE_CAMERA0; + + bReturnValue = CreateCamcorder(&camcorder, &info); + if (true != bReturnValue) { + tet_printf("\n Failed in utc_camcorder_set_video_capture_callback_008 while starting the camcorder \n"); + tet_result(TET_UNTESTED); + return; + } + + errorValue = mm_camcorder_set_video_capture_callback(0, NULL, NULL); + + bReturnValue = DestroyCamcorder(camcorder); + + dts_check_ne("mm_camcorder_set_video_capture_callback", errorValue, MM_ERROR_NONE, "Failed in utc_camcorder_set_video_capture_callback_008 while setting video stream callback function with error %x \n", errorValue); + + if (true != bReturnValue) { + tet_printf("\n Failed in utc_camcorder_set_video_capture_callback_008 while destroying the camcorder \n"); + return; + } + + return; +} +//////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** @} */ + diff --git a/TC/utc/uts_mm_camcorder_set_video_capture_callback.h b/TC/utc/uts_mm_camcorder_set_video_capture_callback.h new file mode 100644 index 0000000..9360829 --- /dev/null +++ b/TC/utc/uts_mm_camcorder_set_video_capture_callback.h @@ -0,0 +1,43 @@ +/* + * libmm-camcorder TC + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Jeongmo Yang + * + * 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. + * + */ + +/** +* @file uts_mm_camcorder_set_video_capture_callback.h +* @brief This file declares the camcorder set video capture callback test cases. +* @author Kishor Reddy (p.kishor@samsung.com) +* @version Initial Creation V0.1 +* @date 2009.03.04 +*/ + +#ifndef UTS_MM_CAMCORDER_SET_VIDEO_CAPTURE_CALLBACK_H +#define UTS_MM_CAMCORDER_SET_VIDEO_CAPTURE_CALLBACK_H + +void utc_camcorder_set_video_capture_callback_001(); +void utc_camcorder_set_video_capture_callback_002(); +void utc_camcorder_set_video_capture_callback_003(); +void utc_camcorder_set_video_capture_callback_004(); +void utc_camcorder_set_video_capture_callback_005(); +void utc_camcorder_set_video_capture_callback_006(); +void utc_camcorder_set_video_capture_callback_007(); +void utc_camcorder_set_video_capture_callback_008(); + +#endif /* UTS_MM_CAMCORDER_SET_VIDEO_CAPTURE_CALLBACK_H */ + diff --git a/TC/utc/uts_mm_camcorder_set_video_stream_callback.c b/TC/utc/uts_mm_camcorder_set_video_stream_callback.c new file mode 100644 index 0000000..f5b0dbb --- /dev/null +++ b/TC/utc/uts_mm_camcorder_set_video_stream_callback.c @@ -0,0 +1,434 @@ +/* + * libmm-camcorder TC + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Jeongmo Yang + * + * 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. + * + */ + +/** +* @ingroup Camcorder_API +* @addtogroup CAMCORDER Camcorder +*/ + +/** +* @ingroup CAMCORDER Camcorder +* @addtogroup UTS_CAMCORDER Unit +*/ + +/** +* @ingroup UTS_CAMCORDER Unit +* @addtogroup UTS_MM_CAMCORDER_SET_VIDEO_STREAM_CALLBACK Uts_Mm_Camcorder_Set_Video_Stream_Callback +* @{ +*/ + + +/** +* @file uts_mm_camcorder_set_video_stream_callback.c +* @brief This is a suite of unit test cases to test mm_camcorder_set_video_stream_callback API. +* @author Kishor Reddy (p.kishor@samsung.com) +* @version Initial Creation V0.1 +* @date 2008.11.27 +*/ + +#include "uts_mm_camcorder_set_video_stream_callback.h" +#include "uts_mm_camcorder_utils.h" + +struct tet_testlist tet_testlist[] = { + {utc_camcorder_set_video_stream_callback_001,1}, + {utc_camcorder_set_video_stream_callback_002,2}, + {utc_camcorder_set_video_stream_callback_003,3}, + {utc_camcorder_set_video_stream_callback_004,4}, + {utc_camcorder_set_video_stream_callback_005,5}, + {utc_camcorder_set_video_stream_callback_006,6}, + {utc_camcorder_set_video_stream_callback_007,7}, + {utc_camcorder_set_video_stream_callback_008,8}, + {NULL,0} +}; +//////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * @brief This tests mm_camcorder_set_video_stream_callback API in normal conditions. + * @par ID: + * UTC_CAMCORDER_SET_VIDEO_STREAM_CALLBACK_001 + * @param [in] camcorder = Valid Camcorder Handle + * @param [in] VideoStreamCallbackFunctionCalledByCamcorder (This itself is a function) + * @param [in] gCamcorderCallbackParameters + * @code + gCamcorderCallbackParameters->camcorder = *camcorder; + gCamcorderCallbackParameters->mode = IMAGE_MODE; + gCamcorderCallbackParameters->isMultishot = false; + gCamcorderCallbackParameters->stillshot_count = 0; + gCamcorderCallbackParameters->multishot_count = 0; + gCamcorderCallbackParameters->stillshot_filename = "stillshot_file";; + gCamcorderCallbackParameters->multishot_filename = "multishot_file";; + * @endcode + * @param [out] None + * @return MM_ERROR_NONE + */ +void utc_camcorder_set_video_stream_callback_001() +{ + tet_printf("\n ======================utc_camcorder_set_video_stream_callback_001====================== \n"); + + gint errorValue = -1; + gboolean bReturnValue = false; + MMHandleType camcorder = 0; + MMCamPreset info; + + info.videodev_type = MM_VIDEO_DEVICE_CAMERA0; + + bReturnValue = CreateCamcorder(&camcorder, &info); + if (true != bReturnValue) { + tet_printf("\n Failed in utc_camcorder_set_video_stream_callback_001 while starting the camcorder \n"); + tet_result(TET_UNTESTED); + return; + } + + errorValue = mm_camcorder_set_video_stream_callback(camcorder, VideoStreamCallbackFunctionCalledByCamcorder, gCamcorderCallbackParameters); + + bReturnValue = DestroyCamcorder(camcorder); + + dts_check_eq("mm_camcorder_set_video_stream_callback", errorValue, MM_ERROR_NONE, "Failed in utc_camcorder_set_video_stream_callback_001 while setting video stream callback function with error %x \n", errorValue); + + if (true != bReturnValue) { + tet_printf("\n Failed in utc_camcorder_set_video_stream_callback_001 while destroying the camcorder \n"); + return; + } + + return; +} +//////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * @brief This tests mm_camcorder_set_video_stream_callback API with NULL user parameter. + * @par ID: + * UTC_CAMCORDER_SET_VIDEO_STREAM_CALLBACK_002 + * @param [in] camcorder = Valid Camcorder Handle + * @param [in] VideoStreamCallbackFunctionCalledByCamcorder (This itself is a function) + * @param [in] Invalid handle + * @param [out] None + * @return MM_ERROR_NONE + */ +void utc_camcorder_set_video_stream_callback_002() +{ + tet_printf("\n ======================utc_camcorder_set_video_stream_callback_002====================== \n"); + + gint errorValue = -1; + gboolean bReturnValue = false; + MMHandleType camcorder = 0; + MMCamPreset info; + + info.videodev_type = MM_VIDEO_DEVICE_CAMERA0; + + bReturnValue = CreateCamcorder(&camcorder, &info); + if (true != bReturnValue) { + tet_printf("\n Failed in utc_camcorder_set_video_stream_callback_002 while starting the camcorder \n"); + tet_result(TET_UNTESTED); + return; + } + + errorValue = mm_camcorder_set_video_stream_callback(camcorder, VideoStreamCallbackFunctionCalledByCamcorder, NULL); + + bReturnValue = DestroyCamcorder(camcorder); + + dts_check_eq("mm_camcorder_set_video_stream_callback", errorValue, MM_ERROR_NONE, "Failed in utc_camcorder_set_video_stream_callback_002 while setting video stream callback function with error %x \n", errorValue); + + if (true != bReturnValue) { + tet_printf("\n Failed in utc_camcorder_set_video_stream_callback_002 while destroying the camcorder \n"); + return; + } + + return; +} +//////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * @brief This tests mm_camcorder_set_video_stream_callback API with NULL callback function. + * @par ID: + * UTC_CAMCORDER_SET_VIDEO_STREAM_CALLBACK_003 + * @param [in] camcorder = Valid Camcorder Handle + * @param [in] Invalid handle + * @param [in] gCamcorderCallbackParameters + * @code + gCamcorderCallbackParameters->camcorder = *camcorder; + gCamcorderCallbackParameters->mode = IMAGE_MODE; + gCamcorderCallbackParameters->isMultishot = false; + gCamcorderCallbackParameters->stillshot_count = 0; + gCamcorderCallbackParameters->multishot_count = 0; + gCamcorderCallbackParameters->stillshot_filename = "stillshot_file";; + gCamcorderCallbackParameters->multishot_filename = "multishot_file";; + * @endcode + * @param [out] None + * @return Error code + */ +void utc_camcorder_set_video_stream_callback_003() +{ + tet_printf("\n ======================utc_camcorder_set_video_stream_callback_003====================== \n"); + + gint errorValue = -1; + gboolean bReturnValue = false; + MMHandleType camcorder = 0; + MMCamPreset info; + + info.videodev_type = MM_VIDEO_DEVICE_CAMERA0; + + bReturnValue = CreateCamcorder(&camcorder, &info); + if (true != bReturnValue) { + tet_printf("\n Failed in utc_camcorder_set_video_stream_callback_003 while starting the camcorder \n"); + tet_result(TET_UNTESTED); + return; + } + + errorValue = mm_camcorder_set_video_stream_callback(camcorder, NULL, gCamcorderCallbackParameters); + + bReturnValue = DestroyCamcorder(camcorder); + + dts_check_eq("mm_camcorder_set_video_stream_callback", errorValue, MM_ERROR_NONE, "Failed in utc_camcorder_set_video_stream_callback_003 while setting video stream callback function with error %x \n", errorValue); + + if (true != bReturnValue) { + tet_printf("\n Failed in utc_camcorder_set_video_stream_callback_003 while destroying the camcorder \n"); + return; + } + + return; +} +//////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * @brief This tests mm_camcorder_set_video_stream_callback API with NULL callback function as well as NULL user parameter. + * @par ID: + * UTC_CAMCORDER_SET_VIDEO_STREAM_CALLBACK_004 + * @param [in] camcorder = Valid Camcorder Handle + * @param [in] Invalid handle + * @param [in] Invalid handle + * @param [out] None + * @return Error code + */ +void utc_camcorder_set_video_stream_callback_004() +{ + tet_printf("\n ======================utc_camcorder_set_video_stream_callback_004====================== \n"); + + gint errorValue = -1; + gboolean bReturnValue = false; + MMHandleType camcorder = 0; + MMCamPreset info; + + info.videodev_type = MM_VIDEO_DEVICE_CAMERA0; + + bReturnValue = CreateCamcorder(&camcorder, &info); + if (true != bReturnValue) { + tet_printf("\n Failed in utc_camcorder_set_video_stream_callback_004 while starting the camcorder \n"); + tet_result(TET_UNTESTED); + return; + } + + errorValue = mm_camcorder_set_video_stream_callback(camcorder, NULL, NULL); + + bReturnValue = DestroyCamcorder(camcorder); + + dts_check_eq("mm_camcorder_set_video_stream_callback", errorValue, MM_ERROR_NONE, "Failed in utc_camcorder_set_video_stream_callback_004 while setting video stream callback function with error %x \n", errorValue); + + if (true != bReturnValue) { + tet_printf("\n Failed in utc_camcorder_set_video_stream_callback_004 while destroying the camcorder \n"); + return; + } + + return; +} +//////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * @brief This tests mm_camcorder_set_video_stream_callback API with invalid camcorder. + * @par ID: + * UTC_CAMCORDER_SET_VIDEO_STREAM_CALLBACK_005 + * @param [in] Invalid handle + * @param [in] VideoStreamCallbackFunctionCalledByCamcorder (This itself is a function) + * @param [in] gCamcorderCallbackParameters + * @code + gCamcorderCallbackParameters->camcorder = *camcorder; + gCamcorderCallbackParameters->mode = IMAGE_MODE; + gCamcorderCallbackParameters->isMultishot = false; + gCamcorderCallbackParameters->stillshot_count = 0; + gCamcorderCallbackParameters->multishot_count = 0; + gCamcorderCallbackParameters->stillshot_filename = "stillshot_file";; + gCamcorderCallbackParameters->multishot_filename = "multishot_file";; + * @endcode + * @param [out] None + * @return Error code + */ +void utc_camcorder_set_video_stream_callback_005() +{ + tet_printf("\n ======================utc_camcorder_set_video_stream_callback_005====================== \n"); + + gint errorValue = -1; + gboolean bReturnValue = false; + MMHandleType camcorder = 0; + MMCamPreset info; + + info.videodev_type = MM_VIDEO_DEVICE_CAMERA0; + + bReturnValue = CreateCamcorder(&camcorder, &info); + if (true != bReturnValue) { + tet_printf("\n Failed in utc_camcorder_set_video_stream_callback_005 while starting the camcorder \n"); + tet_result(TET_UNTESTED); + return; + } + + errorValue = mm_camcorder_set_video_stream_callback(0, VideoStreamCallbackFunctionCalledByCamcorder, gCamcorderCallbackParameters); + + bReturnValue = DestroyCamcorder(camcorder); + + dts_check_ne("mm_camcorder_set_video_stream_callback", errorValue, MM_ERROR_NONE, "Failed in utc_camcorder_set_video_stream_callback_005 while setting video stream callback function with error %x \n", errorValue); + + if (true != bReturnValue) { + tet_printf("\n Failed in utc_camcorder_set_video_stream_callback_005 while destroying the camcorder \n"); + return; + } + + return; +} +//////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * @brief This tests mm_camcorder_set_video_stream_callback API with invalid camcorder as well as with NULL user parameter. + * @par ID: + * UTC_CAMCORDER_SET_VIDEO_STREAM_CALLBACK_006 + * @param [in] Invalid handle + * @param [in] VideoStreamCallbackFunctionCalledByCamcorder (This itself is a function) + * @param [in] Invalid handle + * @param [out] None + * @return Error code + */ +void utc_camcorder_set_video_stream_callback_006() +{ + tet_printf("\n ======================utc_camcorder_set_video_stream_callback_006====================== \n"); + + gint errorValue = -1; + gboolean bReturnValue = false; + MMHandleType camcorder = 0; + MMCamPreset info; + + info.videodev_type = MM_VIDEO_DEVICE_CAMERA0; + + bReturnValue = CreateCamcorder(&camcorder, &info); + if (true != bReturnValue) { + tet_printf("\n Failed in utc_camcorder_set_video_stream_callback_006 while starting the camcorder \n"); + tet_result(TET_UNTESTED); + return; + } + + errorValue = mm_camcorder_set_video_stream_callback(0, VideoStreamCallbackFunctionCalledByCamcorder, NULL); + + bReturnValue = DestroyCamcorder(camcorder); + + dts_check_ne("mm_camcorder_set_video_stream_callback", errorValue, MM_ERROR_NONE, "Failed in utc_camcorder_set_video_stream_callback_006 while setting video stream callback function with error %x \n", errorValue); + + if (true != bReturnValue) { + tet_printf("\n Failed in utc_camcorder_set_video_stream_callback_006 while destroying the camcorder \n"); + return; + } + + return; +} +//////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * @brief This tests mm_camcorder_set_video_stream_callback API with invalid camcorder as well as with NULL callback function. + * @par ID: + * UTC_CAMCORDER_SET_VIDEO_STREAM_CALLBACK_007 + * @param [in] Invalid handle + * @param [in] Invalid handle + * @param [in] gCamcorderCallbackParameters + * @code + gCamcorderCallbackParameters->camcorder = *camcorder; + gCamcorderCallbackParameters->mode = IMAGE_MODE; + gCamcorderCallbackParameters->isMultishot = false; + gCamcorderCallbackParameters->stillshot_count = 0; + gCamcorderCallbackParameters->multishot_count = 0; + gCamcorderCallbackParameters->stillshot_filename = "stillshot_file";; + gCamcorderCallbackParameters->multishot_filename = "multishot_file";; + * @endcode + * @param [out] None + * @return Error code + */ +void utc_camcorder_set_video_stream_callback_007() +{ + tet_printf("\n ======================utc_camcorder_set_video_stream_callback_007====================== \n"); + + gint errorValue = -1; + gboolean bReturnValue = false; + MMHandleType camcorder = 0; + MMCamPreset info; + + info.videodev_type = MM_VIDEO_DEVICE_CAMERA0; + + bReturnValue = CreateCamcorder(&camcorder, &info); + if (true != bReturnValue) { + tet_printf("\n Failed in utc_camcorder_set_video_stream_callback_007 while starting the camcorder \n"); + tet_result(TET_UNTESTED); + return; + } + + errorValue = mm_camcorder_set_video_stream_callback(0, NULL, gCamcorderCallbackParameters); + + bReturnValue = DestroyCamcorder(camcorder); + + dts_check_ne("mm_camcorder_set_video_stream_callback", errorValue, MM_ERROR_NONE, "Failed in utc_camcorder_set_video_stream_callback_007 while setting video stream callback function with error %x \n", errorValue); + + if (true != bReturnValue) { + tet_printf("\n Failed in utc_camcorder_set_video_stream_callback_007 while destroying the camcorder \n"); + return; + } + + return; +} +//////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * @brief This tests mm_camcorder_set_video_stream_callback API with invalid camcorder as well as with NULL callback function and NULL user parameter. + * @par ID: + * UTC_CAMCORDER_SET_VIDEO_STREAM_CALLBACK_008 + * @param [in] Invalid handle + * @param [in] Invalid handle + * @param [in] Invalid handle + * @param [out] None + * @return Error code + */ +void utc_camcorder_set_video_stream_callback_008() +{ + tet_printf("\n ======================utc_camcorder_set_video_stream_callback_008====================== \n"); + + gint errorValue = -1; + gboolean bReturnValue = false; + MMHandleType camcorder = 0; + MMCamPreset info; + + info.videodev_type = MM_VIDEO_DEVICE_CAMERA0; + + bReturnValue = CreateCamcorder(&camcorder, &info); + if (true != bReturnValue) { + tet_printf("\n Failed in utc_camcorder_set_video_stream_callback_008 while starting the camcorder \n"); + tet_result(TET_UNTESTED); + return; + } + + errorValue = mm_camcorder_set_video_stream_callback(0, NULL, NULL); + + bReturnValue = DestroyCamcorder(camcorder); + + dts_check_ne("mm_camcorder_set_video_stream_callback", errorValue, MM_ERROR_NONE, "Failed in utc_camcorder_set_video_stream_callback_008 while setting video stream callback function with error %x \n", errorValue); + + if (true != bReturnValue) { + tet_printf("\n Failed in utc_camcorder_set_video_stream_callback_008 while destroying the camcorder \n"); + return; + } + + return; +} +//////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** @} */ diff --git a/TC/utc/uts_mm_camcorder_set_video_stream_callback.h b/TC/utc/uts_mm_camcorder_set_video_stream_callback.h new file mode 100644 index 0000000..ebb4b9f --- /dev/null +++ b/TC/utc/uts_mm_camcorder_set_video_stream_callback.h @@ -0,0 +1,43 @@ +/* + * libmm-camcorder TC + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Jeongmo Yang + * + * 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. + * + */ + +/** +* @file uts_mm_camcorder_set_video_stream_callback.h +* @brief This file declares the camcorder set video stream callback test cases. +* @author Kishor Reddy (p.kishor@samsung.com) +* @version Initial Creation V0.1 +* @date 2009.03.04 +*/ + +#ifndef UTS_MM_CAMCORDER_SET_VIDEO_STREAM_CALLBACK_H +#define UTS_MM_CAMCORDER_SET_VIDEO_STREAM_CALLBACK_H + +void utc_camcorder_set_video_stream_callback_001(); +void utc_camcorder_set_video_stream_callback_002(); +void utc_camcorder_set_video_stream_callback_003(); +void utc_camcorder_set_video_stream_callback_004(); +void utc_camcorder_set_video_stream_callback_005(); +void utc_camcorder_set_video_stream_callback_006(); +void utc_camcorder_set_video_stream_callback_007(); +void utc_camcorder_set_video_stream_callback_008(); + +#endif /* UTS_MM_CAMCORDER_SET_VIDEO_STREAM_CALLBACK_H */ + diff --git a/TC/utc/uts_mm_camcorder_start.c b/TC/utc/uts_mm_camcorder_start.c new file mode 100644 index 0000000..7b0397d --- /dev/null +++ b/TC/utc/uts_mm_camcorder_start.c @@ -0,0 +1,147 @@ +/* + * libmm-camcorder TC + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Jeongmo Yang + * + * 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. + * + */ + +/** +* @ingroup Camcorder_API +* @addtogroup CAMCORDER Camcorder +*/ + +/** +* @ingroup CAMCORDER Camcorder +* @addtogroup UTS_CAMCORDER Unit +*/ + + +/** +* @ingroup UTS_CAMCORDER Unit +* @addtogroup UTS_MM_CAMCORDER_START Uts_Mm_Camcorder_Start +* @{ +*/ + + +/** +* @file uts_mm_camcorder_strat.c +* @brief This is a suite of unit test cases to test mm_camcorder_start API. +* @author Kishor Reddy (p.kishor@samsung.com) +* @version Initial Creation V0.1 +* @date 2008.11.27 +*/ + +#include "uts_mm_camcorder_start.h" +#include "uts_mm_camcorder_utils.h" + +struct tet_testlist tet_testlist[] = { + {utc_camcorder_start_001,1}, + {utc_camcorder_start_002,2}, + {NULL,0} +}; + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * @brief This tests mm_camcorder_start API in normal conditions. + * @par ID: + * UTC_CAMCORDER_START_001 + * @param [in] camcorder = Valid Camcorder Handle + * @param [out] None + * @pre Camcorder should be in READY state. + * @post Camcorder should come to PREPARE state. + * @return MM_ERROR_NONE + */ +void utc_camcorder_start_001() +{ + tet_printf("\n ======================utc_camcorder_start_001====================== \n"); + + gint errorValue = -1; + gint errorValue_check = -1; + gboolean bReturnValue = false; + MMHandleType camcorder = 0; + MMCamPreset info; + + info.videodev_type = MM_VIDEO_DEVICE_CAMERA0; + + bReturnValue = CreateCamcorder(&camcorder, &info); + if (true != bReturnValue) { + tet_printf("\n Failed in utc_camcorder_start_001 while creating the camcorder \n"); + tet_result(TET_UNTESTED); + return; + } + + bReturnValue = SetDefaultAttributes(camcorder,IMAGE_MODE); + if (true != bReturnValue) { + tet_printf("\n Failed in utc_camcorder_start_001 while setting default attributes to the camcorder \n"); + tet_result(TET_UNTESTED); + return; + } + + errorValue = mm_camcorder_realize(camcorder); + if (MM_ERROR_NONE != errorValue) { + tet_printf("\n Failed in utc_camcorder_start_001 while realizing the camcorder with error %x \n", errorValue); + tet_result(TET_UNTESTED); + return; + } + + errorValue_check = mm_camcorder_start(camcorder); + + errorValue = mm_camcorder_stop(camcorder); + if (MM_ERROR_NONE != errorValue) { + tet_printf("\n Failed in utc_camcorder_start_001 while stoping the camcorder with error %x but mm_camcorder_start API was passed \n", errorValue); + return; + } + + errorValue = mm_camcorder_unrealize(camcorder); + if (MM_ERROR_NONE != errorValue) { + tet_printf("\n Failed in utc_camcorder_start_001 while unrealizing the camcorder with error %x \n", errorValue); + return; + } + + bReturnValue = DestroyCamcorder(camcorder); + + dts_check_eq("mm_camcorder_start", errorValue_check, MM_ERROR_NONE, "Failed in utc_camcorder_start_001 while starting the camcorder with error %x \n", errorValue); + + if (true != bReturnValue) { + tet_printf("\n Failed in utc_camcorder_start_001 while destroying the camcorder \n"); + return; + } + + return; +} +//////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * @brief This tests mm_camcorder_start API with invalid camcorder. + * @par ID: + * UTC_CAMCORDER_START_002 + * @param [in] Invalid handle + * @param [out] None + * @return Error code + */ +void utc_camcorder_start_002() +{ + tet_printf("\n ======================utc_camcorder_start_002====================== \n"); + + gint errorValue = -1; + + errorValue = mm_camcorder_start(0); + dts_check_ne("mm_camcorder_start", errorValue, MM_ERROR_NONE, "Failed in utc_camcorder_start_002 while starting the camcorder with error %x \n", errorValue); + + return; +} +/////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** @} */ diff --git a/TC/utc/uts_mm_camcorder_start.h b/TC/utc/uts_mm_camcorder_start.h new file mode 100644 index 0000000..326b262 --- /dev/null +++ b/TC/utc/uts_mm_camcorder_start.h @@ -0,0 +1,36 @@ +/* + * libmm-camcorder TC + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Jeongmo Yang + * + * 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. + * + */ + +/** +* @file uts_mm_camcorder_start.h +* @brief This file declares the camcorder start test cases. +* @author Kishor Reddy (p.kishor@samsung.com) +* @version Initial Creation V0.1 +* @date 2008.11.27 +*/ + +#ifndef UTS_CAMCORDER_START_H +#define UTS_CAMCORDER_START_H + +void utc_camcorder_start_001(); +void utc_camcorder_start_002(); + +#endif /* UTS_CAMCORDER_START_H */ diff --git a/TC/utc/uts_mm_camcorder_start_focusing.c b/TC/utc/uts_mm_camcorder_start_focusing.c new file mode 100644 index 0000000..eff0e1b --- /dev/null +++ b/TC/utc/uts_mm_camcorder_start_focusing.c @@ -0,0 +1,154 @@ +/* + * libmm-camcorder TC + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Jeongmo Yang + * + * 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. + * + */ + +/** +* @ingroup Camcorder_API +* @addtogroup CAMCORDER Camcorder +*/ + +/** +* @ingroup CAMCORDER Camcorder +* @addtogroup UTS_CAMCORDER Unit +*/ + + +/** +* @ingroup UTS_CAMCORDER Unit +* @addtogroup UTS_MM_CAMCORDER_START Uts_Mm_Camcorder_Start +* @{ +*/ + + +/** +* @file uts_mm_camcorder_strat.c +* @brief This is a suite of unit test cases to test mm_camcorder_start API. +* @author Kishor Reddy (p.kishor@samsung.com) +* @version Initial Creation V0.1 +* @date 2008.11.27 +*/ + +#include "uts_mm_camcorder_start_focusing.h" +#include "uts_mm_camcorder_utils.h" + +struct tet_testlist tet_testlist[] = { + {utc_camcorder_start_focusing_001,1}, + {utc_camcorder_start_focusing_002,2}, + {NULL,0} +}; + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * @brief This tests mm_camcorder_start API in normal conditions. + * @par ID: + * UTC_CAMCORDER_START_001 + * @param [in] camcorder = Valid Camcorder Handle + * @param [out] None + * @pre Camcorder should be in READY state. + * @post Camcorder should come to PREPARE state. + * @return MM_ERROR_NONE + */ +void utc_camcorder_start_focusing_001() +{ + tet_printf("\n ======================utc_camcorder_start_001====================== \n"); + + gint errorValue = -1; + gint errorValue_check = -1; + gboolean bReturnValue = false; + MMHandleType camcorder = 0; + MMCamPreset info; + + info.videodev_type = MM_VIDEO_DEVICE_CAMERA0; + + bReturnValue = CreateCamcorder(&camcorder, &info); + if (true != bReturnValue) { + tet_printf("\n Failed in utc_camcorder_start_001 while creating the camcorder \n"); + tet_result(TET_UNTESTED); + return; + } + + bReturnValue = SetDefaultAttributes(camcorder,IMAGE_MODE); + if (true != bReturnValue) { + tet_printf("\n Failed in utc_camcorder_start_001 while setting default attributes to the camcorder \n"); + tet_result(TET_UNTESTED); + return; + } + + errorValue = mm_camcorder_realize(camcorder); + if (MM_ERROR_NONE != errorValue) { + tet_printf("\n Failed in utc_camcorder_start_001 while realizing the camcorder with error %x \n", errorValue); + tet_result(TET_UNTESTED); + return; + } + + errorValue = mm_camcorder_start(camcorder); + if (MM_ERROR_NONE != errorValue) { + tet_printf("\n Failed in utc_camcorder_start_001 while starting the camcorder with error %x \n", errorValue); + tet_result(TET_FAIL); + return; + } + + errorValue_check = mm_camcorder_start_focusing(camcorder); + + errorValue = mm_camcorder_stop(camcorder); + if (MM_ERROR_NONE != errorValue) { + tet_printf("\n Failed in utc_camcorder_start_001 while stoping the camcorder with error %x but mm_camcorder_start API was passed \n", errorValue); + return; + } + + errorValue = mm_camcorder_unrealize(camcorder); + if (MM_ERROR_NONE != errorValue) { + tet_printf("\n Failed in utc_camcorder_start_001 while unrealizing the camcorder with error %x \n", errorValue); + return; + } + + bReturnValue = DestroyCamcorder(camcorder); + + dts_check_eq("mm_camcorder_start_focusing", errorValue_check, MM_ERROR_NONE, "Failed in utc_camcorder_start_focusing_001 while starting focusing with error %x \n", errorValue); + + if (true != bReturnValue) { + tet_printf("\n Failed in utc_camcorder_start_001 while destroying the camcorder \n"); + return; + } + + return; +} +//////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * @brief This tests mm_camcorder_start API with invalid camcorder. + * @par ID: + * UTC_CAMCORDER_START_002 + * @param [in] Invalid handle + * @param [out] None + * @return Error code + */ +void utc_camcorder_start_focusing_002() +{ + tet_printf("\n ======================utc_camcorder_start_002====================== \n"); + + gint errorValue = -1; + + errorValue = mm_camcorder_start_focusing(0); + dts_check_ne("mm_camcorder_start_focusing", errorValue, MM_ERROR_NONE, "Failed in utc_camcorder_start_focusing_002 while starting the camcorder with error %x \n", errorValue); + + return; +} +/////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** @} */ diff --git a/TC/utc/uts_mm_camcorder_start_focusing.h b/TC/utc/uts_mm_camcorder_start_focusing.h new file mode 100644 index 0000000..6a0b999 --- /dev/null +++ b/TC/utc/uts_mm_camcorder_start_focusing.h @@ -0,0 +1,36 @@ +/* + * libmm-camcorder TC + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Jeongmo Yang + * + * 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. + * + */ + +/** +* @file uts_mm_camcorder_start.h +* @brief This file declares the camcorder start test cases. +* @author Kishor Reddy (p.kishor@samsung.com) +* @version Initial Creation V0.1 +* @date 2008.11.27 +*/ + +#ifndef UTS_CAMCORDER_START_FOCUSING_H +#define UTS_CAMCORDER_START_FOCUSING_H + +void utc_camcorder_start_focusing_001(); +void utc_camcorder_start_focusing_002(); + +#endif /* UTS_CAMCORDER_START_H */ diff --git a/TC/utc/uts_mm_camcorder_stop.c b/TC/utc/uts_mm_camcorder_stop.c new file mode 100644 index 0000000..6b5d640 --- /dev/null +++ b/TC/utc/uts_mm_camcorder_stop.c @@ -0,0 +1,148 @@ +/* + * libmm-camcorder TC + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Jeongmo Yang + * + * 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. + * + */ + +/** +* @ingroup Camcorder_API +* @addtogroup CAMCORDER Camcorder +*/ + +/** +* @ingroup CAMCORDER Camcorder +* @addtogroup UTS_CAMCORDER Unit +*/ + + +/** +* @ingroup UTS_CAMCORDER Unit +* @addtogroup UTS_MM_CAMCORDER_STOP Uts_Mm_Camcorder_Stop +* @{ +*/ + + +/** +* @file uts_mm_camcorder_stop.c +* @brief This is a suite of unit test cases to test mm_camcorder_stop API. +* @author Kishor Reddy (p.kishor@samsung.com) +* @version Initial Creation V0.1 +* @date 2008.11.27 +*/ + +#include "uts_mm_camcorder_stop.h" +#include "uts_mm_camcorder_utils.h" + +struct tet_testlist tet_testlist[] = { + {utc_camcorder_stop_001,1}, + {utc_camcorder_stop_002,2}, + {NULL,0} +}; + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * @brief This tests mm_camcorder_stop API in normal conditions. + * @par ID: + * UTC_CAMCORDER_STOP_001 + * @param [in] camcorder = Valid Camcorder Handle + * @param [out] None + * @pre Camcorder should be in PREPARE state. + * @post Camcorder should come to READY state. + * @return MM_ERROR_NONE + */ +void utc_camcorder_stop_001() +{ + tet_printf("\n ======================utc_camcorder_stop_001====================== \n"); + + gint errorValue = -1; + gint errorValue_check = -1; + gboolean bReturnValue = false; + MMHandleType camcorder = 0; + MMCamPreset info; + + info.videodev_type = MM_VIDEO_DEVICE_CAMERA0; + + bReturnValue = CreateCamcorder(&camcorder, &info); + if (true != bReturnValue) { + tet_printf("\n Failed in utc_camcorder_stop_001 while creating the camcorder \n"); + tet_result(TET_UNTESTED); + return; + } + + bReturnValue = SetDefaultAttributes(camcorder,IMAGE_MODE); + if (true != bReturnValue) { + tet_printf("\n Failed in utc_camcorder_stop_001 while setting default attributes to the camcorder \n"); + tet_result(TET_UNTESTED); + return; + } + + errorValue = mm_camcorder_realize(camcorder); + if (MM_ERROR_NONE != errorValue) { + tet_printf("\n Failed in utc_camcorder_stop_001 while realizing the camcorder with error %x \n", errorValue); + tet_result(TET_UNTESTED); + return; + } + + errorValue = mm_camcorder_start(camcorder); + if (MM_ERROR_NONE != errorValue) { + tet_printf("\n Failed in utc_camcorder_stop_001 while starting the camcorder with error %x \n", errorValue); + tet_result(TET_UNTESTED); + return; + } + + errorValue_check = mm_camcorder_stop(camcorder); + + errorValue = mm_camcorder_unrealize(camcorder); + if (MM_ERROR_NONE != errorValue) { + tet_printf("\n Failed in utc_camcorder_stop_001 while unrealizing the camcorder with error %x \n", errorValue); + return; + } + + bReturnValue = DestroyCamcorder(camcorder); + + dts_check_eq("mm_camcorder_start_focusing", errorValue_check, MM_ERROR_NONE, "Failed in utc_camcorder_stop_001 while stoping the camcorder with error %x \n", errorValue); + + if (true != bReturnValue) { + tet_printf("\n Failed in utc_camcorder_stop_001 while destroying the camcorder \n"); + return; + } + + return; +} +//////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * @brief This tests mm_camcorder_stop API with invalid camcorder. + * @par ID: + * UTC_CAMCORDER_STOP_002 + * @param [in] Invalid handle + * @param [out] None + * @return Error code + */ +void utc_camcorder_stop_002() +{ + tet_printf("\n ======================utc_camcorder_stop_002====================== \n"); + + gint errorValue = -1; + + errorValue = mm_camcorder_stop(0); + dts_check_ne("mm_camcorder_start_focusing", errorValue, MM_ERROR_NONE, "Failed in utc_camcorder_stop_002 while stoping the camcorder with error %x \n", errorValue); + + return; +} +/////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** @} */ diff --git a/TC/utc/uts_mm_camcorder_stop.h b/TC/utc/uts_mm_camcorder_stop.h new file mode 100644 index 0000000..5d6de94 --- /dev/null +++ b/TC/utc/uts_mm_camcorder_stop.h @@ -0,0 +1,36 @@ +/* + * libmm-camcorder TC + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Jeongmo Yang + * + * 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. + * + */ + +/** +* @file uts_mm_camcorder_stop.h +* @brief This file declares the camcorder stop test cases. +* @author Kishor Reddy (p.kishor@samsung.com) +* @version Initial Creation V0.1 +* @date 2008.11.27 +*/ + +#ifndef UTS_CAMCORDER_STOP_H +#define UTS_CAMCORDER_STOP_H + +void utc_camcorder_stop_001(); +void utc_camcorder_stop_002(); + +#endif /* UTS_CAMCORDER_STOP_H */ diff --git a/TC/utc/uts_mm_camcorder_stop_focusing.c b/TC/utc/uts_mm_camcorder_stop_focusing.c new file mode 100644 index 0000000..8b7aab3 --- /dev/null +++ b/TC/utc/uts_mm_camcorder_stop_focusing.c @@ -0,0 +1,161 @@ +/* + * libmm-camcorder TC + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Jeongmo Yang + * + * 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. + * + */ + +/** +* @ingroup Camcorder_API +* @addtogroup CAMCORDER Camcorder +*/ + +/** +* @ingroup CAMCORDER Camcorder +* @addtogroup UTS_CAMCORDER Unit +*/ + + +/** +* @ingroup UTS_CAMCORDER Unit +* @addtogroup UTS_MM_CAMCORDER_STOP Uts_Mm_Camcorder_Stop +* @{ +*/ + + +/** +* @file uts_mm_camcorder_stop.c +* @brief This is a suite of unit test cases to test mm_camcorder_stop API. +* @author Kishor Reddy (p.kishor@samsung.com) +* @version Initial Creation V0.1 +* @date 2008.11.27 +*/ + +#include "uts_mm_camcorder_stop_focusing.h" +#include "uts_mm_camcorder_utils.h" + +struct tet_testlist tet_testlist[] = { + {utc_camcorder_stop_focusing_001,1}, + {utc_camcorder_stop_focusing_002,2}, + {NULL,0} +}; + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * @brief This tests mm_camcorder_stop API in normal conditions. + * @par ID: + * UTC_CAMCORDER_STOP_001 + * @param [in] camcorder = Valid Camcorder Handle + * @param [out] None + * @pre Camcorder should be in PREPARE state. + * @post Camcorder should come to READY state. + * @return MM_ERROR_NONE + */ +void utc_camcorder_stop_focusing_001() +{ + tet_printf("\n ======================utc_camcorder_stop_001====================== \n"); + + gint errorValue = -1; + gint errorValue_check = -1; + gboolean bReturnValue = false; + MMHandleType camcorder = 0; + MMCamPreset info; + + info.videodev_type = MM_VIDEO_DEVICE_CAMERA0; + + bReturnValue = CreateCamcorder(&camcorder, &info); + if (true != bReturnValue) { + tet_printf("\n Failed in utc_camcorder_stop_001 while creating the camcorder \n"); + tet_result(TET_UNTESTED); + return; + } + + bReturnValue = SetDefaultAttributes(camcorder,IMAGE_MODE); + if (true != bReturnValue) { + tet_printf("\n Failed in utc_camcorder_stop_001 while setting default attributes to the camcorder \n"); + tet_result(TET_UNTESTED); + return; + } + + errorValue = mm_camcorder_realize(camcorder); + if (MM_ERROR_NONE != errorValue) { + tet_printf("\n Failed in utc_camcorder_stop_001 while realizing the camcorder with error %x \n", errorValue); + tet_result(TET_UNTESTED); + return; + } + + errorValue = mm_camcorder_start(camcorder); + if (MM_ERROR_NONE != errorValue) { + tet_printf("\n Failed in utc_camcorder_stop_001 while starting the camcorder with error %x \n", errorValue); + tet_result(TET_UNTESTED); + return; + } + + errorValue = mm_camcorder_start_focusing(camcorder); + if (MM_ERROR_NONE != errorValue) { + tet_printf("\n Failed in utc_camcorder_stop_focusing_001 while starting focusing with error %x \n", errorValue); + tet_result(TET_UNTESTED); + return; + } + + errorValue_check = mm_camcorder_stop_focusing(camcorder); + + errorValue = mm_camcorder_stop(camcorder); + if (MM_ERROR_NONE != errorValue) { + tet_printf("\n Failed in utc_camcorder_stop_001 while stoping the camcorder with error %x \n", errorValue); + return; + } + + errorValue = mm_camcorder_unrealize(camcorder); + if (MM_ERROR_NONE != errorValue) { + tet_printf("\n Failed in utc_camcorder_stop_001 while unrealizing the camcorder with error %x \n", errorValue); + return; + } + + bReturnValue = DestroyCamcorder(camcorder); + + dts_check_eq("mm_camcorder_stop_focusing", errorValue_check, MM_ERROR_NONE, "Failed in utc_camcorder_stop_focusing_001 while stoping focusing with error %x \n", errorValue); + + if (true != bReturnValue) { + tet_printf("\n Failed in utc_camcorder_stop_001 while destroying the camcorder \n"); + return; + } + + return; +} +//////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * @brief This tests mm_camcorder_stop API with invalid camcorder. + * @par ID: + * UTC_CAMCORDER_STOP_002 + * @param [in] Invalid handle + * @param [out] None + * @return Error code + */ +void utc_camcorder_stop_focusing_002() +{ + tet_printf("\n ======================utc_camcorder_stop_002====================== \n"); + + gint errorValue = -1; + + errorValue = mm_camcorder_stop_focusing(0); + dts_check_ne("mm_camcorder_stop_focusing", errorValue, MM_ERROR_NONE, "Failed in utc_camcorder_stop_focusing_002 while stoping the camcorder with error %x \n", errorValue); + + return; +} +/////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** @} */ diff --git a/TC/utc/uts_mm_camcorder_stop_focusing.h b/TC/utc/uts_mm_camcorder_stop_focusing.h new file mode 100644 index 0000000..ecc08a1 --- /dev/null +++ b/TC/utc/uts_mm_camcorder_stop_focusing.h @@ -0,0 +1,36 @@ +/* + * libmm-camcorder TC + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Jeongmo Yang + * + * 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. + * + */ + +/** +* @file uts_mm_camcorder_stop.h +* @brief This file declares the camcorder stop test cases. +* @author Kishor Reddy (p.kishor@samsung.com) +* @version Initial Creation V0.1 +* @date 2008.11.27 +*/ + +#ifndef UTS_CAMCORDER_STOP_FOCUSING_H +#define UTS_CAMCORDER_STOP_FOCUSING_H + +void utc_camcorder_stop_focusing_001(); +void utc_camcorder_stop_focusing_002(); + +#endif /* UTS_CAMCORDER_STOP_H */ diff --git a/TC/utc/uts_mm_camcorder_unrealize.c b/TC/utc/uts_mm_camcorder_unrealize.c new file mode 100644 index 0000000..5f2c1fa --- /dev/null +++ b/TC/utc/uts_mm_camcorder_unrealize.c @@ -0,0 +1,149 @@ +/* + * libmm-camcorder TC + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Jeongmo Yang + * + * 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. + * + */ + +/** +* @ingroup Camcorder_API +* @addtogroup CAMCORDER Camcorder +*/ + +/** +* @ingroup CAMCORDER Camcorder +* @addtogroup UTS_CAMCORDER Unit +*/ + + +/** +* @ingroup UTS_CAMCORDER Unit +* @addtogroup UTS_MM_CAMCORDER_UNREALIZE Uts_Mm_Camcorder_Unrealize +* @{ +*/ + +/** +* @file uts_mm_camcorder_unrealize.c +* @brief This is a suite of unit test cases to test mm_camcorder_unrealize API. +* @author Kishor Reddy (p.kishor@samsung.com) +* @version Initial Creation V0.1 +* @date 2008.11.27 +*/ + +#include "uts_mm_camcorder_unrealize.h" +#include "uts_mm_camcorder_utils.h" + +struct tet_testlist tet_testlist[] = { + {utc_camcorder_unrealize_001,1}, + {utc_camcorder_unrealize_002,2}, + {NULL,0} +}; + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * @brief This tests mm_camcorder_unrealize API in normal conditions. + * @par ID: + * UTC_CAMCORDER_UNREALIZE_001 + * @param [in] camcorder = Valid Camcorder Handle + * @param [out] None + * @pre Camcorder should be in READY state. + * @post Camcorder should come to NULL state. + * @return MM_ERROR_NONE + */ +void utc_camcorder_unrealize_001() +{ + tet_printf("\n ======================utc_camcorder_unrealize_001====================== \n"); + + gint errorValue = -1; + gboolean bReturnValue = false; + MMHandleType camcorder = 0; + MMCamPreset info; + + info.videodev_type = MM_VIDEO_DEVICE_CAMERA0; + + bReturnValue = CreateCamcorder(&camcorder, &info); + if (true != bReturnValue) { + tet_printf("\n Failed in utc_camcorder_unrealize_001 while creating the camcorder \n"); + tet_result(TET_UNTESTED); + return; + } + + bReturnValue = SetDefaultAttributes(camcorder,IMAGE_MODE); + if (true != bReturnValue) { + tet_printf("\n Failed in utc_camcorder_unrealize_001 while setting default attributes to the camcorder \n"); + tet_result(TET_UNTESTED); + return; + } + + errorValue = mm_camcorder_realize(camcorder); + if (MM_ERROR_NONE != errorValue) { + tet_printf("\n Failed in utc_camcorder_unrealize_001 while realizing the camcorder with error %x \n", errorValue); + tet_result(TET_UNTESTED); + return; + } + + errorValue = mm_camcorder_start(camcorder); + if (MM_ERROR_NONE != errorValue) { + tet_printf("\n Failed in utc_camcorder_unrealize_001 while starting the camcorder with error %x \n", errorValue); + tet_result(TET_UNTESTED); + return; + } + + sleep(2); + + errorValue = mm_camcorder_stop(camcorder); + if (MM_ERROR_NONE != errorValue) { + tet_printf("\n Failed in utc_camcorder_unrealize_001 while stopping the camcorder with error %x \n", errorValue); + tet_result(TET_UNTESTED); + return; + } + + errorValue = mm_camcorder_unrealize(camcorder); + + bReturnValue = DestroyCamcorder(camcorder); + + dts_check_eq("mm_camcorder_unrealize", errorValue, MM_ERROR_NONE, "Failed in utc_camcorder_unrealize_001 while unrealizing the camcorder with error %x but mm_camcorder_realize API was passed \n", errorValue); + + if (true != bReturnValue) { + tet_printf("\n Failed in utc_camcorder_unrealize_001 while destroying the camcorder \n"); + return; + } + + return; +} +//////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * @brief This tests mm_camcorder_unrealize API iwith invalid handle. + * @par ID: + * UTC_CAMCORDER_UNREALIZE_002 + * @param [in] camcorder = Invalid Camcorder Handle + * @param [out] None + * @return Error code. + */ +void utc_camcorder_unrealize_002() +{ + tet_printf("\n ======================utc_camcorder_unrealize_002====================== \n"); + + gint errorValue = -1; + + errorValue = mm_camcorder_unrealize(0); + dts_check_ne("mm_camcorder_unrealize", errorValue, MM_ERROR_NONE, "Failed in utc_camcorder_unrealize_002 while unrealizing the camcorder with error %x \n", errorValue); + + return; +} +/////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** @} */ diff --git a/TC/utc/uts_mm_camcorder_unrealize.h b/TC/utc/uts_mm_camcorder_unrealize.h new file mode 100644 index 0000000..8c4565c --- /dev/null +++ b/TC/utc/uts_mm_camcorder_unrealize.h @@ -0,0 +1,36 @@ +/* + * libmm-camcorder TC + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Jeongmo Yang + * + * 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. + * + */ + +/** +* @file uts_mm_camcorder_unrealize.h +* @brief This file declares the camcorder unrealize test cases. +* @author Kishor Reddy (p.kishor@samsung.com) +* @version Initial Creation V0.1 +* @date 2008.11.27 +*/ + +#ifndef UTS_CAMCORDER_UNREALIZE_H +#define UTS_CAMCORDER_UNREALIZE_H + +void utc_camcorder_unrealize_001(); +void utc_camcorder_unrealize_002(); + +#endif /* UTS_CAMCORDER_UNREALIZE_H */ diff --git a/TC/utc/uts_mm_camcorder_utils.c b/TC/utc/uts_mm_camcorder_utils.c new file mode 100644 index 0000000..0096a51 --- /dev/null +++ b/TC/utc/uts_mm_camcorder_utils.c @@ -0,0 +1,911 @@ +/* + * libmm-camcorder TC + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Jeongmo Yang + * + * 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 "uts_mm_camcorder_utils.h" + +#ifndef __arm__ +#include +#endif +#include + +#include +GMainLoop *gGMainLoop = NULL; +camcorder_callback_parameters *gCamcorderCallbackParameters = NULL; +camcorder_callback_parameters *gCamcorderCallbackParametersArray[STRESS]; +int overlay = 1; + +void (*tet_startup)() = Startup; +void (*tet_cleanup)() = Cleanup; + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void Startup() +{ + gGMainLoop = g_main_loop_new(NULL, FALSE); + if(!gGMainLoop) { + tet_printf("\n Failed in startup function while initializing GMainLoop \n"); + return; + } +#ifndef __arm__ + gst_init(NULL, NULL); +#endif + tet_printf("\n Initialization[Startup function] was completed \n"); + return; +} +//////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void Cleanup() +{ + if (!gGMainLoop) { + return; + } + g_main_loop_unref(gGMainLoop); +/* if(gGMainLoop->context) { \\Kishor :: This is to check whether g_main_loop_unref was success or not + tet_printf("\n Failed in cleanup function while cleaning GMainLoop \n"); + return; + } +*/ tet_printf("\n Deinitialization[Cleanup function] was completed \n"); + return; +} +//////////////////////////////////////////////////////////////////////////////////////////////////////////////// +gboolean CreateCamcorder(MMHandleType* camcorder, MMCamPreset* pInfo) +{ + tet_printf("\n ======================Creating Camcorder====================== \n"); + gint errorValue = -1; + + errorValue = mm_camcorder_create(camcorder, pInfo); + if (MM_ERROR_NONE != errorValue) { + tet_printf("\n Failed in CreateCamcorder while creating the camcorder with error %x \n", errorValue); + return false; + } + + if(gCamcorderCallbackParameters) { + free(gCamcorderCallbackParameters); + } + + gCamcorderCallbackParameters = (camcorder_callback_parameters *)malloc(sizeof(camcorder_callback_parameters)); + if(!gCamcorderCallbackParameters) { + tet_printf("\n Failed while allocating memory to gCamcorderCallbackParameters \n"); + return false; + } + + gCamcorderCallbackParameters->camcorder = *camcorder; + gCamcorderCallbackParameters->mode = IMAGE_MODE; + gCamcorderCallbackParameters->isMultishot = false; + gCamcorderCallbackParameters->stillshot_count = 0; + gCamcorderCallbackParameters->multishot_count = 0; + gCamcorderCallbackParameters->stillshot_filename = NULL; + gCamcorderCallbackParameters->multishot_filename = NULL; + gCamcorderCallbackParameters->stillshot_filename = (char *)malloc(25*sizeof(char)); + memset(gCamcorderCallbackParameters->stillshot_filename, 0, (25*sizeof(char))); + if(gCamcorderCallbackParameters->stillshot_filename!=NULL) { + gCamcorderCallbackParameters->stillshot_filename = "stillshot_file"; + } + gCamcorderCallbackParameters->multishot_filename = (char *)malloc(25*sizeof(char)); + if(!(gCamcorderCallbackParameters->multishot_filename)) { + gCamcorderCallbackParameters->multishot_filename = "multishot_file"; + } + /* + errorValue = mm_camcorder_set_filename_callback(gCamcorderCallbackParameters->camcorder, FilenameCallbackFunctionCalledByCamcorder, gCamcorderCallbackParameters); + if (MM_ERROR_NONE != errorValue) { + tet_printf("\n Failed in CreateCamcorder while setting filename callback function in the camcorder with error %x \n", errorValue); + return false; + } + */ + + errorValue = mm_camcorder_set_message_callback(gCamcorderCallbackParameters->camcorder, MessageCallbackFunctionCalledByCamcorder, gCamcorderCallbackParameters); + if (MM_ERROR_NONE != errorValue) { + tet_printf("\n Failed in CreateCamcorder while setting message callback function in the camcorder with error %x \n", errorValue); + return false; + } + + return true; +} +//////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * @brief This destroys the camcorder. + * @param [in] camcorder + * @code + errorValue = mm_camcorder_destroy(camcorder); + * @endcode + * @param [out] None + * @return true if successful, otherwise false. + */ +gboolean DestroyCamcorder(MMHandleType camcorder) +{ + tet_printf("\n ======================Destroying Camcorder====================== \n"); + + gint errorValue = -1; + + errorValue = mm_camcorder_destroy(camcorder); + if (MM_ERROR_NONE != errorValue) { + tet_printf("\n Failed in DestroyCamcorder while destroying the camcorder with error %x \n", errorValue); + return false; + } + + return true; +} +//////////////////////////////////////////////////////////////////////////////////////////////////////////////// +gboolean StartCamcorder(MMHandleType* camcorder, MMCamPreset* pInfo,gint mode) +{ + tet_printf("\n ======================Starting Camcorder====================== \n"); + + gint errorValue = -1; + gboolean bReturnValue = false; + + bReturnValue = CreateCamcorder(camcorder, pInfo); + if (false == bReturnValue) { + tet_printf("\n Failed in StartCamcorder while creating the camcorder \n"); + return false; + } + + bReturnValue = SetDefaultAttributes(*camcorder,mode); + if (true != bReturnValue) { + tet_printf("\n Failed in StartCamcorder while setting default attributes to the camcorder \n"); + return false; + } + + errorValue = mm_camcorder_realize(*camcorder); + if (MM_ERROR_NONE != errorValue) { + tet_printf("\n Failed in StartCamcorder while realizing the camcorder with error %x but mm_camcorder_start API was passed \n", errorValue); + return false; + } + + errorValue = mm_camcorder_start(*camcorder); + if (MM_ERROR_NONE != errorValue) { + tet_printf("\n Failed in StartCamcorder while starting the camcorder with error %x but mm_camcorder_create API was passed \n", errorValue); + return false; + } + + return true; +} +//////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/** + * @brief This stops and destroys the camcorder. + * @param [in] camcorder + * @code + errorValue = mm_camcorder_stop(camcorder); + errorValue = mm_camcorder_unrealize(camcorder); + bReturnValue = DestroyCamcorder(camcorder); + * @endcode + * @return true if successful, otherwise false. + */ +gboolean StopCamcorder(MMHandleType camcorder) +{ + tet_printf("\n ======================Stoping Camcorder====================== \n"); + + gint errorValue = -1; + gboolean bReturnValue = false; + + errorValue = mm_camcorder_stop(camcorder); + if (MM_ERROR_NONE != errorValue) { + tet_printf("\n Failed in StopCamcorder while stoping the camcorder with error %x \n", errorValue); + return false; + } + + errorValue = mm_camcorder_unrealize(camcorder); + if (MM_ERROR_NONE != errorValue) { + tet_printf("\n Failed in StopCamcorder while unrealizing the camcorder with error %x \n", errorValue); + return false; + } + + bReturnValue = DestroyCamcorder(camcorder); + if (true != bReturnValue) { + tet_printf("\n Failed in StopCamcorder while destroying the camcorder \n"); + return false; + } + + return true; +} +//////////////////////////////////////////////////////////////////////////////////////////////////////////////// +gboolean StartCamcorderforNInstances(MMHandleType camcorderInstances[], gint noOfInstances) +{ + tet_printf("\n ======================StartCamcorderforNInstances====================== \n"); + + gint errorValue = -1; + gboolean bReturnValue = false; + gint outerLoopVariable = 0; + gint mode = IMAGE_MODE; + MMCamPreset info; + + info.videodev_type = MM_VIDEO_DEVICE_CAMERA0; + + for(outerLoopVariable = 0; outerLoopVariable < noOfInstances ; outerLoopVariable++) { + camcorderInstances[outerLoopVariable] = 0; + + errorValue = mm_camcorder_create((MMHandleType*)camcorderInstances[outerLoopVariable], &info); + if (MM_ERROR_NONE != errorValue) { + tet_printf("\n Failed in StartCamcorderforNInstances while creating the camcorder with error %x (%d time) \n", errorValue, outerLoopVariable); + return false;; + } + + if (!camcorderInstances[outerLoopVariable]) { + tet_printf("\n Failed in StartCamcorderforNInstances while accessing the camcorder with error %x (%d time) \n", errorValue, outerLoopVariable); + return false;; + } + + mode = outerLoopVariable%3; + gCamcorderCallbackParametersArray[outerLoopVariable] = NULL; + gCamcorderCallbackParametersArray[outerLoopVariable] = (camcorder_callback_parameters *)malloc(sizeof(camcorder_callback_parameters)); + if(!gCamcorderCallbackParametersArray[outerLoopVariable]) { + tet_printf("\n Failed while allocating memory to gCamcorderCallbackParameters \n"); + return false; + } + + gCamcorderCallbackParametersArray[outerLoopVariable]->camcorder = camcorderInstances[outerLoopVariable]; + gCamcorderCallbackParametersArray[outerLoopVariable]->mode = mode; + gCamcorderCallbackParametersArray[outerLoopVariable]->isMultishot = false; + gCamcorderCallbackParametersArray[outerLoopVariable]->stillshot_count = 0; + gCamcorderCallbackParametersArray[outerLoopVariable]->multishot_count = 0; + gCamcorderCallbackParametersArray[outerLoopVariable]->stillshot_filename = NULL; + gCamcorderCallbackParametersArray[outerLoopVariable]->multishot_filename = NULL; + gCamcorderCallbackParametersArray[outerLoopVariable]->stillshot_filename = (char *)malloc(25*sizeof(char)); + if(!(gCamcorderCallbackParametersArray[outerLoopVariable]->stillshot_filename)) { + gCamcorderCallbackParametersArray[outerLoopVariable]->stillshot_filename = "stillshot_file"; + } + + gCamcorderCallbackParametersArray[outerLoopVariable]->multishot_filename = (char *)malloc(25*sizeof(char)); + if(!(gCamcorderCallbackParametersArray[outerLoopVariable]->multishot_filename)) { + gCamcorderCallbackParametersArray[outerLoopVariable]->multishot_filename = "multishot_file"; + } + /* + errorValue = mm_camcorder_set_filename_callback(camcorderInstances[outerLoopVariable], FilenameCallbackFunctionCalledByCamcorder, gCamcorderCallbackParametersArray[outerLoopVariable]); + if (MM_ERROR_NONE != errorValue) { + tet_printf("\n Failed in StartCamcorderforNInstances while setting filename callback function in the camcorder with error %d \n", errorValue); + return false; + } + */ + + errorValue = mm_camcorder_set_message_callback(camcorderInstances[outerLoopVariable], MessageCallbackFunctionCalledByCamcorder, gCamcorderCallbackParametersArray[outerLoopVariable]); + if (MM_ERROR_NONE != errorValue) { + tet_printf("\n Failed in StartCamcorderforNInstances while setting message callback function in the camcorder with error %x \n", errorValue); + return false; + } + + bReturnValue = SetDefaultAttributes(camcorderInstances[outerLoopVariable], mode); + if (true != bReturnValue) { + tet_printf("\n Failed in StartCamcorderforNInstances while setting default attributes to the camcorder with mode %d (%d time) \n",mode, outerLoopVariable); + return false; + } + + errorValue = mm_camcorder_realize(camcorderInstances[outerLoopVariable]); + if (MM_ERROR_NONE != errorValue) { + tet_printf("\n Failed in StartCamcorderforNInstances while realizing the camcorder with error %x (%d time) \n", errorValue, outerLoopVariable); + return false; + } + + errorValue = mm_camcorder_start(camcorderInstances[outerLoopVariable]); + if (MM_ERROR_NONE != errorValue) { + tet_printf("\n Failed in StartCamcorderforNInstances while starting the camcorder with error %x (%d time) \n", errorValue, outerLoopVariable); + return false; + } + } + + tet_printf("\n In StartCamcorderforNInstances: All instances were started \n"); + + return true; +} +//////////////////////////////////////////////////////////////////////////////////////////////////////////////// +gboolean StopCamcorderforNInstances(MMHandleType camcorderInstances[], gint noOfInstances) +{ + tet_printf("\n ======================StopCamcorderforNInstances====================== \n"); + + gint errorValue = -1; + gint failedInstances = 0; + gint outerLoopVariable = 0; + + for(outerLoopVariable = 0; outerLoopVariable < noOfInstances ; outerLoopVariable++) { + errorValue = mm_camcorder_stop(camcorderInstances[outerLoopVariable]); + if (MM_ERROR_NONE != errorValue) { + tet_printf("\n Failed in StopCamcorderforNInstances while stoping the camcorder with error %x (%d time) \n", errorValue, outerLoopVariable); + failedInstances++; + break; + } + + errorValue = mm_camcorder_unrealize(camcorderInstances[outerLoopVariable]); + if (MM_ERROR_NONE != errorValue) { + tet_printf("\n Failed in StopCamcorderforNInstances while unrealizing the camcorder with error %x (%d time) \n", errorValue, outerLoopVariable); + failedInstances++; + break; + } + + errorValue = mm_camcorder_destroy(camcorderInstances[outerLoopVariable]); + if ((MM_ERROR_NONE != errorValue) || (camcorderInstances[outerLoopVariable])) { + tet_printf("\n Failed in StopCamcorderforNInstances while destroying the camcorder with error %x (%d time) but mm_camcorder_create API was passed \n", errorValue, outerLoopVariable); + failedInstances++; + break; + } + } + + if(0 != failedInstances) { + tet_printf("\n Failed in StopCamcorderforNInstances, Number of Instances failed %d \n", failedInstances); + return false; + } + + tet_printf("\n In StopCamcorderforNInstances: All instances were stopped \n"); + + return true; +} +//////////////////////////////////////////////////////////////////////////////////////////////////////////////// +gboolean SetDefaultAttributes(MMHandleType camcorder, gint mode) +{ + tet_printf("\n ======================Setting Default Attributes====================== \n"); + + if(0 == camcorder) { + tet_printf(" \n Failed in SetDefaultAttributes: Camcorder not yet created \n"); + return false; + } + + //MMHandleType attrsHandle =0; + char* err_attr_name = (char*)malloc(50); + int errorValue = -1; + + /*================================================================================ + Image mode + *=================================================================================*/ + if (IMAGE_MODE == mode) + { + errorValue = mm_camcorder_set_attributes(camcorder, &err_attr_name, + MMCAM_MODE, MM_CAMCORDER_MODE_IMAGE, + MMCAM_CAMERA_WIDTH, 320, + MMCAM_CAMERA_HEIGHT, 240, + MMCAM_CAMERA_FORMAT, MM_PIXEL_FORMAT_YUYV, + MMCAM_IMAGE_ENCODER, MM_IMAGE_CODEC_JPEG, + MMCAM_IMAGE_ENCODER_QUALITY, IMAGE_ENC_QUALITY, + MMCAM_DISPLAY_DEVICE, MM_DISPLAY_DEVICE_MAINLCD, + MMCAM_DISPLAY_SURFACE, MM_DISPLAY_SURFACE_X, + MMCAM_DISPLAY_ROTATION, MM_DISPLAY_ROTATION_270, + MMCAM_CAPTURE_WIDTH, SRC_W_320, + MMCAM_CAPTURE_HEIGHT, SRC_H_240, + MMCAM_CAPTURE_COUNT, IMAGE_CAPTURE_COUNT_STILL, + NULL ); + + if (errorValue != MM_ERROR_NONE) { + tet_printf("\n Failed in mm_camcorder_set_attributes in image mode. attr_name[%s]\n", err_attr_name); + free( err_attr_name ); + err_attr_name = NULL; + return false; + } + } + /*================================================================================ + video mode + *=================================================================================*/ + else if (VIDEO_MODE == mode) + { + errorValue = mm_camcorder_set_attributes( camcorder, &err_attr_name, + MMCAM_CAMERA_WIDTH, SRC_W_320, + MMCAM_CAMERA_HEIGHT, SRC_H_240, + MMCAM_CAMERA_FORMAT, MM_PIXEL_FORMAT_NV12, + MMCAM_CAMERA_FPS, SRC_VIDEO_FRAME_RATE_30, + MMCAM_MODE, MM_CAMCORDER_MODE_VIDEO, + MMCAM_AUDIO_DEVICE, MM_AUDIO_DEVICE_MIC, + MMCAM_AUDIO_ENCODER, MM_AUDIO_CODEC_AMR, + MMCAM_VIDEO_ENCODER, MM_VIDEO_CODEC_H264, + MMCAM_FILE_FORMAT, MM_FILE_FORMAT_3GP, + MMCAM_AUDIO_SAMPLERATE, AUDIO_SOURCE_SAMPLERATE, + MMCAM_AUDIO_FORMAT, AUDIO_SOURCE_FORMAT, + MMCAM_AUDIO_CHANNEL, AUDIO_SOURCE_CHANNEL, + "audio-input-route", MM_AUDIOROUTE_CAPTURE_NORMAL, + "audio-encoder-bitrate", AUDIO_SOURCE_SAMPLERATE, + MMCAM_DISPLAY_DEVICE, MM_DISPLAY_DEVICE_MAINLCD, + MMCAM_DISPLAY_SURFACE, MM_DISPLAY_SURFACE_X, + MMCAM_TARGET_FILENAME, TARGET_FILENAME, TARGET_FILENAME_LENGTH, + //MM_CAMCORDER_DISPLAY_ROTATION, DISPLAY_ROTATION, + NULL ); + + tet_printf("\n Setting MM_CAMCORDER_DISPLAY_HANDLE \n"); + + if (errorValue != MM_ERROR_NONE) { + tet_printf( "\n Failed in mm_camcorder_set_attributes in video mode. attr_name[%s]\n", err_attr_name ); + free( err_attr_name ); + err_attr_name = NULL; + return false; + } + } + /*================================================================================ + Audio mode + *=================================================================================*/ + else if (AUDIO_MODE == mode) + { + errorValue = mm_camcorder_set_attributes( camcorder, &err_attr_name, MMCAM_MODE, MM_CAMCORDER_MODE_AUDIO, + MMCAM_AUDIO_DEVICE, MM_AUDIO_DEVICE_MIC, + MMCAM_AUDIO_ENCODER, MM_AUDIO_CODEC_AMR, + MMCAM_FILE_FORMAT, MM_FILE_FORMAT_3GP, + MMCAM_AUDIO_SAMPLERATE, AUDIO_SOURCE_SAMPLERATE, + MMCAM_AUDIO_FORMAT, AUDIO_SOURCE_FORMAT, + MMCAM_AUDIO_CHANNEL, AUDIO_SOURCE_CHANNEL, + MMCAM_AUDIO_VOLUME, AUDIO_SOURCE_VOLUME, + MMCAM_AUDIO_ENCODER_BITRATE, MM_CAMCORDER_MR59, + MMCAM_TARGET_FILENAME, TARGET_FILENAME, TARGET_FILENAME_LENGTH, + NULL ); + + if (errorValue != MM_ERROR_NONE) { + tet_printf( "\n Failed in mm_camcorder_set_attributes in audio mode. attr_name[%s]\n", err_attr_name ); + free( err_attr_name ); + err_attr_name = NULL; + return false; + } + } + + free(err_attr_name); + err_attr_name = NULL; + + return true; +} +//////////////////////////////////////////////////////////////////////////////////////////////////////////////// +gboolean GetDefaultAttributes(MMHandleType camcorder, gint mode) +{ + tet_printf("\n ======================Getting Default Attributes====================== \n"); + + if(0 == camcorder) { + tet_printf(" \n Failed in GetDefaultAttributes: Camcorder not yet created \n"); + return false; + } + + //MMHandleType attrsHandle = 0; + int attrsValue = -1; + char *stringAttrsValue = TARGET_FILENAME; + int filenameLength = TARGET_FILENAME_LENGTH; + int errorValue = -1; + char* err_attr_name = (char*)malloc(50); + + /*================================================================================ + Image mode + *=================================================================================*/ + if (IMAGE_MODE == mode) + { + /* profile attribute */ + errorValue = mm_camcorder_get_attributes(camcorder, &err_attr_name, MMCAM_MODE, &attrsValue, NULL); + if ((errorValue < 0) || (attrsValue != MM_CAMCORDER_MODE_IMAGE)) { + tet_printf("\n Failed in GetDefaultAttributes in image mode while getting profile mode attribute \n"); + return false; + } + + errorValue = mm_camcorder_get_attributes(camcorder, &err_attr_name, MMCAM_CAMERA_DEVICE, &attrsValue, NULL); + if ((errorValue < 0) || (attrsValue != MM_VIDEO_DEVICE_CAMERA0)) { + tet_printf("\n Failed in GetDefaultAttributes in image mode while getting profile video device attribute \n"); + return false; + } + + errorValue = mm_camcorder_get_attributes(camcorder, &err_attr_name, MMCAM_IMAGE_ENCODER, &attrsValue, NULL); + if ((errorValue < 0) || (attrsValue != MM_IMAGE_CODEC_JPEG)) { + tet_printf("\n Failed in GetDefaultAttributes in image mode while getting profile image codec attribute \n"); + return false; + } + /* image encoder attribute */ + errorValue = mm_camcorder_get_attributes(camcorder, &err_attr_name, MMCAM_IMAGE_ENCODER_QUALITY, &attrsValue, NULL); + if ((errorValue < 0) || (attrsValue != IMAGE_ENC_QUALITY)) { + tet_printf("\n Failed in GetDefaultAttributes in image mode while getting image encoder quality attribute \n"); + return false; + } + + /* display attribute */ + errorValue = mm_camcorder_get_attributes(camcorder, &err_attr_name, MMCAM_DISPLAY_SURFACE, &attrsValue, NULL); + if ((errorValue < 0) || (attrsValue != DISPLAY_ID)) { + tet_printf("\n Failed in GetDefaultAttributes in image mode while getting display ID attribute \n"); + return false; + } + + errorValue = mm_camcorder_get_attributes(camcorder, &err_attr_name, MMCAM_DISPLAY_ROTATION, &attrsValue, NULL); + if ((errorValue < 0) || (attrsValue != DISPLAY_ROTATION)) { + tet_printf("\n Failed in GetDefaultAttributes in image mode while getting display rotation attribute \n"); + return false; + } + + /* capture attribute */ + errorValue = mm_camcorder_get_attributes(camcorder, &err_attr_name, MMCAM_CAPTURE_WIDTH, &attrsValue, NULL); + if ((errorValue < 0) || (attrsValue != SRC_W_320)) { + tet_printf("\n Failed in GetDefaultAttributes in image mode while getting capture width attribute \n"); + return false; + } + + errorValue = mm_camcorder_get_attributes(camcorder, &err_attr_name, MMCAM_CAPTURE_HEIGHT, &attrsValue, NULL); + if ((errorValue < 0) || (attrsValue != SRC_H_240)) { + tet_printf("\n Failed in GetDefaultAttributes in image mode while getting capture height attribute \n"); + return false; + } + + errorValue = mm_camcorder_get_attributes(camcorder, &err_attr_name, MMCAM_CAPTURE_COUNT, &attrsValue, NULL); + if ((errorValue < 0) || (attrsValue != IMAGE_CAPTURE_COUNT_STILL)) { + tet_printf("\n Failed in GetDefaultAttributes in image mode while getting capture count attribute \n"); + return false; + } + } + /*================================================================================ + video mode + *=================================================================================*/ + else if (VIDEO_MODE == mode) + { + /* video source attribute */ + /* + errorValue = mm_camcorder_get_attributes(camcorder, MM_CAMCORDER_ATTR_VIDEO_SOURCE, &attrsHandle); + if(MM_ERROR_NONE != errorValue) { + tet_printf("\n Failed in GetDefaultAttributes while getting the camcorder video mode video source attributes \n"); + return false; + } + */ + + errorValue = mm_camcorder_get_attributes(camcorder, &err_attr_name, MMCAM_CAMERA_WIDTH, &attrsValue, NULL); + if ((errorValue < 0) || (attrsValue != SRC_W_320)) { + tet_printf("\n Failed in GetDefaultAttributes in video mode while getting video source width attribute \n"); + return false; + } + + errorValue = mm_camcorder_get_attributes(camcorder, &err_attr_name, MMCAM_CAMERA_HEIGHT, &attrsValue, NULL); + if ((errorValue < 0) || (attrsValue != SRC_H_240)) { + tet_printf("\n Failed in GetDefaultAttributes in video mode while getting video source height attribute \n"); + return false; + } + + errorValue = mm_camcorder_get_attributes(camcorder, &err_attr_name, MMCAM_CAMERA_FPS, &attrsValue, NULL); + if ((errorValue < 0) || (attrsValue != SRC_VIDEO_FRAME_RATE_30)) { + tet_printf("\n Failed in GetDefaultAttributes in video mode while getting video source frame rate attribute \n"); + return false; + } + /* profile attribute */ + errorValue = mm_camcorder_get_attributes(camcorder, &err_attr_name, MMCAM_MODE, &attrsValue, NULL); + if ((errorValue < 0) || (attrsValue != MM_CAMCORDER_MODE_VIDEO)) { + tet_printf("\n Failed in GetDefaultAttributes in video mode while getting video mode attribute \n"); + return false; + } + + errorValue = mm_camcorder_get_attributes(camcorder, &err_attr_name, MMCAM_AUDIO_DEVICE, &attrsValue, NULL); + if ((errorValue < 0) || (attrsValue != MM_AUDIO_DEVICE_MIC)) { + tet_printf("\n Failed in GetDefaultAttributes in video mode while getting audio device attribute \n"); + return false; + } + + errorValue = mm_camcorder_get_attributes(camcorder, &err_attr_name, MMCAM_CAMERA_DEVICE, &attrsValue, NULL); + if ((errorValue < 0) || (attrsValue != MM_VIDEO_DEVICE_CAMERA0)) { + tet_printf("\n Failed in GetDefaultAttributes in video mode while getting video device attribute \n"); + return false; + } + + errorValue = mm_camcorder_get_attributes(camcorder, &err_attr_name, MMCAM_AUDIO_ENCODER, &attrsValue, NULL); + if ((errorValue < 0) || (attrsValue != MM_AUDIO_CODEC_AMR)) { + tet_printf("\n Failed in GetDefaultAttributes in video mode while getting audio codec attribute \n"); + return false; + } + + errorValue = mm_camcorder_get_attributes(camcorder, &err_attr_name, MMCAM_VIDEO_ENCODER, &attrsValue, NULL); + if ((errorValue < 0) || (attrsValue != MM_VIDEO_CODEC_MPEG4)) { + tet_printf("\n Failed in GetDefaultAttributes in video mode while getting video codec attribute \n"); + return false; + } + + errorValue = mm_camcorder_get_attributes(camcorder, &err_attr_name, MMCAM_FILE_FORMAT, &attrsValue, NULL); + if ((errorValue < 0) || (attrsValue != MM_FILE_FORMAT_3GP)) { + tet_printf("\n Failed in GetDefaultAttributes in video mode while getting video file format attribute \n"); + return false; + } + + /* audio source attribute setting */ + errorValue = mm_camcorder_get_attributes(camcorder, &err_attr_name, MMCAM_AUDIO_SAMPLERATE, &attrsValue, NULL); + if ((errorValue < 0) || (attrsValue != AUDIO_SOURCE_SAMPLERATE)) { + tet_printf("\n Failed in GetDefaultAttributes in video mode while getting audio sample rate attribute \n"); + return false; + } + + errorValue = mm_camcorder_get_attributes(camcorder, &err_attr_name, MMCAM_AUDIO_FORMAT, &attrsValue, NULL); + if ((errorValue < 0) || (attrsValue != AUDIO_SOURCE_FORMAT)) { + tet_printf("\n Failed in GetDefaultAttributes in video mode while getting audio source format attribute \n"); + return false; + } + + errorValue = mm_camcorder_get_attributes(camcorder, &err_attr_name, MMCAM_AUDIO_CHANNEL, &attrsValue, NULL); + if ((errorValue < 0) || (attrsValue != AUDIO_SOURCE_CHANNEL)) { + tet_printf("\n Failed in GetDefaultAttributes in video mode while getting audio source channel attribute \n"); + return false; + } + /* display attribute */ + + errorValue = mm_camcorder_get_attributes(camcorder, &err_attr_name, MMCAM_DISPLAY_SURFACE, &attrsValue, NULL); + if ((errorValue < 0) || (attrsValue != DISPLAY_ID)) { + tet_printf("\n Failed in GetDefaultAttributes in video mode while getting display ID attribute \n"); + return false; + } + + /* capture attribute */ + errorValue = mm_camcorder_get_attributes(camcorder, &err_attr_name, MMCAM_CAPTURE_WIDTH, &attrsValue, NULL); + if ((errorValue < 0) || (attrsValue != SRC_W_320)) { + tet_printf("\n Failed in GetDefaultAttributes in video mode while getting capture width attribute \n"); + return false; + } + + errorValue = mm_camcorder_get_attributes(camcorder, &err_attr_name, MMCAM_CAPTURE_HEIGHT, &attrsValue, NULL); + if ((errorValue < 0) || (attrsValue != SRC_H_240)) { + tet_printf("\n Failed in GetDefaultAttributes in video mode while getting capture height attribute \n"); + return false; + } + /* target attribute setting */ + errorValue = mm_camcorder_get_attributes(camcorder, &err_attr_name, MMCAM_TARGET_FILENAME, &stringAttrsValue, &filenameLength, NULL); + if ((errorValue < 0) || (stringAttrsValue != NULL)) { //Kishor: string comparison required between stringAttrsValue and TARGET_FILENAME + tet_printf("\n Failed in GetDefaultAttributes in video mode while getting target filename attribute \n"); + return false; + } + } + /*================================================================================ + Audio mode + *=================================================================================*/ + else if (AUDIO_MODE == mode) + { + /* profile attribute */ + errorValue = mm_camcorder_get_attributes(camcorder, &err_attr_name, MMCAM_MODE, &attrsValue, NULL); + if ((errorValue < 0) || (attrsValue != MM_CAMCORDER_MODE_AUDIO)) { + tet_printf("\n Failed in GetDefaultAttributes in audio mode while getting audio mode attribute \n"); + return false; + } + + errorValue = mm_camcorder_get_attributes(camcorder, &err_attr_name, MMCAM_AUDIO_DEVICE, &attrsValue, NULL); + if ((errorValue < 0) || (attrsValue != MM_AUDIO_DEVICE_MIC)) { + tet_printf("\n Failed in GetDefaultAttributes in audio mode while getting audio device attribute \n"); + return false; + } + + errorValue = mm_camcorder_get_attributes(camcorder, &err_attr_name, MMCAM_AUDIO_ENCODER, &attrsValue, NULL); + if ((errorValue < 0) || (attrsValue != MM_AUDIO_CODEC_AMR)) { + tet_printf("\n Failed in GetDefaultAttributes in audio mode while getting audio codec attribute \n"); + return false; + } + + errorValue = mm_camcorder_get_attributes(camcorder, &err_attr_name, MMCAM_FILE_FORMAT, &attrsValue, NULL); + if ((errorValue < 0) || (attrsValue != MM_FILE_FORMAT_3GP)) { + tet_printf("\n Failed in GetDefaultAttributes in audio mode while getting audio file format attribute \n"); + return false; + } + + /* audio source attribute */ + errorValue = mm_camcorder_get_attributes(camcorder, &err_attr_name, MMCAM_AUDIO_SAMPLERATE, &attrsValue, NULL); + if ((errorValue < 0) || (attrsValue != AUDIO_SOURCE_SAMPLERATE)) { + tet_printf("\n Failed in GetDefaultAttributes in audio mode while getting audio sample rate attribute \n"); + return false; + } + + errorValue = mm_camcorder_get_attributes(camcorder, &err_attr_name, MMCAM_AUDIO_FORMAT, &attrsValue, NULL); + if ((errorValue < 0) || (attrsValue != AUDIO_SOURCE_FORMAT)) { + tet_printf("\n Failed in GetDefaultAttributes in audio mode while getting audio source format attribute \n"); + return false; + } + + errorValue = mm_camcorder_get_attributes(camcorder, &err_attr_name, MMCAM_AUDIO_CHANNEL, &attrsValue, NULL); + if ((errorValue < 0) || (attrsValue != AUDIO_SOURCE_CHANNEL)) { + tet_printf("\n Failed in GetDefaultAttributes in audio mode while getting audio source channel attribute \n"); + return false; + } + + errorValue = mm_camcorder_get_attributes(camcorder, &err_attr_name, MMCAM_AUDIO_VOLUME, &attrsValue, NULL); + if ((errorValue < 0) || (attrsValue != AUDIO_SOURCE_VOLUME)) { + tet_printf("\n Failed in GetDefaultAttributes in audio mode while getting audio encoder bitrate attribute \n"); + return false; + } + /* audio encoder attribute */ + errorValue = mm_camcorder_get_attributes(camcorder, &err_attr_name, MMCAM_VIDEO_ENCODER_BITRATE, &attrsValue, NULL); + if ((errorValue < 0) || (attrsValue != MM_CAMCORDER_MR59)) { + tet_printf("\n Failed in GetDefaultAttributes in audio mode while getting audio sample rate attribute \n"); + return false; + } + /* target attribute */ + errorValue = mm_camcorder_get_attributes(camcorder, &err_attr_name, MMCAM_TARGET_FILENAME, &stringAttrsValue, &filenameLength, NULL); + if ((errorValue < 0) || (stringAttrsValue != NULL)) { //Kishor: string comparison required between stringAttrsValue and TARGET_FILENAME + tet_printf("\n Failed in GetDefaultAttributes in audio mode while getting target filename attribute \n"); + return false; + } + } + + free(err_attr_name); + err_attr_name = NULL; + + return true; +} +//////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool FilenameCallbackFunctionCalledByCamcorder(int format, char *filename, void *user_param) +{ + CAMCORDER_RETURN_IF_FAIL(filename, FALSE); + CAMCORDER_RETURN_IF_FAIL(user_param, FALSE); + + //MMHandleType attrsHandle; + char *newFilename = NULL, *previousFilename = NULL; + int errorValue; + int filenameLength = TARGET_FILENAME_LENGTH; + char* err_attr_name = (char*)malloc(50); + + camcorder_callback_parameters *userParamFromCamcorder = (camcorder_callback_parameters *)user_param; + switch (format) { + case MM_FILE_FORMAT_JPG: + /* target attribute */ + /* + errorValue = mm_camcorder_get_attributes(userParamFromCamcorder->camcorder, MM_CAMCORDER_ATTR_TARGET, &attrsHandle, NULL); + if(errorValue != MM_ERROR_NONE) { + tet_printf("\n Failed in CallbackFunctionCalledByCamcorder while getting attributes for the camcorder with JPG format \n"); + return FALSE; + } + */ + + errorValue = mm_camcorder_get_attributes(userParamFromCamcorder->camcorder, &err_attr_name, MMCAM_TARGET_FILENAME, &previousFilename, &filenameLength, NULL); + newFilename = (char *)malloc(CAPTURE_FILENAME_LEN); + if (!newFilename) { + tet_printf("\n Failed in CallbackFunctionCalledByCamcorder while allocating memory for new file in the camcorder with JPG format \n"); + return FALSE; + } + memset(newFilename, '\0', CAPTURE_FILENAME_LEN); //Kishor :: needs to check the error + if (userParamFromCamcorder->isMultishot) { + sprintf(newFilename, "%s%03d.jpg", userParamFromCamcorder->multishot_filename, userParamFromCamcorder->multishot_count++); + } + else { + sprintf(newFilename, "%s%03d.jpg", userParamFromCamcorder->stillshot_filename, userParamFromCamcorder->stillshot_count++); + } + errorValue = mm_camcorder_set_attributes(userParamFromCamcorder->camcorder, &err_attr_name, MMCAM_TARGET_FILENAME, newFilename, sizeof(newFilename), NULL); + if(errorValue < 0) { + tet_printf("\n Failed in CallbackFunctionCalledByCamcorder while setting the string attribute for the camcorder with JPG format \n"); + return FALSE; + } + + //Kishor :: free previous filename space + if (previousFilename) { + free(previousFilename); + } + break; + case MM_FILE_FORMAT_3GP: + /* target attribute setting */ + errorValue = mm_camcorder_get_attributes(userParamFromCamcorder->camcorder, &err_attr_name, MMCAM_TARGET_FILENAME, &previousFilename, &filenameLength, NULL); + newFilename = (char *)malloc(CAPTURE_FILENAME_LEN); + if (!newFilename) { + tet_printf("\n Failed in CallbackFunctionCalledByCamcorder while allocating memory for new file in the camcorder with 3GP format \n"); + return FALSE; + } + memset(newFilename, '\0', CAPTURE_FILENAME_LEN); //Kishor :: needs to check the error + if (userParamFromCamcorder->isMultishot) { + sprintf(newFilename, "%s%03d.3gp", userParamFromCamcorder->multishot_filename, userParamFromCamcorder->multishot_count++); + } + else { + sprintf(newFilename, "%s%03d.3gp", userParamFromCamcorder->stillshot_filename, userParamFromCamcorder->stillshot_count++); //recorder team check + } + + errorValue = mm_camcorder_set_attributes(userParamFromCamcorder->camcorder, &err_attr_name, MMCAM_TARGET_FILENAME, newFilename, sizeof(newFilename), NULL); + if(errorValue < 0) { + tet_printf("\n Failed in CallbackFunctionCalledByCamcorder while setting the string attribute for the camcorder with 3GP format \n"); + return FALSE; + } + + //Kishor :: free previous filename space + if (previousFilename) { + free(previousFilename); + } + break; + case MM_FILE_FORMAT_MP4: + /* target attribute setting */ + errorValue = mm_camcorder_get_attributes(userParamFromCamcorder->camcorder, &err_attr_name, MMCAM_TARGET_FILENAME, &previousFilename, &filenameLength, NULL); + newFilename = (char *)malloc(CAPTURE_FILENAME_LEN); + if (!newFilename) { + tet_printf("\n Failed in CallbackFunctionCalledByCamcorder while allocating memory for new file in the camcorder with MP4 format \n"); + return FALSE; + } + memset(newFilename, '\0', CAPTURE_FILENAME_LEN); //Kishor :: needs to check the error + if (userParamFromCamcorder->isMultishot) { + sprintf(newFilename, "%s%03d.mp4", userParamFromCamcorder->multishot_filename, userParamFromCamcorder->multishot_count++); + } + else { + sprintf(newFilename, "%s%03d.mp4", userParamFromCamcorder->stillshot_filename, userParamFromCamcorder->stillshot_count++); //recorder team check + } + errorValue = mm_camcorder_set_attributes(userParamFromCamcorder->camcorder, &err_attr_name, MMCAM_TARGET_FILENAME, newFilename, sizeof(newFilename), NULL); + if(errorValue < 0) { + tet_printf("\n Failed in CallbackFunctionCalledByCamcorder while setting the string attribute for the camcorder with MP4 format \n"); + return FALSE; + } + + //Kishor :: free previous filename space + if (previousFilename) { + free(previousFilename); + } + break; + default: + g_assert_not_reached(); + break; + } + + CAMCORDER_RETURN_IF_FAIL(newFilename, FALSE); + strcpy(filename, newFilename); + if (newFilename) { + free(newFilename); + } + newFilename = NULL; + + return TRUE; +} +//////////////////////////////////////////////////////////////////////////////////////////////////////////////// +int MessageCallbackFunctionCalledByCamcorder(int message, void *msg_param, void *user_param) +{ + CAMCORDER_RETURN_IF_FAIL(msg_param, FALSE); + CAMCORDER_RETURN_IF_FAIL(user_param, FALSE); + + MMMessageParamType *messageFromCamcorder = (MMMessageParamType*) msg_param; + //camcorder_callback_parameters *userParamFromCamcorder = (camcorder_callback_parameters *)user_param; + int camcorderState = -1; + //MMCamStillshotReport *stillshotReport = NULL; + switch (message) { + case MM_MESSAGE_CAMCORDER_ERROR: + tet_printf("\n In MessageCallbackFunctionCalledByCamcorder with MM_MESSAGE_CAMCORDER_ERROR \n"); + break; + case MM_MESSAGE_CAMCORDER_STATE_CHANGED: + camcorderState = messageFromCamcorder->state.current; + switch(camcorderState) { + case MM_CAMCORDER_STATE_NULL: + tet_printf("[CamcorderApp] Camcorder State is NULL \n"); + break; + case MM_CAMCORDER_STATE_READY: + tet_printf("[CamcorderApp] Camcorder State is READY \n"); + break; + case MM_CAMCORDER_STATE_PREPARE: + tet_printf("[CamcorderApp] Camcorder State is PREPARE \n"); + break; + case MM_CAMCORDER_STATE_CAPTURING: + tet_printf("[CamcorderApp] Camcorder State is CAPTURING \n"); + break; + case MM_CAMCORDER_STATE_RECORDING: + tet_printf("[CamcorderApp] Camcorder State is RECORDING \n"); + break; + case MM_CAMCORDER_STATE_PAUSED: + tet_printf("[CamcorderApp] Camcorder State is PAUSED \n"); + break; + default: + tet_printf("[CamcorderApp] Camcorder State is Unknown \n"); + break; + } + break; + case MM_MESSAGE_CAMCORDER_CAPTURED: + /* + stillshotReport = (MMCamStillshotReport*)(messageFromCamcorder->data); + if (!stillshotReport) { + tet_printf("\n Failed in MessageCallbackFunctionCalledByCamcorder while retriving mmcam_stillshot_report \n"); + return FALSE; + } + if (userParamFromCamcorder->isMultishot) { + tet_printf("[CamcorderApp] Camcorder Captured(filename=%s) \n", stillshotReport->stillshot_filename); + if (stillshotReport->stillshot_no >= IMAGE_CAPTURE_COUNT_MULTI) { + userParamFromCamcorder->isMultishot = FALSE; + } + } + if (stillshotReport->stillshot_filename) { + free(stillshotReport->stillshot_filename); + } + stillshotReport->stillshot_filename = NULL; + if (stillshotReport) { + free(stillshotReport); + } + stillshotReport = NULL; + */ + break; + default: + tet_printf("\n In MessageCallbackFunctionCalledByCamcorder with message as default \n"); + break; + } + return TRUE; +} +//////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool VideoStreamCallbackFunctionCalledByCamcorder(void *stream, int width, int height, void *user_param) +{ + tet_printf("\n In VideoStreamCallbackFunctionCalledByCamcorder \n"); + return true; +} +//////////////////////////////////////////////////////////////////////////////////////////////////////////////// +bool VideoCaptureCallbackFunctionCalledByCamcorder(MMCamcorderCaptureDataType *frame, MMCamcorderCaptureDataType *thumbnail, void *user_param) +{ + tet_printf("\n In VideoCaptureCallbackFunctionCalledByCamcorder \n"); + return true; +} diff --git a/TC/utc/uts_mm_camcorder_utils.h b/TC/utc/uts_mm_camcorder_utils.h new file mode 100644 index 0000000..1a2368b --- /dev/null +++ b/TC/utc/uts_mm_camcorder_utils.h @@ -0,0 +1,159 @@ +/* + * libmm-camcorder TC + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Jeongmo Yang + * + * 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 UTS_MM_CAMCORDER_UTILS_H +#define UTS_MM_CAMCORDER_UTILS_H + +#define _MMCAMCORDER_ENABLE_CAMPROC + +#include +#include +#include +#include +#include +#include +#include + +/** test case startup function */ +void Startup(); +/** test case clean up function */ +void Cleanup(); + +enum { + IMAGE_MODE = MM_CAMCORDER_MODE_IMAGE, + VIDEO_MODE = MM_CAMCORDER_MODE_VIDEO, + AUDIO_MODE = MM_CAMCORDER_MODE_AUDIO, +}; + +// 2M +#define SRC_W_1600 1600 +#define SRC_H_1200 1200 + +//VGA +#define SRC_W_640 640 +#define SRC_H_480 480 + +//QVGA +#define SRC_W_320 320 // video input width +#define SRC_H_240 240 // video input height + +//QCIF +#define SRC_W_176 176 // video input width +#define SRC_H_144 144 // video input height + +//QQVGA +#define SRC_W_160 160 // video input width +#define SRC_H_120 120 // video input heith + +//special resolution +#define SRC_W_400 400 // video input width +#define SRC_H_300 300 // video input height + +#define SRC_W_192 192 // video input width +#define SRC_H_256 256 // video input height + +#define SRC_W_144 144 // video input width +#define SRC_H_176 176 // video input height + +#define SRC_W_300 300 +#define SRC_W_400 400 + + +#define DISPLAY_X_0 0 //for direct FB +#define DISPLAY_Y_0 0 //for direct FB + +#define DISPLAY_W_320 320 //for direct FB +#define DISPLAY_H_240 240 //for direct FB +#define DISPLAY_W_640 640 +#define DISPLAY_H_480 480 +#define DISPLAY_ROTATION 0 + +#define MM_CAMCORDER_MR59 59 + +#ifdef __arm__ +#define AUDIO_SOURCE_CHANNEL 2 +#else +#define AUDIO_SOURCE_CHANNEL 1 +#endif + +#define AUDIO_SOURCE_SAMPLERATE 8000 +#define AUDIO_SOURCE_FORMAT MM_CAMCORDER_AUDIO_FORMAT_PCM_S16_LE +#define TARGET_FILENAME "/opt/media/.tc_tmp" +#define TARGET_FILENAME_LENGTH (sizeof(TARGET_FILENAME)+1) +#define AUDIO_SOURCE_VOLUME 1 + +#define DISPLAY_ID MM_DISPLAY_SURFACE_X + +#define SRC_VIDEO_FRAME_RATE_15 15 +#define SRC_VIDEO_FRAME_RATE_30 30 +#define IMAGE_ENC_QUALITY 85 +#define IMAGE_CAPTURE_COUNT_STILL 1 +#define IMAGE_CAPTURE_COUNT_MULTI 3 +#define IMAGE_CAPTURE_COUNT_INTERVAL 1000 + +#define CAPTURE_FILENAME_LEN 256 + +#define CAMCORDER_RETURN_IF_FAIL(expr, val) \ + if(expr) { \ + } \ + else { \ + return (val); \ + }; + +typedef struct _camcorder_callback_parameters +{ + MMHandleType camcorder; + int mode; /* image(capture)/video(recording) mode */ +// int flip_mode; + bool isMultishot; + int stillshot_count; /* total stillshot count */ + int multishot_count; /* total multishot count */ + char *stillshot_filename; /* stored filename of stillshot */ + char *multishot_filename; /* stored filename of multishot */ +// int g_current_state; +// int src_w, src_h; +// GstCaps *filtercaps; + +}camcorder_callback_parameters; + +#define STRESS 3 //This is for stress testing. + +extern camcorder_callback_parameters *gCamcorderCallbackParameters ; +extern camcorder_callback_parameters *gCamcorderCallbackParametersArray[STRESS] ; + +gboolean CreateCamcorder(MMHandleType* camcorder, MMCamPreset* pInfo); +gboolean DestroyCamcorder(MMHandleType camcorder); + +gboolean StartCamcorder(MMHandleType* camcorder, MMCamPreset* pInfo,gint mode); +gboolean StopCamcorder(MMHandleType camcorder); + +gboolean StartCamcorderforNInstances(MMHandleType camcorderInstances[], gint noOfInstances); +gboolean StopCamcorderforNInstances(MMHandleType camcorderInstances[], gint noOfInstances); + +gboolean SetDefaultAttributes(MMHandleType camcorder, gint mode); +gboolean GetDefaultAttributes(MMHandleType camcorder, gint mode); + +int MessageCallbackFunctionCalledByCamcorder(int message, void *msg_param, void *user_param); +bool FilenameCallbackFunctionCalledByCamcorder(int format, char *filename, void *user_param); +bool VideoStreamCallbackFunctionCalledByCamcorder(void *stream, int width, int height, void *user_param); +bool VideoCaptureCallbackFunctionCalledByCamcorder(MMCamcorderCaptureDataType *frame, MMCamcorderCaptureDataType *thumbnail, void *user_param); + +#endif /* UTS_MM_CAMCORDER_UTILS_H */ diff --git a/autogen.sh b/autogen.sh new file mode 100755 index 0000000..2f43082 --- /dev/null +++ b/autogen.sh @@ -0,0 +1,7 @@ +#! /bin/sh + +libtoolize --copy --force +aclocal -I m4 +autoheader +autoconf +automake -a -c diff --git a/config.guess b/config.guess new file mode 100755 index 0000000..40eaed4 --- /dev/null +++ b/config.guess @@ -0,0 +1,1517 @@ +#! /bin/sh +# Attempt to guess a canonical system name. +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, +# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, +# 2011 Free Software Foundation, Inc. + +timestamp='2011-05-11' + +# This file is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA +# 02110-1301, USA. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + + +# Originally written by Per Bothner. Please send patches (context +# diff format) to and include a ChangeLog +# entry. +# +# This script attempts to guess a canonical system name similar to +# config.sub. If it succeeds, it prints the system name on stdout, and +# exits with 0. Otherwise, it exits with 1. +# +# You can get the latest version of this script from: +# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] + +Output the configuration name of the system \`$me' is run on. + +Operation modes: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to ." + +version="\ +GNU config.guess ($timestamp) + +Originally written by Per Bothner. +Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, +2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free +Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit ;; + --version | -v ) + echo "$version" ; exit ;; + --help | --h* | -h ) + echo "$usage"; exit ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" >&2 + exit 1 ;; + * ) + break ;; + esac +done + +if test $# != 0; then + echo "$me: too many arguments$help" >&2 + exit 1 +fi + +trap 'exit 1' 1 2 15 + +# CC_FOR_BUILD -- compiler used by this script. Note that the use of a +# compiler to aid in system detection is discouraged as it requires +# temporary files to be created and, as you can see below, it is a +# headache to deal with in a portable fashion. + +# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still +# use `HOST_CC' if defined, but it is deprecated. + +# Portable tmp directory creation inspired by the Autoconf team. + +set_cc_for_build=' +trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ; +trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ; +: ${TMPDIR=/tmp} ; + { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || + { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } || + { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } || + { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ; +dummy=$tmp/dummy ; +tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ; +case $CC_FOR_BUILD,$HOST_CC,$CC in + ,,) echo "int x;" > $dummy.c ; + for c in cc gcc c89 c99 ; do + if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then + CC_FOR_BUILD="$c"; break ; + fi ; + done ; + if test x"$CC_FOR_BUILD" = x ; then + CC_FOR_BUILD=no_compiler_found ; + fi + ;; + ,,*) CC_FOR_BUILD=$CC ;; + ,*,*) CC_FOR_BUILD=$HOST_CC ;; +esac ; set_cc_for_build= ;' + +# This is needed to find uname on a Pyramid OSx when run in the BSD universe. +# (ghazi@noc.rutgers.edu 1994-08-24) +if (test -f /.attbin/uname) >/dev/null 2>&1 ; then + PATH=$PATH:/.attbin ; export PATH +fi + +UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown +UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown +UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown +UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown + +# Note: order is significant - the case branches are not exclusive. + +case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in + *:NetBSD:*:*) + # NetBSD (nbsd) targets should (where applicable) match one or + # more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*, + # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently + # switched to ELF, *-*-netbsd* would select the old + # object file format. This provides both forward + # compatibility and a consistent mechanism for selecting the + # object file format. + # + # Note: NetBSD doesn't particularly care about the vendor + # portion of the name. We always set it to "unknown". + sysctl="sysctl -n hw.machine_arch" + UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \ + /usr/sbin/$sysctl 2>/dev/null || echo unknown)` + case "${UNAME_MACHINE_ARCH}" in + armeb) machine=armeb-unknown ;; + arm*) machine=arm-unknown ;; + sh3el) machine=shl-unknown ;; + sh3eb) machine=sh-unknown ;; + sh5el) machine=sh5le-unknown ;; + *) machine=${UNAME_MACHINE_ARCH}-unknown ;; + esac + # The Operating System including object format, if it has switched + # to ELF recently, or will in the future. + case "${UNAME_MACHINE_ARCH}" in + arm*|i386|m68k|ns32k|sh3*|sparc|vax) + eval $set_cc_for_build + if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ELF__ + then + # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). + # Return netbsd for either. FIX? + os=netbsd + else + os=netbsdelf + fi + ;; + *) + os=netbsd + ;; + esac + # The OS release + # Debian GNU/NetBSD machines have a different userland, and + # thus, need a distinct triplet. However, they do not need + # kernel version information, so it can be replaced with a + # suitable tag, in the style of linux-gnu. + case "${UNAME_VERSION}" in + Debian*) + release='-gnu' + ;; + *) + release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` + ;; + esac + # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: + # contains redundant information, the shorter form: + # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. + echo "${machine}-${os}${release}" + exit ;; + *:OpenBSD:*:*) + UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'` + echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE} + exit ;; + *:ekkoBSD:*:*) + echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE} + exit ;; + *:SolidBSD:*:*) + echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE} + exit ;; + macppc:MirBSD:*:*) + echo powerpc-unknown-mirbsd${UNAME_RELEASE} + exit ;; + *:MirBSD:*:*) + echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE} + exit ;; + alpha:OSF1:*:*) + case $UNAME_RELEASE in + *4.0) + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` + ;; + *5.*) + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'` + ;; + esac + # According to Compaq, /usr/sbin/psrinfo has been available on + # OSF/1 and Tru64 systems produced since 1995. I hope that + # covers most systems running today. This code pipes the CPU + # types through head -n 1, so we only detect the type of CPU 0. + ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1` + case "$ALPHA_CPU_TYPE" in + "EV4 (21064)") + UNAME_MACHINE="alpha" ;; + "EV4.5 (21064)") + UNAME_MACHINE="alpha" ;; + "LCA4 (21066/21068)") + UNAME_MACHINE="alpha" ;; + "EV5 (21164)") + UNAME_MACHINE="alphaev5" ;; + "EV5.6 (21164A)") + UNAME_MACHINE="alphaev56" ;; + "EV5.6 (21164PC)") + UNAME_MACHINE="alphapca56" ;; + "EV5.7 (21164PC)") + UNAME_MACHINE="alphapca57" ;; + "EV6 (21264)") + UNAME_MACHINE="alphaev6" ;; + "EV6.7 (21264A)") + UNAME_MACHINE="alphaev67" ;; + "EV6.8CB (21264C)") + UNAME_MACHINE="alphaev68" ;; + "EV6.8AL (21264B)") + UNAME_MACHINE="alphaev68" ;; + "EV6.8CX (21264D)") + UNAME_MACHINE="alphaev68" ;; + "EV6.9A (21264/EV69A)") + UNAME_MACHINE="alphaev69" ;; + "EV7 (21364)") + UNAME_MACHINE="alphaev7" ;; + "EV7.9 (21364A)") + UNAME_MACHINE="alphaev79" ;; + esac + # A Pn.n version is a patched version. + # A Vn.n version is a released version. + # A Tn.n version is a released field test version. + # A Xn.n version is an unreleased experimental baselevel. + # 1.2 uses "1.2" for uname -r. + echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + # Reset EXIT trap before exiting to avoid spurious non-zero exit code. + exitcode=$? + trap '' 0 + exit $exitcode ;; + Alpha\ *:Windows_NT*:*) + # How do we know it's Interix rather than the generic POSIX subsystem? + # Should we change UNAME_MACHINE based on the output of uname instead + # of the specific Alpha model? + echo alpha-pc-interix + exit ;; + 21064:Windows_NT:50:3) + echo alpha-dec-winnt3.5 + exit ;; + Amiga*:UNIX_System_V:4.0:*) + echo m68k-unknown-sysv4 + exit ;; + *:[Aa]miga[Oo][Ss]:*:*) + echo ${UNAME_MACHINE}-unknown-amigaos + exit ;; + *:[Mm]orph[Oo][Ss]:*:*) + echo ${UNAME_MACHINE}-unknown-morphos + exit ;; + *:OS/390:*:*) + echo i370-ibm-openedition + exit ;; + *:z/VM:*:*) + echo s390-ibm-zvmoe + exit ;; + *:OS400:*:*) + echo powerpc-ibm-os400 + exit ;; + arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) + echo arm-acorn-riscix${UNAME_RELEASE} + exit ;; + arm:riscos:*:*|arm:RISCOS:*:*) + echo arm-unknown-riscos + exit ;; + SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) + echo hppa1.1-hitachi-hiuxmpp + exit ;; + Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) + # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. + if test "`(/bin/universe) 2>/dev/null`" = att ; then + echo pyramid-pyramid-sysv3 + else + echo pyramid-pyramid-bsd + fi + exit ;; + NILE*:*:*:dcosx) + echo pyramid-pyramid-svr4 + exit ;; + DRS?6000:unix:4.0:6*) + echo sparc-icl-nx6 + exit ;; + DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*) + case `/usr/bin/uname -p` in + sparc) echo sparc-icl-nx7; exit ;; + esac ;; + s390x:SunOS:*:*) + echo ${UNAME_MACHINE}-ibm-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4H:SunOS:5.*:*) + echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) + echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*) + echo i386-pc-auroraux${UNAME_RELEASE} + exit ;; + i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*) + eval $set_cc_for_build + SUN_ARCH="i386" + # If there is a compiler, see if it is configured for 64-bit objects. + # Note that the Sun cc does not turn __LP64__ into 1 like gcc does. + # This test works for both compilers. + if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then + if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \ + (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_64BIT_ARCH >/dev/null + then + SUN_ARCH="x86_64" + fi + fi + echo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:6*:*) + # According to config.sub, this is the proper way to canonicalize + # SunOS6. Hard to guess exactly what SunOS6 will be like, but + # it's likely to be more like Solaris than SunOS4. + echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:*:*) + case "`/usr/bin/arch -k`" in + Series*|S4*) + UNAME_RELEASE=`uname -v` + ;; + esac + # Japanese Language versions have a version number like `4.1.3-JL'. + echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` + exit ;; + sun3*:SunOS:*:*) + echo m68k-sun-sunos${UNAME_RELEASE} + exit ;; + sun*:*:4.2BSD:*) + UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` + test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3 + case "`/bin/arch`" in + sun3) + echo m68k-sun-sunos${UNAME_RELEASE} + ;; + sun4) + echo sparc-sun-sunos${UNAME_RELEASE} + ;; + esac + exit ;; + aushp:SunOS:*:*) + echo sparc-auspex-sunos${UNAME_RELEASE} + exit ;; + # The situation for MiNT is a little confusing. The machine name + # can be virtually everything (everything which is not + # "atarist" or "atariste" at least should have a processor + # > m68000). The system name ranges from "MiNT" over "FreeMiNT" + # to the lowercase version "mint" (or "freemint"). Finally + # the system name "TOS" denotes a system which is actually not + # MiNT. But MiNT is downward compatible to TOS, so this should + # be no problem. + atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) + echo m68k-milan-mint${UNAME_RELEASE} + exit ;; + hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) + echo m68k-hades-mint${UNAME_RELEASE} + exit ;; + *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) + echo m68k-unknown-mint${UNAME_RELEASE} + exit ;; + m68k:machten:*:*) + echo m68k-apple-machten${UNAME_RELEASE} + exit ;; + powerpc:machten:*:*) + echo powerpc-apple-machten${UNAME_RELEASE} + exit ;; + RISC*:Mach:*:*) + echo mips-dec-mach_bsd4.3 + exit ;; + RISC*:ULTRIX:*:*) + echo mips-dec-ultrix${UNAME_RELEASE} + exit ;; + VAX*:ULTRIX*:*:*) + echo vax-dec-ultrix${UNAME_RELEASE} + exit ;; + 2020:CLIX:*:* | 2430:CLIX:*:*) + echo clipper-intergraph-clix${UNAME_RELEASE} + exit ;; + mips:*:*:UMIPS | mips:*:*:RISCos) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c +#ifdef __cplusplus +#include /* for printf() prototype */ + int main (int argc, char *argv[]) { +#else + int main (argc, argv) int argc; char *argv[]; { +#endif + #if defined (host_mips) && defined (MIPSEB) + #if defined (SYSTYPE_SYSV) + printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_SVR4) + printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) + printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0); + #endif + #endif + exit (-1); + } +EOF + $CC_FOR_BUILD -o $dummy $dummy.c && + dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` && + SYSTEM_NAME=`$dummy $dummyarg` && + { echo "$SYSTEM_NAME"; exit; } + echo mips-mips-riscos${UNAME_RELEASE} + exit ;; + Motorola:PowerMAX_OS:*:*) + echo powerpc-motorola-powermax + exit ;; + Motorola:*:4.3:PL8-*) + echo powerpc-harris-powermax + exit ;; + Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*) + echo powerpc-harris-powermax + exit ;; + Night_Hawk:Power_UNIX:*:*) + echo powerpc-harris-powerunix + exit ;; + m88k:CX/UX:7*:*) + echo m88k-harris-cxux7 + exit ;; + m88k:*:4*:R4*) + echo m88k-motorola-sysv4 + exit ;; + m88k:*:3*:R3*) + echo m88k-motorola-sysv3 + exit ;; + AViiON:dgux:*:*) + # DG/UX returns AViiON for all architectures + UNAME_PROCESSOR=`/usr/bin/uname -p` + if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ] + then + if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \ + [ ${TARGET_BINARY_INTERFACE}x = x ] + then + echo m88k-dg-dgux${UNAME_RELEASE} + else + echo m88k-dg-dguxbcs${UNAME_RELEASE} + fi + else + echo i586-dg-dgux${UNAME_RELEASE} + fi + exit ;; + M88*:DolphinOS:*:*) # DolphinOS (SVR3) + echo m88k-dolphin-sysv3 + exit ;; + M88*:*:R3*:*) + # Delta 88k system running SVR3 + echo m88k-motorola-sysv3 + exit ;; + XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) + echo m88k-tektronix-sysv3 + exit ;; + Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) + echo m68k-tektronix-bsd + exit ;; + *:IRIX*:*:*) + echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` + exit ;; + ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. + echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id + exit ;; # Note that: echo "'`uname -s`'" gives 'AIX ' + i*86:AIX:*:*) + echo i386-ibm-aix + exit ;; + ia64:AIX:*:*) + if [ -x /usr/bin/oslevel ] ; then + IBM_REV=`/usr/bin/oslevel` + else + IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + fi + echo ${UNAME_MACHINE}-ibm-aix${IBM_REV} + exit ;; + *:AIX:2:3) + if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include + + main() + { + if (!__power_pc()) + exit(1); + puts("powerpc-ibm-aix3.2.5"); + exit(0); + } +EOF + if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` + then + echo "$SYSTEM_NAME" + else + echo rs6000-ibm-aix3.2.5 + fi + elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then + echo rs6000-ibm-aix3.2.4 + else + echo rs6000-ibm-aix3.2 + fi + exit ;; + *:AIX:*:[4567]) + IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` + if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then + IBM_ARCH=rs6000 + else + IBM_ARCH=powerpc + fi + if [ -x /usr/bin/oslevel ] ; then + IBM_REV=`/usr/bin/oslevel` + else + IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + fi + echo ${IBM_ARCH}-ibm-aix${IBM_REV} + exit ;; + *:AIX:*:*) + echo rs6000-ibm-aix + exit ;; + ibmrt:4.4BSD:*|romp-ibm:BSD:*) + echo romp-ibm-bsd4.4 + exit ;; + ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and + echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to + exit ;; # report: romp-ibm BSD 4.3 + *:BOSX:*:*) + echo rs6000-bull-bosx + exit ;; + DPX/2?00:B.O.S.:*:*) + echo m68k-bull-sysv3 + exit ;; + 9000/[34]??:4.3bsd:1.*:*) + echo m68k-hp-bsd + exit ;; + hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) + echo m68k-hp-bsd4.4 + exit ;; + 9000/[34678]??:HP-UX:*:*) + HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` + case "${UNAME_MACHINE}" in + 9000/31? ) HP_ARCH=m68000 ;; + 9000/[34]?? ) HP_ARCH=m68k ;; + 9000/[678][0-9][0-9]) + if [ -x /usr/bin/getconf ]; then + sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` + sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` + case "${sc_cpu_version}" in + 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0 + 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1 + 532) # CPU_PA_RISC2_0 + case "${sc_kernel_bits}" in + 32) HP_ARCH="hppa2.0n" ;; + 64) HP_ARCH="hppa2.0w" ;; + '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20 + esac ;; + esac + fi + if [ "${HP_ARCH}" = "" ]; then + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + + #define _HPUX_SOURCE + #include + #include + + int main () + { + #if defined(_SC_KERNEL_BITS) + long bits = sysconf(_SC_KERNEL_BITS); + #endif + long cpu = sysconf (_SC_CPU_VERSION); + + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1"); break; + case CPU_PA_RISC2_0: + #if defined(_SC_KERNEL_BITS) + switch (bits) + { + case 64: puts ("hppa2.0w"); break; + case 32: puts ("hppa2.0n"); break; + default: puts ("hppa2.0"); break; + } break; + #else /* !defined(_SC_KERNEL_BITS) */ + puts ("hppa2.0"); break; + #endif + default: puts ("hppa1.0"); break; + } + exit (0); + } +EOF + (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy` + test -z "$HP_ARCH" && HP_ARCH=hppa + fi ;; + esac + if [ ${HP_ARCH} = "hppa2.0w" ] + then + eval $set_cc_for_build + + # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating + # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler + # generating 64-bit code. GNU and HP use different nomenclature: + # + # $ CC_FOR_BUILD=cc ./config.guess + # => hppa2.0w-hp-hpux11.23 + # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess + # => hppa64-hp-hpux11.23 + + if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | + grep -q __LP64__ + then + HP_ARCH="hppa2.0w" + else + HP_ARCH="hppa64" + fi + fi + echo ${HP_ARCH}-hp-hpux${HPUX_REV} + exit ;; + ia64:HP-UX:*:*) + HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` + echo ia64-hp-hpux${HPUX_REV} + exit ;; + 3050*:HI-UX:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include + int + main () + { + long cpu = sysconf (_SC_CPU_VERSION); + /* The order matters, because CPU_IS_HP_MC68K erroneously returns + true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct + results, however. */ + if (CPU_IS_PA_RISC (cpu)) + { + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; + case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; + default: puts ("hppa-hitachi-hiuxwe2"); break; + } + } + else if (CPU_IS_HP_MC68K (cpu)) + puts ("m68k-hitachi-hiuxwe2"); + else puts ("unknown-hitachi-hiuxwe2"); + exit (0); + } +EOF + $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` && + { echo "$SYSTEM_NAME"; exit; } + echo unknown-hitachi-hiuxwe2 + exit ;; + 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) + echo hppa1.1-hp-bsd + exit ;; + 9000/8??:4.3bsd:*:*) + echo hppa1.0-hp-bsd + exit ;; + *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) + echo hppa1.0-hp-mpeix + exit ;; + hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) + echo hppa1.1-hp-osf + exit ;; + hp8??:OSF1:*:*) + echo hppa1.0-hp-osf + exit ;; + i*86:OSF1:*:*) + if [ -x /usr/sbin/sysversion ] ; then + echo ${UNAME_MACHINE}-unknown-osf1mk + else + echo ${UNAME_MACHINE}-unknown-osf1 + fi + exit ;; + parisc*:Lites*:*:*) + echo hppa1.1-hp-lites + exit ;; + C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) + echo c1-convex-bsd + exit ;; + C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit ;; + C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) + echo c34-convex-bsd + exit ;; + C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) + echo c38-convex-bsd + exit ;; + C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) + echo c4-convex-bsd + exit ;; + CRAY*Y-MP:*:*:*) + echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*[A-Z]90:*:*:*) + echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ + | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ + -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ + -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*TS:*:*:*) + echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*T3E:*:*:*) + echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*SV1:*:*:*) + echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + *:UNICOS/mp:*:*) + echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) + FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` + echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit ;; + 5000:UNIX_System_V:4.*:*) + FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'` + echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit ;; + i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) + echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} + exit ;; + sparc*:BSD/OS:*:*) + echo sparc-unknown-bsdi${UNAME_RELEASE} + exit ;; + *:BSD/OS:*:*) + echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} + exit ;; + *:FreeBSD:*:*) + case ${UNAME_MACHINE} in + pc98) + echo i386-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + amd64) + echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + *) + echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + esac + exit ;; + i*:CYGWIN*:*) + echo ${UNAME_MACHINE}-pc-cygwin + exit ;; + *:MINGW*:*) + echo ${UNAME_MACHINE}-pc-mingw32 + exit ;; + i*:windows32*:*) + # uname -m includes "-pc" on this system. + echo ${UNAME_MACHINE}-mingw32 + exit ;; + i*:PW*:*) + echo ${UNAME_MACHINE}-pc-pw32 + exit ;; + *:Interix*:*) + case ${UNAME_MACHINE} in + x86) + echo i586-pc-interix${UNAME_RELEASE} + exit ;; + authenticamd | genuineintel | EM64T) + echo x86_64-unknown-interix${UNAME_RELEASE} + exit ;; + IA64) + echo ia64-unknown-interix${UNAME_RELEASE} + exit ;; + esac ;; + [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*) + echo i${UNAME_MACHINE}-pc-mks + exit ;; + 8664:Windows_NT:*) + echo x86_64-pc-mks + exit ;; + i*:Windows_NT*:* | Pentium*:Windows_NT*:*) + # How do we know it's Interix rather than the generic POSIX subsystem? + # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we + # UNAME_MACHINE based on the output of uname instead of i386? + echo i586-pc-interix + exit ;; + i*:UWIN*:*) + echo ${UNAME_MACHINE}-pc-uwin + exit ;; + amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*) + echo x86_64-unknown-cygwin + exit ;; + p*:CYGWIN*:*) + echo powerpcle-unknown-cygwin + exit ;; + prep*:SunOS:5.*:*) + echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + *:GNU:*:*) + # the GNU system + echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` + exit ;; + *:GNU/*:*:*) + # other systems with GNU libc and userland + echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-gnu + exit ;; + i*86:Minix:*:*) + echo ${UNAME_MACHINE}-pc-minix + exit ;; + alpha:Linux:*:*) + case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in + EV5) UNAME_MACHINE=alphaev5 ;; + EV56) UNAME_MACHINE=alphaev56 ;; + PCA56) UNAME_MACHINE=alphapca56 ;; + PCA57) UNAME_MACHINE=alphapca56 ;; + EV6) UNAME_MACHINE=alphaev6 ;; + EV67) UNAME_MACHINE=alphaev67 ;; + EV68*) UNAME_MACHINE=alphaev68 ;; + esac + objdump --private-headers /bin/sh | grep -q ld.so.1 + if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi + echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC} + exit ;; + arm*:Linux:*:*) + eval $set_cc_for_build + if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ARM_EABI__ + then + echo ${UNAME_MACHINE}-unknown-linux-gnu + else + if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ARM_PCS_VFP + then + echo ${UNAME_MACHINE}-unknown-linux-gnueabi + else + echo ${UNAME_MACHINE}-unknown-linux-gnueabihf + fi + fi + exit ;; + avr32*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + cris:Linux:*:*) + echo cris-axis-linux-gnu + exit ;; + crisv32:Linux:*:*) + echo crisv32-axis-linux-gnu + exit ;; + frv:Linux:*:*) + echo frv-unknown-linux-gnu + exit ;; + i*86:Linux:*:*) + LIBC=gnu + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #ifdef __dietlibc__ + LIBC=dietlibc + #endif +EOF + eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC'` + echo "${UNAME_MACHINE}-pc-linux-${LIBC}" + exit ;; + ia64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + m32r*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + m68*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + mips:Linux:*:* | mips64:Linux:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #undef CPU + #undef ${UNAME_MACHINE} + #undef ${UNAME_MACHINE}el + #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) + CPU=${UNAME_MACHINE}el + #else + #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) + CPU=${UNAME_MACHINE} + #else + CPU= + #endif + #endif +EOF + eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'` + test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; } + ;; + or32:Linux:*:*) + echo or32-unknown-linux-gnu + exit ;; + padre:Linux:*:*) + echo sparc-unknown-linux-gnu + exit ;; + parisc64:Linux:*:* | hppa64:Linux:*:*) + echo hppa64-unknown-linux-gnu + exit ;; + parisc:Linux:*:* | hppa:Linux:*:*) + # Look for CPU level + case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in + PA7*) echo hppa1.1-unknown-linux-gnu ;; + PA8*) echo hppa2.0-unknown-linux-gnu ;; + *) echo hppa-unknown-linux-gnu ;; + esac + exit ;; + ppc64:Linux:*:*) + echo powerpc64-unknown-linux-gnu + exit ;; + ppc:Linux:*:*) + echo powerpc-unknown-linux-gnu + exit ;; + s390:Linux:*:* | s390x:Linux:*:*) + echo ${UNAME_MACHINE}-ibm-linux + exit ;; + sh64*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + sh*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + sparc:Linux:*:* | sparc64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + tile*:Linux:*:*) + echo ${UNAME_MACHINE}-tilera-linux-gnu + exit ;; + vax:Linux:*:*) + echo ${UNAME_MACHINE}-dec-linux-gnu + exit ;; + x86_64:Linux:*:*) + echo x86_64-unknown-linux-gnu + exit ;; + xtensa*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + i*86:DYNIX/ptx:4*:*) + # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. + # earlier versions are messed up and put the nodename in both + # sysname and nodename. + echo i386-sequent-sysv4 + exit ;; + i*86:UNIX_SV:4.2MP:2.*) + # Unixware is an offshoot of SVR4, but it has its own version + # number series starting with 2... + # I am not positive that other SVR4 systems won't match this, + # I just have to hope. -- rms. + # Use sysv4.2uw... so that sysv4* matches it. + echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} + exit ;; + i*86:OS/2:*:*) + # If we were able to find `uname', then EMX Unix compatibility + # is probably installed. + echo ${UNAME_MACHINE}-pc-os2-emx + exit ;; + i*86:XTS-300:*:STOP) + echo ${UNAME_MACHINE}-unknown-stop + exit ;; + i*86:atheos:*:*) + echo ${UNAME_MACHINE}-unknown-atheos + exit ;; + i*86:syllable:*:*) + echo ${UNAME_MACHINE}-pc-syllable + exit ;; + i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*) + echo i386-unknown-lynxos${UNAME_RELEASE} + exit ;; + i*86:*DOS:*:*) + echo ${UNAME_MACHINE}-pc-msdosdjgpp + exit ;; + i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*) + UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'` + if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then + echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL} + else + echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL} + fi + exit ;; + i*86:*:5:[678]*) + # UnixWare 7.x, OpenUNIX and OpenServer 6. + case `/bin/uname -X | grep "^Machine"` in + *486*) UNAME_MACHINE=i486 ;; + *Pentium) UNAME_MACHINE=i586 ;; + *Pent*|*Celeron) UNAME_MACHINE=i686 ;; + esac + echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} + exit ;; + i*86:*:3.2:*) + if test -f /usr/options/cb.name; then + UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then + UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')` + (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 + (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \ + && UNAME_MACHINE=i586 + (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \ + && UNAME_MACHINE=i686 + (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ + && UNAME_MACHINE=i686 + echo ${UNAME_MACHINE}-pc-sco$UNAME_REL + else + echo ${UNAME_MACHINE}-pc-sysv32 + fi + exit ;; + pc:*:*:*) + # Left here for compatibility: + # uname -m prints for DJGPP always 'pc', but it prints nothing about + # the processor, so we play safe by assuming i586. + # Note: whatever this is, it MUST be the same as what config.sub + # prints for the "djgpp" host, or else GDB configury will decide that + # this is a cross-build. + echo i586-pc-msdosdjgpp + exit ;; + Intel:Mach:3*:*) + echo i386-pc-mach3 + exit ;; + paragon:*:*:*) + echo i860-intel-osf1 + exit ;; + i860:*:4.*:*) # i860-SVR4 + if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then + echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 + else # Add other i860-SVR4 vendors below as they are discovered. + echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4 + fi + exit ;; + mini*:CTIX:SYS*5:*) + # "miniframe" + echo m68010-convergent-sysv + exit ;; + mc68k:UNIX:SYSTEM5:3.51m) + echo m68k-convergent-sysv + exit ;; + M680?0:D-NIX:5.3:*) + echo m68k-diab-dnix + exit ;; + M68*:*:R3V[5678]*:*) + test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;; + 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0) + OS_REL='' + test -r /etc/.relid \ + && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4.3${OS_REL}; exit; } + /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; + 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4; exit; } ;; + NCR*:*:4.2:* | MPRAS*:*:4.2:*) + OS_REL='.3' + test -r /etc/.relid \ + && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4.3${OS_REL}; exit; } + /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } + /bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; + m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) + echo m68k-unknown-lynxos${UNAME_RELEASE} + exit ;; + mc68030:UNIX_System_V:4.*:*) + echo m68k-atari-sysv4 + exit ;; + TSUNAMI:LynxOS:2.*:*) + echo sparc-unknown-lynxos${UNAME_RELEASE} + exit ;; + rs6000:LynxOS:2.*:*) + echo rs6000-unknown-lynxos${UNAME_RELEASE} + exit ;; + PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*) + echo powerpc-unknown-lynxos${UNAME_RELEASE} + exit ;; + SM[BE]S:UNIX_SV:*:*) + echo mips-dde-sysv${UNAME_RELEASE} + exit ;; + RM*:ReliantUNIX-*:*:*) + echo mips-sni-sysv4 + exit ;; + RM*:SINIX-*:*:*) + echo mips-sni-sysv4 + exit ;; + *:SINIX-*:*:*) + if uname -p 2>/dev/null >/dev/null ; then + UNAME_MACHINE=`(uname -p) 2>/dev/null` + echo ${UNAME_MACHINE}-sni-sysv4 + else + echo ns32k-sni-sysv + fi + exit ;; + PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort + # says + echo i586-unisys-sysv4 + exit ;; + *:UNIX_System_V:4*:FTX*) + # From Gerald Hewes . + # How about differentiating between stratus architectures? -djm + echo hppa1.1-stratus-sysv4 + exit ;; + *:*:*:FTX*) + # From seanf@swdc.stratus.com. + echo i860-stratus-sysv4 + exit ;; + i*86:VOS:*:*) + # From Paul.Green@stratus.com. + echo ${UNAME_MACHINE}-stratus-vos + exit ;; + *:VOS:*:*) + # From Paul.Green@stratus.com. + echo hppa1.1-stratus-vos + exit ;; + mc68*:A/UX:*:*) + echo m68k-apple-aux${UNAME_RELEASE} + exit ;; + news*:NEWS-OS:6*:*) + echo mips-sony-newsos6 + exit ;; + R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) + if [ -d /usr/nec ]; then + echo mips-nec-sysv${UNAME_RELEASE} + else + echo mips-unknown-sysv${UNAME_RELEASE} + fi + exit ;; + BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. + echo powerpc-be-beos + exit ;; + BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. + echo powerpc-apple-beos + exit ;; + BePC:BeOS:*:*) # BeOS running on Intel PC compatible. + echo i586-pc-beos + exit ;; + BePC:Haiku:*:*) # Haiku running on Intel PC compatible. + echo i586-pc-haiku + exit ;; + SX-4:SUPER-UX:*:*) + echo sx4-nec-superux${UNAME_RELEASE} + exit ;; + SX-5:SUPER-UX:*:*) + echo sx5-nec-superux${UNAME_RELEASE} + exit ;; + SX-6:SUPER-UX:*:*) + echo sx6-nec-superux${UNAME_RELEASE} + exit ;; + SX-7:SUPER-UX:*:*) + echo sx7-nec-superux${UNAME_RELEASE} + exit ;; + SX-8:SUPER-UX:*:*) + echo sx8-nec-superux${UNAME_RELEASE} + exit ;; + SX-8R:SUPER-UX:*:*) + echo sx8r-nec-superux${UNAME_RELEASE} + exit ;; + Power*:Rhapsody:*:*) + echo powerpc-apple-rhapsody${UNAME_RELEASE} + exit ;; + *:Rhapsody:*:*) + echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} + exit ;; + *:Darwin:*:*) + UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown + case $UNAME_PROCESSOR in + i386) + eval $set_cc_for_build + if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then + if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \ + (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_64BIT_ARCH >/dev/null + then + UNAME_PROCESSOR="x86_64" + fi + fi ;; + unknown) UNAME_PROCESSOR=powerpc ;; + esac + echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE} + exit ;; + *:procnto*:*:* | *:QNX:[0123456789]*:*) + UNAME_PROCESSOR=`uname -p` + if test "$UNAME_PROCESSOR" = "x86"; then + UNAME_PROCESSOR=i386 + UNAME_MACHINE=pc + fi + echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE} + exit ;; + *:QNX:*:4*) + echo i386-pc-qnx + exit ;; + NEO-?:NONSTOP_KERNEL:*:*) + echo neo-tandem-nsk${UNAME_RELEASE} + exit ;; + NSE-?:NONSTOP_KERNEL:*:*) + echo nse-tandem-nsk${UNAME_RELEASE} + exit ;; + NSR-?:NONSTOP_KERNEL:*:*) + echo nsr-tandem-nsk${UNAME_RELEASE} + exit ;; + *:NonStop-UX:*:*) + echo mips-compaq-nonstopux + exit ;; + BS2000:POSIX*:*:*) + echo bs2000-siemens-sysv + exit ;; + DS/*:UNIX_System_V:*:*) + echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} + exit ;; + *:Plan9:*:*) + # "uname -m" is not consistent, so use $cputype instead. 386 + # is converted to i386 for consistency with other x86 + # operating systems. + if test "$cputype" = "386"; then + UNAME_MACHINE=i386 + else + UNAME_MACHINE="$cputype" + fi + echo ${UNAME_MACHINE}-unknown-plan9 + exit ;; + *:TOPS-10:*:*) + echo pdp10-unknown-tops10 + exit ;; + *:TENEX:*:*) + echo pdp10-unknown-tenex + exit ;; + KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) + echo pdp10-dec-tops20 + exit ;; + XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) + echo pdp10-xkl-tops20 + exit ;; + *:TOPS-20:*:*) + echo pdp10-unknown-tops20 + exit ;; + *:ITS:*:*) + echo pdp10-unknown-its + exit ;; + SEI:*:*:SEIUX) + echo mips-sei-seiux${UNAME_RELEASE} + exit ;; + *:DragonFly:*:*) + echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` + exit ;; + *:*VMS:*:*) + UNAME_MACHINE=`(uname -p) 2>/dev/null` + case "${UNAME_MACHINE}" in + A*) echo alpha-dec-vms ; exit ;; + I*) echo ia64-dec-vms ; exit ;; + V*) echo vax-dec-vms ; exit ;; + esac ;; + *:XENIX:*:SysV) + echo i386-pc-xenix + exit ;; + i*86:skyos:*:*) + echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//' + exit ;; + i*86:rdos:*:*) + echo ${UNAME_MACHINE}-pc-rdos + exit ;; + i*86:AROS:*:*) + echo ${UNAME_MACHINE}-pc-aros + exit ;; +esac + +#echo '(No uname command or uname output not recognized.)' 1>&2 +#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2 + +eval $set_cc_for_build +cat >$dummy.c < +# include +#endif +main () +{ +#if defined (sony) +#if defined (MIPSEB) + /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed, + I don't know.... */ + printf ("mips-sony-bsd\n"); exit (0); +#else +#include + printf ("m68k-sony-newsos%s\n", +#ifdef NEWSOS4 + "4" +#else + "" +#endif + ); exit (0); +#endif +#endif + +#if defined (__arm) && defined (__acorn) && defined (__unix) + printf ("arm-acorn-riscix\n"); exit (0); +#endif + +#if defined (hp300) && !defined (hpux) + printf ("m68k-hp-bsd\n"); exit (0); +#endif + +#if defined (NeXT) +#if !defined (__ARCHITECTURE__) +#define __ARCHITECTURE__ "m68k" +#endif + int version; + version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`; + if (version < 4) + printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version); + else + printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version); + exit (0); +#endif + +#if defined (MULTIMAX) || defined (n16) +#if defined (UMAXV) + printf ("ns32k-encore-sysv\n"); exit (0); +#else +#if defined (CMU) + printf ("ns32k-encore-mach\n"); exit (0); +#else + printf ("ns32k-encore-bsd\n"); exit (0); +#endif +#endif +#endif + +#if defined (__386BSD__) + printf ("i386-pc-bsd\n"); exit (0); +#endif + +#if defined (sequent) +#if defined (i386) + printf ("i386-sequent-dynix\n"); exit (0); +#endif +#if defined (ns32000) + printf ("ns32k-sequent-dynix\n"); exit (0); +#endif +#endif + +#if defined (_SEQUENT_) + struct utsname un; + + uname(&un); + + if (strncmp(un.version, "V2", 2) == 0) { + printf ("i386-sequent-ptx2\n"); exit (0); + } + if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */ + printf ("i386-sequent-ptx1\n"); exit (0); + } + printf ("i386-sequent-ptx\n"); exit (0); + +#endif + +#if defined (vax) +# if !defined (ultrix) +# include +# if defined (BSD) +# if BSD == 43 + printf ("vax-dec-bsd4.3\n"); exit (0); +# else +# if BSD == 199006 + printf ("vax-dec-bsd4.3reno\n"); exit (0); +# else + printf ("vax-dec-bsd\n"); exit (0); +# endif +# endif +# else + printf ("vax-dec-bsd\n"); exit (0); +# endif +# else + printf ("vax-dec-ultrix\n"); exit (0); +# endif +#endif + +#if defined (alliant) && defined (i860) + printf ("i860-alliant-bsd\n"); exit (0); +#endif + + exit (1); +} +EOF + +$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && SYSTEM_NAME=`$dummy` && + { echo "$SYSTEM_NAME"; exit; } + +# Apollos put the system type in the environment. + +test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit; } + +# Convex versions that predate uname can use getsysinfo(1) + +if [ -x /usr/convex/getsysinfo ] +then + case `getsysinfo -f cpu_type` in + c1*) + echo c1-convex-bsd + exit ;; + c2*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit ;; + c34*) + echo c34-convex-bsd + exit ;; + c38*) + echo c38-convex-bsd + exit ;; + c4*) + echo c4-convex-bsd + exit ;; + esac +fi + +cat >&2 < in order to provide the needed +information to handle your system. + +config.guess timestamp = $timestamp + +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null` + +hostinfo = `(hostinfo) 2>/dev/null` +/bin/universe = `(/bin/universe) 2>/dev/null` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null` +/bin/arch = `(/bin/arch) 2>/dev/null` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` + +UNAME_MACHINE = ${UNAME_MACHINE} +UNAME_RELEASE = ${UNAME_RELEASE} +UNAME_SYSTEM = ${UNAME_SYSTEM} +UNAME_VERSION = ${UNAME_VERSION} +EOF + +exit 1 + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/config.sub b/config.sub new file mode 100755 index 0000000..30fdca8 --- /dev/null +++ b/config.sub @@ -0,0 +1,1760 @@ +#! /bin/sh +# Configuration validation subroutine script. +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, +# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, +# 2011 Free Software Foundation, Inc. + +timestamp='2011-03-23' + +# This file is (in principle) common to ALL GNU software. +# The presence of a machine in this file suggests that SOME GNU software +# can handle that machine. It does not imply ALL GNU software can. +# +# This file is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA +# 02110-1301, USA. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + + +# Please send patches to . Submit a context +# diff and a properly formatted GNU ChangeLog entry. +# +# Configuration subroutine to validate and canonicalize a configuration type. +# Supply the specified configuration type as an argument. +# If it is invalid, we print an error message on stderr and exit with code 1. +# Otherwise, we print the canonical config type on stdout and succeed. + +# You can get the latest version of this script from: +# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD + +# This file is supposed to be the same for all GNU packages +# and recognize all the CPU types, system types and aliases +# that are meaningful with *any* GNU software. +# Each package is responsible for reporting which valid configurations +# it does not support. The user should be able to distinguish +# a failure to support a valid configuration from a meaningless +# configuration. + +# The goal of this file is to map all the various variations of a given +# machine specification into a single specification in the form: +# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM +# or in some cases, the newer four-part form: +# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM +# It is wrong to echo any other type of specification. + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] CPU-MFR-OPSYS + $0 [OPTION] ALIAS + +Canonicalize a configuration name. + +Operation modes: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to ." + +version="\ +GNU config.sub ($timestamp) + +Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, +2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free +Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit ;; + --version | -v ) + echo "$version" ; exit ;; + --help | --h* | -h ) + echo "$usage"; exit ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" + exit 1 ;; + + *local*) + # First pass through any local machine types. + echo $1 + exit ;; + + * ) + break ;; + esac +done + +case $# in + 0) echo "$me: missing argument$help" >&2 + exit 1;; + 1) ;; + *) echo "$me: too many arguments$help" >&2 + exit 1;; +esac + +# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). +# Here we must recognize all the valid KERNEL-OS combinations. +maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` +case $maybe_os in + nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \ + linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \ + knetbsd*-gnu* | netbsd*-gnu* | \ + kopensolaris*-gnu* | \ + storm-chaos* | os2-emx* | rtmk-nova*) + os=-$maybe_os + basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` + ;; + *) + basic_machine=`echo $1 | sed 's/-[^-]*$//'` + if [ $basic_machine != $1 ] + then os=`echo $1 | sed 's/.*-/-/'` + else os=; fi + ;; +esac + +### Let's recognize common machines as not being operating systems so +### that things like config.sub decstation-3100 work. We also +### recognize some manufacturers as not being operating systems, so we +### can provide default operating systems below. +case $os in + -sun*os*) + # Prevent following clause from handling this invalid input. + ;; + -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \ + -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \ + -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ + -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ + -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ + -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ + -apple | -axis | -knuth | -cray | -microblaze) + os= + basic_machine=$1 + ;; + -bluegene*) + os=-cnk + ;; + -sim | -cisco | -oki | -wec | -winbond) + os= + basic_machine=$1 + ;; + -scout) + ;; + -wrs) + os=-vxworks + basic_machine=$1 + ;; + -chorusos*) + os=-chorusos + basic_machine=$1 + ;; + -chorusrdb) + os=-chorusrdb + basic_machine=$1 + ;; + -hiux*) + os=-hiuxwe2 + ;; + -sco6) + os=-sco5v6 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco5) + os=-sco3.2v5 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco4) + os=-sco3.2v4 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2.[4-9]*) + os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2v[4-9]*) + # Don't forget version if it is 3.2v4 or newer. + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco5v6*) + # Don't forget version if it is 3.2v4 or newer. + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco*) + os=-sco3.2v2 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -udk*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -isc) + os=-isc2.2 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -clix*) + basic_machine=clipper-intergraph + ;; + -isc*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -lynx*) + os=-lynxos + ;; + -ptx*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` + ;; + -windowsnt*) + os=`echo $os | sed -e 's/windowsnt/winnt/'` + ;; + -psos*) + os=-psos + ;; + -mint | -mint[0-9]*) + basic_machine=m68k-atari + os=-mint + ;; +esac + +# Decode aliases for certain CPU-COMPANY combinations. +case $basic_machine in + # Recognize the basic CPU types without company name. + # Some are omitted here because they have special meanings below. + 1750a | 580 \ + | a29k \ + | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ + | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ + | am33_2.0 \ + | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr | avr32 \ + | bfin \ + | c4x | clipper \ + | d10v | d30v | dlx | dsp16xx \ + | fido | fr30 | frv \ + | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ + | i370 | i860 | i960 | ia64 \ + | ip2k | iq2000 \ + | lm32 \ + | m32c | m32r | m32rle | m68000 | m68k | m88k \ + | maxq | mb | microblaze | mcore | mep | metag \ + | mips | mipsbe | mipseb | mipsel | mipsle \ + | mips16 \ + | mips64 | mips64el \ + | mips64octeon | mips64octeonel \ + | mips64orion | mips64orionel \ + | mips64r5900 | mips64r5900el \ + | mips64vr | mips64vrel \ + | mips64vr4100 | mips64vr4100el \ + | mips64vr4300 | mips64vr4300el \ + | mips64vr5000 | mips64vr5000el \ + | mips64vr5900 | mips64vr5900el \ + | mipsisa32 | mipsisa32el \ + | mipsisa32r2 | mipsisa32r2el \ + | mipsisa64 | mipsisa64el \ + | mipsisa64r2 | mipsisa64r2el \ + | mipsisa64sb1 | mipsisa64sb1el \ + | mipsisa64sr71k | mipsisa64sr71kel \ + | mipstx39 | mipstx39el \ + | mn10200 | mn10300 \ + | moxie \ + | mt \ + | msp430 \ + | nds32 | nds32le | nds32be \ + | nios | nios2 \ + | ns16k | ns32k \ + | open8 \ + | or32 \ + | pdp10 | pdp11 | pj | pjl \ + | powerpc | powerpc64 | powerpc64le | powerpcle \ + | pyramid \ + | rx \ + | score \ + | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ + | sh64 | sh64le \ + | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \ + | sparcv8 | sparcv9 | sparcv9b | sparcv9v \ + | spu \ + | tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \ + | ubicom32 \ + | v850 | v850e \ + | we32k \ + | x86 | xc16x | xstormy16 | xtensa \ + | z8k | z80) + basic_machine=$basic_machine-unknown + ;; + c54x) + basic_machine=tic54x-unknown + ;; + c55x) + basic_machine=tic55x-unknown + ;; + c6x) + basic_machine=tic6x-unknown + ;; + m6811 | m68hc11 | m6812 | m68hc12 | picochip) + # Motorola 68HC11/12. + basic_machine=$basic_machine-unknown + os=-none + ;; + m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) + ;; + ms1) + basic_machine=mt-unknown + ;; + + strongarm | thumb | xscale) + basic_machine=arm-unknown + ;; + + xscaleeb) + basic_machine=armeb-unknown + ;; + + xscaleel) + basic_machine=armel-unknown + ;; + + # We use `pc' rather than `unknown' + # because (1) that's what they normally are, and + # (2) the word "unknown" tends to confuse beginning users. + i*86 | x86_64) + basic_machine=$basic_machine-pc + ;; + # Object if more than one company name word. + *-*-*) + echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + exit 1 + ;; + # Recognize the basic CPU types with company name. + 580-* \ + | a29k-* \ + | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ + | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ + | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \ + | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ + | avr-* | avr32-* \ + | bfin-* | bs2000-* \ + | c[123]* | c30-* | [cjt]90-* | c4x-* \ + | clipper-* | craynv-* | cydra-* \ + | d10v-* | d30v-* | dlx-* \ + | elxsi-* \ + | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \ + | h8300-* | h8500-* \ + | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ + | i*86-* | i860-* | i960-* | ia64-* \ + | ip2k-* | iq2000-* \ + | lm32-* \ + | m32c-* | m32r-* | m32rle-* \ + | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ + | m88110-* | m88k-* | maxq-* | mcore-* | metag-* | microblaze-* \ + | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ + | mips16-* \ + | mips64-* | mips64el-* \ + | mips64octeon-* | mips64octeonel-* \ + | mips64orion-* | mips64orionel-* \ + | mips64r5900-* | mips64r5900el-* \ + | mips64vr-* | mips64vrel-* \ + | mips64vr4100-* | mips64vr4100el-* \ + | mips64vr4300-* | mips64vr4300el-* \ + | mips64vr5000-* | mips64vr5000el-* \ + | mips64vr5900-* | mips64vr5900el-* \ + | mipsisa32-* | mipsisa32el-* \ + | mipsisa32r2-* | mipsisa32r2el-* \ + | mipsisa64-* | mipsisa64el-* \ + | mipsisa64r2-* | mipsisa64r2el-* \ + | mipsisa64sb1-* | mipsisa64sb1el-* \ + | mipsisa64sr71k-* | mipsisa64sr71kel-* \ + | mipstx39-* | mipstx39el-* \ + | mmix-* \ + | mt-* \ + | msp430-* \ + | nds32-* | nds32le-* | nds32be-* \ + | nios-* | nios2-* \ + | none-* | np1-* | ns16k-* | ns32k-* \ + | open8-* \ + | orion-* \ + | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ + | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \ + | pyramid-* \ + | romp-* | rs6000-* | rx-* \ + | sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \ + | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ + | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \ + | sparclite-* \ + | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx?-* \ + | tahoe-* \ + | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ + | tile-* | tilegx-* \ + | tron-* \ + | ubicom32-* \ + | v850-* | v850e-* | vax-* \ + | we32k-* \ + | x86-* | x86_64-* | xc16x-* | xps100-* \ + | xstormy16-* | xtensa*-* \ + | ymp-* \ + | z8k-* | z80-*) + ;; + # Recognize the basic CPU types without company name, with glob match. + xtensa*) + basic_machine=$basic_machine-unknown + ;; + # Recognize the various machine names and aliases which stand + # for a CPU type and a company and sometimes even an OS. + 386bsd) + basic_machine=i386-unknown + os=-bsd + ;; + 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) + basic_machine=m68000-att + ;; + 3b*) + basic_machine=we32k-att + ;; + a29khif) + basic_machine=a29k-amd + os=-udi + ;; + abacus) + basic_machine=abacus-unknown + ;; + adobe68k) + basic_machine=m68010-adobe + os=-scout + ;; + alliant | fx80) + basic_machine=fx80-alliant + ;; + altos | altos3068) + basic_machine=m68k-altos + ;; + am29k) + basic_machine=a29k-none + os=-bsd + ;; + amd64) + basic_machine=x86_64-pc + ;; + amd64-*) + basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + amdahl) + basic_machine=580-amdahl + os=-sysv + ;; + amiga | amiga-*) + basic_machine=m68k-unknown + ;; + amigaos | amigados) + basic_machine=m68k-unknown + os=-amigaos + ;; + amigaunix | amix) + basic_machine=m68k-unknown + os=-sysv4 + ;; + apollo68) + basic_machine=m68k-apollo + os=-sysv + ;; + apollo68bsd) + basic_machine=m68k-apollo + os=-bsd + ;; + aros) + basic_machine=i386-pc + os=-aros + ;; + aux) + basic_machine=m68k-apple + os=-aux + ;; + balance) + basic_machine=ns32k-sequent + os=-dynix + ;; + blackfin) + basic_machine=bfin-unknown + os=-linux + ;; + blackfin-*) + basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'` + os=-linux + ;; + bluegene*) + basic_machine=powerpc-ibm + os=-cnk + ;; + c54x-*) + basic_machine=tic54x-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + c55x-*) + basic_machine=tic55x-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + c6x-*) + basic_machine=tic6x-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + c90) + basic_machine=c90-cray + os=-unicos + ;; + cegcc) + basic_machine=arm-unknown + os=-cegcc + ;; + convex-c1) + basic_machine=c1-convex + os=-bsd + ;; + convex-c2) + basic_machine=c2-convex + os=-bsd + ;; + convex-c32) + basic_machine=c32-convex + os=-bsd + ;; + convex-c34) + basic_machine=c34-convex + os=-bsd + ;; + convex-c38) + basic_machine=c38-convex + os=-bsd + ;; + cray | j90) + basic_machine=j90-cray + os=-unicos + ;; + craynv) + basic_machine=craynv-cray + os=-unicosmp + ;; + cr16 | cr16-*) + basic_machine=cr16-unknown + os=-elf + ;; + crds | unos) + basic_machine=m68k-crds + ;; + crisv32 | crisv32-* | etraxfs*) + basic_machine=crisv32-axis + ;; + cris | cris-* | etrax*) + basic_machine=cris-axis + ;; + crx) + basic_machine=crx-unknown + os=-elf + ;; + da30 | da30-*) + basic_machine=m68k-da30 + ;; + decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) + basic_machine=mips-dec + ;; + decsystem10* | dec10*) + basic_machine=pdp10-dec + os=-tops10 + ;; + decsystem20* | dec20*) + basic_machine=pdp10-dec + os=-tops20 + ;; + delta | 3300 | motorola-3300 | motorola-delta \ + | 3300-motorola | delta-motorola) + basic_machine=m68k-motorola + ;; + delta88) + basic_machine=m88k-motorola + os=-sysv3 + ;; + dicos) + basic_machine=i686-pc + os=-dicos + ;; + djgpp) + basic_machine=i586-pc + os=-msdosdjgpp + ;; + dpx20 | dpx20-*) + basic_machine=rs6000-bull + os=-bosx + ;; + dpx2* | dpx2*-bull) + basic_machine=m68k-bull + os=-sysv3 + ;; + ebmon29k) + basic_machine=a29k-amd + os=-ebmon + ;; + elxsi) + basic_machine=elxsi-elxsi + os=-bsd + ;; + encore | umax | mmax) + basic_machine=ns32k-encore + ;; + es1800 | OSE68k | ose68k | ose | OSE) + basic_machine=m68k-ericsson + os=-ose + ;; + fx2800) + basic_machine=i860-alliant + ;; + genix) + basic_machine=ns32k-ns + ;; + gmicro) + basic_machine=tron-gmicro + os=-sysv + ;; + go32) + basic_machine=i386-pc + os=-go32 + ;; + h3050r* | hiux*) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + h8300hms) + basic_machine=h8300-hitachi + os=-hms + ;; + h8300xray) + basic_machine=h8300-hitachi + os=-xray + ;; + h8500hms) + basic_machine=h8500-hitachi + os=-hms + ;; + harris) + basic_machine=m88k-harris + os=-sysv3 + ;; + hp300-*) + basic_machine=m68k-hp + ;; + hp300bsd) + basic_machine=m68k-hp + os=-bsd + ;; + hp300hpux) + basic_machine=m68k-hp + os=-hpux + ;; + hp3k9[0-9][0-9] | hp9[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hp9k2[0-9][0-9] | hp9k31[0-9]) + basic_machine=m68000-hp + ;; + hp9k3[2-9][0-9]) + basic_machine=m68k-hp + ;; + hp9k6[0-9][0-9] | hp6[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hp9k7[0-79][0-9] | hp7[0-79][0-9]) + basic_machine=hppa1.1-hp + ;; + hp9k78[0-9] | hp78[0-9]) + # FIXME: really hppa2.0-hp + basic_machine=hppa1.1-hp + ;; + hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) + # FIXME: really hppa2.0-hp + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][13679] | hp8[0-9][13679]) + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][0-9] | hp8[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hppa-next) + os=-nextstep3 + ;; + hppaosf) + basic_machine=hppa1.1-hp + os=-osf + ;; + hppro) + basic_machine=hppa1.1-hp + os=-proelf + ;; + i370-ibm* | ibm*) + basic_machine=i370-ibm + ;; +# I'm not sure what "Sysv32" means. Should this be sysv3.2? + i*86v32) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv32 + ;; + i*86v4*) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv4 + ;; + i*86v) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv + ;; + i*86sol2) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-solaris2 + ;; + i386mach) + basic_machine=i386-mach + os=-mach + ;; + i386-vsta | vsta) + basic_machine=i386-unknown + os=-vsta + ;; + iris | iris4d) + basic_machine=mips-sgi + case $os in + -irix*) + ;; + *) + os=-irix4 + ;; + esac + ;; + isi68 | isi) + basic_machine=m68k-isi + os=-sysv + ;; + m68knommu) + basic_machine=m68k-unknown + os=-linux + ;; + m68knommu-*) + basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'` + os=-linux + ;; + m88k-omron*) + basic_machine=m88k-omron + ;; + magnum | m3230) + basic_machine=mips-mips + os=-sysv + ;; + merlin) + basic_machine=ns32k-utek + os=-sysv + ;; + microblaze) + basic_machine=microblaze-xilinx + ;; + mingw32) + basic_machine=i386-pc + os=-mingw32 + ;; + mingw32ce) + basic_machine=arm-unknown + os=-mingw32ce + ;; + miniframe) + basic_machine=m68000-convergent + ;; + *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) + basic_machine=m68k-atari + os=-mint + ;; + mips3*-*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` + ;; + mips3*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown + ;; + monitor) + basic_machine=m68k-rom68k + os=-coff + ;; + morphos) + basic_machine=powerpc-unknown + os=-morphos + ;; + msdos) + basic_machine=i386-pc + os=-msdos + ;; + ms1-*) + basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'` + ;; + mvs) + basic_machine=i370-ibm + os=-mvs + ;; + ncr3000) + basic_machine=i486-ncr + os=-sysv4 + ;; + netbsd386) + basic_machine=i386-unknown + os=-netbsd + ;; + netwinder) + basic_machine=armv4l-rebel + os=-linux + ;; + news | news700 | news800 | news900) + basic_machine=m68k-sony + os=-newsos + ;; + news1000) + basic_machine=m68030-sony + os=-newsos + ;; + news-3600 | risc-news) + basic_machine=mips-sony + os=-newsos + ;; + necv70) + basic_machine=v70-nec + os=-sysv + ;; + next | m*-next ) + basic_machine=m68k-next + case $os in + -nextstep* ) + ;; + -ns2*) + os=-nextstep2 + ;; + *) + os=-nextstep3 + ;; + esac + ;; + nh3000) + basic_machine=m68k-harris + os=-cxux + ;; + nh[45]000) + basic_machine=m88k-harris + os=-cxux + ;; + nindy960) + basic_machine=i960-intel + os=-nindy + ;; + mon960) + basic_machine=i960-intel + os=-mon960 + ;; + nonstopux) + basic_machine=mips-compaq + os=-nonstopux + ;; + np1) + basic_machine=np1-gould + ;; + neo-tandem) + basic_machine=neo-tandem + ;; + nse-tandem) + basic_machine=nse-tandem + ;; + nsr-tandem) + basic_machine=nsr-tandem + ;; + op50n-* | op60c-*) + basic_machine=hppa1.1-oki + os=-proelf + ;; + openrisc | openrisc-*) + basic_machine=or32-unknown + ;; + os400) + basic_machine=powerpc-ibm + os=-os400 + ;; + OSE68000 | ose68000) + basic_machine=m68000-ericsson + os=-ose + ;; + os68k) + basic_machine=m68k-none + os=-os68k + ;; + pa-hitachi) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + paragon) + basic_machine=i860-intel + os=-osf + ;; + parisc) + basic_machine=hppa-unknown + os=-linux + ;; + parisc-*) + basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'` + os=-linux + ;; + pbd) + basic_machine=sparc-tti + ;; + pbb) + basic_machine=m68k-tti + ;; + pc532 | pc532-*) + basic_machine=ns32k-pc532 + ;; + pc98) + basic_machine=i386-pc + ;; + pc98-*) + basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentium | p5 | k5 | k6 | nexgen | viac3) + basic_machine=i586-pc + ;; + pentiumpro | p6 | 6x86 | athlon | athlon_*) + basic_machine=i686-pc + ;; + pentiumii | pentium2 | pentiumiii | pentium3) + basic_machine=i686-pc + ;; + pentium4) + basic_machine=i786-pc + ;; + pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) + basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumpro-* | p6-* | 6x86-* | athlon-*) + basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) + basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentium4-*) + basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pn) + basic_machine=pn-gould + ;; + power) basic_machine=power-ibm + ;; + ppc | ppcbe) basic_machine=powerpc-unknown + ;; + ppc-* | ppcbe-*) + basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppcle | powerpclittle | ppc-le | powerpc-little) + basic_machine=powerpcle-unknown + ;; + ppcle-* | powerpclittle-*) + basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppc64) basic_machine=powerpc64-unknown + ;; + ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppc64le | powerpc64little | ppc64-le | powerpc64-little) + basic_machine=powerpc64le-unknown + ;; + ppc64le-* | powerpc64little-*) + basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ps2) + basic_machine=i386-ibm + ;; + pw32) + basic_machine=i586-unknown + os=-pw32 + ;; + rdos) + basic_machine=i386-pc + os=-rdos + ;; + rom68k) + basic_machine=m68k-rom68k + os=-coff + ;; + rm[46]00) + basic_machine=mips-siemens + ;; + rtpc | rtpc-*) + basic_machine=romp-ibm + ;; + s390 | s390-*) + basic_machine=s390-ibm + ;; + s390x | s390x-*) + basic_machine=s390x-ibm + ;; + sa29200) + basic_machine=a29k-amd + os=-udi + ;; + sb1) + basic_machine=mipsisa64sb1-unknown + ;; + sb1el) + basic_machine=mipsisa64sb1el-unknown + ;; + sde) + basic_machine=mipsisa32-sde + os=-elf + ;; + sei) + basic_machine=mips-sei + os=-seiux + ;; + sequent) + basic_machine=i386-sequent + ;; + sh) + basic_machine=sh-hitachi + os=-hms + ;; + sh5el) + basic_machine=sh5le-unknown + ;; + sh64) + basic_machine=sh64-unknown + ;; + sparclite-wrs | simso-wrs) + basic_machine=sparclite-wrs + os=-vxworks + ;; + sps7) + basic_machine=m68k-bull + os=-sysv2 + ;; + spur) + basic_machine=spur-unknown + ;; + st2000) + basic_machine=m68k-tandem + ;; + stratus) + basic_machine=i860-stratus + os=-sysv4 + ;; + strongarm-* | thumb-*) + basic_machine=arm-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + sun2) + basic_machine=m68000-sun + ;; + sun2os3) + basic_machine=m68000-sun + os=-sunos3 + ;; + sun2os4) + basic_machine=m68000-sun + os=-sunos4 + ;; + sun3os3) + basic_machine=m68k-sun + os=-sunos3 + ;; + sun3os4) + basic_machine=m68k-sun + os=-sunos4 + ;; + sun4os3) + basic_machine=sparc-sun + os=-sunos3 + ;; + sun4os4) + basic_machine=sparc-sun + os=-sunos4 + ;; + sun4sol2) + basic_machine=sparc-sun + os=-solaris2 + ;; + sun3 | sun3-*) + basic_machine=m68k-sun + ;; + sun4) + basic_machine=sparc-sun + ;; + sun386 | sun386i | roadrunner) + basic_machine=i386-sun + ;; + sv1) + basic_machine=sv1-cray + os=-unicos + ;; + symmetry) + basic_machine=i386-sequent + os=-dynix + ;; + t3e) + basic_machine=alphaev5-cray + os=-unicos + ;; + t90) + basic_machine=t90-cray + os=-unicos + ;; + # This must be matched before tile*. + tilegx*) + basic_machine=tilegx-unknown + os=-linux-gnu + ;; + tile*) + basic_machine=tile-unknown + os=-linux-gnu + ;; + tx39) + basic_machine=mipstx39-unknown + ;; + tx39el) + basic_machine=mipstx39el-unknown + ;; + toad1) + basic_machine=pdp10-xkl + os=-tops20 + ;; + tower | tower-32) + basic_machine=m68k-ncr + ;; + tpf) + basic_machine=s390x-ibm + os=-tpf + ;; + udi29k) + basic_machine=a29k-amd + os=-udi + ;; + ultra3) + basic_machine=a29k-nyu + os=-sym1 + ;; + v810 | necv810) + basic_machine=v810-nec + os=-none + ;; + vaxv) + basic_machine=vax-dec + os=-sysv + ;; + vms) + basic_machine=vax-dec + os=-vms + ;; + vpp*|vx|vx-*) + basic_machine=f301-fujitsu + ;; + vxworks960) + basic_machine=i960-wrs + os=-vxworks + ;; + vxworks68) + basic_machine=m68k-wrs + os=-vxworks + ;; + vxworks29k) + basic_machine=a29k-wrs + os=-vxworks + ;; + w65*) + basic_machine=w65-wdc + os=-none + ;; + w89k-*) + basic_machine=hppa1.1-winbond + os=-proelf + ;; + xbox) + basic_machine=i686-pc + os=-mingw32 + ;; + xps | xps100) + basic_machine=xps100-honeywell + ;; + xscale-* | xscalee[bl]-*) + basic_machine=`echo $basic_machine | sed 's/^xscale/arm/'` + ;; + ymp) + basic_machine=ymp-cray + os=-unicos + ;; + z8k-*-coff) + basic_machine=z8k-unknown + os=-sim + ;; + z80-*-coff) + basic_machine=z80-unknown + os=-sim + ;; + none) + basic_machine=none-none + os=-none + ;; + +# Here we handle the default manufacturer of certain CPU types. It is in +# some cases the only manufacturer, in others, it is the most popular. + w89k) + basic_machine=hppa1.1-winbond + ;; + op50n) + basic_machine=hppa1.1-oki + ;; + op60c) + basic_machine=hppa1.1-oki + ;; + romp) + basic_machine=romp-ibm + ;; + mmix) + basic_machine=mmix-knuth + ;; + rs6000) + basic_machine=rs6000-ibm + ;; + vax) + basic_machine=vax-dec + ;; + pdp10) + # there are many clones, so DEC is not a safe bet + basic_machine=pdp10-unknown + ;; + pdp11) + basic_machine=pdp11-dec + ;; + we32k) + basic_machine=we32k-att + ;; + sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele) + basic_machine=sh-unknown + ;; + sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v) + basic_machine=sparc-sun + ;; + cydra) + basic_machine=cydra-cydrome + ;; + orion) + basic_machine=orion-highlevel + ;; + orion105) + basic_machine=clipper-highlevel + ;; + mac | mpw | mac-mpw) + basic_machine=m68k-apple + ;; + pmac | pmac-mpw) + basic_machine=powerpc-apple + ;; + *-unknown) + # Make sure to match an already-canonicalized machine name. + ;; + *) + echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + exit 1 + ;; +esac + +# Here we canonicalize certain aliases for manufacturers. +case $basic_machine in + *-digital*) + basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` + ;; + *-commodore*) + basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` + ;; + *) + ;; +esac + +# Decode manufacturer-specific aliases for certain operating systems. + +if [ x"$os" != x"" ] +then +case $os in + # First match some system type aliases + # that might get confused with valid system types. + # -solaris* is a basic system type, with this one exception. + -auroraux) + os=-auroraux + ;; + -solaris1 | -solaris1.*) + os=`echo $os | sed -e 's|solaris1|sunos4|'` + ;; + -solaris) + os=-solaris2 + ;; + -svr4*) + os=-sysv4 + ;; + -unixware*) + os=-sysv4.2uw + ;; + -gnu/linux*) + os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` + ;; + # First accept the basic system types. + # The portable systems comes first. + # Each alternative MUST END IN A *, to match a version number. + # -sysv* is not here because it comes later, after sysvr4. + -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ + | -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\ + | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \ + | -sym* | -kopensolaris* \ + | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ + | -aos* | -aros* \ + | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ + | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ + | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \ + | -openbsd* | -solidbsd* \ + | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \ + | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ + | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ + | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ + | -chorusos* | -chorusrdb* | -cegcc* \ + | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ + | -mingw32* | -linux-gnu* | -linux-android* \ + | -linux-newlib* | -linux-uclibc* \ + | -uxpv* | -beos* | -mpeix* | -udk* \ + | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ + | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ + | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ + | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ + | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ + | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \ + | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es*) + # Remember, each alternative MUST END IN *, to match a version number. + ;; + -qnx*) + case $basic_machine in + x86-* | i*86-*) + ;; + *) + os=-nto$os + ;; + esac + ;; + -nto-qnx*) + ;; + -nto*) + os=`echo $os | sed -e 's|nto|nto-qnx|'` + ;; + -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ + | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \ + | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) + ;; + -mac*) + os=`echo $os | sed -e 's|mac|macos|'` + ;; + -linux-dietlibc) + os=-linux-dietlibc + ;; + -linux*) + os=`echo $os | sed -e 's|linux|linux-gnu|'` + ;; + -sunos5*) + os=`echo $os | sed -e 's|sunos5|solaris2|'` + ;; + -sunos6*) + os=`echo $os | sed -e 's|sunos6|solaris3|'` + ;; + -opened*) + os=-openedition + ;; + -os400*) + os=-os400 + ;; + -wince*) + os=-wince + ;; + -osfrose*) + os=-osfrose + ;; + -osf*) + os=-osf + ;; + -utek*) + os=-bsd + ;; + -dynix*) + os=-bsd + ;; + -acis*) + os=-aos + ;; + -atheos*) + os=-atheos + ;; + -syllable*) + os=-syllable + ;; + -386bsd) + os=-bsd + ;; + -ctix* | -uts*) + os=-sysv + ;; + -nova*) + os=-rtmk-nova + ;; + -ns2 ) + os=-nextstep2 + ;; + -nsk*) + os=-nsk + ;; + # Preserve the version number of sinix5. + -sinix5.*) + os=`echo $os | sed -e 's|sinix|sysv|'` + ;; + -sinix*) + os=-sysv4 + ;; + -tpf*) + os=-tpf + ;; + -triton*) + os=-sysv3 + ;; + -oss*) + os=-sysv3 + ;; + -svr4) + os=-sysv4 + ;; + -svr3) + os=-sysv3 + ;; + -sysvr4) + os=-sysv4 + ;; + # This must come after -sysvr4. + -sysv*) + ;; + -ose*) + os=-ose + ;; + -es1800*) + os=-ose + ;; + -xenix) + os=-xenix + ;; + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + os=-mint + ;; + -aros*) + os=-aros + ;; + -kaos*) + os=-kaos + ;; + -zvmoe) + os=-zvmoe + ;; + -dicos*) + os=-dicos + ;; + -nacl*) + ;; + -none) + ;; + *) + # Get rid of the `-' at the beginning of $os. + os=`echo $os | sed 's/[^-]*-//'` + echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 + exit 1 + ;; +esac +else + +# Here we handle the default operating systems that come with various machines. +# The value should be what the vendor currently ships out the door with their +# machine or put another way, the most popular os provided with the machine. + +# Note that if you're going to try to match "-MANUFACTURER" here (say, +# "-sun"), then you have to tell the case statement up towards the top +# that MANUFACTURER isn't an operating system. Otherwise, code above +# will signal an error saying that MANUFACTURER isn't an operating +# system, and we'll never get to this point. + +case $basic_machine in + score-*) + os=-elf + ;; + spu-*) + os=-elf + ;; + *-acorn) + os=-riscix1.2 + ;; + arm*-rebel) + os=-linux + ;; + arm*-semi) + os=-aout + ;; + c4x-* | tic4x-*) + os=-coff + ;; + tic54x-*) + os=-coff + ;; + tic55x-*) + os=-coff + ;; + tic6x-*) + os=-coff + ;; + # This must come before the *-dec entry. + pdp10-*) + os=-tops20 + ;; + pdp11-*) + os=-none + ;; + *-dec | vax-*) + os=-ultrix4.2 + ;; + m68*-apollo) + os=-domain + ;; + i386-sun) + os=-sunos4.0.2 + ;; + m68000-sun) + os=-sunos3 + # This also exists in the configure program, but was not the + # default. + # os=-sunos4 + ;; + m68*-cisco) + os=-aout + ;; + mep-*) + os=-elf + ;; + mips*-cisco) + os=-elf + ;; + mips*-*) + os=-elf + ;; + or32-*) + os=-coff + ;; + *-tti) # must be before sparc entry or we get the wrong os. + os=-sysv3 + ;; + sparc-* | *-sun) + os=-sunos4.1.1 + ;; + *-be) + os=-beos + ;; + *-haiku) + os=-haiku + ;; + *-ibm) + os=-aix + ;; + *-knuth) + os=-mmixware + ;; + *-wec) + os=-proelf + ;; + *-winbond) + os=-proelf + ;; + *-oki) + os=-proelf + ;; + *-hp) + os=-hpux + ;; + *-hitachi) + os=-hiux + ;; + i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) + os=-sysv + ;; + *-cbm) + os=-amigaos + ;; + *-dg) + os=-dgux + ;; + *-dolphin) + os=-sysv3 + ;; + m68k-ccur) + os=-rtu + ;; + m88k-omron*) + os=-luna + ;; + *-next ) + os=-nextstep + ;; + *-sequent) + os=-ptx + ;; + *-crds) + os=-unos + ;; + *-ns) + os=-genix + ;; + i370-*) + os=-mvs + ;; + *-next) + os=-nextstep3 + ;; + *-gould) + os=-sysv + ;; + *-highlevel) + os=-bsd + ;; + *-encore) + os=-bsd + ;; + *-sgi) + os=-irix + ;; + *-siemens) + os=-sysv4 + ;; + *-masscomp) + os=-rtu + ;; + f30[01]-fujitsu | f700-fujitsu) + os=-uxpv + ;; + *-rom68k) + os=-coff + ;; + *-*bug) + os=-coff + ;; + *-apple) + os=-macos + ;; + *-atari*) + os=-mint + ;; + *) + os=-none + ;; +esac +fi + +# Here we handle the case where we know the os, and the CPU type, but not the +# manufacturer. We pick the logical manufacturer. +vendor=unknown +case $basic_machine in + *-unknown) + case $os in + -riscix*) + vendor=acorn + ;; + -sunos*) + vendor=sun + ;; + -cnk*|-aix*) + vendor=ibm + ;; + -beos*) + vendor=be + ;; + -hpux*) + vendor=hp + ;; + -mpeix*) + vendor=hp + ;; + -hiux*) + vendor=hitachi + ;; + -unos*) + vendor=crds + ;; + -dgux*) + vendor=dg + ;; + -luna*) + vendor=omron + ;; + -genix*) + vendor=ns + ;; + -mvs* | -opened*) + vendor=ibm + ;; + -os400*) + vendor=ibm + ;; + -ptx*) + vendor=sequent + ;; + -tpf*) + vendor=ibm + ;; + -vxsim* | -vxworks* | -windiss*) + vendor=wrs + ;; + -aux*) + vendor=apple + ;; + -hms*) + vendor=hitachi + ;; + -mpw* | -macos*) + vendor=apple + ;; + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + vendor=atari + ;; + -vos*) + vendor=stratus + ;; + esac + basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` + ;; +esac + +echo $basic_machine$os +exit + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/configure.ac b/configure.ac new file mode 100644 index 0000000..e15e812 --- /dev/null +++ b/configure.ac @@ -0,0 +1,112 @@ +AC_PREREQ(2.52) + +AC_INIT([libmm-camcorder], [1.0]) +AM_INIT_AUTOMAKE([-Wall -Werror foreign]) +AC_CONFIG_HEADERS([config.h:config.hin]) +AC_CONFIG_MACRO_DIR([m4]) + +# Checks for programs. +AC_PROG_CC +AC_C_CONST +dnl AC_FUNC_MALLOC +AC_FUNC_MMAP +AC_FUNC_REALLOC +AC_FUNC_SELECT_ARGTYPES +AC_FUNC_STAT +AC_FUNC_VPRINTF +AC_HEADER_STDBOOL +AC_HEADER_STDC +AC_HEADER_TIME +AC_PROG_GCC_TRADITIONAL +AC_PROG_LIBTOOL + +# Checks for libraries. +PKG_CHECK_MODULES(GST, gstreamer-0.10 >= 0.10) +AC_SUBST(GST_CFLAGS) +AC_SUBST(GST_LIBS) + +PKG_CHECK_MODULES(GST_PLUGIN_BASE, gstreamer-base-0.10 >= 0.10) +AC_SUBST(GST_PLUGIN_BASE_CFLAGS) +AC_SUBST(GST_PLUGIN_BASE_LIBS) + +PKG_CHECK_MODULES(GST_INTERFACES, gstreamer-interfaces-0.10 >= 0.10) +AC_SUBST(GST_INTERFACES_CFLAGS) +AC_SUBST(GST_INTERFACES_LIBS) + +#PKG_CHECK_MODULES(GTK, gtk+-2.0) +#AC_SUBST(GTK_CFLAGS) +#AC_SUBST(GTK_LIBS) + +PKG_CHECK_MODULES(MM_COMMON, mm-common) +AC_SUBST(MM_COMMON_CFLAGS) +AC_SUBST(MM_COMMON_LIBS) + +PKG_CHECK_MODULES(MM_LOG, mm-log) +AC_SUBST(MM_LOG_CFLAGS) +AC_SUBST(MM_LOG_LIBS) + +PKG_CHECK_MODULES(MMTA, mm-ta) +AC_SUBST(MMTA_CFLAGS) +AC_SUBST(MMTA_LIBS) + +PKG_CHECK_MODULES(MM_SOUND, mm-sound) +AC_SUBST(MM_SOUND_CFLAGS) +AC_SUBST(MM_SOUND_LIBS) + +#PKG_CHECK_MODULES(INIPARSER, iniparser) +#AC_SUBST(INIPARSER_CFLAGS) +#AC_SUBST(INIPARSER_LIBS) + +PKG_CHECK_MODULES(EXIF, libexif) +AC_SUBST(EXIF_CFLAGS) +AC_SUBST(EXIF_LIBS) + +PKG_CHECK_MODULES(GLIB, glib-2.0) +AC_SUBST(GLIB_CFLAGS) +AC_SUBST(GLIB_LIBS) + +PKG_CHECK_MODULES(MMSESSION, mm-session) +AC_SUBST(MMSESSION_CFLAGS) +AC_SUBST(MMSESSION_LIBS) + +PKG_CHECK_MODULES(AUDIOSESSIONMGR, audio-session-mgr) +AC_SUBST(AUDIOSESSIONMGR_CFLAGS) +AC_SUBST(AUDIOSESSIONMGR_LIBS) + +PKG_CHECK_MODULES(MMSOUND, mm-sound) +AC_SUBST(MMSOUND_CFLAGS) +AC_SUBST(MMSOUND_LIBS) + +PKG_CHECK_MODULES(SNDFILE, sndfile) +AC_SUBST(SNDFILE_CFLAGS) +AC_SUBST(SNDFILE_LIBS) + +PKG_CHECK_MODULES(CAMSRCJPEGENC, camsrcjpegenc) +AC_SUBST(CAMSRCJPEGENC_CFLAGS) +AC_SUBST(CAMSRCJPEGENC_LIBS) + + +# Checks for header files. +AC_HEADER_STDC +AC_CHECK_HEADERS([fcntl.h memory.h stdlib.h string.h sys/time.h unistd.h]) + +# Checks for typedefs, structures, and compiler characteristics. +AC_C_CONST +AC_TYPE_PID_T +AC_TYPE_SIZE_T + +# Checks for library functions. +AC_FUNC_ALLOCA +AC_FUNC_FORK +AC_FUNC_MALLOC +AC_FUNC_MEMCMP +AC_FUNC_SELECT_ARGTYPES +AC_TYPE_SIGNAL +AC_CHECK_FUNCS([memset select]) +AC_CONFIG_FILES([ +Makefile +src/Makefile +test/Makefile +mm-camcorder.pc +]) +AC_OUTPUT diff --git a/debian/changelog b/debian/changelog new file mode 100644 index 0000000..7e8f67a --- /dev/null +++ b/debian/changelog @@ -0,0 +1,8 @@ +libmm-camcorder (0.5.38-0) unstable; urgency=low + + * Initial release + * Git: pkgs/l/libmm-camcorder + * Tag: libmm-camcorder_0.5.38-0 + + -- Jeongmo Yang Wed, 08 Feb 2012 20:37:45 +0900 + diff --git a/debian/compat b/debian/compat new file mode 100644 index 0000000..7ed6ff8 --- /dev/null +++ b/debian/compat @@ -0,0 +1 @@ +5 diff --git a/debian/control b/debian/control new file mode 100644 index 0000000..29564c4 --- /dev/null +++ b/debian/control @@ -0,0 +1,27 @@ +Source: libmm-camcorder +Section: libs +Priority: extra +Maintainer: Jeongmo Yang , JongHyuk Choi , Sangchul Lee +Uploaders: Seungbae Shin +Build-Depends: debhelper (>= 5), autotools-dev, libmm-common-dev, libmm-common-internal-dev, libmm-log-dev, libexif-dev, libgstreamer-plugins-base0.10-dev, libmm-ta-dev, libmm-sound-dev, libmm-session-dev, libaudiosessionmgr-dev (>=0.1.1), libcamsrcjpegenc-dev, libsndfile1-dev +Standards-Version: 3.7.2 +Homepage: N/A + +Package: libmm-camcorder-dev +Section: libdevel +Architecture: any +Depends: libmm-camcorder (= ${Source-Version}), libmm-common-dev, libmm-log-sdk-dev, libexif-dev, libgstreamer-plugins-base0.10-sdk-dev, libmm-ta-sdk-dev, libmm-sound-sdk-dev, libmm-session-sdk-dev, libaudiosessionmgr-sdk-dev (>=0.1.1) +XB-Generate-Docs: yes +Description: camcorder development library + +Package: libmm-camcorder +Section: libs +Architecture: any +Depends: ${shlibs:Depends}, ${misc:Depends},libmm-common, libmm-log, libexif12, libgstreamer-plugins-base0.10-0, libmm-ta, libmm-sound-0, libmm-session-0, libaudiosessionmgr-0 (>=0.1.1), libcamsrcjpegenc, libsndfile1 +Description: camcorder library + +Package: libmm-camcorder-dbg +Section: debug +Architecture: any +Depends: ${shlibs:Depends}, ${misc:Depends}, libmm-camcorder (= ${Source-Version}) +Description: Camcorder Debug Library (unstripped) diff --git a/debian/copyright b/debian/copyright new file mode 100644 index 0000000..2db5a49 --- /dev/null +++ b/debian/copyright @@ -0,0 +1,16 @@ +Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + +Contact: Jeongmo Yang + +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. + diff --git a/debian/dirs b/debian/dirs new file mode 100644 index 0000000..ca882bb --- /dev/null +++ b/debian/dirs @@ -0,0 +1,2 @@ +usr/bin +usr/sbin diff --git a/debian/docs b/debian/docs new file mode 100644 index 0000000..e69de29 diff --git a/debian/libmm-camcorder-dev.install.in b/debian/libmm-camcorder-dev.install.in new file mode 100644 index 0000000..d211184 --- /dev/null +++ b/debian/libmm-camcorder-dev.install.in @@ -0,0 +1,5 @@ +# if your module creates shared libraries +@PREFIX@/include/mmf/* +@PREFIX@/lib/*.*a +@PREFIX@/lib/pkgconfig/* + diff --git a/debian/libmm-camcorder.install.in b/debian/libmm-camcorder.install.in new file mode 100644 index 0000000..43c7eb7 --- /dev/null +++ b/debian/libmm-camcorder.install.in @@ -0,0 +1,5 @@ +# if your module, creates shared libraries +@PREFIX@/lib/*.so* +@PREFIX@/bin/* +@PREFIX@/share/sounds/mm-camcorder/* + diff --git a/debian/rules b/debian/rules new file mode 100755 index 0000000..30ec259 --- /dev/null +++ b/debian/rules @@ -0,0 +1,138 @@ +#!/usr/bin/make -f +# -*- makefile -*- +# Sample debian/rules that uses debhelper. +# This file was originally written by Joey Hess and Craig Small. +# As a special exception, when this file is copied by dh-make into a +# dh-make output file, you may use that output file without restriction. +# This special exception was added by Craig Small in version 0.37 of dh-make. + +# Uncomment this to turn on verbose mode. +#export DH_VERBOSE=1 + + +# These are used for cross-compiling and for saving the configure script +# from having to guess our platform (since we know it already) +DEB_HOST_GNU_TYPE ?= $(shell dpkg-architecture -qDEB_HOST_GNU_TYPE) +DEB_BUILD_GNU_TYPE ?= $(shell dpkg-architecture -qDEB_BUILD_GNU_TYPE) +DEB_HOST_ARCH ?= $(shell dpkg-architecture -qDEB_HOST_ARCH) +DEB_HOST_ARCH_OS ?= $(shell dpkg-architecture -qDEB_HOST_GNU_OS) + +CFLAGS = -Wall -g +LDFLAGS ?= +PREFIX ?= /usr + +ifneq (,$(findstring noopt,$(DEB_BUILD_OPTIONS))) + CFLAGS += -O0 +else + CFLAGS += -O2 +endif + +# architecture is not arm +ifneq (, $(findstring arm, $(DEB_HOST_ARCH))) + # do something here for arm architecture + OPTION= --enable-aquila +else + # do something here + OPTION= --enable-aquila --enable-sdk +endif +CFLAGS += -fPIC +LDFLAGS +=-Wl,--rpath=$(PREFIX)/lib -Wl,--as-needed -Wl,-z,defs -Wl,--hash-style=both + +# shared library versions, option 1 +version=2.0.5 +major=2 +# option 2, assuming the library is created as src/.libs/libfoo.so.2.0.5 or so +#version=`ls src/.libs/lib*.so.* | \ +# awk '{if (match($$0,/[0-9]+\.[0-9]+\.[0-9]+$$/)) print substr($$0,RSTART)}'` +#major=`ls src/.libs/lib*.so.* | \ +# awk '{if (match($$0,/\.so\.[0-9]+$$/)) print substr($$0,RSTART+4)}'` + +config.status: + dh_testdir + ./autogen.sh + # Add here commands to configure the package. + ./configure --prefix=/usr $(OPTION) --mandir=\$${prefix}/share/man --infodir=\$${prefix}/share/info CFLAGS="$(CFLAGS) -DGST_EXT_TIME_ANALYSIS" LDFLAGS="$(LDFLAGS)" + + +build: build-stamp +build-stamp: config.status + dh_testdir + + # Add here commands to compile the package. + $(MAKE) + + for f in `find $(CURDIR)/debian/ -name "*.in"`; do \ + cat $$f > $${f%.in}; \ + sed -i -e "s#@PREFIX@#$(PREFIX)#g" $${f%.in}; \ + sed -i -e "s#@DATADIR@#$(DATADIR)#g" $${f%.in}; \ + done + + touch $@ + +clean: + dh_testdir + dh_testroot + rm -f build-stamp + + # Add here commands to clean up after the build process. + -$(MAKE) distclean +ifneq "$(wildcard /usr/share/misc/config.sub)" "" + cp -f /usr/share/misc/config.sub config.sub +endif +ifneq "$(wildcard /usr/share/misc/config.guess)" "" + cp -f /usr/share/misc/config.guess config.guess +endif + + for f in `find $(CURDIR)/debian/ -name "*.in"`; do \ + rm -f $${f%.in}; \ + done + + dh_clean + +install: build + dh_testdir + dh_testroot + dh_clean -k + dh_installdirs + + # Add here commands to install the package into debian/tmp + $(MAKE) DESTDIR=$(CURDIR)/debian/tmp install + + +# Build architecture-independent files here. +binary-indep: build install +# We have nothing to do by default. + +# Build architecture-dependent files here. +binary-arch: build install + dh_testdir + dh_testroot + dh_installchangelogs + dh_installdocs + dh_installexamples + dh_install --sourcedir=debian/tmp +# dh_installmenu +# dh_installdebconf +# dh_installlogrotate +# dh_installemacsen +# dh_installpam +# dh_installmime +# dh_installinit +# dh_installcron +# dh_installinfo + dh_installman + dh_link + dh_strip --dbg-package=libmm-camcorder-dbg + dh_compress + dh_fixperms +# dh_perl +# dh_python + dh_makeshlibs + dh_installdeb + dh_shlibdeps + dh_gencontrol + dh_md5sums + dh_builddeb + +binary: binary-indep binary-arch +.PHONY: build clean binary-indep binary-arch binary install diff --git a/depcomp b/depcomp new file mode 100755 index 0000000..e5f9736 --- /dev/null +++ b/depcomp @@ -0,0 +1,589 @@ +#! /bin/sh +# depcomp - compile a program generating dependencies as side-effects + +scriptversion=2007-03-29.01 + +# Copyright (C) 1999, 2000, 2003, 2004, 2005, 2006, 2007 Free Software +# Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +# 02110-1301, USA. + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# Originally written by Alexandre Oliva . + +case $1 in + '') + echo "$0: No command. Try \`$0 --help' for more information." 1>&2 + exit 1; + ;; + -h | --h*) + cat <<\EOF +Usage: depcomp [--help] [--version] PROGRAM [ARGS] + +Run PROGRAMS ARGS to compile a file, generating dependencies +as side-effects. + +Environment variables: + depmode Dependency tracking mode. + source Source file read by `PROGRAMS ARGS'. + object Object file output by `PROGRAMS ARGS'. + DEPDIR directory where to store dependencies. + depfile Dependency file to output. + tmpdepfile Temporary file to use when outputing dependencies. + libtool Whether libtool is used (yes/no). + +Report bugs to . +EOF + exit $? + ;; + -v | --v*) + echo "depcomp $scriptversion" + exit $? + ;; +esac + +if test -z "$depmode" || test -z "$source" || test -z "$object"; then + echo "depcomp: Variables source, object and depmode must be set" 1>&2 + exit 1 +fi + +# Dependencies for sub/bar.o or sub/bar.obj go into sub/.deps/bar.Po. +depfile=${depfile-`echo "$object" | + sed 's|[^\\/]*$|'${DEPDIR-.deps}'/&|;s|\.\([^.]*\)$|.P\1|;s|Pobj$|Po|'`} +tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`} + +rm -f "$tmpdepfile" + +# Some modes work just like other modes, but use different flags. We +# parameterize here, but still list the modes in the big case below, +# to make depend.m4 easier to write. Note that we *cannot* use a case +# here, because this file can only contain one case statement. +if test "$depmode" = hp; then + # HP compiler uses -M and no extra arg. + gccflag=-M + depmode=gcc +fi + +if test "$depmode" = dashXmstdout; then + # This is just like dashmstdout with a different argument. + dashmflag=-xM + depmode=dashmstdout +fi + +case "$depmode" in +gcc3) +## gcc 3 implements dependency tracking that does exactly what +## we want. Yay! Note: for some reason libtool 1.4 doesn't like +## it if -MD -MP comes after the -MF stuff. Hmm. +## Unfortunately, FreeBSD c89 acceptance of flags depends upon +## the command line argument order; so add the flags where they +## appear in depend2.am. Note that the slowdown incurred here +## affects only configure: in makefiles, %FASTDEP% shortcuts this. + for arg + do + case $arg in + -c) set fnord "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" "$arg" ;; + *) set fnord "$@" "$arg" ;; + esac + shift # fnord + shift # $arg + done + "$@" + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile" + exit $stat + fi + mv "$tmpdepfile" "$depfile" + ;; + +gcc) +## There are various ways to get dependency output from gcc. Here's +## why we pick this rather obscure method: +## - Don't want to use -MD because we'd like the dependencies to end +## up in a subdir. Having to rename by hand is ugly. +## (We might end up doing this anyway to support other compilers.) +## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like +## -MM, not -M (despite what the docs say). +## - Using -M directly means running the compiler twice (even worse +## than renaming). + if test -z "$gccflag"; then + gccflag=-MD, + fi + "$@" -Wp,"$gccflag$tmpdepfile" + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + echo "$object : \\" > "$depfile" + alpha=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz +## The second -e expression handles DOS-style file names with drive letters. + sed -e 's/^[^:]*: / /' \ + -e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile" +## This next piece of magic avoids the `deleted header file' problem. +## The problem is that when a header file which appears in a .P file +## is deleted, the dependency causes make to die (because there is +## typically no way to rebuild the header). We avoid this by adding +## dummy dependencies for each header file. Too bad gcc doesn't do +## this for us directly. + tr ' ' ' +' < "$tmpdepfile" | +## Some versions of gcc put a space before the `:'. On the theory +## that the space means something, we add a space to the output as +## well. +## Some versions of the HPUX 10.20 sed can't process this invocation +## correctly. Breaking it into two sed invocations is a workaround. + sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +hp) + # This case exists only to let depend.m4 do its work. It works by + # looking at the text of this script. This case will never be run, + # since it is checked for above. + exit 1 + ;; + +sgi) + if test "$libtool" = yes; then + "$@" "-Wp,-MDupdate,$tmpdepfile" + else + "$@" -MDupdate "$tmpdepfile" + fi + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + + if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files + echo "$object : \\" > "$depfile" + + # Clip off the initial element (the dependent). Don't try to be + # clever and replace this with sed code, as IRIX sed won't handle + # lines with more than a fixed number of characters (4096 in + # IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines; + # the IRIX cc adds comments like `#:fec' to the end of the + # dependency line. + tr ' ' ' +' < "$tmpdepfile" \ + | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' | \ + tr ' +' ' ' >> $depfile + echo >> $depfile + + # The second pass generates a dummy entry for each header file. + tr ' ' ' +' < "$tmpdepfile" \ + | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \ + >> $depfile + else + # The sourcefile does not contain any dependencies, so just + # store a dummy comment line, to avoid errors with the Makefile + # "include basename.Plo" scheme. + echo "#dummy" > "$depfile" + fi + rm -f "$tmpdepfile" + ;; + +aix) + # The C for AIX Compiler uses -M and outputs the dependencies + # in a .u file. In older versions, this file always lives in the + # current directory. Also, the AIX compiler puts `$object:' at the + # start of each line; $object doesn't have directory information. + # Version 6 uses the directory in both cases. + dir=`echo "$object" | sed -e 's|/[^/]*$|/|'` + test "x$dir" = "x$object" && dir= + base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'` + if test "$libtool" = yes; then + tmpdepfile1=$dir$base.u + tmpdepfile2=$base.u + tmpdepfile3=$dir.libs/$base.u + "$@" -Wc,-M + else + tmpdepfile1=$dir$base.u + tmpdepfile2=$dir$base.u + tmpdepfile3=$dir$base.u + "$@" -M + fi + stat=$? + + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" + exit $stat + fi + + for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" + do + test -f "$tmpdepfile" && break + done + if test -f "$tmpdepfile"; then + # Each line is of the form `foo.o: dependent.h'. + # Do two passes, one to just change these to + # `$object: dependent.h' and one to simply `dependent.h:'. + sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile" + # That's a tab and a space in the []. + sed -e 's,^.*\.[a-z]*:[ ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile" + else + # The sourcefile does not contain any dependencies, so just + # store a dummy comment line, to avoid errors with the Makefile + # "include basename.Plo" scheme. + echo "#dummy" > "$depfile" + fi + rm -f "$tmpdepfile" + ;; + +icc) + # Intel's C compiler understands `-MD -MF file'. However on + # icc -MD -MF foo.d -c -o sub/foo.o sub/foo.c + # ICC 7.0 will fill foo.d with something like + # foo.o: sub/foo.c + # foo.o: sub/foo.h + # which is wrong. We want: + # sub/foo.o: sub/foo.c + # sub/foo.o: sub/foo.h + # sub/foo.c: + # sub/foo.h: + # ICC 7.1 will output + # foo.o: sub/foo.c sub/foo.h + # and will wrap long lines using \ : + # foo.o: sub/foo.c ... \ + # sub/foo.h ... \ + # ... + + "$@" -MD -MF "$tmpdepfile" + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + # Each line is of the form `foo.o: dependent.h', + # or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'. + # Do two passes, one to just change these to + # `$object: dependent.h' and one to simply `dependent.h:'. + sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile" + # Some versions of the HPUX 10.20 sed can't process this invocation + # correctly. Breaking it into two sed invocations is a workaround. + sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" | + sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +hp2) + # The "hp" stanza above does not work with aCC (C++) and HP's ia64 + # compilers, which have integrated preprocessors. The correct option + # to use with these is +Maked; it writes dependencies to a file named + # 'foo.d', which lands next to the object file, wherever that + # happens to be. + # Much of this is similar to the tru64 case; see comments there. + dir=`echo "$object" | sed -e 's|/[^/]*$|/|'` + test "x$dir" = "x$object" && dir= + base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'` + if test "$libtool" = yes; then + tmpdepfile1=$dir$base.d + tmpdepfile2=$dir.libs/$base.d + "$@" -Wc,+Maked + else + tmpdepfile1=$dir$base.d + tmpdepfile2=$dir$base.d + "$@" +Maked + fi + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile1" "$tmpdepfile2" + exit $stat + fi + + for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" + do + test -f "$tmpdepfile" && break + done + if test -f "$tmpdepfile"; then + sed -e "s,^.*\.[a-z]*:,$object:," "$tmpdepfile" > "$depfile" + # Add `dependent.h:' lines. + sed -ne '2,${; s/^ *//; s/ \\*$//; s/$/:/; p;}' "$tmpdepfile" >> "$depfile" + else + echo "#dummy" > "$depfile" + fi + rm -f "$tmpdepfile" "$tmpdepfile2" + ;; + +tru64) + # The Tru64 compiler uses -MD to generate dependencies as a side + # effect. `cc -MD -o foo.o ...' puts the dependencies into `foo.o.d'. + # At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put + # dependencies in `foo.d' instead, so we check for that too. + # Subdirectories are respected. + dir=`echo "$object" | sed -e 's|/[^/]*$|/|'` + test "x$dir" = "x$object" && dir= + base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'` + + if test "$libtool" = yes; then + # With Tru64 cc, shared objects can also be used to make a + # static library. This mechanism is used in libtool 1.4 series to + # handle both shared and static libraries in a single compilation. + # With libtool 1.4, dependencies were output in $dir.libs/$base.lo.d. + # + # With libtool 1.5 this exception was removed, and libtool now + # generates 2 separate objects for the 2 libraries. These two + # compilations output dependencies in $dir.libs/$base.o.d and + # in $dir$base.o.d. We have to check for both files, because + # one of the two compilations can be disabled. We should prefer + # $dir$base.o.d over $dir.libs/$base.o.d because the latter is + # automatically cleaned when .libs/ is deleted, while ignoring + # the former would cause a distcleancheck panic. + tmpdepfile1=$dir.libs/$base.lo.d # libtool 1.4 + tmpdepfile2=$dir$base.o.d # libtool 1.5 + tmpdepfile3=$dir.libs/$base.o.d # libtool 1.5 + tmpdepfile4=$dir.libs/$base.d # Compaq CCC V6.2-504 + "$@" -Wc,-MD + else + tmpdepfile1=$dir$base.o.d + tmpdepfile2=$dir$base.d + tmpdepfile3=$dir$base.d + tmpdepfile4=$dir$base.d + "$@" -MD + fi + + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" "$tmpdepfile4" + exit $stat + fi + + for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" "$tmpdepfile4" + do + test -f "$tmpdepfile" && break + done + if test -f "$tmpdepfile"; then + sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile" + # That's a tab and a space in the []. + sed -e 's,^.*\.[a-z]*:[ ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile" + else + echo "#dummy" > "$depfile" + fi + rm -f "$tmpdepfile" + ;; + +#nosideeffect) + # This comment above is used by automake to tell side-effect + # dependency tracking mechanisms from slower ones. + +dashmstdout) + # Important note: in order to support this mode, a compiler *must* + # always write the preprocessed file to stdout, regardless of -o. + "$@" || exit $? + + # Remove the call to Libtool. + if test "$libtool" = yes; then + while test $1 != '--mode=compile'; do + shift + done + shift + fi + + # Remove `-o $object'. + IFS=" " + for arg + do + case $arg in + -o) + shift + ;; + $object) + shift + ;; + *) + set fnord "$@" "$arg" + shift # fnord + shift # $arg + ;; + esac + done + + test -z "$dashmflag" && dashmflag=-M + # Require at least two characters before searching for `:' + # in the target name. This is to cope with DOS-style filenames: + # a dependency such as `c:/foo/bar' could be seen as target `c' otherwise. + "$@" $dashmflag | + sed 's:^[ ]*[^: ][^:][^:]*\:[ ]*:'"$object"'\: :' > "$tmpdepfile" + rm -f "$depfile" + cat < "$tmpdepfile" > "$depfile" + tr ' ' ' +' < "$tmpdepfile" | \ +## Some versions of the HPUX 10.20 sed can't process this invocation +## correctly. Breaking it into two sed invocations is a workaround. + sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +dashXmstdout) + # This case only exists to satisfy depend.m4. It is never actually + # run, as this mode is specially recognized in the preamble. + exit 1 + ;; + +makedepend) + "$@" || exit $? + # Remove any Libtool call + if test "$libtool" = yes; then + while test $1 != '--mode=compile'; do + shift + done + shift + fi + # X makedepend + shift + cleared=no + for arg in "$@"; do + case $cleared in + no) + set ""; shift + cleared=yes ;; + esac + case "$arg" in + -D*|-I*) + set fnord "$@" "$arg"; shift ;; + # Strip any option that makedepend may not understand. Remove + # the object too, otherwise makedepend will parse it as a source file. + -*|$object) + ;; + *) + set fnord "$@" "$arg"; shift ;; + esac + done + obj_suffix="`echo $object | sed 's/^.*\././'`" + touch "$tmpdepfile" + ${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@" + rm -f "$depfile" + cat < "$tmpdepfile" > "$depfile" + sed '1,2d' "$tmpdepfile" | tr ' ' ' +' | \ +## Some versions of the HPUX 10.20 sed can't process this invocation +## correctly. Breaking it into two sed invocations is a workaround. + sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" "$tmpdepfile".bak + ;; + +cpp) + # Important note: in order to support this mode, a compiler *must* + # always write the preprocessed file to stdout. + "$@" || exit $? + + # Remove the call to Libtool. + if test "$libtool" = yes; then + while test $1 != '--mode=compile'; do + shift + done + shift + fi + + # Remove `-o $object'. + IFS=" " + for arg + do + case $arg in + -o) + shift + ;; + $object) + shift + ;; + *) + set fnord "$@" "$arg" + shift # fnord + shift # $arg + ;; + esac + done + + "$@" -E | + sed -n -e '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \ + -e '/^#line [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' | + sed '$ s: \\$::' > "$tmpdepfile" + rm -f "$depfile" + echo "$object : \\" > "$depfile" + cat < "$tmpdepfile" >> "$depfile" + sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +msvisualcpp) + # Important note: in order to support this mode, a compiler *must* + # always write the preprocessed file to stdout, regardless of -o, + # because we must use -o when running libtool. + "$@" || exit $? + IFS=" " + for arg + do + case "$arg" in + "-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI") + set fnord "$@" + shift + shift + ;; + *) + set fnord "$@" "$arg" + shift + shift + ;; + esac + done + "$@" -E | + sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::echo "`cygpath -u \\"\1\\"`":p' | sort | uniq > "$tmpdepfile" + rm -f "$depfile" + echo "$object : \\" > "$depfile" + . "$tmpdepfile" | sed 's% %\\ %g' | sed -n '/^\(.*\)$/ s:: \1 \\:p' >> "$depfile" + echo " " >> "$depfile" + . "$tmpdepfile" | sed 's% %\\ %g' | sed -n '/^\(.*\)$/ s::\1\::p' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +none) + exec "$@" + ;; + +*) + echo "Unknown depmode $depmode" 1>&2 + exit 1 + ;; +esac + +exit 0 + +# Local Variables: +# mode: shell-script +# sh-indentation: 2 +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-end: "$" +# End: diff --git a/image/camcorder_state.png b/image/camcorder_state.png new file mode 100755 index 0000000000000000000000000000000000000000..0b24da94581697fbcfa69719bc168d3e29df31a5 GIT binary patch literal 33655 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 z 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 Z9&_bWUOa^elCfR|39CRQt$u( literal 0 HcmV?d00001 diff --git a/install-sh b/install-sh new file mode 100755 index 0000000..a5897de --- /dev/null +++ b/install-sh @@ -0,0 +1,519 @@ +#!/bin/sh +# install - install a program, script, or datafile + +scriptversion=2006-12-25.00 + +# This originates from X11R5 (mit/util/scripts/install.sh), which was +# later released in X11R6 (xc/config/util/install.sh) with the +# following copyright and license. +# +# Copyright (C) 1994 X Consortium +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to +# deal in the Software without restriction, including without limitation the +# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +# sell copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- +# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# +# Except as contained in this notice, the name of the X Consortium shall not +# be used in advertising or otherwise to promote the sale, use or other deal- +# ings in this Software without prior written authorization from the X Consor- +# tium. +# +# +# FSF changes to this file are in the public domain. +# +# Calling this script install-sh is preferred over install.sh, to prevent +# `make' implicit rules from creating a file called install from it +# when there is no Makefile. +# +# This script is compatible with the BSD install script, but was written +# from scratch. + +nl=' +' +IFS=" "" $nl" + +# set DOITPROG to echo to test this script + +# Don't use :- since 4.3BSD and earlier shells don't like it. +doit=${DOITPROG-} +if test -z "$doit"; then + doit_exec=exec +else + doit_exec=$doit +fi + +# Put in absolute file names if you don't have them in your path; +# or use environment vars. + +chgrpprog=${CHGRPPROG-chgrp} +chmodprog=${CHMODPROG-chmod} +chownprog=${CHOWNPROG-chown} +cmpprog=${CMPPROG-cmp} +cpprog=${CPPROG-cp} +mkdirprog=${MKDIRPROG-mkdir} +mvprog=${MVPROG-mv} +rmprog=${RMPROG-rm} +stripprog=${STRIPPROG-strip} + +posix_glob='?' +initialize_posix_glob=' + test "$posix_glob" != "?" || { + if (set -f) 2>/dev/null; then + posix_glob= + else + posix_glob=: + fi + } +' + +posix_mkdir= + +# Desired mode of installed file. +mode=0755 + +chgrpcmd= +chmodcmd=$chmodprog +chowncmd= +mvcmd=$mvprog +rmcmd="$rmprog -f" +stripcmd= + +src= +dst= +dir_arg= +dst_arg= + +copy_on_change=false +no_target_directory= + +usage="\ +Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE + or: $0 [OPTION]... SRCFILES... DIRECTORY + or: $0 [OPTION]... -t DIRECTORY SRCFILES... + or: $0 [OPTION]... -d DIRECTORIES... + +In the 1st form, copy SRCFILE to DSTFILE. +In the 2nd and 3rd, copy all SRCFILES to DIRECTORY. +In the 4th, create DIRECTORIES. + +Options: + --help display this help and exit. + --version display version info and exit. + + -c (ignored) + -C install only if different (preserve the last data modification time) + -d create directories instead of installing files. + -g GROUP $chgrpprog installed files to GROUP. + -m MODE $chmodprog installed files to MODE. + -o USER $chownprog installed files to USER. + -s $stripprog installed files. + -t DIRECTORY install into DIRECTORY. + -T report an error if DSTFILE is a directory. + +Environment variables override the default commands: + CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG + RMPROG STRIPPROG +" + +while test $# -ne 0; do + case $1 in + -c) ;; + + -C) copy_on_change=true;; + + -d) dir_arg=true;; + + -g) chgrpcmd="$chgrpprog $2" + shift;; + + --help) echo "$usage"; exit $?;; + + -m) mode=$2 + case $mode in + *' '* | *' '* | *' +'* | *'*'* | *'?'* | *'['*) + echo "$0: invalid mode: $mode" >&2 + exit 1;; + esac + shift;; + + -o) chowncmd="$chownprog $2" + shift;; + + -s) stripcmd=$stripprog;; + + -t) dst_arg=$2 + shift;; + + -T) no_target_directory=true;; + + --version) echo "$0 $scriptversion"; exit $?;; + + --) shift + break;; + + -*) echo "$0: invalid option: $1" >&2 + exit 1;; + + *) break;; + esac + shift +done + +if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then + # When -d is used, all remaining arguments are directories to create. + # When -t is used, the destination is already specified. + # Otherwise, the last argument is the destination. Remove it from $@. + for arg + do + if test -n "$dst_arg"; then + # $@ is not empty: it contains at least $arg. + set fnord "$@" "$dst_arg" + shift # fnord + fi + shift # arg + dst_arg=$arg + done +fi + +if test $# -eq 0; then + if test -z "$dir_arg"; then + echo "$0: no input file specified." >&2 + exit 1 + fi + # It's OK to call `install-sh -d' without argument. + # This can happen when creating conditional directories. + exit 0 +fi + +if test -z "$dir_arg"; then + trap '(exit $?); exit' 1 2 13 15 + + # Set umask so as not to create temps with too-generous modes. + # However, 'strip' requires both read and write access to temps. + case $mode in + # Optimize common cases. + *644) cp_umask=133;; + *755) cp_umask=22;; + + *[0-7]) + if test -z "$stripcmd"; then + u_plus_rw= + else + u_plus_rw='% 200' + fi + cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;; + *) + if test -z "$stripcmd"; then + u_plus_rw= + else + u_plus_rw=,u+rw + fi + cp_umask=$mode$u_plus_rw;; + esac +fi + +for src +do + # Protect names starting with `-'. + case $src in + -*) src=./$src;; + esac + + if test -n "$dir_arg"; then + dst=$src + dstdir=$dst + test -d "$dstdir" + dstdir_status=$? + else + + # Waiting for this to be detected by the "$cpprog $src $dsttmp" command + # might cause directories to be created, which would be especially bad + # if $src (and thus $dsttmp) contains '*'. + if test ! -f "$src" && test ! -d "$src"; then + echo "$0: $src does not exist." >&2 + exit 1 + fi + + if test -z "$dst_arg"; then + echo "$0: no destination specified." >&2 + exit 1 + fi + + dst=$dst_arg + # Protect names starting with `-'. + case $dst in + -*) dst=./$dst;; + esac + + # If destination is a directory, append the input filename; won't work + # if double slashes aren't ignored. + if test -d "$dst"; then + if test -n "$no_target_directory"; then + echo "$0: $dst_arg: Is a directory" >&2 + exit 1 + fi + dstdir=$dst + dst=$dstdir/`basename "$src"` + dstdir_status=0 + else + # Prefer dirname, but fall back on a substitute if dirname fails. + dstdir=` + (dirname "$dst") 2>/dev/null || + expr X"$dst" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$dst" : 'X\(//\)[^/]' \| \ + X"$dst" : 'X\(//\)$' \| \ + X"$dst" : 'X\(/\)' \| . 2>/dev/null || + echo X"$dst" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q' + ` + + test -d "$dstdir" + dstdir_status=$? + fi + fi + + obsolete_mkdir_used=false + + if test $dstdir_status != 0; then + case $posix_mkdir in + '') + # Create intermediate dirs using mode 755 as modified by the umask. + # This is like FreeBSD 'install' as of 1997-10-28. + umask=`umask` + case $stripcmd.$umask in + # Optimize common cases. + *[2367][2367]) mkdir_umask=$umask;; + .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;; + + *[0-7]) + mkdir_umask=`expr $umask + 22 \ + - $umask % 100 % 40 + $umask % 20 \ + - $umask % 10 % 4 + $umask % 2 + `;; + *) mkdir_umask=$umask,go-w;; + esac + + # With -d, create the new directory with the user-specified mode. + # Otherwise, rely on $mkdir_umask. + if test -n "$dir_arg"; then + mkdir_mode=-m$mode + else + mkdir_mode= + fi + + posix_mkdir=false + case $umask in + *[123567][0-7][0-7]) + # POSIX mkdir -p sets u+wx bits regardless of umask, which + # is incompatible with FreeBSD 'install' when (umask & 300) != 0. + ;; + *) + tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$ + trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0 + + if (umask $mkdir_umask && + exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1 + then + if test -z "$dir_arg" || { + # Check for POSIX incompatibilities with -m. + # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or + # other-writeable bit of parent directory when it shouldn't. + # FreeBSD 6.1 mkdir -m -p sets mode of existing directory. + ls_ld_tmpdir=`ls -ld "$tmpdir"` + case $ls_ld_tmpdir in + d????-?r-*) different_mode=700;; + d????-?--*) different_mode=755;; + *) false;; + esac && + $mkdirprog -m$different_mode -p -- "$tmpdir" && { + ls_ld_tmpdir_1=`ls -ld "$tmpdir"` + test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1" + } + } + then posix_mkdir=: + fi + rmdir "$tmpdir/d" "$tmpdir" + else + # Remove any dirs left behind by ancient mkdir implementations. + rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null + fi + trap '' 0;; + esac;; + esac + + if + $posix_mkdir && ( + umask $mkdir_umask && + $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir" + ) + then : + else + + # The umask is ridiculous, or mkdir does not conform to POSIX, + # or it failed possibly due to a race condition. Create the + # directory the slow way, step by step, checking for races as we go. + + case $dstdir in + /*) prefix='/';; + -*) prefix='./';; + *) prefix='';; + esac + + eval "$initialize_posix_glob" + + oIFS=$IFS + IFS=/ + $posix_glob set -f + set fnord $dstdir + shift + $posix_glob set +f + IFS=$oIFS + + prefixes= + + for d + do + test -z "$d" && continue + + prefix=$prefix$d + if test -d "$prefix"; then + prefixes= + else + if $posix_mkdir; then + (umask=$mkdir_umask && + $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break + # Don't fail if two instances are running concurrently. + test -d "$prefix" || exit 1 + else + case $prefix in + *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;; + *) qprefix=$prefix;; + esac + prefixes="$prefixes '$qprefix'" + fi + fi + prefix=$prefix/ + done + + if test -n "$prefixes"; then + # Don't fail if two instances are running concurrently. + (umask $mkdir_umask && + eval "\$doit_exec \$mkdirprog $prefixes") || + test -d "$dstdir" || exit 1 + obsolete_mkdir_used=true + fi + fi + fi + + if test -n "$dir_arg"; then + { test -z "$chowncmd" || $doit $chowncmd "$dst"; } && + { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } && + { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false || + test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1 + else + + # Make a couple of temp file names in the proper directory. + dsttmp=$dstdir/_inst.$$_ + rmtmp=$dstdir/_rm.$$_ + + # Trap to clean up those temp files at exit. + trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 + + # Copy the file name to the temp name. + (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") && + + # and set any options; do chmod last to preserve setuid bits. + # + # If any of these fail, we abort the whole thing. If we want to + # ignore errors from any of these, just make sure not to ignore + # errors from the above "$doit $cpprog $src $dsttmp" command. + # + { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } && + { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } && + { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } && + { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } && + + # If -C, don't bother to copy if it wouldn't change the file. + if $copy_on_change && + old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` && + new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` && + + eval "$initialize_posix_glob" && + $posix_glob set -f && + set X $old && old=:$2:$4:$5:$6 && + set X $new && new=:$2:$4:$5:$6 && + $posix_glob set +f && + + test "$old" = "$new" && + $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1 + then + rm -f "$dsttmp" + else + # Rename the file to the real destination. + $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null || + + # The rename failed, perhaps because mv can't rename something else + # to itself, or perhaps because mv is so ancient that it does not + # support -f. + { + # Now remove or move aside any old file at destination location. + # We try this two ways since rm can't unlink itself on some + # systems and the destination file might be busy for other + # reasons. In this case, the final cleanup might fail but the new + # file should still install successfully. + { + test ! -f "$dst" || + $doit $rmcmd -f "$dst" 2>/dev/null || + { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null && + { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; } + } || + { echo "$0: cannot unlink or rename $dst" >&2 + (exit 1); exit 1 + } + } && + + # Now rename the file to the real destination. + $doit $mvcmd "$dsttmp" "$dst" + } + fi || exit 1 + + trap '' 0 + fi +done + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-end: "$" +# End: diff --git a/m4/lt~obsolete.m4 b/m4/lt~obsolete.m4 new file mode 100644 index 0000000..637bb20 --- /dev/null +++ b/m4/lt~obsolete.m4 @@ -0,0 +1,92 @@ +# lt~obsolete.m4 -- aclocal satisfying obsolete definitions. -*-Autoconf-*- +# +# Copyright (C) 2004, 2005, 2007 Free Software Foundation, Inc. +# Written by Scott James Remnant, 2004. +# +# This file is free software; the Free Software Foundation gives +# unlimited permission to copy and/or distribute it, with or without +# modifications, as long as this notice is preserved. + +# serial 4 lt~obsolete.m4 + +# These exist entirely to fool aclocal when bootstrapping libtool. +# +# In the past libtool.m4 has provided macros via AC_DEFUN (or AU_DEFUN) +# which have later been changed to m4_define as they aren't part of the +# exported API, or moved to Autoconf or Automake where they belong. +# +# The trouble is, aclocal is a bit thick. It'll see the old AC_DEFUN +# in /usr/share/aclocal/libtool.m4 and remember it, then when it sees us +# using a macro with the same name in our local m4/libtool.m4 it'll +# pull the old libtool.m4 in (it doesn't see our shiny new m4_define +# and doesn't know about Autoconf macros at all.) +# +# So we provide this file, which has a silly filename so it's always +# included after everything else. This provides aclocal with the +# AC_DEFUNs it wants, but when m4 processes it, it doesn't do anything +# because those macros already exist, or will be overwritten later. +# We use AC_DEFUN over AU_DEFUN for compatibility with aclocal-1.6. +# +# Anytime we withdraw an AC_DEFUN or AU_DEFUN, remember to add it here. +# Yes, that means every name once taken will need to remain here until +# we give up compatibility with versions before 1.7, at which point +# we need to keep only those names which we still refer to. + +# This is to help aclocal find these macros, as it can't see m4_define. +AC_DEFUN([LTOBSOLETE_VERSION], [m4_if([1])]) + +m4_ifndef([AC_LIBTOOL_LINKER_OPTION], [AC_DEFUN([AC_LIBTOOL_LINKER_OPTION])]) +m4_ifndef([AC_PROG_EGREP], [AC_DEFUN([AC_PROG_EGREP])]) +m4_ifndef([_LT_AC_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_AC_PROG_ECHO_BACKSLASH])]) +m4_ifndef([_LT_AC_SHELL_INIT], [AC_DEFUN([_LT_AC_SHELL_INIT])]) +m4_ifndef([_LT_AC_SYS_LIBPATH_AIX], [AC_DEFUN([_LT_AC_SYS_LIBPATH_AIX])]) +m4_ifndef([_LT_PROG_LTMAIN], [AC_DEFUN([_LT_PROG_LTMAIN])]) +m4_ifndef([_LT_AC_TAGVAR], [AC_DEFUN([_LT_AC_TAGVAR])]) +m4_ifndef([AC_LTDL_ENABLE_INSTALL], [AC_DEFUN([AC_LTDL_ENABLE_INSTALL])]) +m4_ifndef([AC_LTDL_PREOPEN], [AC_DEFUN([AC_LTDL_PREOPEN])]) +m4_ifndef([_LT_AC_SYS_COMPILER], [AC_DEFUN([_LT_AC_SYS_COMPILER])]) +m4_ifndef([_LT_AC_LOCK], [AC_DEFUN([_LT_AC_LOCK])]) +m4_ifndef([AC_LIBTOOL_SYS_OLD_ARCHIVE], [AC_DEFUN([AC_LIBTOOL_SYS_OLD_ARCHIVE])]) +m4_ifndef([_LT_AC_TRY_DLOPEN_SELF], [AC_DEFUN([_LT_AC_TRY_DLOPEN_SELF])]) +m4_ifndef([AC_LIBTOOL_PROG_CC_C_O], [AC_DEFUN([AC_LIBTOOL_PROG_CC_C_O])]) +m4_ifndef([AC_LIBTOOL_SYS_HARD_LINK_LOCKS], [AC_DEFUN([AC_LIBTOOL_SYS_HARD_LINK_LOCKS])]) +m4_ifndef([AC_LIBTOOL_OBJDIR], [AC_DEFUN([AC_LIBTOOL_OBJDIR])]) +m4_ifndef([AC_LTDL_OBJDIR], [AC_DEFUN([AC_LTDL_OBJDIR])]) +m4_ifndef([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH], [AC_DEFUN([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH])]) +m4_ifndef([AC_LIBTOOL_SYS_LIB_STRIP], [AC_DEFUN([AC_LIBTOOL_SYS_LIB_STRIP])]) +m4_ifndef([AC_PATH_MAGIC], [AC_DEFUN([AC_PATH_MAGIC])]) +m4_ifndef([AC_PROG_LD_GNU], [AC_DEFUN([AC_PROG_LD_GNU])]) +m4_ifndef([AC_PROG_LD_RELOAD_FLAG], [AC_DEFUN([AC_PROG_LD_RELOAD_FLAG])]) +m4_ifndef([AC_DEPLIBS_CHECK_METHOD], [AC_DEFUN([AC_DEPLIBS_CHECK_METHOD])]) +m4_ifndef([AC_LIBTOOL_PROG_COMPILER_NO_RTTI], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_NO_RTTI])]) +m4_ifndef([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE], [AC_DEFUN([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE])]) +m4_ifndef([AC_LIBTOOL_PROG_COMPILER_PIC], [AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_PIC])]) +m4_ifndef([AC_LIBTOOL_PROG_LD_SHLIBS], [AC_DEFUN([AC_LIBTOOL_PROG_LD_SHLIBS])]) +m4_ifndef([AC_LIBTOOL_POSTDEP_PREDEP], [AC_DEFUN([AC_LIBTOOL_POSTDEP_PREDEP])]) +m4_ifndef([LT_AC_PROG_EGREP], [AC_DEFUN([LT_AC_PROG_EGREP])]) +m4_ifndef([LT_AC_PROG_SED], [AC_DEFUN([LT_AC_PROG_SED])]) +m4_ifndef([_LT_CC_BASENAME], [AC_DEFUN([_LT_CC_BASENAME])]) +m4_ifndef([_LT_COMPILER_BOILERPLATE], [AC_DEFUN([_LT_COMPILER_BOILERPLATE])]) +m4_ifndef([_LT_LINKER_BOILERPLATE], [AC_DEFUN([_LT_LINKER_BOILERPLATE])]) +m4_ifndef([_AC_PROG_LIBTOOL], [AC_DEFUN([_AC_PROG_LIBTOOL])]) +m4_ifndef([AC_LIBTOOL_SETUP], [AC_DEFUN([AC_LIBTOOL_SETUP])]) +m4_ifndef([_LT_AC_CHECK_DLFCN], [AC_DEFUN([_LT_AC_CHECK_DLFCN])]) +m4_ifndef([AC_LIBTOOL_SYS_DYNAMIC_LINKER], [AC_DEFUN([AC_LIBTOOL_SYS_DYNAMIC_LINKER])]) +m4_ifndef([_LT_AC_TAGCONFIG], [AC_DEFUN([_LT_AC_TAGCONFIG])]) +m4_ifndef([AC_DISABLE_FAST_INSTALL], [AC_DEFUN([AC_DISABLE_FAST_INSTALL])]) +m4_ifndef([_LT_AC_LANG_CXX], [AC_DEFUN([_LT_AC_LANG_CXX])]) +m4_ifndef([_LT_AC_LANG_F77], [AC_DEFUN([_LT_AC_LANG_F77])]) +m4_ifndef([_LT_AC_LANG_GCJ], [AC_DEFUN([_LT_AC_LANG_GCJ])]) +m4_ifndef([AC_LIBTOOL_RC], [AC_DEFUN([AC_LIBTOOL_RC])]) +m4_ifndef([AC_LIBTOOL_LANG_C_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_C_CONFIG])]) +m4_ifndef([_LT_AC_LANG_C_CONFIG], [AC_DEFUN([_LT_AC_LANG_C_CONFIG])]) +m4_ifndef([AC_LIBTOOL_LANG_CXX_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_CXX_CONFIG])]) +m4_ifndef([_LT_AC_LANG_CXX_CONFIG], [AC_DEFUN([_LT_AC_LANG_CXX_CONFIG])]) +m4_ifndef([AC_LIBTOOL_LANG_F77_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_F77_CONFIG])]) +m4_ifndef([_LT_AC_LANG_F77_CONFIG], [AC_DEFUN([_LT_AC_LANG_F77_CONFIG])]) +m4_ifndef([AC_LIBTOOL_LANG_GCJ_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_GCJ_CONFIG])]) +m4_ifndef([_LT_AC_LANG_GCJ_CONFIG], [AC_DEFUN([_LT_AC_LANG_GCJ_CONFIG])]) +m4_ifndef([AC_LIBTOOL_LANG_RC_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_RC_CONFIG])]) +m4_ifndef([_LT_AC_LANG_RC_CONFIG], [AC_DEFUN([_LT_AC_LANG_RC_CONFIG])]) +m4_ifndef([AC_LIBTOOL_CONFIG], [AC_DEFUN([AC_LIBTOOL_CONFIG])]) +m4_ifndef([_LT_AC_FILE_LTDLL_C], [AC_DEFUN([_LT_AC_FILE_LTDLL_C])]) diff --git a/missing b/missing new file mode 100755 index 0000000..1c8ff70 --- /dev/null +++ b/missing @@ -0,0 +1,367 @@ +#! /bin/sh +# Common stub for a few missing GNU programs while installing. + +scriptversion=2006-05-10.23 + +# Copyright (C) 1996, 1997, 1999, 2000, 2002, 2003, 2004, 2005, 2006 +# Free Software Foundation, Inc. +# Originally by Fran,cois Pinard , 1996. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +# 02110-1301, USA. + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +if test $# -eq 0; then + echo 1>&2 "Try \`$0 --help' for more information" + exit 1 +fi + +run=: +sed_output='s/.* --output[ =]\([^ ]*\).*/\1/p' +sed_minuso='s/.* -o \([^ ]*\).*/\1/p' + +# In the cases where this matters, `missing' is being run in the +# srcdir already. +if test -f configure.ac; then + configure_ac=configure.ac +else + configure_ac=configure.in +fi + +msg="missing on your system" + +case $1 in +--run) + # Try to run requested program, and just exit if it succeeds. + run= + shift + "$@" && exit 0 + # Exit code 63 means version mismatch. This often happens + # when the user try to use an ancient version of a tool on + # a file that requires a minimum version. In this case we + # we should proceed has if the program had been absent, or + # if --run hadn't been passed. + if test $? = 63; then + run=: + msg="probably too old" + fi + ;; + + -h|--h|--he|--hel|--help) + echo "\ +$0 [OPTION]... PROGRAM [ARGUMENT]... + +Handle \`PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an +error status if there is no known handling for PROGRAM. + +Options: + -h, --help display this help and exit + -v, --version output version information and exit + --run try to run the given command, and emulate it if it fails + +Supported PROGRAM values: + aclocal touch file \`aclocal.m4' + autoconf touch file \`configure' + autoheader touch file \`config.h.in' + autom4te touch the output file, or create a stub one + automake touch all \`Makefile.in' files + bison create \`y.tab.[ch]', if possible, from existing .[ch] + flex create \`lex.yy.c', if possible, from existing .c + help2man touch the output file + lex create \`lex.yy.c', if possible, from existing .c + makeinfo touch the output file + tar try tar, gnutar, gtar, then tar without non-portable flags + yacc create \`y.tab.[ch]', if possible, from existing .[ch] + +Send bug reports to ." + exit $? + ;; + + -v|--v|--ve|--ver|--vers|--versi|--versio|--version) + echo "missing $scriptversion (GNU Automake)" + exit $? + ;; + + -*) + echo 1>&2 "$0: Unknown \`$1' option" + echo 1>&2 "Try \`$0 --help' for more information" + exit 1 + ;; + +esac + +# Now exit if we have it, but it failed. Also exit now if we +# don't have it and --version was passed (most likely to detect +# the program). +case $1 in + lex|yacc) + # Not GNU programs, they don't have --version. + ;; + + tar) + if test -n "$run"; then + echo 1>&2 "ERROR: \`tar' requires --run" + exit 1 + elif test "x$2" = "x--version" || test "x$2" = "x--help"; then + exit 1 + fi + ;; + + *) + if test -z "$run" && ($1 --version) > /dev/null 2>&1; then + # We have it, but it failed. + exit 1 + elif test "x$2" = "x--version" || test "x$2" = "x--help"; then + # Could not run --version or --help. This is probably someone + # running `$TOOL --version' or `$TOOL --help' to check whether + # $TOOL exists and not knowing $TOOL uses missing. + exit 1 + fi + ;; +esac + +# If it does not exist, or fails to run (possibly an outdated version), +# try to emulate it. +case $1 in + aclocal*) + echo 1>&2 "\ +WARNING: \`$1' is $msg. You should only need it if + you modified \`acinclude.m4' or \`${configure_ac}'. You might want + to install the \`Automake' and \`Perl' packages. Grab them from + any GNU archive site." + touch aclocal.m4 + ;; + + autoconf) + echo 1>&2 "\ +WARNING: \`$1' is $msg. You should only need it if + you modified \`${configure_ac}'. You might want to install the + \`Autoconf' and \`GNU m4' packages. Grab them from any GNU + archive site." + touch configure + ;; + + autoheader) + echo 1>&2 "\ +WARNING: \`$1' is $msg. You should only need it if + you modified \`acconfig.h' or \`${configure_ac}'. You might want + to install the \`Autoconf' and \`GNU m4' packages. Grab them + from any GNU archive site." + files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER(\([^)]*\)).*/\1/p' ${configure_ac}` + test -z "$files" && files="config.h" + touch_files= + for f in $files; do + case $f in + *:*) touch_files="$touch_files "`echo "$f" | + sed -e 's/^[^:]*://' -e 's/:.*//'`;; + *) touch_files="$touch_files $f.in";; + esac + done + touch $touch_files + ;; + + automake*) + echo 1>&2 "\ +WARNING: \`$1' is $msg. You should only need it if + you modified \`Makefile.am', \`acinclude.m4' or \`${configure_ac}'. + You might want to install the \`Automake' and \`Perl' packages. + Grab them from any GNU archive site." + find . -type f -name Makefile.am -print | + sed 's/\.am$/.in/' | + while read f; do touch "$f"; done + ;; + + autom4te) + echo 1>&2 "\ +WARNING: \`$1' is needed, but is $msg. + You might have modified some files without having the + proper tools for further handling them. + You can get \`$1' as part of \`Autoconf' from any GNU + archive site." + + file=`echo "$*" | sed -n "$sed_output"` + test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"` + if test -f "$file"; then + touch $file + else + test -z "$file" || exec >$file + echo "#! /bin/sh" + echo "# Created by GNU Automake missing as a replacement of" + echo "# $ $@" + echo "exit 0" + chmod +x $file + exit 1 + fi + ;; + + bison|yacc) + echo 1>&2 "\ +WARNING: \`$1' $msg. You should only need it if + you modified a \`.y' file. You may need the \`Bison' package + in order for those modifications to take effect. You can get + \`Bison' from any GNU archive site." + rm -f y.tab.c y.tab.h + if test $# -ne 1; then + eval LASTARG="\${$#}" + case $LASTARG in + *.y) + SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'` + if test -f "$SRCFILE"; then + cp "$SRCFILE" y.tab.c + fi + SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'` + if test -f "$SRCFILE"; then + cp "$SRCFILE" y.tab.h + fi + ;; + esac + fi + if test ! -f y.tab.h; then + echo >y.tab.h + fi + if test ! -f y.tab.c; then + echo 'main() { return 0; }' >y.tab.c + fi + ;; + + lex|flex) + echo 1>&2 "\ +WARNING: \`$1' is $msg. You should only need it if + you modified a \`.l' file. You may need the \`Flex' package + in order for those modifications to take effect. You can get + \`Flex' from any GNU archive site." + rm -f lex.yy.c + if test $# -ne 1; then + eval LASTARG="\${$#}" + case $LASTARG in + *.l) + SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'` + if test -f "$SRCFILE"; then + cp "$SRCFILE" lex.yy.c + fi + ;; + esac + fi + if test ! -f lex.yy.c; then + echo 'main() { return 0; }' >lex.yy.c + fi + ;; + + help2man) + echo 1>&2 "\ +WARNING: \`$1' is $msg. You should only need it if + you modified a dependency of a manual page. You may need the + \`Help2man' package in order for those modifications to take + effect. You can get \`Help2man' from any GNU archive site." + + file=`echo "$*" | sed -n "$sed_output"` + test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"` + if test -f "$file"; then + touch $file + else + test -z "$file" || exec >$file + echo ".ab help2man is required to generate this page" + exit 1 + fi + ;; + + makeinfo) + echo 1>&2 "\ +WARNING: \`$1' is $msg. You should only need it if + you modified a \`.texi' or \`.texinfo' file, or any other file + indirectly affecting the aspect of the manual. The spurious + call might also be the consequence of using a buggy \`make' (AIX, + DU, IRIX). You might want to install the \`Texinfo' package or + the \`GNU make' package. Grab either from any GNU archive site." + # The file to touch is that specified with -o ... + file=`echo "$*" | sed -n "$sed_output"` + test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"` + if test -z "$file"; then + # ... or it is the one specified with @setfilename ... + infile=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'` + file=`sed -n ' + /^@setfilename/{ + s/.* \([^ ]*\) *$/\1/ + p + q + }' $infile` + # ... or it is derived from the source name (dir/f.texi becomes f.info) + test -z "$file" && file=`echo "$infile" | sed 's,.*/,,;s,.[^.]*$,,'`.info + fi + # If the file does not exist, the user really needs makeinfo; + # let's fail without touching anything. + test -f $file || exit 1 + touch $file + ;; + + tar) + shift + + # We have already tried tar in the generic part. + # Look for gnutar/gtar before invocation to avoid ugly error + # messages. + if (gnutar --version > /dev/null 2>&1); then + gnutar "$@" && exit 0 + fi + if (gtar --version > /dev/null 2>&1); then + gtar "$@" && exit 0 + fi + firstarg="$1" + if shift; then + case $firstarg in + *o*) + firstarg=`echo "$firstarg" | sed s/o//` + tar "$firstarg" "$@" && exit 0 + ;; + esac + case $firstarg in + *h*) + firstarg=`echo "$firstarg" | sed s/h//` + tar "$firstarg" "$@" && exit 0 + ;; + esac + fi + + echo 1>&2 "\ +WARNING: I can't seem to be able to run \`tar' with the given arguments. + You may want to install GNU tar or Free paxutils, or check the + command line arguments." + exit 1 + ;; + + *) + echo 1>&2 "\ +WARNING: \`$1' is needed, and is $msg. + You might have modified some files without having the + proper tools for further handling them. Check the \`README' file, + it often tells you about the needed prerequisites for installing + this package. You may also peek at any GNU archive site, in case + some other package would contain this missing \`$1' program." + exit 1 + ;; +esac + +exit 0 + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-end: "$" +# End: diff --git a/mm-camcorder.pc.in b/mm-camcorder.pc.in new file mode 100644 index 0000000..fb785ee --- /dev/null +++ b/mm-camcorder.pc.in @@ -0,0 +1,11 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: mm-camcorder +Description: Multimedia Framework Camcorder Library +Requires: gstreamer-0.10 gstreamer-base-0.10 mm-common mm-log libexif mm-ta +Version: $VERSION +Libs: -L${libdir} -lmmfcamcorder +Cflags: -I${includedir}/ -I${includedir}/mmf diff --git a/packaging/libmm-camcorder.spec b/packaging/libmm-camcorder.spec new file mode 100644 index 0000000..6f323f0 --- /dev/null +++ b/packaging/libmm-camcorder.spec @@ -0,0 +1,71 @@ +Name: libmm-camcorder +Summary: camcorder library +Version: 0.5.5 +Release: 1 +Group: libs +License: Samsung +URL: N/A +Source0: %{name}-%{version}.tar.gz +Requires(post): /sbin/ldconfig +Requires(postun): /sbin/ldconfig +BuildRequires: pkgconfig(mm-common) +BuildRequires: pkgconfig(mm-sound) +BuildRequires: pkgconfig(libexif) +BuildRequires: pkgconfig(mmutil-imgp) +BuildRequires: pkgconfig(elementary) +BuildRequires: pkgconfig(appcore-efl) +BuildRequires: pkgconfig(vconf) +BuildRequires: pkgconfig(mm-log) +BuildRequires: pkgconfig(gstreamer-plugins-base-0.10) +BuildRequires: pkgconfig(mm-ta) +BuildRequires: pkgconfig(mm-session) +BuildRequires: pkgconfig(audio-session-mgr) +BuildRequires: pkgconfig(gstreamer-floatcast-0.10) +BuildRequires: pkgconfig(gstreamer-check-0.10) +BuildRequires: pkgconfig(camsrcjpegenc) +BuildRequires: gst-plugins-base-devel + +%description +camcorder library. + + +%package devel +Summary: camcorder development library +Group: libdevel +Version: %{version} +Requires: %{name} = %{version}-%{release} + +%description devel +camcorder development library. + + +%prep +%setup -q + + +%build +./autogen.sh +%configure --disable-static +make %{?jobs:-j%jobs} + +%install +rm -rf %{buildroot} +%make_install + + +%post -p /sbin/ldconfig + +%postun -p /sbin/ldconfig + +%files +%defattr(-,root,root,-) +%{_bindir}/* +%{_libdir}/*.so.* +%{_datadir}/edje/* +/usr/share/sounds/mm-camcorder/* + +%files devel +%defattr(-,root,root,-) +%{_includedir}/mmf/mm_camcorder.h +%{_libdir}/pkgconfig/mm-camcorder.pc +%{_libdir}/*.so diff --git a/sounds/af_fail.wav b/sounds/af_fail.wav new file mode 100644 index 0000000000000000000000000000000000000000..ab94bccc677e69cf7d7c51ffb3cb98d4bbcbdacd GIT binary patch literal 9748 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 literal 0 HcmV?d00001 diff --git a/sounds/recording_stop_01.wav b/sounds/recording_stop_01.wav new file mode 100644 index 0000000000000000000000000000000000000000..5f89edd80c68ea6c62c822dd2d279f65dde61332 GIT binary patch literal 26584 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 literal 0 HcmV?d00001 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 + * + * 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 +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FUNCTIONPRE-STATEPOST-STATESYNC TYPE
mm_camcorder_create()NONENULLSYNC
mm_camcorder_destroy()NULLNONESYNC
mm_camcorder_realize()NULLREADYSYNC
mm_camcorder_unrealize()READYNULLSYNC
mm_camcorder_start()READYPREPAREDSYNC
mm_camcorder_stop()PREPAREDREADYSYNC
mm_camcorder_capture_start()PREPAREDCAPTURINGSYNC
mm_camcorder_capture_stop()CAPTURINGPREPAREDSYNC
mm_camcorder_record()PREPARED/PAUSEDRECORDINGSYNC
mm_camcorder_pause()RECORDINGPAUSEDSYNC
mm_camcorder_commit()RECORDING/PAUSEDPREPAREDSYNC
mm_camcorder_cancel()RECORDING/PAUSEDPREPAREDSYNC
mm_camcorder_set_message_callback()N/AN/ASYNC
mm_camcorder_set_video_stream_callback()N/AN/ASYNC
mm_camcorder_set_video_capture_callback()N/AN/ASYNC
mm_camcorder_get_state()N/AN/ASYNC
mm_camcorder_get_attributes()N/AN/ASYNC
mm_camcorder_set_attributes()N/AN/ASYNC
mm_camcorder_get_attribute_info()N/AN/ASYNC
mm_camcorder_init_focusing()N/AN/ASYNC
mm_camcorder_start_focusing()N/AN/ASYNC
mm_camcorder_stop_focusing()N/AN/ASYNC
+
+ + @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 +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Attribute
Description
#MMCAM_MODEMode of camcorder ( still/video/audio )
#MMCAM_AUDIO_DEVICEAudio device ID for capturing audio stream
#MMCAM_CAMERA_DEVICEVideo device ID for capturing video stream
#MMCAM_AUDIO_ENCODERAudio codec for encoding audio stream
#MMCAM_VIDEO_ENCODERVideo codec for encoding video stream
#MMCAM_IMAGE_ENCODERImage codec for capturing still-image
#MMCAM_FILE_FORMATFile format for recording media stream
#MMCAM_AUDIO_SAMPLERATESampling rate of audio stream ( This is an integer field )
#MMCAM_AUDIO_FORMATAudio format of each sample
#MMCAM_AUDIO_CHANNELChannels of each sample ( This is an integer field )
#MMCAM_AUDIO_INPUT_ROUTE(deprecated)Set audio input route
#MMCAM_CAMERA_FORMATFormat of video stream. This is an integer field
#MMCAM_CAMERA_FPSFrames per second ( This is an integer field )
#MMCAM_CAMERA_WIDTHWidth of input video stream
#MMCAM_CAMERA_HEIGHTHeight of input video stream
#MMCAM_CAMERA_FPS_AUTOFPS Auto. When you set true to this attribute, FPS will vary depending on the amount of the light.
#MMCAM_DISPLAY_HANDLEPointer of display buffer or ID of xwindow
#MMCAM_DISPLAY_DEVICEDevice of display
#MMCAM_DISPLAY_SURFACESurface of display
#MMCAM_DISPLAY_SOURCE_XX position of source rectangle. When you want to crop the source, you can set the area with this value.
#MMCAM_DISPLAY_SOURCE_YY position of source rectangle. When you want to crop the source, you can set the area with this value.
#MMCAM_DISPLAY_SOURCE_WIDTHWidth of source rectangle. When you want to crop the source, you can set the area with this value.
#MMCAM_DISPLAY_SOURCE_HEIGHTHeight of source rectangle. When you want to crop the source, you can set the area with this value.
#MMCAM_DISPLAY_ROTATIONRotation of display
#MMCAM_DISPLAY_VISIBLEVisible of display
#MMCAM_DISPLAY_SCALEA scale of displayed image
#MMCAM_DISPLAY_GEOMETRY_METHODA method that describes a form of geometry for display
+
+ + @par + Following are the attributes which should be set before recording (mm_camcorder_record()): + + @par +
+ + + + + + + + + + + + + + + + + + + + + +
Attribute
Description
#MMCAM_AUDIO_ENCODER_BITRATEBitrate of Audio Encoder
#MMCAM_VIDEO_ENCODER_BITRATEBitrate of Video Encoder
#MMCAM_TARGET_FILENAMETarget filename. Only used in Audio/Video recording. This is not used for capturing.
#MMCAM_TARGET_TIME_LIMITTime limit of recording file. If the elapsed time of recording reaches this value.
+
+ + @par + Following are the attributes which should be set before capturing (mm_camcorder_capture_start()): + + @par +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Attribute
Description
#MMCAM_IMAGE_ENCODER_QUALITYEncoding quality of Image codec
#MMCAM_CAPTURE_FORMATPixel format that you want to capture
#MMCAM_CAPTURE_WIDTHWidth of the image that you want to capture
#MMCAM_CAPTURE_HEIGHTHeight of the image that you want to capture
#MMCAM_CAPTURE_COUNTTotal count of capturing
#MMCAM_CAPTURE_INTERVALInterval between each capturing on Multishot ( MMCAM_CAPTURE_COUNT > 1 )
+
+ + @par + Following are the attributes which can be set anytime: + + @par +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Attribute
Description
#MMCAM_AUDIO_VOLUMEInput volume of audio source ( double value )
#MMCAM_CAMERA_DIGITAL_ZOOMDigital zoom level
#MMCAM_CAMERA_OPTICAL_ZOOMOptical zoom level
#MMCAM_CAMERA_FOCUS_MODEFocus mode
#MMCAM_CAMERA_AF_SCAN_RANGEAF Scan range
#MMCAM_CAMERA_AF_TOUCH_XX coordinate of touching position
#MMCAM_CAMERA_AF_TOUCH_YY coordinate of touching position
#MMCAM_CAMERA_AF_TOUCH_WIDTHWidth of touching area
#MMCAM_CAMERA_AF_TOUCH_HEIGHTHeight of touching area
#MMCAM_CAMERA_EXPOSURE_MODEExposure mode
#MMCAM_CAMERA_EXPOSURE_VALUEExposure value
#MMCAM_CAMERA_F_NUMBERf number of camera
#MMCAM_CAMERA_SHUTTER_SPEEDShutter speed
#MMCAM_CAMERA_ISOISO of capturing image
#MMCAM_CAMERA_WDRWide dynamic range
#MMCAM_CAMERA_ANTI_HANDSHAKEAnti Handshake
#MMCAM_CAMERA_FOCAL_LENGTHFocal length of camera lens
#MMCAM_FILTER_BRIGHTNESSBrightness level
#MMCAM_FILTER_CONTRASTContrast level
#MMCAM_FILTER_WBWhite balance
#MMCAM_FILTER_COLOR_TONEColor tone (Color effect)
#MMCAM_FILTER_SCENE_MODEScene mode (Program mode)
#MMCAM_FILTER_SATURATIONSaturation level
#MMCAM_FILTER_HUEHue level
#MMCAM_FILTER_SHARPNESSSharpness level
#MMCAM_CAPTURE_BREAK_CONTINUOUS_SHOTSet this as true when you want to stop multishot immediately
#MMCAM_DISPLAY_RECT_XX position of display rectangle (This is only available when MMCAM_DISPLAY_GEOMETRY_METHOD is MM_CAMCORDER_CUSTOM_ROI)
#MMCAM_DISPLAY_RECT_YY position of display rectangle (This is only available when MMCAM_DISPLAY_GEOMETRY_METHOD is MM_CAMCORDER_CUSTOM_ROI)
#MMCAM_DISPLAY_RECT_WIDTHWidth of display rectangle (This is only available when MMCAM_DISPLAY_GEOMETRY_METHOD is MM_CAMCORDER_CUSTOM_ROI)
#MMCAM_DISPLAY_RECT_HEIGHTHeight of display rectangle (This is only available when MMCAM_DISPLAY_GEOMETRY_METHOD is MM_CAMCORDER_CUSTOM_ROI)
#MMCAM_TAG_ENABLEEnable to write tags (If this value is FALSE, none of tag information will be written to captured file)
#MMCAM_TAG_IMAGE_DESCRIPTIONImage description
#MMCAM_TAG_ORIENTATIONOrientation of captured image
#MMCAM_TAG_SOFTWAREsoftware name and version
#MMCAM_TAG_LATITUDELatitude of captured postion (GPS information)
#MMCAM_TAG_LONGITUDELongitude of captured postion (GPS information)
#MMCAM_TAG_ALTITUDEAltitude of captured postion (GPS information)
#MMCAM_STROBE_CONTROLStrobe control
#MMCAM_STROBE_MODEOperation Mode of strobe
#MMCAM_DETECT_MODEDetection mode
#MMCAM_DETECT_NUMBERTotal number of detected object
#MMCAM_DETECT_FOCUS_SELECTSelect one of detected objects
+
+ */ + + + +#ifndef __MM_CAMCORDER_H__ +#define __MM_CAMCORDER_H__ + + +/*======================================================================================= +| INCLUDE FILES | +========================================================================================*/ +#include + +#include +#include +#include + +#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 + +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 + +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 + +//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 + +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 + +//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 + +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 + +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 + +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 + +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 + +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 + +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 + +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 + +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 + +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 + +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 + +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 + +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 + +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 + +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 + +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 + +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 + +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 + +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 + * + * 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 +#include + +#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 + * + * 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 + +#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 + * + * 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 + * + * 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 + * + * 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 +#include +#include +#include +#include + +#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 + * + * 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 +#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 + * + * 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 +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#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 + * + * 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 +#include + + + +#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 + * + * 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 + * + * 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 +#include +#include + +#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 + * + * 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 + * + * 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 + +#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 + * + * 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 +#include + + +#include +#include + +#include +#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 + * + * 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 +#include +#include + + +/*--------------------------------------------------------------------------------------- +| 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 + * + * 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 + +/*--------------------------------------------------------------------------------------- +| 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 + * + * 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 +#include +#include +#include + +#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 + * + * 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 +#include +#include + +#include +#include +#include +#include +#include +#include + +#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 +#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 + * + * 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 +#include +#include +#include + +#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(¤t_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 + * + * 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 +#include +#include +#include +#include + +#include +#include "mm_camcorder_internal.h" +#include + +#include +#include +#include + +#include +#include +#include + +/*--------------------------------------------------------------------------------------- +| 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 + * + * 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 + * + * 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 +#include +#include +#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 + * + * 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 +#include +#include +#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 + * + * 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 +#include +#include +#include /* 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( ¤t_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 + * + * 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; +} diff --git a/symbols b/symbols new file mode 100644 index 0000000..014b9df --- /dev/null +++ b/symbols @@ -0,0 +1,695 @@ +ELF Header: + Magic: 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00 + Class: ELF32 + Data: 2's complement, little endian + Version: 1 (current) + OS/ABI: UNIX - System V + ABI Version: 0 + Type: DYN (Shared object file) + Machine: ARM + Version: 0x1 + Entry point address: 0x3bd0 + Start of program headers: 52 (bytes into file) + Start of section headers: 55684 (bytes into file) + Flags: 0x5000002, has entry point, Version5 EABI + Size of this header: 52 (bytes) + Size of program headers: 32 (bytes) + Number of program headers: 4 + Size of section headers: 40 (bytes) + Number of section headers: 24 + Section header string table index: 23 + +Section Headers: + [Nr] Name Type Addr Off Size ES Flg Lk Inf Al + [ 0] NULL 00000000 000000 000000 00 0 0 0 + [ 1] .hash HASH 000000b4 0000b4 000684 04 A 2 0 4 + [ 2] .dynsym DYNSYM 00000738 000738 000da0 10 A 3 2 4 + [ 3] .dynstr STRTAB 000014d8 0014d8 00170d 00 A 0 0 1 + [ 4] .gnu.version VERSYM 00002be6 002be6 0001b4 02 A 2 0 2 + [ 5] .gnu.version_r VERNEED 00002d9c 002d9c 000040 00 A 3 2 4 + [ 6] .rel.dyn REL 00002ddc 002ddc 000500 08 A 2 0 4 + [ 7] .rel.plt REL 000032dc 0032dc 000388 08 A 2 9 4 + [ 8] .init PROGBITS 00003664 003664 00000c 00 AX 0 0 4 + [ 9] .plt PROGBITS 00003670 003670 000560 04 AX 0 0 4 + [10] .text PROGBITS 00003bd0 003bd0 006fa4 00 AX 0 0 4 + [11] .fini PROGBITS 0000ab74 00ab74 000008 00 AX 0 0 4 + [12] .rodata PROGBITS 0000ab7c 00ab7c 0020e4 00 A 0 0 4 + [13] .eh_frame PROGBITS 0000cc60 00cc60 000004 00 A 0 0 4 + [14] .init_array INIT_ARRAY 00015000 00d000 000004 00 WA 0 0 4 + [15] .fini_array FINI_ARRAY 00015004 00d004 000004 00 WA 0 0 4 + [16] .jcr PROGBITS 00015008 00d008 000004 00 WA 0 0 4 + [17] .data.rel.ro PROGBITS 0001500c 00d00c 000540 00 WA 0 0 4 + [18] .dynamic DYNAMIC 0001554c 00d54c 000130 08 WA 3 0 4 + [19] .got PROGBITS 0001567c 00d67c 00020c 04 WA 0 0 4 + [20] .data PROGBITS 00015888 00d888 000004 00 WA 0 0 4 + [21] .bss NOBITS 0001588c 00d88c 0000bc 00 WA 0 0 4 + [22] .ARM.attributes ARM_ATTRIBUTES 00000000 00d88c 000031 00 0 0 1 + [23] .shstrtab STRTAB 00000000 00d8bd 0000c6 00 0 0 1 +Key to Flags: + W (write), A (alloc), X (execute), M (merge), S (strings) + I (info), L (link order), G (group), x (unknown) + O (extra OS processing required) o (OS specific), p (processor specific) + +There are no section groups in this file. + +Program Headers: + Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align + LOAD 0x000000 0x00000000 0x00000000 0x0cc64 0x0cc64 R E 0x8000 + LOAD 0x00d000 0x00015000 0x00015000 0x0088c 0x00948 RW 0x8000 + DYNAMIC 0x00d54c 0x0001554c 0x0001554c 0x00130 0x00130 RW 0x4 + GNU_STACK 0x000000 0x00000000 0x00000000 0x00000 0x00000 RW 0x4 + + Section to Segment mapping: + Segment Sections... + 00 .hash .dynsym .dynstr .gnu.version .gnu.version_r .rel.dyn .rel.plt .init .plt .text .fini .rodata .eh_frame + 01 .init_array .fini_array .jcr .data.rel.ro .dynamic .got .data .bss + 02 .dynamic + 03 + +Dynamic section at offset 0xd54c contains 34 entries: + Tag Type Name/Value + 0x00000001 (NEEDED) Shared library: [libgstreamer-0.10.so.0] + 0x00000001 (NEEDED) Shared library: [libgobject-2.0.so.0] + 0x00000001 (NEEDED) Shared library: [libgmodule-2.0.so.0] + 0x00000001 (NEEDED) Shared library: [libdl.so.2] + 0x00000001 (NEEDED) Shared library: [libgthread-2.0.so.0] + 0x00000001 (NEEDED) Shared library: [libpthread.so.0] + 0x00000001 (NEEDED) Shared library: [librt.so.1] + 0x00000001 (NEEDED) Shared library: [libglib-2.0.so.0] + 0x00000001 (NEEDED) Shared library: [libm.so.6] + 0x00000001 (NEEDED) Shared library: [libc.so.6] + 0x0000000e (SONAME) Library soname: [libgstinterfaces-0.10.so.0] + 0x0000000c (INIT) 0x3664 + 0x0000000d (FINI) 0xab74 + 0x00000019 (INIT_ARRAY) 0x15000 + 0x0000001b (INIT_ARRAYSZ) 4 (bytes) + 0x0000001a (FINI_ARRAY) 0x15004 + 0x0000001c (FINI_ARRAYSZ) 4 (bytes) + 0x00000004 (HASH) 0xb4 + 0x00000005 (STRTAB) 0x14d8 + 0x00000006 (SYMTAB) 0x738 + 0x0000000a (STRSZ) 5901 (bytes) + 0x0000000b (SYMENT) 16 (bytes) + 0x00000003 (PLTGOT) 0x1567c + 0x00000002 (PLTRELSZ) 904 (bytes) + 0x00000014 (PLTREL) REL + 0x00000017 (JMPREL) 0x32dc + 0x00000011 (REL) 0x2ddc + 0x00000012 (RELSZ) 1280 (bytes) + 0x00000013 (RELENT) 8 (bytes) + 0x6ffffffe (VERNEED) 0x2d9c + 0x6fffffff (VERNEEDNUM) 2 + 0x6ffffff0 (VERSYM) 0x2be6 + 0x6ffffffa (RELCOUNT) 145 + 0x00000000 (NULL) 0x0 + +Relocation section '.rel.dyn' at offset 0x2ddc contains 160 entries: + Offset Info Type Sym. Value Symbol's Name +00015000 00000017 R_ARM_RELATIVE +00015004 00000017 R_ARM_RELATIVE +00015010 00000017 R_ARM_RELATIVE +0001503c 00000017 R_ARM_RELATIVE +0001504c 00000017 R_ARM_RELATIVE +00015058 00000017 R_ARM_RELATIVE +00015084 00000017 R_ARM_RELATIVE +00015094 00000017 R_ARM_RELATIVE +000150a8 00000017 R_ARM_RELATIVE +000150b8 00000017 R_ARM_RELATIVE +000150c4 00000017 R_ARM_RELATIVE +000150e8 00000017 R_ARM_RELATIVE +00015114 00000017 R_ARM_RELATIVE +00015130 00000017 R_ARM_RELATIVE +0001515c 00000017 R_ARM_RELATIVE +0001516c 00000017 R_ARM_RELATIVE +00015180 00000017 R_ARM_RELATIVE +00015190 00000017 R_ARM_RELATIVE +0001519c 00000017 R_ARM_RELATIVE +000151c0 00000017 R_ARM_RELATIVE +000151e4 00000017 R_ARM_RELATIVE +000151e8 00000017 R_ARM_RELATIVE +000151f0 00000017 R_ARM_RELATIVE +000151f4 00000017 R_ARM_RELATIVE +00015208 00000017 R_ARM_RELATIVE +0001520c 00000017 R_ARM_RELATIVE +00015214 00000017 R_ARM_RELATIVE +00015218 00000017 R_ARM_RELATIVE +0001522c 00000017 R_ARM_RELATIVE +00015230 00000017 R_ARM_RELATIVE +00015238 00000017 R_ARM_RELATIVE +0001523c 00000017 R_ARM_RELATIVE +00015244 00000017 R_ARM_RELATIVE +00015248 00000017 R_ARM_RELATIVE +00015250 00000017 R_ARM_RELATIVE +00015254 00000017 R_ARM_RELATIVE +00015268 00000017 R_ARM_RELATIVE +0001526c 00000017 R_ARM_RELATIVE +00015274 00000017 R_ARM_RELATIVE +00015278 00000017 R_ARM_RELATIVE +00015280 00000017 R_ARM_RELATIVE +00015284 00000017 R_ARM_RELATIVE +00015298 00000017 R_ARM_RELATIVE +0001529c 00000017 R_ARM_RELATIVE +000152a4 00000017 R_ARM_RELATIVE +000152a8 00000017 R_ARM_RELATIVE +000152b0 00000017 R_ARM_RELATIVE +000152b4 00000017 R_ARM_RELATIVE +000152bc 00000017 R_ARM_RELATIVE +000152c0 00000017 R_ARM_RELATIVE +000152c8 00000017 R_ARM_RELATIVE +000152cc 00000017 R_ARM_RELATIVE +000152d4 00000017 R_ARM_RELATIVE +000152d8 00000017 R_ARM_RELATIVE +000152e0 00000017 R_ARM_RELATIVE +000152e4 00000017 R_ARM_RELATIVE +000152f8 00000017 R_ARM_RELATIVE +000152fc 00000017 R_ARM_RELATIVE +00015304 00000017 R_ARM_RELATIVE +00015308 00000017 R_ARM_RELATIVE +00015310 00000017 R_ARM_RELATIVE +00015314 00000017 R_ARM_RELATIVE +0001531c 00000017 R_ARM_RELATIVE +00015320 00000017 R_ARM_RELATIVE +00015334 00000017 R_ARM_RELATIVE +00015338 00000017 R_ARM_RELATIVE +00015340 00000017 R_ARM_RELATIVE +00015344 00000017 R_ARM_RELATIVE +0001534c 00000017 R_ARM_RELATIVE +00015350 00000017 R_ARM_RELATIVE +00015364 00000017 R_ARM_RELATIVE +00015368 00000017 R_ARM_RELATIVE +00015370 00000017 R_ARM_RELATIVE +00015374 00000017 R_ARM_RELATIVE +0001537c 00000017 R_ARM_RELATIVE +00015380 00000017 R_ARM_RELATIVE +00015388 00000017 R_ARM_RELATIVE +0001538c 00000017 R_ARM_RELATIVE +00015394 00000017 R_ARM_RELATIVE +00015398 00000017 R_ARM_RELATIVE +000153a0 00000017 R_ARM_RELATIVE +000153a4 00000017 R_ARM_RELATIVE +000153ac 00000017 R_ARM_RELATIVE +000153b0 00000017 R_ARM_RELATIVE +000153b8 00000017 R_ARM_RELATIVE +000153bc 00000017 R_ARM_RELATIVE +000153c4 00000017 R_ARM_RELATIVE +000153c8 00000017 R_ARM_RELATIVE +000153d0 00000017 R_ARM_RELATIVE +000153d4 00000017 R_ARM_RELATIVE +000153dc 00000017 R_ARM_RELATIVE +000153e0 00000017 R_ARM_RELATIVE +000153e8 00000017 R_ARM_RELATIVE +000153ec 00000017 R_ARM_RELATIVE +000153f4 00000017 R_ARM_RELATIVE +000153f8 00000017 R_ARM_RELATIVE +00015400 00000017 R_ARM_RELATIVE +00015404 00000017 R_ARM_RELATIVE +0001540c 00000017 R_ARM_RELATIVE +00015410 00000017 R_ARM_RELATIVE +00015424 00000017 R_ARM_RELATIVE +00015428 00000017 R_ARM_RELATIVE +00015430 00000017 R_ARM_RELATIVE +00015434 00000017 R_ARM_RELATIVE +0001543c 00000017 R_ARM_RELATIVE +00015440 00000017 R_ARM_RELATIVE +00015448 00000017 R_ARM_RELATIVE +0001544c 00000017 R_ARM_RELATIVE +00015454 00000017 R_ARM_RELATIVE +00015458 00000017 R_ARM_RELATIVE +00015460 00000017 R_ARM_RELATIVE +00015464 00000017 R_ARM_RELATIVE +0001546c 00000017 R_ARM_RELATIVE +00015470 00000017 R_ARM_RELATIVE +00015478 00000017 R_ARM_RELATIVE +0001547c 00000017 R_ARM_RELATIVE +00015484 00000017 R_ARM_RELATIVE +00015488 00000017 R_ARM_RELATIVE +00015490 00000017 R_ARM_RELATIVE +00015494 00000017 R_ARM_RELATIVE +0001549c 00000017 R_ARM_RELATIVE +000154a0 00000017 R_ARM_RELATIVE +000154b4 00000017 R_ARM_RELATIVE +000154b8 00000017 R_ARM_RELATIVE +000154c0 00000017 R_ARM_RELATIVE +000154c4 00000017 R_ARM_RELATIVE +000154cc 00000017 R_ARM_RELATIVE +000154d0 00000017 R_ARM_RELATIVE +000154d8 00000017 R_ARM_RELATIVE +000154dc 00000017 R_ARM_RELATIVE +000154f0 00000017 R_ARM_RELATIVE +000154f4 00000017 R_ARM_RELATIVE +000154fc 00000017 R_ARM_RELATIVE +00015500 00000017 R_ARM_RELATIVE +00015508 00000017 R_ARM_RELATIVE +0001550c 00000017 R_ARM_RELATIVE +00015514 00000017 R_ARM_RELATIVE +00015518 00000017 R_ARM_RELATIVE +00015520 00000017 R_ARM_RELATIVE +00015524 00000017 R_ARM_RELATIVE +0001552c 00000017 R_ARM_RELATIVE +00015530 00000017 R_ARM_RELATIVE +00015538 00000017 R_ARM_RELATIVE +0001553c 00000017 R_ARM_RELATIVE +00015888 00000017 R_ARM_RELATIVE +0001584c 00000215 R_ARM_GLOB_DAT 00000000 g_free +00015850 00000915 R_ARM_GLOB_DAT 00009e60 gst_interfaces_marshal_VOID__OBJECT_ULONG +00015854 00001315 R_ARM_GLOB_DAT 00000000 g_cclosure_marshal_VOID__INT +00015858 00001815 R_ARM_GLOB_DAT 00000000 __gst_debug_min +0001585c 00001915 R_ARM_GLOB_DAT 00009f90 gst_interfaces_marshal_VOID__OBJECT_POINTER +00015860 00001c15 R_ARM_GLOB_DAT 00000000 __gmon_start__ +00015864 00001d15 R_ARM_GLOB_DAT 00000000 _Jv_RegisterClasses +00015868 00003e15 R_ARM_GLOB_DAT 00009ef8 gst_interfaces_marshal_VOID__OBJECT_STRING +0001586c 00005615 R_ARM_GLOB_DAT 00000000 GST_CAT_DEFAULT +00015870 00008815 R_ARM_GLOB_DAT 00000000 g_cclosure_marshal_VOID__POINTER +00015874 0000b215 R_ARM_GLOB_DAT 0000a028 gst_interfaces_marshal_VOID__OBJECT_BOOLEAN +00015878 0000b415 R_ARM_GLOB_DAT 00000000 g_cclosure_marshal_VOID__OBJECT +0001587c 0000cc15 R_ARM_GLOB_DAT 00000000 g_cclosure_marshal_VOID__ULONG +00015880 0000d415 R_ARM_GLOB_DAT 00000000 __cxa_finalize +00015884 0000d515 R_ARM_GLOB_DAT 00009dcc gst_interfaces_marshal_VOID__OBJECT_INT + +Relocation section '.rel.plt' at offset 0x32dc contains 113 entries: + Offset Info Type Sym. Value Symbol's Name +00015688 00000216 R_ARM_JUMP_SLOT 00000000 g_free +0001568c 00000316 R_ARM_JUMP_SLOT 00000000 g_type_interface_peek +00015690 00000616 R_ARM_JUMP_SLOT 00000000 g_value_unset +00015694 00000816 R_ARM_JUMP_SLOT 00000000 g_param_spec_string +00015698 00000a16 R_ARM_JUMP_SLOT 00000000 gst_structure_has_name +0001569c 00000c16 R_ARM_JUMP_SLOT 00000000 gst_value_array_get_value +000156a0 00000d16 R_ARM_JUMP_SLOT 000072c4 gst_navigation_send_event +000156a4 00001116 R_ARM_JUMP_SLOT 00006c10 gst_navigation_query_get_type +000156a8 00001216 R_ARM_JUMP_SLOT 00000000 g_value_dup_string +000156ac 00001416 R_ARM_JUMP_SLOT 00000000 g_flags_register_static +000156b0 00001516 R_ARM_JUMP_SLOT 000076ec gst_property_probe_needs_probe +000156b4 00001716 R_ARM_JUMP_SLOT 00000000 g_object_get_data +000156b8 00001a16 R_ARM_JUMP_SLOT 00000000 g_signal_emit +000156bc 00001b16 R_ARM_JUMP_SLOT 000074b0 gst_property_probe_get_type +000156c0 00001c16 R_ARM_JUMP_SLOT 00000000 __gmon_start__ +000156c4 00001e16 R_ARM_JUMP_SLOT 00000000 g_signal_emit_by_name +000156c8 00002216 R_ARM_JUMP_SLOT 00000000 pow +000156cc 00002416 R_ARM_JUMP_SLOT 00000000 g_value_get_enum +000156d0 00002716 R_ARM_JUMP_SLOT 00000000 g_list_foreach +000156d4 00002816 R_ARM_JUMP_SLOT 00000000 g_list_free +000156d8 00002916 R_ARM_JUMP_SLOT 00000000 gst_message_new_custom +000156dc 00002b16 R_ARM_JUMP_SLOT 00000000 g_value_set_int +000156e0 00002d16 R_ARM_JUMP_SLOT 00000000 g_object_set_data_full +000156e4 00003116 R_ARM_JUMP_SLOT 00007274 gst_navigation_get_type +000156e8 00003216 R_ARM_JUMP_SLOT 00000000 gst_structure_get_int +000156ec 00003316 R_ARM_JUMP_SLOT 00000000 g_value_get_uint +000156f0 00003516 R_ARM_JUMP_SLOT 00000000 gst_fraction_get_type +000156f4 00003616 R_ARM_JUMP_SLOT 00000000 g_object_class_install_property +000156f8 00003716 R_ARM_JUMP_SLOT 00000000 gst_value_array_get_type +000156fc 00003816 R_ARM_JUMP_SLOT 00000000 g_param_spec_uint +00015700 00003916 R_ARM_JUMP_SLOT 00000000 g_enum_register_static +00015704 00003a16 R_ARM_JUMP_SLOT 00000000 g_malloc +00015708 00003d16 R_ARM_JUMP_SLOT 00009348 gst_tuner_norm_get_type +0001570c 00003f16 R_ARM_JUMP_SLOT 00000000 g_value_peek_pointer +00015710 00004016 R_ARM_JUMP_SLOT 00000000 gst_structure_set_value +00015714 00004116 R_ARM_JUMP_SLOT 00000000 gst_structure_get_uint +00015718 00004216 R_ARM_JUMP_SLOT 00000000 gst_structure_get_double +0001571c 00004416 R_ARM_JUMP_SLOT 00000000 g_param_spec_int +00015720 00004916 R_ARM_JUMP_SLOT 00000000 gst_structure_new +00015724 00004e16 R_ARM_JUMP_SLOT 000040b0 gst_mixer_message_get_type +00015728 00004f16 R_ARM_JUMP_SLOT 000098b8 gst_x_overlay_get_type +0001572c 00005016 R_ARM_JUMP_SLOT 00009640 gst_video_orientation_get_type +00015730 00005216 R_ARM_JUMP_SLOT 00007500 gst_property_probe_get_values +00015734 00005716 R_ARM_JUMP_SLOT 00000000 gst_implements_interface_check +00015738 00005816 R_ARM_JUMP_SLOT 00005560 gst_mixer_get_type +0001573c 00005916 R_ARM_JUMP_SLOT 00000000 g_value_set_string +00015740 00005a16 R_ARM_JUMP_SLOT 00005ca4 gst_mixer_options_get_type +00015744 00005b16 R_ARM_JUMP_SLOT 0000a3fc gst_navigation_command_get_type +00015748 00005e16 R_ARM_JUMP_SLOT 000069f8 gst_navigation_message_get_type +0001574c 00005f16 R_ARM_JUMP_SLOT 00000000 gst_value_list_get_size +00015750 00006016 R_ARM_JUMP_SLOT 00000000 cbrt +00015754 00006116 R_ARM_JUMP_SLOT 00000000 g_type_check_class_cast +00015758 00006716 R_ARM_JUMP_SLOT 00000000 gst_debug_log +0001575c 00006916 R_ARM_JUMP_SLOT 00000000 g_object_set_data +00015760 00006a16 R_ARM_JUMP_SLOT 00000000 g_once_init_enter_impl +00015764 00006b16 R_ARM_JUMP_SLOT 00000000 g_param_spec_boolean +00015768 00006c16 R_ARM_JUMP_SLOT 00000000 gst_value_list_get_type +0001576c 00006e16 R_ARM_JUMP_SLOT 00008dbc gst_tuner_list_norms +00015770 00007016 R_ARM_JUMP_SLOT 00000000 gst_message_get_type +00015774 00007116 R_ARM_JUMP_SLOT 00000000 g_object_get +00015778 00007216 R_ARM_JUMP_SLOT 00000000 gst_structure_get_string +0001577c 00007316 R_ARM_JUMP_SLOT 000079d4 gst_property_probe_probe_and_get_values +00015780 00007616 R_ARM_JUMP_SLOT 00000000 g_value_set_enum +00015784 00007a16 R_ARM_JUMP_SLOT 00000000 g_return_if_fail_warning +00015788 00007d16 R_ARM_JUMP_SLOT 00000000 g_type_register_static +0001578c 00007f16 R_ARM_JUMP_SLOT 00000000 gst_event_get_structure +00015790 00008016 R_ARM_JUMP_SLOT 00000000 g_object_set +00015794 00008316 R_ARM_JUMP_SLOT 00000000 g_value_get_object +00015798 00008916 R_ARM_JUMP_SLOT 00000000 g_signal_new +0001579c 00008a16 R_ARM_JUMP_SLOT 00003cf4 gst_color_balance_get_type +000157a0 00008b16 R_ARM_JUMP_SLOT 00000000 g_type_check_instance_is_a +000157a4 00008d16 R_ARM_JUMP_SLOT 00000000 gst_message_new_element +000157a8 00008e16 R_ARM_JUMP_SLOT 00000000 gst_structure_get_value +000157ac 00008f16 R_ARM_JUMP_SLOT 00005e5c gst_mixer_track_get_type +000157b0 00009016 R_ARM_JUMP_SLOT 00000000 gst_query_new_application +000157b4 00009116 R_ARM_JUMP_SLOT 00000000 g_param_spec_double +000157b8 00009416 R_ARM_JUMP_SLOT 00000000 gst_value_array_get_size +000157bc 00009516 R_ARM_JUMP_SLOT 00000000 gst_message_get_structure +000157c0 00009616 R_ARM_JUMP_SLOT 00000000 g_type_name +000157c4 00009716 R_ARM_JUMP_SLOT 00000000 log10 +000157c8 00009916 R_ARM_JUMP_SLOT 00009480 gst_tuner_channel_get_type +000157cc 00009b16 R_ARM_JUMP_SLOT 00000000 gst_value_list_get_value +000157d0 00009c16 R_ARM_JUMP_SLOT 00000000 g_type_interface_add_prerequisite +000157d4 00009d16 R_ARM_JUMP_SLOT 00000000 gst_element_post_message +000157d8 00009e16 R_ARM_JUMP_SLOT 00000000 gst_implements_interface_get_type +000157dc 00009f16 R_ARM_JUMP_SLOT 00008538 gst_tuner_get_type +000157e0 0000a116 R_ARM_JUMP_SLOT 00000000 g_type_check_instance_cast +000157e4 0000a216 R_ARM_JUMP_SLOT 00000000 gst_element_get_type +000157e8 0000a316 R_ARM_JUMP_SLOT 00007f94 gst_stream_volume_convert_volume +000157ec 0000a416 R_ARM_JUMP_SLOT 00008260 gst_stream_volume_get_type +000157f0 0000a516 R_ARM_JUMP_SLOT 00000000 g_object_interface_install_property +000157f4 0000a916 R_ARM_JUMP_SLOT 00000000 g_object_class_find_property +000157f8 0000aa16 R_ARM_JUMP_SLOT 00000000 gst_value_list_append_value +000157fc 0000af16 R_ARM_JUMP_SLOT 00007cbc gst_property_probe_get_properties +00015800 0000b016 R_ARM_JUMP_SLOT 00000000 g_value_init +00015804 0000b516 R_ARM_JUMP_SLOT 00000000 gst_structure_get_boolean +00015808 0000b616 R_ARM_JUMP_SLOT 0000902c gst_tuner_list_channels +0001580c 0000b816 R_ARM_JUMP_SLOT 00000000 g_value_set_uint +00015810 0000b916 R_ARM_JUMP_SLOT 00000000 gst_query_get_structure +00015814 0000be16 R_ARM_JUMP_SLOT 00000000 g_type_check_value_holds +00015818 0000c016 R_ARM_JUMP_SLOT 00000000 g_value_get_int +0001581c 0000c216 R_ARM_JUMP_SLOT 00000000 g_once_init_leave +00015820 0000c416 R_ARM_JUMP_SLOT 00000000 gst_value_array_append_value +00015824 0000c516 R_ARM_JUMP_SLOT 000078e8 gst_property_probe_probe_property +00015828 0000c616 R_ARM_JUMP_SLOT 00000000 gst_object_get_type +0001582c 0000cd16 R_ARM_JUMP_SLOT 00000000 g_type_class_peek_parent +00015830 0000ce16 R_ARM_JUMP_SLOT 0000642c gst_navigation_event_get_type +00015834 0000cf16 R_ARM_JUMP_SLOT 00000000 g_log +00015838 0000d116 R_ARM_JUMP_SLOT 00000000 strcmp +0001583c 0000d216 R_ARM_JUMP_SLOT 00000000 g_str_equal +00015840 0000d416 R_ARM_JUMP_SLOT 00000000 __cxa_finalize +00015844 0000d716 R_ARM_JUMP_SLOT 00000000 gst_structure_set +00015848 0000d816 R_ARM_JUMP_SLOT 00003f08 gst_color_balance_channel_get_type + +There are no unwind sections in this file. + +Symbol table '.dynsym' contains 218 entries: + Num: Value Size Type Bind Vis Ndx Name + 0: 00000000 0 NOTYPE LOCAL DEFAULT UND + 1: 00003664 0 SECTION LOCAL DEFAULT 8 + 2: 00000000 88 FUNC GLOBAL DEFAULT UND g_free + 3: 00000000 424 FUNC GLOBAL DEFAULT UND g_type_interface_peek + 4: 00006560 168 FUNC GLOBAL DEFAULT 10 gst_navigation_event_parse_command + 5: 00009bb4 368 FUNC GLOBAL DEFAULT 10 gst_x_overlay_got_xwindow_id + 6: 00000000 148 FUNC GLOBAL DEFAULT UND g_value_unset + 7: 00009924 160 FUNC GLOBAL DEFAULT 10 gst_x_overlay_handle_events + 8: 00000000 116 FUNC GLOBAL DEFAULT UND g_param_spec_string + 9: 00009e60 152 FUNC GLOBAL DEFAULT 10 gst_interfaces_marshal_VOID__OBJECT_ULONG + 10: 00000000 172 FUNC GLOBAL DEFAULT UND gst_structure_has_name + 11: 00004304 340 FUNC GLOBAL DEFAULT 10 gst_mixer_message_parse_option_changed + 12: 00000000 204 FUNC GLOBAL DEFAULT UND gst_value_array_get_value + 13: 000072c4 60 FUNC GLOBAL DEFAULT 10 gst_navigation_send_event + 14: 00004814 376 FUNC GLOBAL DEFAULT 10 gst_mixer_message_parse_mute_toggled + 15: 00008ba4 272 FUNC GLOBAL DEFAULT 10 gst_tuner_set_frequency + 16: 000097ac 64 FUNC GLOBAL DEFAULT 10 gst_video_orientation_get_vcenter + 17: 00006c10 172 FUNC GLOBAL DEFAULT 10 gst_navigation_query_get_type + 18: 00000000 116 FUNC GLOBAL DEFAULT UND g_value_dup_string + 19: 00000000 176 FUNC GLOBAL DEFAULT UND g_cclosure_marshal_VOID__INT + 20: 00000000 220 FUNC GLOBAL DEFAULT UND g_flags_register_static + 21: 000076ec 252 FUNC GLOBAL DEFAULT 10 gst_property_probe_needs_probe + 22: 00008d38 132 FUNC GLOBAL DEFAULT 10 gst_tuner_set_norm + 23: 00000000 188 FUNC GLOBAL DEFAULT UND g_object_get_data + 24: 00000000 4 OBJECT GLOBAL DEFAULT UND __gst_debug_min + 25: 00009f90 152 FUNC GLOBAL DEFAULT 10 gst_interfaces_marshal_VOID__OBJECT_POINTER + 26: 00000000 48 FUNC GLOBAL DEFAULT UND g_signal_emit + 27: 000074b0 80 FUNC GLOBAL DEFAULT 10 gst_property_probe_get_type + 28: 00000000 0 NOTYPE WEAK DEFAULT UND __gmon_start__ + 29: 00000000 0 NOTYPE WEAK DEFAULT UND _Jv_RegisterClasses + 30: 00000000 496 FUNC GLOBAL DEFAULT UND g_signal_emit_by_name + 31: 000057a8 68 FUNC GLOBAL DEFAULT 10 gst_mixer_set_record + 32: 0000a4ec 120 FUNC GLOBAL DEFAULT 10 gst_mixer_flags_get_type + 33: 0000a1a4 120 FUNC GLOBAL DEFAULT 10 gst_tuner_channel_flags_get_type + 34: 00000000 728 FUNC GLOBAL DEFAULT UND pow@GLIBC_2.4 (2) + 35: 00009a64 336 FUNC GLOBAL DEFAULT 10 gst_x_overlay_prepare_xwindow_id + 36: 00000000 112 FUNC GLOBAL DEFAULT UND g_value_get_enum + 37: 00005a5c 112 FUNC GLOBAL DEFAULT 10 gst_mixer_list_tracks + 38: 00007d7c 384 FUNC GLOBAL DEFAULT 10 gst_property_probe_get_property + 39: 00000000 52 FUNC GLOBAL DEFAULT UND g_list_foreach + 40: 00000000 16 FUNC GLOBAL DEFAULT UND g_list_free + 41: 00000000 276 FUNC GLOBAL DEFAULT UND gst_message_new_custom + 42: 000096ac 64 FUNC GLOBAL DEFAULT 10 gst_video_orientation_set_vcenter + 43: 00000000 112 FUNC GLOBAL DEFAULT UND g_value_set_int + 44: 000041dc 296 FUNC GLOBAL DEFAULT 10 gst_mixer_message_parse_options_list_changed + 45: 00000000 196 FUNC GLOBAL DEFAULT UND g_object_set_data_full + 46: 000066e8 268 FUNC GLOBAL DEFAULT 10 gst_navigation_event_parse_mouse_button_event + 47: 00004b04 540 FUNC GLOBAL DEFAULT 10 gst_mixer_options_list_changed + 48: 00005890 252 FUNC GLOBAL DEFAULT 10 gst_mixer_get_volume + 49: 00007274 80 FUNC GLOBAL DEFAULT 10 gst_navigation_get_type + 50: 00000000 272 FUNC GLOBAL DEFAULT UND gst_structure_get_int + 51: 00000000 112 FUNC GLOBAL DEFAULT UND g_value_get_uint + 52: 0000563c 32 FUNC GLOBAL DEFAULT 10 gst_mixer_get_mixer_type + 53: 00000000 120 FUNC GLOBAL DEFAULT UND gst_fraction_get_type + 54: 00000000 564 FUNC GLOBAL DEFAULT UND g_object_class_install_property + 55: 00000000 124 FUNC GLOBAL DEFAULT UND gst_value_array_get_type + 56: 00000000 184 FUNC GLOBAL DEFAULT UND g_param_spec_uint + 57: 00000000 220 FUNC GLOBAL DEFAULT UND g_enum_register_static + 58: 00000000 160 FUNC GLOBAL DEFAULT UND g_malloc + 59: 00006d9c 156 FUNC GLOBAL DEFAULT 10 gst_navigation_query_set_angles + 60: 00003c8c 104 FUNC GLOBAL DEFAULT 10 gst_color_balance_value_changed + 61: 00009348 80 FUNC GLOBAL DEFAULT 10 gst_tuner_norm_get_type + 62: 00009ef8 152 FUNC GLOBAL DEFAULT 10 gst_interfaces_marshal_VOID__OBJECT_STRING + 63: 00000000 180 FUNC GLOBAL DEFAULT UND g_value_peek_pointer + 64: 00000000 232 FUNC GLOBAL DEFAULT UND gst_structure_set_value + 65: 00000000 272 FUNC GLOBAL DEFAULT UND gst_structure_get_uint + 66: 00000000 272 FUNC GLOBAL DEFAULT UND gst_structure_get_double + 67: 000057ec 164 FUNC GLOBAL DEFAULT 10 gst_mixer_set_mute + 68: 00000000 184 FUNC GLOBAL DEFAULT UND g_param_spec_int + 69: 0000a564 120 FUNC GLOBAL DEFAULT 10 gst_mixer_message_type_get_type + 70: 000067f4 136 FUNC GLOBAL DEFAULT 10 gst_navigation_event_parse_key_event + 71: 0000972c 64 FUNC GLOBAL DEFAULT 10 gst_video_orientation_set_vflip + 72: 00008a88 284 FUNC GLOBAL DEFAULT 10 gst_tuner_get_frequency + 73: 00000000 124 FUNC GLOBAL DEFAULT UND gst_structure_new + 74: 00006e38 92 FUNC GLOBAL DEFAULT 10 gst_navigation_query_new_angles + 75: 0000986c 64 FUNC GLOBAL DEFAULT 10 gst_video_orientation_get_hflip + 76: 00008894 216 FUNC GLOBAL DEFAULT 10 gst_tuner_channel_changed + 77: 0000896c 284 FUNC GLOBAL DEFAULT 10 gst_tuner_signal_strength + 78: 000040b0 300 FUNC GLOBAL DEFAULT 10 gst_mixer_message_get_type + 79: 000098b8 108 FUNC GLOBAL DEFAULT 10 gst_x_overlay_get_type + 80: 00009640 108 FUNC GLOBAL DEFAULT 10 gst_video_orientation_get_type + 81: 00008354 128 FUNC GLOBAL DEFAULT 10 gst_stream_volume_get_mute + 82: 00007500 240 FUNC GLOBAL DEFAULT 10 gst_property_probe_get_values + 83: 000097ec 64 FUNC GLOBAL DEFAULT 10 gst_video_orientation_get_hcenter + 84: 0000737c 192 FUNC GLOBAL DEFAULT 10 gst_navigation_send_mouse_event + 85: 00006ef0 152 FUNC GLOBAL DEFAULT 10 gst_navigation_query_parse_commands_length + 86: 00000000 4 OBJECT GLOBAL DEFAULT UND GST_CAT_DEFAULT + 87: 00000000 164 FUNC GLOBAL DEFAULT UND gst_implements_interface_check + 88: 00005560 108 FUNC GLOBAL DEFAULT 10 gst_mixer_get_type + 89: 00000000 160 FUNC GLOBAL DEFAULT UND g_value_set_string + 90: 00005ca4 88 FUNC GLOBAL DEFAULT 10 gst_mixer_options_get_type + 91: 0000a3fc 120 FUNC GLOBAL DEFAULT 10 gst_navigation_command_get_type + 92: 00003d5c 32 FUNC GLOBAL DEFAULT 10 gst_color_balance_get_balance_type + 93: 0000a21c 120 FUNC GLOBAL DEFAULT 10 gst_stream_volume_format_get_type + 94: 000069f8 224 FUNC GLOBAL DEFAULT 10 gst_navigation_message_get_type + 95: 00000000 128 FUNC GLOBAL DEFAULT UND gst_value_list_get_size + 96: 00000000 656 FUNC GLOBAL DEFAULT UND cbrt@GLIBC_2.4 (2) + 97: 00000000 360 FUNC GLOBAL DEFAULT UND g_type_check_class_cast + 98: 00003d7c 68 FUNC GLOBAL DEFAULT 10 gst_color_balance_get_value + 99: 00007300 124 FUNC GLOBAL DEFAULT 10 gst_navigation_send_command + 100: 000052ec 628 FUNC GLOBAL DEFAULT 10 gst_mixer_volume_changed + 101: 000087bc 216 FUNC GLOBAL DEFAULT 10 gst_tuner_norm_changed + 102: 000085a4 264 FUNC GLOBAL DEFAULT 10 gst_tuner_signal_changed + 103: 00000000 56 FUNC GLOBAL DEFAULT UND gst_debug_log + 104: 000050fc 496 FUNC GLOBAL DEFAULT 10 gst_mixer_mute_toggled + 105: 00000000 184 FUNC GLOBAL DEFAULT UND g_object_set_data + 106: 00000000 272 FUNC GLOBAL DEFAULT UND g_once_init_enter_impl + 107: 00000000 148 FUNC GLOBAL DEFAULT UND g_param_spec_boolean + 108: 00000000 124 FUNC GLOBAL DEFAULT UND gst_value_list_get_type + 109: 000077e8 256 FUNC GLOBAL DEFAULT 10 gst_property_probe_needs_probe_name + 110: 00008dbc 132 FUNC GLOBAL DEFAULT 10 gst_tuner_list_norms + 111: 00003e04 56 FUNC GLOBAL DEFAULT 10 gst_color_balance_list_channels + 112: 00000000 220 FUNC GLOBAL DEFAULT UND gst_message_get_type + 113: 00000000 164 FUNC GLOBAL DEFAULT UND g_object_get + 114: 00000000 168 FUNC GLOBAL DEFAULT UND gst_structure_get_string + 115: 000079d4 244 FUNC GLOBAL DEFAULT 10 gst_property_probe_probe_and_get_values + 116: 00004458 580 FUNC GLOBAL DEFAULT 10 gst_mixer_message_parse_volume_changed + 117: 00006bb8 88 FUNC GLOBAL DEFAULT 10 gst_navigation_message_parse_mouse_over + 118: 00000000 112 FUNC GLOBAL DEFAULT UND g_value_set_enum + 119: 00008f24 132 FUNC GLOBAL DEFAULT 10 gst_tuner_get_channel + 120: 0000743c 116 FUNC GLOBAL DEFAULT 10 gst_navigation_send_key_event + 121: 00006608 224 FUNC GLOBAL DEFAULT 10 gst_navigation_event_parse_mouse_move_event + 122: 00000000 100 FUNC GLOBAL DEFAULT UND g_return_if_fail_warning + 123: 000096ec 64 FUNC GLOBAL DEFAULT 10 gst_video_orientation_set_hcenter + 124: 00006f88 200 FUNC GLOBAL DEFAULT 10 gst_navigation_query_parse_commands_nth + 125: 00000000 1288 FUNC GLOBAL DEFAULT UND g_type_register_static + 126: 0000a474 120 FUNC GLOBAL DEFAULT 10 gst_mixer_track_flags_get_type + 127: 00000000 136 FUNC GLOBAL DEFAULT UND gst_event_get_structure + 128: 00000000 168 FUNC GLOBAL DEFAULT UND g_object_set + 129: 000099c4 160 FUNC GLOBAL DEFAULT 10 gst_x_overlay_expose + 130: 00008fa8 132 FUNC GLOBAL DEFAULT 10 gst_tuner_set_channel + 131: 00000000 112 FUNC GLOBAL DEFAULT UND g_value_get_object + 132: 0000565c 168 FUNC GLOBAL DEFAULT 10 gst_mixer_get_option + 133: 00003dc0 68 FUNC GLOBAL DEFAULT 10 gst_color_balance_set_value + 134: 00006cbc 224 FUNC GLOBAL DEFAULT 10 gst_navigation_query_parse_angles + 135: 0000687c 152 FUNC GLOBAL DEFAULT 10 gst_navigation_message_new_angles_changed + 136: 00000000 176 FUNC GLOBAL DEFAULT UND g_cclosure_marshal_VOID__POINTER + 137: 00000000 544 FUNC GLOBAL DEFAULT UND g_signal_new + 138: 00003cf4 104 FUNC GLOBAL DEFAULT 10 gst_color_balance_get_type + 139: 00000000 452 FUNC GLOBAL DEFAULT UND g_type_check_instance_is_a + 140: 0000469c 376 FUNC GLOBAL DEFAULT 10 gst_mixer_message_parse_record_toggled + 141: 00000000 16 FUNC GLOBAL DEFAULT UND gst_message_new_element + 142: 00000000 148 FUNC GLOBAL DEFAULT UND gst_structure_get_value + 143: 00005e5c 80 FUNC GLOBAL DEFAULT 10 gst_mixer_track_get_type + 144: 00000000 132 FUNC GLOBAL DEFAULT UND gst_query_new_application + 145: 00000000 236 FUNC GLOBAL DEFAULT UND g_param_spec_double + 146: 00006e94 92 FUNC GLOBAL DEFAULT 10 gst_navigation_query_new_commands + 147: 00005704 164 FUNC GLOBAL DEFAULT 10 gst_mixer_set_option + 148: 00000000 128 FUNC GLOBAL DEFAULT UND gst_value_array_get_size + 149: 00000000 136 FUNC GLOBAL DEFAULT UND gst_message_get_structure + 150: 00000000 156 FUNC GLOBAL DEFAULT UND g_type_name + 151: 00000000 236 FUNC GLOBAL DEFAULT UND log10@GLIBC_2.4 (2) + 152: 00007188 236 FUNC GLOBAL DEFAULT 10 gst_navigation_query_set_commands + 153: 00009480 80 FUNC GLOBAL DEFAULT 10 gst_tuner_channel_get_type + 154: 00007bc4 248 FUNC GLOBAL DEFAULT 10 gst_property_probe_probe_property_name + 155: 00000000 204 FUNC GLOBAL DEFAULT UND gst_value_list_get_value + 156: 00000000 984 FUNC GLOBAL DEFAULT UND g_type_interface_add_prerequisite + 157: 00000000 492 FUNC GLOBAL DEFAULT UND gst_element_post_message + 158: 00000000 136 FUNC GLOBAL DEFAULT UND gst_implements_interface_get_type + 159: 00008538 108 FUNC GLOBAL DEFAULT 10 gst_tuner_get_type + 160: 00005cfc 144 FUNC GLOBAL DEFAULT 10 gst_mixer_options_get_values + 161: 00000000 616 FUNC GLOBAL DEFAULT UND g_type_check_instance_cast + 162: 00000000 160 FUNC GLOBAL DEFAULT UND gst_element_get_type + 163: 00007f94 512 FUNC GLOBAL DEFAULT 10 gst_stream_volume_convert_volume + 164: 00008260 128 FUNC GLOBAL DEFAULT 10 gst_stream_volume_get_type + 165: 00000000 316 FUNC GLOBAL DEFAULT UND g_object_interface_install_property + 166: 000083d4 184 FUNC GLOBAL DEFAULT 10 gst_stream_volume_set_volume + 167: 0000598c 208 FUNC GLOBAL DEFAULT 10 gst_mixer_set_volume + 168: 00008cb4 132 FUNC GLOBAL DEFAULT 10 gst_tuner_get_norm + 169: 00000000 220 FUNC GLOBAL DEFAULT UND g_object_class_find_property + 170: 00000000 192 FUNC GLOBAL DEFAULT UND gst_value_list_append_value + 171: 00008e40 228 FUNC GLOBAL DEFAULT 10 gst_tuner_find_norm_by_name + 172: 000082e0 116 FUNC GLOBAL DEFAULT 10 gst_stream_volume_set_mute + 173: 0000a0c0 108 FUNC GLOBAL DEFAULT 10 gst_mixer_type_get_type + 174: 00007ac8 252 FUNC GLOBAL DEFAULT 10 gst_property_probe_probe_and_get_values_name + 175: 00007cbc 192 FUNC GLOBAL DEFAULT 10 gst_property_probe_get_properties + 176: 00000000 348 FUNC GLOBAL DEFAULT UND g_value_init + 177: 0000982c 64 FUNC GLOBAL DEFAULT 10 gst_video_orientation_get_vflip + 178: 0000a028 152 FUNC GLOBAL DEFAULT 10 gst_interfaces_marshal_VOID__OBJECT_BOOLEAN + 179: 00004f0c 496 FUNC GLOBAL DEFAULT 10 gst_mixer_record_toggled + 180: 00000000 176 FUNC GLOBAL DEFAULT UND g_cclosure_marshal_VOID__OBJECT + 181: 00000000 220 FUNC GLOBAL DEFAULT UND gst_structure_get_boolean + 182: 0000902c 132 FUNC GLOBAL DEFAULT 10 gst_tuner_list_channels + 183: 00006914 100 FUNC GLOBAL DEFAULT 10 gst_navigation_message_new_commands_changed + 184: 00000000 112 FUNC GLOBAL DEFAULT UND g_value_set_uint + 185: 00000000 136 FUNC GLOBAL DEFAULT UND gst_query_get_structure + 186: 0000976c 64 FUNC GLOBAL DEFAULT 10 gst_video_orientation_set_hflip + 187: 000086ac 272 FUNC GLOBAL DEFAULT 10 gst_tuner_frequency_changed + 188: 0000a294 120 FUNC GLOBAL DEFAULT 10 gst_navigation_event_type_get_type + 189: 00006ad8 224 FUNC GLOBAL DEFAULT 10 gst_navigation_message_parse_angles_changed + 190: 00000000 504 FUNC GLOBAL DEFAULT UND g_type_check_value_holds + 191: 000075f0 252 FUNC GLOBAL DEFAULT 10 gst_property_probe_get_values_name + 192: 00000000 112 FUNC GLOBAL DEFAULT UND g_value_get_int + 193: 0000a30c 120 FUNC GLOBAL DEFAULT 10 gst_navigation_message_type_get_type + 194: 00000000 284 FUNC GLOBAL DEFAULT UND g_once_init_leave + 195: 0000a384 120 FUNC GLOBAL DEFAULT 10 gst_navigation_query_type_get_type + 196: 00000000 192 FUNC GLOBAL DEFAULT UND gst_value_array_append_value + 197: 000078e8 236 FUNC GLOBAL DEFAULT 10 gst_property_probe_probe_property + 198: 00000000 172 FUNC GLOBAL DEFAULT UND gst_object_get_type + 199: 000070b8 208 FUNC GLOBAL DEFAULT 10 gst_navigation_query_set_commandsv + 200: 00004d20 492 FUNC GLOBAL DEFAULT 10 gst_mixer_option_changed + 201: 000055cc 112 FUNC GLOBAL DEFAULT 10 gst_mixer_get_mixer_flags + 202: 0000848c 172 FUNC GLOBAL DEFAULT 10 gst_stream_volume_get_volume + 203: 0000a12c 120 FUNC GLOBAL DEFAULT 10 gst_color_balance_type_get_type + 204: 00000000 176 FUNC GLOBAL DEFAULT UND g_cclosure_marshal_VOID__ULONG + 205: 00000000 260 FUNC GLOBAL DEFAULT UND g_type_class_peek_parent + 206: 0000642c 308 FUNC GLOBAL DEFAULT 10 gst_navigation_event_get_type + 207: 00000000 48 FUNC GLOBAL DEFAULT UND g_log + 208: 000090b0 228 FUNC GLOBAL DEFAULT 10 gst_tuner_find_channel_by_name + 209: 00000000 52 FUNC GLOBAL DEFAULT UND strcmp@GLIBC_2.4 (3) + 210: 00000000 20 FUNC GLOBAL DEFAULT UND g_str_equal + 211: 00009d24 168 FUNC GLOBAL DEFAULT 10 gst_x_overlay_set_xwindow_id + 212: 00000000 332 FUNC WEAK DEFAULT UND __cxa_finalize@GLIBC_2.4 (3) + 213: 00009dcc 148 FUNC GLOBAL DEFAULT 10 gst_interfaces_marshal_VOID__OBJECT_INT + 214: 0000498c 376 FUNC GLOBAL DEFAULT 10 gst_mixer_mixer_changed + 215: 00000000 116 FUNC GLOBAL DEFAULT UND gst_structure_set + 216: 00003f08 80 FUNC GLOBAL DEFAULT 10 gst_color_balance_channel_get_type + 217: 00006978 128 FUNC GLOBAL DEFAULT 10 gst_navigation_message_new_mouse_over + +Histogram for bucket list length (total of 197 buckets): + Length Number % of total Coverage + 0 71 ( 36.0%) + 1 69 ( 35.0%) 31.9% + 2 37 ( 18.8%) 66.2% + 3 12 ( 6.1%) 82.9% + 4 4 ( 2.0%) 90.3% + 5 3 ( 1.5%) 97.2% + 6 1 ( 0.5%) 100.0% + +Version symbols section '.gnu.version' contains 218 entries: + Addr: 0000000000002be6 Offset: 0x002be6 Link: 2 (.dynsym) + 000: 0 (*local*) 0 (*local*) 0 (*local*) 0 (*local*) + 004: 1 (*global*) 1 (*global*) 0 (*local*) 1 (*global*) + 008: 0 (*local*) 1 (*global*) 0 (*local*) 1 (*global*) + 00c: 0 (*local*) 1 (*global*) 1 (*global*) 1 (*global*) + 010: 1 (*global*) 1 (*global*) 0 (*local*) 0 (*local*) + 014: 0 (*local*) 1 (*global*) 1 (*global*) 0 (*local*) + 018: 0 (*local*) 1 (*global*) 0 (*local*) 1 (*global*) + 01c: 0 (*local*) 0 (*local*) 0 (*local*) 1 (*global*) + 020: 1 (*global*) 1 (*global*) 2 (GLIBC_2.4) 1 (*global*) + 024: 0 (*local*) 1 (*global*) 1 (*global*) 0 (*local*) + 028: 0 (*local*) 0 (*local*) 1 (*global*) 0 (*local*) + 02c: 1 (*global*) 0 (*local*) 1 (*global*) 1 (*global*) + 030: 1 (*global*) 1 (*global*) 0 (*local*) 0 (*local*) + 034: 1 (*global*) 0 (*local*) 0 (*local*) 0 (*local*) + 038: 0 (*local*) 0 (*local*) 0 (*local*) 1 (*global*) + 03c: 1 (*global*) 1 (*global*) 1 (*global*) 0 (*local*) + 040: 0 (*local*) 0 (*local*) 0 (*local*) 1 (*global*) + 044: 0 (*local*) 1 (*global*) 1 (*global*) 1 (*global*) + 048: 1 (*global*) 0 (*local*) 1 (*global*) 1 (*global*) + 04c: 1 (*global*) 1 (*global*) 1 (*global*) 1 (*global*) + 050: 1 (*global*) 1 (*global*) 1 (*global*) 1 (*global*) + 054: 1 (*global*) 1 (*global*) 0 (*local*) 0 (*local*) + 058: 1 (*global*) 0 (*local*) 1 (*global*) 1 (*global*) + 05c: 1 (*global*) 1 (*global*) 1 (*global*) 0 (*local*) + 060: 2 (GLIBC_2.4) 0 (*local*) 1 (*global*) 1 (*global*) + 064: 1 (*global*) 1 (*global*) 1 (*global*) 0 (*local*) + 068: 1 (*global*) 0 (*local*) 0 (*local*) 0 (*local*) + 06c: 0 (*local*) 1 (*global*) 1 (*global*) 1 (*global*) + 070: 0 (*local*) 0 (*local*) 0 (*local*) 1 (*global*) + 074: 1 (*global*) 1 (*global*) 0 (*local*) 1 (*global*) + 078: 1 (*global*) 1 (*global*) 0 (*local*) 1 (*global*) + 07c: 1 (*global*) 0 (*local*) 1 (*global*) 0 (*local*) + 080: 0 (*local*) 1 (*global*) 1 (*global*) 0 (*local*) + 084: 1 (*global*) 1 (*global*) 1 (*global*) 1 (*global*) + 088: 0 (*local*) 0 (*local*) 1 (*global*) 0 (*local*) + 08c: 1 (*global*) 0 (*local*) 0 (*local*) 1 (*global*) + 090: 0 (*local*) 0 (*local*) 1 (*global*) 1 (*global*) + 094: 0 (*local*) 0 (*local*) 0 (*local*) 2 (GLIBC_2.4) + 098: 1 (*global*) 1 (*global*) 1 (*global*) 0 (*local*) + 09c: 0 (*local*) 0 (*local*) 0 (*local*) 1 (*global*) + 0a0: 1 (*global*) 0 (*local*) 0 (*local*) 1 (*global*) + 0a4: 1 (*global*) 0 (*local*) 1 (*global*) 1 (*global*) + 0a8: 1 (*global*) 0 (*local*) 0 (*local*) 1 (*global*) + 0ac: 1 (*global*) 1 (*global*) 1 (*global*) 1 (*global*) + 0b0: 0 (*local*) 1 (*global*) 1 (*global*) 1 (*global*) + 0b4: 0 (*local*) 0 (*local*) 1 (*global*) 1 (*global*) + 0b8: 0 (*local*) 0 (*local*) 1 (*global*) 1 (*global*) + 0bc: 1 (*global*) 1 (*global*) 0 (*local*) 1 (*global*) + 0c0: 0 (*local*) 1 (*global*) 0 (*local*) 1 (*global*) + 0c4: 0 (*local*) 1 (*global*) 0 (*local*) 1 (*global*) + 0c8: 1 (*global*) 1 (*global*) 1 (*global*) 1 (*global*) + 0cc: 0 (*local*) 0 (*local*) 1 (*global*) 0 (*local*) + 0d0: 1 (*global*) 3 (GLIBC_2.4) 0 (*local*) 1 (*global*) + 0d4: 3 (GLIBC_2.4) 1 (*global*) 1 (*global*) 0 (*local*) + 0d8: 1 (*global*) 1 (*global*) + +Version needs section '.gnu.version_r' contains 2 entries: + Addr: 0x0000000000002d9c Offset: 0x002d9c Link to section: 3 (.dynstr) + 000000: Version: 1 File: libc.so.6 Cnt: 1 + 0x0010: Name: GLIBC_2.4 Flags: none Version: 3 + 0x0020: Version: 1 File: libm.so.6 Cnt: 1 + 0x0030: Name: GLIBC_2.4 Flags: none Version: 2 +Attribute Section: aeabi +File Attributes + Tag_CPU_name: "ARM10TDMI" + Tag_CPU_arch: v5TE + Tag_ARM_ISA_use: Yes + Tag_THUMB_ISA_use: Thumb-1 + Tag_ABI_PCS_wchar_t: 4 + Tag_ABI_FP_denormal: Needed + Tag_ABI_FP_exceptions: Needed + Tag_ABI_FP_number_model: IEEE 754 + Tag_ABI_align8_needed: Yes + Tag_ABI_align8_preserved: Yes, except leaf SP + Tag_ABI_enum_size: int + Tag_ABI_optimization_goals: Aggressive Speed diff --git a/test/Makefile.am b/test/Makefile.am new file mode 100755 index 0000000..0c18a31 --- /dev/null +++ b/test/Makefile.am @@ -0,0 +1,24 @@ +bin_PROGRAMS = mm_camcorder_testsuite + +mm_camcorder_testsuite_SOURCES = mm_camcorder_testsuite.c + +mm_camcorder_testsuite_CFLAGS = -I$(srcdir)/../src/include \ + $(GLIB_CFLAGS)\ + $(GST_CFLAGS)\ + $(MM_COMMON_CFLAGS)\ + $(MMTA_CFLAGS)\ + $(MM_SOUND_CFLAGS) + +############################################ +#mm_camcorder_testsuite_CFLAGS += -DAPPSRC_TEST +############################################ + +mm_camcorder_testsuite_DEPENDENCIES = $(top_builddir)/src/libmmfcamcorder.la + +mm_camcorder_testsuite_LDADD = $(top_builddir)/src/libmmfcamcorder.la \ + $(GLIB_LIBS)\ + $(GST_LIBS)\ + $(MM_COMMON_LIBS)\ + $(MMTA_LIBS)\ + $(MM_SOUND_LIBS) + diff --git a/test/mm_camcorder_testsuite.c b/test/mm_camcorder_testsuite.c new file mode 100644 index 0000000..57e7eb6 --- /dev/null +++ b/test/mm_camcorder_testsuite.c @@ -0,0 +1,3054 @@ +/* + * mm_camcorder_testsuite + * + * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: Jeongmo Yang + * + * 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. + * + */ + +/* =========================================================================================== +EDIT HISTORY FOR MODULE + This section contains comments describing changes made to the module. + Notice that changes are listed in reverse chronological order. +when who what, where, why +--------- -------------------- ---------------------------------------------------------- +10/08/07 soyeon.kang@samsung.com Created +10/10/07 wh01.cho@samsung.com Created +12/30/08 jh1979.park@samsung.com Modified +08/31/11 sc11.lee@samsung.com Modified (Reorganized for easy look) +*/ + + +/*=========================================================================================== +| | +| INCLUDE FILES | +| | +========================================================================================== */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/*--------------------------------------------------------------------------- +| GLOBAL VARIABLE DEFINITIONS: | +---------------------------------------------------------------------------*/ +#define EXPORT_API __attribute__((__visibility__("default"))) + +#define PACKAGE "mm_camcorder_testsuite" + +GMainLoop *g_loop; +GIOChannel *stdin_channel; +int resolution_set; +int g_current_state; +int src_w, src_h; +GstCaps *filtercaps; +bool isMultishot; +MMCamPreset cam_info; +int mmcamcorder_state; +int mmcamcorder_print_state; +int multishot_num; +static int audio_stream_cb_cnt, video_stream_cb_cnt; +static GTimer *timer = NULL; + +/*--------------------------------------------------------------------------- +| GLOBAL CONSTANT DEFINITIONS: | +---------------------------------------------------------------------------*/ + + +/*--------------------------------------------------------------------------- +| IMPORTED VARIABLE DECLARATIONS: | +---------------------------------------------------------------------------*/ + + +/*--------------------------------------------------------------------------- +| IMPORTED FUNCTION DECLARATIONS: | +---------------------------------------------------------------------------*/ + + +/*--------------------------------------------------------------------------- +| LOCAL #defines: | +---------------------------------------------------------------------------*/ +#define test_ffmux_mp4 + +// FULLHD(1080P) +#define SRC_W_1920 1920 +#define SRC_H_1080 1080 + + +// 2M +#define SRC_W_1600 1600 +#define SRC_H_1200 1200 + +//VGA +#define SRC_W_640 640 +#define SRC_H_480 480 + +//QVGA +#define SRC_W_320 320 // video input width +#define SRC_H_240 240 // video input height + +//QCIF +#define SRC_W_176 176 // video input width +#define SRC_H_144 144 // video input height + +//QQVGA +#define SRC_W_160 160 // video input width +#define SRC_H_120 120 // video input heith + +//special resolution +#define SRC_W_400 400 // video input width +#define SRC_H_300 300 // video input height + +#define SRC_W_192 192 // video input width +#define SRC_H_256 256 // video input height + +#define SRC_W_144 144 // video input width +#define SRC_H_176 176 // video input height + +#define SRC_W_300 300 +#define SRC_W_400 400 + + +#define DISPLAY_X_0 0 //for direct FB +#define DISPLAY_Y_0 0 //for direct FB + +#define DISPLAY_W_320 320 //for direct FB +#define DISPLAY_H_240 240 //for direct FB + + +#define SRC_VIDEO_FRAME_RATE_15 15 // video input frame rate +#define SRC_VIDEO_FRAME_RATE_30 30 // video input frame rate +#define IMAGE_ENC_QUALITY 85 // quality of jpeg +#define IMAGE_CAPTURE_COUNT_STILL 1 // the number of still-shot +#define IMAGE_CAPTURE_COUNT_MULTI 3 // default the number of multi-shot +#define IMAGE_CAPTURE_COUNT_INTERVAL 500 // mili seconds + +#define MAX_FILE_SIZE_FOR_MMS (250 * 1024) + +#define EXT_JPEG "jpg" +#define EXT_MP4 "mp4" +#define EXT_3GP "3gp" +#define EXT_AMR "amr" +#define EXT_MKV "mkv" + +#define STILL_CAPTURE_FILE_PATH_NAME "/root/StillshotCapture" +#define MULTI_CAPTURE_FILE_PATH_NAME "/root/MultishotCapture" +#define TARGET_FILENAME_PATH "/opt/media/" +#define TARGET_FILENAME_VIDEO "/opt/media/test_rec_video.3gp" +#define TARGET_FILENAME_AUDIO "/opt/media/test_rec_audio.amr" +#define CAPTURE_FILENAME_LEN 256 + +#define AUDIO_SOURCE_SAMPLERATE_AAC 44100 +#define AUDIO_SOURCE_SAMPLERATE_AMR 8000 +#define AUDIO_SOURCE_FORMAT MM_CAMCORDER_AUDIO_FORMAT_PCM_S16_LE +#define AUDIO_SOURCE_CHANNEL_AAC 2 +#define AUDIO_SOURCE_CHANNEL_AMR 1 + +#define DEFAULT_CAM_DEVICE MM_VIDEO_DEVICE_CAMERA1 + +/* + * D E B U G M E S S A G E + */ +#define MMF_DEBUG "** (mmcamcorder testsuite) DEBUG: " +#define MMF_ERR "** (mmcamcorder testsuite) ERROR: " +#define MMF_INFO "** (mmcamcorder testsuite) INFO: " +#define MMF_WARN "** (mmcamcorder testsuite) WARNING: " +#define MMF_TIME "** (mmcamcorder testsuite) TIME: " + +#define CHECK_MM_ERROR(expr) \ +do {\ + int ret = 0; \ + ret = expr; \ + if (ret != MM_ERROR_NONE) {\ + printf("[%s:%d] error code : %x \n", __func__, __LINE__, ret); \ + return; \ + }\ +} while(0) + +#define time_msg_t(fmt,arg...) \ +do { \ + fprintf(stderr,"\x1b[44m\x1b[37m"MMF_TIME"[%s:%05d] " fmt ,__func__, __LINE__, ##arg); \ + fprintf(stderr,"\x1b[0m\n"); \ +} while(0) + + #define debug_msg_t(fmt,arg...)\ + do { \ + fprintf(stderr, MMF_DEBUG"[%s:%05d] " fmt "\n",__func__, __LINE__, ##arg); \ + } while(0) + +#define err_msg_t(fmt,arg...) \ +do { \ + fprintf(stderr, MMF_ERR"[%s:%05d] " fmt "\n",__func__, __LINE__, ##arg); \ +} while(0) + +#define info_msg_t(fmt,arg...) \ +do { \ + fprintf(stderr, MMF_INFO"[%s:%05d] " fmt "\n",__func__, __LINE__, ##arg); \ +} while(0) + +#define warn_msg_t(fmt,arg...) \ +do { \ + fprintf(stderr, MMF_WARN"[%s:%05d] " fmt "\n",__func__, __LINE__, ##arg); \ +} while(0) + +#ifndef SAFE_FREE +#define SAFE_FREE(x) if(x) {g_free(x); x = NULL;} +#endif + + +GTimeVal previous; +GTimeVal current; +GTimeVal result; +//temp + +/** + * Enumerations for command + */ +#define SENSOR_WHITEBALANCE_NUM 10 +#define SENSOR_COLOR_TONE_NUM 27 +#define SENSOR_FLIP_NUM 3 +#define SENSOR_PROGRAM_MODE_NUM 15 +#define SENSOR_FOCUS_NUM 5 +#define SENSOR_INPUT_ROTATION 6 +#define SENSOR_AF_SCAN_NUM 4 +#define SENSOR_ISO_NUM 8 +#define SENSOR_EXPOSURE_NUM 9 +#define SENSOR_IMAGE_FORMAT 9 + + +/*--------------------------------------------------------------------------- +| LOCAL CONSTANT DEFINITIONS: | +---------------------------------------------------------------------------*/ +enum +{ + MODE_IMAGE, /* capture mode */ + MODE_VIDEO, /* recording mode */ + MODE_AUDIO, /* audio recording*/ + MODE_NUM, +}; + +enum +{ + MENU_STATE_MAIN, + MENU_STATE_SETTING, + MENU_STATE_NUM, +}; + +/*--------------------------------------------------------------------------- +| LOCAL DATA TYPE DEFINITIONS: | +---------------------------------------------------------------------------*/ +typedef struct _cam_handle +{ + MMHandleType camcorder; + int mode; /* image(capture)/video(recording) mode */ + bool isMultishot; + int stillshot_count; /* total stillshot count */ + int multishot_count; /* total multishot count */ + char *stillshot_filename; /* stored filename of stillshot */ + char *multishot_filename; /* stored filename of multishot */ + int menu_state; + int fps; + bool isMute; + unsigned int elapsed_time; +} cam_handle_t; + +typedef struct _cam_xypair +{ + char* attr_subcat_x; + char* attr_subcat_y; + int x; + int y; +} cam_xypair_t; + +/*--------------------------------------------------------------------------- +| LOCAL VARIABLE DEFINITIONS: | +---------------------------------------------------------------------------*/ +static cam_handle_t *hcamcorder ; + +char *wb[SENSOR_WHITEBALANCE_NUM]={ + "None", + "Auto", + "Daylight", + "Cloudy", + "Fluoroscent", + "Incandescent", + "Shade", + "Horizon", + "Flash", + "Custom", +}; + +char *ct[SENSOR_COLOR_TONE_NUM] = { + "NONE", + "MONO", + "SEPIA", + "NEGATIVE", + "BLUE", + "GREEN", + "AQUA", + "VIOLET", + "ORANGE", + "GRAY", + "RED", + "ANTIQUE", + "WARM", + "PINK", + "YELLOW", + "PURPLE", + "EMBOSS", + "OUTLINE", + "SOLARIZATION_1", + "SOLARIZATION_2", + "SOLARIZATION_3", + "SOLARIZATION_4", + "SKETCH_1", + "SKETCH_2", + "SKETCH_3", + "SKETCH_4", +}; + +char *flip[SENSOR_FLIP_NUM] = { + "Horizontal", + "Vertical", + "Not flipped", +}; + +char *program_mode[SENSOR_PROGRAM_MODE_NUM] = { + "NORMAL", + "PORTRAIT", + "LANDSCAPE", + "SPORTS", + "PARTY_N_INDOOR", + "BEACH_N_INDOOR", + "SUNSET", + "DUSK_N_DAWN", + "FALL_COLOR", + "NIGHT_SCENE", + "FIREWORK", + "TEXT", + "SHOW_WINDOW", + "CANDLE_LIGHT", + "BACKLIGHT", +}; + +char *focus_mode[SENSOR_FOCUS_NUM] = { + "None", + "Pan", + "Auto", + "Manual", + "Touch Auto", +}; + +char *camera_rotation[SENSOR_INPUT_ROTATION] = { + "None", + "90", + "180", + "270", + "Flip Horizontal", + "Flip Vertical", +}; + +char *af_scan[SENSOR_AF_SCAN_NUM] = { + "None", + "Normal", + "Macro mode", + "Full mode", +}; + +char *iso_name[SENSOR_ISO_NUM] = { + "ISO Auto", + "ISO 50", + "ISO 100", + "ISO 200", + "ISO 400", + "ISO 800", + "ISO 1600", + "ISO 3200", +}; + +char *exposure_mode[SENSOR_EXPOSURE_NUM] = { + "AE off", + "AE all mode", + "AE center 1 mode", + "AE center 2 mode", + "AE center 3 mode", + "AE spot 1 mode", + "AE spot 2 mode", + "AE custom 1 mode", + "AE custom 2 mode", +}; + +char *image_fmt[SENSOR_IMAGE_FORMAT] = { + "NV12", + "NV12T", + "NV16", + "NV21", + "YUYV", + "UYVY", + "422P", + "I420", + "YV12", +}; + +char *output_mode[] = { + "Letter Box mode", + "Original Size mode", + "Full Screen mode", + "Cropped Full Screen mode", + "ROI mode", +}; + +char *rotate_mode[] = { + "0", + "90", + "180", + "270", + "Flip Horizontal", + "Flip Vertical", +}; + +char* strobe_mode[] = { + "Strobe OFF", + "Strobe ON", + "Strobe Auto", + "Strobe RedEyeReduction", + "Strobe SlowSync", + "Strobe FrontCurtain", + "Strobe RearCurtain", + "Strobe Permanent", +}; + +char *detection_mode[2] = { + "Face Detection OFF", + "Face Detection ON", +}; + +char *wdr_mode[] = { + "WDR OFF", + "WDR ON", + "WDR AUTO", +}; + +char *ahs_mode[] = { + "Anti-handshake OFF", + "Anti-handshake ON", + "Anti-handshake AUTO", + "Anti-handshake MOVIE", +}; + +char *visible_mode[] = { + "Display OFF", + "Display ON", +}; + +char *camcorder_rotate_val[] = { + "0", + "90", + "180", + "270", +}; + +/*--------------------------------------------------------------------------- +| LOCAL FUNCTION PROTOTYPES: | +---------------------------------------------------------------------------*/ +static void print_menu(); +void get_me_out(); +static gboolean cmd_input(GIOChannel *channel); +//static bool filename_callback (int format, char *filename, void *user_param); +static gboolean msg_callback(int message, void *msg_param, void *user_param); +static gboolean init(int type); +static gboolean mode_change(); +int camcordertest_set_attr_int(char* attr_subcategory, int value); + + +static inline void flush_stdin() +{ + int ch; + while((ch=getchar()) != EOF && ch != '\n'); +} + +void +cam_utils_convert_YUYV_to_UYVY(unsigned char* dst, unsigned char* src, gint length) +{ + int i = 0; + + //memset dst + memset(dst, 0x00, length); + memcpy(dst, src + 1, length-1); + + for ( i = 0 ; i < length; i ++) + { + if ( !(i % 2) ) + { + dst[i+1] = src[i]; + } + } +} + +static int camcordertest_audio_stream_cb(MMCamcorderAudioStreamDataType *stream, void *user_param) +{ + if ( (int)(stream->timestamp)/1000 == audio_stream_cb_cnt ) { + audio_stream_cb_cnt++; + printf("audio_stream cb is called ( data:%p, format:%d, channel:%d, volume_dB:%f, length:%d, timestamp:%d)\n", stream->data, stream->format, stream->channel, stream->volume_dB, stream->length, stream->timestamp); + } + return TRUE; +} + +static int camcordertest_video_stream_cb(MMCamcorderVideoStreamDataType *stream, void *user_param) +{ + if ( (int)(stream->timestamp)/1000 == video_stream_cb_cnt ) { + video_stream_cb_cnt++; + printf("video_stream cb is called ( data:%p, format:%d, length:%d, width:%d, height:%d, timestamp:%d)\n", stream->data, stream->format, stream->length, stream->width, stream->height, stream->timestamp); + } + return TRUE; +} + +static int +camcordertest_video_capture_cb(MMCamcorderCaptureDataType *main, MMCamcorderCaptureDataType *thumb, void *data) +{ + int nret = 0; + int scrnl_size = 0; + char m_filename[CAPTURE_FILENAME_LEN]; + FILE *fp = NULL; + MMCamcorderCaptureDataType *scrnl = NULL; + + debug_msg_t("hcamcorder->isMultishot=%d =>1: MULTI, 0: STILL",hcamcorder->isMultishot); + + if (main == NULL) { + warn_msg_t("Capture callback : Main image buffer is NULL!!!"); + return FALSE; + } + + if (hcamcorder->isMultishot == TRUE) { + snprintf(m_filename, CAPTURE_FILENAME_LEN, "%s%03d.jpg", hcamcorder->multishot_filename,hcamcorder->multishot_count++); + } else { + snprintf(m_filename, CAPTURE_FILENAME_LEN, "%s%03d.jpg", hcamcorder->stillshot_filename,hcamcorder->stillshot_count++); + } + + debug_msg_t("filename : %s", m_filename); + + if (main->format != MM_PIXEL_FORMAT_ENCODED) { + unsigned int dst_size = 0; + void *dst = NULL; + + nret = _mmcamcorder_encode_jpeg(main->data, main->width, main->height, main->format, + main->length, 90, &dst, &dst_size); + if (nret) { + fp = fopen(m_filename, "w+"); + if (fp == NULL) { + printf("FileOPEN error!!\n"); + warn_msg_t("FileOPEN error!!"); + return FALSE; + } else { + printf("open success\n"); + if (fwrite(dst, dst_size, 1, fp) != 1) { + printf("File write error!!\n"); + warn_msg_t("File write error!!"); + fclose(fp); + return FALSE; + } + printf("write success\n"); + } + fclose(fp); + fp = NULL; + } else { + printf("Failed to encode YUV(%d) -> JPEG. \n", main->format); + } + + free(dst); + dst = NULL; + } else { + printf("MM_PIXEL_FORMAT_ENCODED main->data=%p main->length=%d, main->width=%d, main->heigtht=%d \n", + main->data, main->length, main->width, main->height); + + /* main image */ + fp = fopen(m_filename, "w+"); + if (fp == NULL) { + printf("FileOPEN error!!\n"); + warn_msg_t("FileOPEN error!!"); + return FALSE; + } else { + printf("open success\n"); + if (fwrite(main->data, main->length, 1, fp) != 1) { + printf("File write error!!\n"); + warn_msg_t("File write error!!"); + fclose(fp); + return FALSE; + } + printf("write success\n"); + } + fclose(fp); + fp = NULL; + + /* thumbnail */ + if (thumb != NULL) { + fp = fopen("./thumbnail.jpg", "w+"); + if (fp == NULL) { + printf("FileOPEN error!!\n"); + warn_msg_t("FileOPEN error!!"); + return FALSE; + } else { + printf("open success\n"); + if (fwrite(thumb->data, thumb->length, 1, fp) != 1) { + printf("File write error!!\n"); + warn_msg_t("File write error!!"); + fclose(fp); + return FALSE; + } + printf("write success\n"); + } + fclose(fp); + fp = NULL; + } + + /* screennail */ + mm_camcorder_get_attributes(hcamcorder->camcorder, NULL, + "captured-screennail", &scrnl, &scrnl_size, + NULL); + if (scrnl != NULL) { + fp = fopen("./screennail.yuv", "w+"); + if (fp == NULL) { + printf("FileOPEN error!!\n"); + warn_msg_t("FileOPEN error!!"); + return FALSE; + } else { + printf("open success\n"); + + if (fwrite(scrnl->data, scrnl->length, 1, fp) != 1) { + printf("File write error!!\n"); + warn_msg_t("File write error!!"); + fclose(fp); + fp = NULL; + return FALSE; + } + + fclose(fp); + fp = NULL; + + printf("write success\n"); + } + } else { + printf( "Screennail buffer is NULL.\n" ); + } + } + + return TRUE; +} + +static gboolean test_idle_capture_start() +{ + int err; + + if (!hcamcorder->isMultishot) + { + camcordertest_set_attr_int("capture-format", MM_PIXEL_FORMAT_ENCODED); + camcordertest_set_attr_int(MMCAM_IMAGE_ENCODER, MM_IMAGE_CODEC_JPEG); + } + else + { +// camcordertest_set_attr_int("capture-format", MM_PIXEL_FORMAT_I420); + camcordertest_set_attr_int("capture-format", MM_PIXEL_FORMAT_YUYV); + } + + g_timer_reset(timer); + err = mm_camcorder_capture_start(hcamcorder->camcorder); + + if (err < 0) + { +// if(hcamcorder->isMultishot == TRUE) +// hcamcorder->isMultishot = FALSE; + warn_msg_t("Multishot mm_camcorder_capture_start = %x", err); + } + return FALSE; +} + +int camcordertest_set_attr_int(char * attr_subcategory, int value) +{ + char * err_attr_name = NULL; + int err; + + if (hcamcorder) + { + if (hcamcorder->camcorder) + { + debug_msg_t("camcordertest_set_attr_int(%s, %d)", attr_subcategory, value); + + err = mm_camcorder_set_attributes(hcamcorder->camcorder, &err_attr_name, + attr_subcategory, value, + NULL); + if (err < 0) + { + err_msg_t("camcordertest_set_attr_int : Error(%s:%x)!!!!!!!", err_attr_name, err); + SAFE_FREE (err_attr_name); + return FALSE; + } + + //success + return TRUE; + } + + debug_msg_t("camcordertest_set_attr_int(!hcamcorder->camcorde)"); + } + + debug_msg_t("camcordertest_set_attr_int(!hcamcorder)"); + return FALSE; + +} + +int camcordertest_set_attr_xypair(cam_xypair_t pair) +{ + char * err_attr_name = NULL; + int err; + + if (hcamcorder) + { + if (hcamcorder->camcorder) + { + debug_msg_t("camcordertest_set_attr_xypair((%s, %s), (%d, %d))", pair.attr_subcat_x, pair.attr_subcat_y, pair.x, pair.y); + + err = mm_camcorder_set_attributes(hcamcorder->camcorder, &err_attr_name, + pair.attr_subcat_x, pair.x, + pair.attr_subcat_y, pair.y, + NULL); + if (err < 0) + { + err_msg_t("camcordertest_set_attr_xypair : Error(%s:%x)!!", err_attr_name, err); + SAFE_FREE (err_attr_name); + return FALSE; + } + + //success + return TRUE; + } + + debug_msg_t("camcordertest_set_attr_xypair(!hcamcorder->camcorde)"); + } + + debug_msg_t("camcordertest_set_attr_xypair(!hcamcorder)"); + return FALSE; +} + +int camcordertest_get_attr_valid_intarray(char * attr_name, int ** array, int *count) +{ + MMCamAttrsInfo info; + int err; + + if (hcamcorder) + { + if (hcamcorder->camcorder) + { + debug_msg_t("camcordertest_get_attr_valid_intarray((%s),(%p, %p))", attr_name, array, count); + + err = mm_camcorder_get_attribute_info(hcamcorder->camcorder, attr_name, &info); + + if (err < 0) + { + err_msg_t("camcordertest_get_attr_valid_intarray : Error(%x)!!", err); + return FALSE; + } + else + { + if (info.type == MM_CAM_ATTRS_TYPE_INT) + if (info.validity_type == MM_CAM_ATTRS_VALID_TYPE_INT_ARRAY) + { + *array = info.int_array.array; + *count = info.int_array.count; + return TRUE; + } + + err_msg_t("camcordertest_get_attr_valid_intarray : Type mismatched!!"); + return FALSE; + } + //success + } + + debug_msg_t("camcordertest_get_attr_valid_intarray(!hcamcorder->camcorde)"); + } + + debug_msg_t("camcordertest_get_attr_valid_intarray(!hcamcorder)"); + return FALSE; +} + +int camcordertest_get_attr_valid_intrange(char * attr_name, int *min, int *max) +{ + MMCamAttrsInfo info; + int err; + + if (hcamcorder) + { + if (hcamcorder->camcorder) + { + debug_msg_t("camcordertest_get_attr_valid_intarray((%s),(%p, %p))", attr_name, min, max); + + err = mm_camcorder_get_attribute_info(hcamcorder->camcorder, attr_name, &info); + + if (err < 0) + { + err_msg_t("camcordertest_get_attr_valid_intarray : Error(%x)!!", err); + return FALSE; + } + else + { + if (info.type == MM_CAM_ATTRS_TYPE_INT) + if (info.validity_type == MM_CAM_ATTRS_VALID_TYPE_INT_RANGE) + { + *min = info.int_range.min; + *max = info.int_range.max; + return TRUE; + } + + err_msg_t("camcordertest_get_attr_valid_intarray : Type mismatched!!"); + return FALSE; + } + //success + + } + + debug_msg_t("camcordertest_get_attr_valid_intarray(!hcamcorder->camcorde)"); + } + + debug_msg_t("camcordertest_get_attr_valid_intarray(!hcamcorder)"); + return FALSE; +} + + +void get_me_out() +{ + mm_camcorder_capture_stop(hcamcorder->camcorder); +} + +static void print_menu() +{ + switch(hcamcorder->menu_state) + { + case MENU_STATE_MAIN: + if (hcamcorder->mode == MODE_IMAGE) + { + g_print("\n\t=======================================\n"); + if ( cam_info.videodev_type == MM_VIDEO_DEVICE_CAMERA1 ) + g_print("\t Image Capture (Front camera)\n"); + else if( cam_info.videodev_type == MM_VIDEO_DEVICE_CAMERA0 ) + g_print("\t Image Capture (Rear camera)\n"); + g_print("\t=======================================\n"); + g_print("\t '1' Take a photo\n"); + g_print("\t '2' Setting\n"); + g_print("\t '3' Print FPS\n"); + g_print("\t 'b' back\n"); + g_print("\t=======================================\n"); + } + else if (hcamcorder->mode == MODE_VIDEO) + { + g_print("\n\t=======================================\n"); + if ( cam_info.videodev_type == MM_VIDEO_DEVICE_CAMERA1 ) + g_print("\t Video Recording (Front camera)\n"); + else if( cam_info.videodev_type == MM_VIDEO_DEVICE_CAMERA0 ) + g_print("\t Video Recording (Rear camera)\n"); + g_print("\t=======================================\n"); + + if(mmcamcorder_print_state <= MM_CAMCORDER_STATE_PREPARE) { + g_print("\t '1' Start Recording\n"); + g_print("\t '2' Setting\n"); + g_print("\t '3' Print FPS\n"); + g_print("\t 'b' back\n"); + } + else if(mmcamcorder_print_state == MM_CAMCORDER_STATE_RECORDING) { + g_print("\t 'p' Pause Recording\n"); + g_print("\t 'c' Cancel\n"); + g_print("\t 's' Save\n"); + } + else if(mmcamcorder_print_state == MM_CAMCORDER_STATE_PAUSED) { + g_print("\t 'r' Resume Recording\n"); + g_print("\t 'c' Cancel\n"); + g_print("\t 's' Save\n"); + } + g_print("\t=======================================\n"); + } + else if (hcamcorder->mode == MODE_AUDIO) + { + g_print("\n\t=======================================\n"); + g_print("\t Audio Recording\n"); + g_print("\t=======================================\n"); + if(mmcamcorder_print_state <= MM_CAMCORDER_STATE_PREPARE) { + g_print("\t '1' Start Recording\n"); + g_print("\t 'b' back\n"); + } + else if(mmcamcorder_print_state == MM_CAMCORDER_STATE_RECORDING) { + g_print("\t 'p' Pause Recording\n"); + g_print("\t 'c' Cancel\n"); + g_print("\t 's' Save\n"); + } + else if(mmcamcorder_print_state == MM_CAMCORDER_STATE_PAUSED) { + g_print("\t 'r' Resume Recording\n"); + g_print("\t 'c' Cancel\n"); + g_print("\t 's' Save\n"); + } + g_print("\t=======================================\n"); + } + break; + + case MENU_STATE_SETTING: + if (hcamcorder->mode == MODE_IMAGE) { + g_print("\n\t=======================================\n"); + g_print("\t Image Capture > Setting\n"); + g_print("\t=======================================\n"); + g_print("\t >>>>>>>>>>>>>>>>>>>>>>>>>>>> [Camera] \n"); + g_print("\t '1' Capture resolution \n"); + g_print("\t '2' Digital zoom level \n"); + g_print("\t '3' Optical zoom level \n"); + g_print("\t '4' AF mode \n"); + g_print("\t '5' AF scan range \n"); + g_print("\t '6' Exposure mode \n"); + g_print("\t '7' Exposure value \n"); + g_print("\t '8' F number \n"); + g_print("\t '9' Shutter speed \n"); + g_print("\t 'i' ISO \n"); + g_print("\t 'r' Rotate camera input \n"); + g_print("\t 'j' Jpeg quality \n"); + g_print("\t 'p' Picture format \n"); + g_print("\t >>>>>>>>>>>>>>>>>>>> [Display/Filter]\n"); + g_print("\t 'v' Visible \n"); + g_print("\t 'o' Output mode \n"); + g_print("\t 'y' Rotate display \n"); + g_print("\t 'g' Brightness \n"); + g_print("\t 'c' Contrast \n"); + g_print("\t 's' Saturation \n"); + g_print("\t 'h' Hue \n"); + g_print("\t 'a' Sharpness \n"); + g_print("\t 'w' White balance \n"); + g_print("\t 't' Color tone \n"); + g_print("\t 'd' WDR \n"); + g_print("\t 'e' EV program mode \n"); + g_print("\t >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> [etc.]\n"); + g_print("\t 'z' Strobe (Flash) \n"); + g_print("\t 'x' Capture mode (Still/Multishot)\n"); + g_print("\t 'f' Face detection \n"); + g_print("\t 'k' Anti-handshake \n"); + g_print("\t 'u' Touch AF area \n"); + g_print("\t 'm' Stream callback function \n"); + g_print("\t 'b' back\n"); + g_print("\t=======================================\n"); + + } else if (hcamcorder->mode == MODE_VIDEO) { + g_print("\n\t=======================================\n"); + g_print("\t Video Recording > Setting\n"); + g_print("\t=======================================\n"); + g_print("\t >>>>>>>>>>>>>>>>>>>>>>>>>>>> [Camera] \n"); + g_print("\t '1' Recording resolution \n"); + g_print("\t '2' Digital zoom level \n"); + g_print("\t '3' Optical zoom level \n"); + g_print("\t '4' AF mode \n"); + g_print("\t '5' AF scan range \n"); + g_print("\t '6' Exposure mode \n"); + g_print("\t '7' Exposure value \n"); + g_print("\t '8' F number \n"); + g_print("\t 'i' ISO \n"); + g_print("\t 'r' Rotate camera input \n"); + g_print("\t 'p' FPS \n"); + g_print("\t >>>>>>>>>>>>>>>>>>>> [Display/Filter]\n"); + g_print("\t 'v' Visible \n"); + g_print("\t 'o' Output mode \n"); + g_print("\t 'y' Rotate display \n"); + g_print("\t 'g' Brightness \n"); + g_print("\t 'c' Contrast \n"); + g_print("\t 's' Saturation \n"); + g_print("\t 'h' Hue \n"); + g_print("\t 'a' Sharpness \n"); + g_print("\t 'w' White balance \n"); + g_print("\t 't' Color tone \n"); + g_print("\t 'd' WDR \n"); + g_print("\t >>>>>>>>>>>>>>>>>>>>>>>>>>>>>> [etc.]\n"); + g_print("\t 'x' High speed recording\n"); + g_print("\t 'u' Mute \n"); + g_print("\t 'z' Strobe (Flash) \n"); + g_print("\t 'k' Anti-handshake \n"); + g_print("\t 'e' Camcorder-rotation setting \n"); + g_print("\t 'm' Stream callback function \n"); + g_print("\t 'b' back\n"); + g_print("\t=======================================\n"); + } + break; + + default: + warn_msg_t("unknow menu state !!\n"); + break; + } + + return; +} + +static void main_menu(gchar buf) +{ + int err = 0; + int current_fps = 0; + int average_fps = 0; + char *err_attr_name = NULL; + int width = 0, height = 0; + + if (hcamcorder->mode == MODE_IMAGE) { + switch(buf) { + case '1' : //Capture + if(hcamcorder->isMultishot) { + err = mm_camcorder_set_attributes(hcamcorder->camcorder, &err_attr_name, + MMCAM_CAPTURE_WIDTH, 640, + MMCAM_CAPTURE_HEIGHT, 480, + MMCAM_CAPTURE_COUNT, multishot_num, + MMCAM_CAPTURE_INTERVAL, IMAGE_CAPTURE_COUNT_INTERVAL, + NULL); + if (err < 0) { + err_msg_t("Attribute setting fail : (%s:%x)", err_attr_name, err); + SAFE_FREE (err_attr_name); + } + } else { + err = mm_camcorder_set_attributes(hcamcorder->camcorder, &err_attr_name, + MMCAM_CAPTURE_COUNT, IMAGE_CAPTURE_COUNT_STILL, + NULL); + if (err < 0) { + err_msg_t("Attribute setting fail : (%s:%x)", err_attr_name, err); + SAFE_FREE (err_attr_name); + } + } + + g_idle_add_full(G_PRIORITY_DEFAULT_IDLE, (GSourceFunc)test_idle_capture_start, NULL, NULL); + break; + + case '2' : // Setting + hcamcorder->menu_state = MENU_STATE_SETTING; + break; + + case '3' : // Print frame rate + current_fps = _mmcamcorder_video_current_framerate(hcamcorder->camcorder); + average_fps = _mmcamcorder_video_average_framerate(hcamcorder->camcorder); + g_print("\tVideo Frame Rate[Current : %d.0 fps, Average : %d.0 fps]\n", current_fps, average_fps); + break; + + case 'b' : // back + hcamcorder->menu_state = MENU_STATE_MAIN; + mode_change(); + break; + + default: + g_print("\t Invalid input \n"); + break; + } + } + else if (hcamcorder->mode == MODE_VIDEO) + { + if (mmcamcorder_state == MM_CAMCORDER_STATE_PREPARE) { + switch(buf) { + case '1' : // Start Recording + g_print("*Recording start!\n"); + video_stream_cb_cnt = 0; + audio_stream_cb_cnt = 0; + + mm_camcorder_get_attributes( hcamcorder->camcorder, NULL, + MMCAM_CAMERA_WIDTH, &width, + MMCAM_CAMERA_HEIGHT, &height, + NULL ); + + mm_camcorder_set_attributes( hcamcorder->camcorder, NULL, + MMCAM_CAMERA_AF_TOUCH_X, width>>1, + MMCAM_CAMERA_AF_TOUCH_Y, height>>1, + MMCAM_CAMERA_AF_TOUCH_WIDTH, 30, + MMCAM_CAMERA_AF_TOUCH_HEIGHT, 30, + NULL ); + + mm_camcorder_start_focusing(hcamcorder->camcorder); + + g_timer_reset(timer); + err = mm_camcorder_record(hcamcorder->camcorder); + + if (err < 0) { + warn_msg_t("Rec start mm_camcorder_record = %x", err); + } + + mmcamcorder_print_state = MM_CAMCORDER_STATE_RECORDING; + break; + + case '2' : // Setting + hcamcorder->menu_state = MENU_STATE_SETTING; + break; + + case '3' : + current_fps = _mmcamcorder_video_current_framerate(hcamcorder->camcorder); + average_fps = _mmcamcorder_video_average_framerate(hcamcorder->camcorder); + g_print("\tVideo Frame Rate[Current : %d.0 fps, Average : %d.0 fps]\n", current_fps, average_fps); + break; + + case 'b' : // back + hcamcorder->menu_state = MENU_STATE_MAIN; + mode_change(); + break; + } + } else if (mmcamcorder_state == MM_CAMCORDER_STATE_RECORDING || mmcamcorder_state == MM_CAMCORDER_STATE_PAUSED) { + switch(buf) { + if (mmcamcorder_state == MM_CAMCORDER_STATE_RECORDING) { + case 'p' : // Pause Recording + g_print("*Pause!\n"); + err = mm_camcorder_pause(hcamcorder->camcorder); + + if (err < 0) { + warn_msg_t("Rec pause mm_camcorder_pause = %x", err); + } + mmcamcorder_print_state = MM_CAMCORDER_STATE_PAUSED; + break; + + } else { + case 'r' : // Resume Recording + g_print("*Resume!\n"); + err = mm_camcorder_record(hcamcorder->camcorder); + if (err < 0) { + warn_msg_t("Rec start mm_camcorder_record = %x", err); + } + mmcamcorder_print_state = MM_CAMCORDER_STATE_RECORDING; + break; + } + + case 'c' : // Cancel + g_print("*Cancel Recording !\n"); + + err = mm_camcorder_cancel(hcamcorder->camcorder); + + if (err < 0) { + warn_msg_t("Cancel recording mm_camcorder_cancel = %x", err); + } + mmcamcorder_print_state = MM_CAMCORDER_STATE_PREPARE; + break; + + case 's' : // Save + g_print("*Save Recording!\n"); + g_timer_reset(timer); + + err = mm_camcorder_commit(hcamcorder->camcorder); + + if (err < 0) { + warn_msg_t("Save recording mm_camcorder_commit = %x", err); + } + mmcamcorder_print_state = MM_CAMCORDER_STATE_PREPARE; + break; + + default : + g_print("\t Invalid input \n"); + break; + } //switch + } else { + err_msg_t("Wrong camcorder state, check status!!"); + } + } + else if (hcamcorder->mode == MODE_AUDIO) + { + if (mmcamcorder_state == MM_CAMCORDER_STATE_PREPARE) { + switch(buf) { + case '1' : // Start Recording + g_print("*Recording start!\n"); + g_timer_reset(timer); + err = mm_camcorder_record(hcamcorder->camcorder); + + if (err < 0) { + warn_msg_t("Rec start mm_camcorder_record = %x", err); + } + mmcamcorder_print_state = MM_CAMCORDER_STATE_RECORDING; + break; + + case 'b' : // back + hcamcorder->menu_state = MENU_STATE_MAIN; + mode_change(); + break; + + default : + g_print("\t Invalid input \n"); + break; + } + } else if (mmcamcorder_state == MM_CAMCORDER_STATE_RECORDING || mmcamcorder_state == MM_CAMCORDER_STATE_PAUSED) { + switch(buf) { + if (mmcamcorder_state == MM_CAMCORDER_STATE_RECORDING) { + case 'p' : // Pause Recording + g_print("*Pause!\n"); + err = mm_camcorder_pause(hcamcorder->camcorder); + + if (err < 0) { + warn_msg_t("Rec pause mm_camcorder_pause = %x", err); + } + mmcamcorder_print_state = MM_CAMCORDER_STATE_PAUSED; + break; + } else { + case 'r' : // Resume Recording + g_print("*Resume!\n"); + err = mm_camcorder_record(hcamcorder->camcorder); + if (err < 0) { + warn_msg_t("Rec start mm_camcorder_record = %x", err); + } + mmcamcorder_print_state = MM_CAMCORDER_STATE_RECORDING; + break; + } + + case 'c' : // Cancel + g_print("*Cancel Recording !\n"); + err = mm_camcorder_cancel(hcamcorder->camcorder); + + if (err < 0) { + warn_msg_t("Cancel recording mm_camcorder_cancel = %x", err); + } + mmcamcorder_print_state = MM_CAMCORDER_STATE_PREPARE; + break; + + case 's' : // Save + g_print("*Save Recording!\n"); + g_timer_reset(timer); + err = mm_camcorder_commit(hcamcorder->camcorder); + + if (err < 0) { + warn_msg_t("Save recording mm_camcorder_commit = %x", err); + } + mmcamcorder_print_state = MM_CAMCORDER_STATE_PREPARE; + break; + + default : + g_print("\t Invalid input \n"); + break; + } + } else { + err_msg_t("Wrong camcorder state, check status!!"); + } + } + else { + g_print("\t Invalid mode, back to upper menu \n"); + hcamcorder->menu_state = MENU_STATE_MAIN; + mode_change(); + } +} + + +static void setting_menu(gchar buf) +{ + gboolean bret = FALSE; + int index=0; + int min = 0; + int max = 0; + int width_count = 0; + int heigh_count = 0; + int i=0; + int count = 0; + int value = 0; + int* array = NULL; + int *width_array = NULL; + int *heigh_array = NULL; + char *err_attr_name = NULL; + cam_xypair_t input_pair; + int err = MM_ERROR_NONE; + int x = 0, y = 0, width = 0, height = 0; + double new_volume = 0.0; + gint error_num=0; + + if (hcamcorder->mode == MODE_IMAGE) + { + switch(buf) { + /* Camera setting */ + case '1' : // Setting > Capture Resolution setting + g_print("*Select the resolution!\n"); + camcordertest_get_attr_valid_intarray("capture-width", &width_array, &width_count); + camcordertest_get_attr_valid_intarray("capture-height", &heigh_array, &heigh_count); + + if(width_count != heigh_count) { + err_msg_t("System has wrong information!!"); + } else if (width_count == 0) { + g_print("Not supported!!\n"); + } else { + g_print("\n Select resolution \n"); + flush_stdin(); + + for ( i = 0; i < width_count; i++) { + g_print("\t %d. %d*%d\n", i+1, width_array[i], heigh_array[i]); + } + scanf("%d",&index); + + if( index > 0 && index <= width_count ) { + //Set capture size first + input_pair.attr_subcat_x = "capture-width"; + input_pair.attr_subcat_y = "capture-height"; + input_pair.x = width_array[index-1]; + input_pair.y = heigh_array[index-1]; + bret = camcordertest_set_attr_xypair(input_pair); + } + } + break; + + case '2' : // Setting > Digital zoom level + g_print("*Digital zoom level !\n"); + camcordertest_get_attr_valid_intrange("camera-digital-zoom", &min, &max); + + if(min >= max) { + g_print("Not supported !! \n"); + } else { + flush_stdin(); + g_print("\n Select Digital zoom level (%d ~ %d)\n", min, max); + scanf("%d",&index); + bret = camcordertest_set_attr_int("camera-digital-zoom", index); + } + break; + + case '3' : // Setting > Optical zoom level + g_print("*Optical zoom level !\n"); + camcordertest_get_attr_valid_intrange("camera-optical-zoom", &min, &max); + + if(min >= max) { + g_print("Not supported !! \n"); + } else { + flush_stdin(); + g_print("\n Select Optical zoom level (%d ~ %d)\n", min, max); + scanf("%d",&index); + bret = camcordertest_set_attr_int("camera-optical-zoom", index); + } + break; + + case '4' : // Setting > AF mode + g_print("*Focus mode !\n"); + camcordertest_get_attr_valid_intarray("camera-focus-mode", &array, &count); + + if(count <= 0) { + g_print("Not supported !! \n"); + } else { + g_print("\n Select Focus mode \n"); + flush_stdin(); + for ( i = 0; i < count; i++) { + g_print("\t %d. %s\n", array[i], focus_mode[array[i]]); + } + scanf("%d",&index); + bret = camcordertest_set_attr_int("camera-focus-mode", index); + } + break; + + case '5' : // Setting > AF scan range + g_print("*AF scan range !\n"); + camcordertest_get_attr_valid_intarray("camera-af-scan-range", &array, &count); + + if(count <= 0) { + g_print("Not supported !! \n"); + } else { + g_print("\n Select AF scan range \n"); + flush_stdin(); + for ( i = 0; i < count; i++) { + g_print("\t %d. %s\n", array[i], af_scan[array[i]]); + } + scanf("%d",&index); + bret = camcordertest_set_attr_int("camera-af-scan-range", index); + + if( bret ) { + mm_camcorder_start_focusing(hcamcorder->camcorder); + } + } + break; + + case '6' : // Setting > Exposure mode + g_print("* Exposure mode!\n"); + camcordertest_get_attr_valid_intarray("camera-exposure-mode", &array, &count); + + if(count <= 0) { + g_print("Not supported !! \n"); + } else { + g_print("\n Select Exposure mode \n"); + flush_stdin(); + for ( i = 0; i < count; i++) { + g_print("\t %d. %s\n", array[i], exposure_mode[array[i]]); + } + scanf("%d",&index); + bret = camcordertest_set_attr_int("camera-exposure-mode", index); + } + break; + + case '7' : // Setting > Exposure value + g_print("*Exposure value !\n"); + camcordertest_get_attr_valid_intrange("camera-exposure-value", &min, &max); + + if(min >= max) { + g_print("Not supported !! \n"); + } else { + flush_stdin(); + g_print("\n Select Exposure value(%d ~ %d)\n", min, max); + scanf("%d",&index); + bret = camcordertest_set_attr_int("camera-exposure-value", index); + } + break; + + case '8' : // Setting > F number + g_print("Not supported !! \n"); + break; + + case '9' : // Setting > Shutter speed + g_print("*Shutter speed !\n"); + camcordertest_get_attr_valid_intarray("camera-shutter-speed", &array, &count); + + if(count <= 0) { + g_print("Not supported !! \n"); + } else { + g_print("\n Select Shutter speed \n"); + flush_stdin(); + for ( i = 0; i < count; i++) { + g_print("\t %d. %d \n", i+1, array[i]); + } + scanf("%d",&index); + + if( index > 0 && index <= count ) { + bret = camcordertest_set_attr_int("camera-shutter-speed", array[index-1]); + } + } + break; + + case 'i' : // Setting > ISO + g_print("*ISO !\n"); + camcordertest_get_attr_valid_intarray("camera-iso", &array, &count); + + if(count <= 0) { + g_print("Not supported !! \n"); + } else { + g_print("\n Select ISO \n"); + flush_stdin(); + for ( i = 0; i < count; i++) { + g_print("\t %d. %s\n", array[i], iso_name[array[i]]); + } + scanf("%d",&index); + bret = camcordertest_set_attr_int("camera-iso", index); + } + break; + + case 'r' : // Setting > Rotate camera input when recording + g_print("*Rotate camera input when recording !\n"); + camcordertest_get_attr_valid_intarray(MMCAM_CAMERA_ROTATION, &array, &count); + + if(count <= 0) { + g_print("Not supported !! \n"); + } else { + g_print("\n Select Rotate angle of camera \n"); + flush_stdin(); + for ( i = 0; i < count; i++) { + g_print("\t %d. %s\n", array[i], camera_rotation[array[i]]); + } + scanf("%d",&index); + bret = camcordertest_set_attr_int(MMCAM_CAMERA_ROTATION, index); + CHECK_MM_ERROR(mm_camcorder_stop(hcamcorder->camcorder)); + CHECK_MM_ERROR(mm_camcorder_unrealize(hcamcorder->camcorder)); + CHECK_MM_ERROR(mm_camcorder_realize(hcamcorder->camcorder)); + CHECK_MM_ERROR(mm_camcorder_start(hcamcorder->camcorder)); + } + break; + + case 'j' : // Setting > Jpeg quality + g_print("*Jpeg quality !\n"); + camcordertest_get_attr_valid_intrange("image-encoder-quality", &min, &max); + + if(min >= max) { + g_print("Not supported !! \n"); + } else { + flush_stdin(); + g_print("\n Select Jpeg quality (%d ~ %d)\n", min, max); + scanf("%d",&index); + bret = camcordertest_set_attr_int("image-encoder-quality", index); + } + break; + + case 'p' : // Setting > Picture format + g_print("* Picture format!\n"); + camcordertest_get_attr_valid_intarray("camera-format", &array, &count); + + if(count <= 0) { + g_print("Not supported !! \n"); + } else { + g_print("\n Select Picture format \n"); + flush_stdin(); + for ( i = 0; i < count; i++) { + g_print("\t %d. %s\n", array[i], image_fmt[array[i]]); + } + scanf("%d",&index); + bret = camcordertest_set_attr_int("camera-format", index); + CHECK_MM_ERROR(mm_camcorder_stop(hcamcorder->camcorder)); + CHECK_MM_ERROR(mm_camcorder_unrealize(hcamcorder->camcorder)); + CHECK_MM_ERROR(mm_camcorder_realize(hcamcorder->camcorder)); + CHECK_MM_ERROR(mm_camcorder_start(hcamcorder->camcorder)); + } + break; + + /* Display / Filter setting */ + case 'v' : // Display visible + g_print("* Display visible setting !\n"); + camcordertest_get_attr_valid_intarray( "display-visible", &array, &count ); + + if( count < 1 ) { + g_print("Not supported !! \n"); + } else { + g_print("\n Select Display visible \n"); + flush_stdin(); + for ( i = 0; i < count; i++) { + g_print("\t %d. %s\n", array[i], visible_mode[array[i]]); + } + scanf("%d",&value); + bret = camcordertest_set_attr_int( "display-visible", value ); + } + break; + + case 'o' : // Setting > Output mode + g_print("* Output mode!\n"); + camcordertest_get_attr_valid_intrange("display-geometry-method", &min, &max); + + if( min > max ) { + g_print("Not supported !! \n"); + } else { + flush_stdin(); + g_print("\n Select Output mode(%d ~ %d)\n", min, max); + for( i = min ; i <= max ; i++ ) { + g_print( "%d. %s\n", i, output_mode[i] ); + } + scanf("%d",&index); + bret = camcordertest_set_attr_int("display-geometry-method", index); + } + break; + + case 'y' : // Setting > Rotate Display + camcordertest_get_attr_valid_intarray( MMCAM_DISPLAY_ROTATION, &array, &count ); + + if( count <= 0 || count > 256 ) { + g_print("Not supported !! \n"); + } else { + flush_stdin(); + g_print("\n Select Rotation mode\n"); + for ( i = 0; i < count; i++) { + g_print("\t %d. %s\n", array[i], rotate_mode[array[i]]); + } + scanf("%d",&index); + bret = camcordertest_set_attr_int( MMCAM_DISPLAY_ROTATION, index ); + } + break; + + case 'g' : // Setting > Brightness + g_print("*Brightness !\n"); + camcordertest_get_attr_valid_intrange("filter-brightness", &min, &max); + + if(min >= max) { + g_print("Not supported !! \n"); + } else { + flush_stdin(); + g_print("\n Select brightness (%d ~ %d)\n", min, max); + scanf("%d",&index); + bret = camcordertest_set_attr_int("filter-brightness", index); + } + break; + + case 'c' : // Setting > Contrast + g_print("*Contrast !\n"); + camcordertest_get_attr_valid_intrange("filter-contrast", &min, &max); + + if(min >= max) { + g_print("Not supported !! \n"); + } else { + flush_stdin(); + g_print("\n Select Contrast (%d ~ %d)\n", min, max); + scanf("%d",&index); + bret = camcordertest_set_attr_int("filter-contrast", index); + } + break; + + case 's' : // Setting > Saturation + g_print("*Saturation !\n"); + camcordertest_get_attr_valid_intrange("filter-saturation", &min, &max); + + if(min >= max) { + g_print("Not supported !! \n"); + } else { + flush_stdin(); + g_print("\n Select Saturation (%d ~ %d)\n", min, max); + scanf("%d",&index); + bret = camcordertest_set_attr_int("filter-saturation", index); + } + break; + + case 'h' : // Setting > Hue + g_print("*Hue !\n"); + camcordertest_get_attr_valid_intrange("filter-hue", &min, &max); + + if(min >= max) { + g_print("Not supported !! \n"); + } else { + flush_stdin(); + g_print("\n Select Hue (%d ~ %d)\n", min, max); + scanf("%d",&index); + bret = camcordertest_set_attr_int("filter-hue", index); + } + break; + + case 'a' : // Setting > Sharpness + g_print("*Sharpness !\n"); + camcordertest_get_attr_valid_intrange("filter-sharpness", &min, &max); + + if(min >= max) { + g_print("Not supported !! \n"); + } else { + flush_stdin(); + g_print("\n Select Sharpness (%d ~ %d)\n", min, max); + scanf("%d",&index); + bret = camcordertest_set_attr_int("filter-sharpness", index); + } + break; + + case 'w' : // Setting > White balance + g_print("*White balance !\n"); + camcordertest_get_attr_valid_intarray("filter-wb", &array, &count); + + if(count <= 0) { + g_print("Not supported !! \n"); + } else { + flush_stdin(); + g_print("\n Select White balance \n"); + for ( i = 0; i < count; i++) { + g_print("\t %d. %s\n", array[i], wb[array[i]]); + } + scanf("%d",&index); + bret = camcordertest_set_attr_int("filter-wb", index); + } + break; + + case 't' : // Setting > Color tone + g_print("*Color tone !\n"); + camcordertest_get_attr_valid_intarray("filter-color-tone", &array, &count); + + if(count <= 0) { + g_print("Not supported !! \n"); + } else { + g_print("\n Select Color tone \n"); + flush_stdin(); + for ( i = 0; i < count; i++) { + g_print("\t %d. %s\n", array[i], ct[array[i]]); + } + scanf("%d",&index); + bret = camcordertest_set_attr_int("filter-color-tone", index); + } + break; + + case 'd' : // Setting > WDR + g_print("*WDR !\n"); + camcordertest_get_attr_valid_intarray("camera-wdr", &array, &count); + + if(count <= 0) { + g_print("Not supported !! \n"); + } + else { + g_print("\n Select WDR Mode \n"); + flush_stdin(); + for ( i = 0; i < count; i++) { + g_print("\t %d. %s\n", array[i], wdr_mode[array[i]]); + } + scanf("%d",&index); + bret = camcordertest_set_attr_int("camera-wdr", index); + } + break; + + case 'e' : // Setting > EV program mode + g_print("* EV program mode!\n"); + camcordertest_get_attr_valid_intarray("filter-scene-mode", &array, &count); + + if(count <= 0) { + g_print("Not supported !! \n"); + } else { + g_print("\n Select EV program mode \n"); + flush_stdin(); + for ( i = 0; i < count; i++) { + g_print("\t %d. %s\n", array[i], program_mode[array[i]]); + } + scanf("%d",&index); + bret = camcordertest_set_attr_int("filter-scene-mode", index); + } + break; + + /* ext. setting */ + case 'z' : // Setting > Strobe setting + g_print("*Strobe Mode\n"); + camcordertest_get_attr_valid_intarray("strobe-mode", &array, &count); + if(count <= 0) { + g_print("Not supported !! \n"); + } else { + g_print("\n Select Strobe Mode \n"); + flush_stdin(); + for ( i = 0; i < count; i++) { + g_print("\t %d. %s\n", array[i], strobe_mode[array[i]]); + } + scanf("%d",&index); + bret = camcordertest_set_attr_int("strobe-mode", index); + } + break; + + case 'x' : // Setting > Capture mode ,Muitishot? + g_print("*Select Capture mode!\n"); + flush_stdin(); + g_print(" \n\t1. Stillshot mode\n\t2. Multishot mode \n"); + scanf("%d",&index); + + if(index == 1) { + g_print("stillshot mode selected and capture callback is set!!!!\n"); + hcamcorder->isMultishot = FALSE; + } else if (index == 2) { + g_print("Multilshot mode selected!!\n"); + + index = 0; + min = 0; + max = 0; + + camcordertest_get_attr_valid_intrange("capture-count", &min, &max); + if(min >= max) { + g_print("Not supported !! \n"); + } else { + flush_stdin(); + //g_print("\n Check Point!!! [Change resolution to 800x480]\n"); + g_print("Select mulitshot number (%d ~ %d)\n", min, max); + scanf("%d",&index); + if( index >= min && index <= max ) { + multishot_num = index; + hcamcorder->isMultishot = TRUE; + } else { + g_print("Wrong input value, Multishot setting failed!!\n"); + } + } + } else { + g_print("Wrong input, select again!!\n"); + } + break; + + case 'f' : // Setting > Face detection setting + //hcamcorder->menu_state = MENU_STATE_SETTING_DETECTION; + g_print("* Face detect mode !\n"); + + camcordertest_get_attr_valid_intarray("detect-mode", &array, &count); + if(count <= 0 || count > 256) { + g_print("Not supported !! \n"); + } else { + g_print("\n Face detect mode \n"); + flush_stdin(); + for ( i = 0; i < count; i++) { + g_print("\t %d. %s \n", array[i], detection_mode[array[i]]); + } + scanf("%d",&index); + + if( index >= 0 && index < count ) { + bret = camcordertest_set_attr_int("detect-mode", array[index]); + } else { + g_print("Wrong input value. Try again!!\n"); + bret = FALSE; + } + } + break; + + case 'k' : // Setting > Anti-handshake + g_print("*Anti-handshake !\n"); + camcordertest_get_attr_valid_intarray("camera-anti-handshake", &array, &count); + + if(count <= 0) { + g_print("Not supported !! \n"); + } else { + g_print("\n Select Anti-handshake mode \n"); + flush_stdin(); + for ( i = 0; i < count; i++) { + g_print("\t %d. %s\n", array[i], ahs_mode[array[i]]); + } + scanf("%d",&index); + bret = camcordertest_set_attr_int("camera-anti-handshake", index); + } + break; + + case 'u': // Touch AF area + g_print("* Touch AF area !\n"); + camcordertest_get_attr_valid_intrange("camera-af-touch-x", &min, &max); + if( max < min ) { + g_print( "Not Supported camera-af-touch-x !!\n" ); + break; + } + camcordertest_get_attr_valid_intrange("camera-af-touch-y", &min, &max); + if( max < min ) { + g_print( "Not Supported camera-af-touch-y !!\n" ); + break; + } + camcordertest_get_attr_valid_intrange("camera-af-touch-width", &min, &max); + if( max < min ) { + g_print( "Not Supported camera-af-touch-width !!\n" ); + break; + } + camcordertest_get_attr_valid_intrange("camera-af-touch-height", &min, &max); + if( max < min ) { + g_print( "Not Supported camera-af-touch-height!!\n" ); + break; + } + + flush_stdin(); + g_print( "\n Input x,y,width,height \n" ); + scanf( "%d,%d,%d,%d", &x, &y, &width, &height ); + err = mm_camcorder_set_attributes(hcamcorder->camcorder, &err_attr_name, + MMCAM_CAMERA_AF_TOUCH_X, x, + MMCAM_CAMERA_AF_TOUCH_Y, y, + MMCAM_CAMERA_AF_TOUCH_WIDTH, width, + MMCAM_CAMERA_AF_TOUCH_HEIGHT, height, + NULL); + + if( err != MM_ERROR_NONE ) { + g_print( "Failed to set touch AF area.(%x)(%s)\n", err, err_attr_name ); + free( err_attr_name ); + err_attr_name = NULL; + } else { + g_print( "Succeed to set touch AF area.\n" ); + } + break; + + case 'm' : // Setting > Stream callback function + g_print("Not supported !! \n"); + break; + + case 'b' : // back + hcamcorder->menu_state = MENU_STATE_MAIN; + break; + + default : + g_print("\t Invalid input \n"); + break; + } + } + else if(hcamcorder->mode == MODE_VIDEO) + { + switch(buf) + { + /* Camera setting */ + case '1' : // Setting > Recording Resolution + g_print("*Select resolution!\n"); + + camcordertest_get_attr_valid_intarray("camera-width", &width_array, &width_count); + camcordertest_get_attr_valid_intarray("camera-height", &heigh_array, &heigh_count); + + if(width_count != heigh_count) { + err_msg_t("System has wrong information!!"); + } else if(width_count == 0) { + g_print("Not supported !! \n"); + } else { + g_print("\n Select the resolution \n"); + flush_stdin(); + for ( i = 0; i < width_count; i++) { + g_print("\t %d. %d*%d\n", i+1, width_array[i], heigh_array[i]); + } + scanf("%d",&index); + + if( index > 0 && index <= width_count ) { + g_timer_reset(timer); + CHECK_MM_ERROR(mm_camcorder_stop(hcamcorder->camcorder)); + CHECK_MM_ERROR(mm_camcorder_unrealize(hcamcorder->camcorder)); + + //Set source size + input_pair.attr_subcat_x = "camera-width"; + input_pair.attr_subcat_y = "camera-height"; + input_pair.x = width_array[index-1]; + input_pair.y = heigh_array[index-1]; + + bret = camcordertest_set_attr_xypair(input_pair); + + CHECK_MM_ERROR(mm_camcorder_realize(hcamcorder->camcorder)); + CHECK_MM_ERROR(mm_camcorder_start(hcamcorder->camcorder)); + time_msg_t("Resolution change : %12.6lf s", g_timer_elapsed(timer, NULL)); + } else { + warn_msg_t( "Out of index" ); + } + } + break; + + case '2' : // Setting > Digital zoom level + g_print("*Digital zoom level !\n"); + camcordertest_get_attr_valid_intrange("camera-digital-zoom", &min, &max); + + if(min >= max) { + g_print("Not supported !! \n"); + } else { + flush_stdin(); + g_print("\n Select Digital zoom level (%d ~ %d)\n", min, max); + scanf("%d",&index); + bret = camcordertest_set_attr_int("camera-digital-zoom", index); + } + break; + + case '3' : // Setting > Optical zoom level + g_print("*Optical zoom level !\n"); + camcordertest_get_attr_valid_intrange("camera-optical-zoom", &min, &max); + + if(min >= max) { + g_print("Not supported !! \n"); + } else { + flush_stdin(); + g_print("\n Select Optical zoom level (%d ~ %d)\n", min, max); + scanf("%d",&index); + bret = camcordertest_set_attr_int("camera-optical-zoom", index); + } + break; + + case '4' : // Setting > AF mode + g_print("*Focus mode !\n"); + camcordertest_get_attr_valid_intarray("camera-focus-mode", &array, &count); + + if(count <= 0) { + g_print("Not supported !! \n"); + } else { + g_print("\n Select Focus mode \n"); + flush_stdin(); + for ( i = 0; i < count; i++) { + g_print("\t %d. %s\n", array[i], focus_mode[array[i]]); + } + scanf("%d",&index); + bret = camcordertest_set_attr_int("camera-focus-mode", index); + } + break; + + case '5' : // Setting > AF scan range + g_print("*AF scan range !\n"); + camcordertest_get_attr_valid_intarray("camera-af-scan-range", &array, &count); + + if(count <= 0) { + g_print("Not supported !! \n"); + } else { + g_print("\n Select AF scan range \n"); + flush_stdin(); + for ( i = 0; i < count; i++) { + g_print("\t %d. %s\n", array[i], af_scan[array[i]]); + } + scanf("%d",&index); + bret = camcordertest_set_attr_int("camera-af-scan-range", index); + + if( bret ) { + mm_camcorder_start_focusing(hcamcorder->camcorder); + } + } + break; + + case '6' : // Setting > Exposure mode + g_print("* Exposure mode!\n"); + camcordertest_get_attr_valid_intarray("camera-exposure-mode", &array, &count); + + if(count <= 0) { + g_print("Not supported !! \n"); + } else { + g_print("\n Select Exposure mode \n"); + flush_stdin(); + for ( i = 0; i < count; i++) { + g_print("\t %d. %s\n", array[i], exposure_mode[array[i]]); + } + scanf("%d",&index); + bret = camcordertest_set_attr_int("camera-exposure-mode", index); + } + break; + + case '7' : // Setting > Exposure value + g_print("*Exposure value !\n"); + camcordertest_get_attr_valid_intrange("camera-exposure-value", &min, &max); + + if(min >= max) { + g_print("Not supported !! \n"); + } else { + flush_stdin(); + g_print("\n Select Exposure value(%d ~ %d)\n", min, max); + scanf("%d",&index); + bret = camcordertest_set_attr_int("camera-exposure-value", index); + } + break; + + case '8' : // Setting > F number + g_print("Not supported !! \n"); + break; + + case 'i' : // Setting > ISO + g_print("*ISO !\n"); + camcordertest_get_attr_valid_intarray("camera-iso", &array, &count); + + if(count <= 0) { + g_print("Not supported !! \n"); + } else { + g_print("\n Select ISO \n"); + flush_stdin(); + for ( i = 0; i < count; i++) { + g_print("\t %d. %s\n", array[i], iso_name[array[i]]); + } + scanf("%d",&index); + bret = camcordertest_set_attr_int("camera-iso", index); + } + break; + + case 'r' : // Setting > Rotate camera input when recording + g_print("*Rotate camera input !\n"); + camcordertest_get_attr_valid_intarray(MMCAM_CAMERA_ROTATION, &array, &count); + + if(count <= 0) { + g_print("Not supported !! \n"); + } else { + g_print("\n Select Rotate angle of camera (Do Not use it for recording test !!) \n"); + flush_stdin(); + for ( i = 0; i < count; i++) { + g_print("\t %d. %s\n", array[i], camera_rotation[array[i]]); + } + scanf("%d",&index); + + CHECK_MM_ERROR(mm_camcorder_stop(hcamcorder->camcorder)); + CHECK_MM_ERROR(mm_camcorder_unrealize(hcamcorder->camcorder)); + + bret = camcordertest_set_attr_int(MMCAM_CAMERA_ROTATION, index); + + CHECK_MM_ERROR(mm_camcorder_realize(hcamcorder->camcorder)); + CHECK_MM_ERROR(mm_camcorder_start(hcamcorder->camcorder)); + } + break; + + case 'p' : // Setting > FPS + g_print("* FPS !\n"); + + camcordertest_get_attr_valid_intarray("camera-fps", &array, &count); + + if(count <= 0 || count > 256) + { + g_print("Not supported !! \n"); + } + else + { + g_print("\n Select FPS \n"); + flush_stdin(); + for ( i = 0; i < count; i++) + { + g_print("\t %d. %d \n", i+1, array[i]); + } + scanf("%d",&index); + + if( index > 0 && index <= count ) + { + bret = camcordertest_set_attr_int("camera-fps", array[index-1]); + hcamcorder->fps = array[index-1]; + } + else + { + bret = FALSE; + g_print("\n Out of index \n"); + } + } + break; + + /* Display / Filter setting */ + case 'v' : // Setting > Display visible + g_print("* Display visible setting !\n"); + camcordertest_get_attr_valid_intarray( "display-visible", &array, &count ); + + if( count < 1 ) { + g_print("Not supported !! \n"); + } else { + g_print("\n Select Display visible \n"); + flush_stdin(); + for ( i = 0; i < count; i++) { + g_print("\t %d. %s\n", array[i], visible_mode[array[i]]); + } + scanf("%d",&value); + bret = camcordertest_set_attr_int( "display-visible", value ); + } + break; + + case 'o' : // Setting > Output mode + g_print("* Output mode!\n"); + camcordertest_get_attr_valid_intrange("display-geometry-method", &min, &max); + + if( min > max ) { + g_print("Not supported !! \n"); + } else { + flush_stdin(); + g_print("\n Select Output mode(%d ~ %d)\n", min, max); + for( i = min ; i <= max ; i++ ) { + g_print( "%d. %s\n", i, output_mode[i] ); + } + scanf("%d",&index); + bret = camcordertest_set_attr_int("display-geometry-method", index); + } + break; + + case 'y' : // Setting > Rotate Display + camcordertest_get_attr_valid_intarray( MMCAM_DISPLAY_ROTATION, &array, &count ); + + if( count <= 0 || count > 256 ) { + g_print("Not supported !! \n"); + } else { + flush_stdin(); + g_print("\n Select Rotation mode\n"); + for ( i = 0; i < count; i++) { + g_print("\t %d. %s\n", array[i], rotate_mode[array[i]]); + } + scanf("%d",&index); + bret = camcordertest_set_attr_int( MMCAM_DISPLAY_ROTATION, index ); + } + break; + + case 'g' : // Setting > Brightness + g_print("*Brightness !\n"); + camcordertest_get_attr_valid_intrange("filter-brightness", &min, &max); + + if(min >= max) { + g_print("Not supported !! \n"); + } else { + flush_stdin(); + g_print("\n Select brightness (%d ~ %d)\n", min, max); + scanf("%d",&index); + bret = camcordertest_set_attr_int("filter-brightness", index); + } + break; + + case 'c' : // Setting > Contrast + g_print("*Contrast !\n"); + camcordertest_get_attr_valid_intrange("filter-contrast", &min, &max); + + if(min >= max) { + g_print("Not supported !! \n"); + } else { + flush_stdin(); + g_print("\n Select Contrast (%d ~ %d)\n", min, max); + scanf("%d",&index); + bret = camcordertest_set_attr_int("filter-contrast", index); + } + break; + + case 's' : // Setting > Saturation + g_print("*Saturation !\n"); + camcordertest_get_attr_valid_intrange("filter-saturation", &min, &max); + + if(min >= max) { + g_print("Not supported !! \n"); + } else { + flush_stdin(); + g_print("\n Select Saturation (%d ~ %d)\n", min, max); + scanf("%d",&index); + bret = camcordertest_set_attr_int("filter-saturation", index); + } + break; + + case 'h' : // Setting > Hue + g_print("*Hue !\n"); + camcordertest_get_attr_valid_intrange("filter-hue", &min, &max); + + if(min >= max) { + g_print("Not supported !! \n"); + } else { + flush_stdin(); + g_print("\n Select Hue (%d ~ %d)\n", min, max); + scanf("%d",&index); + bret = camcordertest_set_attr_int("filter-hue", index); + } + break; + + case 'a' : // Setting > Sharpness + g_print("*Sharpness !\n"); + camcordertest_get_attr_valid_intrange("filter-sharpness", &min, &max); + + if(min >= max) { + g_print("Not supported !! \n"); + } else { + flush_stdin(); + g_print("\n Select Sharpness (%d ~ %d)\n", min, max); + scanf("%d",&index); + bret = camcordertest_set_attr_int("filter-sharpness", index); + } + break; + + case 'w' : // Setting > White balance + g_print("*White balance !\n"); + camcordertest_get_attr_valid_intarray("filter-wb", &array, &count); + + if(count <= 0) { + g_print("Not supported !! \n"); + } else { + flush_stdin(); + g_print("\n Select White balance \n"); + for ( i = 0; i < count; i++) { + g_print("\t %d. %s\n", array[i], wb[array[i]]); + } + scanf("%d",&index); + bret = camcordertest_set_attr_int("filter-wb", index); + } + break; + + case 't' : // Setting > Color tone + g_print("*Color tone !\n"); + camcordertest_get_attr_valid_intarray("filter-color-tone", &array, &count); + + if(count <= 0) { + g_print("Not supported !! \n"); + } else { + g_print("\n Select Color tone \n"); + flush_stdin(); + for ( i = 0; i < count; i++) { + g_print("\t %d. %s\n", array[i], ct[array[i]]); + } + scanf("%d",&index); + bret = camcordertest_set_attr_int("filter-color-tone", index); + } + break; + + case 'd' : // Setting > WDR + g_print("*WDR !\n"); + camcordertest_get_attr_valid_intarray("camera-wdr", &array, &count); + + if(count <= 0) { + g_print("Not supported !! \n"); + } + else { + g_print("\n Select WDR Mode \n"); + flush_stdin(); + for ( i = 0; i < count; i++) { + g_print("\t %d. %s\n", array[i], wdr_mode[array[i]]); + } + scanf("%d",&index); + bret = camcordertest_set_attr_int("camera-wdr", index); + } + break; + + /* ext. setting */ + case 'x' : // Setting > High Speed + { + static int backup_width = 0; + static int backup_height = 0; + + g_print("\n Select High Speed Recording mode\n"); + g_print("\t 1. High Speed Recording mode ON\n"); + g_print("\t 2. High Speed Recording mode OFF \n"); + + flush_stdin(); + scanf("%d",&index); + if (index == 1) { + mm_camcorder_get_attributes(hcamcorder->camcorder, &err_attr_name, + MMCAM_CAMERA_WIDTH, &backup_width, + MMCAM_CAMERA_HEIGHT, &backup_height, + NULL); + + CHECK_MM_ERROR(mm_camcorder_stop(hcamcorder->camcorder)); + CHECK_MM_ERROR(mm_camcorder_unrealize(hcamcorder->camcorder)); + + err = mm_camcorder_set_attributes(hcamcorder->camcorder, &err_attr_name, + MMCAM_CAMERA_WIDTH, 320, + MMCAM_CAMERA_HEIGHT, 240, + MMCAM_CAMERA_FPS, 120, + "camera-slow-motion-fps", 30, + NULL); + if (err != MM_ERROR_NONE) { + warn_msg_t("High speed recording. mm_camcorder_set_attributes fail. (%s:%x)", err_attr_name, err); + SAFE_FREE(err_attr_name); + } + + CHECK_MM_ERROR(mm_camcorder_realize(hcamcorder->camcorder)); + CHECK_MM_ERROR(mm_camcorder_start(hcamcorder->camcorder)); + + } else if(index == 2) { + CHECK_MM_ERROR(mm_camcorder_stop(hcamcorder->camcorder)); + CHECK_MM_ERROR(mm_camcorder_unrealize(hcamcorder->camcorder)); + + if (backup_width && backup_height) { + err = mm_camcorder_set_attributes(hcamcorder->camcorder, &err_attr_name, + MMCAM_CAMERA_WIDTH, backup_width, + MMCAM_CAMERA_HEIGHT, backup_height, + NULL); + if (err != MM_ERROR_NONE) { + warn_msg_t("get_attributes fail. (%s:%x)", err_attr_name, err); + SAFE_FREE (err_attr_name); + } + } + + err = mm_camcorder_set_attributes(hcamcorder->camcorder, &err_attr_name, + MMCAM_CAMERA_FPS, SRC_VIDEO_FRAME_RATE_30, + "camera-slow-motion-fps", 0, + NULL); + if (err != MM_ERROR_NONE) { + warn_msg_t("Normal speed recording. mm_camcorder_set_attributes fail. (%s:%x)", err_attr_name, err); + SAFE_FREE (err_attr_name); + } + + CHECK_MM_ERROR(mm_camcorder_realize(hcamcorder->camcorder)); + CHECK_MM_ERROR(mm_camcorder_start(hcamcorder->camcorder)); + } else { + g_print("Wrong input, Try again!!\n"); + } + break; + } + case 'u' : // Setting > Mute + g_print("*Mute!(%d)\n", hcamcorder->isMute); + + if (hcamcorder->isMute) { + new_volume = 0.0; + } else { + new_volume = 1.0; + } + + err = mm_camcorder_set_attributes(hcamcorder->camcorder, &err_attr_name, + MMCAM_AUDIO_VOLUME, new_volume, + NULL); + if (err < 0) { + warn_msg_t("Can' Mute. mm_camcorder_set_attributes fail. (%s:%x)", err_attr_name, err); + SAFE_FREE (err_attr_name); + } + + hcamcorder->isMute = !(hcamcorder->isMute); + break; + + case 'z' : // Setting > Strobe setting + g_print("*Strobe Mode\n"); + camcordertest_get_attr_valid_intarray("strobe-mode", &array, &count); + if(count <= 0) { + g_print("Not supported !! \n"); + } else { + g_print("\n Select Strobe Mode \n"); + flush_stdin(); + for ( i = 0; i < count; i++) { + g_print("\t %d. %s\n", array[i], strobe_mode[array[i]]); + } + scanf("%d",&index); + bret = camcordertest_set_attr_int("strobe-mode", index); + } + break; + + case 'k' : // Setting > Anti-handshake + g_print("*Anti-handshake !\n"); + camcordertest_get_attr_valid_intarray("camera-anti-handshake", &array, &count); + + if(count <= 0) { + g_print("Not supported !! \n"); + } else { + g_print("\n Select Anti-handshake mode \n"); + flush_stdin(); + for ( i = 0; i < count; i++) { + g_print("\t %d. %s\n", array[i], ahs_mode[array[i]]); + } + scanf("%d",&index); + bret = camcordertest_set_attr_int("camera-anti-handshake", index); + } + break; + + case 'e' : // Setting > Camcorder-rotation setting + g_print("*Camcorder-rotation setting!\n"); + camcordertest_get_attr_valid_intrange("camcorder-rotation", &min, &max); + + if(min >= max) { + g_print("Not supported !! \n"); + } else { + g_print("\n Select camcorder-rotation value \n"); + flush_stdin(); + for ( i = 0; i < (max-min+1); i++) { + g_print("\t %d. %s\n", i, camcorder_rotate_val[i]); + } + scanf("%d",&index); + bret = camcordertest_set_attr_int("camcorder-rotation", index); + } + break; + + case 'm' : // Setting > Stream callback function + g_print("\n Select Stream Callback Function\n"); + g_print("\t 1. Set Video Stream Callback \n"); + g_print("\t 2. Set Audio Stream Callback \n"); + g_print("\t 3. Unset Stream Callback \n"); + flush_stdin(); + scanf("%d", &index); + if(index == 1) { + video_stream_cb_cnt = 0; + error_num = mm_camcorder_set_video_stream_callback(hcamcorder->camcorder, (mm_camcorder_video_stream_callback)camcordertest_video_stream_cb, (void*)hcamcorder->camcorder); + if( error_num == MM_ERROR_NONE ) { + g_print("\n Setting Success\n"); + } else { + g_print("\n Setting Failure\n"); + } + } else if(index == 2) { + audio_stream_cb_cnt = 0; + error_num = mm_camcorder_set_audio_stream_callback(hcamcorder->camcorder, (mm_camcorder_audio_stream_callback)camcordertest_audio_stream_cb, (void*)hcamcorder->camcorder); + if( error_num == MM_ERROR_NONE ) { + g_print("\n Setting Success\n"); + } else { + g_print("\n Setting Failure\n"); + } + } else if(index == 3) { + mm_camcorder_set_video_stream_callback(hcamcorder->camcorder, NULL, (void*)hcamcorder->camcorder); + mm_camcorder_set_audio_stream_callback(hcamcorder->camcorder, NULL, (void*)hcamcorder->camcorder); + video_stream_cb_cnt = 0; + audio_stream_cb_cnt = 0; + g_print("\n Unset stream callback success\n"); + } else { + g_print("\t Invalid input \n"); + } + //g_print("Not supported !! \n"); + break; + + case 'b' : // back + hcamcorder->menu_state = MENU_STATE_MAIN; + break; + + default : + g_print("\t Invalid input \n"); + break; + } + } + else + { + g_print("\t Invalid mode, back to upper menu \n"); + hcamcorder->menu_state = MENU_STATE_MAIN; + } +} + + +/** + * This function is to execute command. + * + * @param channel [in] 1st parameter + * + * @return This function returns TRUE/FALSE + * @remark + * @see + */ +static gboolean cmd_input(GIOChannel *channel) +{ + gchar buf[256]; + gsize read; + + debug_msg_t("ENTER"); + + g_io_channel_read(channel, buf, CAPTURE_FILENAME_LEN, &read); + buf[read] = '\0'; + g_strstrip(buf); + + debug_msg_t("Menu Status : %d", hcamcorder->menu_state); + switch(hcamcorder->menu_state) + { + case MENU_STATE_MAIN: + main_menu(buf[0]); + break; + case MENU_STATE_SETTING: + setting_menu(buf[0]); + break; + default: + break; + } + print_menu(); + return TRUE; +} + +void validity_print(MMCamAttrsInfo *info) +{ + printf("info(%d,%d, %d))\n", info->type, info->flag, info->validity_type); + if (info->validity_type == MM_CAM_ATTRS_VALID_TYPE_INT_ARRAY) + { + printf("int array(%p, %d)\n", info->int_array.array, info->int_array.count); + } + else if (info->validity_type == MM_CAM_ATTRS_VALID_TYPE_INT_RANGE) + { + printf("int range(%d, %d)\n", info->int_range.min, info->int_range.max); + } + else if (info->validity_type == MM_CAM_ATTRS_VALID_TYPE_DOUBLE_ARRAY) + { + printf("double array(%p, %d)\n", info->double_array.array, info->double_array.count); + } + else if(info->validity_type == MM_CAM_ATTRS_VALID_TYPE_DOUBLE_RANGE) + { + printf("double range(%f, %f)\n", info->double_range.min, info->double_range.max); + } + else + { + printf("validity none\n"); + } + return; +} + + +/** + * This function is to initiate camcorder attributes . + * + * @param type [in] image(capture)/video(recording) mode + * + * @return This function returns TRUE/FALSE + * @remark + * @see other functions + */ +static gboolean init(int type) +{ + int err; + int size; + int preview_format = MM_PIXEL_FORMAT_NV12; + MMHandleType cam_handle = 0; + + char *err_attr_name = NULL; + + if (!hcamcorder) + return FALSE; + + if(!hcamcorder->camcorder) + return FALSE; + + cam_handle = (MMHandleType)(hcamcorder->camcorder); + + /*================================================================================ + image mode + *=================================================================================*/ + if (type == MODE_IMAGE) + { + mm_camcorder_get_attributes((MMHandleType)cam_handle, NULL, + MMCAM_RECOMMEND_PREVIEW_FORMAT_FOR_CAPTURE, &preview_format, + NULL); + + /* camcorder attribute setting */ + err = mm_camcorder_set_attributes( (MMHandleType)cam_handle, &err_attr_name, + MMCAM_MODE, MM_CAMCORDER_MODE_IMAGE, + MMCAM_CAMERA_FORMAT, preview_format, + "camera-delay-attr-setting", TRUE, + MMCAM_IMAGE_ENCODER, MM_IMAGE_CODEC_JPEG, + MMCAM_IMAGE_ENCODER_QUALITY, IMAGE_ENC_QUALITY, + MMCAM_TAG_ENABLE, 1, + MMCAM_TAG_LATITUDE, 35.3036944, + MMCAM_TAG_LONGITUDE, 176.67837, + MMCAM_TAG_ALTITUDE, 190.3455, + MMCAM_DISPLAY_DEVICE, MM_DISPLAY_DEVICE_MAINLCD, + MMCAM_DISPLAY_SURFACE, MM_DISPLAY_SURFACE_X, + MMCAM_DISPLAY_RECT_X, DISPLAY_X_0, + MMCAM_DISPLAY_RECT_Y, DISPLAY_Y_0, + MMCAM_DISPLAY_RECT_WIDTH, 480, + MMCAM_DISPLAY_RECT_HEIGHT, 640, + MMCAM_DISPLAY_ROTATION, MM_DISPLAY_ROTATION_270, + MMCAM_DISPLAY_GEOMETRY_METHOD, MM_DISPLAY_METHOD_LETTER_BOX, + MMCAM_CAPTURE_COUNT, IMAGE_CAPTURE_COUNT_STILL, + "capture-thumbnail", TRUE, + "tag-gps-time-stamp", 72815.5436243543, + "tag-gps-date-stamp", "2010:09:20", 10, + "tag-gps-processing-method", "GPS NETWORK HYBRID ARE ALL FINE.", 32, + "capture-sound-enable", TRUE, + NULL ); + + if (err != MM_ERROR_NONE) { + warn_msg_t("Init fail. (%s:%x)", err_attr_name, err); + SAFE_FREE (err_attr_name); + goto ERROR; + } + + mm_camcorder_set_video_capture_callback(hcamcorder->camcorder, (mm_camcorder_video_capture_callback)camcordertest_video_capture_cb, hcamcorder); + } + /*================================================================================ + video mode + *=================================================================================*/ + else if (type == MODE_VIDEO) + { + mm_camcorder_get_attributes((MMHandleType)cam_handle, NULL, + MMCAM_RECOMMEND_PREVIEW_FORMAT_FOR_RECORDING, &preview_format, + NULL); + + size = strlen(TARGET_FILENAME_VIDEO)+1; + + /* camcorder attribute setting */ + err = mm_camcorder_set_attributes( (MMHandleType)cam_handle, &err_attr_name, + MMCAM_MODE, MM_CAMCORDER_MODE_VIDEO, + MMCAM_AUDIO_DEVICE, MM_AUDIO_DEVICE_MIC, + MMCAM_AUDIO_ENCODER, MM_AUDIO_CODEC_AMR, + MMCAM_VIDEO_ENCODER, MM_VIDEO_CODEC_H264, + MMCAM_FILE_FORMAT, MM_FILE_FORMAT_3GP, + MMCAM_CAMERA_FORMAT, preview_format, + MMCAM_CAMERA_FPS, SRC_VIDEO_FRAME_RATE_30, + MMCAM_CAMERA_FPS_AUTO, 0, + "camera-delay-attr-setting", TRUE, + MMCAM_CAMERA_ROTATION, MM_VIDEO_INPUT_ROTATION_NONE, + MMCAM_AUDIO_SAMPLERATE, AUDIO_SOURCE_SAMPLERATE_AMR, + MMCAM_AUDIO_FORMAT, AUDIO_SOURCE_FORMAT, + MMCAM_AUDIO_CHANNEL, AUDIO_SOURCE_CHANNEL_AMR, + MMCAM_AUDIO_INPUT_ROUTE, MM_AUDIOROUTE_CAPTURE_NORMAL, + MMCAM_TAG_ENABLE, 1, + MMCAM_TAG_LATITUDE, 37.25796666, + MMCAM_TAG_LONGITUDE, 127.05332222, + MMCAM_TAG_ALTITUDE, 45.0000, + MMCAM_DISPLAY_DEVICE, MM_DISPLAY_DEVICE_MAINLCD, + MMCAM_DISPLAY_SURFACE, MM_DISPLAY_SURFACE_X, + MMCAM_DISPLAY_RECT_X, DISPLAY_X_0, + MMCAM_DISPLAY_RECT_Y, DISPLAY_Y_0, + MMCAM_DISPLAY_RECT_WIDTH, 480, + MMCAM_DISPLAY_RECT_HEIGHT, 640, + MMCAM_DISPLAY_ROTATION, MM_DISPLAY_ROTATION_270, + MMCAM_TARGET_FILENAME, TARGET_FILENAME_VIDEO, size, + "capture-sound-enable", TRUE, + NULL ); + + if (err != MM_ERROR_NONE) { + fprintf(stderr, "video mode init fail. [%s][%x)", err_attr_name, err); + SAFE_FREE (err_attr_name); + goto ERROR; + } +// mm_camcorder_set_audio_stream_callback(hcamcorder->camcorder, (mm_camcorder_audio_stream_callback)camcordertest_audio_stream_cb, (void*)hcamcorder->camcorder); + } + + /*================================================================================ + Audio mode + *=================================================================================*/ + else if (type == MODE_AUDIO) + { + size = strlen(TARGET_FILENAME_AUDIO)+1; + + /* camcorder attribute setting */ + err = mm_camcorder_set_attributes( hcamcorder->camcorder, &err_attr_name, + MMCAM_MODE, MM_CAMCORDER_MODE_AUDIO, + MMCAM_AUDIO_DEVICE, MM_AUDIO_DEVICE_MIC, + MMCAM_AUDIO_ENCODER, MM_AUDIO_CODEC_AMR, + MMCAM_FILE_FORMAT, MM_FILE_FORMAT_AMR, + MMCAM_AUDIO_SAMPLERATE, AUDIO_SOURCE_SAMPLERATE_AMR, + MMCAM_AUDIO_FORMAT, AUDIO_SOURCE_FORMAT, + MMCAM_AUDIO_CHANNEL, AUDIO_SOURCE_CHANNEL_AMR, + MMCAM_AUDIO_INPUT_ROUTE, MM_AUDIOROUTE_CAPTURE_NORMAL, + MMCAM_TARGET_FILENAME, TARGET_FILENAME_AUDIO, size, + MMCAM_TARGET_TIME_LIMIT, 360000, + NULL); + + if (err < 0) + { + warn_msg_t("Init fail. (%s:%x)", err_attr_name, err); + SAFE_FREE (err_attr_name); + goto ERROR; + } + +// mm_camcorder_set_audio_stream_callback(hcamcorder->camcorder, (mm_camcorder_audio_stream_callback)camcordertest_audio_stream_cb, (void*)hcamcorder->camcorder); + } + + debug_msg_t("Init DONE."); + + return TRUE; + +ERROR: + err_msg_t("init failed."); + return FALSE; +} + +/** + * This function is to represent messagecallback + * + * @param message [in] Specifies the message + * @param param [in] Specifies the message type + * @param user_param [in] Specifies the user poiner for passing to callback function + * @return This function returns TRUE/FALSE + * @remark + * @see other functions + */ +static gboolean msg_callback(int message, void *msg_param, void *user_param) +{ + + MMMessageParamType *param = (MMMessageParamType *) msg_param; + + switch (message) { + case MM_MESSAGE_CAMCORDER_ERROR: + g_print("MM_MESSAGE_ERROR : code = %x", param->code); + break; + case MM_MESSAGE_CAMCORDER_STATE_CHANGED: + g_current_state = param->state.current; + switch(g_current_state) + { + case MM_CAMCORDER_STATE_NULL : + mmcamcorder_state = MM_CAMCORDER_STATE_NULL; + debug_msg_t("Camcorder State is [NULL]"); + break; + case MM_CAMCORDER_STATE_READY : + mmcamcorder_state = MM_CAMCORDER_STATE_READY; + debug_msg_t("Camcorder State is [READY]"); + break; + case MM_CAMCORDER_STATE_PREPARE : + mmcamcorder_state = MM_CAMCORDER_STATE_PREPARE; + debug_msg_t("Camcorder State is [PREPARE]"); + break; + case MM_CAMCORDER_STATE_CAPTURING : + mmcamcorder_state = MM_CAMCORDER_STATE_CAPTURING; + debug_msg_t("Camcorder State is [CAPTURING]"); + break; + case MM_CAMCORDER_STATE_RECORDING : + mmcamcorder_state = MM_CAMCORDER_STATE_RECORDING; + time_msg_t("Recording start time : %12.6lf s", g_timer_elapsed(timer, NULL)); + debug_msg_t("Camcorder State is [RECORDING]"); + break; + case MM_CAMCORDER_STATE_PAUSED : + mmcamcorder_state = MM_CAMCORDER_STATE_PAUSED; + debug_msg_t("Camcorder State is [PAUSED]"); + break; + } + break; + + case MM_MESSAGE_CAMCORDER_CAPTURED: + { + if (hcamcorder->mode == MODE_IMAGE) + { + time_msg_t("Stillshot capture : %12.6lf s", g_timer_elapsed(timer, NULL)); + + g_print("*******************************************************\n"); + g_print("[Camcorder Testsuite] Camcorder Stillshot Captured!!\n"); + g_print("*******************************************************\n"); + + if (hcamcorder->isMultishot) //multishot + { + g_print("[CamcorderApp] Camcorder Captured(Capture Count=%d)\n", param->code); + + if (param->code >= multishot_num) + { + get_me_out(); +// g_timeout_add (100, (GSourceFunc)get_me_out, NULL); +// hcamcorder->isMultishot = FALSE; + } + } + else //singleshot + { + get_me_out(); +// g_timeout_add (1000, (GSourceFunc)get_me_out, NULL); + } + + } + else + { + MMCamRecordingReport* report ; + + time_msg_t("Recording commit time : %12.6lf s", g_timer_elapsed(timer, NULL)); + + if (param) + report = (MMCamRecordingReport*)(param->data); + else + return FALSE; + + if( report != NULL ) + { + g_print("*******************************************************\n"); + g_print("[Camcorder Testsuite] Camcorder Captured(filename=%s)\n", report->recording_filename); + g_print("*******************************************************\n"); + + SAFE_FREE (report->recording_filename); + SAFE_FREE (report); + } + else + { + g_print( "[Camcorder Testsuite] report is NULL.\n" ); + } + } + } + break; + case MM_MESSAGE_CAMCORDER_TIME_LIMIT: + { + debug_msg_t("Got TIME LIMIT MESSAGE"); + } + break; + case MM_MESSAGE_CAMCORDER_RECORDING_STATUS: + { + unsigned int elapsed; + elapsed = param->recording_status.elapsed / 1000; + if (hcamcorder->elapsed_time != elapsed) { + unsigned int temp_time; + int hour, minute, second; + hcamcorder->elapsed_time = elapsed; + temp_time = elapsed; + hour = temp_time / 3600; + temp_time = elapsed % 3600; + minute = temp_time / 60; + second = temp_time % 60; + debug_msg_t("Current Time - %d:%d:%d", hour, minute, second); + } + } + break; + case MM_MESSAGE_CAMCORDER_MAX_SIZE: + { + int err; + g_print("*Save Recording because receives message : MM_MESSAGE_CAMCORDER_MAX_SIZE\n"); + g_timer_reset(timer); + err = mm_camcorder_commit(hcamcorder->camcorder); + + if (err < 0) + { + warn_msg_t("Save recording mm_camcorder_commit = %x", err); +// goto ERROR; + } + } + break; + case MM_MESSAGE_CAMCORDER_CURRENT_VOLUME: + break; + case MM_MESSAGE_CAMCORDER_NO_FREE_SPACE: + { + int err; + g_print("*Save Recording because receives message : MM_MESSAGE_CAMCORDER_NO_FREE_SPACE\n"); + g_timer_reset(timer); + err = mm_camcorder_commit(hcamcorder->camcorder); + + if (err < 0) + { + warn_msg_t("Save recording mm_camcorder_commit = %x", err); +// goto ERROR; + } + } + break; + case MM_MESSAGE_CAMCORDER_FOCUS_CHANGED: + { + g_print( "Focus State changed. State:[%d]\n", param->code ); + } + break; + default: + g_print("Message %x received\n", message); + break; + } + + return TRUE; +} + +static gboolean init_handle() +{ + hcamcorder->mode = MODE_IMAGE; /* image(capture)/video(recording) mode */ + hcamcorder->isMultishot = FALSE; + hcamcorder->stillshot_count = 0; /* total stillshot count */ + hcamcorder->multishot_count = 0; /* total multishot count */ + hcamcorder->stillshot_filename = STILL_CAPTURE_FILE_PATH_NAME; /* stored filename of stillshot */ + hcamcorder->multishot_filename = MULTI_CAPTURE_FILE_PATH_NAME; /* stored filename of multishot */ + hcamcorder->menu_state = MENU_STATE_MAIN; + hcamcorder->isMute = FALSE; + hcamcorder->elapsed_time = 0; + hcamcorder->fps = SRC_VIDEO_FRAME_RATE_15; //SRC_VIDEO_FRAME_RATE_30; + multishot_num = IMAGE_CAPTURE_COUNT_MULTI; + + return TRUE; +} +/** + * This function is to change camcorder mode. + * + * @param type [in] image(capture)/video(recording) mode + * + * @return This function returns TRUE/FALSE + * @remark + * @see other functions + */ +static gboolean mode_change() +{ + int err = MM_ERROR_NONE; + int state; + char media_type = '\0'; + bool check= FALSE; + + debug_msg_t("MMCamcorder State : %d", mmcamcorder_state); + + err = mm_camcorder_get_state(hcamcorder->camcorder, (MMCamcorderStateType *)&state); + if(state != MM_CAMCORDER_STATE_NONE) + { + if ((state == MM_CAMCORDER_STATE_RECORDING) + || (state == MM_CAMCORDER_STATE_PAUSED)) + { + debug_msg_t("mm_camcorder_cancel"); + err = mm_camcorder_cancel(hcamcorder->camcorder); + + if (err < 0) + { + warn_msg_t("exit mm_camcorder_cancel = %x", err); + return FALSE; + } + } + else if (state == MM_CAMCORDER_STATE_CAPTURING) + { + debug_msg_t("mm_camcorder_capture_stop"); + err = mm_camcorder_capture_stop(hcamcorder->camcorder); + + if (err < 0) + { + warn_msg_t("exit mmcamcorder_capture_stop = %x", err); + return FALSE; + } + } + + err = mm_camcorder_get_state(hcamcorder->camcorder, (MMCamcorderStateType *)&state); + if(state == MM_CAMCORDER_STATE_PREPARE) + { + debug_msg_t("mm_camcorder_stop"); + mm_camcorder_stop(hcamcorder->camcorder); + } + + err = mm_camcorder_get_state(hcamcorder->camcorder, (MMCamcorderStateType *)&state); + if(state == MM_CAMCORDER_STATE_READY) + { + debug_msg_t("mm_camcorder_unrealize"); + mm_camcorder_unrealize(hcamcorder->camcorder); + } + + err = mm_camcorder_get_state(hcamcorder->camcorder, (MMCamcorderStateType *)&state); + if(state == MM_CAMCORDER_STATE_NULL) + { + debug_msg_t("mm_camcorder_destroy"); + mm_camcorder_destroy(hcamcorder->camcorder); + + mmcamcorder_state = MM_CAMCORDER_STATE_NONE; + } + } + + init_handle(); + mmcamcorder_print_state = MM_CAMCORDER_STATE_PREPARE; + while(!check) { + g_print("\n\t=======================================\n"); + g_print("\t MM_CAMCORDER_TESTSUIT\n"); + g_print("\t=======================================\n"); + g_print("\t '1' Image Capture - Front Camera\n"); + g_print("\t '2' Image Capture - Rear Camera\n"); + g_print("\t '3' Video Recording - Front Camera\n"); + g_print("\t '4' Video Recording - Rear Camera\n"); + g_print("\t '5' Audio Recording\n"); + g_print("\t 'q' Exit\n"); + g_print("\t=======================================\n"); + + g_print("\t Enter the media type:\n\t"); + + while ((media_type=getchar()) == '\n'); + + switch(media_type) { + case '1': + hcamcorder->mode= MODE_IMAGE; + cam_info.videodev_type = MM_VIDEO_DEVICE_CAMERA1; + check = TRUE; + break; + case '2': + hcamcorder->mode= MODE_IMAGE; + cam_info.videodev_type = MM_VIDEO_DEVICE_CAMERA0; + check = TRUE; + break; + case '3': + hcamcorder->mode= MODE_VIDEO; + cam_info.videodev_type = MM_VIDEO_DEVICE_CAMERA1; + check = TRUE; + break; + case '4': + hcamcorder->mode= MODE_VIDEO; + cam_info.videodev_type = MM_VIDEO_DEVICE_CAMERA0; + check = TRUE; + break; + case '5': + hcamcorder->mode= MODE_AUDIO; + cam_info.videodev_type = MM_VIDEO_DEVICE_NONE; + check = TRUE; + break; + case 'q': + g_print("\t Quit Camcorder Testsuite!!\n"); + hcamcorder->mode = -1; + if(g_main_loop_is_running(g_loop)) { + g_main_loop_quit(g_loop); + } + return FALSE; + default: + g_print("\t Invalid media type(%d)\n", media_type); + continue; + } + } + + debug_msg_t("mm_camcorder_create"); + g_get_current_time(&previous); + g_timer_reset(timer); + + err = mm_camcorder_create(&hcamcorder->camcorder, &cam_info); + time_msg_t("mm_camcorder_create() : %12.6lfs", g_timer_elapsed(timer, NULL)); + + if (err != MM_ERROR_NONE) { + err_msg_t("mmcamcorder_create = %x", err); + return -1; + } else { + mmcamcorder_state = MM_CAMCORDER_STATE_NULL; + } + + mm_camcorder_set_message_callback(hcamcorder->camcorder, (MMMessageCallback)msg_callback, hcamcorder); + + if (!init(hcamcorder->mode)) { + err_msg_t("testsuite init() failed."); + return -1; + } + + debug_msg_t("mm_camcorder_realize"); + + g_timer_reset(timer); + + err = mm_camcorder_realize(hcamcorder->camcorder); + time_msg_t("mm_camcorder_realize() : %12.6lfs", g_timer_elapsed(timer, NULL)); + if (err != MM_ERROR_NONE) { + err_msg_t("mm_camcorder_realize = %x", err); + return -1; + } + + /* start camcorder */ + debug_msg_t("mm_camcorder_start"); + + g_timer_reset(timer); + + err = mm_camcorder_start(hcamcorder->camcorder); + time_msg_t("mm_camcorder_start() : %12.6lfs", g_timer_elapsed(timer, NULL)); + + if (err != MM_ERROR_NONE) { + err_msg_t("mm_camcorder_start = %x", err); + return -1; + } + + g_get_current_time(¤t); + timersub(¤t, &previous, &result); + time_msg_t("Camera Starting Time : %ld.%lds", result.tv_sec, result.tv_usec); + + return TRUE; +} + + +/** + * This function is the example main function for mmcamcorder API. + * + * @param + * + * @return This function returns 0. + * @remark + * @see other functions + */ +int main(int argc, char **argv) +{ + int bret; + + if (!g_thread_supported()) + g_thread_init (NULL); + + timer = g_timer_new(); + + gst_init(&argc, &argv); + + time_msg_t("gst_init() : %12.6lfs", g_timer_elapsed(timer, NULL)); + + hcamcorder = (cam_handle_t *) g_malloc0(sizeof(cam_handle_t)); + mmcamcorder_state = MM_CAMCORDER_STATE_NONE; + + g_timer_reset(timer); + + bret = mode_change(); + if(!bret){ + return bret; + } + + print_menu(); + + g_loop = g_main_loop_new(NULL, FALSE); + + stdin_channel = g_io_channel_unix_new(fileno(stdin));/* read from stdin */ + g_io_add_watch(stdin_channel, G_IO_IN, (GIOFunc)cmd_input, NULL); + + debug_msg_t("RUN main loop"); + + g_main_loop_run(g_loop); + + debug_msg_t("STOP main loop"); + + if (timer) { + g_timer_stop(timer); + g_timer_destroy(timer); + timer = NULL; + } + //g_print("\t Exit from the application.\n"); + g_free(hcamcorder); + g_main_loop_unref(g_loop); + g_io_channel_unref(stdin_channel); + + return bret; +} + +/*EOF*/ -- 2.7.4