From: Hyuntae, Kim Date: Mon, 21 Dec 2015 23:36:38 +0000 (+0900) Subject: [mediastreamrecorder] initial code for streamrecorder X-Git-Tag: accepted/tizen/ivi/20160218.022854^0 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=f2ff588a8a38033ed9d0427e104fa684dd6cda23;p=platform%2Fcore%2Fapi%2Fmediastreamrecorder.git [mediastreamrecorder] initial code for streamrecorder Change-Id: Iaa58d74566b11fd58f1720bb68e5cc3a7f109a3e --- diff --git a/AUTHORS b/AUTHORS new file mode 100644 index 0000000..ac14513 --- /dev/null +++ b/AUTHORS @@ -0,0 +1,5 @@ +sahil bansal +ruchika saxena +hyuntae kim +Jeongmo Yang +Heechul Jeon diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..195f9c8 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,118 @@ +CMAKE_MINIMUM_REQUIRED(VERSION 2.6) + +SET(Services + "application" + "base" + "content" + "location" + "media" + "messaging" + "network" + "social" + "telephony" + "system" + ) + +# project +SET(project_prefix "capi") +SET(prefix "/usr") +SET(maintainer "Sahil Bansal ") +SET(description "A Stream Recorder library in Tizen Native API") +SET(service "media") +SET(submodule "streamrecorder") + +# for package file +SET(dependents "dlog mm-streamrecorder capi-media-audio-io capi-media-tool") +SET(pc_dependents "capi-base-common capi-media-audio-io capi-media-tool") + +SET(fw_name "${project_prefix}-${service}-${submodule}") + +PROJECT(${fw_name}) + +SET(CMAKE_INSTALL_PREFIX ${prefix}) +SET(PREFIX ${CMAKE_INSTALL_PREFIX}) + +SET(INC_DIR include) +INCLUDE_DIRECTORIES(${INC_DIR}) + +INCLUDE(FindPkgConfig) +pkg_check_modules(${fw_name} REQUIRED ${dependents}) +FOREACH(flag ${${fw_name}_CFLAGS}) + SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}") +ENDFOREACH(flag) + +SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS} -fPIC -Wall -Wextra -Wno-array-bounds -Wno-empty-body -Wno-ignored-qualifiers -Wno-unused-parameter -Wshadow -Wwrite-strings -Wswitch-default -Wno-unused-but-set-parameter -Wno-unused-but-set-variable") +SET(CMAKE_C_FLAGS_DEBUG "-O0 -g") + +IF("${ARCH}" STREQUAL "arm") + ADD_DEFINITIONS("-DTARGET") +ENDIF("${ARCH}" STREQUAL "arm") + +ADD_DEFINITIONS("-DPREFIX=\"${CMAKE_INSTALL_PREFIX}\"") +ADD_DEFINITIONS("-DTIZEN_DEBUG") + +SET(CMAKE_EXE_LINKER_FLAGS "-Wl,--as-needed -Wl,--rpath=${LIB_INSTALL_DIR}") + +aux_source_directory(src SOURCES) +ADD_LIBRARY(${fw_name} SHARED ${SOURCES}) + +SET_TARGET_PROPERTIES(${fw_name} + PROPERTIES + VERSION ${FULLVER} + SOVERSION ${MAJORVER} + CLEAN_DIRECT_OUTPUT 1 +) + +TARGET_LINK_LIBRARIES(${fw_name} ${${fw_name}_LDFLAGS}) + +INSTALL(TARGETS ${fw_name} DESTINATION ${LIB_INSTALL_DIR}) +INSTALL( + DIRECTORY ${INC_DIR}/ DESTINATION include/${service} + FILES_MATCHING + PATTERN "*_private.h" EXCLUDE + PATTERN "${INC_DIR}/*.h" + ) + +SET(PC_NAME ${fw_name}) +SET(PC_REQUIRED ${pc_dependents}) +SET(PC_LDFLAGS -l${fw_name}) + +CONFIGURE_FILE( + ${fw_name}.pc.in + ${CMAKE_CURRENT_SOURCE_DIR}/${fw_name}.pc + @ONLY +) +INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/${fw_name}.pc DESTINATION ${LIB_INSTALL_DIR}/pkgconfig) + +ADD_SUBDIRECTORY(test) + +IF(UNIX) + +ADD_CUSTOM_TARGET (distclean @echo cleaning for source distribution) +ADD_CUSTOM_COMMAND( + DEPENDS clean + COMMENT "distribution clean" + COMMAND find + ARGS . + -not -name config.cmake -and \( + -name tester.c -or + -name Testing -or + -name CMakeFiles -or + -name cmake.depends -or + -name cmake.check_depends -or + -name CMakeCache.txt -or + -name cmake.check_cache -or + -name *.cmake -or + -name Makefile -or + -name core -or + -name core.* -or + -name gmon.out -or + -name install_manifest.txt -or + -name *.pc -or + -name *~ \) + | grep -v TC | xargs rm -rf + TARGET distclean + VERBATIM +) + +ENDIF(UNIX) diff --git a/LICENSE.APLv2 b/LICENSE.APLv2 new file mode 100644 index 0000000..bbe9d02 --- /dev/null +++ b/LICENSE.APLv2 @@ -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/NOTICE b/NOTICE new file mode 100644 index 0000000..0e0f016 --- /dev/null +++ b/NOTICE @@ -0,0 +1,3 @@ +Copyright (c) Samsung Electronics Co., Ltd. All rights reserved. +Except as noted, this software is licensed under Apache License, Version 2. +Please, see the LICENSE.APLv2 file for Apache License terms and conditions. diff --git a/capi-media-streamrecorder.manifest b/capi-media-streamrecorder.manifest new file mode 100644 index 0000000..a76fdba --- /dev/null +++ b/capi-media-streamrecorder.manifest @@ -0,0 +1,5 @@ + + + + + diff --git a/capi-media-streamrecorder.pc.in b/capi-media-streamrecorder.pc.in new file mode 100644 index 0000000..1508489 --- /dev/null +++ b/capi-media-streamrecorder.pc.in @@ -0,0 +1,15 @@ + +# Package Information for pkg-config + +prefix=@PREFIX@ +exec_prefix=/usr +libdir=@LIB_INSTALL_DIR@ +includedir=/usr/include/media + +Name: @PC_NAME@ +Description: @PACKAGE_DESCRIPTION@ +Version: @VERSION@ +Requires: @PC_REQUIRED@ +Libs: -L${libdir} @PC_LDFLAGS@ +Cflags: -I${includedir} + diff --git a/doc/images/capi_media_streamrecorder_state_diagram.png b/doc/images/capi_media_streamrecorder_state_diagram.png new file mode 100644 index 0000000..2aabd6d Binary files /dev/null and b/doc/images/capi_media_streamrecorder_state_diagram.png differ diff --git a/doc/streamrecorder_doc.h b/doc/streamrecorder_doc.h new file mode 100644 index 0000000..cb1684e --- /dev/null +++ b/doc/streamrecorder_doc.h @@ -0,0 +1,229 @@ +/* + * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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 __TIZEN_MEDIA_STREAMRECORDER_DOC_H__ +#define __TIZEN_MEDIA_STREAMRECORDER_DOC_H__ + + +/** + * @file streamrecorder_doc.h + * @brief The file contains the high level documentation for the StreamRecorder API. + */ + +/** + * @ingroup CAPI_MEDIA_FRAMEWORK + * @defgroup CAPI_MEDIA_STREAMRECORDER_MODULE StreamRecorder + * @brief The @ref CAPI_MEDIA_STREAMRECORDER_MODULE API provides functions for StreamRecorder with buffer including media packet. + * + * @section CAPI_MEDIA_STREAMRECORDER_MODULE_HEADER Required Header + * \#include + * + * @section CAPI_MEDIA_STREAMRECORDER_MODULE_OVERVIEW Overview + * The StreamRecorder API allows application developers to support using the video or audio recorder. It includes functions that record video or audio and supports to set up + * notifications for state changes of creation, prepared, record, pause, information about resolution and binary data format, and functions for artistic. + * + * The StreamRecorder API allows creation of components required in recording video or audio including: + * - selecting a proper output format + * - controlling the StreamRecorder state + * - getting supported formats and video resolutions + * + * The StreamRecorder API also notifies you (by callback mechanism) when a significant parameter changes. + * + * @subsection CAPI_MEDIA_STREAMRECORDER_DIFFERENCE Difference + * Basically, the StreamRecorder API can help easily to make video/audio content same as the Recorder API.\n + * + * However, the StreamRecorder API is different from Recorder API. \n + * The StreamRecorder API is able to record user buffer from application. This allows the user to make unique contents with a purpose. + * + *
+ * + * + * + * + * + * + * + * + * + * + *
Difference RecorderStreamRecorder
INPUT Camera / Mic Device Media Packet / Buffer
+ * + * @subsection CAPI_MEDIA_STREAMRECORDER_LIFE_CYCLE_STATE_DIAGRAM State Diagram + * @image html capi_media_streamrecorder_state_diagram.png + * + * @subsection CAPI_MEDIA_STREAMRECORDER_LIFE_CYCLE_STATE_TRANSITIONS State Transitions + *
+ * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
FUNCTIONPRE-STATEPOST-STATESYNC TYPE
streamrecorder_create() NONE CREATED SYNC
streamrecorder_prepare() CREATED PREPARED SYNC
streamrecorder_start() PREPARED / PAUSED RECORDING SYNC
streamrecorder_pause() RECORDING PAUSED SYNC
streamrecorder_commit() RECORDING/ PAUSED PREPARED SYNC
streamrecorder_cancel() RECORDING/ PAUSED PREPARED SYNC
streamrecorder_unprepare() PREPARED CREATED SYNC
streamrecorder_destroy() CREATED NONE SYNC
+ * + * @subsection CAPI_MEDIA_STREAMRECORDER_LIFE_CYCLE_CALLBACK_OPERATIONS Callback(Event) Operations + * The callback mechanism is used to notify the application about significant StreamRecorder events. + *
+ * + * + * + * + * + * + * + * + * + * + * + * + *
REGISTERUNREGISTERCALLBACKDESCRIPTION
streamrecorder_set_error_cb()streamrecorder_unset_error_cb()streamrecorder_error_cb()This callback is used to notify error has occurred
+ * + * @subsection CAPI_MEDIA_STREAMRECORDER_FOREACH_OPERATIONS Foreach Operations + *
+ * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
FOREACHCALLBACKDESCRIPTION
streamrecorder_foreach_supported_audio_encoder()streamrecorder_supported_audio_encoder_cb()Supported audio encoders
streamrecorder_foreach_supported_video_encoder()streamrecorder_supported_video_encoder_cb()Supported video encoders
streamrecorder_foreach_supported_file_format()streamrecorder_supported_file_format_cb()Supported file formats
streamrecorder_foreach_supported_video_resolution()streamrecorder_supported_video_resolution_cb()Supported video resolutions
+ * + */ + + +/** + * @defgroup CAPI_MEDIA_STREAMRECORDER_ATTRIBUTES_MODULE Attributes + * @brief The @ref CAPI_MEDIA_STREAMRECORDER_ATTRIBUTES_MODULE API provides functions to fetch StreamRecorder attributes. + * @ingroup CAPI_MEDIA_STREAMRECORDER_MODULE + * + * @section CAPI_MEDIA_STREAMRECORDER_ATTRIBUTES_MODULE_HEADER Required Header + * \#include + * + * @section CAPI_MEDIA_STREAMRECORDER_ATTRIBUTES_MODULE_OVERVIEW Overview + * The StreamRecorder Attributes API provides functions to get/set basic StreamRecorder attributes. + * + * With the StreamRecorder Attributes API you are able to set and get StreamRecorder attributes like: + *
    + *
  • File name
  • + *
  • File format
  • + *
  • Audio encoder
  • + *
  • Video encoder
  • + *
  • Recording size limit
  • + *
  • Recording time limit
  • + *
  • Audio samplerate
  • + *
  • Audio encoder bitrate
  • + *
  • Video encoder bitrate
  • + *
  • Audio channel
  • + *
+ * + */ + +/** + * @defgroup CAPI_MEDIA_STREAMRECORDER_CALLBACK_MODULE Callback + * @brief The @ref CAPI_MEDIA_STREAMRECORDER_CALLBACK_MODULE API Callbacks from the StreamRecorder frameworks. + * @ingroup CAPI_MEDIA_STREAMRECORDER_MODULE + * + * @section CAPI_MEDIA_STREAMRECORDER_CALLBACK_MODULE_HEADER Required Header + * \#include + * + * @section CAPI_MEDIA_STREAMRECORDER_CALLBACK_MODULE_OVERVIEW Overview + * The StreamRecorder Callback API provides functions status. + * + */ + +/** + * @ingroup CAPI_MEDIA_STREAMRECORDER_MODULE + * @defgroup CAPI_MEDIA_STREAMRECORDER_CAPABILITY_MODULE Capability + * @brief The @ref CAPI_MEDIA_STREAMRECORDER_CAPABILITY_MODULE API provides capability information of the StreamRecorder. + * @section CAPI_MEDIA_STREAMRECORDER_CAPABILITY_MODULE_HEADER Required Header + * \#include + * + * @section CAPI_MEDIA_STREAMRECORDER_CAPABILITY_MODULE_OVERVIEW Overview + * The StreamRecorder Capability API provides functions to obtain capability information of the StreamRecorder. + * + */ + +#endif /* __TIZEN_MEDIA_STREAMRECORDER_DOC_H__ */ + + diff --git a/include/streamrecorder.h b/include/streamrecorder.h new file mode 100644 index 0000000..b9c8653 --- /dev/null +++ b/include/streamrecorder.h @@ -0,0 +1,1103 @@ +/* +* Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved +* +* 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 __TIZEN_MEDIA_STREAMRECORDER_H__ +#define __TIZEN_MEDIA_STREAMRECORDER_H__ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @file streamrecorder.h + * @brief This file contains the Streamrecorder API, related structures and enumerations. + * @since_tizen 3.0 + */ + +/** + * @addtogroup CAPI_MEDIA_STREAMRECORDER_MODULE + * @{ + */ + +#ifndef TIZEN_ERROR_STREAMRECORDER +#define TIZEN_ERROR_STREAMRECORDER -0x01B0000 +#endif /* TIZEN_ERROR_STREAMRECORDER */ + +/** + * @brief The Streamrecorder handle. + * @since_tizen 3.0 + */ +typedef struct streamrecorder_s *streamrecorder_h; + +/** + * @brief Enumeration for the source type. + * @since_tizen 3.0 + */ +typedef enum { + STREAMRECORDER_SOURCE_VIDEO, /**< Video only */ + STREAMRECORDER_SOURCE_AUDIO, /**< Audio only */ + STREAMRECORDER_SOURCE_VIDEO_AUDIO, /**< Video and Audio */ +} streamrecorder_source_e; + +/** + * @brief Enumeration for the pixel format. + * @since_tizen 3.0 + */ +typedef enum { + STREAMRECORDER_VIDEO_SOURCE_FORMAT_INVALID = -1, /**< Invalid pixel format */ + STREAMRECORDER_VIDEO_SOURCE_FORMAT_NV12, /**< NV12 pixel format */ + STREAMRECORDER_VIDEO_SOURCE_FORMAT_NV21, /**< NV12 pixel format */ + STREAMRECORDER_VIDEO_SOURCE_FORMAT_I420, /**< I420 pixel format */ + STREAMRECORDER_VIDEO_SOURCE_FORMAT_NUM /**< Number of the video source format */ +} streamrecorder_video_source_format_e; + +/** + * @brief Enumeration for the file container format. + * @since_tizen 3.0 + */ +typedef enum { + STREAMRECORDER_FILE_FORMAT_3GP, /**< 3GP file format */ + STREAMRECORDER_FILE_FORMAT_MP4, /**< MP4 file format */ + STREAMRECORDER_FILE_FORMAT_AMR, /**< AMR file format */ + STREAMRECORDER_FILE_FORMAT_ADTS, /**< ADTS file format */ + STREAMRECORDER_FILE_FORMAT_WAV, /**< WAV file format */ +} streamrecorder_file_format_e; + +/** + * @brief Enumeration for the audio codec. + * @since_tizen 3.0 + */ +typedef enum { + STREAMRECORDER_AUDIO_CODEC_AMR = 0, /**< AMR codec */ + STREAMRECORDER_AUDIO_CODEC_AAC, /**< AAC codec */ + STREAMRECORDER_AUDIO_CODEC_PCM /**< PCM codec */ +} streamrecorder_audio_codec_e; + +/** + * @brief Enumeration for the video codec. + * @since_tizen 3.0 + */ +typedef enum { + STREAMRECORDER_VIDEO_CODEC_H263, /**< H263 codec */ + STREAMRECORDER_VIDEO_CODEC_MPEG4, /**< MPEG4 codec */ +} streamrecorder_video_codec_e; + +/** + * @brief Enumeration for the recording limit reached. + * @since_tizen 3.0 + */ +typedef enum { + STREAMRECORDER_RECORDING_LIMIT_TYPE_TIME, /**< Time limit (second) of recording file */ + STREAMRECORDER_RECORDING_LIMIT_TYPE_SIZE, /**< Size limit (kilo bytes [KB]) of recording file */ +} streamrecorder_recording_limit_type_e; + +/** + * @brief Enumeration for Streamrecorder error type. + * @since_tizen 3.0 + */ +typedef enum { + STREAMRECORDER_ERROR_NONE = TIZEN_ERROR_NONE, /**< Successful */ + STREAMRECORDER_ERROR_INVALID_PARAMETER = TIZEN_ERROR_INVALID_PARAMETER, /**< Invalid parameter */ + STREAMRECORDER_ERROR_INVALID_STATE = TIZEN_ERROR_STREAMRECORDER | 0x01, /**< Invalid state */ + STREAMRECORDER_ERROR_OUT_OF_MEMORY = TIZEN_ERROR_OUT_OF_MEMORY , /**< Out of memory */ + STREAMRECORDER_ERROR_INVALID_OPERATION = TIZEN_ERROR_INVALID_OPERATION, /**< Internal error */ + STREAMRECORDER_ERROR_OUT_OF_STORAGE = TIZEN_ERROR_STREAMRECORDER | 0x02, /**< Out of storage */ + STREAMRECORDER_ERROR_PERMISSION_DENIED = TIZEN_ERROR_PERMISSION_DENIED, /**< The access to the resources can not be granted */ + STREAMRECORDER_ERROR_NOT_SUPPORTED = TIZEN_ERROR_NOT_SUPPORTED, /**< The feature is not supported */ +} streamrecorder_error_e; + +/** + * @brief Enumeration for the Streamrecorder notification. + * @since_tizen 3.0 + */ +typedef enum { + STREAMRECORDER_NOTIFY_NONE = 0, /**< None */ + STREAMRECORDER_NOTIFY_STATE_CHANGED, /**< The notification of normal state changes */ +} streamrecorder_notify_e; + +/** + * @brief Enumeration for Streamrecorder states. + * @since_tizen 3.0 + */ +typedef enum { + STREAMRECORDER_STATE_NONE, /**< StreamRecorder is not created */ + STREAMRECORDER_STATE_CREATED, /**< StreamRecorder is created, but not prepared */ + STREAMRECORDER_STATE_PREPARED, /**< StreamRecorder is prepared to record */ + STREAMRECORDER_STATE_RECORDING, /**< StreamRecorder is recording media */ + STREAMRECORDER_STATE_PAUSED, /**< StreamRecorder is paused while recording media */ +} streamrecorder_state_e; + +/** + * @} + */ + +/** + * @addtogroup CAPI_MEDIA_STREAMRECORDER_CALLBACK_MODULE + * @{ + */ + +/** + * @brief Called when limitation error occurs while recording. + * @details The callback function is possible to receive three types of limits: time and size. + * @since_tizen 3.0 + * @remarks After being called, recording data except present recorded data will be discarded and not written in the recording file. Also the state of streamrecorder is not changed. + * @param[in] type The imitation type + * @param[in] user_data The user data passed from the callback registration function + * @pre You have to register a callback using streamrecorder_set_recording_limit_reached_cb(). + * @see streamrecorder_set_recording_status_cb() + * @see streamrecorder_set_recording_limit_reached_cb() + * @see streamrecorder_unset_recording_limit_reached_cb() + */ +typedef void (*streamrecorder_recording_limit_reached_cb)(streamrecorder_recording_limit_type_e type, void *user_data); + +/** + * @brief Called to indicate the recording status. + * @since_tizen 3.0 + * @remarks This callback function is repeatedly invoked during the #STREAMRECORDER_STATE_RECORDING state. + * @param[in] elapsed_time The time of the recording (milliseconds) + * @param[in] file_size The size of the recording file (KB) + * @param[in] user_data The user data passed from the callback registration function + * @pre streamrecorder_start() will invoke this callback if you register it using streamrecorder_set_recording_status_cb(). + * @see streamrecorder_set_recording_status_cb() + * @see streamrecorder_unset_recording_status_cb() + * @see streamrecorder_start() + */ +typedef void (*streamrecorder_recording_status_cb)(unsigned long long elapsed_time, unsigned long long file_size, void *user_data); + +/** + * @brief Called when the streamrecorder gets some nofications. + * @since_tizen 3.0 + * @param[in] previous The previous state of the streamrecorder + * @param[in] current The current state of the streamrecorder + * @param[in] notification The notification type of the srecorder + * @param[in] user_data The user data passed from the callback registration function + * @pre This function is required to register a callback using streamrecorder_set_notify_cb(). + * @see streamrecorder_set_notify_cb() + * @see streamrecorder_prepare() + * @see streamrecorder_unprepare() + * @see streamrecorder_start() + * @see streamrecorder_pause() + * @see streamrecorder_commit() + * @see streamrecorder_cancel() + */ +typedef void (*streamrecorder_notify_cb)(streamrecorder_state_e previous, streamrecorder_state_e current, streamrecorder_notify_e notification, void *user_data); + +/** + * @brief Called when the error occurred. + * @since_tizen 3.0 + * @remarks This callback informs about the critical error situation. \n + * When being invoked, user should release the resource and terminate the application. \n + * This error code will be reported. \n + * #STREAMRECORDER_ERROR_INVALID_OPERATION \n + * #STREAMRECORDER_ERROR_OUT_OF_MEMORY + * @param[in] error The error code + * @param[in] current_state The current state of the streamrecorder + * @param[in] user_data The user data passed from the callback registration function + * @pre This callback function is invoked if you register this callback using streamrecorder_set_error_cb(). + * @see streamrecorder_set_error_cb() + * @see streamrecorder_unset_error_cb() + */ +typedef void (*streamrecorder_error_cb)(streamrecorder_error_e error, streamrecorder_state_e current_state, void *user_data); + +/** + * @brief Called iteratively to notify about the buffer has been consumed + * @since_tizen 3.0 + * @remarks The user needs to release consumed buffer if buffer is allocated by user including media packet + * @param[in] buffer The consumed buffer that user pushed + * @param[in] user_data The user data passed + * @see streamrecorder_set_buffer_consume_completed_cb() will invoke this callback. + * @see streamrecorder_unset_buffer_consume_completed_cb() + */ +typedef void (*streamrecorder_consume_completed_cb)(void *buffer, void *user_data); + +/** + * @} + */ + +/** + * @addtogroup CAPI_MEDIA_STREAMRECORDER_CAPABILITY_MODULE + * @{ + */ + +/** + * @brief Called once for each supported video resolution. + * @since_tizen 3.0 + * @param[in] width The video image width + * @param[in] height The video image height + * @param[in] user_data The user data passed from the foreach function + * @return @c true to continue with the next iteration of the loop, \n otherwise @c false to break out of the loop + * @pre streamrecorder_foreach_supported_video_resolution() will invoke this callback. + * @see streamrecorder_foreach_supported_video_resolution() + */ +typedef bool (*streamrecorder_supported_video_resolution_cb)(int width, int height, void *user_data); + +/** + * @brief Called iteratively to notify about the supported file formats. + * @since_tizen 3.0 + * @param[in] format The format of recording files + * @param[in] user_data The user data passed from the foreach function + * @return @c true to continue with the next iteration of the loop, \n otherwise @c false to break out of the loop + * @pre streamrecorder_foreach_supported_file_format() will invoke this callback. + * @see streamrecorder_foreach_supported_file_format() + */ +typedef bool (*streamrecorder_supported_file_format_cb)(streamrecorder_file_format_e format, void *user_data); + +/** + * @brief Called iteratively to notify about the supported audio encoders. + * @since_tizen 3.0 + * @param[in] codec The codec of audio encoder + * @param[in] user_data The user data passed from the foreach function + * @return @c true to continue with the next iteration of the loop, \n otherwise @c false to break out of the loop + * @pre streamrecorder_foreach_supported_audio_encoder() will invoke this callback. + * @see streamrecorder_foreach_supported_audio_encoder() + */ +typedef bool (*streamrecorder_supported_audio_encoder_cb)(streamrecorder_audio_codec_e codec, void *user_data); + +/** + * @brief Called iteratively to notify about the supported video encoders. + * @since_tizen 3.0 + * @param[in] codec The codec of video encoder + * @param[in] user_data The user data passed from the foreach function + * @return @c true to continue with the next iteration of the loop, \n otherwise @c false to break out of the loop + * @pre streamrecorder_foreach_supported_video_encoder() will invoke this callback. + * @see streamrecorder_foreach_supported_video_encoder() + */ +typedef bool (*streamrecorder_supported_video_encoder_cb)(streamrecorder_video_codec_e codec, void *user_data); + +/** + * @} + */ + +/** + * @addtogroup CAPI_MEDIA_STREAMRECORDER_MODULE + * @{ + */ + +/** + * @brief Creates a streamrecorder handle to record a video or audio + * @since_tizen 3.0 + * @remarks You must release @a recorder using streamrecorder_destroy(). + * @param[out] recorder A handle to the streamrecorder + * @return @c 0 on success, otherwise a negative error value + * @retval #STREAMRECORDER_ERROR_NONE Successful + * @retval #STREAMRECORDER_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #STREAMRECORDER_ERROR_OUT_OF_MEMORY Out of memory + * @retval #STREAMRECORDER_ERROR_INVALID_OPERATION Invalid operation + */ +int streamrecorder_create(streamrecorder_h *recorder); + +/** + * @brief Destroys the streamrecorder handle + * @since_tizen 3.0 + * @param[in] recorder The handle to the streamrecorder + * @return @c 0 on success, otherwise a negative error value + * @retval #STREAMRECORDER_ERROR_NONE Successful + * @retval #STREAMRECORDER_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #STREAMRECORDER_ERROR_INVALID_OPERATION Invalid operation + * @retval #STREAMRECORDER_ERROR_INVALID_STATE Invalid state + * @pre The recorder state should be #STREAMRECORDER_STATE_CREATED. + * @post The recorder state will be #STREAMRECORDER_STATE_NONE. + */ +int streamrecorder_destroy(streamrecorder_h recorder); + +/** + * @brief Prepares the streamrecorder for recording. + * @since_tizen 3.0 + * @remarks Before calling the function, it is required to properly set streamrecorder_enable_source_buffer(), + * audio encoder (streamrecorder_set_audio_encoder()), + * video encoder(streamrecorder_set_video_encoder()) and file format (streamrecorder_set_file_format()). + * @param[in] recorder The handle to the streamrecorder + * @return @c 0 on success, otherwise a negative error value + * @retval #STREAMRECORDER_ERROR_NONE Successful + * @retval #STREAMRECORDER_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #STREAMRECORDER_ERROR_INVALID_OPERATION Invalid operation + * @retval #STREAMRECORDER_ERROR_INVALID_STATE Invalid state + * @pre The recorder state should be #STREAMRECORDER_STATE_CREATED. \n + * The streamrecorder_enable_source_buffer() should be invoked before this function. + * @post The streamrecorder state will be #STREAMRECORDER_STATE_PREPARED + * @see streamrecorder_unprepare() + * @see streamrecorder_set_audio_encoder() + * @see streamrecorder_set_video_encoder() + * @see streamrecorder_set_file_format() + */ +int streamrecorder_prepare(streamrecorder_h recorder); + +/** + * @brief Resets the streamrecorder. + * @since_tizen 3.0 + * @param[in] recorder The handle to the streamrecorder + * @return @c 0 on success, otherwise a negative error value + * @retval #STREAMRECORDER_ERROR_NONE Successful + * @retval #STREAMRECORDER_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #STREAMRECORDER_ERROR_INVALID_OPERATION Invalid operation + * @retval #STREAMRECORDER_ERROR_INVALID_STATE Invalid state + * @pre The streamrecorder state should be #STREAMRECORDER_STATE_PREPARED set by streamrecorder_prepare(), streamrecorder_cancel() or streamrecorder_commit(). + * @post The streamrecorder state will be #STREAMRECORDER_STATE_CREATED. + * @see streamrecorder_prepare() + * @see streamrecorder_cancel() + * @see streamrecorder_commit() + */ +int streamrecorder_unprepare(streamrecorder_h recorder); + +/** + * @brief Starts the recording. + * @since_tizen 3.0 + * @remarks If file path has been set to an existing file, this file is removed automatically and updated by new one. \n + * When you want to record audio or video file, you need to add privilege according to rules below additionally. \n + * http://tizen.org/privilege/mediastorage is needed if input or output path are relevant to media storage.\n + * http://tizen.org/privilege/externalstorage is needed if input or output path are relevant to external storage. + * The filename should be set before this function is invoked. + * @param[in] recorder The handle to the streamrecorder + * @return @c 0 on success, otherwise a negative error value + * @retval #STREAMRECORDER_ERROR_NONE Successful + * @retval #STREAMRECORDER_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #STREAMRECORDER_ERROR_INVALID_OPERATION Invalid operation + * @retval #STREAMRECORDER_ERROR_INVALID_STATE Invalid state + * @retval #STREAMRECORDER_ERROR_PERMISSION_DENIED The access to the resources can not be granted + * @pre The streamrecorder state must be #STREAMRECORDER_STATE_PREPARED by streamrecorder_prepare() or #STREAMRECORDER_STATE_PAUSED by streamrecorder_pause(). \n + * The filename should be set by streamrecorder_set_filename(). + * @post The recorder state will be #STREAMRECORDER_STATE_RECORDING. + * @see streamrecorder_pause() + * @see streamrecorder_commit() + * @see streamrecorder_cancel() + * @see streamrecorder_set_audio_encoder() + * @see streamrecorder_set_filename() + * @see streamrecorder_set_file_format() + * @see streamrecorder_recording_status_cb() + * @see streamrecorder_set_filename() + */ +int streamrecorder_start(streamrecorder_h recorder); + +/** + * @brief Pauses the recording. + * @since_tizen 3.0 + * @remarks Recording can be resumed with streamrecorder_start(). + * @param[in] recorder The handle to the streamrecorder + * @return @c 0 on success, otherwise a negative error value + * @retval #STREAMRECORDER_ERROR_NONE Successful + * @retval #STREAMRECORDER_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #STREAMRECORDER_ERROR_INVALID_OPERATION Invalid operation + * @retval #STREAMRECORDER_ERROR_INVALID_STATE Invalid state + * @pre The streamrecorder state must be #STREAMRECORDER_STATE_RECORDING. + * @post The streamrecorder state will be #STREAMRECORDER_STATE_PAUSED. + * @see streamrecorder_pause() + * @see streamrecorder_commit() + * @see streamrecorder_cancel() + */ +int streamrecorder_pause(streamrecorder_h recorder); + +/** + * @brief Stops recording and saves the result. + * @since_tizen 3.0 + * @remarks When you want to record audio or video file, you need to add privilege according to rules below additionally. \n + * http://tizen.org/privilege/mediastorage is needed if input or output path are relevant to media storage.\n + * http://tizen.org/privilege/externalstorage is needed if input or output path are relevant to external storage. + * @param[in] recorder The handle to the streamrecorder + * @return @c 0 on success, otherwise a negative error value + * @retval #STREAMRECORDER_ERROR_NONE Successful + * @retval #STREAMRECORDER_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #STREAMRECORDER_ERROR_INVALID_OPERATION Invalid operation + * @retval #STREAMRECORDER_ERROR_INVALID_STATE Invalid state + * @retval #STREAMRECORDER_ERROR_PERMISSION_DENIED The access to the resources can not be granted + * @pre The streamrecorder state must be #STREAMRECORDER_STATE_RECORDING set by streamrecorder_start() or #STREAMRECORDER_STATE_PAUSED by streamrecorder_pause(). + * @post The streamrecorder state will be #STREAMRECORDER_STATE_PREPARED. + * @see streamrecorder_pause() + * @see streamrecorder_cancel() + * @see streamrecorder_set_filename() + * @see streamrecorder_start() + */ +int streamrecorder_commit(streamrecorder_h recorder); + +/** + * @brief Cancels the recording. + * @details The recording data is discarded and not written in the recording file. + * @since_tizen 3.0 + * @remarks When you want to record audio or video file, you need to add privilege according to rules below additionally. \n + * http://tizen.org/privilege/mediastorage is needed if input or output path are relevant to media storage.\n + * http://tizen.org/privilege/externalstorage is needed if input or output path are relevant to external storage. + * @param[in] recorder The handle to the streamrecorder + * @return @c 0 on success, otherwise a negative error value + * @retval #STREAMRECORDER_ERROR_NONE Successful + * @retval #STREAMRECORDER_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #STREAMRECORDER_ERROR_INVALID_OPERATION Invalid operation + * @retval #STREAMRECORDER_ERROR_INVALID_STATE Invalid state + * @retval #STREAMRECORDER_ERROR_PERMISSION_DENIED The access to the resources can not be granted + * @pre The streamrecorder state must be #STREAMRECORDER_STATE_RECORDING set by streamrecorder_start() or #STREAMRECORDER_STATE_PAUSED by streamrecorder_pause(). + * @post The streamrecorder state will be #STREAMRECORDER_STATE_PREPARED. + * @see streamrecorder_pause() + * @see streamrecorder_commit() + * @see streamrecorder_cancel() + * @see streamrecorder_start() + */ +int streamrecorder_cancel(streamrecorder_h recorder); + +/** + * @brief Pushes buffer to StreamRecorder to record audio/video + * @since_tizen 3.0 + * @remarks When you want to record audio or video file, you need to add privilege according to rules below additionally. \n + * http://tizen.org/privilege/mediastorage is needed if input or output path are relevant to media storage.\n + * http://tizen.org/privilege/externalstorage is needed if input or output path are relevant to external storage. + * @param[in] recorder The handle to the streamrecorder + * @param[in] inbuf The media packet containing buffer and other associated values + * @return @c 0 on success, otherwise a negative error value + * @retval #STREAMRECORDER_ERROR_NONE Successful + * @retval #STREAMRECORDER_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #STREAMRECORDER_ERROR_PERMISSION_DENIED The access to the resources can not be granted + */ +int streamrecorder_push_stream_buffer(streamrecorder_h recorder, media_packet_h inbuf); + +/** + * @brief Sets the video source as live buffer to be used for recording + * @since_tizen 3.0 + * @remarks if you want to enable video or audio or both recording, call before streamrecorder_prepare() + * @param[in] recorder A handle to the streamrecorder + * @param[in] type The type of source input + * @return @c 0 on success, otherwise a negative error value + * @retval #STREAMRECORDER_ERROR_NONE Successful + * @retval #STREAMRECORDER_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #STREAMRECORDER_ERROR_INVALID_STATE Invalid state + * @pre The streamrecorder state must be only #STREAMRECORDER_STATE_CREATED + */ +int streamrecorder_enable_source_buffer(streamrecorder_h recorder, streamrecorder_source_e type); + +/** + * @brief Gets the streamrecorder's current state. + * @since_tizen 3.0 + * @param[in] recorder The handle to the streamrecorder + * @param[out] state The current state of the streamrecorder + * @return @c 0 on success, otherwise a negative error value + * @retval #STREAMRECORDER_ERROR_NONE Successful + * @retval #STREAMRECORDER_ERROR_INVALID_PARAMETER Invalid parameter + */ +int streamrecorder_get_state(streamrecorder_h recorder, streamrecorder_state_e *state); + +/** + * @} + */ + +/** + * @addtogroup CAPI_MEDIA_STREAMRECORDER_ATTRIBUTES_MODULE + * @{ + */ + + +/** + * @brief Sets the file path to record. + * @details This function sets file path which defines where newly recorded data should be stored. + * @since_tizen 3.0 + * @remarks If the same file already exists in the file system, then old file will be overwritten. + * @param[in] recorder The handle to the streamrecorder + * @param[in] path The recording file path + * @return @c 0 on success, otherwise a negative error value + * @retval #STREAMRECORDER_ERROR_NONE Successful + * @retval #STREAMRECORDER_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #STREAMRECORDER_ERROR_INVALID_STATE Invalid state + * @pre The streamrecorder state must be #STREAMRECORDER_STATE_CREATED. \n + * streamrecorder_enable_source_buffer() should be invoked before this function. + * @see streamrecorder_get_filename() + */ +int streamrecorder_set_filename(streamrecorder_h recorder, const char *path); + +/** + * @brief Gets the file path to record. + * @since_tizen 3.0 + * @remarks You must release @a path using free(). + * @param[in] recorder The handle to the streamrecorder + * @param[out] path The recording file path + * @return @c 0 on success, otherwise a negative error value + * @retval #STREAMRECORDER_ERROR_NONE Successful + * @retval #STREAMRECORDER_ERROR_INVALID_PARAMETER Invalid parameter + * streamrecorder_enable_source_buffer() should be invoked before this function. + * @see streamrecorder_set_filename() + */ +int streamrecorder_get_filename(streamrecorder_h recorder, char **path); + +/** + * @brief Sets the file format for recording media stream. + * @since_tizen 3.0 + * @param[in] recorder The handle to the streamrecorder + * @param[in] format The media file format + * @return @c 0 on success, otherwise a negative error value + * @retval #STREAMRECORDER_ERROR_NONE Successful + * @retval #STREAMRECORDER_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #STREAMRECORDER_ERROR_INVALID_STATE Invalid state + * @retval #STREAMRECORDER_ERROR_INVALID_OPERATION Invalid operation + * @pre The streamrecorder state must be #STREAMRECORDER_STATE_CREATED. \n + * streamrecorder_enable_source_buffer() should be invoked before this function. + * @see streamrecorder_get_file_format() + * @see streamrecorder_foreach_supported_file_format() + */ +int streamrecorder_set_file_format(streamrecorder_h recorder, streamrecorder_file_format_e format); + + +/** + * @brief Gets the file format for recording media stream. + * @since_tizen 3.0 + * @param[in] recorder The handle to the streamrecorder + * @param[out] format The media file format + * @return @c 0 on success, otherwise a negative error value + * @retval #STREAMRECORDER_ERROR_NONE Successful + * @retval #STREAMRECORDER_ERROR_INVALID_PARAMETER Invalid parameter + * @pre The streamrecorder_enable_source_buffer() should be invoked before this function. + * @see streamrecorder_set_file_format() + * @see streamrecorder_foreach_supported_file_format() + */ +int streamrecorder_get_file_format(streamrecorder_h recorder, streamrecorder_file_format_e *format); + + +/** + * @brief Sets the audio codec for encoding an audio stream. + * @since_tizen 3.0 + * @remarks You can get available audio encoders by using streamrecorder_foreach_supported_audio_encoder(). \n + * @param[in] recorder The handle to the streamrecorder + * @param[in] codec The audio codec + * @return @c 0 on success, otherwise a negative error value + * @retval #STREAMRECORDER_ERROR_NONE Successful + * @retval #STREAMRECORDER_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #STREAMRECORDER_ERROR_INVALID_STATE Invalid state + * @retval #STREAMRECORDER_ERROR_NOT_SUPPORTED The feature is not supported + * @retval #STREAMRECORDER_ERROR_INVALID_OPERATION Invalid operation + * @pre The streamrecorder state must be #STREAMRECORDER_STATE_CREATED. \n + * streamrecorder_enable_source_buffer() should be invoked before this function. + * @see streamrecorder_get_audio_encoder() + * @see streamrecorder_foreach_supported_audio_encoder() + */ +int streamrecorder_set_audio_encoder(streamrecorder_h recorder, streamrecorder_audio_codec_e codec); + +/** + * @brief Gets the audio codec for encoding an audio stream. + * @since_tizen 3.0 + * @param[in] recorder The handle to the streamrecorder + * @param[out] codec The audio codec + * @return @c 0 on success, otherwise a negative error value + * @retval #STREAMRECORDER_ERROR_NONE Successful + * @retval #STREAMRECORDER_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #STREAMRECORDER_ERROR_NOT_SUPPORTED The feature is not supported + * @pre The streamrecorder_enable_source_buffer() should be invoked before this function. + * @see streamrecorder_set_audio_encoder() + * @see streamrecorder_foreach_supported_audio_encoder() + */ +int streamrecorder_get_audio_encoder(streamrecorder_h recorder, streamrecorder_audio_codec_e *codec); + +/** + * @brief Sets the resolution of the video recording. + * @since_tizen 3.0 + * @remarks This function should be called before recording (streamrecorder_start()). + * @param[in] recorder The handle to the streamrecorder + * @param[in] width The input width + * @param[in] height The input height + * @return @c 0 on success, otherwise a negative error value + * @retval #STREAMRECORDER_ERROR_NONE Successful + * @retval #STREAMRECORDER_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #STREAMRECORDER_ERROR_INVALID_STATE Invalid state + * @retval #STREAMRECORDER_ERROR_NOT_SUPPORTED The feature is not supported + * @pre The streamrecorder state must be #STREAMRECORDER_STATE_CREATED. \n + * streamrecorder_enable_source_buffer() should be invoked before this function. + * @see streamrecorder_start() + * @see streamrecorder_get_video_resolution() + * @see streamrecorder_foreach_supported_video_resolution() + */ +int streamrecorder_set_video_resolution(streamrecorder_h recorder, int width, int height); + +/** + * @brief Gets the resolution of the video recording. + * @since_tizen 3.0 + * @param[in] recorder The handle to the streamrecorder + * @param[out] width The video width + * @param[out] height The video height + * @return @c 0 on success, otherwise a negative error value + * @retval #STREAMRECORDER_ERROR_NONE Successful + * @retval #STREAMRECORDER_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #STREAMRECORDER_ERROR_NOT_SUPPORTED The feature is not supported + * @pre The streamrecorder_enable_source_buffer() should be invoked before this function. + * @see streamrecorder_set_video_resolution() + * @see streamrecorder_foreach_supported_video_resolution() + */ +int streamrecorder_get_video_resolution(streamrecorder_h recorder, int *width, int *height); + +/** + * @brief Sets the video codec for encoding video stream. + * @since_tizen 3.0 + * @remarks You can get available video encoders by using recorder_foreach_supported_video_encoder(). + * @param[in] recorder The handle to the streamrecorder + * @param[in] codec The video codec + * @return @c 0 on success, otherwise a negative error value + * @retval #STREAMRECORDER_ERROR_NONE Successful + * @retval #STREAMRECORDER_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #STREAMRECORDER_ERROR_INVALID_STATE Invalid state + * @retval #STREAMRECORDER_ERROR_NOT_SUPPORTED The feature is not supported + * @pre The streamrecorder state must be #STREAMRECORDER_STATE_CREATED. \n + * streamrecorder_enable_source_buffer() should be invoked before this function. + * @see streamrecorder_get_video_encoder() + * @see streamrecorder_foreach_supported_video_encoder() + */ +int streamrecorder_set_video_encoder(streamrecorder_h recorder, streamrecorder_video_codec_e codec); + +/** + * @brief Gets the video codec for encoding video stream. + * @since_tizen 3.0 + * @param[in] recorder The handle to the streamrecorder + * @param[out] codec The video codec + * @return @c 0 on success, otherwise a negative error value + * @retval #STREAMRECORDER_ERROR_NONE Successful + * @retval #STREAMRECORDER_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #STREAMRECORDER_ERROR_NOT_SUPPORTED The feature is not supported + * @pre The streamrecorder_enable_source_buffer() should be invoked before this function. + * @see streamrecorder_set_video_encoder() + * @see streamrecorder_foreach_supported_video_encoder() + */ +int streamrecorder_get_video_encoder(streamrecorder_h recorder, streamrecorder_video_codec_e *codec); + +/** + * @brief Sets the recording frame rate. + * @since_tizen 3.0 + * @remarks This function should be called before prepared state. + * @param[in] recorder The handle to the streamrecorder + * @param[in] framerate The frame rate for recording + * @return @c 0 on success, otherwise a negative error value + * @retval #STREAMRECORDER_ERROR_NONE Successful + * @retval #STREAMRECORDER_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #STREAMRECORDER_ERROR_INVALID_STATE Invalid state + * @see streamrecorder_get_video_framerate() + */ +int streamrecorder_set_video_framerate(streamrecorder_h recorder, int framerate); + +/** + * @brief Gets the recording frame rate. + * @since_tizen 3.0 + * @param[in] recorder The handle to the camera + * @param[out] framerate The frame rate for recording that already is set + * @return @c 0 on success, otherwise a negative error value + * @retval #STREAMRECORDER_ERROR_NONE Successful + * @retval #STREAMRECORDER_ERROR_INVALID_PARAMETER Invalid parameter + * @see streamrecorder_set_video_framerate() + */ +int streamrecorder_get_video_framerate(streamrecorder_h recorder, int *framerate); + +/** + * @brief Sets the video source format. + * @since_tizen 3.0 + * @remarks This function should be called before prepared state. + * @param[in] recorder The handle to the streamrecorder + * @param[in] format The color type of video source + * @return @c 0 on success, otherwise a negative error value + * @retval #STREAMRECORDER_ERROR_NONE Successful + * @retval #STREAMRECORDER_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #STREAMRECORDER_ERROR_INVALID_STATE Invalid state + * @see streamrecorder_get_video_source_format() + */ +int streamrecorder_set_video_source_format(streamrecorder_h recorder, streamrecorder_video_source_format_e format); + +/** + * @brief Gets the video source format. + * @since_tizen 3.0 + * @remarks This function should be called before prepared state. + * @param[in] recorder The handle to the streamrecorder + * @param[out] format The color type of video source that already is set + * @return @c 0 on success, otherwise a negative error value + * @retval #STREAMRECORDER_ERROR_NONE Successful + * @retval #STREAMRECORDER_ERROR_INVALID_PARAMETER Invalid parameter + * @see streamrecorder_set_video_source_format() + */ +int streamrecorder_get_video_source_format(streamrecorder_h recorder, streamrecorder_video_source_format_e *format); + +/** + * @brief Sets the maximum size of a recording file. + * @since_tizen 3.0 + * @remarks After reaching the limitation, the recording data is discarded and not written in the recording file. + * @param[in] recorder The handle to the streamrecorder + * @param[in] type The recording limit type + * @param[in] limit If limit type is STREAMRECORDER_RECORDING_LIMIT_TYPE_SIZE, the limit value is the maximum size of the recording file(KB), \n + * otherwise limit value is the maximum time of the recording file (in seconds) \n + * @c 0 means unlimited recording size or time. + * @return @c 0 on success, otherwise a negative error value + * @retval #STREAMRECORDER_ERROR_NONE Successful + * @retval #STREAMRECORDER_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #STREAMRECORDER_ERROR_INVALID_STATE Invalid state + * @pre The streamrecorder state must be #STREAMRECORDER_STATE_CREATED. \n + * streamrecorder_enable_source_buffer() should be invoked before this function. + * @see streamrecorder_get_recording_limit() + */ +int streamrecorder_set_recording_limit(streamrecorder_h recorder, streamrecorder_recording_limit_type_e type, int limit); + +/** + * @brief Gets the maximum size of a recording file. + * @since_tizen 3.0 + * @param[in] recorder The handle to the streamrecorder + * @param[in] type The recording limit type + * @param[out] limit If limit type is STREAMRECORDER_RECORDING_LIMIT_TYPE_SIZE, the limit value is the maximum size of the recording file(KB), \n + * otherwise limit value is the maximum time of the recording file (in seconds) \n + * @c 0 means unlimited recording size or time. + * @return @c 0 on success, otherwise a negative error value + * @retval #STREAMRECORDER_ERROR_NONE Successful + * @retval #STREAMRECORDER_ERROR_INVALID_PARAMETER Invalid parameter + * @pre The streamrecorder_enable_source_buffer() should be invoked before this function. + * @see streamrecorder_set_recording_limit() + */ +int streamrecorder_get_recording_limit(streamrecorder_h recorder, streamrecorder_recording_limit_type_e type, int *limit); + +/** + * @brief Sets the sampling rate of an audio stream. + * @since_tizen 3.0 + * @param[in] recorder The handle to the streamrecorder + * @param[in] samplerate The sample rate in Hertz + * @return @c 0 on success, otherwise a negative error value + * @retval #STREAMRECORDER_ERROR_NONE Successful + * @retval #STREAMRECORDER_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #STREAMRECORDER_ERROR_INVALID_STATE Invalid state + * @pre The streamrecorder state must be #STREAMRECORDER_STATE_CREATED. \n + * streamrecorder_enable_source_buffer() should be invoked before this function. + * @see streamrecorder_get_audio_samplerate() + */ +int streamrecorder_set_audio_samplerate(streamrecorder_h recorder, int samplerate); + +/** + * @brief Gets the sampling rate of an audio stream. + * @since_tizen 3.0 + * @param[in] recorder The handle to the streamrecorder + * @param[out] samplerate The sample rate in Hertz + * @return @c 0 on success, otherwise a negative error value + * @retval #STREAMRECORDER_ERROR_NONE Successful + * @retval #STREAMRECORDER_ERROR_INVALID_PARAMETER Invalid parameter + * @pre The streamrecorder_enable_source_buffer() should be invoked before this function. + * @see streamrecorder_set_audio_samplerate() + */ +int streamrecorder_get_audio_samplerate(streamrecorder_h recorder, int *samplerate); + +/** + * @brief Sets the bitrate of an audio encoder. + * @since_tizen 3.0 + * @param[in] recorder The handle to the streamrecorder + * @param[in] bitrate The bitrate (for mms : 12200[bps], normal : 288000[bps]) + * @return @c 0 on success, otherwise a negative error value + * @retval #STREAMRECORDER_ERROR_NONE Successful + * @retval #STREAMRECORDER_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #STREAMRECORDER_ERROR_INVALID_STATE Invalid state + * @pre The streamrecorder state must be #STREAMRECORDER_STATE_CREATED. \n + * streamrecorder_enable_source_buffer() should be invoked before this function. + * @see streamrecorder_get_audio_encoder_bitrate() + */ +int streamrecorder_set_audio_encoder_bitrate(streamrecorder_h recorder, int bitrate); + +/** + * @brief Sets the bitrate of a video encoder. + * @since_tizen 3.0 + * @param[in] recorder The handle to the streamrecorder + * @param[in] bitrate The bitrate in bits per second + * @return @c 0 on success, otherwise a negative error value + * @retval #STREAMRECORDER_ERROR_NONE Successful + * @retval #STREAMRECORDER_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #STREAMRECORDER_ERROR_INVALID_STATE Invalid state + * @pre The streamrecorder state must be #STREAMRECORDER_STATE_CREATED. \n + * streamrecorder_enable_source_buffer() should be invoked before this function. + * @see streamrecorder_get_video_encoder_bitrate() + */ +int streamrecorder_set_video_encoder_bitrate(streamrecorder_h recorder, int bitrate); + +/** + * @brief Gets the bitrate of an audio encoder. + * @since_tizen 3.0 + * @param[in] recorder The handle to the streamrecorder + * @param[out] bitrate The bitrate in bits per second + * @return @c 0 on success, otherwise a negative error value + * @retval #STREAMRECORDER_ERROR_NONE Successful + * @retval #STREAMRECORDER_ERROR_INVALID_PARAMETER Invalid parameter + * @pre The streamrecorder_enable_source_buffer() should be invoked before this function. + * @see streamrecorder_set_audio_encoder_bitrate() + */ +int streamrecorder_get_audio_encoder_bitrate(streamrecorder_h recorder, int *bitrate); + +/** + * @brief Gets the bitrate of a video encoder. + * @since_tizen 3.0 + * @param[in] recorder The handle to the streamrecorder + * @param[out] bitrate The bitrate in bits per second + * @return @c 0 on success, otherwise a negative error value + * @retval #STREAMRECORDER_ERROR_NONE Successful + * @retval #STREAMRECORDER_ERROR_INVALID_PARAMETER Invalid parameter + * @pre The streamrecorder_enable_source_buffer() should be invoked before this function. + * @see streamrecorder_set_audio_encoder_bitrate() + */ +int streamrecorder_get_video_encoder_bitrate(streamrecorder_h recorder, int *bitrate); + +/** + * @brief Sets the number of the audio channel. + * @since_tizen 3.0 + * @remarks This attribute is applied only in STREAMRECORDER_STATE_CREATED state. \n + * For mono recording, setting channel to @c 1. \n + * For stereo recording, setting channel to @c 2. + * @param[in] recorder The handle to the streamrecorder + * @param[in] channel_count The number of the audio channel + * @return @c 0 on success, otherwise a negative error value + * @retval #STREAMRECORDER_ERROR_NONE Successful + * @retval #STREAMRECORDER_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #STREAMRECORDER_ERROR_INVALID_STATE Invalid state + * @pre The streamrecorder state must be #STREAMRECORDER_STATE_CREATED.\n + * streamrecorder_enable_source_buffer() should be invoked before this function. + * @see streamrecorder_get_audio_channel() + */ +int streamrecorder_set_audio_channel(streamrecorder_h recorder, int channel_count); + +/** + * @brief Gets the number of the audio channel. + * @since_tizen 3.0 + * @param[in] recorder The handle to the streamrecorder + * @param[out] channel_count The number of the audio channel + * @return @c 0 on success, otherwise a negative error value + * @retval #STREAMRECORDER_ERROR_NONE Successful + * @retval #STREAMRECORDER_ERROR_INVALID_PARAMETER Invalid parameter + * @pre The streamrecorder_enable_source_buffer() should be invoked before this function. + * @see streamrecorder_set_audio_channel() + */ +int streamrecorder_get_audio_channel(streamrecorder_h recorder, int *channel_count); + +/** + * @} + */ + +/** + * @addtogroup CAPI_MEDIA_STREAMRECORDER_CAPABILITY_MODULE + * @{ + */ + + +/** + * @brief Retrieves all supported file formats by invoking a specific callback for each supported file format. + * @since_tizen 3.0 + * @param[in] recorder The handle to the streamrecorder + * @param[in] callback The iteration callback + * @param[in] user_data The user data to be passed to the callback function + * @return @c 0 on success, otherwise a negative error value + * @retval #STREAMRECORDER_ERROR_NONE Successful + * @retval #STREAMRECORDER_ERROR_INVALID_PARAMETER Invalid parameter + * @post streamrecorder_supported_file_format_cb() will be invoked. + * @see streamrecorder_get_file_format() + * @see streamrecorder_set_file_format() + * @see streamrecorder_supported_file_format_cb() + */ +int streamrecorder_foreach_supported_file_format(streamrecorder_h recorder, streamrecorder_supported_file_format_cb callback, void *user_data); + +/** + * @brief Retrieves all supported audio encoders by invoking a specific callback for each supported audio encoder. + * @since_tizen 3.0 + * @param[in] recorder The handle to the streamrecorder + * @param[in] callback The iteration callback + * @param[in] user_data The user data to be passed to the callback function + * @return @c 0 on success, otherwise a negative error value + * @retval #STREAMRECORDER_ERROR_NONE Successful + * @retval #STREAMRECORDER_ERROR_INVALID_PARAMETER Invalid parameter + * @post streamrecorder_supported_audio_encoder_cb() will be invoked. + * @see streamrecorder_set_audio_encoder() + * @see streamrecorder_get_audio_encoder() + * @see streamrecorder_supported_audio_encoder_cb() + */ +int streamrecorder_foreach_supported_audio_encoder(streamrecorder_h recorder, streamrecorder_supported_audio_encoder_cb callback, void *user_data); + +/** + * @brief Retrieves all supported video encoders by invoking a specific callback for each supported video encoder. + * @since_tizen 3.0 + * @param[in] recorder The handle to the streamrecorder + * @param[in] callback The iteration callback + * @param[in] user_data The user data to be passed to the callback function + * @return @c 0 on success, otherwise a negative error value + * @retval #STREAMRECORDER_ERROR_NONE Successful + * @retval #STREAMRECORDER_ERROR_INVALID_PARAMETER Invalid parameter + * @post streamrecorder_supported_video_encoder_cb() will be invoked. + * @see streamrecorder_set_video_encoder() + * @see streamrecorder_get_video_encoder() + * @see streamrecorder_supported_video_encoder_cb() + */ +int streamrecorder_foreach_supported_video_encoder(streamrecorder_h recorder, streamrecorder_supported_video_encoder_cb callback, void *user_data); + +/** + * @brief Retrieves all supported video resolutions by invoking callback function once for each supported video resolution. + * @since_tizen 3.0 + * @param[in] recorder The handle to the streamrecorder + * @param[in] foreach_cb The callback function to be invoked + * @param[in] user_data The user data to be passed to the callback function + * @return @c 0 on success, otherwise a negative error value + * @retval #STREAMRECORDER_ERROR_NONE Successful + * @retval #STREAMRECORDER_ERROR_INVALID_PARAMETER Invalid parameter + * @post This function invokes streamrecorder_supported_video_resolution_cb() repeatedly to retrieve each supported video resolution. + * @see streamrecorder_set_video_resolution() + * @see streamrecorder_get_video_resolution() + * @see streamrecorder_supported_video_resolution_cb() + */ +int streamrecorder_foreach_supported_video_resolution(streamrecorder_h recorder, + streamrecorder_supported_video_resolution_cb foreach_cb, void *user_data); + +/** + * @} + */ + +/** + * @addtogroup CAPI_MEDIA_STREAMRECORDER_CALLBACK_MODULE + * @{ + */ + + +/** + * @brief Registers the callback function that will be invoked when the streamrecorder get some notification. + * @since_tizen 3.0 + * @param[in] recorder The handle to the streamrecorder + * @param[in] callback The function pointer of user callback + * @param[in] user_data The user data to be passed to the callback function + * @return @c 0 on success, otherwise a negative error value + * @retval #STREAMRECORDER_ERROR_NONE Successful + * @retval #STREAMRECORDER_ERROR_INVALID_PARAMETER Invalid parameter + * @post streamrecorder_notify_cb() will be invoked. + * @see streamrecorder_unset_notify_cb() + * @see streamrecorder_notify_cb() + */ +int streamrecorder_set_notify_cb(streamrecorder_h recorder, streamrecorder_notify_cb callback, void *user_data); + +/** + * @brief Unregisters the callback function. + * @since_tizen 3.0 + * @param[in] recorder The handle to the streamrecorder + * @return @c 0 on success, otherwise a negative error value + * @retval #STREAMRECORDER_ERROR_NONE Successful + * @retval #STREAMRECORDER_ERROR_INVALID_PARAMETER Invalid parameter + * @see streamrecorder_set_notify_cb() + */ +int streamrecorder_unset_notify_cb(streamrecorder_h recorder); + +/** + * @brief Registers a callback function to be invoked when the recording information changes. + * @since_tizen 3.0 + * @param[in] recorder The handle to the streamrecorder + * @param[in] callback The function pointer of user callback + * @param[in] user_data The user data to be passed to the callback function + * @return @c 0 on success, otherwise a negative error value + * @retval #STREAMRECORDER_ERROR_NONE Successful + * @retval #STREAMRECORDER_ERROR_INVALID_PARAMETER Invalid parameter + * @post streamrecorder_recording_status_cb() will be invoked. + * @see streamrecorder_unset_recording_status_cb() + * @see streamrecorder_recording_status_cb() + */ +int streamrecorder_set_recording_status_cb(streamrecorder_h recorder, streamrecorder_recording_status_cb callback, void *user_data); + +/** + * @brief Unregisters the callback function. + * @since_tizen 3.0 + * @param[in] recorder The handle to the streamrecorder + * @return @c 0 on success, otherwise a negative error value + * @retval #STREAMRECORDER_ERROR_NONE Successful + * @retval #STREAMRECORDER_ERROR_INVALID_PARAMETER Invalid parameter + * @see streamrecorder_set_recording_status_cb() + */ +int streamrecorder_unset_recording_status_cb(streamrecorder_h recorder); + +/** + * @brief Registers the callback function to be run when reached the recording limit. + * @since_tizen 3.0 + * @param[in] recorder The handle to treamrecorder + * @param[in] callback The function pointer of user callback + * @param[in] user_data The user data to be passed to the callback function + * @return @c 0 on success, otherwise a negative error value + * @retval #STREAMRECORDER_ERROR_NONE Successful + * @retval #STREAMRECORDER_ERROR_INVALID_PARAMETER Invalid parameter + * @post streamrecorder_recording_limit_reached_cb() will be invoked. + * @see streamrecorder_unset_recording_limit_reached_cb() + * @see streamrecorder_set_size_limit() + * @see streamrecorder_set_time_limit() + * @see streamrecorder_recording_limit_reached_cb() + */ +int streamrecorder_set_recording_limit_reached_cb(streamrecorder_h recorder, streamrecorder_recording_limit_reached_cb callback, void *user_data); + +/** + * @brief Unregisters the callback function. + * @since_tizen 3.0 + * @param[in] recorder The handle to the streamrecorder + * @return @c 0 on success, otherwise a negative error value + * @retval #STREAMRECORDER_ERROR_NONE Successful + * @retval #STREAMRECORDER_ERROR_INVALID_PARAMETER Invalid parameter + * @see streamrecorder_set_recording_limit_reached_cb() + */ +int streamrecorder_unset_recording_limit_reached_cb(streamrecorder_h recorder); + +/** + * @brief Registers a callback function to be called when an asynchronous operation error occurred. + * @since_tizen 3.0 + * @remarks This callback informs critical error situation.\n + * When this callback is invoked, user should release the resource and terminate the application. \n + * These error codes will occur. \n + * #STREAMRECORDER_ERROR_INVALID_OPERATION \n + * #STREAMRECORDER_ERROR_OUT_OF_MEMORY + * @param[in] recorder The handle to the streamrecorder + * @param[in] callback The callback function to register + * @param[in] user_data The user data to be passed to the callback function + * @return @c 0 on success, otherwise a negative error value + * @retval #STREAMRECORDER_ERROR_NONE Successful + * @retval #STREAMRECORDER_ERROR_INVALID_PARAMETER Invalid parameter + * @post This function will invoke streamrecorder_error_cb() when an asynchronous operation error occur. + * @see streamrecorder_unset_error_cb() + * @see streamrecorder_error_cb() + */ +int streamrecorder_set_error_cb(streamrecorder_h recorder, streamrecorder_error_cb callback, void *user_data); + + +/** + * @brief Unregisters the callback function. + * @since_tizen 3.0 + * @param[in] recorder The handle to the streamrecorder + * @return @c on success, otherwise a negative error value + * @retval #STREAMRECORDER_ERROR_NONE Successful + * @retval #STREAMRECORDER_ERROR_INVALID_PARAMETER Invalid parameter + * @see streamrecorder_set_error_cb() + */ +int streamrecorder_unset_error_cb(streamrecorder_h recorder); + +/** + * @brief Registers a callback function to be called when asynchronous buffers are consumed. + * @since_tizen 3.0 + * @remarks This callback informs to user dealloc buffer.\n + * When this callback is invoked, user should release the buffer or media packet. \n + * @param[in] recorder The handle to the streamrecorder + * @param[in] callback The callback function to register + * @param[in] user_data The user data to be passed to the callback function + * @return @c 0 on success, otherwise a negative error value + * @retval #STREAMRECORDER_ERROR_NONE Successful + * @retval #STREAMRECORDER_ERROR_INVALID_PARAMETER Invalid parameter + * @see streamrecorder_unset_buffer_consume_completed_cb() + * @see streamrecorder_push_stream_buffer() + */ +int streamrecorder_set_buffer_consume_completed_cb(streamrecorder_h recorder, streamrecorder_consume_completed_cb callback, void *user_data); + +/** + * @brief Unregisters the callback function. + * @since_tizen 3.0 + * @param[in] recorder The handle to the streamrecorder + * @return @c on success, otherwise a negative error value + * @retval #STREAMRECORDER_ERROR_NONE Successful + * @retval #STREAMRECORDER_ERROR_INVALID_PARAMETER Invalid parameter + * @see streamrecorder_set_buffer_consume_completed_cb() + */ +int streamrecorder_unset_buffer_consume_completed_cb(streamrecorder_h recorder); + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __TIZEN_MEDIA_STREAMRECORDER_H__ */ + diff --git a/include/streamrecorder_private.h b/include/streamrecorder_private.h new file mode 100644 index 0000000..223ece6 --- /dev/null +++ b/include/streamrecorder_private.h @@ -0,0 +1,95 @@ +/* +* Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved +* +* 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 __TIZEN_MEDIA_STREAMRECORDER_PRIVATE_H__ +#define __TIZEN_MEDIA_STREAMRECORDER_PRIVATE_H__ + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum { + _STREAMRECORDER_EVENT_TYPE_NOTIFY, + _STREAMRECORDER_EVENT_TYPE_RECORDING_LIMITED, + _STREAMRECORDER_EVENT_TYPE_RECORDING_STATUS, + _STREAMRECORDER_EVENT_TYPE_ERROR, + _STREAMRECORDER_EVENT_TYPE_CONSUME_COMPLETE, + _STREAMRECORDER_EVENT_TYPE_NUM +}_streamrecorder_event_e; + +typedef struct { + MMHandleType mm_handle; + void* user_cb[_STREAMRECORDER_EVENT_TYPE_NUM]; + void* user_data[_STREAMRECORDER_EVENT_TYPE_NUM]; + unsigned int state; + _streamrecorder_event_e type; + double last_max_input_level; +}streamrecorder_s; + +int __convert_streamrecorder_error_code(const char *func, int code); +int _streamrecorder_set_videosource_buffer(streamrecorder_h recorder); +int _streamrecorder_set_audiosource_buffer(streamrecorder_h recorder); +int _streamrecorder_get_state(streamrecorder_h recorder, streamrecorder_state_e *state); +int _streamrecorder_destroy(streamrecorder_h recorder); +int _streamrecorder_prepare(streamrecorder_h recorder); +int _streamrecorder_unprepare(streamrecorder_h recorder); +int _streamrecorder_start(streamrecorder_h recorder); +int _streamrecorder_pause(streamrecorder_h recorder); +int _streamrecorder_commit(streamrecorder_h recorder); +int _streamrecorder_cancel(streamrecorder_h recorder); +int _streamrecorder_set_video_framerate(streamrecorder_h recorder, int framerate); +int _streamrecorder_get_video_framerate(streamrecorder_h recorder, int *framerate); +int _streamrecorder_set_video_source_format(streamrecorder_h recorder, int format); +int _streamrecorder_get_video_source_format(streamrecorder_h recorder, int *format); +int _streamrecorder_set_video_resolution(streamrecorder_h recorder, int width, int height); +int _streamrecorder_get_video_resolution(streamrecorder_h recorder, int *width, int *height); +int _streamrecorder_foreach_supported_video_resolution(streamrecorder_h recorder,streamrecorder_supported_video_resolution_cb foreach_cb, void *user_data); +int _streamrecorder_set_filename(streamrecorder_h recorder, const char *filename); +int _streamrecorder_get_filename(streamrecorder_h recorder, char **filename); +int _streamrecorder_set_file_format(streamrecorder_h recorder, streamrecorder_file_format_e format); +int _streamrecorder_get_file_format(streamrecorder_h recorder, streamrecorder_file_format_e *format); +int _streamrecorder_foreach_supported_file_format(streamrecorder_h recorder, streamrecorder_supported_file_format_cb foreach_cb, void *user_data); +int _streamrecorder_set_size_limit(streamrecorder_h recorder, int kbyte); +int _streamrecorder_set_time_limit(streamrecorder_h recorder, int second); +int _streamrecorder_set_audio_encoder(streamrecorder_h recorder, streamrecorder_audio_codec_e codec); +int _streamrecorder_get_audio_encoder(streamrecorder_h recorder, streamrecorder_audio_codec_e *codec); +int _streamrecorder_set_video_encoder(streamrecorder_h recorder, streamrecorder_video_codec_e codec); +int _streamrecorder_get_video_encoder(streamrecorder_h recorder, streamrecorder_video_codec_e *codec); +int _streamrecorder_set_audio_samplerate(streamrecorder_h recorder, int samplerate); +int _streamrecorder_set_audio_encoder_bitrate(streamrecorder_h recorder, int bitrate); +int _streamrecorder_set_video_encoder_bitrate(streamrecorder_h recorder, int bitrate); +int _streamrecorder_get_size_limit(streamrecorder_h recorder, int *kbyte); +int _streamrecorder_get_time_limit(streamrecorder_h recorder, int *second); +int _streamrecorder_get_audio_samplerate(streamrecorder_h recorder, int *samplerate); +int _streamrecorder_get_audio_encoder_bitrate(streamrecorder_h recorder, int *bitrate); +int _streamrecorder_get_video_encoder_bitrate(streamrecorder_h recorder, int *bitrate); +int _streamrecorder_foreach_supported_audio_encoder(streamrecorder_h recorder, streamrecorder_supported_audio_encoder_cb foreach_cb, void *user_data); +int _streamrecorder_foreach_supported_video_encoder(streamrecorder_h recorder, streamrecorder_supported_video_encoder_cb foreach_cb, void *user_data); +int _streamrecorder_set_audio_channel(streamrecorder_h recorder, int channel_count); +int _streamrecorder_get_audio_channel(streamrecorder_h recorder, int *channel_count); +#ifdef __cplusplus +} +#endif + +#endif //__TIZEN_MEDIA_STREAMRECORDER_PRIVATE_H__ + + diff --git a/packaging/capi-media-streamrecorder.spec b/packaging/capi-media-streamrecorder.spec new file mode 100644 index 0000000..4182c63 --- /dev/null +++ b/packaging/capi-media-streamrecorder.spec @@ -0,0 +1,65 @@ +Name: capi-media-streamrecorder +Summary: A Streamrecorder library in Tizen Native API +Version: 0.0.1 +Release: 0 +Group: Multimedia/Other +License: Apache-2.0 +Source0: %{name}-%{version}.tar.gz +BuildRequires: cmake +BuildRequires: pkgconfig(dlog) +Buildrequires: pkgconfig(mm-streamrecorder) +BuildRequires: pkgconfig(capi-base-common) +BuildRequires: pkgconfig(capi-media-tool) +BuildRequires: pkgconfig(capi-media-audio-io) +BuildRequires: pkgconfig(libtbm) +Requires(post): /sbin/ldconfig +Requires(postun): /sbin/ldconfig + +%description +A StreamRecorder library in Tizen Native API to record live buffer sent by the application + + +%package devel +Summary: A StreamRecorder library in Tizen Native API (Development) +Requires: %{name} = %{version}-%{release} + + +%description devel +A MediaStreamRecorder library in Tizen Native API Development Package to record live buffer + + +%prep +%setup -q + + +%build +MAJORVER=`echo %{version} | awk 'BEGIN {FS="."}{print $1}'` +%cmake . -DCMAKE_INSTALL_PREFIX=%{_prefix} -DFULLVER=%{version} -DMAJORVER=${MAJORVER} + + +make %{?jobs:-j%jobs} + + +%install +rm -rf %{buildroot} +%make_install +mkdir -p %{buildroot}%{_datadir}/license +cp LICENSE.APLv2 %{buildroot}%{_datadir}/license/%{name} + + +%post -p /sbin/ldconfig + + +%postun -p /sbin/ldconfig + +%files +%manifest capi-media-streamrecorder.manifest +%{_libdir}/libcapi-media-streamrecorder.so.* +%{_datadir}/license/%{name} +%{_bindir}/* + +%files devel +%{_includedir}/media/streamrecorder.h +%{_libdir}/pkgconfig/*.pc +%{_libdir}/libcapi-media-streamrecorder.so + diff --git a/src/streamrecorder.c b/src/streamrecorder.c new file mode 100644 index 0000000..380aea9 --- /dev/null +++ b/src/streamrecorder.c @@ -0,0 +1,957 @@ +/* +* Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved +* +* 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef LOG_TAG +#undef LOG_TAG +#endif +#define LOG_TAG "TIZEN_N_STREAMRECORDER" + +static int __mm_streamrecorder_msg_cb(int message, void *param, void *user_data); + + +int streamrecorder_create(streamrecorder_h *recorder) +{ + int ret = STREAMRECORDER_ERROR_NONE; + + streamrecorder_s *handle = NULL; + handle = (streamrecorder_s *)malloc(sizeof(streamrecorder_s)); + if (handle == NULL) { + LOGE("[%s] malloc error", __func__); + return STREAMRECORDER_ERROR_OUT_OF_MEMORY; + } + + memset(handle, 0 , sizeof(streamrecorder_s)); + + ret = mm_streamrecorder_create(&handle->mm_handle); + if (ret != MM_ERROR_NONE) { + free(handle); + LOGE("[%s] mm_streamrecorder_create fail", __func__); + return __convert_streamrecorder_error_code(__func__, ret); + } + + mm_streamrecorder_set_message_callback(handle->mm_handle, __mm_streamrecorder_msg_cb, (void *)handle); + + *recorder = (streamrecorder_h)handle; + return ret; +} + +int streamrecorder_get_state(streamrecorder_h recorder, streamrecorder_state_e *state) +{ + int ret = STREAMRECORDER_ERROR_NONE; + + if (recorder == NULL) { + LOGE("NULL pointer handle"); + return STREAMRECORDER_ERROR_INVALID_PARAMETER; + } + ret = _streamrecorder_get_state(recorder, state); + + return ret; +} + +int streamrecorder_enable_source_buffer(streamrecorder_h recorder, streamrecorder_source_e type) +{ + int ret = STREAMRECORDER_ERROR_NONE; + if (recorder == NULL) { + LOGE("NULL video pointer handle"); + return STREAMRECORDER_ERROR_INVALID_PARAMETER; + } + if (type == STREAMRECORDER_SOURCE_VIDEO) { + ret = _streamrecorder_set_videosource_buffer(recorder); + } else if (type == STREAMRECORDER_SOURCE_AUDIO) { + ret = _streamrecorder_set_audiosource_buffer(recorder); + } else { + ret = _streamrecorder_set_videosource_buffer(recorder); + if (ret == STREAMRECORDER_ERROR_NONE) { + ret = _streamrecorder_set_audiosource_buffer(recorder); + } + } + return ret; +} + +int streamrecorder_push_stream_buffer(streamrecorder_h recorder, media_packet_h packet) +{ + int ret = MM_ERROR_NONE; + uint64_t pts = 0; + bool flag = FALSE; + tbm_surface_h surface = NULL; + int width; + int height; + + if ((recorder == NULL) || (packet == NULL)) { + LOGE("[%s] INVALID_PARAMETER(0x%08x)", __func__, STREAMRECORDER_ERROR_INVALID_PARAMETER); + return STREAMRECORDER_ERROR_INVALID_PARAMETER; + } + streamrecorder_s *handle = (streamrecorder_s *)recorder; + + /* pts */ + media_packet_get_pts(packet, &pts); + media_packet_is_video(packet, &flag); + if (flag) { + media_format_h fmt = NULL; + media_format_mimetype_e mimetype = 0; + media_packet_get_format(packet, &fmt); + media_format_get_video_info(fmt, &mimetype, &width, &height, NULL, NULL); + media_format_unref(fmt); + + if ((mimetype == MEDIA_FORMAT_NV12) || (mimetype == MEDIA_FORMAT_NV21)) { + MMVideoBuffer *video_buf = NULL; + void *dataPtr = NULL; + video_buf = (MMVideoBuffer *)malloc(sizeof(MMVideoBuffer)); + if (!video_buf) { + LOGE("Failed to alloc MMVideoBuffer"); + return STREAMRECORDER_ERROR_OUT_OF_MEMORY; + } + memset(video_buf, 0x00, sizeof(MMVideoBuffer)); + media_packet_get_buffer_data_ptr(packet, (void **)&dataPtr); + media_packet_get_tbm_surface(packet, &surface); + if (surface == NULL) { + LOGE("Failed to get surface"); + free(video_buf); + return STREAMRECORDER_ERROR_INVALID_PARAMETER; + } + video_buf->handle_num = tbm_surface_internal_get_num_bos(surface); + video_buf->type = MM_VIDEO_BUFFER_TYPE_TBM_BO; + video_buf->handle.paddr[0] = dataPtr; + video_buf->data[0] = dataPtr; + video_buf->width[0] = width; + video_buf->height[0] = height; + video_buf->stride_width[0] = video_buf->width[0]; + video_buf->stride_height[0] = video_buf->height[0]; + video_buf->size[0] = width*height*3/2; + + ret = mm_streamrecorder_push_stream_buffer(handle->mm_handle, MM_STREAM_TYPE_VIDEO, pts, video_buf, video_buf->size[0]); + free(video_buf); + } else if (mimetype == MEDIA_FORMAT_I420) { + void *buf_data = NULL; + uint64_t buf_size = 0; + ret = media_packet_get_buffer_size(packet, &buf_size); + if (ret != MEDIA_PACKET_ERROR_NONE) { + LOGW("buffer size get fail"); + return STREAMRECORDER_ERROR_INVALID_PARAMETER; + } + ret = media_packet_get_buffer_data_ptr(packet, (void **)&buf_data); + if (ret != MEDIA_PACKET_ERROR_NONE) { + LOGW("buffer size get fail"); + return STREAMRECORDER_ERROR_INVALID_PARAMETER; + } + ret = mm_streamrecorder_push_stream_buffer(handle->mm_handle, MM_STREAM_TYPE_VIDEO, pts, buf_data, buf_size); + } + } else { + media_packet_is_audio(packet, &flag); + if (flag) { + void *buf_data = NULL; + uint64_t buf_size = 0; + ret = media_packet_get_buffer_size(packet, &buf_size); + if (ret != MEDIA_PACKET_ERROR_NONE) { + LOGW("buffer size get fail"); + return STREAMRECORDER_ERROR_INVALID_PARAMETER; + } + ret = media_packet_get_buffer_data_ptr(packet, &buf_data); + if (ret != MEDIA_PACKET_ERROR_NONE) { + LOGW("buffer size get fail"); + return STREAMRECORDER_ERROR_INVALID_PARAMETER; + } + ret = mm_streamrecorder_push_stream_buffer(handle->mm_handle, MM_STREAM_TYPE_AUDIO, pts, buf_data, buf_size); + } + + } + return __convert_streamrecorder_error_code(__func__, ret); +} + + +int streamrecorder_destroy(streamrecorder_h recorder) +{ + int ret = STREAMRECORDER_ERROR_NONE; + + if (recorder == NULL) { + LOGE("NULL pointer handle"); + return STREAMRECORDER_ERROR_INVALID_PARAMETER; + } + + ret = _streamrecorder_destroy(recorder); + + return ret; +} + + +int streamrecorder_prepare(streamrecorder_h recorder) +{ + int ret = STREAMRECORDER_ERROR_NONE; + if (recorder == NULL) { + LOGE("NULL pointer handle"); + return STREAMRECORDER_ERROR_INVALID_PARAMETER; + } + ret = _streamrecorder_prepare(recorder); + + return ret; +} + + +int streamrecorder_unprepare(streamrecorder_h recorder) +{ + int ret = STREAMRECORDER_ERROR_NONE; + if (recorder == NULL) { + LOGE("NULL pointer handle"); + return STREAMRECORDER_ERROR_INVALID_PARAMETER; + } + ret = _streamrecorder_unprepare(recorder); + + return ret; + +} + + +int streamrecorder_start(streamrecorder_h recorder) +{ + int ret = STREAMRECORDER_ERROR_NONE; + + if (recorder == NULL) { + LOGE("NULL startointer handle"); + return STREAMRECORDER_ERROR_INVALID_PARAMETER; + } + + ret = _streamrecorder_start(recorder); + return ret; +} + + +int streamrecorder_pause(streamrecorder_h recorder) +{ + int ret = STREAMRECORDER_ERROR_NONE; + + if (recorder == NULL) { + LOGE("NULL pointer handle"); + return STREAMRECORDER_ERROR_INVALID_PARAMETER; + } + + ret = _streamrecorder_pause(recorder); + return ret; +} + + +int streamrecorder_commit(streamrecorder_h recorder) +{ + int ret = STREAMRECORDER_ERROR_NONE; + + if (recorder == NULL) { + LOGE("NULL pointer handle"); + return STREAMRECORDER_ERROR_INVALID_PARAMETER; + } + + ret = _streamrecorder_commit(recorder); + return ret; +} + + +int streamrecorder_cancel(streamrecorder_h recorder) +{ + int ret = STREAMRECORDER_ERROR_NONE; + + if (recorder == NULL) { + LOGE("NULL pointer handle"); + return STREAMRECORDER_ERROR_INVALID_PARAMETER; + } + + ret = _streamrecorder_cancel(recorder); + return ret; +} + +int streamrecorder_set_video_framerate(streamrecorder_h recorder, int framerate) +{ + int ret = STREAMRECORDER_ERROR_NONE; + + if (recorder == NULL) { + LOGE("NULL pointer handle"); + return STREAMRECORDER_ERROR_INVALID_PARAMETER; + } + + ret = _streamrecorder_set_video_framerate(recorder, framerate); + return ret; + +} + +int streamrecorder_get_video_framerate(streamrecorder_h recorder, int *framerate) +{ + int ret = STREAMRECORDER_ERROR_NONE; + + if (recorder == NULL) { + LOGE("NULL pointer handle"); + return STREAMRECORDER_ERROR_INVALID_PARAMETER; + } + + ret = _streamrecorder_get_video_framerate(recorder, framerate); + return ret; +} + +int streamrecorder_set_video_source_format(streamrecorder_h recorder, streamrecorder_video_source_format_e format) +{ + int ret = STREAMRECORDER_ERROR_NONE; + + if (recorder == NULL) { + LOGE("NULL pointer handle"); + return STREAMRECORDER_ERROR_INVALID_PARAMETER; + } + + ret = _streamrecorder_set_video_source_format(recorder, format); + return ret; +} + +int streamrecorder_get_video_source_format(streamrecorder_h recorder, streamrecorder_video_source_format_e *format) +{ + int ret = STREAMRECORDER_ERROR_NONE; + + if (recorder == NULL) { + LOGE("NULL pointer handle"); + return STREAMRECORDER_ERROR_INVALID_PARAMETER; + } + + ret = _streamrecorder_get_video_source_format(recorder, format); + return ret; +} + + +int streamrecorder_set_video_resolution(streamrecorder_h recorder, int width, int height) +{ + int ret = STREAMRECORDER_ERROR_NONE; + + if (recorder == NULL) { + LOGE("NULL pointer handle"); + return STREAMRECORDER_ERROR_INVALID_PARAMETER; + } + + ret = _streamrecorder_set_video_resolution(recorder, width, height); + return ret; +} + +int streamrecorder_get_video_resolution(streamrecorder_h recorder, int *width, int *height) +{ + int ret = STREAMRECORDER_ERROR_NONE; + + if (recorder == NULL) { + LOGE("NULL pointer handle"); + return STREAMRECORDER_ERROR_INVALID_PARAMETER; + } + + ret = _streamrecorder_get_video_resolution(recorder, width , height); + return ret; +} + + + +int streamrecorder_foreach_supported_video_resolution(streamrecorder_h recorder, + streamrecorder_supported_video_resolution_cb foreach_cb, void *user_data) +{ + + int ret = STREAMRECORDER_ERROR_NONE; + + if (recorder == NULL) { + LOGE("NULL pointer handle"); + return STREAMRECORDER_ERROR_INVALID_PARAMETER; + } + ret = _streamrecorder_foreach_supported_video_resolution(recorder, foreach_cb, user_data); + return ret; + + +} + +int streamrecorder_set_filename(streamrecorder_h recorder, const char *filename) +{ + int ret = STREAMRECORDER_ERROR_NONE; + + if (recorder == NULL) { + LOGE("NULL pointer handle"); + return STREAMRECORDER_ERROR_INVALID_PARAMETER; + } + + ret = _streamrecorder_set_filename(recorder, filename); + return ret; +} + + +int streamrecorder_get_filename(streamrecorder_h recorder, char **filename) +{ + int ret = STREAMRECORDER_ERROR_NONE; + + if (recorder == NULL) { + LOGE("NULL pointer handle"); + return STREAMRECORDER_ERROR_INVALID_PARAMETER; + } + + ret = _streamrecorder_get_filename(recorder, filename); + return ret; +} + + +int streamrecorder_set_file_format(streamrecorder_h recorder, streamrecorder_file_format_e format) +{ + int ret = STREAMRECORDER_ERROR_NONE; + + if (recorder == NULL) { + LOGE("NULL pointer handle"); + return STREAMRECORDER_ERROR_INVALID_PARAMETER; + } + + ret = _streamrecorder_set_file_format(recorder, format); + return ret; +} + + +int streamrecorder_get_file_format(streamrecorder_h recorder, streamrecorder_file_format_e *format) +{ + + int ret = STREAMRECORDER_ERROR_NONE; + + if (recorder == NULL) { + LOGE("NULL pointer handle"); + return STREAMRECORDER_ERROR_INVALID_PARAMETER; + } + + ret = _streamrecorder_get_file_format(recorder, format); + return ret; + +} + + +int streamrecorder_set_notify_cb(streamrecorder_h recorder, streamrecorder_notify_cb callback, void *user_data) +{ + streamrecorder_s *handle = (streamrecorder_s *)recorder; + + if (recorder == NULL) { + LOGE("NULL pointer handle"); + return STREAMRECORDER_ERROR_INVALID_PARAMETER; + } + + if (callback == NULL) { + LOGE("NULL pointer callback"); + return STREAMRECORDER_ERROR_INVALID_PARAMETER; + } + + handle->user_cb[_STREAMRECORDER_EVENT_TYPE_NOTIFY] = callback; + handle->user_data[_STREAMRECORDER_EVENT_TYPE_NOTIFY] = user_data; + + return STREAMRECORDER_ERROR_NONE; +} + + +int streamrecorder_unset_notify_cb(streamrecorder_h recorder) +{ + streamrecorder_s *handle = (streamrecorder_s *)recorder; + + if (recorder == NULL) { + LOGE("NULL pointer handle"); + return STREAMRECORDER_ERROR_INVALID_PARAMETER; + } + + handle->user_cb[_STREAMRECORDER_EVENT_TYPE_NOTIFY] = NULL; + handle->user_data[_STREAMRECORDER_EVENT_TYPE_NOTIFY] = NULL; + + return STREAMRECORDER_ERROR_NONE; +} + +int streamrecorder_set_buffer_consume_completed_cb(streamrecorder_h recorder, streamrecorder_consume_completed_cb callback, void *user_data) +{ + if (recorder == NULL) + return STREAMRECORDER_ERROR_INVALID_PARAMETER; + streamrecorder_s *handle = (streamrecorder_s *)recorder; + if (callback == NULL) + return STREAMRECORDER_ERROR_INVALID_PARAMETER; + + handle->user_cb[_STREAMRECORDER_EVENT_TYPE_CONSUME_COMPLETE] = callback; + handle->user_data[_STREAMRECORDER_EVENT_TYPE_CONSUME_COMPLETE] = user_data; + return STREAMRECORDER_ERROR_NONE; +} + +int streamrecorder_unset_buffer_consume_completed_cb(streamrecorder_h recorder) +{ + if (recorder == NULL) + return STREAMRECORDER_ERROR_INVALID_PARAMETER; + streamrecorder_s *handle = (streamrecorder_s *)recorder; + + handle->user_cb[_STREAMRECORDER_EVENT_TYPE_CONSUME_COMPLETE] = NULL; + handle->user_data[_STREAMRECORDER_EVENT_TYPE_CONSUME_COMPLETE] = NULL; + return STREAMRECORDER_ERROR_NONE; +} + +int streamrecorder_set_error_cb(streamrecorder_h recorder, streamrecorder_error_cb callback, void *user_data) +{ + streamrecorder_s *handle = (streamrecorder_s *)recorder; + + if (recorder == NULL) { + LOGE("NULL pointer handle"); + return STREAMRECORDER_ERROR_INVALID_PARAMETER; + } + if (callback == NULL) { + LOGE("NULL pointer callback"); + return STREAMRECORDER_ERROR_INVALID_PARAMETER; + } + + handle->user_cb[_STREAMRECORDER_EVENT_TYPE_ERROR] = callback; + handle->user_data[_STREAMRECORDER_EVENT_TYPE_ERROR] = user_data; + + return STREAMRECORDER_ERROR_NONE; +} + + +int streamrecorder_unset_error_cb(streamrecorder_h recorder) +{ + streamrecorder_s *handle = (streamrecorder_s *)recorder; + + if (recorder == NULL) { + LOGE("NULL pointer handle"); + return STREAMRECORDER_ERROR_INVALID_PARAMETER; + } + + handle->user_cb[_STREAMRECORDER_EVENT_TYPE_ERROR] = NULL; + handle->user_data[_STREAMRECORDER_EVENT_TYPE_ERROR] = NULL; + + return STREAMRECORDER_ERROR_NONE; +} + + +int streamrecorder_set_recording_status_cb(streamrecorder_h recorder, streamrecorder_recording_status_cb callback, void *user_data) +{ + streamrecorder_s *handle = (streamrecorder_s *)recorder; + + if (recorder == NULL) { + LOGE("NULL pointer handle"); + return STREAMRECORDER_ERROR_INVALID_PARAMETER; + } + if (callback == NULL) { + LOGE("NULL pointer callback"); + return STREAMRECORDER_ERROR_INVALID_PARAMETER; + } + + handle->user_cb[_STREAMRECORDER_EVENT_TYPE_RECORDING_STATUS] = callback; + handle->user_data[_STREAMRECORDER_EVENT_TYPE_RECORDING_STATUS] = user_data; + + return STREAMRECORDER_ERROR_NONE; +} + + +int streamrecorder_unset_recording_status_cb(streamrecorder_h recorder) +{ + streamrecorder_s *handle = (streamrecorder_s *)recorder; + + if (recorder == NULL) { + LOGE("NULL pointer handle"); + return STREAMRECORDER_ERROR_INVALID_PARAMETER; + } + + handle->user_cb[_STREAMRECORDER_EVENT_TYPE_RECORDING_STATUS] = NULL; + handle->user_data[_STREAMRECORDER_EVENT_TYPE_RECORDING_STATUS] = NULL; + + return STREAMRECORDER_ERROR_NONE; +} + + +int streamrecorder_set_recording_limit_reached_cb(streamrecorder_h recorder, streamrecorder_recording_limit_reached_cb callback, void *user_data) +{ + streamrecorder_s *handle = (streamrecorder_s *)recorder; + + if (recorder == NULL) { + LOGE("NULL pointer handle"); + return STREAMRECORDER_ERROR_INVALID_PARAMETER; + } + if (callback == NULL) { + LOGE("NULL pointer callback"); + return STREAMRECORDER_ERROR_INVALID_PARAMETER; + } + + handle->user_cb[_STREAMRECORDER_EVENT_TYPE_RECORDING_LIMITED] = callback; + handle->user_data[_STREAMRECORDER_EVENT_TYPE_RECORDING_LIMITED] = user_data; + + return STREAMRECORDER_ERROR_NONE; +} + + +int streamrecorder_unset_recording_limit_reached_cb(streamrecorder_h recorder) +{ + streamrecorder_s *handle = (streamrecorder_s *)recorder; + + if (recorder == NULL) { + LOGE("NULL pointer handle"); + return STREAMRECORDER_ERROR_INVALID_PARAMETER; + } + + handle->user_cb[_STREAMRECORDER_EVENT_TYPE_RECORDING_LIMITED] = NULL; + handle->user_data[_STREAMRECORDER_EVENT_TYPE_RECORDING_LIMITED] = NULL; + + return STREAMRECORDER_ERROR_NONE; +} + + +int streamrecorder_foreach_supported_file_format(streamrecorder_h recorder, streamrecorder_supported_file_format_cb foreach_cb, void *user_data) +{ + int ret = STREAMRECORDER_ERROR_NONE; + + if (recorder == NULL) { + LOGE("NULL pointer handle"); + return STREAMRECORDER_ERROR_INVALID_PARAMETER; + } + + ret = _streamrecorder_foreach_supported_file_format(recorder, foreach_cb, user_data); + return ret; + +} + + +int streamrecorder_set_recording_limit(streamrecorder_h recorder, streamrecorder_recording_limit_type_e type, int limit) +{ + int ret = STREAMRECORDER_ERROR_NONE; + + if (recorder == NULL) { + LOGE("NULL pointer handle"); + return STREAMRECORDER_ERROR_INVALID_PARAMETER; + } + + if (type == STREAMRECORDER_RECORDING_LIMIT_TYPE_TIME) + ret = _streamrecorder_set_size_limit(recorder, limit); + else + ret = _streamrecorder_set_time_limit(recorder, limit); + return ret; +} + +int streamrecorder_get_recording_limit(streamrecorder_h recorder, streamrecorder_recording_limit_type_e type, int *limit) +{ + int ret = STREAMRECORDER_ERROR_NONE; + + if (recorder == NULL) { + LOGE("NULL pointer handle"); + return STREAMRECORDER_ERROR_INVALID_PARAMETER; + } + if (type == STREAMRECORDER_RECORDING_LIMIT_TYPE_TIME) + ret = _streamrecorder_get_size_limit(recorder, limit); + else + ret = _streamrecorder_get_time_limit(recorder, limit); + return ret; +} + +int streamrecorder_set_audio_encoder(streamrecorder_h recorder, streamrecorder_audio_codec_e codec) +{ + + int ret = STREAMRECORDER_ERROR_NONE; + + if (recorder == NULL) { + LOGE("NULL pointer handle"); + return STREAMRECORDER_ERROR_INVALID_PARAMETER; + } + + ret = _streamrecorder_set_audio_encoder(recorder, codec); + return ret; + +} + + +int streamrecorder_get_audio_encoder(streamrecorder_h recorder, streamrecorder_audio_codec_e *codec) +{ + + int ret = STREAMRECORDER_ERROR_NONE; + + if (recorder == NULL) { + LOGE("NULL pointer handle"); + return STREAMRECORDER_ERROR_INVALID_PARAMETER; + } + + ret = _streamrecorder_get_audio_encoder(recorder, codec); + return ret; + +} + + +int streamrecorder_set_video_encoder(streamrecorder_h recorder, streamrecorder_video_codec_e codec) +{ + + int ret = STREAMRECORDER_ERROR_NONE; + + if (recorder == NULL) { + LOGE("NULL pointer handle"); + return STREAMRECORDER_ERROR_INVALID_PARAMETER; + } + + ret = _streamrecorder_set_video_encoder(recorder, codec); + return ret; + +} + + +int streamrecorder_get_video_encoder(streamrecorder_h recorder, streamrecorder_video_codec_e *codec) +{ + + int ret = STREAMRECORDER_ERROR_NONE; + + if (recorder == NULL) { + LOGE("NULL pointer handle"); + return STREAMRECORDER_ERROR_INVALID_PARAMETER; + } + + ret = _streamrecorder_get_video_encoder(recorder, codec); + return ret; + +} + + +int streamrecorder_set_audio_samplerate(streamrecorder_h recorder, int samplerate) +{ + + int ret = STREAMRECORDER_ERROR_NONE; + + if (recorder == NULL) { + LOGE("NULL pointer handle"); + return STREAMRECORDER_ERROR_INVALID_PARAMETER; + } + + ret = _streamrecorder_set_audio_samplerate(recorder, samplerate); + return ret; + +} + + +int streamrecorder_set_audio_encoder_bitrate(streamrecorder_h recorder, int bitrate) +{ + int ret = STREAMRECORDER_ERROR_NONE; + + if (recorder == NULL) { + LOGE("NULL pointer handle"); + return STREAMRECORDER_ERROR_INVALID_PARAMETER; + } + + ret = _streamrecorder_set_audio_encoder_bitrate(recorder, bitrate); + return ret; + +} + +int streamrecorder_set_video_encoder_bitrate(streamrecorder_h recorder, int bitrate) +{ + int ret = STREAMRECORDER_ERROR_NONE; + + if (recorder == NULL) { + LOGE("NULL pointer handle"); + return STREAMRECORDER_ERROR_INVALID_PARAMETER; + } + + ret = _streamrecorder_set_video_encoder_bitrate(recorder, bitrate); + return ret; +} + +int streamrecorder_get_audio_samplerate(streamrecorder_h recorder, int *samplerate) +{ + int ret = STREAMRECORDER_ERROR_NONE; + + if (recorder == NULL) { + LOGE("NULL pointer handle"); + return STREAMRECORDER_ERROR_INVALID_PARAMETER; + } + + ret = _streamrecorder_get_audio_samplerate(recorder, samplerate); + return ret; +} + +int streamrecorder_get_audio_encoder_bitrate(streamrecorder_h recorder, int *bitrate) +{ + int ret = STREAMRECORDER_ERROR_NONE; + + if (recorder == NULL) { + LOGE("NULL pointer handle"); + return STREAMRECORDER_ERROR_INVALID_PARAMETER; + } + + ret = _streamrecorder_get_audio_encoder_bitrate(recorder, bitrate); + return ret; +} + + +int streamrecorder_get_video_encoder_bitrate(streamrecorder_h recorder, int *bitrate) +{ + int ret = STREAMRECORDER_ERROR_NONE; + + if (recorder == NULL) { + LOGE("NULL pointer handle"); + return STREAMRECORDER_ERROR_INVALID_PARAMETER; + } + + ret = _streamrecorder_get_video_encoder_bitrate(recorder, bitrate); + return ret; +} + + +int streamrecorder_foreach_supported_audio_encoder(streamrecorder_h recorder, streamrecorder_supported_audio_encoder_cb foreach_cb, void *user_data) +{ + + int ret = STREAMRECORDER_ERROR_NONE; + + if (recorder == NULL) { + LOGE("NULL pointer handle"); + return STREAMRECORDER_ERROR_INVALID_PARAMETER; + } + + ret = _streamrecorder_foreach_supported_audio_encoder(recorder, foreach_cb, user_data); + return ret; + +} + + +int streamrecorder_foreach_supported_video_encoder(streamrecorder_h recorder, streamrecorder_supported_video_encoder_cb foreach_cb, void *user_data) +{ + + int ret = STREAMRECORDER_ERROR_NONE; + + if (recorder == NULL) { + LOGE("NULL pointer handle"); + return STREAMRECORDER_ERROR_INVALID_PARAMETER; + } + + ret = _streamrecorder_foreach_supported_video_encoder(recorder, foreach_cb, user_data); + return ret; + +} + + +int streamrecorder_set_audio_channel(streamrecorder_h recorder, int channel_count) +{ + int ret = STREAMRECORDER_ERROR_NONE; + + if (recorder == NULL) { + LOGE("NULL pointer handle"); + return STREAMRECORDER_ERROR_INVALID_PARAMETER; + } + + ret = _streamrecorder_set_audio_channel(recorder, channel_count); + return ret; +} + + +int streamrecorder_get_audio_channel(streamrecorder_h recorder, int *channel_count) +{ + int ret = STREAMRECORDER_ERROR_NONE; + + if (recorder == NULL) { + LOGE("NULL pointer handle"); + return STREAMRECORDER_ERROR_INVALID_PARAMETER; + } + + ret = _streamrecorder_get_audio_channel(recorder, channel_count); + return ret; + +} + +static int __mm_streamrecorder_msg_cb(int message, void *param, void *user_data) +{ + streamrecorder_s * handle = (streamrecorder_s *)user_data; + MMMessageParamType *m = (MMMessageParamType *)param; + streamrecorder_notify_e notification = STREAMRECORDER_NOTIFY_NONE; + streamrecorder_state_e previous_state; + streamrecorder_recording_limit_type_e type; + int streamrecorder_error = 0; + switch (message) { + case MM_MESSAGE_READY_TO_RESUME: + LOGW("not supported message"); + break; + case MM_MESSAGE_STREAMRECORDER_STATE_CHANGED: + previous_state = handle->state; + notification = STREAMRECORDER_NOTIFY_STATE_CHANGED; + if (previous_state != handle->state && handle->user_cb[_STREAMRECORDER_EVENT_TYPE_NOTIFY]) + ((streamrecorder_notify_cb)handle->user_cb[_STREAMRECORDER_EVENT_TYPE_NOTIFY])(previous_state, handle->state, notification, handle->user_data[_STREAMRECORDER_EVENT_TYPE_NOTIFY]); + + break; + case MM_MESSAGE_STREAMRECORDER_MAX_SIZE: + case MM_MESSAGE_STREAMRECORDER_NO_FREE_SPACE: + case MM_MESSAGE_STREAMRECORDER_TIME_LIMIT: + if (MM_MESSAGE_STREAMRECORDER_MAX_SIZE == message) { + type = STREAMRECORDER_RECORDING_LIMIT_TYPE_SIZE; + } else { + type = STREAMRECORDER_RECORDING_LIMIT_TYPE_TIME; + } + if (handle->user_cb[_STREAMRECORDER_EVENT_TYPE_RECORDING_LIMITED]) { + ((streamrecorder_recording_limit_reached_cb)handle->user_cb[_STREAMRECORDER_EVENT_TYPE_RECORDING_LIMITED])(type, handle->user_data[_STREAMRECORDER_EVENT_TYPE_RECORDING_LIMITED]); + } + break; + case MM_MESSAGE_STREAMRECORDER_RECORDING_STATUS: + if (handle->user_cb[_STREAMRECORDER_EVENT_TYPE_RECORDING_STATUS]) { + ((streamrecorder_recording_status_cb)handle->user_cb[_STREAMRECORDER_EVENT_TYPE_RECORDING_STATUS])(m->recording_status.elapsed, m->recording_status.filesize, handle->user_data[_STREAMRECORDER_EVENT_TYPE_RECORDING_STATUS]); + } + break; + + case MM_MESSAGE_STREAMRECORDER_VIDEO_CAPTURED: + { + MMStreamRecordingReport *report = (MMStreamRecordingReport *)m->data; + if (report != NULL && report->recording_filename) { + free(report->recording_filename); + report->recording_filename = NULL; + } + if (report) { + free(report); + report = NULL; + } + } break; + case MM_MESSAGE_STREAMRECORDER_CONSUME_COMPLETE: + { + void *consume = (m->consumed_mediabuffer).consumed_buffer; + if (handle->user_cb[_STREAMRECORDER_EVENT_TYPE_CONSUME_COMPLETE]) { + ((streamrecorder_consume_completed_cb)handle->user_cb[_STREAMRECORDER_EVENT_TYPE_CONSUME_COMPLETE])(consume, handle->user_data[_STREAMRECORDER_EVENT_TYPE_CONSUME_COMPLETE]); + } + } break; + case MM_MESSAGE_STREAMRECORDER_ERROR: + switch (m->code) { + case MM_ERROR_STREAMRECORDER_GST_CORE: + case MM_ERROR_STREAMRECORDER_GST_LIBRARY: + case MM_ERROR_STREAMRECORDER_GST_RESOURCE: + case MM_ERROR_STREAMRECORDER_GST_STREAM: + case MM_ERROR_STREAMRECORDER_GST_NEGOTIATION: + case MM_ERROR_STREAMRECORDER_GST_FLOW_ERROR: + case MM_ERROR_STREAMRECORDER_ENCODER: + case MM_ERROR_STREAMRECORDER_ENCODER_BUFFER: + case MM_ERROR_STREAMRECORDER_ENCODER_WORKING: + case MM_ERROR_STREAMRECORDER_INTERNAL: + case MM_ERROR_FILE_NOT_FOUND: + case MM_ERROR_FILE_READ: + streamrecorder_error = STREAMRECORDER_ERROR_INVALID_OPERATION; + break; + case MM_ERROR_OUT_OF_STORAGE: + streamrecorder_error = STREAMRECORDER_ERROR_OUT_OF_STORAGE; + break; + default: + streamrecorder_error = STREAMRECORDER_ERROR_INVALID_OPERATION; + break; + } + + if (streamrecorder_error != 0 && handle->user_cb[_STREAMRECORDER_EVENT_TYPE_ERROR]) { + ((streamrecorder_error_cb)handle->user_cb[_STREAMRECORDER_EVENT_TYPE_ERROR])(streamrecorder_error, handle->state, handle->user_data[_STREAMRECORDER_EVENT_TYPE_ERROR]); + } + break; + default: + break; + } + return 1; +} + diff --git a/src/streamrecorder_private.c b/src/streamrecorder_private.c new file mode 100644 index 0000000..4d4d126 --- /dev/null +++ b/src/streamrecorder_private.c @@ -0,0 +1,1038 @@ +/* +* Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved +* +* 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#define LOWSET_DECIBEL -300.0 + +int __convert_streamrecorder_error_code(const char *func, int code) +{ + int ret = STREAMRECORDER_ERROR_INVALID_OPERATION; + const char *errorstr = NULL; + + switch (code) { + case STREAMRECORDER_ERROR_INVALID_PARAMETER: + ret = STREAMRECORDER_ERROR_INVALID_PARAMETER; + errorstr = "INVALID_PARAMETER"; + break; + case MM_ERROR_NONE: + ret = STREAMRECORDER_ERROR_NONE; + errorstr = "ERROR_NONE"; + break; + case MM_ERROR_STREAMRECORDER_INVALID_ARGUMENT: + case MM_ERROR_COMMON_INVALID_ATTRTYPE: + ret = STREAMRECORDER_ERROR_INVALID_PARAMETER; + errorstr = "INVALID_PARAMETER"; + break; + case MM_ERROR_COMMON_INVALID_PERMISSION: + ret = STREAMRECORDER_ERROR_PERMISSION_DENIED; + errorstr = "ERROR_PERMISSION_DENIED"; + break; + case MM_ERROR_STREAMRECORDER_NOT_INITIALIZED: + ret = STREAMRECORDER_ERROR_INVALID_STATE; + errorstr = "INVALID_STATE"; + break; + case MM_ERROR_STREAMRECORDER_GST_CORE: + case MM_ERROR_STREAMRECORDER_GST_LIBRARY: + case MM_ERROR_STREAMRECORDER_GST_RESOURCE: + case MM_ERROR_STREAMRECORDER_GST_STREAM: + case MM_ERROR_STREAMRECORDER_GST_STATECHANGE: + case MM_ERROR_STREAMRECORDER_GST_NEGOTIATION: + case MM_ERROR_STREAMRECORDER_GST_LINK: + case MM_ERROR_STREAMRECORDER_GST_FLOW_ERROR: + case MM_ERROR_STREAMRECORDER_ENCODER: + case MM_ERROR_STREAMRECORDER_ENCODER_BUFFER: + case MM_ERROR_STREAMRECORDER_ENCODER_WRONG_TYPE: + case MM_ERROR_STREAMRECORDER_ENCODER_WORKING: + case MM_ERROR_STREAMRECORDER_RESPONSE_TIMEOUT: + case MM_ERROR_STREAMRECORDER_CMD_IS_RUNNING: + ret = STREAMRECORDER_ERROR_INVALID_OPERATION; + errorstr = "INVALID_OPERATION"; + break; + case MM_ERROR_STREAMRECORDER_RESOURCE_CREATION: + case MM_ERROR_COMMON_OUT_OF_MEMORY: + ret = STREAMRECORDER_ERROR_OUT_OF_MEMORY; + errorstr = "OUT_OF_MEMORY"; + break; + case MM_ERROR_OUT_OF_STORAGE: + ret = STREAMRECORDER_ERROR_OUT_OF_STORAGE; + errorstr = "OUT_OF_STORAGE"; + break; + case MM_ERROR_COMMON_OUT_OF_ARRAY: + case MM_ERROR_COMMON_OUT_OF_RANGE: + case MM_ERROR_COMMON_ATTR_NOT_EXIST: + ret = STREAMRECORDER_ERROR_NOT_SUPPORTED; + errorstr = "NOT_SUPPORTED"; + break; + default: + ret = STREAMRECORDER_ERROR_INVALID_OPERATION; + errorstr = "INVALID_OPERATION"; + break; + } + + + LOGE("[%s] %s(0x%08x) : core frameworks error code(0x%08x)", func, errorstr, ret, code); + + return ret; +} + +static streamrecorder_state_e __streamrecorder_state_convert(void *mm_state) +{ + streamrecorder_state_e state = STREAMRECORDER_STATE_NONE; + MMStreamRecorderStateType srstate = (MMStreamRecorderStateType)mm_state; + + switch (srstate) { + case MM_STREAMRECORDER_STATE_NONE: + state = STREAMRECORDER_STATE_NONE; + break; + case MM_STREAMRECORDER_STATE_CREATED: + state = STREAMRECORDER_STATE_CREATED; + break; + case MM_STREAMRECORDER_STATE_PREPARED: + state = STREAMRECORDER_STATE_PREPARED; + break; + case MM_STREAMRECORDER_STATE_RECORDING: + state = STREAMRECORDER_STATE_RECORDING; + break; + case MM_STREAMRECORDER_STATE_PAUSED: + state = STREAMRECORDER_STATE_PAUSED; + break; + default: + state = STREAMRECORDER_STATE_NONE; + break; + } + + return state; +} + +static int _streamrecorder_check_and_set_attribute(streamrecorder_h recorder, const char *attribute_name, int set_value) +{ + int ret = MM_ERROR_NONE; + + MMStreamRecorderStateType mmstate; + streamrecorder_s *handle = (streamrecorder_s *)recorder; + + if (recorder == NULL) { + LOGE("handle is NULL"); + return STREAMRECORDER_ERROR_INVALID_PARAMETER; + } + + mm_streamrecorder_get_state(handle->mm_handle, &mmstate); + if (mmstate >= MM_STREAMRECORDER_STATE_RECORDING) { + LOGE("invalid state %d", mmstate); + return STREAMRECORDER_ERROR_INVALID_STATE; + } + + ret = mm_streamrecorder_set_attributes(handle->mm_handle, NULL, + attribute_name, set_value, + NULL); + + if (ret != MM_ERROR_NONE) { + LOGE("set [%s] failed 0x%x", attribute_name, ret); + } + + + + return __convert_streamrecorder_error_code(attribute_name, ret); +} + + +int _streamrecorder_set_videosource_buffer(streamrecorder_h recorder) +{ + int ret = STREAMRECORDER_ERROR_NONE; + if (recorder == NULL) + return STREAMRECORDER_ERROR_INVALID_PARAMETER; + + streamrecorder_s *handle = (streamrecorder_s *)recorder; + + mm_streamrecorder_set_attributes(handle->mm_handle, NULL, + MMSTR_RECORDER_MODE, MM_STREAMRECORDER_MODE_MEDIABUFFER, + NULL); + + mm_streamrecorder_set_attributes(handle->mm_handle, NULL, + MMSTR_VIDEO_ENABLE, true, + NULL); + + + return ret; +} + +int _streamrecorder_set_audiosource_buffer(streamrecorder_h recorder) +{ + int ret = STREAMRECORDER_ERROR_NONE; + if (recorder == NULL) + return STREAMRECORDER_ERROR_INVALID_PARAMETER; + + streamrecorder_s *handle; + handle = (streamrecorder_s *) recorder; + mm_streamrecorder_set_attributes(handle->mm_handle, NULL, + MMSTR_RECORDER_MODE, MM_STREAMRECORDER_MODE_MEDIABUFFER, + NULL); + + mm_streamrecorder_set_attributes(handle->mm_handle, NULL, + MMSTR_AUDIO_ENABLE, true, + NULL); + + return ret; +} + +int _streamrecorder_get_state(streamrecorder_h recorder, streamrecorder_state_e *state) +{ + int ret = STREAMRECORDER_ERROR_NONE; + MMStreamRecorderStateType srstate; + + if (recorder == NULL) { + LOGE("NULL pointer handle"); + return STREAMRECORDER_ERROR_INVALID_PARAMETER; + } + if (state == NULL) { + LOGE("NULL pointer state"); + return STREAMRECORDER_ERROR_INVALID_PARAMETER; + } + + streamrecorder_s *handle = (streamrecorder_s *)recorder; + + + ret = mm_streamrecorder_get_state(handle->mm_handle, &srstate); + if (ret != MM_ERROR_NONE) { + return __convert_streamrecorder_error_code(__func__, ret); + } + *state = __streamrecorder_state_convert((void *)srstate); + + return STREAMRECORDER_ERROR_NONE; +} + +int _streamrecorder_destroy(streamrecorder_h recorder) +{ + streamrecorder_s *handle = NULL; + int ret = MM_ERROR_NONE; + if (recorder == NULL) { + LOGE("NULL pointer handle"); + return STREAMRECORDER_ERROR_INVALID_PARAMETER; + } + + handle = (streamrecorder_s *)recorder; + + ret = mm_streamrecorder_destroy(handle->mm_handle); + + if (ret == MM_ERROR_NONE) { + free(handle); + } + + return __convert_streamrecorder_error_code(__func__, ret); +} + +int _streamrecorder_prepare(streamrecorder_h recorder) +{ + int ret = MM_ERROR_NONE; + streamrecorder_s *handle = (streamrecorder_s *)recorder; + + if (recorder == NULL) { + LOGE("NULL pointer handle"); + return STREAMRECORDER_ERROR_INVALID_PARAMETER; + } + + ret = mm_streamrecorder_realize(handle->mm_handle); + if (ret != MM_ERROR_NONE) { + LOGE("prepare fail"); + return __convert_streamrecorder_error_code(__func__, ret); + } + + return STREAMRECORDER_ERROR_NONE; +} + +int _streamrecorder_unprepare(streamrecorder_h recorder) +{ + int ret = MM_ERROR_NONE; + streamrecorder_s *handle = (streamrecorder_s *)recorder; + + if (recorder == NULL) { + LOGE("NULL pointer handle"); + return STREAMRECORDER_ERROR_INVALID_PARAMETER; + } + + ret = mm_streamrecorder_unrealize(handle->mm_handle); + if (ret != MM_ERROR_NONE) { + LOGE("stramrecorder_unrealize fail"); + } + return __convert_streamrecorder_error_code(__func__, ret); +} + +int _streamrecorder_start(streamrecorder_h recorder) +{ + streamrecorder_s *handle = (streamrecorder_s *)recorder; + + if (recorder == NULL) { + LOGE("NULL pointer handle"); + return STREAMRECORDER_ERROR_INVALID_PARAMETER; + } + + return __convert_streamrecorder_error_code(__func__, mm_streamrecorder_record(handle->mm_handle)); +} + +int _streamrecorder_pause(streamrecorder_h recorder) +{ + streamrecorder_s *handle = (streamrecorder_s *)recorder; + + if (recorder == NULL) { + LOGE("NULL pointer handle"); + return STREAMRECORDER_ERROR_INVALID_PARAMETER; + } + + return __convert_streamrecorder_error_code(__func__, mm_streamrecorder_pause(handle->mm_handle)); +} + +int _streamrecorder_commit(streamrecorder_h recorder) +{ + streamrecorder_s *handle = (streamrecorder_s *)recorder; + + if (recorder == NULL) { + LOGE("NULL pointer handle"); + return STREAMRECORDER_ERROR_INVALID_PARAMETER; + } + + return __convert_streamrecorder_error_code(__func__, mm_streamrecorder_commit(handle->mm_handle)); +} + +int _streamrecorder_cancel(streamrecorder_h recorder) +{ + streamrecorder_s *handle = (streamrecorder_s *)recorder; + + if (recorder == NULL) { + LOGE("NULL pointer handle"); + return STREAMRECORDER_ERROR_INVALID_PARAMETER; + } + + return __convert_streamrecorder_error_code(__func__, mm_streamrecorder_cancel(handle->mm_handle)); +} + +int _streamrecorder_set_video_framerate(streamrecorder_h recorder , int framerate) +{ + int ret = MM_ERROR_NONE; + streamrecorder_s *handle = (streamrecorder_s *)recorder; + + ret = mm_streamrecorder_set_attributes(handle->mm_handle, NULL, + MMSTR_VIDEO_FRAMERATE, framerate, + NULL); + + return __convert_streamrecorder_error_code(__func__, ret); + +} + +int _streamrecorder_get_video_framerate(streamrecorder_h recorder, int *framerate) +{ + int ret = MM_ERROR_NONE; + streamrecorder_s *handle = (streamrecorder_s *)recorder; + + ret = mm_streamrecorder_get_attributes(handle->mm_handle, NULL, + MMSTR_VIDEO_FRAMERATE, framerate, + NULL); + + return __convert_streamrecorder_error_code(__func__, ret); +} + +int _streamrecorder_set_video_source_format(streamrecorder_h recorder , int format) +{ + int ret = MM_ERROR_NONE; + streamrecorder_s *handle = (streamrecorder_s *)recorder; + + ret = mm_streamrecorder_set_attributes(handle->mm_handle, NULL, + MMSTR_VIDEO_SOURCE_FORMAT, format, + NULL); + + return __convert_streamrecorder_error_code(__func__, ret); +} + +int _streamrecorder_get_video_source_format(streamrecorder_h recorder, int *format) +{ + int ret = MM_ERROR_NONE; + streamrecorder_s *handle = (streamrecorder_s *)recorder; + + ret = mm_streamrecorder_get_attributes(handle->mm_handle, NULL, + MMSTR_VIDEO_SOURCE_FORMAT, format, + NULL); + + return __convert_streamrecorder_error_code(__func__, ret); +} + +int _streamrecorder_set_video_resolution(streamrecorder_h recorder, int width, int height) +{ + int ret = MM_ERROR_NONE; + streamrecorder_s *handle = (streamrecorder_s *)recorder; + streamrecorder_state_e state; + + if (handle == NULL) { + LOGE("NULL pointer handle"); + return STREAMRECORDER_ERROR_INVALID_PARAMETER; + } + streamrecorder_get_state(recorder, &state); + if (state > STREAMRECORDER_STATE_CREATED) { + LOGE("STREAMRECORDER_ERROR_INVALID_STATE (state:%d)", state); + return STREAMRECORDER_ERROR_INVALID_STATE; + } + + + ret = mm_streamrecorder_set_attributes(handle->mm_handle, NULL, + MMSTR_VIDEO_RESOLUTION_WIDTH, width, + MMSTR_VIDEO_RESOLUTION_HEIGHT, height, + NULL); + + return __convert_streamrecorder_error_code(__func__, ret); +} + +int _streamrecorder_get_video_resolution(streamrecorder_h recorder, int *width, int *height) +{ + int ret = MM_ERROR_NONE; + streamrecorder_s *handle = (streamrecorder_s *)recorder; + + if (!handle) { + LOGE("NULL pointer handle"); + return STREAMRECORDER_ERROR_INVALID_PARAMETER; + } + + + if (!width || !height) { + LOGE("NULL pointer width = [%p], height = [%p]", width, height); + return STREAMRECORDER_ERROR_INVALID_PARAMETER; + } + + ret = mm_streamrecorder_get_attributes(handle->mm_handle, NULL, + MMSTR_VIDEO_RESOLUTION_WIDTH , width, + MMSTR_VIDEO_RESOLUTION_HEIGHT , height, + NULL); + return __convert_streamrecorder_error_code(__func__, ret); +} + +int _streamrecorder_foreach_supported_video_resolution(streamrecorder_h recorder, streamrecorder_supported_video_resolution_cb foreach_cb, void *user_data) +{ + int i = 0; + int ret = MM_ERROR_NONE; + streamrecorder_s * handle = (streamrecorder_s *)recorder; + + if (!handle) { + LOGE("NULL pointer handle"); + return STREAMRECORDER_ERROR_INVALID_PARAMETER; + } + + + if (!foreach_cb) { + LOGE("NULL pointer callback"); + return STREAMRECORDER_ERROR_INVALID_PARAMETER; + } + + MMStreamRecorderAttrsInfo video_width; + MMStreamRecorderAttrsInfo video_height; + ret = mm_streamrecorder_get_attribute_info(handle->mm_handle, MMSTR_VIDEO_RESOLUTION_WIDTH, &video_width); + ret |= mm_streamrecorder_get_attribute_info(handle->mm_handle, MMSTR_VIDEO_RESOLUTION_HEIGHT, &video_height); + + if (ret != MM_ERROR_NONE) { + return __convert_streamrecorder_error_code(__func__, ret); + } + for (i = 0 ; i < video_width.int_array.count ; i++) { + if (!foreach_cb(video_width.int_array.array[i], video_height.int_array.array[i], user_data)) { + break; + } + } + + return STREAMRECORDER_ERROR_NONE; +} + + +int _streamrecorder_set_filename(streamrecorder_h recorder, const char *filename) +{ + int ret = MM_ERROR_NONE; + streamrecorder_s *handle = (streamrecorder_s *)recorder; + + if (recorder == NULL) { + LOGE("handle is NULL"); + return STREAMRECORDER_ERROR_INVALID_PARAMETER; + } + + if (filename == NULL) { + LOGE("filename is NULL"); + return STREAMRECORDER_ERROR_INVALID_PARAMETER; + } + + MMStreamRecorderStateType mmstate = MM_STREAMRECORDER_STATE_NONE; + mm_streamrecorder_get_state(handle->mm_handle, &mmstate); + if (mmstate >= MM_STREAMRECORDER_STATE_RECORDING) { + LOGE("invalid state %d", mmstate); + return STREAMRECORDER_ERROR_INVALID_STATE; + } + ret = mm_streamrecorder_set_attributes(handle->mm_handle, NULL, + MMSTR_FILENAME, filename, strlen(filename), + NULL); + return __convert_streamrecorder_error_code(__func__, ret); +} + +int _streamrecorder_get_filename(streamrecorder_h recorder, char **filename) +{ + int ret = MM_ERROR_NONE; + char *record_filename = NULL; + int record_filename_size; + streamrecorder_s *handle = (streamrecorder_s *)recorder; + + if (recorder == NULL) { + LOGE("handle is NULL"); + return STREAMRECORDER_ERROR_INVALID_PARAMETER; + } + + if (filename == NULL) { + LOGE("filename is NULL"); + return STREAMRECORDER_ERROR_INVALID_PARAMETER; + } + + ret = mm_streamrecorder_get_attributes(handle->mm_handle, NULL, + MMSTR_FILENAME, &record_filename, &record_filename_size, + NULL); + if (ret == MM_ERROR_NONE && record_filename) { + *filename = strdup(record_filename); + } else { + LOGE("internal return (0x%08x), get filename p:%p", ret, record_filename); + *filename = NULL; + } + return __convert_streamrecorder_error_code(__func__, ret); +} + +int _streamrecorder_set_file_format(streamrecorder_h recorder, streamrecorder_file_format_e format) +{ + int format_table[5] = {MM_FILE_FORMAT_3GP, /* STREAMRECORDER_FILE_FORMAT_3GP */ + MM_FILE_FORMAT_MP4, /* STREAMRECORDER_FILE_FORMAT_MP4 */ + MM_FILE_FORMAT_AMR, /* STREAMRECORDER_FILE_FORMAT_AMR */ + MM_FILE_FORMAT_AAC, /* STREAMRECORDER_FILE_FORMAT_ADTS */ + MM_FILE_FORMAT_WAV, /* STREAMRECORDER_FILE_FORMAT_WAV */ + }; + + if (format < STREAMRECORDER_FILE_FORMAT_3GP || format > STREAMRECORDER_FILE_FORMAT_WAV) { + LOGE("invalid format %d", format); + return STREAMRECORDER_ERROR_INVALID_PARAMETER; + } + return _streamrecorder_check_and_set_attribute(recorder, MMSTR_FILE_FORMAT, format_table[format]); + +} + +int _streamrecorder_get_file_format(streamrecorder_h recorder, streamrecorder_file_format_e *format) +{ + int ret = MM_ERROR_NONE; + streamrecorder_s *handle = (streamrecorder_s *)recorder; + int mm_format; + + if (recorder == NULL) { + LOGE("handle is NULL"); + return STREAMRECORDER_ERROR_INVALID_PARAMETER; + } + + if (format == NULL) { + LOGE("format is NULL"); + return STREAMRECORDER_ERROR_INVALID_PARAMETER; + } + + ret = mm_streamrecorder_get_attributes(handle->mm_handle, NULL, + MMSTR_FILE_FORMAT, &mm_format, + NULL); + if (ret == MM_ERROR_NONE) { + switch (mm_format) { + case MM_FILE_FORMAT_3GP: + *format = STREAMRECORDER_FILE_FORMAT_3GP; + break; + case MM_FILE_FORMAT_MP4: + *format = STREAMRECORDER_FILE_FORMAT_MP4; + break; + case MM_FILE_FORMAT_AMR: + *format = STREAMRECORDER_FILE_FORMAT_AMR; + break; + case MM_FILE_FORMAT_AAC: + *format = STREAMRECORDER_FILE_FORMAT_ADTS; + break; + case MM_FILE_FORMAT_WAV: + *format = STREAMRECORDER_FILE_FORMAT_WAV; + break; + default: + ret = MM_ERROR_STREAMRECORDER_INTERNAL; + break; + } + } + + return __convert_streamrecorder_error_code(__func__, ret); +} + +int _streamrecorder_foreach_supported_file_format(streamrecorder_h recorder, streamrecorder_supported_file_format_cb foreach_cb, void *user_data) +{ + int i = 0; + int ret = MM_ERROR_NONE; + streamrecorder_s *handle = (streamrecorder_s *)recorder; + int format; + + if (recorder == NULL) { + LOGE("NULL pointer handle"); + return STREAMRECORDER_ERROR_INVALID_PARAMETER; + } + if (foreach_cb == NULL) { + LOGE("NULL pointer foreach_cb"); + return STREAMRECORDER_ERROR_INVALID_PARAMETER; + } + + MMStreamRecorderAttrsInfo info; + ret = mm_streamrecorder_get_attribute_info(handle->mm_handle, MMSTR_FILE_FORMAT, &info); + if (ret != MM_ERROR_NONE) { + LOGE("mm_streamrecorder_get_attribute_info failed 0x%x", ret); + return __convert_streamrecorder_error_code(__func__, ret); + } + + for (i = 0 ; i < info.int_array.count ; i++) { + switch (info.int_array.array[i]) { + case MM_FILE_FORMAT_3GP: + format = STREAMRECORDER_FILE_FORMAT_3GP; + break; + case MM_FILE_FORMAT_MP4: + format = STREAMRECORDER_FILE_FORMAT_MP4; + break; + case MM_FILE_FORMAT_AMR: + format = STREAMRECORDER_FILE_FORMAT_AMR; + break; + case MM_FILE_FORMAT_AAC: + format = STREAMRECORDER_FILE_FORMAT_ADTS; + break; + case MM_FILE_FORMAT_WAV: + format = STREAMRECORDER_FILE_FORMAT_WAV; + break; + default: + format = -1; + break; + } + + if (format != -1 && !foreach_cb(format, user_data)) { + break; + } + } + + return STREAMRECORDER_ERROR_NONE; +} + +int _streamrecorder_set_size_limit(streamrecorder_h recorder, int kbyte) +{ + int ret = MM_ERROR_NONE; + streamrecorder_s *handle = (streamrecorder_s *)recorder; + + if (recorder == NULL) { + LOGE("NULL pointer handle"); + return STREAMRECORDER_ERROR_INVALID_PARAMETER; + } + + ret = mm_streamrecorder_set_attributes(handle->mm_handle, NULL, + MMSTR_TARGET_MAX_SIZE, kbyte, + NULL); + return __convert_streamrecorder_error_code(__func__, ret); +} + +int _streamrecorder_set_time_limit(streamrecorder_h recorder, int second) +{ + int ret = MM_ERROR_NONE; + streamrecorder_s *handle = (streamrecorder_s *)recorder; + + if (recorder == NULL) { + LOGE("NULL pointer handle"); + return STREAMRECORDER_ERROR_INVALID_PARAMETER; + } + + ret = mm_streamrecorder_set_attributes(handle->mm_handle, NULL, + MMSTR_TARGET_TIME_LIMIT, second, + NULL); + return __convert_streamrecorder_error_code(__func__, ret); +} + +int _streamrecorder_set_audio_encoder(streamrecorder_h recorder, streamrecorder_audio_codec_e codec) +{ + streamrecorder_s *handle = (streamrecorder_s *)recorder; + int audio_table[3] = { MM_AUDIO_CODEC_AMR, /* STREAMRECORDER_AUDIO_CODEC_AMR */ + MM_AUDIO_CODEC_AAC, /* STREAMRECORDER_AUDIO_CODEC_AAC */ + MM_AUDIO_CODEC_WAVE /* STREAMRECORDER_AUDIO_CODEC_PCM */ + }; + + if (recorder == NULL) { + LOGE("handle is NULL"); + return STREAMRECORDER_ERROR_INVALID_PARAMETER; + } + + if ((codec < STREAMRECORDER_AUDIO_CODEC_AMR || codec > STREAMRECORDER_AUDIO_CODEC_PCM)) { + LOGE("invalid parameter : codec %d", codec); + return STREAMRECORDER_ERROR_INVALID_PARAMETER; + } + + return _streamrecorder_check_and_set_attribute(recorder, MMSTR_AUDIO_ENCODER, audio_table[codec]); +} + +int _streamrecorder_get_audio_encoder(streamrecorder_h recorder, streamrecorder_audio_codec_e *codec) +{ + int ret = MM_ERROR_NONE; + int mm_codec = 0; + int audio_enable = 0; + streamrecorder_s *handle = (streamrecorder_s *)recorder; + + if (recorder == NULL) { + LOGE("handle is NULL"); + return STREAMRECORDER_ERROR_INVALID_PARAMETER; + } + + if (codec == NULL) { + LOGE("codec is NULL"); + return STREAMRECORDER_ERROR_INVALID_PARAMETER; + } + + ret = mm_streamrecorder_get_attributes(handle->mm_handle, NULL, + MMSTR_AUDIO_ENCODER, &mm_codec, + MMSTR_AUDIO_ENABLE, &audio_enable, + NULL); + + if (ret == MM_ERROR_NONE && audio_enable != 0) { + switch (mm_codec) { + case MM_AUDIO_CODEC_AMR: + *codec = STREAMRECORDER_AUDIO_CODEC_AMR; + break; + case MM_AUDIO_CODEC_AAC: + *codec = STREAMRECORDER_AUDIO_CODEC_AAC; + break; + case MM_AUDIO_CODEC_WAVE: + *codec = STREAMRECORDER_AUDIO_CODEC_PCM; + break; + default: + ret = MM_ERROR_STREAMRECORDER_INTERNAL; + break; + } + } else { + ret = MM_ERROR_STREAMRECORDER_INTERNAL; + } + + return __convert_streamrecorder_error_code(__func__, ret); +} + +int _streamrecorder_set_video_encoder(streamrecorder_h recorder, streamrecorder_video_codec_e codec) +{ + int ret = MM_ERROR_NONE; + int video_table[2] = {MM_VIDEO_CODEC_H263, /* STREAMRECORDER_VIDEO_CODEC_H263 */ + MM_VIDEO_CODEC_MPEG4, /* STREAMRECORDER_VIDEO_CODEC_MPEG4 */ + }; + streamrecorder_s *handle = (streamrecorder_s *)recorder; + + if (handle == NULL) { + LOGE("handle is NULL"); + return STREAMRECORDER_ERROR_INVALID_PARAMETER; + } + + + if (codec < STREAMRECORDER_VIDEO_CODEC_H263 || codec > STREAMRECORDER_VIDEO_CODEC_MPEG4) { + LOGE("invalid codec %d", codec); + return STREAMRECORDER_ERROR_INVALID_PARAMETER; + } + + ret = mm_streamrecorder_set_attributes(handle->mm_handle, NULL, + MMSTR_VIDEO_ENCODER, video_table[codec], + NULL); + return __convert_streamrecorder_error_code(__func__, ret); +} + +int _streamrecorder_get_video_encoder(streamrecorder_h recorder, streamrecorder_video_codec_e *codec) +{ + int ret = MM_ERROR_NONE; + int mm_codec = 0; + streamrecorder_s *handle = (streamrecorder_s *)recorder; + + if (handle == NULL) { + LOGE("handle is NULL"); + return STREAMRECORDER_ERROR_INVALID_PARAMETER; + } + if (codec == NULL) { + LOGE("codec is NULL"); + return STREAMRECORDER_ERROR_INVALID_PARAMETER; + } + + ret = mm_streamrecorder_get_attributes(handle->mm_handle, NULL, + MMSTR_VIDEO_ENCODER, &mm_codec, + NULL); + if (ret == MM_ERROR_NONE) { + switch (mm_codec) { + case MM_VIDEO_CODEC_H263: + *codec = STREAMRECORDER_VIDEO_CODEC_H263; + break; + case MM_VIDEO_CODEC_MPEG4: + *codec = STREAMRECORDER_VIDEO_CODEC_MPEG4; + break; + default: + ret = MM_ERROR_STREAMRECORDER_INTERNAL; + break; + } + } + + return __convert_streamrecorder_error_code(__func__, ret); +} + + +int _streamrecorder_set_audio_samplerate(streamrecorder_h recorder, int samplerate) +{ + if (samplerate < 1) { + LOGE("invalid samplerate %d", samplerate); + return STREAMRECORDER_ERROR_INVALID_PARAMETER; + } + + return _streamrecorder_check_and_set_attribute(recorder, MMSTR_AUDIO_SAMPLERATE, samplerate); + +} + +int _streamrecorder_set_audio_encoder_bitrate(streamrecorder_h recorder, int bitrate) +{ + if (bitrate < 1) { + LOGE("invalid bitrate %d", bitrate); + return STREAMRECORDER_ERROR_INVALID_PARAMETER; + } + + return _streamrecorder_check_and_set_attribute(recorder, MMSTR_AUDIO_BITRATE, bitrate); + +} + +int _streamrecorder_set_video_encoder_bitrate(streamrecorder_h recorder, int bitrate) +{ + int ret = MM_ERROR_NONE; + streamrecorder_s *handle = (streamrecorder_s *)recorder; + + if (handle == NULL) { + LOGE("handle is NULL"); + return STREAMRECORDER_ERROR_INVALID_PARAMETER; + } + + ret = mm_streamrecorder_set_attributes(handle->mm_handle, NULL, + MMSTR_VIDEO_BITRATE, bitrate, + NULL); + + return __convert_streamrecorder_error_code(__func__, ret); +} + +int _streamrecorder_get_size_limit(streamrecorder_h recorder, int *kbyte) +{ + int ret = MM_ERROR_NONE; + streamrecorder_s *handle = (streamrecorder_s *)recorder; + + if (recorder == NULL) { + LOGE("handle is NULL"); + return STREAMRECORDER_ERROR_INVALID_PARAMETER; + } + + ret = mm_streamrecorder_get_attributes(handle->mm_handle, NULL, + MMSTR_TARGET_MAX_SIZE, kbyte, + NULL); + + return __convert_streamrecorder_error_code(__func__, ret); +} + +int _streamrecorder_get_time_limit(streamrecorder_h recorder, int *second) +{ + int ret = MM_ERROR_NONE; + streamrecorder_s *handle = (streamrecorder_s *)recorder; + + if (recorder == NULL) { + LOGE("handle is NULL"); + return STREAMRECORDER_ERROR_INVALID_PARAMETER; + } + + ret = mm_streamrecorder_get_attributes(handle->mm_handle, NULL, + MMSTR_TARGET_TIME_LIMIT, second, + NULL); + + return __convert_streamrecorder_error_code(__func__, ret); +} + + +int _streamrecorder_get_audio_samplerate(streamrecorder_h recorder, int *samplerate) +{ + int ret = MM_ERROR_NONE; + streamrecorder_s *handle = (streamrecorder_s *)recorder; + + if (recorder == NULL) { + LOGE("handle is NULL"); + return STREAMRECORDER_ERROR_INVALID_PARAMETER; + } + + ret = mm_streamrecorder_get_attributes(handle->mm_handle, NULL, + MMSTR_AUDIO_SAMPLERATE, samplerate, + NULL); + + return __convert_streamrecorder_error_code(__func__, ret); +} + +int _streamrecorder_get_audio_encoder_bitrate(streamrecorder_h recorder, int *bitrate) +{ + int ret = MM_ERROR_NONE; + streamrecorder_s *handle = (streamrecorder_s *)recorder; + + if (recorder == NULL) { + LOGE("handle is NULL"); + return STREAMRECORDER_ERROR_INVALID_PARAMETER; + } + + ret = mm_streamrecorder_get_attributes(handle->mm_handle, NULL, + MMSTR_AUDIO_BITRATE, bitrate, + NULL); + + return __convert_streamrecorder_error_code(__func__, ret); +} + +int _streamrecorder_get_video_encoder_bitrate(streamrecorder_h recorder, int *bitrate) +{ + int ret = MM_ERROR_NONE; + streamrecorder_s *handle = (streamrecorder_s *)recorder; + + if (handle == NULL) { + LOGE("handle is NULL"); + return STREAMRECORDER_ERROR_INVALID_PARAMETER; + } + ret = mm_streamrecorder_get_attributes(handle->mm_handle, NULL, + MMSTR_VIDEO_BITRATE, bitrate, + NULL); + return __convert_streamrecorder_error_code(__func__, ret); +} + +int _streamrecorder_foreach_supported_audio_encoder(streamrecorder_h recorder, streamrecorder_supported_audio_encoder_cb foreach_cb, void *user_data) +{ + int i = 0; + int ret = MM_ERROR_NONE; + int codec; + streamrecorder_s *handle = (streamrecorder_s *)recorder; + + if (recorder == NULL) { + LOGE("handle is NULL"); + return STREAMRECORDER_ERROR_INVALID_PARAMETER; + } + if (foreach_cb == NULL) { + LOGE("foreach_cb is NULL"); + return STREAMRECORDER_ERROR_INVALID_PARAMETER; + } + + MMStreamRecorderAttrsInfo info; + ret = mm_streamrecorder_get_attribute_info(handle->mm_handle, MMSTR_AUDIO_ENCODER, &info); + if (ret != MM_ERROR_NONE) { + return __convert_streamrecorder_error_code(__func__, ret); + } + + for (i = 0 ; i < info.int_array.count ; i++) { + switch (info.int_array.array[i]) { + case MM_AUDIO_CODEC_AMR: + codec = STREAMRECORDER_AUDIO_CODEC_AMR; + break; + case MM_AUDIO_CODEC_AAC: + codec = STREAMRECORDER_AUDIO_CODEC_AAC; + break; + case MM_AUDIO_CODEC_WAVE: + codec = STREAMRECORDER_AUDIO_CODEC_PCM; + break; + default: + codec = -1; + break; + } + if (codec != -1 && !foreach_cb(codec, user_data)) { + break; + } + } + + return STREAMRECORDER_ERROR_NONE; +} + + +int _streamrecorder_foreach_supported_video_encoder(streamrecorder_h recorder, streamrecorder_supported_video_encoder_cb foreach_cb, void *user_data) +{ + int i = 0; + int ret = MM_ERROR_NONE; + int codec; + streamrecorder_s *handle = (streamrecorder_s *)recorder; + + if (handle == NULL) { + LOGE("handle is NULL"); + return STREAMRECORDER_ERROR_INVALID_PARAMETER; + } + if (foreach_cb == NULL) { + LOGE("foreach_cb is NULL"); + return STREAMRECORDER_ERROR_INVALID_PARAMETER; + } + + MMStreamRecorderAttrsInfo info; + ret = mm_streamrecorder_get_attribute_info(handle->mm_handle, MMSTR_VIDEO_ENCODER, &info); + if (ret != MM_ERROR_NONE) { + return __convert_streamrecorder_error_code(__func__, ret); + } + + for (i = 0 ; i < info.int_array.count ; i++) { + switch (info.int_array.array[i]) { + case MM_VIDEO_CODEC_H263: + codec = STREAMRECORDER_VIDEO_CODEC_H263; + break; + case MM_VIDEO_CODEC_MPEG4: + codec = STREAMRECORDER_VIDEO_CODEC_MPEG4; + break; + default: + codec = -1; + break; + } + + if (codec != -1 && !foreach_cb(codec, user_data)) { + break; + } + } + + return STREAMRECORDER_ERROR_NONE; +} + + + +int _streamrecorder_set_audio_channel(streamrecorder_h recorder, int channel_count) +{ + if (channel_count < 1) { + LOGE("invalid channel %d", channel_count); + return STREAMRECORDER_ERROR_INVALID_PARAMETER; + } + + return _streamrecorder_check_and_set_attribute(recorder, MMSTR_AUDIO_CHANNEL, channel_count); +} + +int _streamrecorder_get_audio_channel(streamrecorder_h recorder, int *channel_count) +{ + int ret = MM_ERROR_NONE; + streamrecorder_s *handle = (streamrecorder_s *)recorder; + + if (recorder == NULL) { + LOGE("handle is NULL"); + return STREAMRECORDER_ERROR_INVALID_PARAMETER; + } + if (channel_count == NULL) { + LOGE("channel_count is NULL"); + return STREAMRECORDER_ERROR_INVALID_PARAMETER; + } + + ret = mm_streamrecorder_get_attributes(handle->mm_handle, NULL, + MMSTR_AUDIO_CHANNEL, channel_count, + NULL); + + return __convert_streamrecorder_error_code(__func__, ret); +} + diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt new file mode 100644 index 0000000..5d5c0e9 --- /dev/null +++ b/test/CMakeLists.txt @@ -0,0 +1,24 @@ +CMAKE_MINIMUM_REQUIRED(VERSION 2.6) +SET(fw_test "${fw_name}-test") + +#INCLUDE_DIRECTORIES(../include) +#link_directories(${CMAKE_SOURCE_DIR}/../) + +INCLUDE(FindPkgConfig) +pkg_check_modules(${fw_test} REQUIRED mm-streamrecorder) +FOREACH(flag ${${fw_test}_CFLAGS}) + SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}") + MESSAGE(${flag}) +ENDFOREACH() + +SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS} -fPIC -pie -Wall") + +aux_source_directory(. sources) +FOREACH(src ${sources}) + GET_FILENAME_COMPONENT(src_name ${src} NAME_WE) + MESSAGE("${src_name}") + ADD_EXECUTABLE(${src_name} ${src}) + TARGET_LINK_LIBRARIES(${src_name} ${fw_name} ${${fw_test}_LDFLAGS}) + INSTALL(TARGETS ${src_name} DESTINATION bin) + +ENDFOREACH() diff --git a/test/streamrecorder_test.c b/test/streamrecorder_test.c new file mode 100644 index 0000000..480530c --- /dev/null +++ b/test/streamrecorder_test.c @@ -0,0 +1,827 @@ +/* +* recorder_testsuite +* +* Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. +* +* 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 +#include + +#define LOGD g_print +#define LOGE g_print +#define LOGW g_print +/*----------------------------------------------------------------------- +| GLOBAL VARIABLE DEFINITIONS: | +-----------------------------------------------------------------------*/ +#define EXPORT_API __attribute__((__visibility__("default"))) + +#define PACKAGE "recorder_testsuite" + +GMainLoop *g_loop; +GIOChannel *stdin_channel; +int resolution_set; +int g_current_state; +int src_w, src_h; +GstCaps *filtercaps; +int recorder_state; +static GTimer *timer = NULL; +void *display; + +/*----------------------------------------------------------------------- +| GLOBAL CONSTANT DEFINITIONS: | +-----------------------------------------------------------------------*/ + + +/*----------------------------------------------------------------------- +| IMPORTED VARIABLE DECLARATIONS: | +-----------------------------------------------------------------------*/ + + +/*----------------------------------------------------------------------- +| IMPORTED FUNCTION DECLARATIONS: | +-----------------------------------------------------------------------*/ + + +/*----------------------------------------------------------------------- +| LOCAL #defines: | +-----------------------------------------------------------------------*/ + + +#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 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 TARGET_FILENAME_PATH "/opt/usr/media/" +#define IMAGE_CAPTURE_EXIF_PATH TARGET_FILENAME_PATH"exif.raw" +#define TARGET_FILENAME_VIDEO TARGET_FILENAME_PATH"test.mp4" +#define TARGET_FILENAME_AUDIO TARGET_FILENAME_PATH"test_rec_audio.m4a" +#define CAPTURE_FILENAME_LEN 256 + +#define AUDIO_SOURCE_SAMPLERATE_AAC 44100 +#define AUDIO_SOURCE_SAMPLERATE_AMR 8000 +#define AUDIO_SOURCE_FORMAT MM_STREAMRECORDER_AUDIO_FORMAT_PCM_S16_LE +#define AUDIO_SOURCE_CHANNEL_AAC 2 +#define AUDIO_SOURCE_CHANNEL_AMR 1 +#define VIDEO_ENCODE_BITRATE 40000000 /* bps */ + +#define CHECK_MM_ERROR(expr) \ +do {\ + int ret = 0; \ + ret = expr; \ + if (ret != 0) {\ + printf("[%s:%d] error code : %x \n", __func__, __LINE__, ret); \ + return; \ + } \ +} 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 31 +#define SENSOR_FLIP_NUM 3 +#define SENSOR_PROGRAM_MODE_NUM 15 +#define SENSOR_FOCUS_NUM 6 +#define SENSOR_INPUT_ROTATION 4 +#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_LIVE_BUFFER_I420_VIDEO , /*video capturing mode from live buffer I420 using software encoder*/ + MODE_LIVE_BUFFER_NV12_VIDEO_SW , /*video capturing mode from live buffer NV12 using software encoder */ + MODE_LIVE_BUFFER_NV12_VIDEO_HW , /*video capturing mode from live buffer NV12 using hardware encoder*/ + MODE_NUM, +}; + +enum { + MENU_STATE_MAIN, + MENU_STATE_NUM, +}; + +/*----------------------------------------------------------------------- +| LOCAL DATA TYPE DEFINITIONS: | +-----------------------------------------------------------------------*/ +typedef struct _mstreamrecorder_handle { + streamrecorder_h recorder; + int mode; /*video/audio(recording) mode */ + int menu_state; + int fps; + bool isMute; + unsigned long long elapsed_time; +} mstreamrecorder_handle_t; + + +/*--------------------------------------------------------------------------- +| LOCAL VARIABLE DEFINITIONS: | +---------------------------------------------------------------------------*/ +static mstreamrecorder_handle_t *hmstreamrecorder ; + +/*--------------------------------------------------------------------------- +| LOCAL FUNCTION PROTOTYPES: | +---------------------------------------------------------------------------*/ +static void print_menu(); +static gboolean cmd_input(GIOChannel *channel); +static gboolean init(int type); +static gboolean mode_change(); + + +void _recording_status_cb(unsigned long long elapsed_time, unsigned long long file_size, void *user_data) +{ + printf("elapsed time :%d, file_size :%d\n", elapsed_time, file_size); +} + +void _recording_limit_reached_cb(streamrecorder_recording_limit_type_e type, void *user_data) +{ + g_print("limited!! %d\n", type); + int *ischeck = (int *)user_data; + *ischeck = 1; +} +static inline void flush_stdin() +{ + int ch; + while ((ch = getchar()) != EOF && ch != '\n'); +} + + +static void print_menu() +{ + switch (hmstreamrecorder->menu_state) { + case MENU_STATE_MAIN: + if (hmstreamrecorder->mode == MODE_LIVE_BUFFER_I420_VIDEO || hmstreamrecorder->mode == MODE_LIVE_BUFFER_NV12_VIDEO_SW) { + g_print("\n\t=======================================\n"); + if (recorder_state <= STREAMRECORDER_STATE_NONE) { + g_print("\t '1' Start Recording\n"); + g_print("\t 'b' back\n"); + } else if (recorder_state == STREAMRECORDER_STATE_RECORDING) { + g_print("\t 'p' Pause Recording\n"); + g_print("\t 'c' Cancel\n"); + g_print("\t 's' Save\n"); + } else if (recorder_state == STREAMRECORDER_STATE_PAUSED) { + g_print("\t 'r' Resume Recording\n"); + g_print("\t 's' Save\n"); + } + } + break; + + default: + LOGE("unknow menu state !!\n"); + break; + } + return; +} + +media_packet_h streamrecorder_make_media_packet(int video, void *data, int size) +{ + guint8 *pkt_data; + media_packet_h out_pkt; + media_format_h output_fmt; + if (media_format_create(&output_fmt)) { + g_print("media_format_create failed\n"); + return NULL; + } + int i; + int bo_num = 0; + + if (video) { + if (hmstreamrecorder->mode == MODE_LIVE_BUFFER_NV12_VIDEO_SW) { + media_format_set_video_mime(output_fmt, MEDIA_FORMAT_NV12); + } else if (hmstreamrecorder->mode == MODE_LIVE_BUFFER_I420_VIDEO) { + media_format_set_video_mime(output_fmt, MEDIA_FORMAT_I420); + } + media_format_set_video_width(output_fmt, 1280); + media_format_set_video_height(output_fmt, 720); + if (media_format_set_video_frame_rate(output_fmt, 30)) { + g_print("media_format_set_video_frame_rate failed\n"); + return NULL; + } + } else { + media_format_set_audio_mime(output_fmt, MEDIA_FORMAT_PCM); + media_format_set_audio_channel(output_fmt, 1); + media_format_set_audio_samplerate(output_fmt, 44100); + /*media_format_set_audio_bit(core->output_fmt, info->bit);*/ + } + if (media_packet_create(output_fmt, NULL, NULL, &out_pkt)) { + g_print("create video media_packet failed\n"); + return NULL; + } + if (media_packet_alloc(out_pkt)) { + g_print("video media_packet alloc failed\n"); + return NULL; + } + media_packet_get_buffer_data_ptr(out_pkt, (void **)&pkt_data); + memcpy((char *)pkt_data, data, size); + if (media_packet_set_buffer_size(out_pkt, (uint64_t)(size))) { + g_print("video set_buffer_size failed\n"); + return NULL; + } + + return out_pkt; +} + +void feed_video_es(GstElement *element, GstBuffer *buffer, GstPad *pad, gpointer data) +{ + guint n; + GstMemory *mem; + GstMapInfo map = GST_MAP_INFO_INIT; + media_packet_h out_pkt = NULL; + static GstBuffer *buf = NULL; + MMVideoBuffer *m_buf; + + MMHandleType handle = (MMHandleType)data; + + gst_buffer_ref(buffer); + + n = gst_buffer_n_memory(buffer); + + mem = gst_buffer_peek_memory(buffer, n-1); + + gst_memory_map(mem, &map, GST_MAP_READ); + out_pkt = streamrecorder_make_media_packet(1, map.data, map.size); + gst_memory_unmap(mem, &map); + if (out_pkt) { + media_packet_set_pts(out_pkt, buffer->pts); + media_packet_set_extra(out_pkt, buffer); + streamrecorder_push_stream_buffer(hmstreamrecorder->recorder, out_pkt); + } + return; +} + +GstElement *vpipeline, *vconvert, *vsrc, *vfakesink, *vcaps; +void close_pipeline(void) +{ + if (vpipeline) + gst_object_unref(vpipeline); + if (vsrc) + gst_object_unref(vsrc); + if (vfakesink) + gst_object_unref(vfakesink); + if (vcaps) + gst_object_unref(vcaps); + if (vconvert) + gst_object_unref(vconvert); +} + + +int __feed_buffer_test(MMHandleType handle, int mode) +{ + + GstCaps *caps; + g_print("creating __feed_buffer_test pipeline\n"); + if (!handle) + return FALSE; + /* create video pipeline */ + vpipeline = gst_pipeline_new(NULL); + if (!vpipeline) { + g_print("pipeline create fail\n"); + return FALSE; + } + if (mode == MODE_LIVE_BUFFER_NV12_VIDEO_SW) { + vsrc = gst_element_factory_make("videotestsrc", NULL); + if (!vsrc) { + g_print("src element creation failed\n"); + return FALSE; + } + } else { + vsrc = gst_element_factory_make("videotestsrc", NULL); + if (!vsrc) { + g_print("src element creation failed\n"); + return FALSE; + } + } + if (mode == MODE_LIVE_BUFFER_NV12_VIDEO_SW) { + vconvert = gst_element_factory_make("videoconvert", NULL); + if (!vconvert) { + g_print("convert element creation failed\n"); + return FALSE; + } + } + vcaps = gst_element_factory_make("capsfilter", NULL); + if (!vcaps) { + g_print("capsfilter element creation failed\n"); + return FALSE; + } + if (mode == MODE_LIVE_BUFFER_I420_VIDEO) { + caps = gst_caps_new_simple("video/x-raw", + "format", G_TYPE_STRING, "I420", + "width", G_TYPE_INT, 1280, + "height", G_TYPE_INT, 720, NULL); + } else if (mode == MODE_LIVE_BUFFER_NV12_VIDEO_SW) { + caps = gst_caps_new_simple("video/x-raw", + "format", G_TYPE_STRING, "NV12", + "width", G_TYPE_INT, 1280, + "height", G_TYPE_INT, 720, + "framerate", GST_TYPE_FRACTION, 30, 1, NULL); + } + g_object_set(vcaps, "caps", caps, NULL); + gst_caps_unref(caps); + + vfakesink = gst_element_factory_make("fakesink", NULL); + if (!vfakesink) { + g_print("video fakesink creation failed\n"); + return FALSE; + } + g_object_set(GST_OBJECT(vfakesink), "signal-handoffs", TRUE, NULL); + g_signal_connect(vfakesink, "handoff", G_CALLBACK(feed_video_es), handle); + + if (mode == MODE_LIVE_BUFFER_I420_VIDEO) { + gst_bin_add_many(GST_BIN(vpipeline), vsrc, vcaps, vfakesink, NULL); + /* link elements */ + if (!gst_element_link_many(vsrc, vcaps, vfakesink, NULL)) { + GST_WARNING("Can't link elements video pipeline"); + return FALSE; + } + } else if (mode == MODE_LIVE_BUFFER_NV12_VIDEO_SW) { + gst_bin_add_many(GST_BIN(vpipeline), vsrc, vconvert, vcaps, vfakesink, NULL); + /* link elements */ + if (!gst_element_link_many(vsrc , vconvert, vcaps, vfakesink, NULL)) { + GST_WARNING("Can't link elements video pipeline"); + return FALSE; + } + } + g_print("Linking done video pipeline\n"); + +#if 0 + GstElement *a_pipeline, *asrc, *afakesink; + /* create common elements */ + a_pipeline = gst_pipeline_new(NULL); + if (v_pipeline) { + g_print("pipeline create fail\n"); + return FALSE; + } + asrc = gst_element_factory_make("audiotestsrc", NULL); + if (!asrc) { + g_print("src element creation failed\n"); + return FALSE; + } + afakesink = gst_element_factory_make("fakesink", NULL); + if (!afakesink) { + g_print("audio fakesink creation failed\n"); + return FALSE; + } + /* connect handoff */ + g_object_set(GST_OBJECT(afakesink), "signal-handoffs", TRUE, NULL); + g_signal_connect(fakesink, "handoff", G_CALLBACK(feed_audio_es), handle); + + gst_bin_add_many(GST_BIN(v_pipeline), asrc, afakesink, NULL); + + /* link elements */ + if (!gst_element_link_many(asrc, afakesink, NULL)) { + GST_WARNING("Can't link elements audio pipeline"); + return FALSE; + } + g_print("Linking done audio pipeline\n"); + gst_element_set_state(apipeline, GST_STATE_PLAYING); +#endif + gst_element_set_state(vpipeline, GST_STATE_PLAYING); + g_print("feed_task pipeline is playing\n"); + + return 0; +} + + +static void main_menu(gchar buf) +{ + int err = 0; + int current_fps = 0; + int average_fps = 0; + char *err_attr_name = NULL; + + if (hmstreamrecorder->mode == MODE_LIVE_BUFFER_I420_VIDEO || hmstreamrecorder->mode == MODE_LIVE_BUFFER_NV12_VIDEO_SW) { + if (recorder_state == STREAMRECORDER_STATE_NONE) { + switch (buf) { + case '1': /* Start Recording*/ + hmstreamrecorder->elapsed_time = 0; + err = streamrecorder_start(hmstreamrecorder->recorder); + sleep(1); + g_timer_reset(timer); + err = __feed_buffer_test(hmstreamrecorder->recorder, hmstreamrecorder->mode); + if (err != MM_ERROR_NONE) + + g_print("Rec star in live buffer 0x%x", err); + if (err == 0) + LOGE("Rec start live buffer 0x%x", err); + + recorder_state = STREAMRECORDER_STATE_RECORDING; + break; + + case 'b': /* back*/ + hmstreamrecorder->menu_state = MENU_STATE_MAIN; + mode_change(); + break; + + default: + g_print("\t Invalid input \n"); + break; + } + } else if (recorder_state == STREAMRECORDER_STATE_RECORDING || recorder_state == STREAMRECORDER_STATE_PAUSED) { + switch (buf) { + if (recorder_state == STREAMRECORDER_STATE_RECORDING) { + case 'p': /* Pause Recording*/ + g_print("*Pause!\n"); + err = streamrecorder_pause(hmstreamrecorder->recorder); + + if (err < 0) + LOGE("Rec pause streamrecorder_pause = %x", err); + + recorder_state = STREAMRECORDER_STATE_PAUSED; + break; + + } else { + case 'r': /* Resume Recording*/ + g_print("*Resume!\n"); + err = streamrecorder_start(hmstreamrecorder->recorder); + if (err < 0) + LOGE("Rec start streamrecorder_record = %x", err); + + recorder_state = STREAMRECORDER_STATE_RECORDING; + break; + } + + case 'c': /* Cancel*/ + g_print("*Cancel Recording !\n"); + + err = streamrecorder_cancel(hmstreamrecorder->recorder); + + if (err < 0) + LOGE("Cancel recording streamrecorder_cancel = %x", err); + + recorder_state = STREAMRECORDER_STATE_NONE; + break; + + case 's': /* Save*/ + g_print("*Save Recording!\n"); + g_timer_reset(timer); + + err = streamrecorder_commit(hmstreamrecorder->recorder); + + if (err < 0) + LOGE("Save recording streamrecorder_commit = %x", err); + + recorder_state = STREAMRECORDER_STATE_NONE; + break; + + default: + g_print("\t Invalid input \n"); + break; + } /*switch*/ + } else { + LOGE("Wrong streamrecorder state, check status!!"); + } + } else { + g_print("\t Invalid mode, back to upper menu \n"); + hmstreamrecorder->menu_state = MENU_STATE_MAIN; + mode_change(); + } +} + + +/** +* 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 = NULL; + gsize read_size; + GError *g_error = NULL; + + LOGD("ENTER"); + + g_io_channel_read_line(channel, &buf, &read_size, NULL, &g_error); + if (g_error) { + LOGD("g_io_channel_read_chars error"); + g_error_free(g_error); + g_error = NULL; + } + + if (buf) { + g_strstrip(buf); + + LOGD("Menu Status : %d", hmstreamrecorder->menu_state); + switch (hmstreamrecorder->menu_state) { + case MENU_STATE_MAIN: + main_menu(buf[0]); + break; + default: + break; + } + + g_free(buf); + buf = NULL; + + print_menu(); + } else { + LOGD("No read input"); + } + + return TRUE; +} + +static gboolean init(int type) +{ + int err; + int size; + int support_zero_copy_format = 0; + int ischeck = 0; + char *err_attr_name = NULL; + + if (!hmstreamrecorder) + return FALSE; + + if (!hmstreamrecorder->recorder) + return FALSE; + + /*================================================================================ + Video capture mode + *=================================================================================*/ + if (type == MODE_LIVE_BUFFER_I420_VIDEO || type == MODE_LIVE_BUFFER_NV12_VIDEO_SW) { + if (type == MODE_LIVE_BUFFER_I420_VIDEO) { + err = streamrecorder_set_video_source_format(hmstreamrecorder->recorder, STREAMRECORDER_VIDEO_SOURCE_FORMAT_I420); + if (err < 0) { + LOGE("Init fail. (%x)", err); + goto ERROR; + } + } else if (type == MODE_LIVE_BUFFER_NV12_VIDEO_SW) { + err = streamrecorder_set_video_source_format(hmstreamrecorder->recorder, STREAMRECORDER_VIDEO_SOURCE_FORMAT_NV12); + if (err < 0) { + LOGE("Init fail. (%x)", err); + goto ERROR; + } + } + err = streamrecorder_set_file_format(hmstreamrecorder->recorder, STREAMRECORDER_FILE_FORMAT_MP4); + if (err < 0) { + LOGE("aInit fail. (%x)", err); + goto ERROR; + } + err = streamrecorder_set_video_encoder(hmstreamrecorder->recorder, STREAMRECORDER_VIDEO_CODEC_MPEG4); + if (err < 0) { + LOGE("bInit fail. (%x)", err); + goto ERROR; + } + err = streamrecorder_set_video_resolution(hmstreamrecorder->recorder, 1280, 720); + if (err < 0) { + LOGE("dInit fail. (%x)", err); + goto ERROR; + } + err = streamrecorder_set_video_framerate(hmstreamrecorder->recorder, 30); + if (err < 0) { + LOGE("dInit fail. (%x)", err); + goto ERROR; + } + err = streamrecorder_set_filename(hmstreamrecorder->recorder, TARGET_FILENAME_VIDEO); + if (err < 0) { + LOGE("dInit fail. (%x)", err); + goto ERROR; + } + } + + streamrecorder_set_recording_status_cb(hmstreamrecorder->recorder, _recording_status_cb, NULL); + streamrecorder_set_recording_limit_reached_cb(hmstreamrecorder->recorder, _recording_limit_reached_cb, &ischeck); + + LOGD("Init DONE."); + + return TRUE; + +ERROR: + LOGE("init failed."); + return FALSE; +} + +static gboolean init_handle() +{ + hmstreamrecorder->mode = 0; /* image(capture)/video(recording) mode */ + hmstreamrecorder->menu_state = MENU_STATE_MAIN; + hmstreamrecorder->isMute = FALSE; + hmstreamrecorder->elapsed_time = 0; + hmstreamrecorder->fps = SRC_VIDEO_FRAME_RATE_15; /*SRC_VIDEO_FRAME_RATE_30;*/ + + return TRUE; +} +/** +* This function is to change streamrecorder 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 = STREAMRECORDER_ERROR_NONE; + int state = STREAMRECORDER_STATE_NONE; + int name_size = 0; + int device_count = 0; + int facing_direction = 0; + char media_type = '\0'; + char *evassink_name = NULL; + bool check = FALSE; + + err = streamrecorder_get_state(hmstreamrecorder->recorder, (streamrecorder_state_e *)&state); + if (state != STREAMRECORDER_STATE_NONE) { + if ((state == STREAMRECORDER_STATE_RECORDING) || (state == STREAMRECORDER_STATE_PAUSED)) { + LOGD("streamrecorder_cancel"); + err = streamrecorder_cancel(hmstreamrecorder->recorder); + + if (err < 0) { + LOGE("exit streamrecorder_cancel = %x", err); + return FALSE; + } + } + + err = streamrecorder_get_state(hmstreamrecorder->recorder, (streamrecorder_state_e *)&state); + if (state == STREAMRECORDER_STATE_PREPARED) { + LOGD("streamrecorder_destroy"); + streamrecorder_unprepare(hmstreamrecorder->recorder); + } + + err = streamrecorder_get_state(hmstreamrecorder->recorder, (streamrecorder_state_e *)&state); + if (state == STREAMRECORDER_STATE_CREATED) { + LOGD("streamrecorder_destroy"); + streamrecorder_destroy(hmstreamrecorder->recorder); + } + } + + init_handle(); + streamrecorder_create(&hmstreamrecorder->recorder); + g_get_current_time(&previous); + g_timer_reset(timer); + while (!check) { + g_print("\n\t=======================================\n"); + g_print("\t RECORDER_TESTSUIT\n"); + g_print("\t=======================================\n"); + g_print("\t '1' i420 sw buffer - Video\n"); + g_print("\t '2' nv12 sw buffer - Video\n"); + g_print("\t 'q' Exit\n"); + g_print("\t=======================================\n"); + + g_print("\t Enter the media type:\n\t"); + + err = scanf("%c", &media_type); + if (err == EOF) { + g_print("\t!!!read input error!!!\n"); + continue; + } + + switch (media_type) { + case '1': + hmstreamrecorder->mode = MODE_LIVE_BUFFER_I420_VIDEO; + streamrecorder_enable_source_buffer(hmstreamrecorder->recorder, STREAMRECORDER_SOURCE_VIDEO); + check = TRUE; + break; + case '2': + hmstreamrecorder->mode = MODE_LIVE_BUFFER_NV12_VIDEO_SW; + streamrecorder_enable_source_buffer(hmstreamrecorder->recorder, STREAMRECORDER_SOURCE_VIDEO); + check = TRUE; + break; + case 'q': + g_print("\t Quit Streamrecorder Testsuite!!\n"); + hmstreamrecorder->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; + } + } + + g_timer_reset(timer); + + if (!init(hmstreamrecorder->mode)) { + g_print("hmstreamrecorder->mode = %d\n", hmstreamrecorder->mode); + LOGE("testsuite init() failed."); + return -1; + } + + g_timer_reset(timer); + + err = streamrecorder_prepare(hmstreamrecorder->recorder); + LOGD("streamrecorder_start() : %12.6lfs", g_timer_elapsed(timer, NULL)); + + if (err != 0) { + LOGE("streamrecorder_prepare = %x", err); + return -1; + } + + g_get_current_time(¤t); + timersub(¤t, &previous, &result); + LOGD("Streamrecorder Starting Time : %ld.%lds", result.tv_sec, result.tv_usec); + + return TRUE; +} + + +/** +* This function is the example main function for recorder API. +* +* @param +* +* @return This function returns 0. +* @remark +* @see other functions +*/ +int main(int argc, char **argv) +{ + int bret; + + timer = g_timer_new(); + + gst_init(&argc, &argv); + + LOGD("gst_init() : %12.6lfs", g_timer_elapsed(timer, NULL)); + + hmstreamrecorder = (mstreamrecorder_handle_t *) g_malloc0(sizeof(mstreamrecorder_handle_t)); + + recorder_state = STREAMRECORDER_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); + + LOGD("RUN main loop"); + + g_main_loop_run(g_loop); + + LOGD("STOP main loop"); + + if (timer) { + g_timer_stop(timer); + g_timer_destroy(timer); + timer = NULL; + } + + g_free(hmstreamrecorder); + g_main_loop_unref(g_loop); + g_io_channel_unref(stdin_channel); + + return bret; +} + +/*EOF*/