From: YoungHun Kim Date: Wed, 12 Jun 2024 10:16:25 +0000 (+0900) Subject: Initial Release X-Git-Tag: accepted/tizen/unified/20240801.021629~1 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=c90b99e8ef4c548275b93084851a51ab85d30659;p=platform%2Fcore%2Fmultimedia%2Fresource-manager.git Initial Release Change-Id: Idf763695e21499e52c22355f49f1d0417c40f739 --- diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..3653527 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,93 @@ +CMAKE_MINIMUM_REQUIRED(VERSION 2.6...2.29.2) +PROJECT(resource-manager CXX C) +IF(VD_UNIT_TEST) + ADD_DEFINITIONS(-DVD_UNIT_TEST) +ENDIF(VD_UNIT_TEST) + +#second modification +INCLUDE(FindPkgConfig) +pkg_check_modules(RM_PKGS REQUIRED + resource-information + dlog + glib-2.0 + gio-unix-2.0 + capi-system-resource +) + +IF(NOT DEFINED PACKAGE_NAME) + SET(PACKAGE_NAME ${PROJECT_NAME}) +ENDIF(NOT DEFINED PACKAGE_NAME) + +SET(PREFIX ${CMAKE_INSTALL_PREFIX}) +IF(NOT DEFINED BINDIR) + SET(IMAGEDIR "${PREFIX}/bin") +ENDIF(NOT DEFINED BINDIR) + +SET(CMAKE_EXE_LINKER_FLAGS "-Wl,--as-needed -Wl,--rpath=${LIBDIR}") + +SET(INC_PATH ${CMAKE_CURRENT_SOURCE_DIR}/include) +SET(INC_PATH_INTERNAL ${CMAKE_CURRENT_SOURCE_DIR}/include_internal) +SET(INC_FILE + ${INC_PATH}/rm_api.h + ${INC_PATH}/rm_type.h + ${INC_PATH}/rm_module_api.h + ${INC_PATH}/rm_resource.h + ${INC_PATH}/rm_shm_api.h + ${INC_PATH}/RMShm.h +) +SET(SRC + src/rm_api.cpp + src/rm_module_api.cpp + src/rm_debug.cpp + src/rm_callback.cpp + src/rm_msg.cpp + src/rm_dbus.cpp + src/rm_shm_api.cpp + src/RMShmCache.cpp +) + +SET(RC_HIJACK "off") +IF(RC_HIJACK STREQUAL on) +ADD_DEFINITIONS("-DRC_HIJACK") +SET(SRC ${SRC} + src/rm_rc_hijack.cpp +) +ENDIF() + + +MESSAGE("INC_PATH : "${INC_PATH}) +MESSAGE("INC_FILE : "${INC_FILE}) +MESSAGE("SRC : "${SRC}) + +INCLUDE_DIRECTORIES(${INC_PATH}) +INCLUDE_DIRECTORIES(${INC_PATH_INTERNAL}) +INCLUDE_DIRECTORIES(${RM_PKGS_INCLUDE_DIRS}) + +#IF(RM_UNIT_TEST) +# ADD_SUBDIRECTORY(ut) +#ENDIF(RM_UNIT_TEST) + +ADD_LIBRARY(${PROJECT_NAME} SHARED ${SRC}) + +CONFIGURE_FILE(resource-manager.pc.in "${CMAKE_CURRENT_SOURCE_DIR}/resource-manager.pc" @ONLY) + +FOREACH (flag ${RM_PKGS_CXXFLAGS}) + SET(EXTRA_CXXFLAGS "${EXTRA_CXXFLAGS} ${flag}") +ENDFOREACH(flag) + +SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${EXTRA_CXXFLAGS}") + +MESSAGE("RM_PKGS_LDFLAGS : "${RM_PKGS_LDFLAGS}) +TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${RM_PKGS_LDFLAGS}) + +SET_TARGET_PROPERTIES(${PROJECT_NAME} + PROPERTIES + VERSION ${VERSION} + SOVERSION ${MAJORVERSION} + CLEAN_DIRECT_OUTPUT 1 +) +# Install +INSTALL(TARGETS ${PROJECT_NAME} DESTINATION ${LIBDIR}) +INSTALL(FILES ${INC_FILE} DESTINATION ${INCLUDEDIR}) +INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/resource-manager.pc DESTINATION ${PKGCONFIG_INSTALL_DIR}) + 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/include/RMShm.h b/include/RMShm.h new file mode 100644 index 0000000..bc21e7d --- /dev/null +++ b/include/RMShm.h @@ -0,0 +1,280 @@ +/* + * Copyright (c) 2024 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 __RM_SHM_H__ +#define __RM_SHM_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/** +* @brief Shared memory object type +*/ +typedef enum { + RM_SHM_OBJ_PLAYER = 0, /**< the object including pair */ + RM_SHM_OBJ_SCALER, /**< the object including pair */ + RM_SHM_OBJ_AUDIO_OUT /**< the object including pair */ +} rm_shm_object_id; + +/** + * @vd_noapi + * @brief This class is for the shared memory between resource-manager and rscmgr-service + * @remark Please do not use this in other package. + */ +class CShmResource +{ +public: + /** + * @vd_noapi + * @brief Construct an instance of CShmResource class + * @param[in] device_id device id + * @param[in] state resource state + * @param[in] player_id player id using this resource + * @return None + * @pre None + * @post None + * @exception None + * @remark + * \li This is supposed to be used by resource-manager and rscmgr-service + * \li Do not use in other package + */ + CShmResource(): device_id_(-1), state_(-1), player_id_(-1) {} + + /** + * @vd_noapi + * @brief Construct an instance of CShmResource class + * @param[in] device_id device id + * @param[in] state resource state + * @param[in] player_id player id using this resource + * @return None + * @pre None + * @post None + * @exception None + * @remark + * \li This is supposed to be used by resource-manager and rscmgr-service + * \li Do not use in other package + */ + CShmResource(const int device_id, const int state, const int player_id): device_id_(device_id), state_(state), player_id_(player_id) {} + + /** + * @vd_noapi + * @brief Destruct an instance of CShmResource class + * @param None + * @return None + * @pre None + * @post None + * @exception None + * @remark + * \li This is supposed to be used by resource-manager and rscmgr-service + * \li Do not use in other package + */ + ~CShmResource() = default; + + /** + * @vd_noapi + * @brief Get device id + * @param None + * @return device id + * @pre None + * @post None + * @exception None + * @remark + * \li This is supposed to be used by resource-manager and rscmgr-service + * \li Do not use in other package + */ + int GetDeviceID(void) { return device_id_; } + + /** + * @vd_noapi + * @brief Set resource state + * @param[in] state resource state + * @return None + * @pre None + * @post None + * @exception None + * @remark + * \li This is supposed to be used by resource-manager and rscmgr-service + * \li Do not use in other package + */ + void SetState(const int state) { state_ = state; } + + /** + * @vd_noapi + * @brief Get resource state + * @param None + * @return resource state + * @pre None + * @post None + * @exception None + * @remark + * \li This is supposed to be used by resource-manager and rscmgr-service + * \li Do not use in other package + */ + int GetState(void) { return state_; } + + /** + * @vd_noapi + * @brief Set player id using this resource + * @param[in] player_id player id + * @return None + * @pre None + * @post None + * @exception None + * @remark + * \li This is supposed to be used by resource-manager and rscmgr-service + * \li Do not use in other package + */ + void SetPlayerID(const int player_id) { player_id_ = player_id; } + + /** + * @vd_noapi + * @brief Get player id + * @param None + * @return player id + * @pre None + * @post None + * @exception None + * @remark + * \li This is supposed to be used by resource-manager and rscmgr-service + * \li Do not use in other package + */ + int GetPlayerID(void) { return player_id_; } + +protected: + /** + * @vd_noapi + * @brief Set device id + * @param None + * @return device id + * @pre None + * @post None + * @exception None + * @remark + * \li This is supposed to be used by resource-manager and rscmgr-service + * \li Do not use in other package + */ + void SetDeviceID(const int device_id) { device_id_ = device_id; } + +private: + int device_id_; + int state_; + int player_id_; +}; + +/** + * @vd_noapi + * @brief This class is for the shared memory between resource-manager and rscmgr-service + * @remark Please do not use this in other package. + */ +class CShmScaler : public CShmResource +{ +public: + /** + * @vd_noapi + * @brief Construct an instance of CShmScaler class + * @param[in] device_id device id of scaler + * @param[in] state resource state of scaler + * @param[in] zone_id multiview zone id of scaler + * @return None + * @pre None + * @post None + * @exception None + * @remark + * \li This is supposed to be used by resource-manager and rscmgr-service + * \li Do not use in other package + */ + CShmScaler(const int device_id, const int state, const int zone_id): zone_id_(zone_id), virtual_id_(-1) { CShmResource::SetDeviceID(device_id); CShmResource::SetState(state); } + + /** + * @vd_noapi + * @brief Destruct an instance of CShmScaler class + * @param None + * @return None + * @pre None + * @post None + * @exception None + * @remark + * \li This is supposed to be used by resource-manager and rscmgr-service + * \li Do not use in other package + */ + ~CShmScaler() = default; + + /** + * @vd_noapi + * @brief Set multiview zone id + * @param[in] id multiview zone id + * @return None + * @pre None + * @post None + * @exception None + * @remark + * \li This is supposed to be used by resource-manager and rscmgr-service + * \li Do not use in other package + */ + void SetZoneID(const int id) { zone_id_ = id; } + + /** + * @vd_noapi + * @brief Get multiview zone id + * @param None + * @return multiview zone id + * @pre None + * @post None + * @exception None + * @remark + * \li This is supposed to be used by resource-manager and rscmgr-service + * \li Do not use in other package + */ + int GetZoneID(void) { return zone_id_; } + + /** + * @vd_noapi + * @brief Set virtual id + * @param[in] id virtual id + * @return None + * @pre None + * @post None + * @exception None + * @remark + * \li This is supposed to be used by resource-manager and rscmgr-service + * \li Do not use in other package + */ + void SetVirtualID(const int id) { virtual_id_ = id; } + + /** + * @vd_noapi + * @brief Get virtual id + * @param None + * @return virtual id + * @pre None + * @post None + * @exception None + * @remark + * \li This is supposed to be used by resource-manager and rscmgr-service + * \li Do not use in other package + */ + int GetVirtualID(void) { return virtual_id_; } + +private: + int zone_id_; + int virtual_id_; +}; + +#ifdef __cplusplus +} +#endif +#endif //__RM_SHM_H__ diff --git a/include/rm_api.h b/include/rm_api.h new file mode 100644 index 0000000..60167a7 --- /dev/null +++ b/include/rm_api.h @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2024 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 __RM_API_H__ +#define __RM_API_H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Register a player + * @param[in] cb callback to receive resource conflict event + * @param[in] data user data passed to cb + * @param[out] handle handle got from resource manager + * @param[in] consumer_info player information such as player type, priority, window id and so on + * @return int failure reason + * @pre None + * @post None + * @exception None + */ +int rm_register(rm_resource_cb cb, void *data, int *handle, rm_consumer_info *consumer_info); + +/** + * @brief Unregister a player + * @param[in] handle handle to unregister + * @return int failure reason + * @pre None + * @post handle is deactivated.\n + * All resources which have been allocated to handle are released + * @exception None + */ +int rm_unregister(int handle); + +/** + * @brief request to allocate resources + * @param[in] handle handle to which resources are to be allocated + * @param[in] requests Resource information to allocate + * can request N resources simultaneously + * Ex. {Resource A, Resource A, Resouce B,¡¦. Resouce N} + * @param[out] return_devices allocated Device ID. Caller needs to release memory allocated by Resource Manager + * !!IMPORTANT!!! + * The member of structure(device_node, omx_comp_name) must be freed by API caller side. + * @return int failure reason + * @pre None + * @post None + * @exception None + */ +int rm_allocate_resources(int handle, const rm_category_request_s *requests, rm_device_return_s *return_devices); + +/** + * @brief request to release resources + * @param[in] handle handle to which resources have been allocated + * @param[in] requests device information to release + * @return int failure reason + * @pre None + * @post None + * @exception None + */ +int rm_deallocate_resources(int handle, rm_device_request_s *requests); + +/** + * @brief Query resource state + * @param[in] handle handle gotten from rm_register() + * @param[in] query_type query type such as allocation + * @param[in] requests Resource information to query + * @param[out] query_result 0: not available + * 1: available + * @return int failure reason + * @pre None + * @post None + * @exception None + */ +int rm_query(int handle, rm_query_type_e query_type, rm_category_request_s *requests, int *query_result); + +/** + * @brief Set priority of handle + * @param[in] handle handle to change priority + * @param[in] priority new priority of handle + * @return int failure reason + * @pre None + * @post None + * @exception None + */ +int rm_set_priority(int handle, int priority); + +/** + * @brief Set application id of handle + * @param[in] handle handle to change application id + * @param[in] app_id new application id of handle + * @return int failure reason + * @pre None + * @post None + * @exception None + */ +int rm_set_app_id(int handle, char *app_id); + + +#ifdef __cplusplus +} +#endif +#endif // __RM_API_H__ \ No newline at end of file diff --git a/include/rm_module_api.h b/include/rm_module_api.h new file mode 100644 index 0000000..05ab413 --- /dev/null +++ b/include/rm_module_api.h @@ -0,0 +1,653 @@ +/* + * Copyright (c) 2024 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 __RM_MODULE_API_H__ +#define __RM_MODULE_API_H__ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief The resource category option to select a resource + * @remark This is supposed to be used by the resource center only + * @version 3.0 + */ +typedef enum { + RM_FORCE_TO_MAIN = (0x1 << 27), + RM_FORCE_TO_SUB = (0x1 << 26) +} rm_device_request_e; + +/** + * @brief The resource collection + * @remark This is supposed to be used by the resource center only + * @version 4.0 + */ +typedef enum { + RM_RSC_COLLECTION_MAIN = 0, /**< main resources */ + RM_RSC_COLLECTION_ACTIVE_VIDEO_DECODER, /**< active video decoders */ + RM_RSC_COLLECTION_AUDIO /**< audio resources (audio decoder, audio out) */ +} rm_rsc_collection_e; + +/** + * @brief The audio out type + * @remark This is supposed to be used by the resource center only + * @version 3.0 + */ +typedef enum { + RM_AUDIO_OUT_NONE = 0, + RM_AUDIO_OUT_MAIN = 0x1, + RM_AUDIO_OUT_SUB = 0x2, +} rm_audio_out_e; + +/** + * @brief The video sampling format + * @remark This is used as a return value of rm_resource_get_max_sampling_format() + * @version 3.0 + */ +typedef enum { + RM_SAMPLING_FORMAT_ARGB = 0, /**< ARGB */ + RM_SAMPLING_FORMAT_420, /**< YUV420 */ + RM_SAMPLING_FORMAT_422, /**< YUV422 */ + RM_SAMPLING_FORMAT_444 /**< YUV444 */ +} rm_sampling_format_e; + +/** + * @brief The video resolution + * @remark This is used as a return value of rm_resource_get_max_resolution() + * @version 3.0 + */ +typedef enum { + RM_RESOLUTION_HD = 0, /**< HD */ + RM_RESOLUTION_FHD, /**< FHD */ + RM_RESOLUTION_4K, /**< 4K */ + RM_RESOLUTION_8K /**< 8K */ +} rm_resolution_e; + +/** + * @brief Get current resource state + * @param[in] rsc_id resource id + * @param[out] state current resource state + * @return RM_OK on success, otherwise RM_ERROR + * @pre None + * @post None + * @version 3.0 + * @exception None + */ +int rm_get_resource_state(int rsc_id, rm_resource_state_e *state); + +/** + * @brief Get the resource list handle of video scaler + * @param[out] list resource list handle + * @return RM_OK on success, otherwise RM_ERROR + * @pre None + * @post None + * @version 3.0 + * @exception None + * @remark + * \li This API is supposed to be used by the resource center for internal use + * \li Please do not use for other purpose + * \li The returned list must be freed by rm_free_resource_list() after use + */ +int rm_get_scaler_state(rm_resource_list_h *list); + +/** + * @brief Called when scaler state is changed + * @param[out] scalers Scaler list + * @param[out] data The user data passed from the callback registration function + * @pre None + * @post None + * @version 3.0 + */ +typedef void (*scaler_state_change_cb)(rm_resource_list_h scalers, void *data); + +/** + * @brief Register a callback to observe scaler state change + * @details Once there is any state change of scaler, the registered callback will be invoked. + * @param[in] cb The callback function to register + * @param[in] data The user data to be passed to the callback function + * @return @c RM_OK on success, + * otherwise RM_ERROR + * @pre None + * @post None + * @exception None + * @version 3.0 + * @remark + * \li This API is supposed to be used by the resource center for internal use + * \li Please do not use for other purpose + */ +int rm_subscribe_scaler_state_change(scaler_state_change_cb cb, void *data); + +/** + * @brief Unregister a callback which had been added to observe scaler state change + * @param[in] cb The callback function to unregister + * @return @c RM_OK on success, + * otherwise RM_ERROR + * @pre None + * @post None + * @exception None + * @version 3.0 + * @remark + * \li This API is supposed to be used by the resource center for internal use + * \li Please do not use for other purpose + */ +int rm_unsubscribe_scaler_state_change(scaler_state_change_cb cb); + +/** + * @brief Get virtual id of scaler + * @param[in] scaler scaler handle + * @return virtual id of scaler + * @pre None + * @post None + * @exception None + * @version 3.0 + * @remark + * \li This API is supposed to be used by the resource center for internal use + * \li Please do not use for other purpose + */ +int rm_scaler_get_virtual_id(rm_resource_h scaler); + +/** + * @brief Get source id of scaler + * @param[in] scaler scaler handle + * @return source id of scaler + * @pre None + * @post None + * @exception None + * @version 3.0 + * @remark + * \li This API is supposed to be used by the resource center for internal use + * \li Please do not use for other purpose + */ +int rm_scaler_get_source_id(rm_resource_h scaler); + +/** + * @brief Called when a resource state is changed + * @param[out] state The resource state handle + * @param[out] data The user data passed from the callback registration function + * @pre None + * @post None + * @version 3.0 + * @remarks The data of the resource state handle can be accessed by the following APIs. + * rm_rsc_state_get_category() + * rm_rsc_state_get_id() + * rm_rsc_state_get_state() + * The passed resource state handle is valid in resource_state_change_cb() only. + * In other words, the passed resource state handle is freed once resource_state_change_cb() returns. + * Thus, need a deep copy in case information of the resource state handle is required outside of resource_state_change_cb(). + */ +typedef void (*resource_state_change_cb)(rm_resource_state_h state, void *data); + +/** + * @brief Register a callback to observe resource state change + * @details Once there is state change of a resource included in passed category, the registered callback will be invoked. + * @param[in] category category id to observe + * @param[in] cb The callback function to register + * @param[in] data The user data to be passed to the callback function + * @return @c RM_OK on success, + * otherwise RM_ERROR + * @pre None + * @post None + * @exception None + * @version 3.0 + */ +int rm_subscribe_resource_state_change(rm_rsc_category_e category, resource_state_change_cb cb, void *data); + +/** + * @brief Unregister a callback which had been added to observe resource state change + * @param[in] category category id to stop to observe + * @param[in] cb The callback function to unregister + * @return @c RM_OK on success, + * otherwise RM_ERROR + * @pre None + * @post None + * @exception None + * @version 3.0 + */ +int rm_unsubscribe_resource_state_change(rm_rsc_category_e category, resource_state_change_cb cb); + +/** + * @brief Get category id of the state changed resource + * @param[in] state The state changed resource handle + * @return category id of the state changed resource handle on success, + * otherwise negative value + * @pre None + * @post None + * @exception None + * @version 3.0 + */ +int rm_rsc_state_get_category(rm_resource_state_h state); + +/** + * @brief Get device id of the state changed resource + * @param[in] state The state changed resource handle + * @return device id of the state changed resource handle on success, + * otherwise negative value + * @pre None + * @post None + * @exception None + * @version 3.0 + */ +int rm_rsc_state_get_device_id(rm_resource_state_h state); + +/** + * @brief Get state of the state changed resource + * @param[in] state The state changed resource handle + * @return state of the state changed resource handle on success, + * otherwise negative value + * @pre None + * @post None + * @exception None + * @version 3.0 + */ +int rm_rsc_state_get_state(rm_resource_state_h state); + +/** + * @brief Get consumer id of the state changed resource + * @param[in] state The state changed resource handle + * @return consumer id of the state changed resource handle on success, + * otherwise negative value + * @pre None + * @post None + * @exception None + * @version 3.0 + */ +int rm_rsc_state_get_consumer_id(rm_resource_state_h state); + +/** + * @brief Get app id of the state changed resource + * @param[in] state The state changed resource handle + * @return app id of the state changed resource handle on success, + * otherwise NULL + * @pre None + * @post None + * @exception None + * @version 3.0 + */ +char *rm_rsc_state_get_app_id(rm_resource_state_h state); + +struct rm_conflict_resource; +/** + * @brief The conflicted resource handle + */ +typedef struct rm_conflict_resource *rm_conflict_resource_h; + +/** + * @brief Called when a resource conflict occurs + * @param[out] resource The conflicted resource handle + * @param[out] data The user data passed from the callback registration function + * @pre None + * @post None + * @version 3.0 + * @remarks The data of the conflicted resource handle can be accessed by the following APIs. + * rm_conflict_get_category_id() + * rm_conflict_get_device_id() + * rm_conflict_get_consumer_id() + * rm_conflict_get_app_id() + * The passed conflicted resource handle is valid in rm_conflict_event_cb() only. + * In other words, the passed conflicted resource handle is freed once rm_conflict_event_cb() returns. + * Thus, need a deep copy in case information of the conflicted resource handle is required outside of rm_conflict_event_cb(). + */ +typedef void (*rm_conflict_event_cb)(rm_conflict_resource_h resource, void *data); + +/** + * @brief Register a callback to observe resource conflict event. + * @details Once there is a resource conflict, the registered callback will be invoked. + * @param[in] cb The callback function to add + * @param[in] data The user data to be passed to the callback function + * @return @c RM_OK on success, + * otherwise RM_ERROR + * @pre None + * @post None + * @exception None + * @version 3.0 + */ +int rm_subscribe_resource_conflict_event(rm_conflict_event_cb cb, void *data); + +/** + * @brief Unregister a callback which had been added to observe resource conflict event. + * @param[in] cb The callback function to remove + * @return @c RM_OK on success, + * otherwise RM_ERROR + * @pre None + * @post None + * @exception None + * @version 3.0 + */ +int rm_unsubscribe_resource_conflict_event(rm_conflict_event_cb cb); + +/** + * @brief Gets resource category id of the conflicted resource + * @param[in] rsc The conflicted resource handle + * @return resource category id of the conflicted resource handle on success, + * otherwise negative value + * @pre None + * @post None + * @exception None + * @version 3.0 + */ +int rm_conflict_get_category_id(rm_conflict_resource_h rsc); + +/** + * @brief Gets device id of the conflicted resource + * @param[in] rsc The conflicted resource handle + * @return device id of the conflicted resource handle on success, + * otherwise negative value + * @pre None + * @post None + * @exception None + * @version 3.0 + */ +int rm_conflict_get_device_id(rm_conflict_resource_h rsc); + +/** + * @brief Gets consumer id of the conflicted resource + * @param[in] rsc The conflicted resource handle + * @return consumer id of the conflicted resource handle on success, + * otherwise negative value + * @pre None + * @post None + * @remarks The consumer id is an unique id which is assigned to a player as a result of rm_register(). + * @exception None + * @version 3.0 + */ +int rm_conflict_get_consumer_id(rm_conflict_resource_h rsc); + +/** + * @brief Gets application id of the conflicted resource + * @param[in] rsc The conflicted resource handle + * @return application id of the conflicted resource on success + * otherwise NULL + * @pre None + * @post None + * @remarks In case any application id is not set by a player, NULL can be returned on success. + * @exception None + * @version 3.0 + */ +const char *rm_conflict_get_app_id(rm_conflict_resource_h rsc); + +/** + * @brief Gets multiview zone id of the consumer that needs to release the conflicted resource + * @param[in] rsc The conflicted resource handle + * @return multiview zone id in case the conflicted resource is allocated to a multiview zone + * otherwise negative value + * @pre None + * @post None + * @exception None + * @version 3.0 + */ +int rm_conflict_get_multiview_zone_id_consumer(rm_conflict_resource_h rsc); + +/** + * @brief Gets multiview zone id of the requester that caused this resource conflict + * @param[in] rsc The conflicted resource handle + * @return multiview zone id in case the requester is placed to a multiview zone + * otherwise negative value + * @pre None + * @post None + * @exception None + * @version 3.0 + */ +int rm_conflict_get_multiview_zone_id_requester(rm_conflict_resource_h rsc); + +/** + * @brief Unmask category option bits + * @param[in] category resource category to unmask + * @return unmasked category id + * @pre None + * @post None + * @exception None + * @version 3.0 + * @remark + */ +int rm_unmask_category_options(int category); + +/** + * @brief Find real device id which is mapped to virtual device id + * @param[in] virtual_id virtual device id + * @return positive real resource id on success, negative value on failure + * @pre None + * @post None + * @exception None + * @version 3.0 + * @remark + * \li This API is available for the scaler device supporting virtual device. + */ +int rm_find_device_id(int virtual_id); + +/** + * @brief Swap two resources + * @param[in] device_id_a device id to swap + * @param[in] device_id_b device id to swap + * @return RM_OK on success, otherwise RM_ERROR + * @pre None + * @post None + * @exception None + * @version 3.0 + * @remark + * \li This API is available for the scaler device supporting virtual device. + * \li This API is supposed to be called by the resource center only + */ +int rm_swap_resources(int device_id_a, int device_id_b); + +/** + * @brief Swap two resources asynchronously + * @param[in] device_id_a device id to swap + * @param[in] device_id_b device id to swap + * @return RM_OK on success, otherwise RM_ERROR + * @pre None + * @post None + * @exception None + * @version 3.1 + * @remark + * \li This API is available for the scaler device supporting virtual device. + * \li This API is supposed to be called by the resource center only + */ +int rm_swap_resources_async(int device_id_a, int device_id_b); + +/** + * @brief Restore resources that have been swapped by rm_swap_resources() + * @param[in] category resource category to restore + * @return RM_OK on success, otherwise RM_ERROR + * @pre None + * @post None + * @exception None + * @version 3.0 + * @remark + * \li This API is supposed to be called by the resource center only + */ +int rm_restore_resources(int category); + +/** + * @brief Get the resource list handle of resource collection + * @param[in] collection resource collection + * @param[out] list resource list handle + * @return RM_OK on success, otherwise RM_ERROR + * @pre None + * @post None + * @exception None + * @version 3.0 + * @remark + * \li The returned list must be freed by rm_free_resource_list() after use + */ +int rm_get_resource_collection_state(rm_rsc_collection_e collection, rm_resource_list_h *list); + +/** + * @brief Get application id of handle + * @param[in] handle player handle returned by rm_register() + * @param[out] app_id application id of handle + * @return RM_OK on success, otherwise RM_ERROR + * @pre None + * @post None + * @exception None + * @version 3.0 + * @remark + * \li This API is supposed to be called by the resource center only + * \li Do not use other purpose + */ +int rm_get_app_id(int handle, char**app_id); + +/** + * @brief Get active audio out resources being used by handle + * @param[in] handle player handle returned by rm_register() + * @return positive value masked with rm_audio_out_e on success, otherwise negative value + * @pre None + * @post None + * @exception None + * @version 3.0 + * @remark + * \li This API is supposed to be called by the resource center only + * \li Do not use other purpose + */ +int rm_get_active_audio_out(int handle); + +/** + * @brief Get hw id of scaler assigned to passed multiview zone id + * @param[in] zone_id multiview zone id + * @param[out] id The hw id of scaler assigned to passed multiview zone id, + * @return positive value on success, otherwise negative value + * @pre None + * @post None + * @exception None + * @version 3.0 + * @remark + * \li This API is supposed to be called by the resource center only + * \li Do not use other purpose + */ +int rm_get_scaler_hw_id(int zone_id, int *id); + +/** + * @brief Notify current resource policy + * @param[in] policy resource policy + * @return positive value on success, otherwise negative value + * @pre None + * @post None + * @exception None + * @version 3.1 + * @remark + * \li This API is supposed to be called by the resource center only + * \li Do not use other purpose + */ +int rm_notify_resource_policy(int policy); + +/** + * @brief Notify application's zone info in multiview + * @param[in] app_id application id + * @param[in] zone_id zone id + * @return positive value on success, otherwise negative value + * @pre None + * @post None + * @exception None + * @version 5.0 + * @remark + * \li This API is supposed to be called by the resource center only + * \li Do not use other purpose + */ +int rm_notify_app_zone_info_async(const char *app_id, int zone_id); + +/** + * @brief Reclaim all resources allocated to the handle + * @param[in] handle player handle returned by rm_register() + * @return positive value on success, otherwise negative value + * @pre None + * @post None + * @exception None + * @version 4.0 + * @remark + * \li This API is supposed to be called by the resource center only + * \li Do not use other purpose + */ +int rm_reclaim_resources(int handle); + +/** + * @brief Reclaim all resources allocated to the application + * @param[in] app_id application id + * @param[in] notify true : notify resource conflict, false : skip to notify + * @return positive value on success, otherwise negative value + * @pre None + * @post None + * @exception None + * @version 5.0 + * @remark + * \li This API is supposed to be called by the resource center only + * \li Do not use other purpose + */ +int rm_reclaim_app_resources(const char *app_id, const bool notify); + + +/** + * @brief Reclaim all resources allocated to the application asynchronously + * @param[in] app_id application id + * @param[in] notify true : notify resource conflict, false : skip to notify + * @return positive value on success, otherwise negative value + * @pre None + * @post None + * @exception None + * @version 5.0 + * @remark + * \li This API is supposed to be called by the resource center only + * \li Do not use other purpose + */ +int rm_reclaim_app_resources_async(const char *app_id, const bool notify); + +/** + * @brief Reclaim all video decoders allocated to applications other than requester + * @param[in] requester application id of the requester + * @return RM_OK on success, otherwise RM_ERROR + * @pre None + * @post None + * @exception None + * @version 5.0 + * @remark + * \li This API is supposed to be called by the camera framework only + * \li Do not use for other purpose + */ +int rm_reclaim_video_decoders(const char *requester); + +/** + * @brief Check if the handle is valid or not + * @param[in] handle player handle returned by rm_register() + * @return true : player handle is valid, false : player handle is invalid + * @pre None + * @post None + * @exception None + * @version 6.0 + * @remark + * \li This API is supposed to be called by the resource center only + * \li Do not use for other purpose + */ +bool rm_active_player(const int handle); + +/** + * @brief Check if the player is in progress of reclaiming resource + * @param[in] handle player handle returned by rm_register() + * @return true : reclaim is in progress against the player, false : reclaim is not in progress against the player + * @pre None + * @post None + * @exception None + * @remark + * \li This API is supposed to be called by the resource center only + * \li Do not use for other purpose + */ +bool rm_reclaimed_player(const int handle); + +#ifdef __cplusplus +} +#endif +#endif //__RM_MODULE_API_H__ diff --git a/include/rm_resource.h b/include/rm_resource.h new file mode 100644 index 0000000..2e9adad --- /dev/null +++ b/include/rm_resource.h @@ -0,0 +1,326 @@ +/* + * Copyright (c) 2024 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 __RM_RESOURCE_H__ +#define __RM_RESOURCE_H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Create a resource list handle + * @param None + * @return resource list handle on success, otherwise NULL + * @pre None + * @post None + * @exception None + * @version 3.0 + * @remark + * \li The returned list must be freed by rm_free_resource_list() after use + */ +rm_resource_list_h rm_resource_list_create(void); + +/** + * @brief Get the resource list handle of resource category + * @param[in] category resource category + * @param[out] list resource list handle + * @return RM_OK on success, otherwise RM_ERROR + * @pre None + * @post None + * @exception None + * @version 3.0 + * @remark + * \li The returned list must be freed by rm_free_resource_list() after use + */ +int rm_get_resource_list(rm_rsc_category_e category, rm_resource_list_h *list); + +/** + * @brief Free resource list handle + * @param[in] list resource list handle + * @return None + * @pre None + * @post None + * @exception None + * @version 3.0 + * @remark + * \li The elements in the list will be freed as well + */ +void rm_free_resource_list(rm_resource_list_h list); + +/** + * @brief Append a resource to the resource list + * @param[in] list resource list handle + * @param[out] resource resource handle + * @return RM_OK on success, otherwise RM_ERROR + * @pre None + * @post None + * @exception None + */ +int rm_resource_list_append(rm_resource_list_h list, rm_resource_h resource); + +/** + * @brief Get next resource handle from resource list handle + * @param[in] list resource list handle + * @return next resource handle + * In case there is no next resource handle or error, returns NULL + * @pre None + * @post None + * @exception None + */ +rm_resource_h rm_resource_list_get_next(rm_resource_list_h list); + +/** + * @brief Get previous resource handle from resource list handle + * @param[in] list resource list handle + * @return previous resource handle + * In case there is no previous resource handle or error, returns NULL + * @pre None + * @post None + * @exception None + */ +rm_resource_h rm_resource_list_get_prev(rm_resource_list_h list); + +/** + * @brief Get first resource handle from resource list handle + * @param[in] list resource list handle + * @return first resource handle + * In case there is no previous resource handle or error, returns NULL + * @pre None + * @post None + * @exception None + */ +rm_resource_h rm_resource_list_get_first(rm_resource_list_h list); + +/** + * @brief Get last resource handle from resource list handle + * @param[in] list resource list handle + * @return last resource handle + * @pre In case there is no last resource handle or error, returns NULL + * @post None + * @exception None + */ +rm_resource_h rm_resource_list_get_last(rm_resource_list_h list); + +/** + * @brief Get number of resource handles in resource list handle + * @param[in] list resource list handle + * @return number of resource handles in resource list handle + * @pre None + * @post None + * @exception None + */ +int rm_resource_list_get_count(rm_resource_list_h list); + +/** + * @brief Get node of the resource + * @param[in] resource resource handle + * @return node of the resource + * @pre None + * @post None + * @exception None + */ +const char *rm_resource_get_node(rm_resource_h resource); + +/** + * @brief Get id of the resource + * @param[in] resource resource handle + * @return resource id + * @pre None + * @post None + * @exception None + */ +int rm_resource_get_id(rm_resource_h resource); + +/** + * @brief Get category id of the resource + * @param[in] resource resource handle + * @return resource id + * @pre None + * @post None + * @exception None + */ +int rm_resource_get_category(rm_resource_h resource); + +/** + * @brief Get category id of the resource + * @param[in] resource resource handle + * @return resource id + * @pre None + * @post None + * @exception None + */ +int rm_resource_get_cur_category(rm_resource_h resource); + +/** + * @brief Get consumer id using the resource + * @param[in] resource resource handle + * @return resource id + * @pre None + * @post None + * @exception None + */ +int rm_resource_get_consumer(rm_resource_h resource); + +/** + * @brief Get state of the resource + * @param[in] resource resource handle + * @return resource id + * @pre None + * @post None + * @exception None + */ +int rm_resource_get_state(rm_resource_h resource); + +/** + * @brief Get application id using the resource + * @param[in] resource resource handle + * @return resource id + * @pre None + * @post None + * @exception None + */ +const char *rm_resource_get_app_id(rm_resource_h resource); + +/** + * @brief Check whether the resource is being used by the android app + * @param[in] resource resource handle + * @return true : the resource is being used by the android app, false : not being used by the android app + * @pre None + * @post None + * @exception None + */ +bool rm_resource_android_app(const rm_resource_h resource); + +/** + * @brief Get framerate of the resource + * @param[in] resource resource handle + * @return framerate + * @pre None + * @post None + * @version 3.0 + * @exception None + */ +unsigned int rm_resource_get_framerate(rm_resource_h resource); + +/** + * @brief Get max resolution of the resource + * @param[in] resource resource handle + * @return max resolution. This is one of rm_resolution_e values. + * @pre None + * @post None + * @exception None + * @version 3.0 + * @remark + * \li The API is valid for the resource belongs to RM_CATEGORY_DISPLAY_OUT + */ +int rm_resource_get_max_resolution(rm_resource_h resource); + +/** + * @brief This function returns whether the resource supports overlay or not + * @param[in] resource resource handle + * @return true : overlay supported, false : overlay not supported + * @pre None + * @post None + * @exception None + * @version 3.0 + * @remark + * \li The API is valid for the resource belongs to RM_CATEGORY_DISPLAY_OUT + */ +bool rm_resource_support_overlay(rm_resource_h resource); + +/** + * @brief Get max sampling format of the resource + * @param[in] resource resource handle + * @return max color format. This is one of rm_sampling_format_e values. + * @pre None + * @post None + * @exception None + * @remark + * \li The API is valid for the resource belongs to RM_CATEGORY_DISPLAY_OUT + */ +int rm_resource_get_max_sampling_format(rm_resource_h resource); + +/** + * @brief Get multiview zone id of the resource + * @param[in] resource resource handle + * @return multiview zone id + * @pre None + * @post None + * @exception None + * @remark + * \li The API is valid for the resource belongs to RM_CATEGORY_SCALER + */ +int rm_resource_get_zone_id(rm_resource_h resource); + +/** + * @brief Get width of the resource + * @param[in] resource resource handle + * @return width of the content to be encoded + * @pre None + * @post None + * @exception None + * @remark + * \li The API is valid for the resource belongs to RM_CATEGORY_VIDEO_ENCODER + */ +unsigned int rm_resource_get_width(const rm_resource_h resource); + +/** + * @brief Get height of the resource + * @param[in] resource resource handle + * @return height of the content to be encoded + * @pre None + * @post None + * @exception None + * @remark + * \li The API is valid for the resource belongs to RM_CATEGORY_VIDEO_ENCODER + */ +unsigned int rm_resource_get_height(const rm_resource_h resource); + +/** + * @brief Create a video encoder handle + * @param[in] width width of the content to encode (in pixel) + * @param[in] height height of the content to encode (in pixel) + * @param[in] framerate frame rate of the content to encode (frame per second) + * @return resource handle on success, otherwise NULL + * @pre None + * @post None + * @exception None + * @remark + * \li If the returned resource handle is appended to the resource list then you can free this with rm_free_resource_list() + */ +rm_resource_h rm_create_video_encoder(const unsigned int width, const unsigned int height, const unsigned int framerate); + +/** + * @brief Checks whether the video encoders in the list are allocatable for multi encoding scenario + * @param[in] list the resource list including the video encoders + * @param[out] result true : allocatable, false : not allocatable + * @return RM_OK on success, otherwise RM_ERROR + * @pre None + * @post None + * @exception None + * @remark + * \li This function checks whether the video encoders are allocatable based on available bandwidth of the video encoder. + * \li In other words, the result can be different depending on current video encoder usage status. + */ +int rm_allocatable_video_encoders(const rm_resource_list_h list, bool *result); + +#ifdef __cplusplus +} +#endif +#endif //__RM_RESOURCE_H__ diff --git a/include/rm_shm_api.h b/include/rm_shm_api.h new file mode 100644 index 0000000..7e285d3 --- /dev/null +++ b/include/rm_shm_api.h @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2024 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 __RM_SHM_API_H__ +#define __RM_SHM_API_H__ +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @vd_noapi + * @brief Get application id of handle from shared memory + * @param[in] handle player handle returned by rm_register() + * @param[out] app_id application id of handle + * @return RM_OK on success, otherwise RM_ERROR + * @pre None + * @post None + * @exception None + * @remark + * \li This API is supposed to be called by the resource center only + * \li Do not use for other purpose + */ +int rm_shm_get_app_id(const int handle, char** app_id); + +/** + * @vd_noapi + * @brief Find hardware id of scaler allocated to a multiview zone + * @param[in] zone_id multiview zone id + * @param[out] hw_id hardware id of scaler + * @return RM_OK on success, otherwise RM_ERROR + * @pre None + * @post None + * @exception None + * @remark + * \li This API is supposed to be called by the resource center only + * \li Do not use for other purpose + */ +int rm_shm_find_scaler_hw_id(const int zone_id, int *hw_id); + +/** + * @vd_noapi + * @brief Find device id of scaler + * @param[in] virtual_id scaler virtual id + * @param[out] device_id scaler device id + * @return RM_OK on success, otherwise RM_ERROR + * @pre None + * @post None + * @exception None + * @remark + * \li This API is supposed to be called by the resource center only + * \li Do not use for other purpose + */ +int rm_shm_find_device_id(const int virtual_id, int *device_id); + +/** + * @vd_noapi + * @brief Find player list using main audio out + * @param[in] list player list + * @return RM_OK on success, otherwise RM_ERROR + * @pre None + * @post None + * @exception None + * @remark + * \li This API is supposed to be called by the resource center only + * \li Do not use for other purpose + */ +int rm_shm_find_players_using_audio_main_out(rm_resource_list_h *list); + +/** + * @vd_noapi + * @brief Get audio out being used by handle + * @param[in] handle player id + * @param[out] audio_out audio outs being used by handle + * @return RM_OK on success, otherwise RM_ERROR + * @pre None + * @post None + * @exception None + * @remark + * \li This API is supposed to be called by the resource center only + * \li Do not use for other purpose + */ +int rm_shm_get_active_audio_out(const int handle, int *audio_out); + +/** + * @vd_noapi + * @brief Check if the player handle is registered or not + * @param[in] handle player id + * @param[out] result true : player handle is registered, false : player handle is not registered + * @return RM_OK on success, otherwise RM_ERROR + * @pre None + * @post None + * @exception None + * @remark + * \li This API is supposed to be called by the resource center only + * \li Do not use for other purpose + */ +int rm_shm_active_player(const int handle, bool *result); + +#ifdef __cplusplus +} +#endif +#endif \ No newline at end of file diff --git a/include/rm_type.h b/include/rm_type.h new file mode 100644 index 0000000..277fcc4 --- /dev/null +++ b/include/rm_type.h @@ -0,0 +1,653 @@ +/* + * Copyright (c) 2024 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 __RM_TYPE_H__ +#define __RM_TYPE_H__ + +#include + +#define IN +#define OUT + +/** + * @brief The callback execution result + */ +typedef enum { + RM_CB_RESULT_OK, /**< callback event has been processed successfully */ + RM_CB_RESULT_ERROR /**< callback event has been processed with error */ +} rm_cb_result; + + +/** + * @brief The resource category to which device belongs + * @version 4.0 + */ +typedef enum { + RM_CATEGORY_VIDEO_ENCODER_NOT_SUPPORTED = RI_CATEGORY_VIDEO_ENCODER_NOT_SUPPORTED, /**< Not supported video encoder, support since 5.0 */ + RM_CATEGORY_IMAGE_DECODER_NOT_SUPPORTED = RI_CATEGORY_IMAGE_DECODER_NOT_SUPPORTED, /**< Not supported Image decoder */ + RM_CATEGORY_NOT_PERMITTED = RI_CATEGORY_NOT_PERMITTED, /**< Not permitted category by resource policy */ + RM_CATEGORY_MJPEG_DECODER_NOT_SUPPORTED = RI_CATEGORY_MJPEG_DECODER_NOT_SUPPORTED, + RM_CATEGORY_JPEG_DECODER_NOT_SUPPORTED = RI_CATEGORY_JPEG_DECODER_NOT_SUPPORTED, + RM_CATEGORY_VIDEO_DECODER_NOT_SUPPORTED = RI_CATEGORY_VIDEO_DECODER_NOT_SUPPORTED, + RM_CATEGORY_NONE = RI_CATEGORY_NONE, /**< no category information */ + RM_CATEGORY_AUDIO_DECODER = RI_CATEGORY_AUDIO_DECODER, /**< Audio Decoder */ + RM_CATEGORY_AUDIO_EVENT_COMPRESS = RI_CATEGORY_AUDIO_EVENT_COMPRESS, + RM_CATEGORY_AUDIO_SPDIF_ES_OUTPUT = RI_CATEGORY_AUDIO_SPDIF_ES_OUTPUT, /**< spdif es output */ + RM_CATEGORY_VIDEO_DECODER = RI_CATEGORY_VIDEO_DECODER, /**< Video Decoder - MFD (Multi Format Decoder), FullHD */ + RM_CATEGORY_DEMUX = RI_CATEGORY_DEMUX, /**< Demux */ + RM_CATEGORY_AUDIO_ENCODER = RI_CATEGORY_AUDIO_ENCODER, /**< Audio Encoder */ + RM_CATEGORY_VIDEO_ENCODER = RI_CATEGORY_VIDEO_ENCODER, /**< Video Encoder */ + RM_CATEGORY_SCALER = RI_CATEGORY_SCALER, /**< Main Scaler */ + RM_CATEGORY_TUNER = RI_CATEGORY_TUNER, /**< Tuner */ + RM_CATEGORY_AUDIO_MAIN_OUT = RI_CATEGORY_AUDIO_MAIN_OUT, /**< Logical resource to manage ALSA main out source */ + RM_CATEGORY_AUDIO_REMOTE_OUT = RI_CATEGORY_AUDIO_REMOTE_OUT, /**< Logical resource to manage ALSA remote out source */ + RM_CATEGORY_AUDIO_SCART_OUT = RI_CATEGORY_AUDIO_SCART_OUT, /**< Logical resource to manage ALSA scart out source */ + RM_CATEGORY_MM_PCM_OUT = RI_CATEGORY_MM_PCM_OUT, /**< PCM out - used by mm-player */ + RM_CATEGORY_AUDIO_DECODER_SUB = RI_CATEGORY_AUDIO_DECODER_SUB, /**< Sub Audio Decoder */ + RM_CATEGORY_AUDIO_DECODER_PRIMARY = RI_CATEGORY_AUDIO_DECODER_PRIMARY, /**< Sub Audio Decoder */ + RM_CATEGORY_JPEG_DECODER = RI_CATEGORY_JPEG_DECODER, /**< JPEG Decoder */ + RM_CATEGORY_SCALER_SUB = RI_CATEGORY_SCALER_SUB, /**< Sub Scaler */ + RM_CATEGORY_EXT_VIDEO_SRC = RI_CATEGORY_EXT_VIDEO_SRC, /**< Logical resource to manage video input path - used by player */ + RM_CATEGORY_EXT_AUDIO_SRC = RI_CATEGORY_EXT_AUDIO_SRC, /**< Logical resource to manage audio input path - used by player */ + RM_CATEGORY_EXT_HDMI_SRC = RI_CATEGORY_EXT_HDMI_SRC, /**< Logical resource to manage hdmi input path - used by player */ + RM_CATEGORY_VIDEO_DECODER_SUB = RI_CATEGORY_VIDEO_DECODER_SUB, /**< Sub Video Decoder - MFD (Multi Format Decoder), FullHD */ + RM_CATEGORY_CAMERA = RI_CATEGORY_CAMERA, /**< Logical resource to manage camera device */ + RM_CATEGORY_DEMUX_REC = RI_CATEGORY_DEMUX_REC, /**< Demux for recording */ + RM_CATEGORY_TUNER_SUB = RI_CATEGORY_TUNER_SUB, /**< Sub Tuner */ + RM_CATEGORY_MJPEG_DECODER = RI_CATEGORY_MJPEG_DECODER, /**< MJPEG decoder */ + + RM_CATEGORY_INPUT_SRC_DTV = RI_CATEGORY_INPUT_SRC_DTV, /**< input source dtv */ + RM_CATEGORY_INPUT_SRC_ATV = RI_CATEGORY_INPUT_SRC_ATV, /**< input source atv */ + RM_CATEGORY_INPUT_SRC_HDMI = RI_CATEGORY_INPUT_SRC_HDMI, /**< input source hdmi */ + RM_CATEGORY_INPUT_SRC_COMP = RI_CATEGORY_INPUT_SRC_COMP, /**< input source comp */ + RM_CATEGORY_INPUT_SRC_AV = RI_CATEGORY_INPUT_SRC_AV, /**< input source av */ + RM_CATEGORY_INPUT_SRC_SCART = RI_CATEGORY_INPUT_SRC_SCART, /**< input source scart */ + + RM_CATEGORY_MIC = RI_CATEGORY_MIC, /**< MIC */ + RM_CATEGORY_EXT_COMP_SRC = RI_CATEGORY_EXT_COMP_SRC, /**< ext comp src */ + RM_CATEGORY_EXT_AV_SRC = RI_CATEGORY_EXT_AV_SRC, /**< ext av src */ + RM_CATEGORY_SW_DECODER = RI_CATEGORY_SW_DECODER, /**< sw decoder */ + RM_CATEGORY_MMP_MEMORY_CLUSTER = RI_CATEGORY_MMP_MEMORY_CLUSTER, /**< mem cluster */ + + RM_CATEGORY_EXT_AUDIO_SRC_DVI = RI_CATEGORY_EXT_AUDIO_SRC_DVI, /**< LFD only */ + RM_CATEGORY_EXT_AUDIO_SRC_HDMI = RI_CATEGORY_EXT_AUDIO_SRC_HDMI, /**< LFD only */ + RM_CATEGORY_EXT_AUDIO_SRC_DP = RI_CATEGORY_EXT_AUDIO_SRC_DP, /** +#include +#include +#include +#include +#include + +#include +#include + +namespace shared +{ + using segment = boost::interprocess::managed_shared_memory; + template + using allocator = boost::interprocess::allocator; + using string = boost::container::basic_string, shared::allocator>; + template + using unordered_map = boost::unordered_map, std::equal_to, shared::allocator>>; +} + +class RMShmCache +{ +public: + static RMShmCache *GetInstance(void); + + char *GetAppId(const int handle); + int FindScalerHWID(const int zone_id, int *hw_id); + int FindScalerDeviceID(const int virtual_id, int *device_id); + int FindPlayersUsingAudioMainOut(rm_resource_list_h *list); + int GetActiveAudioOut(const int handle, int *result); + bool Activated(const rm_shm_object_id id); + int ActivePlayer(const int handle, bool *result); + +private: + RMShmCache(); + ~RMShmCache() = default; + + bool Init(void); + + bool ready_; + std::mutex init_mutex_; + + shared::segment *shm_segment_; + shared::unordered_map* players_; // player id, app id + shared::unordered_map* scalers_; // device id, scaler + shared::unordered_map* audio_outs_; // device id, audio main out + shared::unordered_map* active_state_; // object id, active or not +}; + +#endif //__RC_SHM_CACHE_H__ diff --git a/include_internal/rm_callback.h b/include_internal/rm_callback.h new file mode 100644 index 0000000..5914eeb --- /dev/null +++ b/include_internal/rm_callback.h @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2024 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 __RM_CALLBACK_H__ +#define __RM_CALLBACK_H__ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct { + int msg_type; // callback message type + int cid; // consumer id + int pid; // process id + int conflicted_num; // conflicted resource num +} rm_cb_head_s; + +typedef struct { + rm_conflict_event_cb cb; + void *data; +} conflict_event_cb; + +typedef struct { + scaler_state_change_cb cb; + void *data; +} scaler_state_cb; + +GMainLoop *rm_get_main_loop(void); +GMainContext *rm_get_context(void); +void rm_set_context(GMainContext *context); +int rm_init_cb(int cid, rm_resource_cb cb, void *data); +int rm_send_cb_msg(rm_cb_head_s *cb_head, int result); +void rm_register_callback(int handle, rm_resource_cb cb, void *data, int fd, GSource *callback_handler, GIOChannel *gio); +void rm_unregister_callback(int handle); + +int rm_add_state_change_cb(int category, resource_state_change_cb cb, void *data); +int rm_remove_state_change_cb(int category, resource_state_change_cb cb); +void rm_call_state_changed_cb(int category, int device_id, int state, int consumer_id, char *app_id); + +int rm_add_conflict_event_cb(rm_conflict_event_cb cb, void *data); +int rm_remove_conflict_event_cb(rm_conflict_event_cb cb); +std::list& rm_get_conflict_event_cb_list(void); + +int rm_add_scaler_state_change_cb(scaler_state_change_cb cb, void *data); +int rm_remove_scaler_state_change_cb(scaler_state_change_cb cb); +void rm_call_scaler_state_changed_cb(rm_resource_list *scaler_list); + +#ifdef __cplusplus +} +#endif +#endif// __RM_CALLBACK_H__ diff --git a/include_internal/rm_dbus.h b/include_internal/rm_dbus.h new file mode 100644 index 0000000..0cf8140 --- /dev/null +++ b/include_internal/rm_dbus.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2024 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 __RM_DBUS_H__ +#define __RM_DBUS_H__ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define RM_DBUS_BUS_NAME "rscmgr.resource" +#define RM_DBUS_INTERFACE_NAME "rscmgr.resource" +#define RM_DBUS_OBJ_PATH "/rscmgr/resource" + +int rm_dbus_method_call(const char *method, GVariant *args, GVariant **result); +int rm_dbus_method_call_async_with_no_reply(const char *method, GVariant *args); + +#ifdef __cplusplus +} +#endif + +#endif //__RM_DBUS_H__ \ No newline at end of file diff --git a/include_internal/rm_debug.h b/include_internal/rm_debug.h new file mode 100644 index 0000000..4cfb311 --- /dev/null +++ b/include_internal/rm_debug.h @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2024 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 __RM_DEBUG_H__ +#define __RM_DEBUG_H__ + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef LOG_TAG +#undef LOG_TAG +#endif //LOG_TAG + +#define LOG_TAG "RSC_MGR" + + +#ifndef RM_DBG +#define RM_DBG(fmt, args...) SLOGD(fmt, ##args) +#endif + +#ifndef RM_INFO +#define RM_INFO(fmt, args...) SLOGI(fmt, ##args) +#endif + +#ifndef RM_WARN +#define RM_WARN(fmt, args...) SLOGW(fmt, ##args) +#endif + +#ifndef RM_ERR +#define RM_ERR(fmt, args...) SLOGE(fmt, ##args) +#endif + +const char *rm_convert_requested_state_enum_to_string(rm_requests_resource_state_e state_enum); +const char *rm_convert_category_enum_to_string(rm_rsc_category_e category_enum); +int is_symlink_file(const char *path); +int _rc_get_capable_catgory_id(int handle, const char *app_id, int category_src); + +#ifdef __cplusplus +} +#endif +#endif //__RM_DEBUG_H__ diff --git a/include_internal/rm_internal.h b/include_internal/rm_internal.h new file mode 100644 index 0000000..9759fe0 --- /dev/null +++ b/include_internal/rm_internal.h @@ -0,0 +1,226 @@ +/* + * Copyright (c) 2024 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 __RM_INTERNAL_H__ +#define __RM_INTERNAL_H__ + +#include +#include + +#define RM_RETURN_ERR_IF_NULL(a, msg) \ + if (!a) \ + { \ + RM_ERR("%s", msg); \ + return RM_ERROR; \ + } + +#define RM_RETURN_NULL_IF_NULL(a, msg) \ + if (!a) \ + { \ + RM_ERR("%s", msg); \ + return NULL; \ + } + +#define RM_RETURN_MINUS_IF_NULL(a, msg) \ + if (!a) \ + { \ + RM_ERR("%s", msg); \ + return -1; \ + } + +#define RM_RETURN_IF_NULL(a, msg) \ + if (!a) \ + { \ + RM_ERR("%s", msg); \ + return; \ + } + +#define RM_FREE(a) \ + if (a) \ + { \ + free(a); \ + a = NULL; \ + } + +#define RM_RETURN_ERR_IF_LT(a, v, msg) \ + if (a < v) \ + { \ + RM_ERR("invalid value(%d)", a); \ + return RM_ERROR; \ + } + +#define RM_RETURN_ERR_IF_GT(a, v, msg) \ + if (a > v) \ + { \ + RM_ERR("invalid value(%d)", a); \ + return RM_ERROR; \ + } + +#define RM_DEVICE_NODE_LEN_MAX 4096 +#define RM_INT32_LEN 32 + +/** + * @enum rm_resource_internal_state_e + * @brief Resource State + * This state can be returned using RM API + */ +typedef enum { + RM_INTERNAL_STATE_FREE, + RM_INTERNAL_STATE_SHARABLE, + RM_INTERNAL_STATE_SHARED, + RM_INTERNAL_STATE_EXCLUSIVE, + RM_INTERNAL_STATE_ERROR +} rm_resource_internal_state_e; + +typedef struct +{ + rm_rsc_category_e category_id; + int device_id; +} rm_conflicted_resource_info_s; + +/** + * @brief request data type + */ +typedef enum { + RM_REQUEST_DATA_TYPE_COMMON = 1, + RM_REQUEST_DATA_TYPE_REGISTER = (0x2 << 29), +} rm_request_data_type; + +typedef enum { + RM_RESPONSE_DATA_TYPE_ALL = 0, + RM_RESPONSE_DATA_TYPE_COMMON = 1, + RM_RESPONSE_DATA_TYPE_REGISTER = (0x2 << 29) +} rm_response_data_type; + +typedef enum { + RM_REQUEST_REGISTER, + RM_REQUEST_UNREGISTER, + RM_REQUEST_ALLOCATE_RESOURCE, + RM_REQUEST_RELEASE_RESOURCES, + RM_REQUEST_QUERY, + RM_REQUEST_SET_PRIORITY, + RM_REQUEST_SET_APPID, + RM_REQUEST_MAX, +} rm_request_type_e; + +/** + * @struct rm_category_s + * @brief category information for allocation + */ +typedef struct +{ + rm_rsc_category_e category_id; + int category_id_optional; + rm_requests_resource_state_e requested_state; +} rm_category_s; + + +/** + * @struct rm_requests_category_s + * @brief resource type information when consumer requests resource category + * + * The rm_requests_category_s struct encapsulate the number of resource. + * resource type array. requests_state in the one data + * + */ +typedef struct +{ + int resources_num; + rm_category_s *resources_categories; +} rm_requests_category_s; + +#define RM_APPID_LENGTH 256 + +typedef struct { + long data_type; + int type; + int handle; + int pid; + int request_num; + int resource[RM_REQUEST_RESOURCE_MAX]; + int resource_option[RM_REQUEST_RESOURCE_MAX]; + int state[RM_REQUEST_RESOURCE_MAX]; + int main_priority; + int sub_priority; + int app_pid; + char app_id[RM_APPID_LENGTH]; /* APPID */ + int device_id[RM_REQUEST_RESOURCE_MAX]; + int sub_type; + unsigned long time; +} rm_msg_request; + +typedef struct { + long data_type; + int type; + int result; + int resource_num; + int resource[RM_REQUEST_RESOURCE_MAX]; + rm_resource_internal_state_e resource_state[RM_REQUEST_RESOURCE_MAX]; + int available; + int handle; + int error_type; + int pid; +} rm_msg_response; + +struct rm_resource { + int id; + char *node; + int state; + int category_id; + int consumer_id; + char *app_id; + int virtual_id; //only for scaler + int source_id; //only for scaler + int max_rez; // max resolution only for scaler + int max_sampling_format; // only for scaler + int support_overlay; // only for scaler + int zone_id; // only for scaler + unsigned int framerate; + int cur_category_id; //only for scaler + unsigned int width; + unsigned int height; + bool android_app; +}; + +struct rm_resource_state { + int catId; + int devId; + int state; + int consumerId; + char *appId; +}; + +struct rm_resource_list { + int n_rsc; + GList *rsc_list; + GList *iter; +}; + +struct rm_conflict_resource { + int catId; // resource category id + int devId; // device id + int cId; // consumer id + const char *appId; // application id + int aZoneId; //application zone id + int rZoneId; //requester zone id +}; + +void rm_wait_for_server_ready(void); + +void rm_set_cpu_inheritance(void); +void rm_clear_cpu_inheritance(void); + +#endif //__RM_INTERNAL_H__ diff --git a/include_internal/rm_msg.h b/include_internal/rm_msg.h new file mode 100644 index 0000000..86dd15d --- /dev/null +++ b/include_internal/rm_msg.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2024 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 __RM_MSG_H__ +#define __RM_MSG_H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +int rm_send_msg(rm_msg_request *data); +int rm_receive_msg(rm_msg_response *response, int msg_type); +void rm_construct_request_msg(rm_msg_request *request, int msg_type, int handle); + +#ifdef __cplusplus +} +#endif +#endif //__RM_MSG_H__ diff --git a/packaging/resource-manager.spec b/packaging/resource-manager.spec new file mode 100644 index 0000000..3152b3c --- /dev/null +++ b/packaging/resource-manager.spec @@ -0,0 +1,79 @@ +Name: resource-manager +Summary: Resource manager +Version: 0.1 +Release: 0 +Group: Multimedia/Libraries +License: Apache-2.0 +Source0: %{name}-%{version}.tar.gz +BuildRequires: cmake +BuildRequires: pkgconfig(dlog) +BuildRequires: pkgconfig(resource-information) +BuildRequires: pkgconfig(capi-system-info) +BuildRequires: pkgconfig(capi-system-resource) +BuildRequires: pkgconfig(libtzplatform-config) +BuildRequires: pkgconfig(glib-2.0) +BuildRequires: pkgconfig(gio-unix-2.0) +BuildRequires: pkgconfig(boost) +BuildRequires: pkgconfig(gmock) + +%define _pkgconfigdir %{_libdir}/pkgconfig +%define _packagedir %{_libdir}/%{name} +%define _includedir %{_libdir}/%{name} +%define _bindir %{_packagedir} + +%define _utname resource-manager-ut + +%description +This package manages the resources of Tizen device. + +%package devel +Summary: Resource manager header files, static libraries +Group: Development/Libraries +Requires: %{name} = %{version}-%{release} +Requires: pkgconfig(resource-information) + +%description devel +This package contains the header files and static libraries +for Resource manager. + +%prep + +%setup -q + +export EVK_TV=n +MAJORVER=`echo %{version} | awk 'BEGIN {FS="."}{print $1}'` + +cmake . \ + -DCMAKE_INSTALL_PREFIX=%{_packagedir} \ + -DPACKAGE_NAME=%{name} \ + -DBINDIR=%{_bindir} \ + -DINCLUDEDIR=%{_includedir} \ + -DPKGCONFIG_INSTALL_DIR=%{_pkgconfigdir} \ + -DVERSION=%{version} \ + -DMAJORVERSION=${MAJORVER} \ + -DLIBDIR=%{_libdir} \ + -DRSCMGRPKGNAME=%{_utname} \ + -DTZ_SYS_RW_APP=%{TZ_SYS_RW_APP} \ + -DUNIT_TEST=1 + +make %{?jobs:-j%jobs} + +%install +rm -rf %{buildroot} +%make_install + +%clean +rm -rf %{buildroot} + +%files +%defattr(-,root,root,-) +%{_libdir}/*.so.* +%{_bindir}/* +%manifest resource-manager.manifest +%license LICENSE.APLv2 + +%files devel +%defattr(-,root,root,-) +%{_pkgconfigdir}/resource-manager.pc +%{_includedir}/*.h +%{_libdir}/*.so diff --git a/resource-manager.manifest b/resource-manager.manifest new file mode 100644 index 0000000..75b0fa5 --- /dev/null +++ b/resource-manager.manifest @@ -0,0 +1,5 @@ + + + + + diff --git a/resource-manager.pc.in b/resource-manager.pc.in new file mode 100644 index 0000000..7ba499d --- /dev/null +++ b/resource-manager.pc.in @@ -0,0 +1,12 @@ +prefix=/usr +exec_prefix=${prefix} +libdir=@LIBDIR@ +includedir=@INCLUDEDIR@ + +Name: resource-manager +Description: This package manages the resource of Tizen device +Version: @VERSION@ +Requires: resource-information +Libs: -L${libdir} -lresource-manager +Cflags: -I${includedir} -I${libdir} +CXXflags: -I${includedir} -I${libdir} diff --git a/rscmgr-test.manifest b/rscmgr-test.manifest new file mode 100644 index 0000000..677989e --- /dev/null +++ b/rscmgr-test.manifest @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/RMShmCache.cpp b/src/RMShmCache.cpp new file mode 100644 index 0000000..36cb180 --- /dev/null +++ b/src/RMShmCache.cpp @@ -0,0 +1,274 @@ +/* + * Copyright (c) 2024 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 + +#define ARRAY_SIZE(name) (sizeof(name)/sizeof(name[0])) + +static RMShmCache *instance_ = nullptr; +static std::mutex instance_mutex_; + +// LCOV_EXCL_START + +RMShmCache *RMShmCache::GetInstance(void) +{ + if (instance_ == nullptr) { + std::lock_guard guard(instance_mutex_); + if (instance_ == nullptr) { + instance_ = new RMShmCache(); + } + } + return instance_; +} + +RMShmCache::RMShmCache(): ready_(false) +{ + Init(); +} + +bool RMShmCache::Init(void) +{ + if (ready_) + return true; + + std::lock_guard guard(init_mutex_); + + try { + shm_segment_ = new shared::segment(boost::interprocess::open_read_only, "shm_rm"); + players_ = shm_segment_->find>("players").first; + scalers_ = shm_segment_->find>("scalers").first; + audio_outs_ = shm_segment_->find>("audio_outs").first; + active_state_ = shm_segment_->find>("active_state").first; + } catch (const std::exception &e) { + RM_ERR("failed to initialize shm (%s)", e.what()); + return false; + } + + ready_ = true; + return true; +} + +char *RMShmCache::GetAppId(const int handle) +{ + if (!ready_ && !Init()) { + RM_ERR("shm is not ready (%d)", handle); + return nullptr; + } + + if (!players_ || !Activated(RM_SHM_OBJ_PLAYER)) { + RM_ERR("object (players) not found or inactive"); + return nullptr; + } + + auto it = players_->find(handle); + if (it == players_->end()) { + RM_ERR("player not found (%d)", handle); + return nullptr; + } + + RM_INFO("(%d:%s)", it->first, it->second.c_str()); + return strdup(it->second.c_str()); +} + +typedef struct { + int device_id; + int hw_id; +}scaler_id; + +static const scaler_id scaler_ids_[] = { + { RM_DEVICE_SCALER, 0}, + { RM_DEVICE_SCALER_SUB, 1}, + { RM_DEVICE_SCALER_SUB2, 2}, + { RM_DEVICE_SCALER_SUB3, 3} +}; + +int RMShmCache::FindScalerHWID(const int zone_id, int *hw_id) +{ + if (!ready_ && !Init()) { + RM_ERR("shm is not ready (%d)", zone_id); + return RM_ERROR; + } + + if (!scalers_ || !Activated(RM_SHM_OBJ_SCALER)) { + RM_ERR("object (scalers) not found or inactive"); + return RM_ERROR; + } + + for (unsigned int i = 0; i < ARRAY_SIZE(scaler_ids_); i++) { + auto it = scalers_->find(scaler_ids_[i].device_id); + if (it == scalers_->end()) + continue; + RM_INFO("requested zone id (%d)/device_id(%d)/zone id(%d)", zone_id, scaler_ids_[i].device_id, it->second.GetZoneID()); + if (it->second.GetZoneID() != zone_id) + continue; + + *hw_id = scaler_ids_[i].hw_id; + RM_INFO("hw id (%d:%d)", zone_id, *hw_id); + return RM_OK; + } + + *hw_id = -1; + RM_INFO("hw id (%d:%d)", zone_id, *hw_id); + return RM_OK; +} + +int RMShmCache::FindScalerDeviceID(const int virtual_id, int *device_id) +{ + if (!ready_ && !Init()) { + RM_ERR("shm is not ready (%d)", virtual_id); + return RM_ERROR; + } + + if (!scalers_ || !Activated(RM_SHM_OBJ_SCALER)) { + RM_ERR("object (scalers) not found or inactive"); + return RM_ERROR; + } + + for (unsigned int i = 0; i < ARRAY_SIZE(scaler_ids_); i++) { + auto it = scalers_->find(scaler_ids_[i].device_id); + if (it == scalers_->end()) + continue; + if (it->second.GetVirtualID() != virtual_id) + continue; + + *device_id = scaler_ids_[i].device_id; + return RM_OK; + } + + *device_id = virtual_id; + return RM_OK; +} + +int RMShmCache::FindPlayersUsingAudioMainOut(rm_resource_list_h *list) +{ + if (!ready_ && !Init()) { + RM_ERR("shm is not ready"); + return RM_ERROR; + } + + if (!audio_outs_ || !Activated(RM_SHM_OBJ_AUDIO_OUT)) { + RM_ERR("object (audio_outs) not found or inactive"); + return RM_ERROR; + } + + const int audio_main_out_devices[] = { + RM_DEVICE_AUDIO_MAIN_OUT, + RM_DEVICE_AUDIO_MAIN_OUT_SHARE0, + RM_DEVICE_AUDIO_MAIN_OUT_SHARE1 + }; + + rm_resource_list *result = (rm_resource_list*) calloc(1, sizeof(rm_resource_list)); + result->n_rsc = 0; + + for (unsigned int i = 0; i < ARRAY_SIZE(audio_main_out_devices); i++) { + auto it = audio_outs_->find(audio_main_out_devices[i]); + if (it == audio_outs_->end()) + continue; + if (it->second.GetState() != RM_RSC_STATE_EXCLUSIVE) + continue; + + rm_resource *resource = (rm_resource*) calloc(1, sizeof(rm_resource)); + resource->id = audio_main_out_devices[i]; + resource->state = RM_RSC_STATE_EXCLUSIVE; + resource->consumer_id = it->second.GetPlayerID(); + resource->app_id = GetAppId(it->second.GetPlayerID()); + + result->rsc_list = g_list_append(result->rsc_list, resource); + } + + result->n_rsc = g_list_length(result->rsc_list); + result->iter = result->rsc_list; + *list = result; + RM_INFO("audio main out players found (%d)", result->n_rsc); + return RM_OK; +} + +bool RMShmCache::Activated(const rm_shm_object_id id) +{ + if (!ready_ && !Init()) { + RM_ERR("shm is not ready"); + return false; + } + + auto it = active_state_->find(id); + return (it == active_state_->end()) ? false : it->second; +} + +int RMShmCache::GetActiveAudioOut(const int handle, int *result) +{ + if (!ready_ && !Init()) { + RM_ERR("shm is not ready"); + return RM_ERROR; + } + + if (!audio_outs_ || !Activated(RM_SHM_OBJ_AUDIO_OUT)) { + RM_ERR("object (audio_outs) not found or inactive"); + return RM_ERROR; + } + + const int audio_out_devices[] = { + RM_DEVICE_AUDIO_MAIN_OUT, + RM_DEVICE_AUDIO_MAIN_OUT_SHARE0, + RM_DEVICE_AUDIO_MAIN_OUT_SHARE1, + RM_DEVICE_AUDIO_SUB_OUT + }; + + const int audio_main_out = 1; + const int audio_sub_out = 2; + int tmp = 0; + + for (unsigned int i = 0; i < ARRAY_SIZE(audio_out_devices); i++) { + auto it = audio_outs_->find(audio_out_devices[i]); + if (it == audio_outs_->end()) + continue; + if (it->second.GetState() != RM_RSC_STATE_EXCLUSIVE) + continue; + if (it->second.GetPlayerID() != handle) + continue; + + if (audio_out_devices[i] == RM_DEVICE_AUDIO_SUB_OUT) + tmp |= audio_sub_out; + else + tmp |= audio_main_out; + } + + *result = tmp; + RM_INFO("(%d:%d)", handle, *result); + return RM_OK; +} + +int RMShmCache::ActivePlayer(const int handle, bool *result) +{ + if (!ready_ && !Init()) { + RM_ERR("shm is not ready (%d)", handle); + return RM_ERROR; + } + + if (!players_ || !Activated(RM_SHM_OBJ_PLAYER)) { + RM_ERR("object (players) not found or inactive"); + return RM_ERROR; + } + + auto it = players_->find(handle); + *result = (it != players_->end()); + + RM_INFO("(%d:%d)", handle, *result); + return RM_OK; +} + +// LCOV_EXCL_STOP diff --git a/src/rm_api.cpp b/src/rm_api.cpp new file mode 100644 index 0000000..b077301 --- /dev/null +++ b/src/rm_api.cpp @@ -0,0 +1,442 @@ +/* + * Copyright (c) 2024 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 +#include +#include +#include +#include +#include + +using namespace std; + +#ifndef PR_TASK_PERF_USER_TRACE +#define PR_TASK_PERF_USER_TRACE 666 +#endif + +#define RM_HANDLE_COMMON 100 +#define RM_DEFAULT_PRIORITY 100 + +int rm_register(rm_resource_cb cb, void *data, int *handle, rm_consumer_info *consumer_info) +{ + RM_RETURN_ERR_IF_NULL(cb, "invalid cb"); + ri_init(); + rm_wait_for_server_ready(); + + rm_msg_request msg; + memset(&msg, 0, sizeof(msg)); + + rm_construct_request_msg(&msg, RM_REQUEST_REGISTER, -1); + + if (consumer_info != NULL) { + msg.main_priority = consumer_info->main_priority; + msg.sub_priority = consumer_info->sub_priority; + msg.app_pid = consumer_info->app_pid; + + int len = strlen(consumer_info->app_id); + + if (len >= RM_APPID_LENGTH) { + RM_ERR("appid[%s] is too long", consumer_info->app_id); + return RM_ERROR; + } + + strncpy(msg.app_id, consumer_info->app_id, RM_APPID_LENGTH); + msg.app_id[RM_APPID_LENGTH - 1] = '\0'; + } + + RM_INFO("request for registration"); + + msg.main_priority = (msg.main_priority == 0) ? RM_DEFAULT_PRIORITY : msg.main_priority; + + rm_set_cpu_inheritance(); + + RM_INFO("send msg (%p)...", &msg); + if (rm_send_msg(&msg) != RM_OK) { + RM_ERR("failed to send message"); + rm_clear_cpu_inheritance(); + return RM_ERROR; + } + + rm_msg_response response; + memset(&response, 0, sizeof(rm_msg_response)); + + if (rm_receive_msg(&response, msg.data_type) != RM_OK) { + rm_clear_cpu_inheritance(); + return RM_ERROR; + } + + if (response.result != RM_OK) { + RM_ERR("failed to get result(%d)", response.result); + rm_clear_cpu_inheritance(); + return RM_ERROR; + } + + RM_DBG("registered handle (%d)", response.handle); + + *handle = response.handle; + + if (rm_init_cb(response.handle, cb, data) != RM_OK) { + rm_unregister(response.handle); + RM_ERR("failed to init cb (%d)", response.handle); + rm_clear_cpu_inheritance(); + return RM_ERROR; + } + + rm_clear_cpu_inheritance(); + return RM_OK; +} + +int rm_unregister(int handle) +{ + RM_RETURN_ERR_IF_LT(handle, 0, "invalid handle"); + + //trace_begin("[RSC_MGR] rm_deallocate_resources (handle:%d)", handle); + //trace_end(); + + rm_wait_for_server_ready(); + + rm_msg_request msg; + memset(&msg, 0, sizeof(msg)); + + rm_construct_request_msg(&msg, RM_REQUEST_UNREGISTER, handle); + + rm_set_cpu_inheritance(); + + RM_INFO("send msg (%p)...", &msg); + if (rm_send_msg(&msg) != RM_OK) { + RM_ERR("handle(%d) failed to send message", handle); + rm_clear_cpu_inheritance(); + return RM_ERROR; + } + + rm_msg_response response; + memset(&response, 0, sizeof(rm_msg_response)); + + if (rm_receive_msg(&response, msg.data_type) != RM_OK) { + rm_clear_cpu_inheritance(); + return RM_ERROR; + } + + if (response.result != RM_OK) { + RM_ERR("handle(%d) failed to get result(%d)", handle, response.result); + rm_clear_cpu_inheritance(); + return RM_ERROR; + } + + rm_unregister_callback(handle); + rm_clear_cpu_inheritance(); + + RM_INFO("handle(%d) unregister result(%d)", handle, response.result); + return RM_OK; +} + +int rm_allocate_resources(int handle, const rm_category_request_s *requests, rm_device_return_s *return_devices) +{ + int idx = 0; + RM_RETURN_ERR_IF_LT(handle, 0, "invalid handle"); + RM_RETURN_ERR_IF_NULL(requests, "invalid requests"); + RM_RETURN_ERR_IF_NULL(return_devices, "invalid return_devices"); + RM_RETURN_ERR_IF_GT(requests->request_num, RM_REQUEST_RESOURCE_MAX, "invalid requests"); + + RM_INFO("Request for Allocation handle[%d] / pid[%d] / requested #[%d]", + handle, getpid(), requests->request_num); + + for (idx=0; idx < requests->request_num; idx++) + RM_INFO("(%d) CatID[%d-%s] / CatOpt[%d]", + idx + 1, requests->category_id[idx], rm_convert_category_enum_to_string(requests->category_id[idx]), requests->category_option[idx]); + + rm_wait_for_server_ready(); + + rm_msg_request msg; + memset(&msg, 0, sizeof(msg)); + + rm_construct_request_msg(&msg, RM_REQUEST_ALLOCATE_RESOURCE, handle); + + msg.request_num = requests->request_num; + + for (idx = 0; idx < msg.request_num; idx++) { + msg.resource[idx] = requests->category_id[idx]; + msg.resource_option[idx] = requests->category_option[idx]; + msg.state[idx] = requests->state[idx]; + msg.device_id[idx] = (requests->device_node[idx] != NULL) ? ri_get_device_id(requests->device_node[idx]) : RM_DEVICE_NONE; + RM_INFO("[#%d] category id %d category option %d state %d device node %d", idx, msg.resource[idx], msg.resource_option[idx], msg.state[idx], msg.device_id[idx]); + } + + RM_WARN("send msg (%p)...", &msg); + if (rm_send_msg(&msg) != RM_OK) { + RM_ERR("failed to send message"); + rm_clear_cpu_inheritance(); + return RM_ERROR; + } + + rm_msg_response response; + memset(&response, 0, sizeof(rm_msg_response)); + + if (rm_receive_msg(&response, msg.data_type) != RM_OK) { + rm_clear_cpu_inheritance(); + return RM_ERROR; + } + + if (response.result != RM_OK) { + RM_WARN("RETURNED [%d] ERR_TYPE [%d]", response.result, response.error_type); + return_devices->error_type = (rm_error_type_e) response.error_type; + rm_clear_cpu_inheritance(); + return response.result; + } + + /* resource info got from server */ + return_devices->allocated_num = response.resource_num; + + const char *device_name = NULL; + + for (idx = 0; idx < response.resource_num; idx++) { + return_devices->device_id[idx] = response.resource[idx]; + ri_get_device_path_by_device_id(return_devices->device_id[idx], &(return_devices->device_node[idx])); + ri_get_omx_comp_name_by_device_id(return_devices->device_id[idx], &(return_devices->omx_comp_name[idx])); + device_name = ri_get_device_name_by_device_id(return_devices->device_id[idx]); + snprintf(return_devices->device_name[idx], RM_DEVICE_NAME_LEN_MAX, "%s", (device_name) ? device_name : ""); + } + + RM_WARN("Request for Allocation CID[%d] / PID[%d] / REQUESTED_RSC_NUM[%d] : SUCCESS", handle, getpid(), requests->request_num); + + for (idx = 0; idx < return_devices->allocated_num; idx++) { + RM_INFO("(%d) CatID[%d] / Opt[%d] / DevID[%d ] / DevName[%s : %s : %s] ", idx, + requests->category_id[idx], + requests->category_option[idx], + return_devices->device_id[idx], + return_devices->device_node[idx], + return_devices->omx_comp_name[idx], + return_devices->device_name[idx]); + } + + return RM_OK; +} + +int rm_deallocate_resources(int handle, rm_device_request_s *requests) +{ + int idx = 0; + RM_INFO("request for deallocate handle(%d)", handle); + + RM_RETURN_ERR_IF_LT(handle, 0, "invalid handle"); + RM_RETURN_ERR_IF_NULL(requests, "invalid requests"); + RM_RETURN_ERR_IF_GT(requests->request_num, RM_REQUEST_RESOURCE_MAX, "invalid requests"); + + rm_wait_for_server_ready(); + + rm_msg_request msg; + memset(&msg, 0, sizeof(msg)); + + rm_construct_request_msg(&msg, RM_REQUEST_RELEASE_RESOURCES, handle); + + msg.request_num = requests->request_num; + + for (idx = 0; idx < msg.request_num; idx++) + msg.resource[idx] = requests->device_id[idx]; + + RM_INFO("send msg (%p)...", &msg); + if (rm_send_msg(&msg) != RM_OK) { + RM_ERR("failed to send message"); + rm_clear_cpu_inheritance(); + return RM_ERROR; + } + + rm_msg_response response; + memset(&response, 0, sizeof(rm_msg_response)); + + if (rm_receive_msg(&response, msg.data_type) != RM_OK) { + rm_clear_cpu_inheritance(); + return RM_ERROR; + } + + if (response.result != RM_OK) { + RM_WARN("ERROR RETURNED[%d]", response.result); + rm_clear_cpu_inheritance(); + return response.result; + } + + return RM_OK; +} + +int rm_query(int handle, rm_query_type_e query_type, rm_category_request_s *requests, int *result) +{ + int idx; + RM_RETURN_ERR_IF_LT(handle, 0, "invalid handle"); + RM_RETURN_ERR_IF_NULL(requests, "invalid requests"); + RM_RETURN_ERR_IF_GT(requests->request_num, RM_REQUEST_RESOURCE_MAX, "invalid requests"); + + RM_INFO("Request for Query(%d) handle[%d]/pid[%d]/requested[%d]", + query_type, handle, getpid(), requests->request_num); + + for (idx = 0; idx < requests->request_num; idx++) { + RM_INFO("requested (%d) CatID[%d-%s]/CatOpt[%d]/State(%s)", idx + 1, requests->category_id[idx], rm_convert_category_enum_to_string(requests->category_id[idx]), + requests->category_option[idx], rm_convert_requested_state_enum_to_string(requests->state[idx])); + } + + rm_wait_for_server_ready(); + + rm_msg_request msg; + memset(&msg, 0, sizeof(msg)); + + rm_construct_request_msg(&msg, RM_REQUEST_QUERY, handle); + msg.sub_type = query_type; + + msg.request_num = requests->request_num; + + for (idx = 0; idx < msg.request_num; idx++) { + msg.resource[idx] = requests->category_id[idx]; + msg.resource_option[idx] = requests->category_option[idx]; + msg.state[idx] = requests->state[idx]; + } + + rm_set_cpu_inheritance(); + + if (rm_send_msg(&msg) != RM_OK) { + RM_ERR("failed to send message"); + rm_clear_cpu_inheritance(); + return RM_ERROR; + } + + rm_msg_response response; + memset(&response, 0, sizeof(rm_msg_response)); + + if (rm_receive_msg(&response, msg.data_type) != RM_OK) { + rm_clear_cpu_inheritance(); + return RM_ERROR; + } + + if (response.result != RM_OK) { + RM_ERR("ERROR RETURNED[%d]", response.result); + rm_clear_cpu_inheritance(); + return response.result; + } + + *result = (int)response.available; + + if (!response.available) + RM_INFO("query result : false (cannot use resources)"); + else + RM_INFO("query result : true (can use resources)"); + + rm_clear_cpu_inheritance(); + return RM_OK; +} + +int rm_set_priority(int handle, int priority) +{ + RM_RETURN_ERR_IF_LT(handle, 0, "invalid handle"); + + RM_INFO("Request for Setting Priority handle[%d]/pid[%d]/priority[%d]", handle, getpid(), priority); + + rm_wait_for_server_ready(); + + rm_msg_request msg; + memset(&msg, 0, sizeof(msg)); + + rm_construct_request_msg(&msg, RM_REQUEST_SET_PRIORITY, handle); + + msg.main_priority = priority; + + if (rm_send_msg(&msg) != RM_OK) { + RM_ERR("failed to send message"); + return RM_ERROR; + } + + rm_msg_response response; + memset(&response, 0, sizeof(rm_msg_response)); + + if (rm_receive_msg(&response, msg.data_type) != RM_OK) + return RM_ERROR; + + if (response.result != RM_OK) { + RM_ERR("ERROR RETURNED[%d]", response.result); + return response.result; + } + + return RM_OK; +} + +int rm_set_app_id(int handle, char *app_id) +{ + int len, buf_size; + + RM_RETURN_ERR_IF_LT(handle, 0, "invalid handle"); + RM_RETURN_ERR_IF_NULL(app_id, "invalid app_id"); + + RM_INFO("Request for Setting APPID handle[%d]/pid[%d]/appid[%s]", handle, getpid(), app_id); + + rm_wait_for_server_ready(); + + len = strlen(app_id); + + if (len >= RM_APPID_LENGTH) { + RM_ERR("appid[%s] is too long", app_id); + return RM_ERROR; + } + + rm_msg_request msg; + memset(&msg, 0, sizeof(msg)); + buf_size = sizeof(msg.app_id); + + rm_construct_request_msg(&msg, RM_REQUEST_SET_APPID, handle); + + strncpy(msg.app_id, app_id, buf_size); + msg.app_id[buf_size - 1] = '\0'; + + RM_INFO("intput[%s] / [%s]", app_id, msg.app_id); + + rm_set_cpu_inheritance(); + + if (rm_send_msg(&msg) != RM_OK) { + RM_ERR("failed to send message"); + rm_clear_cpu_inheritance(); + return RM_ERROR; + } + + rm_msg_response response; + memset(&response, 0, sizeof(rm_msg_response)); + + if (rm_receive_msg(&response, msg.data_type) != RM_OK) { + rm_clear_cpu_inheritance(); + return RM_ERROR; + } + + if (response.result != RM_OK) { + RM_ERR("ERROR RETURNED[%d]", response.result); + rm_clear_cpu_inheritance(); + return response.result; + } + + rm_clear_cpu_inheritance(); + + return RM_OK; +} diff --git a/src/rm_callback.cpp b/src/rm_callback.cpp new file mode 100644 index 0000000..8bee3c2 --- /dev/null +++ b/src/rm_callback.cpp @@ -0,0 +1,712 @@ +/* + * Copyright (c) 2024 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 +#include +#include + +#define RM_HANDLE_MAX 100 + +#ifndef __CONSTRUCTOR__ +#define __CONSTRUCTOR__ __attribute__ ((constructor)) +#endif + +#ifndef PR_TASK_PERF_USER_TRACE +#define PR_TASK_PERF_USER_TRACE 666 +#endif + +#define IS_SMACK_READY (access("/tmp/smack_early_ready", F_OK) == 0) + +typedef struct { + int handle; + rm_resource_cb cb; + void *data; + int is_used; + int fd; //fd to FIFO from Server to Client + GSource *callback_handler; + GIOChannel *gio; +} rm_cb_handle_s; + +static rm_cb_handle_s rm_cb_info[RM_HANDLE_MAX]; + +static pthread_mutex_t rm_cb_mutex = PTHREAD_MUTEX_INITIALIZER; + +static GMainLoop *rm_client_loop = NULL; +static GMainContext *rm_client_context = NULL; + +static void rm_add_main_loop(GMainLoop *loop) +{ + rm_client_loop = loop; +} + +GMainLoop *rm_get_main_loop(void) +{ + return rm_client_loop; +} + +gboolean _watchdog_cb(gpointer data) +{ + RM_INFO("watchdog notified"); + return G_SOURCE_CONTINUE; +} + +static gpointer rm_run_loop(gpointer data) +{ + RM_INFO("Run RM client thread"); + GMainLoop *main_loop = rm_get_main_loop(); + + if (main_loop != NULL) + g_main_loop_run(main_loop); + + RM_INFO("RM client thread finished\n"); + return NULL; +} + +int _create_event_loop(void) +{ + GMainContext *rm_client_ctx = NULL; + + rm_client_ctx = g_main_context_new(); + rm_set_context(rm_client_ctx); + + GMainLoop *main_loop = g_main_loop_new(rm_client_ctx, FALSE); + rm_add_main_loop(main_loop); + + GThread *rm_thrd = g_thread_new("rm_client", rm_run_loop, NULL); + + if (rm_thrd == NULL) { + // LCOV_EXCL_START + g_main_loop_unref(main_loop); + RM_ERR("Failed to create new thread"); + return RM_ERROR; + // LCOV_EXCL_STOP + } + + return RM_OK; + +} + +int _create_cb_root_dir(void) +{ + const char *cb_dir_path = "/run/rsc_mgr"; + + mode_t pmask; + struct stat stat_info; + + if (stat(cb_dir_path, &stat_info) == 0) // On Success zero returned, exists + return RM_OK; + +// LCOV_EXCL_START + mode_t dir_mode = 0666 | 0111; + pmask = umask(0); + + if (mkdir(cb_dir_path, dir_mode) !=0) { + RM_ERR("failed to create cb directory (%d)", errno); + umask(pmask); + return RM_ERROR; + } + chmod(cb_dir_path, dir_mode); + umask(pmask); + + return RM_OK; +// LCOV_EXCL_STOP +} + +int _create_FIFO_s2c(int pid, int cid) +{ + struct stat stat_info; + mode_t pmask; + char cb_path_s2c[256] = {0, }; + //3.0 + snprintf(cb_path_s2c, 256, "/run/rsc_mgr/%d.%d.s2c.cb", pid, cid); + + if (stat(cb_path_s2c, &stat_info) == 0) { + return RM_OK; + } + + pmask = umask(0); + + if (mknod(cb_path_s2c, S_IFIFO|0666, 0)) { + RM_ERR("failed to create cb for S2C(%s)-(%d)", cb_path_s2c, errno); + umask(pmask); + return RM_ERROR; + } + + umask(pmask); + + return RM_OK; + +} + +int _remove_FIFO_s2c(int pid, int cid) +{ + struct stat stat_info; + char cb_path_s2c[256] = {0, }; + //3.0 + snprintf(cb_path_s2c, 256, "/run/rsc_mgr/%d.%d.s2c.cb", pid, cid); + + if (stat(cb_path_s2c, &stat_info) != 0) { + return RM_OK; + } + + if (remove(cb_path_s2c) != 0) { + RM_ERR("failed to remove cb for S2C(%s)-(%d)", cb_path_s2c, errno); + return RM_ERROR; + } + + RM_INFO("Removed cb for S2C(%s)", cb_path_s2c); + return RM_OK; + +} + +void rm_register_callback(int handle, rm_resource_cb cb, void *data, int fd, GSource *callback_handler, GIOChannel *gio) +{ + for (int i = 0; i < RM_HANDLE_MAX; i++) { + if (rm_cb_info[i].is_used == 0) { + rm_cb_info[i].is_used = 1; + rm_cb_info[i].handle = handle; + rm_cb_info[i].cb = cb; + rm_cb_info[i].data = data; + rm_cb_info[i].fd = fd; + rm_cb_info[i].callback_handler = callback_handler; + rm_cb_info[i].gio = gio; + return; + } + } + + RM_ERR("error! there is no empty slot"); +} + +void rm_unregister_callback(int handle) +{ + pthread_mutex_lock(&rm_cb_mutex); + + for (int i = 0; i < RM_HANDLE_MAX; i++) { + if (rm_cb_info[i].handle == handle) { + rm_cb_info[i].handle = 0; + rm_cb_info[i].cb = NULL; + rm_cb_info[i].data = NULL; + rm_cb_info[i].is_used = 0; + + g_io_channel_unref(rm_cb_info[i].gio); + + if ((rm_cb_info[i].callback_handler != NULL) && !g_source_is_destroyed(rm_cb_info[i].callback_handler)) { + g_source_destroy(rm_cb_info[i].callback_handler); + g_source_unref(rm_cb_info[i].callback_handler); + } + + rm_cb_info[i].callback_handler = NULL; + + if (close(rm_cb_info[i].fd)!= 0) + RM_ERR("error! on close FIFO(%d)..errno(%d)", rm_cb_info[i].fd, errno); + + rm_cb_info[i].fd = -1; + + _remove_FIFO_s2c(getpid(), handle); + + pthread_mutex_unlock(&rm_cb_mutex); + return; + } + } + + RM_ERR("error! there is no callback registered by handle(%d)", handle); + + pthread_mutex_unlock(&rm_cb_mutex); +} + +static bool _is_valid_fd(int fd) +{ + for (int i = 0; i < RM_HANDLE_MAX; i++) { + if (fd == rm_cb_info[i].fd && rm_cb_info[i].is_used) { + RM_WARN("handle : (%d), fd : (%d)", i, fd); + return true; + } + } + RM_ERR("invalid fd : (%d)", fd); + return false; +} + +static int _parse_common_callback(int fd, rm_cb_head_s cb_head, rm_device_request_s *requests) +{ + int conflicted_resource_num = cb_head.conflicted_num; + int res_size = sizeof(int) * conflicted_resource_num; + int *resources = (int*) calloc(1, res_size); + assert(resources); + + int rbyte = read(fd, resources, res_size); + if ((rbyte <= 0) || (rbyte != res_size)) { + RM_ERR("Unexpected read byte size (%d)", rbyte); + free(resources); + return RM_ERROR; + } + + for (int i = 0; i < conflicted_resource_num; i++) + RM_WARN("[#%d / #%d] conflicted resource id : %d", i, conflicted_resource_num, resources[i]); + + requests->request_num = conflicted_resource_num; + + for (int i = 0; i < requests->request_num; i++) + requests->device_id[i] = resources[i]; + + free(resources); + return RM_OK; +} + +static gboolean rm_gio_cb(GIOChannel *src, GIOCondition cond, gpointer data) +{ + RM_WARN("callback called"); + + rm_cb_head_s cb_head; + + int fd = g_io_channel_unix_get_fd(src); + int rbyte = read(fd, &cb_head, sizeof(cb_head)); + + if ((rbyte <= 0) || (rbyte != sizeof(cb_head))) { + RM_ERR("fd(%d) unexpected size (%d:%zu)/err(%d:%d:%d)", fd, rbyte, sizeof(cb_head), (cond & G_IO_ERR), (cond & G_IO_HUP), (cond & G_IO_NVAL)); + if (cond & (G_IO_ERR | G_IO_HUP | G_IO_NVAL)) + return G_SOURCE_REMOVE; + return _is_valid_fd(fd) ? G_SOURCE_CONTINUE : G_SOURCE_REMOVE; + } + + RM_WARN("TYPE[%d] / CID[%d] / PID[%d] / CONFLICTED[%d]", cb_head.msg_type, cb_head.cid, cb_head.pid, cb_head.conflicted_num); + + if ((cb_head.conflicted_num <= 0) || (cb_head.conflicted_num > RM_REQUEST_RESOURCE_MAX)) { + RM_ERR("fd(%d) invalid data, conflicted_num(%d)", fd, cb_head.conflicted_num); + return _is_valid_fd(fd) ? G_SOURCE_CONTINUE : G_SOURCE_REMOVE; + } + + rm_device_request_s requests; + memset(&requests, 0, sizeof(rm_device_request_s)); + + if (_parse_common_callback(fd, cb_head, &requests)) + return G_SOURCE_CONTINUE; + + rm_resource_cb cb = NULL; + void *cb_data = NULL; + + pthread_mutex_lock(&rm_cb_mutex); + + for (int i = 0; i < RM_HANDLE_MAX; i++) { + if (rm_cb_info[i].handle == cb_head.cid) { + cb = rm_cb_info[i].cb; + cb_data = rm_cb_info[i].data; + break; + } + } + + pthread_mutex_unlock(&rm_cb_mutex); + + RM_WARN("call client callback CID[%d]/PID[%d]", cb_head.cid, cb_head.pid); + + if (cb == NULL) { + RM_ERR("callback was unregistered CID[%d]/PID[%d]", cb_head.cid, cb_head.pid); + return G_SOURCE_CONTINUE; + } + + rm_callback_type cb_type = RM_CALLBACK_TYPE_UNKNOWN; + + cb_type = (rm_callback_type) (cb_head.msg_type); + + int cb_result = cb(cb_head.cid, cb_type, &requests, cb_data); + + RM_WARN("client callback CID[%d]/PID[%d] returned. result[%d]", cb_head.cid, cb_head.pid, cb_result); + return G_SOURCE_CONTINUE; +} + +GMainContext *rm_get_context(void) +{ + return rm_client_context; +} + +void rm_set_context(GMainContext *context) +{ + rm_client_context = context; +} + +int rm_init_cb(int cid, rm_resource_cb cb, void *data) +{ + pthread_mutex_lock(&rm_cb_mutex); + int pid = getpid(); + + // initialize event loop to receive callback message from server + GMainContext *rm_client_ctx = rm_get_context(); + + if (rm_client_ctx == NULL) { + if (_create_event_loop() != RM_OK) { + pthread_mutex_unlock(&rm_cb_mutex); + return RM_ERROR; + } + } + + // check and create root directory required for FIFO + if (_create_cb_root_dir() != RM_OK) { + pthread_mutex_unlock(&rm_cb_mutex); + return RM_ERROR; + } + + // check and create FIFO (server to client) + if (_create_FIFO_s2c(pid, cid) != RM_OK) { + pthread_mutex_unlock(&rm_cb_mutex); + return RM_ERROR; + } + + char cb_path_s2c[256] = {0, }; + int fd = -1; + GSource *rm_cb_handler = NULL; + //3.0 + snprintf(cb_path_s2c, 256, "/run/rsc_mgr/%d.%d.s2c.cb", pid, cid); + + if ((fd = open(cb_path_s2c, O_RDWR|O_NONBLOCK)) < 0) { + RM_ERR("open error (%s), errno(%d)\n", cb_path_s2c, errno); + pthread_mutex_unlock(&rm_cb_mutex); + return RM_ERROR; + } + + //register as a GSource + GIOChannel *gio = g_io_channel_unix_new(fd); + + if (gio == NULL) { + RM_ERR("failed to create a new GIOChannel"); + pthread_mutex_unlock(&rm_cb_mutex); + close(fd); + return RM_ERROR; + } + + g_io_channel_set_flags(gio, G_IO_FLAG_NONBLOCK, NULL); + rm_cb_handler = g_io_create_watch(gio, G_IO_IN); + + g_source_set_callback(rm_cb_handler, ((GSourceFunc) (void (*)(void)) (rm_gio_cb)), NULL, NULL); + RM_INFO("set callback to rm_cb_handler(%p), fd=(%d), rm_client_ctx(%p)", rm_cb_handler, fd, rm_get_context()); + g_source_attach(rm_cb_handler, rm_get_context()); + + // register callback into internal structure + rm_register_callback(cid, cb, data, fd, rm_cb_handler, gio); + + pthread_mutex_unlock(&rm_cb_mutex); + return RM_OK; + +} + +// LCOV_EXCL_START +static GHashTable *htable_state_cb = NULL; + +typedef struct { + int category; + GList *list; +} rm_category_cb; + +typedef struct { + resource_state_change_cb cb; + void *data; +} rm_state_change_cb; + +void _free_rm_state_change_cb(gpointer data) +{ + if (!data) + return; + + rm_state_change_cb *state_cb = (rm_state_change_cb*) data; + RM_FREE(state_cb); +} + +static void _destroy_data(gpointer data) +{ + if (!data) + return; + + rm_category_cb *category_cb = (rm_category_cb*) data; + g_list_free_full(category_cb->list, _free_rm_state_change_cb); + RM_FREE(category_cb); +} + +GHashTable *_get_state_change_cb_htable(void) +{ + if (!htable_state_cb) + htable_state_cb = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, _destroy_data); + + return htable_state_cb; +} + + +rm_state_change_cb *_new_rm_state_change_cb(resource_state_change_cb cb, void *data) +{ + rm_state_change_cb *state_cb = (rm_state_change_cb*) calloc(1, sizeof(rm_state_change_cb)); + assert(state_cb); + + state_cb->cb = cb; + state_cb->data = data; + + return state_cb; +} + +static int _find_state_cb(GList *list, resource_state_change_cb cb, rm_state_change_cb **state_cb) +{ + RM_RETURN_MINUS_IF_NULL(list, "invalid list"); + RM_RETURN_MINUS_IF_NULL(cb, "invalid cb"); + RM_RETURN_MINUS_IF_NULL(state_cb, "invalid state_cb"); + + rm_state_change_cb *tmp_cb = NULL; + GList *tmp_list = g_list_first(list); + + while(tmp_list) { + tmp_cb = (rm_state_change_cb*) tmp_list->data; + if (tmp_cb->cb == cb) { + *state_cb = tmp_cb; + return 0; + } + tmp_list = g_list_next(tmp_list); + } + + return -1; +} + +GList *rm_get_state_change_cb_list(int category) +{ + rm_category_cb *category_cb = (rm_category_cb*) g_hash_table_lookup(_get_state_change_cb_htable(), GINT_TO_POINTER(category)); + + if (!category_cb) + return NULL; + + if (!category_cb->list) + return NULL; + + return g_list_copy(category_cb->list); +} + +void rm_call_state_changed_cb(int category, int device_id, int state, int handle, char *app_id) +{ + rm_category_cb *category_cb = (rm_category_cb*) g_hash_table_lookup(_get_state_change_cb_htable(), GINT_TO_POINTER(category)); + + if (!category_cb) { + RM_INFO("no callback (%d)", category); + return; + } + + if (!category_cb->list) { + RM_INFO("no callback (%d)", category); + return; + } + + GList *l; + struct rm_resource_state rsc_state; + rsc_state.catId = category; + rsc_state.devId = device_id; + rsc_state.state = state; + rsc_state.consumerId = handle; + rsc_state.appId = app_id; + + for (l = category_cb->list; l; l = g_list_next(l)) { + rm_state_change_cb *state_change_cb = (rm_state_change_cb*) l->data; + RM_INFO("call cb(%p)", state_change_cb); + state_change_cb->cb(&rsc_state, state_change_cb->data); + } +} + +int rm_add_state_change_cb(int category, resource_state_change_cb cb, void *data) +{ + rm_category_cb *category_cb = (rm_category_cb*) g_hash_table_lookup(_get_state_change_cb_htable(), GINT_TO_POINTER(category)); + rm_state_change_cb *state_cb = NULL; + + if (!category_cb) { + category_cb = (rm_category_cb*) calloc(1, sizeof(rm_category_cb)); + assert(category_cb); + category_cb->category = category; + category_cb->list = g_list_append(category_cb->list, _new_rm_state_change_cb(cb, data)); + + g_hash_table_insert(_get_state_change_cb_htable(), GINT_TO_POINTER(category), category_cb); + RM_INFO("state change cb added (%d:%p) catcb(%p)", category, cb, category_cb); + return 0; + } + + if (_find_state_cb(category_cb->list, cb, &state_cb) == 0) { + RM_ERR("already registered cb (%d:%p)", category, cb); + return -1; + } + + category_cb->list = g_list_append(category_cb->list, _new_rm_state_change_cb(cb, data)); + RM_INFO("state change cb added (%d:%p) l(%d)", category, cb, g_list_length(category_cb->list)); + return 0; +} + +int rm_remove_state_change_cb(int category, resource_state_change_cb cb) +{ + rm_category_cb *category_cb = (rm_category_cb*) g_hash_table_lookup(_get_state_change_cb_htable(), GINT_TO_POINTER(category)); + rm_state_change_cb *found_cb = NULL; + + if (!category_cb) { + RM_ERR("no cb registered for category (%d:%p)", category, cb); + return -1; + } + + if (_find_state_cb(category_cb->list, cb, &found_cb) < 0) { + RM_ERR("not registered cb (%d:%p)", category, cb); + return -1; + } + + category_cb->list = g_list_remove(category_cb->list, found_cb); + RM_INFO("cb removed (%d:%p) l(%d)", category, cb, g_list_length(category_cb->list)); + + RM_FREE(found_cb); + + if (g_list_length(category_cb->list) == 0) { + RM_INFO("all cbs removed for (%d) h(%d)", category, g_hash_table_size(_get_state_change_cb_htable())); + g_hash_table_remove(_get_state_change_cb_htable(), GINT_TO_POINTER(category)); + } + + return (int) g_hash_table_size(_get_state_change_cb_htable()); +} + +static std::list conflict_event_cb_list; +std::list& rm_get_conflict_event_cb_list(void) +{ + return conflict_event_cb_list; +} + +conflict_event_cb *_new_conflict_event_cb(rm_conflict_event_cb cb, void *data) +{ + conflict_event_cb *new_cb = (conflict_event_cb*)calloc(1, sizeof(conflict_event_cb)); + assert(new_cb); + new_cb->cb = cb; + new_cb->data = data; + return new_cb; +} + +void _free_conflict_event_cb(conflict_event_cb *cb) +{ + if (!cb) + return; + + free(cb); + cb = NULL; +} + +int rm_add_conflict_event_cb(rm_conflict_event_cb cb, void *data) +{ + std::list &cb_list = rm_get_conflict_event_cb_list(); + + for (auto& it : cb_list) { + if (it->cb == cb) + return -1; + } + + cb_list.push_back(_new_conflict_event_cb(cb, data)); + RM_INFO("callback added (%p)", cb); + + return 0; +} + +int rm_remove_conflict_event_cb(rm_conflict_event_cb cb) +{ + std::list &cb_list = rm_get_conflict_event_cb_list(); + + for (auto it = cb_list.begin(); it != cb_list.end(); ++it) { + conflict_event_cb *tmp_cb = *it; + if (tmp_cb->cb == cb) { + it = cb_list.erase(it); + RM_INFO("removed cb (%p)", cb); + _free_conflict_event_cb(tmp_cb); + return cb_list.size(); + } + } + return -1; +} + +static std::list scaler_state_change_cb_list; +std::list& rm_get_scaler_state_change_cb_list(void) +{ + return scaler_state_change_cb_list; +} + +scaler_state_cb *_new_scaler_state_cb(scaler_state_change_cb cb, void *data) +{ + scaler_state_cb *new_cb = (scaler_state_cb *)calloc(1, sizeof(scaler_state_cb)); + assert(new_cb); + new_cb->cb = cb; + new_cb->data = data; + return new_cb; +} + +void _free_scaler_state_cb(scaler_state_cb *cb) +{ + if (!cb) + return; + + free(cb); + cb = NULL; +} + +int rm_add_scaler_state_change_cb(scaler_state_change_cb cb, void *data) +{ + std::list &cb_list = rm_get_scaler_state_change_cb_list(); + + for (auto& it : cb_list) { + if (it->cb == cb) + return -1; + } + + cb_list.push_back(_new_scaler_state_cb(cb, data)); + RM_INFO("callback added (%p)", cb); + return 0; +} + +int rm_remove_scaler_state_change_cb(scaler_state_change_cb cb) +{ + std::list &cb_list = rm_get_scaler_state_change_cb_list(); + + for (auto it = cb_list.begin(); it != cb_list.end(); ++it) { + scaler_state_cb *tmp_cb = *it; + if (tmp_cb->cb == cb) { + it = cb_list.erase(it); + RM_INFO("removed cb (%p)", cb); + _free_scaler_state_cb(tmp_cb); + return cb_list.size(); + } + } + return -1; +} + +void rm_call_scaler_state_changed_cb(rm_resource_list *scaler_list) +{ + std::list cb_list = rm_get_scaler_state_change_cb_list(); + + for (auto &it : cb_list) { + RM_INFO("call cb(%p)", it->cb); + it->cb(scaler_list, it->data); + } +} + +// LCOV_EXCL_STOP + +static void __CONSTRUCTOR__ module_init(void) +{ + memset(&rm_cb_info, 0, sizeof(rm_cb_handle_s)*RM_HANDLE_MAX); +} diff --git a/src/rm_dbus.cpp b/src/rm_dbus.cpp new file mode 100644 index 0000000..509eeca --- /dev/null +++ b/src/rm_dbus.cpp @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2024 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 + +// LCOV_EXCL_START + +static bool _wait_server_ready(void) +{ + const char *rsc_event_name = "/run/rsc_mgr_ready"; + + return access(rsc_event_name, F_OK) == 0; +} + +static GDBusConnection* __dbus_get_connection() +{ + static GDBusConnection *conn = NULL; + GError *err = NULL; + + if (conn) + return conn; + + conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &err); + if (!conn) { + RM_ERR("g_bus_get_sync() error (%s)", err->message); + g_error_free(err); + return NULL; + } + + return conn; +} + +void rm_set_cpu_inheritance(void) +{ + //resource_set_cpu_inheritance(0, "rscmgr-service", 1000); +} + +void rm_clear_cpu_inheritance(void) +{ + //resource_clear_cpu_inheritance(0, "rscmgr-service"); +} + +int rm_dbus_method_call(const char *method, GVariant *args, GVariant **result) +{ + GError *err = NULL; + GVariant *reply = NULL; + GDBusConnection *conn = NULL; + + if (!method) { + RM_ERR("Invalid Argument"); + g_variant_unref(args); + return -1; + } + + RM_INFO("Method call '%s'", method); + + if (!_wait_server_ready()) { + RM_ERR("server is not ready yet"); + g_variant_unref(args); + return -1; + } + + conn = __dbus_get_connection(); + + if (!conn) { + g_variant_unref(args); + return -1; + } + + rm_set_cpu_inheritance(); + reply = g_dbus_connection_call_sync(conn, RM_DBUS_BUS_NAME, RM_DBUS_OBJ_PATH, RM_DBUS_INTERFACE_NAME, + method, args, NULL, G_DBUS_CALL_FLAGS_NONE, -1, NULL, &err); + rm_clear_cpu_inheritance(); + + if (!reply) { + RM_ERR("Method Call '%s' Failed (%s)", method, err->message); + g_error_free(err); + return -1; + } + + if (result) + *result = reply; + + return 0; +} + +int rm_dbus_method_call_async_with_no_reply(const char *method, GVariant *args) +{ + if (!method) { + RM_ERR("Invalid Argument"); + g_variant_unref(args); + return -1; + } + + RM_INFO("Method call (async) '%s'", method); + + if (!_wait_server_ready()) { + RM_ERR("server is not ready yet"); + return -1; + } + + GDBusConnection *conn = __dbus_get_connection(); + if (!conn) { + g_variant_unref(args); + return -1; + } + + g_dbus_connection_call(conn, RM_DBUS_BUS_NAME, RM_DBUS_OBJ_PATH, RM_DBUS_INTERFACE_NAME, + method, args, NULL, G_DBUS_CALL_FLAGS_NONE, -1, NULL, NULL, NULL); + + return 0; +} +// LCOV_EXCL_STOP diff --git a/src/rm_debug.cpp b/src/rm_debug.cpp new file mode 100644 index 0000000..f3dde03 --- /dev/null +++ b/src/rm_debug.cpp @@ -0,0 +1,128 @@ +/* + * Copyright (c) 2024 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 + +// LCOV_EXCL_START +const char *rm_convert_requested_state_enum_to_string(rm_requests_resource_state_e state_enum) +{ + switch(state_enum) { + case RM_STATE_PASSIVE: + return "PASSIVE"; + case RM_STATE_SHARABLE: + return "SHARABLE"; + case RM_STATE_EXCLUSIVE: + return "EXCLUSIVE"; + case RM_STATE_EXCLUSIVE_CONDITIONAL: + return "EXCLUSIVE_CONDITIONAL"; + case RM_STATE_EXCLUSIVE_AUTO: + return "EXCLUSIVE_AUTO"; + case RM_STATE_EXCLUSIVE_PREFERENCE: + return "EXCLUSIVE_PREFERENCE"; + default: + return "NONE"; + } +} + +const char *rm_convert_category_enum_to_string(rm_rsc_category_e category_enum) +{ + switch(category_enum) { + case RM_CATEGORY_NONE: + return "NONE"; + case RM_CATEGORY_AUDIO_DECODER: + return "Audio_Decoder"; + case RM_CATEGORY_AUDIO_DECODER_PRIMARY: + return "Audio_Decoder_Primary"; + case RM_CATEGORY_AUDIO_EVENT_COMPRESS: + return "Audio_Event_Compress"; + case RM_CATEGORY_AUDIO_SPDIF_ES_OUTPUT: + return "Not Defined Yet"; + case RM_CATEGORY_VIDEO_DECODER: + return "Video_Decoder"; + case RM_CATEGORY_DEMUX: + return "Demux_Main"; + case RM_CATEGORY_AUDIO_ENCODER: + return "Audio_Encoder"; + case RM_CATEGORY_VIDEO_ENCODER: + return "Video_Encoder"; + case RM_CATEGORY_SCALER: + return "Video_Scaler"; + case RM_CATEGORY_TUNER: + return "Tuner"; + case RM_CATEGORY_AUDIO_MAIN_OUT: + return "Audio_Main_Out"; + case RM_CATEGORY_AUDIO_REMOTE_OUT: + return "Audio_Remote_Out"; + case RM_CATEGORY_AUDIO_SCART_OUT: + return "Audio_Scart_Out"; + case RM_CATEGORY_MM_PCM_OUT: + return "MM_PCM_playback"; + case RM_CATEGORY_AUDIO_DECODER_SUB: + return "Audio_Decorder_Sub"; + case RM_CATEGORY_JPEG_DECODER: + return "JPEG_Decoder"; + case RM_CATEGORY_MJPEG_DECODER: + return "MJPEG_Decoder"; + case RM_CATEGORY_SCALER_SUB: + return "Video_Scaler_Sub"; + case RM_CATEGORY_EXT_VIDEO_SRC: + return "Ext_Video_Src"; + case RM_CATEGORY_EXT_AUDIO_SRC: + return "Ext_Audio_Src"; + case RM_CATEGORY_EXT_HDMI_SRC: + return "Ext_HDMI_Src"; + case RM_CATEGORY_VIDEO_DECODER_SUB: + return "Video_Decoder_Sub"; + case RM_CATEGORY_CAMERA: + return "Camera"; + case RM_CATEGORY_DEMUX_REC: + return "Demux_Rec"; + case RM_CATEGORY_TUNER_SUB: + return "Tuner_Sub"; + case RM_CATEGORY_VIDEO_DECODER_UHD: + return "Video_Decoder UHD"; + case RM_CATEGORY_INPUT_SRC_DTV: + return "Input_Src_DTV"; + case RM_CATEGORY_INPUT_SRC_ATV: + return "Input_Src_ATV"; + case RM_CATEGORY_INPUT_SRC_HDMI: + return "Input_Src_HDMI"; + case RM_CATEGORY_INPUT_SRC_COMP: + return "Input_Src_COMP"; + case RM_CATEGORY_INPUT_SRC_AV: + return "Input_Src_AV"; + case RM_CATEGORY_INPUT_SRC_SCART: + return "Input_Src_SCART"; + + default: + return ""; + } +} + +int is_symlink_file(const char *path) +{ + struct stat st; + if (lstat(path, &st) == -1) { + RM_ERR("stat error. file path(%s)", path); + return 0; + } + + return (S_ISLNK(st.st_mode)) ? 1 : 0; +} +// LCOV_EXCL_STOP diff --git a/src/rm_module_api.cpp b/src/rm_module_api.cpp new file mode 100644 index 0000000..8cb6d5f --- /dev/null +++ b/src/rm_module_api.cpp @@ -0,0 +1,1260 @@ +/* + * Copyright (c) 2024 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 + +// LCOV_EXCL_START + +#define RMS_INITIALIZED (access("/run/rsc_mgr_ready", F_OK) == 0) + +void rm_wait_for_server_ready(void) +{ + while (!RMS_INITIALIZED) { + RM_INFO("waiting for server ready"); + usleep(50*1000); // 50ms + } + RM_WARN("resource manager server is ready !!!"); +} + +int rm_get_resource_state(int rsc_id, rm_resource_state_e *state) +{ + RM_RETURN_ERR_IF_NULL(state, "invalid parameter"); + if (rsc_id < 0) { + RM_ERR("invalid resource id (%d)", rsc_id); + return RM_ERROR; + } + + int ret = RM_OK; + int rsc_state = 0; + GVariant *result = NULL; + + ret = rm_dbus_method_call("GetResourceState", + g_variant_new("(i)", rsc_id), + &result); + + if (ret) { + RM_ERR("dbus_method_call() for FindDeviceId is failed"); + return RM_ERROR; + } + + g_variant_get(result, "(i)", &rsc_state); + + if (rsc_state < 0) { + RM_ERR("can't get state(%d : %d)", rsc_id, rsc_state); + return RM_ERROR; + } + + *state = (rm_resource_state_e) rsc_state; + RM_INFO("state (%d : %d)", rsc_id, rsc_state); + g_variant_unref(result); + return RM_OK; +} + +int rm_get_scaler_state(rm_resource_list_h *list) +{ + RM_RETURN_ERR_IF_NULL(list, "invalid parameter"); + + int ret = RM_OK; + GVariant *result = NULL; + rm_resource_list *list_reply = NULL; + + list_reply = (rm_resource_list*) calloc(1, sizeof(rm_resource_list)); + assert(list_reply); + list_reply->n_rsc = 0; + *list = list_reply; + + ret = rm_dbus_method_call("GetScalerState", + g_variant_new("(i)", RM_CATEGORY_SCALER), + &result); + + if (ret) { + RM_ERR("dbus_method_call() for GetScalerState is failed"); + return RM_ERROR; + } + + int category_id; + int cur_category_id; + int rsc_id; + int state; + int cid; + int zone_id; + int android_app; + gchar *app_id; + + GVariantIter *iter; + g_variant_get(result, "(a(iiiiiisi))", &iter); + + while (g_variant_iter_loop(iter, "(iiiiiisi)", &category_id, &cur_category_id, &rsc_id, &state, &cid, &zone_id, &app_id, &android_app)) { + rm_resource *resource = (rm_resource*) calloc(1, sizeof(rm_resource)); + assert(resource); + resource->category_id = category_id; + resource->cur_category_id = cur_category_id; + resource->id = rsc_id; + resource->state = state; + resource->consumer_id = cid; + resource->zone_id = zone_id; + RM_INFO("(%d : %s)", resource->id, app_id ? app_id : "null"); + resource->app_id = (app_id) ? (char*) strndup(app_id, strlen(app_id)) : NULL; + resource->android_app = android_app; + list_reply->rsc_list = g_list_append(list_reply->rsc_list, resource); + } + g_variant_iter_free(iter); + + list_reply->n_rsc = g_list_length(list_reply->rsc_list); + list_reply->iter = list_reply->rsc_list; + + g_variant_unref(result); + return ret; +} + +int rm_get_resource_list(rm_rsc_category_e category, rm_resource_list_h *list) +{ + RM_RETURN_ERR_IF_NULL(list, "invalid parameter"); + + int ret = RM_OK; + GVariant *result = NULL; + rm_resource_list *list_reply = NULL; + + list_reply = (rm_resource_list*) calloc(1, sizeof(rm_resource_list)); + assert(list_reply); + list_reply->n_rsc = 0; + *list = list_reply; + + ret = rm_dbus_method_call("GetResourceList", + g_variant_new("(i)", category), + &result); + + if (ret) { + RM_ERR("dbus_method_call() for GetResourceList is failed"); + return RM_ERROR; + } + + int rsc_id; + int rsc_state; + int cid; + gchar *dev_node; + gchar *app_id; + + GVariantIter *iter; + g_variant_get(result, "(a(iissi))", &iter); + + while (g_variant_iter_loop(iter, "(iissi)", &rsc_id, &rsc_state, &dev_node, &app_id, &cid)) { + rm_resource *resource = (rm_resource*) calloc(1, sizeof(rm_resource)); + assert(resource); + resource->id = rsc_id; + resource->state = rsc_state; + resource->consumer_id = cid; + resource->support_overlay = ri_is_overlay_supported(rsc_id); + resource->max_rez = ri_get_supported_max_resolution(rsc_id); + resource->max_sampling_format = ri_get_max_sampling_format(rsc_id); + int category_id = 0; + if (ri_get_category_type_by_device_id(rsc_id, &category_id) != RI_OK) { + RM_ERR("failed to get category of (%d)", rsc_id); + } + resource->category_id = category_id; + + RM_INFO("(%d:%s)", resource->id, dev_node?dev_node : "null"); + resource->node = (dev_node) ? (char*) strndup(dev_node, strlen(dev_node)) : NULL; + resource->app_id = (app_id) ? (char*) strndup(app_id, strlen(app_id)) : NULL; + list_reply->rsc_list = g_list_append(list_reply->rsc_list, resource); + } + + g_variant_iter_free(iter); + + list_reply->n_rsc = g_list_length(list_reply->rsc_list); + list_reply->iter = list_reply->rsc_list; + + g_variant_unref(result); + return ret; +} + +static void rm_resource_free(gpointer data) +{ + rm_resource *resource = (rm_resource*) data; + RM_RETURN_IF_NULL(resource, "resource null"); + RM_FREE(resource->node); + RM_FREE(resource->app_id); + RM_FREE(resource); +} + +void rm_free_resource_list(rm_resource_list_h list) +{ + if (!list) + return; + + g_list_free_full(list->rsc_list, rm_resource_free); + RM_FREE(list); +} + +rm_resource_h rm_resource_list_get_next(rm_resource_list_h list) +{ + RM_RETURN_NULL_IF_NULL(list, "invalid list"); + RM_RETURN_NULL_IF_NULL(list->rsc_list, "no device in resource list"); + RM_RETURN_NULL_IF_NULL(list->iter, "no device in resource list"); + + GList *tmp = g_list_next(list->iter); + + RM_RETURN_NULL_IF_NULL(tmp, "no next resource"); + + list->iter = tmp; + return (rm_resource_h) list->iter->data; +} + +rm_resource_h rm_resource_list_get_prev(rm_resource_list_h list) +{ + RM_RETURN_NULL_IF_NULL(list, "invalid list"); + RM_RETURN_NULL_IF_NULL(list->rsc_list, "no device in resource list"); + RM_RETURN_NULL_IF_NULL(list->iter, "no device in resource list"); + + GList *tmp = g_list_previous(list->iter); + + RM_RETURN_NULL_IF_NULL(tmp, "no prev resource"); + + list->iter = tmp; + return (rm_resource_h) list->iter->data; +} + +rm_resource_h rm_resource_list_get_first(rm_resource_list_h list) +{ + RM_RETURN_NULL_IF_NULL(list, "invalid list"); + RM_RETURN_NULL_IF_NULL(list->rsc_list, "no device in resource list"); + RM_RETURN_NULL_IF_NULL(list->iter, "no device in resource list"); + + GList *tmp = g_list_first(list->iter); + + RM_RETURN_NULL_IF_NULL(tmp, "no first resource"); + + list->iter = tmp; + return (rm_resource_h) list->iter->data; +} + +rm_resource_h rm_resource_list_get_last(rm_resource_list_h list) +{ + RM_RETURN_NULL_IF_NULL(list, "invalid list"); + RM_RETURN_NULL_IF_NULL(list->rsc_list, "no device in resource list"); + RM_RETURN_NULL_IF_NULL(list->iter, "no device in resource list"); + + GList *tmp = g_list_last(list->iter); + + RM_RETURN_NULL_IF_NULL(tmp, "no last resource"); + + list->iter = tmp; + return (rm_resource_h) list->iter->data; +} + +int rm_resource_list_get_count(rm_resource_list_h list) +{ + return (list) ? list->n_rsc : 0; +} + +const char *rm_resource_get_node(rm_resource_h resource) +{ + RM_RETURN_NULL_IF_NULL(resource, "invalid parameter"); + return resource->node; +} + +int rm_resource_get_category(rm_resource_h resource) +{ + RM_RETURN_MINUS_IF_NULL(resource, "invalid parameter"); + return resource->category_id; +} + +int rm_resource_get_cur_category(rm_resource_h resource) +{ + RM_RETURN_MINUS_IF_NULL(resource, "invalid parameter"); + return resource->cur_category_id; +} + +int rm_resource_get_consumer(rm_resource_h resource) +{ + RM_RETURN_MINUS_IF_NULL(resource, "invalid parameter"); + return resource->consumer_id; +} + +int rm_resource_get_state(rm_resource_h resource) +{ + RM_RETURN_MINUS_IF_NULL(resource, "invalid parameter"); + return resource->state; +} + +const char *rm_resource_get_app_id(rm_resource_h resource) +{ + RM_RETURN_NULL_IF_NULL(resource, "invalid parameter"); + return resource->app_id; +} + +unsigned int rm_resource_get_framerate(rm_resource_h resource) +{ + RM_RETURN_MINUS_IF_NULL(resource, "invalid parameter"); + return resource->framerate; +} + +int rm_resource_get_id(rm_resource_h resource) +{ + return (resource) ? resource->id : -1; +} + +int rm_resource_get_max_resolution(rm_resource_h resource) +{ + return (resource) ? resource->max_rez : -1; +} + +bool rm_resource_support_overlay(rm_resource_h resource) +{ + return (resource) ? resource->support_overlay : false; +} + +int rm_resource_get_max_sampling_format(rm_resource_h resource) +{ + return (resource) ? resource->max_sampling_format : -1; +} + +int rm_resource_get_zone_id(rm_resource_h resource) +{ + return (resource) ? resource->zone_id : -1; +} + +static unsigned int state_change_signal_id = 0; + +static void onResourceStateChanged(GDBusConnection *conn, + const gchar *sender, + const gchar *object, + const gchar *interface, + const gchar *signal, + GVariant *parameters, + gpointer user_data) +{ + int device_id; + int category_id; + int state; + int handle; + char *app_id; + + g_variant_get(parameters, "(iiii&s)", &device_id, &category_id, &state, &handle, &app_id); + RM_INFO("signal (%s) received - (%d(%d) : %d : %d(%s))", signal, device_id, category_id, state, handle, app_id); + rm_call_state_changed_cb(category_id, device_id, state, handle, app_id); +} + +int rm_subscribe_resource_state_change(rm_rsc_category_e category, resource_state_change_cb cb, void *data) +{ + RM_RETURN_ERR_IF_NULL(cb, "invalid parameter"); + + if (rm_add_state_change_cb(category, cb, data) < 0) { + RM_ERR("already registered cb (%d : %p)", category, cb); + return RM_ERROR; + } + + if (state_change_signal_id) + return RM_OK; + + GError *error = NULL; + GDBusConnection *connection = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error); + if (!connection) { + RM_ERR("failed to get connection (%s)", (error) ? error->message : "unknown"); + return RM_ERROR; + } + + state_change_signal_id = g_dbus_connection_signal_subscribe(connection, + NULL, + RM_DBUS_INTERFACE_NAME, + "RscStateChanged", + RM_DBUS_OBJ_PATH, + NULL, + G_DBUS_SIGNAL_FLAGS_NONE, + onResourceStateChanged, + NULL, + NULL); + + if (state_change_signal_id == 0) { + if (error) { + RM_ERR("dbus connection close error: %s", error->message); + g_clear_error(&error); + } + return RM_ERROR; + } + + RM_INFO("subscribe resource state changed (%d)", state_change_signal_id); + return RM_OK; +} + +int rm_unsubscribe_resource_state_change(rm_rsc_category_e category, resource_state_change_cb cb) +{ + RM_RETURN_ERR_IF_NULL(cb, "invalid parameter"); + + int remain = 0; + if ((remain = rm_remove_state_change_cb(category, cb)) < 0) { + RM_ERR("not registered cb (%d:%p)", category, cb); + return RM_ERROR; + } + + if (remain > 0) { + RM_INFO("resource state change cb(%d:%p) removed", category, cb); + return RM_OK; + } + + GError *error = NULL; + GDBusConnection *connection = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error); + if (!connection) { + RM_ERR("failed to get connection (%s)", (error) ? error->message : "unknown"); + return RM_OK; + } + + RM_INFO("remove state change signal id(%d)", state_change_signal_id); + g_dbus_connection_signal_unsubscribe(connection, state_change_signal_id); + state_change_signal_id = 0; + + return RM_OK; +} + +int rm_rsc_state_get_category(rm_resource_state_h state) +{ + RM_RETURN_MINUS_IF_NULL(state, "invalid state"); + return state->catId; +} + +int rm_rsc_state_get_device_id(rm_resource_state_h state) +{ + RM_RETURN_MINUS_IF_NULL(state, "invalid state"); + return state->devId; +} + +int rm_rsc_state_get_state(rm_resource_state_h state) +{ + RM_RETURN_MINUS_IF_NULL(state, "invalid state"); + return state->state; +} + +int rm_rsc_state_get_consumer_id(rm_resource_state_h state) +{ + RM_RETURN_MINUS_IF_NULL(state, "invalid state"); + return state->consumerId; +} + +char *rm_rsc_state_get_app_id(rm_resource_state_h state) +{ + RM_RETURN_NULL_IF_NULL(state, "invalid state"); + return state->appId; +} + +static void OnResourceConflictEvent(GDBusConnection *conn, + const gchar *sender, + const gchar *object, + const gchar *interface, + const gchar *signal, + GVariant *parameters, + gpointer user_data) +{ + rm_conflict_resource rsc; + g_variant_get(parameters, "(iii&sii)", &rsc.catId, &rsc.devId, &rsc.cId, &rsc.appId, &rsc.aZoneId, &rsc.rZoneId); + + RM_INFO("signal (%s) received - (%d:%d:%d:%s:%d:%d)", signal, rsc.catId, rsc.devId, rsc.cId, rsc.appId, rsc.aZoneId, rsc.rZoneId); + + std::list cb_list = rm_get_conflict_event_cb_list(); + + for (auto& it : cb_list) { + RM_INFO("call cb(%p)", it->cb); + it->cb(&rsc, it->data); + } +} + +static unsigned int conflict_event_signal_id = 0; + +int rm_subscribe_resource_conflict_event(rm_conflict_event_cb cb, void *data) +{ + RM_RETURN_ERR_IF_NULL(cb, "invalid cb"); + + if (rm_add_conflict_event_cb(cb, data) < 0) { + RM_ERR("already registered cb(%p)", cb); + return RM_ERROR; + } + + if (conflict_event_signal_id) + return RM_OK; + + GError *error = NULL; + GDBusConnection *connection = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error); + if (!connection) { + RM_ERR("failed to get connection (%s)", (error) ? error->message : "unknown"); + rm_remove_conflict_event_cb(cb); + return RM_ERROR; + } + + conflict_event_signal_id = g_dbus_connection_signal_subscribe(connection, + NULL, + RM_DBUS_INTERFACE_NAME, + "RscConflicted", + RM_DBUS_OBJ_PATH, + NULL, + G_DBUS_SIGNAL_FLAGS_NONE, + OnResourceConflictEvent, + NULL, + NULL); + + if (conflict_event_signal_id == 0) { + if (error) { + RM_ERR("dbus connection close error: %s", error->message); + g_clear_error(&error); + rm_remove_conflict_event_cb(cb); + } + return RM_ERROR; + } + + RM_INFO("subscribe conflict event (%d)", conflict_event_signal_id); + + return RM_OK; +} + +int rm_unsubscribe_resource_conflict_event(rm_conflict_event_cb cb) +{ + RM_RETURN_ERR_IF_NULL(cb, "invalid cb"); + + int remain = 0; + if ((remain = rm_remove_conflict_event_cb(cb)) < 0) { + RM_ERR("unregistered cb(%p)", cb); + return RM_ERROR; + } + + RM_INFO("callback unregistered(%p)-(%d)", cb, remain); + + if (remain > 0) + return RM_OK; + + GError *error = NULL; + GDBusConnection *connection = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error); + if (!connection) { + RM_ERR("failed to get connection (%s)", (error) ? error->message : "unknown"); + return RM_OK; + } + + RM_INFO("remove conflict event signal id(%d)", conflict_event_signal_id); + g_dbus_connection_signal_unsubscribe(connection, conflict_event_signal_id); + conflict_event_signal_id = 0; + + return RM_OK; +} + +int rm_conflict_get_category_id(rm_conflict_resource_h rsc) +{ + RM_RETURN_MINUS_IF_NULL(rsc, "invalid rsc"); + return rsc->catId; +} + +int rm_conflict_get_device_id(rm_conflict_resource_h rsc) +{ + RM_RETURN_MINUS_IF_NULL(rsc, "invalid rsc"); + return rsc->devId; +} + +int rm_conflict_get_consumer_id(rm_conflict_resource_h rsc) +{ + RM_RETURN_MINUS_IF_NULL(rsc, "invalid rsc"); + return rsc->cId; +} + +const char *rm_conflict_get_app_id(rm_conflict_resource_h rsc) +{ + RM_RETURN_NULL_IF_NULL(rsc, "invalid rsc"); + return rsc->appId; +} + +int rm_conflict_get_multiview_zone_id_consumer(rm_conflict_resource_h rsc) +{ + RM_RETURN_MINUS_IF_NULL(rsc, "invalid rsc"); + return rsc->aZoneId; +} + +int rm_conflict_get_multiview_zone_id_requester(rm_conflict_resource_h rsc) +{ + RM_RETURN_MINUS_IF_NULL(rsc, "invalid rsc"); + return rsc->rZoneId; +} + +int rm_get_resource_collection_state(rm_rsc_collection_e collection, rm_resource_list_h *list) +{ + RM_RETURN_ERR_IF_NULL(list, "invalid parameter"); + + int ret; + GVariant *result = NULL; + rm_resource_list *list_reply = NULL; + + list_reply = (rm_resource_list*) calloc(1, sizeof(rm_resource_list)); + assert(list_reply); + list_reply->n_rsc = 0; + *list = list_reply; + + ret = rm_dbus_method_call("GetRscCollectionState", + g_variant_new("(i)", collection), + &result); + + if (ret) { + RM_ERR("dbus_method_call() for GetRscCollectionState is failed"); + return RM_ERROR; + } + + int rsc_id; + int rsc_state; + int rsc_category; + int cid; + int zone_id; + int android_app; + gchar *app_id; + gchar *dev_node; + + GVariantIter *iter; + g_variant_get(result, "(a(isiiisii))", &iter); + + while (g_variant_iter_loop(iter, "(isiiisii)", &rsc_id, &dev_node, &rsc_state, &rsc_category, &cid, &app_id, &zone_id, &android_app)) { + rm_resource *resource = (rm_resource*) calloc(1, sizeof(rm_resource)); + assert(resource); + resource->id = rsc_id; + RM_INFO("(%d:%s)", resource->id, dev_node?dev_node : "null"); + resource->node = (dev_node) ? (char*) strndup(dev_node, strlen(dev_node)) : NULL; + resource->state = rsc_state; + resource->category_id = rsc_category; + resource->framerate = ri_get_video_category_framerate(rsc_category); + resource->consumer_id = cid; + resource->app_id = (app_id) ? (char*) strndup(app_id, strlen(app_id)) : NULL; + resource->zone_id = zone_id; + resource->android_app = android_app; + list_reply->rsc_list = g_list_append(list_reply->rsc_list, resource); + } + + g_variant_iter_free(iter); + + list_reply->n_rsc = g_list_length(list_reply->rsc_list); + list_reply->iter = list_reply->rsc_list; + + g_variant_unref(result); + return ret; +} + +int rm_unmask_category_options(int category) +{ + int result = category; + + result = (result & ~RM_DEVICE_OPT_MAIN); + result = (result & ~RM_DEVICE_OPT_SUB); + + return ri_unmask_category_options(result); +} + +int rm_find_device_id(int virtual_id) +{ + if (virtual_id < 0) { + RM_ERR("invalid resource id (%d)", virtual_id); + return -1; + } + + int real_id = 0; + if (rm_shm_find_device_id(virtual_id, &real_id) == RM_OK) { + RM_INFO("real id (%d:%d)", virtual_id, real_id); + return real_id; + } + + int ret = RM_OK; + + GVariant *result = NULL; + + ret = rm_dbus_method_call("FindDeviceId", + g_variant_new("(i)", virtual_id), + &result); + + if (ret) { + RM_ERR("dbus_method_call() for FindDeviceId is failed"); + return RM_ERROR; + } + + g_variant_get(result, "(i)", &real_id); + + RM_INFO("real id (%d:%d)", virtual_id, real_id); + + g_variant_unref(result); + return real_id; +} + +int rm_swap_resources(int device_id_a, int device_id_b) +{ + if ((device_id_a < 0) || (device_id_b < 0)) { + RM_ERR("invalid resource id (%d/%d)", device_id_a, device_id_b); + return RM_ERROR; + } + + int ret = RM_OK; + int swap_result = 0; + GVariant *result = NULL; + + ret = rm_dbus_method_call("SwapResources", + g_variant_new("(ii)", device_id_a, device_id_b), + &result); + + if (ret) { + RM_ERR("dbus_method_call() for SwapResources is failed"); + return RM_ERROR; + } + + g_variant_get(result, "(i)", &swap_result); + + if (swap_result < 0) { + RM_ERR("faild to swap resources(%d:%d)", device_id_a, device_id_b); + ret = RM_ERROR; + } + + RM_INFO("swapped (%d:%d)", device_id_a, device_id_b); + + g_variant_unref(result); + return ret; +} + +int rm_swap_resources_async(int device_id_a, int device_id_b) +{ + if ((device_id_a < 0) || (device_id_b < 0)) { + RM_ERR("invalid resource id (%d/%d)", device_id_a, device_id_b); + return RM_ERROR; + } + + int ret = rm_dbus_method_call_async_with_no_reply("SwapResources", + g_variant_new("(ii)", device_id_a, device_id_b)); + if (ret) { + RM_ERR("dbus_method_call() for SwapResourcesAsync is failed"); + return RM_ERROR; + } + + RM_INFO("swapped requested (%d:%d)", device_id_a, device_id_b); + return RM_OK; +} + +int rm_restore_resources(int category) +{ + if (category < 0) { + RM_ERR("invalid category id (%d)", category); + return RM_ERROR; + } + + int ret = RM_OK; + int restore_result = 0; + GVariant *result = NULL; + + ret = rm_dbus_method_call("RestoreResources", + g_variant_new("(i)", category), + &result); + + if (ret) { + RM_ERR("dbus_method_call() for RestoreResources is failed"); + return RM_ERROR; + } + + g_variant_get(result, "(i)", &restore_result); + + if (restore_result < 0) { + RM_ERR("faild to restore resources(%d)", category); + ret = RM_ERROR; + } + + RM_INFO("restored (%d)", category); + + g_variant_unref(result); + return ret; +} + +int rm_get_app_id(int handle, char**app_id) +{ + if (handle < 0 || !app_id) { + RM_ERR("invalid param (%d)", handle); + return RM_ERROR; + } + + if (rm_shm_get_app_id(handle, app_id) == RM_OK) + return RM_OK; + + int ret = RM_OK; + int dbus_ret = 0; + char *ret_val = NULL; + GVariant *result = NULL; + + ret = rm_dbus_method_call("GetAppId", + g_variant_new("(i)", handle), + &result); + + if (ret) { + RM_ERR("dbus_method_call() for GetAppId is failed"); + return RM_ERROR; + } + + g_variant_get(result, "(i&s)", &dbus_ret, &ret_val); + + if (dbus_ret < 0) + ret = RM_ERROR; + + if (ret_val) + *app_id = strndup(ret_val, strlen(ret_val)); + + RM_INFO("(%d) - app_id(%d : %s)", dbus_ret, handle, (ret_val) ? *app_id : "null"); + + g_variant_unref(result); + return ret; +} + +int rm_get_active_audio_out(int handle) +{ + if (handle < 0) { + RM_ERR("invalid handle(%d)", handle); + return -1; + } + + int active_audio_out = 0; + if (rm_shm_get_active_audio_out(handle, &active_audio_out) == RM_OK) + return active_audio_out; + + int ret = 0; + GVariant *result = NULL; + + ret = rm_dbus_method_call("GetActiveAudioOut", + g_variant_new("(i)", handle), + &result); + if (ret) { + RM_ERR("dbus_method_call() for GetActiveAudioOut is failed"); + return -1; + } + + g_variant_get(result, "(i)", &active_audio_out); + + RM_INFO("active audio out (%d:%d)", handle, active_audio_out); + + g_variant_unref(result); + return active_audio_out; +} + +int rm_scaler_get_virtual_id(rm_resource_h scaler) +{ + return (scaler) ? scaler->virtual_id : -1; +} + +int rm_scaler_get_source_id(rm_resource_h scaler) +{ + return (scaler) ? scaler->source_id : -1; +} + +static unsigned int scaler_change_signal_id = 0; +static void onScalerStateChanged(GDBusConnection *conn, + const gchar *sender, + const gchar *object, + const gchar *interface, + const gchar *signal, + GVariant *param, + gpointer user_data) +{ + rm_resource_list *scaler_list = NULL; + + scaler_list = (rm_resource_list*) calloc(1, sizeof(rm_resource_list)); + assert(scaler_list); + scaler_list->n_rsc = 0; + + int virtual_id; + int source_id; + GVariantIter *iter; + g_variant_get(param, "(a(ii))", &iter); + + RM_INFO(">> scaler state changed"); + while (g_variant_iter_loop(iter, "(ii)", &virtual_id, &source_id)) { + rm_resource *scaler = (rm_resource*) calloc(1, sizeof(rm_resource)); + assert(scaler); + + scaler->virtual_id = virtual_id; + scaler->source_id = source_id; + RM_INFO("(%d:%d)", scaler->virtual_id, scaler->source_id); + + scaler_list->rsc_list = g_list_append(scaler_list->rsc_list, scaler); + } + + g_variant_iter_free(iter); + + scaler_list->n_rsc = g_list_length(scaler_list->rsc_list); + scaler_list->iter = scaler_list->rsc_list; + + rm_call_scaler_state_changed_cb(scaler_list); + + g_list_free_full(scaler_list->rsc_list, rm_resource_free); + RM_FREE(scaler_list); +} + +int rm_subscribe_scaler_state_change(scaler_state_change_cb cb, void *data) +{ + RM_RETURN_ERR_IF_NULL(cb, "invalid parameter"); + + if (rm_add_scaler_state_change_cb(cb, data) < 0) { + RM_ERR("already registered cb (%p)", cb); + return RM_ERROR; + } + + if (scaler_change_signal_id) + return RM_OK; + + GError *error = NULL; + GDBusConnection *connection = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error); + if (!connection) { + RM_ERR("failed to get connection (%s)", (error) ? error->message : "unknown"); + return RM_ERROR; + } + + scaler_change_signal_id = g_dbus_connection_signal_subscribe(connection, + NULL, + RM_DBUS_INTERFACE_NAME, + "ScalerStateChanged", + RM_DBUS_OBJ_PATH, + NULL, + G_DBUS_SIGNAL_FLAGS_NONE, + onScalerStateChanged, + NULL, + NULL); + + if (scaler_change_signal_id == 0) { + if (error) { + RM_ERR("dbus connection close error: %s", error->message); + g_clear_error(&error); + } + return RM_ERROR; + } + + RM_INFO("subscribe resource state changed (%d)", scaler_change_signal_id); + return RM_OK; +} + +int rm_unsubscribe_scaler_state_change(scaler_state_change_cb cb) +{ + RM_RETURN_ERR_IF_NULL(cb, "invalid parameter"); + + int remain = 0; + if ((remain = rm_remove_scaler_state_change_cb(cb)) < 0) { + RM_ERR("not registered cb (%p)", cb); + return RM_ERROR; + } + + if (remain > 0) { + RM_INFO("scaler state change cb(%p) removed", cb); + return RM_OK; + } + + GError *error = NULL; + GDBusConnection *connection = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error); + if (!connection) { + RM_ERR("failed to get connection (%s)", (error) ? error->message : "unknown"); + return RM_OK; + } + + RM_INFO("remove scaler change signal id(%d)", scaler_change_signal_id); + g_dbus_connection_signal_unsubscribe(connection, scaler_change_signal_id); + scaler_change_signal_id = 0; + + return RM_OK; +} + +int rm_get_scaler_hw_id(int zone_id, int *id) +{ + if (zone_id <= 0) { + RM_ERR("invalid resource id (%d)", zone_id); + return RM_ERROR; + } + + if (rm_shm_find_scaler_hw_id(zone_id, id) == RM_OK) + return RM_OK; + + int ret = RM_OK; + int hw_id = 0; + GVariant *result = NULL; + + ret = rm_dbus_method_call("GetScalerHWID", + g_variant_new("(i)", zone_id), + &result); + + if (ret) { + RM_ERR("dbus_method_call() for GetScalerHWID is failed"); + return RM_ERROR; + } + + g_variant_get(result, "(i)", &hw_id); + + if (hw_id < 0) { + RM_ERR("can't get hw id(%d:%d)", zone_id, hw_id); + g_variant_unref(result); + return RM_ERROR; + } + + *id = hw_id; + RM_INFO("hw id (%d:%d)", zone_id, hw_id); + g_variant_unref(result); + return RM_OK; +} + +int rm_notify_resource_policy(int policy) +{ + if (policy < 0) { + RM_ERR("invalid policy (%d)", policy); + return RM_ERROR; + } + + int ret = rm_dbus_method_call_async_with_no_reply("NotifyResourcePolicy", + g_variant_new("(i)", policy)); + + if (ret) { + RM_ERR("dbus_method_call() for NotifyResourcePolicy is failed"); + return RM_ERROR; + } + + RM_INFO("notified (%d)", policy); + return ret; +} + +int rm_notify_app_zone_info_async(const char *app_id, int zone_id) +{ + if (!app_id || zone_id < -1) { + RM_ERR("invalid param (%d)", zone_id); + return RM_ERROR; + } + + if (rm_dbus_method_call_async_with_no_reply("NotifyAppZoneInfo", g_variant_new("(si)", app_id, zone_id)) != 0) { + RM_ERR("dbus_method_call() for NotifyAppZoneInfo is failed"); + return RM_ERROR; + } + + RM_INFO("notified (%s:%d)", app_id, zone_id); + return RM_OK; +} + +int rm_reclaim_resources(int handle) +{ + RM_INFO("reclaim resources of (%d)", handle); + + if (rm_dbus_method_call_async_with_no_reply("ReclaimResources", g_variant_new("(i)", handle)) != 0) { + RM_ERR("dbus call for ReclaimResources failed"); + return RM_ERROR; + } + + return RM_OK; +} + +int rm_reclaim_app_resources(const char *app_id, const bool notify) +{ + if (!app_id) { + RM_ERR("invalid app id"); + return RM_ERROR; + } + + RM_INFO("reclaim resources of (%s:%d)", app_id, notify); + + GVariant *response = NULL; + if (rm_dbus_method_call("ReclaimAppResources", g_variant_new("(si)", app_id, notify), &response) != 0) { + RM_ERR("dbus call for ReclaimAppResources failed"); + return RM_ERROR; + } + + int reclaim_result = 0; + g_variant_get(response, "(i)", &reclaim_result); + + int result = (reclaim_result < 0) ? RM_ERROR : RM_OK; + RM_INFO("reclaime result (%s : %d)", app_id, result); + + g_variant_unref(response); + return result; +} + +int rm_reclaim_app_resources_async(const char *app_id, const bool notify) +{ + if (!app_id) { + RM_ERR("invalid app id"); + return RM_ERROR; + } + + RM_INFO("reclaim resources of (%s : %d)", app_id, notify); + + if (rm_dbus_method_call_async_with_no_reply("ReclaimAppResources", g_variant_new("(si)", app_id, notify)) != 0) { + RM_ERR("dbus call for ReclaimAppResources failed"); + return RM_ERROR; + } + + return RM_OK; +} + +rm_resource_list_h rm_resource_list_create(void) +{ + rm_resource_list *list = (rm_resource_list*) calloc(1, sizeof(rm_resource_list)); + if (!list) { + RM_ERR("insufficient memory"); + return NULL; + } + + list->n_rsc = 0; + return list; +} + +int rm_resource_list_append(rm_resource_list_h list, const rm_resource_h resource) +{ + if (!list || !resource) { + RM_ERR("invalid param"); + return RM_ERROR; + } + + list->rsc_list = g_list_append(list->rsc_list, resource); + list->n_rsc = g_list_length(list->rsc_list); + list->iter = list->rsc_list; + return RM_OK; +} + +rm_resource_h rm_create_video_encoder(const unsigned int width, const unsigned int height, const unsigned int framerate) +{ + rm_resource *resource = (rm_resource*) calloc(1, sizeof(rm_resource)); + if (!resource) { + RM_ERR("insufficient memory"); + return NULL; + } + + resource->width = width; + resource->height = height; + resource->framerate = framerate; + return resource; +} + +int rm_allocatable_video_encoders(const rm_resource_list_h list, bool *result) +{ + if (!list) { + RM_ERR("invalid param"); + *result = false; + return RM_ERROR; + } + + GVariantBuilder builder; + g_variant_builder_init(&builder, G_VARIANT_TYPE("(a(uuu))")); + g_variant_builder_open(&builder, G_VARIANT_TYPE("a(uuu)")); + + rm_resource_h resource = rm_resource_list_get_first(list); + while (resource) { + RM_INFO("w(%u)/h(%u)/fps(%u)", rm_resource_get_width(resource), rm_resource_get_height(resource), rm_resource_get_framerate(resource)); + g_variant_builder_add(&builder, "(uuu)", rm_resource_get_width(resource), rm_resource_get_height(resource), rm_resource_get_framerate(resource)); + resource = rm_resource_list_get_next(list); + }; + + g_variant_builder_close(&builder); + + GVariant *response = NULL; + if (rm_dbus_method_call("AllocatableVideoEncoders", g_variant_builder_end(&builder), &response) != 0) { + *result = false; + RM_ERR("dbus_method_call() for AllocatableVideoEncoders failed"); + return RM_ERROR; + } + + int available = 0; + g_variant_get(response, "(i)", &available); + g_variant_unref(response); + RM_INFO("available (%d)", available); + *result = (available == 1); + return RM_OK; +} + +unsigned int rm_resource_get_width(const rm_resource_h resource) +{ + if (!resource) { + RM_ERR("invalid param"); + return 0; + } + return resource->width; +} + +unsigned int rm_resource_get_height(const rm_resource_h resource) +{ + if (!resource) { + RM_ERR("invalid param"); + return 0; + } + return resource->height; +} + +bool rm_resource_android_app(const rm_resource_h resource) +{ + if (!resource) + return false; + + return resource->android_app; +} + +int rm_reclaim_video_decoders(const char *requester) +{ + if (!requester) { + RM_ERR("invalid param"); + return RM_ERROR; + } + + RM_INFO("reclaim video decoders allocated to other than (%s)", requester); + + GVariant *response = NULL; + if (rm_dbus_method_call("ReclaimVideoDecoders", g_variant_new("(s)", requester), &response) != 0) { + RM_ERR("dbus call for ReclaimVideoDecoders failed"); + return RM_ERROR; + } + + int result = 0; + g_variant_get(response, "(i)", &result); + g_variant_unref(response); + + RM_INFO("result : (%d)", result); + return (result == 0) ? RM_OK : RM_ERROR; +} + +bool rm_active_player(const int handle) +{ + bool result = false; + if (rm_shm_active_player(handle, &result) == RM_OK) { + RM_INFO("(%d : %d)", handle, result); + return result; + } + + GVariant *response = NULL; + if (rm_dbus_method_call("ActivePlayer", g_variant_new("(i)", handle), &response) != 0) { + RM_ERR("dbus call for ActivePlayer (%d) failed", handle); + return false; + } + + g_variant_get(response, "(b)", &result); + + RM_INFO("(%d : %d)", handle, result); + return result; +} + +bool rm_reclaimed_player(const int handle) +{ + bool result = false; + + GVariant *response = NULL; + if (rm_dbus_method_call("ReclaimedPlayer", g_variant_new("(i)", handle), &response)!= 0) { + RM_ERR("dbus call for ReclaimedPlayer (%d) failed", handle); + return false; + } + + g_variant_get(response, "(b)", &result); + + RM_INFO("(%d : %d)", handle, result); + return result; +} + +// LCOV_EXCL_STOP diff --git a/src/rm_msg.cpp b/src/rm_msg.cpp new file mode 100644 index 0000000..f1f6ae4 --- /dev/null +++ b/src/rm_msg.cpp @@ -0,0 +1,211 @@ +/* + * Copyright (c) 2024 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 + +#define RM_MSGQ_KEY_TX 8211 +#define RM_MSGQ_KEY_RX 8212 + +static int msgq_tx = -1; +static int msgq_rx = -1; + +static inline bool msgq_initialized(void) +{ + return ((msgq_tx >= 0) && (msgq_rx >= 0)); +} + +static int msgq_create(void) +{ + msgq_tx = msgget((key_t)RM_MSGQ_KEY_TX, 0666 | IPC_CREAT); + msgq_rx = msgget((key_t)RM_MSGQ_KEY_RX, 0666 | IPC_CREAT); + + if ((msgq_tx == -1) || (msgq_rx == -1)) { + RM_ERR("failed to get msgq_id - msgq_tx(%d), msgq_rx(%d)", msgq_tx, msgq_rx); + return RM_ERROR; + } + + RM_INFO("msgq_tx (%d), msgq_rx(%d)", msgq_tx, msgq_rx); + + return RM_OK; +} + +// LCOV_EXCL_START +static int msgq_recover_tx(void) +{ + msgq_tx = msgget((key_t)RM_MSGQ_KEY_TX, 0666 | IPC_CREAT); + + if (msgq_tx == -1) { + RM_ERR("failed to get new msgq_id - msgq_tx(%d), errno(%d)", msgq_tx, errno); + return RM_ERROR; + } + + RM_ERR("msgq recovered - msgq_tx(%d)", msgq_tx); + return RM_OK; +} + + +static int msgq_recover_rx(void) +{ + msgq_rx = msgget((key_t)RM_MSGQ_KEY_RX, 0666 | IPC_CREAT); + + if (msgq_rx == -1) { + RM_ERR("failed to get new msgq_id - msgq_rx(%d), errno(%d)", msgq_rx, errno); + return RM_ERROR; + } + + RM_ERR("msgq recovered - msgq_rx(%d)", msgq_rx); + return RM_OK; +} +// LCOV_EXCL_STOP + +int rm_send_msg(rm_msg_request *data) +{ + struct timespec tnow; + clock_gettime(CLOCK_MONOTONIC, &tnow); + + if (!msgq_initialized()) + msgq_create(); + + RM_INFO("msgq_tx %d msgq_rx %d", msgq_tx, msgq_rx); + + int retry = 0; + + RM_WARN("handle(%d) req.data_type : %ld, req #%d, req.type : %d, req.pid : %d", data->handle, data->data_type, data->request_num, data->type, data->pid); + + while (msgsnd(msgq_tx,(void*) data, sizeof(rm_msg_request) - sizeof(long), 0) == -1) { + // LCOV_EXCL_START + RM_ERR("failed to send message (%d)", errno); + + if (errno == EIDRM) { + RM_ERR("ERROR! msgid removed from system"); + if (msgq_recover_tx() != RM_OK) + return RM_ERROR; + } else if ((errno == EINVAL) && (data->data_type > 0)) { /* maybe msgid removed from system */ + RM_ERR("ERROR! invalid argument error. maybe msgid removed from system"); + if (msgq_recover_tx() != RM_OK) + return RM_ERROR; + } + + if (retry >= 5) { + RM_ERR("ERROR! timeout"); + return RM_ERROR; + } + + usleep(20 * 1000); /* 20ms */ + retry++; + // LCOV_EXCL_STOP + } + + return RM_OK; +} + +int rm_receive_msg(rm_msg_response *response, int msg_type) +{ + int retry = 0; + struct timespec tnow; + clock_gettime(CLOCK_MONOTONIC, &tnow); + + if (!msgq_initialized()) + msgq_create(); + + while (msgrcv(msgq_rx, (void*) response, sizeof(rm_msg_response) - sizeof(long), msg_type, 0) == -1) { + // LCOV_EXCL_START + RM_ERR("Failed to get message, errno(%d)", errno); + + if (errno == EIDRM) { + RM_ERR("WARNING! msgid removed from system"); + msgq_recover_rx(); + return RM_ERROR; + } else if (errno == EINVAL) { /* maybe msgid removed from system */ + RM_ERR("ERROR! invalid argument error. maybe msgid removed from system"); + if (msgq_recover_rx() != RM_OK) + return RM_ERROR; + + if (retry >= 5) { + RM_ERR("ERROR! timeout"); + return RM_ERROR; + } + + usleep(20 * 1000); /* 20ms */ + retry++; + } else if (errno == EINTR) { + RM_ERR("WARNING! System Call Inturrupted"); + continue; + } else { + RM_ERR("Error(errno:%d) is occured!!", errno); + return RM_ERROR; + } + // LCOV_EXCL_STOP + } + + return RM_OK; +} + +static int get_msg_uid(void) +{ + static int msg_id = 1; + const int msg_id_max = 65535; // (2^16 - 1) + + return (++msg_id > msg_id_max) ? 1 : msg_id; +} + +long get_data_type(int handle, int msg_type) +{ + long data_type = 0L; + int msg_uid = get_msg_uid(); + + data_type = ((static_cast(handle)) << 22); + data_type |= ((static_cast(msg_type)) << 16); + data_type |= msg_uid; + data_type = (data_type < 0) ? labs(data_type) : data_type; /* message type must be > 0, refer to description of struct msgbuf */ + + RM_INFO("data_type : (%ld), msg_uid : (%d), handle : (%d), msg_type : (%d)", data_type, msg_uid, handle, msg_type); + + return data_type; +} + +unsigned long long get_uptime(void) +{ + struct timespec t; + clock_gettime(CLOCK_MONOTONIC, &t); + return t.tv_sec; +} + +void rm_construct_request_msg(rm_msg_request *request, int msg_type, int handle) +{ + if (!request) { + RM_ERR("request is NULL"); + return; + } + + request->data_type = (msg_type == RM_REQUEST_REGISTER) ? (RM_REQUEST_DATA_TYPE_REGISTER | getpid()) : get_data_type(handle, msg_type); + request->type = msg_type; + request->handle = handle; + request->pid = getpid(); + request->time = get_uptime(); + + RM_INFO("DONE"); +} diff --git a/src/rm_shm_api.cpp b/src/rm_shm_api.cpp new file mode 100644 index 0000000..8686641 --- /dev/null +++ b/src/rm_shm_api.cpp @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2024 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 + +// LCOV_EXCL_START + +int rm_shm_get_app_id(const int handle, char** app_id) +{ + if (handle < 0 || !app_id) { + RM_ERR("invalid param (%d)", handle); + return RM_ERROR; + } + + *app_id = RMShmCache::GetInstance()->GetAppId(handle); + return (*app_id == nullptr) ? RM_ERROR : RM_OK; +} + +int rm_shm_find_scaler_hw_id(const int zone_id, int *hw_id) +{ + if (zone_id < 0 || !hw_id) { + RM_ERR("invalid param (%d)", zone_id); + return RM_ERROR; + } + + return RMShmCache::GetInstance()->FindScalerHWID(zone_id, hw_id); +} + +int rm_shm_find_device_id(const int virtual_id, int *device_id) +{ + if (!device_id) { + RM_ERR("invalid param (%d)", virtual_id); + return RM_ERROR; + } + + return RMShmCache::GetInstance()->FindScalerDeviceID(virtual_id, device_id); +} + +int rm_shm_find_players_using_audio_main_out(rm_resource_list_h *list) +{ + if (!list) { + RM_ERR("invalid param"); + return RM_ERROR; + } + + return RMShmCache::GetInstance()->FindPlayersUsingAudioMainOut(list); +} + +int rm_shm_get_active_audio_out(const int handle, int *audio_out) +{ + if (handle < 0 || !audio_out) { + RM_ERR("invalid param (%d)", handle); + return RM_ERROR; + } + + return RMShmCache::GetInstance()->GetActiveAudioOut(handle, audio_out); +} + +int rm_shm_active_player(const int handle, bool *result) +{ + if (handle < 0 || !result) { + RM_ERR("invalid param (%d)", handle); + return false; + } + + return RMShmCache::GetInstance()->ActivePlayer(handle, result); +} + +// LCOV_EXCL_STOP diff --git a/ut/CMakeLists.txt b/ut/CMakeLists.txt new file mode 100644 index 0000000..c4e2cd9 --- /dev/null +++ b/ut/CMakeLists.txt @@ -0,0 +1,44 @@ +INCLUDE(FindPkgConfig) +pkg_check_modules(PKGS REQUIRED + resource-information + dlog + glib-2.0 + gtest + gmock +) + +FOREACH(inc ${PKGS_INCLUDE_DIRS}) + INCLUDE_DIRECTORIES(${inc}) +ENDFOREACH(inc) + +FOREACH (flag ${PKGS_CXXFLAGS}) + SET(EXTRA_CXXFLAGS "${EXTRA_CXXFLAGS} ${flag}") +ENDFOREACH(flag) + +IF(NOT DEFINED CHIP_NAME) + SET(CHIP_NAME CHIP_PONTUSM) +ENDIF(NOT DEFINED CHIP_NAME) + +SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${EXTRA_CXXFLAGS}") + +SET(INCLUDE_DIR_TO_TEST ${CMAKE_CURRENT_SOURCE_DIR}/../include ${CMAKE_CURRENT_SOURCE_DIR}/testcase) + +SET(SRC_TESTCASE + ${CMAKE_CURRENT_SOURCE_DIR}/testcase/common.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/testcase/TCPlayer.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/testcase/TCResource.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/testcase/TCCallbackListener.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/testcase/ut_main.cpp +) + +ADD_EXECUTABLE(${RSCMGRPKGNAME} ${SRC_TESTCASE}) + +INCLUDE_DIRECTORIES(${INCLUDE_DIR_GTEST} ${INCLUDE_DIR_TO_TEST}) +#FIND_PACKAGE(Threads REQUIRED) + +MESSAGE("PKGS_LDFLAGS : "${PKGS_LDFLAGS}) +TARGET_LINK_LIBRARIES(${RSCMGRPKGNAME} ${CMAKE_THREAD_LIBS_INIT} ${PKGS_LDFLAGS} ${PROJECT_NAME} -lpthread) + +MESSAGE("INSTALL DIR :" ${BINDIR}) + +INSTALL(TARGETS ${RSCMGRPKGNAME} DESTINATION ${BINDIR}) diff --git a/ut/TCList.dat.in b/ut/TCList.dat.in new file mode 100644 index 0000000..f90bfd5 --- /dev/null +++ b/ut/TCList.dat.in @@ -0,0 +1 @@ +rscmgr_hawkp_atsc.xml diff --git a/ut/testcase/TCCallbackListener.cpp b/ut/testcase/TCCallbackListener.cpp new file mode 100644 index 0000000..713b85a --- /dev/null +++ b/ut/testcase/TCCallbackListener.cpp @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2024 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 + +void TCCallbackListener::ScalerStateChangeCb(rm_resource_list_h scalers, void *data) +{ + TCCallbackListener *listener = (TCCallbackListener*) data; + assert(listener); + + listener->RemoveAllScalers(); + listener->IncreaseNotificationNum(); + + int n_allocated_scalers = rm_resource_list_get_count(scalers); + RM_TEST_MSG("n_allocated_scalers(%d)", n_allocated_scalers); + if (n_allocated_scalers == 0) + return; + + rm_resource_h scaler = rm_resource_list_get_first(scalers); + while (scaler) { + RM_TEST_MSG("scaler(%d:%d)", rm_scaler_get_virtual_id(scaler), rm_scaler_get_source_id(scaler)); + listener->AddScaler(rm_scaler_get_virtual_id(scaler), rm_scaler_get_source_id(scaler)); + scaler = rm_resource_list_get_next(scalers); + } +} + +TCCallbackListener::TCCallbackListener() +{ + m_n_notification = 0; +} + +TCCallbackListener::~TCCallbackListener() +{ + UnregisterScalerStateChangeCb(); +} + +void TCCallbackListener::AddScaler(int vid, int src_id) +{ + m_scalers.insert(std::pair(vid, src_id)); +} + +bool TCCallbackListener::IsIncluded(int vid, int src_id) +{ + auto it = m_scalers.find(vid); + if (it == m_scalers.end()) + return false; + + return (it->second == src_id) ? true:false; +} + +int TCCallbackListener::RegisterScalerStateChangeCb(void) +{ + return rm_subscribe_scaler_state_change(TCCallbackListener::ScalerStateChangeCb, this); +} + +int TCCallbackListener::UnregisterScalerStateChangeCb(void) +{ + return rm_unsubscribe_scaler_state_change(TCCallbackListener::ScalerStateChangeCb); +} diff --git a/ut/testcase/TCCallbackListener.h b/ut/testcase/TCCallbackListener.h new file mode 100644 index 0000000..b1c1ce5 --- /dev/null +++ b/ut/testcase/TCCallbackListener.h @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2024 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 __TC_CALLBACK_LISTENER_H__ +#define __TC_CALLBACK_LISTENER_H__ + +#include +#include + +class TCCallbackListener +{ +public: + TCCallbackListener(); + ~TCCallbackListener(); + + static void ScalerStateChangeCb(rm_resource_list_h scalers, void *data); + + int RegisterScalerStateChangeCb(void); + int UnregisterScalerStateChangeCb(void); + void RemoveAllScalers(void) { m_scalers.clear(); } + void AddScaler(int vid, int src_id); + bool IsIncluded(int vid, int src_id); + int GetNotificationNum(void) { return m_n_notification; } + void ResetNotificationNum(void) { m_n_notification = 0; } + void IncreaseNotificationNum(void) { m_n_notification++; } + +private: + std::map m_scalers; + int m_n_notification; +}; + +#endif //__TC_CALLBACK_LISTENER_H__ \ No newline at end of file diff --git a/ut/testcase/TCPlayer.cpp b/ut/testcase/TCPlayer.cpp new file mode 100644 index 0000000..8408b30 --- /dev/null +++ b/ut/testcase/TCPlayer.cpp @@ -0,0 +1,316 @@ +/* + * Copyright (c) 2024 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 "gtest/gtest.h" +#include +#include +#include +#include +#include +#include "TCResource.h" +#include "TCPlayer.h" + +TCPlayer::TCPlayer() +{ + m_handle = 0; + m_allocated_rsc_index = 0; + m_rsc_index = 0; + m_query_index = 0; + m_n_conflict = 0; + m_n_conflicted_rsc = 0; +} + +TCPlayer::~TCPlayer() +{ + Unregister(); +} + +rm_cb_result TCPlayer::ConflictCb(int handle, rm_callback_type event, rm_device_request_s *info, void *data) +{ + if (!data) + return RM_CB_RESULT_ERROR; + + TCPlayer *player = (TCPlayer*) data; + player->IncreaseConflictNum(); + player->SetConflictedResourcesNum(info->request_num); + + for (int j = 0; j < info->request_num; j++) { + player->AddConflictedResource(j+1, info->device_id[j]); + } + + EXPECT_EQ(RM_OK, rm_deallocate_resources(handle, info)); + return RM_CB_RESULT_OK; +} + +int TCPlayer::Register(void) +{ + if (m_handle != 0) + return RM_ERROR; + + return rm_register(TCPlayer::ConflictCb, this, &m_handle, NULL); +} + +int TCPlayer::Unregister(void) +{ + int result = RM_ERROR;; + + RemoveResources(); + RemoveQueries(); + m_allocated_resources.clear(); + + result = rm_unregister(m_handle); + m_handle = 0; + + return result; +} + +int TCPlayer::SetPriority(int priority) +{ + return rm_set_priority(m_handle, priority); +} + +int TCPlayer::SetAppId(std::string app_id) +{ + return rm_set_app_id(m_handle, (char*) app_id.c_str()); +} + +int TCPlayer::AddResource(int category_id, int state) +{ + TCResource *rsc = new TCResource(category_id, 0, state); + m_rsc_index++; + m_requested_resources.insert(std::pair(m_rsc_index, rsc)); + return 0; +} + +int TCPlayer::AddResource(int category_id, int category_option, int state) +{ + TCResource *rsc = new TCResource(category_id, category_option, state); + m_rsc_index++; + m_requested_resources.insert(std::pair(m_rsc_index, rsc)); + return 0; +} + +int TCPlayer::AddQuery(int category_id, int category_option, int state) +{ + TCResource *rsc = new TCResource(category_id, category_option, state); + m_query_index++; + m_queries.insert(std::pair(m_query_index, rsc)); + return 0; +} + +void TCPlayer::RemoveResources(void) +{ + TCResource *rsc = nullptr; + + for (auto &it : m_requested_resources) { + rsc = it.second; + if (rsc) + delete rsc; + } + m_requested_resources.clear(); +} + +int TCPlayer::GetAudioCategory(std::string codec_name, int mixing_mode) +{ + ri_audio_category_option_request_s audio_option; + memset(&audio_option, 0, sizeof(ri_audio_category_option_request_s)); + + audio_option.codec_name = codec_name.c_str(); + audio_option.mixing_mode = (ri_audio_mixing_mode) mixing_mode; + + return ri_get_capable_audio_category_id(&audio_option); +} + +int TCPlayer::GetCapableVideoCategory(std::string codec_name, int h_size, int v_size, int color_depth, int sampling_format, int framerate) +{ + ri_video_category_option_request_s opt; + memset(&opt, 0, sizeof(ri_video_category_option_request_s)); + + opt.codec_name = strndup(codec_name.c_str(), codec_name.length()); + opt.color_depth = color_depth; + opt.framerate = framerate; + opt.h_size = h_size; + opt.v_size = v_size; + opt.sampling_format = sampling_format; + + int result = ri_get_capable_video_category_id(&opt); + + free((void*) opt.codec_name); + return result; +} + +int TCPlayer::GetCapableImageCategory(std::string codec_name, int w_size, int h_size) +{ + char *codec = strndup(codec_name.c_str(), codec_name.length()); + int result = ri_get_image_category_id(codec, w_size, h_size); + free(codec); + return result; +} + +int TCPlayer::GetCapableNDecoderCategory(std::string codec_name, int h_size, int v_size, int color_depth, int sampling_format, int framerate) +{ + ri_video_category_option_request_s opt; + memset(&opt, 0, sizeof(ri_video_category_option_request_s)); + + opt.codec_name = strndup(codec_name.c_str(), codec_name.length()); + opt.color_depth = color_depth; + opt.framerate = framerate; + opt.h_size = h_size; + opt.v_size = v_size; + opt.sampling_format = sampling_format; + + return ri_get_n_decoder_category_id(&opt); +} + +int TCPlayer::Query(int query_type, int *ans) +{ + rm_category_request_s req; + memset(&req, 0, sizeof(rm_category_request_s)); + + int i = 0; + int result = RM_ERROR; + int answer; + + req.request_num = m_queries.size(); + + for (auto &it : m_queries) { + TCResource *rsc = it.second; + req.category_id[i] = (rm_rsc_category_e) rsc->GetCategoryId(); + req.category_option[i] = rsc->GetCategoryOption(); + req.state[i] = (rm_requests_resource_state_e) rsc->GetState(); + i++; + } + + result = rm_query(m_handle, (rm_query_type_e) query_type, &req, &answer); + *ans = answer; + + return result; +} + +void TCPlayer::RemoveQueries(void) +{ + TCResource *rsc = nullptr; + + for (auto &it : m_queries) { + rsc = it.second; + if (rsc) + delete rsc; + } + m_queries.clear(); +} + +void TCPlayer::AddAllocatedResource(int device_id) +{ + m_allocated_resources.insert(std::pair(++m_allocated_rsc_index, device_id)); +} + +int TCPlayer::GetAllocatedResourceId(int index) +{ + auto it = m_allocated_resources.find(index); + + return (it == m_allocated_resources.end()) ? -1 : it->second; +} + +int TCPlayer::AllocateResources(void) +{ + if (m_requested_resources.size() == 0) + return RM_ERROR; + + int i = 0; + int result = RM_ERROR; + + rm_category_request_s req; + memset(&req, 0, sizeof(rm_category_request_s)); + + req.request_num = m_requested_resources.size(); + + for (auto &it : m_requested_resources) { + TCResource *rsc = it.second; + req.category_id[i] = (rm_rsc_category_e) rsc->GetCategoryId(); + req.category_option[i] = rsc->GetCategoryOption(); + req.state[i] = (rm_requests_resource_state_e) rsc->GetState(); + i++; + } + + rm_device_return_s allocated; + memset(&allocated, 0, sizeof(allocated)); + + result = rm_allocate_resources(m_handle, &req, &allocated); + + if (result == RM_OK) { + for (int j = 0; j < allocated.allocated_num; j++) + AddAllocatedResource(allocated.device_id[j]); + } + + return result; +} + +int TCPlayer::ReleaseResources(void) +{ + if (m_allocated_resources.size() <= 0) + return RM_ERROR; + + int i = 0; + rm_device_request_s req; + memset(&req, 0, sizeof(req)); + + req.request_num = m_allocated_resources.size(); + + for (auto &it : m_allocated_resources) { + req.device_id[i] = it.second; + i++; + } + + m_allocated_resources.clear(); + + return rm_deallocate_resources(m_handle, &req); +} + +int TCPlayer::ReleaseResource(int index) +{ + if (m_allocated_resources.size() <= 0) + return RM_ERROR; + + auto it = m_allocated_resources.find(index); + int device_id = (it == m_allocated_resources.end()) ? -1 : it->second; + + rm_device_request_s req; + memset(&req, 0, sizeof(req)); + + req.request_num = 1; + req.device_id[0] = device_id; + + m_allocated_resources.erase(index); + + return rm_deallocate_resources(m_handle, &req); +} + +int TCPlayer::GetActiveAudioOut(void) +{ + return rm_get_active_audio_out(m_handle); +} + +int TCPlayer::GetConflictedResourceId(int index) +{ + auto it = m_conflicted_resources.find(index); + + return (it == m_conflicted_resources.end()) ? -1 : it->second; +} + +void TCPlayer::AddConflictedResource(int index, int device_id) +{ + m_conflicted_resources.insert(std::pair(index, device_id)); +} diff --git a/ut/testcase/TCPlayer.h b/ut/testcase/TCPlayer.h new file mode 100644 index 0000000..3910ed1 --- /dev/null +++ b/ut/testcase/TCPlayer.h @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2024 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 __TC_PLAYER_H__ +#define __TC_PLAYER_H__ + +#include +#include +#include + +class TCResource; +class TCPlayer +{ +public: + TCPlayer(); + TCPlayer(std::string app_id) { m_app_id = app_id; } + ~TCPlayer(); + + static rm_cb_result ConflictCb(int handle, rm_callback_type event, rm_device_request_s *info, void *data); + int Register(void); + int Unregister(void); + + int SetPriority(int priority); + int SetAppId(std::string app_id); + void SetCustomHandle(int handle) { m_handle = handle;} + + int AddResource(int category_id, int state); + int AddResource(int category_id, int category_option, int state); + void RemoveResources(void); + int GetAudioCategory(std::string codec_name, int mixing_mode); + int GetCapableVideoCategory(std::string codec_name, int h_size, int v_size, int color_depth, int sampling_format, int framerate); + int GetCapableNDecoderCategory(std::string codec_name, int h_size, int v_size, int color_depth, int sampling_format, int framerate); + int GetCapableImageCategory(std::string codec_name, int h_size, int v_size); + + int AddQuery(int category_id, int category_option, int state); + void RemoveQueries(void); + int Query(int query_type, int *ans); + + void AddAllocatedResource(int device_id); + int AllocateResources(void); + int ReleaseResources(void); + int ReleaseResource(int index); + int GetAllocatedResourceId(int index); + int GetAllocatedResourcesNum(void) { return m_allocated_resources.size(); } + + void IncreaseConflictNum(void) { m_n_conflict++; } + int GetConflictNum(void) { return m_n_conflict; } + void SetConflictedResourcesNum(int n) { m_n_conflicted_rsc = n; } + int GetConflictedResourcesNum(void) { return m_n_conflicted_rsc; } + int GetConflictedResourceId(int index); + void AddConflictedResource(int index, int device_id); + int GetActiveAudioOut(void); + +private: + std::map m_allocated_resources; + std::map m_conflicted_resources; + std::map m_requested_resources; + std::map m_queries; + + std::string m_app_id; + int m_handle; + int m_rsc_index; + int m_query_index; + int m_allocated_rsc_index; + int m_n_conflict; + int m_n_conflicted_rsc; +}; + +#endif //__TC_PLAYER_H__ diff --git a/ut/testcase/TCResource.cpp b/ut/testcase/TCResource.cpp new file mode 100644 index 0000000..c149966 --- /dev/null +++ b/ut/testcase/TCResource.cpp @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2024 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 "TCResource.h" + +TCResource::TCResource(int category_id, int category_option, int state) +{ + m_category_id = category_id; + m_category_option = category_option; + m_state = state; +} + +TCResource::~TCResource() +{ +} diff --git a/ut/testcase/TCResource.h b/ut/testcase/TCResource.h new file mode 100644 index 0000000..545b5af --- /dev/null +++ b/ut/testcase/TCResource.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2024 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 __TC_RESOURCE_H__ +#define __TC_RESOURCE_H__ + +class TCResource +{ +public: + TCResource(int category_id, int category_option, int state); + ~TCResource(); + + int GetCategoryId(void) {return m_category_id;} + int GetCategoryOption(void) {return m_category_option;} + int GetState(void) {return m_state;} + +private: + int m_category_id; + int m_category_option; + int m_state; +}; + +#endif //__TC_RESOURCE_H__ \ No newline at end of file diff --git a/ut/testcase/common.cpp b/ut/testcase/common.cpp new file mode 100644 index 0000000..eaa331b --- /dev/null +++ b/ut/testcase/common.cpp @@ -0,0 +1,294 @@ +/* + * Copyright (c) 2020 Samsung Electronics Co., Ltd All Rights Reserved + * For conditions of distribution and use, see the accompanying LICENSE.Samsung file . + */ + +#include +#include +#include +#include +#include "gtest/gtest.h" +#include +#include + +bool read_rm_index(const char *filename, int *data) +{ + FILE *fp = NULL; + char str[10] = {0,}; + size_t str_size; + + if (!data) { + RM_TEST_MSG("invalid input : null data"); + return false; + } + + fp = fopen(filename, "rb"); + + if (!fp) { + RM_TEST_MSG("failed to open (%s) - errno(%d)", filename, errno); + return false; + } + + str_size = fread(str, sizeof(char), sizeof(str)-1, fp); + + str[str_size] = '\0'; + + if (str_size == 0) { + fclose(fp); + return false; + } + + *data = atoi(str); + + fclose(fp); + fp = NULL; + + return true; +} + +bool is_8k_model(void) +{ + return false; +} + +static int conflicted; +static int conflicted_cmp; +static int num_of_dealloc_rsc; + +rm_cb_result rm_cb_counting_conflicted(int handle, rm_callback_type event, rm_device_request_s *info, void *data) +{ + ++conflicted; + num_of_dealloc_rsc = info->request_num; + + EXPECT_EQ(RM_OK, rm_deallocate_resources(handle, info)); + return RM_CB_RESULT_OK; +} + +rm_cb_result rm_cb_counting_conflicted_cmp(int handle, rm_callback_type event, rm_device_request_s *info, void *data) +{ + ++conflicted_cmp; + + EXPECT_EQ(RM_OK, rm_deallocate_resources(handle, info)); + return RM_CB_RESULT_OK; +} + +rm_cb_result rm_cb_set_conflict_flag(int handle, rm_callback_type event, rm_device_request_s *info, void *data) +{ + conflicted = 1; + num_of_dealloc_rsc = info->request_num; + + EXPECT_EQ(RM_OK, rm_deallocate_resources(handle, info)); + + return RM_CB_RESULT_OK; +} + +rm_cb_result rm_cb_for_conditional_check(int handle, rm_callback_type event, rm_device_request_s *info, void *data) +{ + rm_deallocate_resources(handle, info); + return RM_CB_RESULT_OK; +} + +int rm_tc_get_conflict_num(void) +{ + return conflicted; +} + +void rm_tc_reset_conflict_num(void) +{ + conflicted = 0; +} + +int rm_tc_get_conflict_num_cmp(void) +{ + return conflicted_cmp; +} + +void rm_tc_reset_conflict_num_cmp(void) +{ + conflicted_cmp = 0; +} + +int rm_tc_get_conflicted_resources_num(void) +{ + return num_of_dealloc_rsc; +} + +void rm_tc_reset_conflicted_resources_num(void) +{ + num_of_dealloc_rsc = 0; +} + +void rm_tc_clear_audio_decoders(void) +{ + RM_TEST_MSG("clear_audio_decoders..."); + + int handle1 = 0; + if (rm_register(rm_cb_counting_conflicted, NULL, &handle1, NULL) != RM_OK) { + RM_TEST_MSG("failed to register"); + return; + } + + rm_category_request_s request; + memset(&request, 0, sizeof(rm_category_request_s)); + + request.request_num = 2; + request.category_id[0] = RM_CATEGORY_AUDIO_DECODER; + request.category_option[0] = 0; + request.state[0] = RM_STATE_EXCLUSIVE; + request.category_id[1] = RM_CATEGORY_AUDIO_DECODER_SUB; + request.category_option[1] = 0; + request.state[1] = RM_STATE_EXCLUSIVE; + + rm_device_return_s allocated; + memset(&allocated, 0, sizeof(rm_device_return_s)); + + if (rm_allocate_resources(handle1, &request, &allocated) != RM_OK) + RM_TEST_MSG("failed to clear audio decoders"); + + if (rm_unregister(handle1) != RM_OK) + RM_TEST_MSG("failed to unregister"); + + RM_TEST_MSG("clear_audio_decoders done..."); +} + +void rm_tc_clear_video_decoders(void) +{ + RM_TEST_MSG("clear_video_decoders..."); + + int handle1 = 0; + if (rm_register(rm_cb_counting_conflicted, NULL, &handle1, NULL) != RM_OK) { + RM_TEST_MSG("failed to register"); + return; + } + + rm_category_request_s request; + memset(&request, 0, sizeof(rm_category_request_s)); + + request.request_num = 1; + request.category_id[0] = RM_CATEGORY_VIDEO_DECODER; + request.category_option[0] = RM_CATEGORY_VIDEO_DECODER_MPEG4_FHD_8BIT_60P; + request.state[0] = RM_STATE_EXCLUSIVE; + + rm_device_return_s allocated; + memset(&allocated, 0, sizeof(rm_device_return_s)); + + if (rm_allocate_resources(handle1, &request, &allocated) != RM_OK) + RM_TEST_MSG("failed to clear video decoders"); + + memset(&request, 0, sizeof(rm_category_request_s)); + + request.request_num = 1; + request.category_id[0] = RM_CATEGORY_VIDEO_DECODER; + request.category_option[0] = RM_CATEGORY_VIDEO_DECODER_H264_UHD_8BIT_60P; + request.state[0] = RM_STATE_EXCLUSIVE; + + memset(&allocated, 0, sizeof(rm_device_return_s)); + + if (rm_allocate_resources(handle1, &request, &allocated) != RM_OK) + RM_TEST_MSG("failed to clear video decoders"); + + if (rm_unregister(handle1) != RM_OK) + RM_TEST_MSG("failed to unregister"); + + RM_TEST_MSG("clear_video_decoders done..."); +} + +void rm_tc_template_exceptional_test_case(int vdec1, int vdec2) +{ + //consumer#1 + int handle1 = 0; + EXPECT_EQ(RM_OK, rm_register(rm_cb_set_conflict_flag, NULL, &handle1, NULL)); + + //alloc + rm_category_request_s *request = (rm_category_request_s*) malloc (sizeof(rm_category_request_s)); + memset((void*)request, 0, sizeof(rm_category_request_s)); + + request->request_num = 1; + request->category_id[0] = RM_CATEGORY_VIDEO_DECODER; + request->category_option[0] = vdec1 | RM_DEVICE_OPT_MAIN; + request->state[0] = RM_STATE_EXCLUSIVE; + + rm_device_return_s *allocated = (rm_device_return_s*) malloc (sizeof(rm_device_return_s)); + memset((void*)allocated, 0, sizeof(rm_device_return_s)); + + EXPECT_EQ(RM_OK, rm_allocate_resources(handle1, request, allocated)); + + //consumer#2 + int handle2 = 0; + EXPECT_EQ(RM_OK, rm_register(rm_cb_set_conflict_flag, NULL, &handle2, NULL)); + + //alloc + rm_category_request_s *request2 = (rm_category_request_s*) malloc (sizeof(rm_category_request_s)); + memset((void*)request2, 0, sizeof(rm_category_request_s)); + + request2->request_num = 1; + request2->category_id[0] = RM_CATEGORY_VIDEO_DECODER; + request2->category_option[0] = vdec2; + request2->state[0] = RM_STATE_EXCLUSIVE; + + rm_device_return_s *allocated2 = (rm_device_return_s*) malloc (sizeof(rm_device_return_s)); + memset((void*)allocated2, 0, sizeof(rm_device_return_s)); + + EXPECT_EQ(RM_OK, rm_allocate_resources(handle2, request2, allocated2)); + + //unregister + EXPECT_EQ(RM_OK, rm_unregister(handle1)); + EXPECT_EQ(RM_OK, rm_unregister(handle2)); + + sleep(RM_TEST_SLEEP_TIME); + +} + +bool is_support_4k(void) +{ +#ifdef RM_TC_SUPPORT_4K + return true; +#else + return false; +#endif //RM_TC_SUPPORT_4K +} + +bool is_support_8k(void) +{ +#ifdef RM_TC_SUPPORT_8K + return true; +#else + return false; +#endif //RM_TC_SUPPORT_8K +} + +bool is_support_av1_120p(void) +{ +#ifdef RM_TC_SUPPORT_AV1_120P + return true; +#else + return false; +#endif //RM_TC_SUPPORT_AV1_120P +} + +bool use_unified_jpeg_decoder(void) +{ +#ifdef RM_TC_USE_UNIFIED_JPEG_DEC + return true; +#else + return false; +#endif// RM_TC_USE_UNIFIED_JPEG_DEC +} + +bool is_oscars_unified_jpeg_decoder(void) +{ +#ifdef RM_TC_USE_UNIFIED_JPEG_DEC_OSCARS + return true; +#else + return false; +#endif +} + +bool is_support_audio_dual_decoding(void) +{ +#ifdef RM_TC_SUPPORT_AUDIO_DUAL_DECODING + return true; +#else + return false; +#endif //RM_TC_SUPPORT_AUDIO_DUAL_DECODING +} diff --git a/ut/testcase/ut_common.h b/ut/testcase/ut_common.h new file mode 100644 index 0000000..d56023c --- /dev/null +++ b/ut/testcase/ut_common.h @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2024 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 __UT_COMMON_H__ +#define __UT_COMMON_H__ + +#include +#include +#include + +#ifdef LOG_TAG +#undef LOG_TAG +#endif//LOG_TAG + +#define LOG_TAG "RSC_MGR_SERVER_TEST" +#define RM_TEST_SLEEP_TIME 1 +#define RM_TEST_MSG(fmt, arg...) \ + do { SLOGE(fmt, ##arg); } while (0) + +#define RM_TC_FREE(a) \ + if (a) \ + { \ + free(a); \ + a = NULL; \ + } + +bool is_8k_model(void); +bool read_rm_index(const char *filename, int *data); +bool is_support_4k(void); +bool is_support_8k(void); +bool is_support_av1_120p(void); +bool use_unified_jpeg_decoder(void); +bool is_support_audio_dual_decoding(void); +bool is_oscars_unified_jpeg_decoder(void); + +GMainContext *get_callback_thread_context(void); + +rm_cb_result rm_cb_counting_conflicted(int handle, rm_callback_type event, rm_device_request_s *info, void *data); +rm_cb_result rm_cb_counting_conflicted_cmp(int handle, rm_callback_type event, rm_device_request_s *info, void *data); +rm_cb_result rm_cb_set_conflict_flag(int handle, rm_callback_type event, rm_device_request_s *info, void *data); +rm_cb_result rm_cb_for_conditional_check(int handle, rm_callback_type event, rm_device_request_s *info, void *data); + +void rm_tc_template_exceptional_test_case(int vdec1, int vdec2); + +int rm_tc_get_conflict_num(void); +void rm_tc_reset_conflict_num(void); +int rm_tc_get_conflict_num_cmp(void); +void rm_tc_reset_conflict_num_cmp(void); +int rm_tc_get_conflicted_resources_num(void); +void rm_tc_reset_conflicted_resources_num(void); +void rm_tc_clear_audio_decoders(void); +void rm_tc_clear_video_decoders(void); +#endif //__UT_COMMON_H__ diff --git a/ut/testcase/ut_main.cpp b/ut/testcase/ut_main.cpp new file mode 100644 index 0000000..d8b7ad2 --- /dev/null +++ b/ut/testcase/ut_main.cpp @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2024 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 "gtest/gtest.h" + +#include + +static GMainLoop *g_main_loop; +static gpointer tc_run_loop(gpointer data) +{ + RM_TEST_MSG("Run callback thread"); + GMainLoop *main_loop = (GMainLoop*) data; + + if (main_loop != NULL) { + g_main_loop_run(main_loop); + } + + RM_TEST_MSG("callback thread terminated"); + return NULL; +} + +GMainContext *get_callback_thread_context(void) +{ + return g_main_loop_get_context(g_main_loop); +} + +GTEST_API_ int main(int argc, char **argv) +{ + RM_TEST_MSG("Running main() from ut_main.cpp\n"); + + //GMainContext *context = g_main_context_new(); + g_main_loop = g_main_loop_new(NULL, FALSE); + GThread *cb_thread = g_thread_new("rc_cb_thread", tc_run_loop, g_main_loop); + + if (cb_thread == NULL) { + g_main_loop_unref(g_main_loop); + RM_TEST_MSG("failed to create the callback thread"); + } + + // Here, your global initialization if necessary + + testing::InitGoogleTest(&argc, argv); + + return RUN_ALL_TESTS(); +} diff --git a/ut/testcase/ut_tc.cpp b/ut/testcase/ut_tc.cpp new file mode 100644 index 0000000..b894c25 --- /dev/null +++ b/ut/testcase/ut_tc.cpp @@ -0,0 +1,3019 @@ +/* + * Copyright (c) 2024 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 "gtest/gtest.h" +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +static int conflicted = 0; +static int conflicted4 = 0; + +static int num_of_dealloc_rsc = 0; +int category_call_num[50]; +int category_opt_call_num[5000]; + +//define for MSGQ TC +typedef struct { + int category_id; + int device_id; +} rms_conflicted_resource_info_s; + +typedef struct { + long data_type; + int type; + int result; + int resource_num; + int resource[10]; + int resource_state[10]; + int is_available; + int handle; + int error_type; +} rms_msg_response; + +rm_cb_result conflict_cb(int handle, rm_callback_type event, rm_device_request_s *info, void *data) +{ + conflicted = 1; + + RM_TEST_MSG("conflict_cb called"); + RM_TEST_MSG("conflicted resources..."); + + for (int i = 0; i < info->request_num; i++) { + RM_TEST_MSG("[%d] device id : %d", i+1, info->device_id[i]); + } + + EXPECT_EQ(RM_OK, rm_deallocate_resources(handle, info)); + return RM_CB_RESULT_OK; +} + +rm_cb_result conflict_cb2(int handle, rm_callback_type event, rm_device_request_s *info, void *data) +{ + conflicted = 1; + num_of_dealloc_rsc = info->request_num; + + EXPECT_EQ(RM_OK, rm_deallocate_resources(handle, info)); + + return RM_CB_RESULT_OK; +} + +static rm_cb_result conflict_cb3(int handle, rm_callback_type event, rm_device_request_s *info, void *data) +{ + ++conflicted; + num_of_dealloc_rsc = info->request_num; + + EXPECT_EQ(RM_OK, rm_deallocate_resources(handle, info)); + return RM_CB_RESULT_OK; +} + +rm_cb_result conflict_cb4(int handle, rm_callback_type event, rm_device_request_s *info, void *data) +{ + conflicted4 = 1; + + RM_TEST_MSG("conflict_cb4 called"); + RM_TEST_MSG("conflicted resources..."); + + for (int i = 0; i < info->request_num; i++) { + RM_TEST_MSG("[%d] device id : %d", i+1, info->device_id[i]); + } + + EXPECT_EQ(RM_OK, rm_deallocate_resources(handle, info)); + return RM_CB_RESULT_OK; +} + +int flag1=0; +int flag2=0; +int endflag=0; +pthread_t t1,t2,t3; +rm_cb_result cb1(int handle, rm_callback_type event, rm_device_request_s *info, void *data) +{ + flag2=1; + usleep(1000*2000); + EXPECT_EQ(RM_OK, rm_deallocate_resources(handle, info)); + return RM_CB_RESULT_OK; +} +rm_cb_result cb2(int handle, rm_callback_type event, rm_device_request_s *info, void *data) +{ + EXPECT_EQ(RM_OK, rm_deallocate_resources(handle, info)); + return RM_CB_RESULT_OK; +} + +void *thread_main1(void*) +{ + int handle=0; + EXPECT_EQ(RM_OK,rm_register(cb1, NULL, &handle, NULL)); + + //alloc + rm_category_request_s *request = (rm_category_request_s*) malloc (sizeof(rm_category_request_s)); + memset((void*)request, 0, sizeof(rm_category_request_s)); + + request->request_num = 1; + request->category_id[0] = RM_CATEGORY_EXT_VIDEO_SRC; + request->category_option[0] = 0; + request->state[0] = RM_STATE_EXCLUSIVE; + + rm_device_return_s *allocated = (rm_device_return_s*) malloc (sizeof(rm_device_return_s)); + memset((void*)allocated, 0, sizeof(rm_device_return_s)); + + EXPECT_EQ(RM_OK,rm_allocate_resources(handle, request, allocated)); + flag1=1; + while (true) { + if (endflag) { + EXPECT_EQ(RM_OK, rm_unregister(handle)); + pthread_exit(0); + } + usleep(1000); + } +} +void *thread_main2(void*) +{ + int handle=0; + while (true) { + if (flag1) { + EXPECT_EQ(RM_OK,rm_register(cb2, NULL, &handle, NULL)); + //alloc + rm_category_request_s *request = (rm_category_request_s*) malloc (sizeof(rm_category_request_s)); + memset((void*)request, 0, sizeof(rm_category_request_s)); + + request->request_num = 1; + request->category_id[0] = RM_CATEGORY_EXT_VIDEO_SRC; + request->category_option[0] = 0; + request->state[0] = RM_STATE_EXCLUSIVE; + + rm_device_return_s *allocated = (rm_device_return_s*) malloc (sizeof(rm_device_return_s)); + memset((void*)allocated, 0, sizeof(rm_device_return_s)); + EXPECT_EQ(RM_OK,rm_allocate_resources(handle, request, allocated)); + flag1=0; + + } + if (endflag) { + EXPECT_EQ(RM_OK, rm_unregister(handle)); + pthread_exit(0); + } + usleep(1000*1000); + } +} + +void *thread_main3(void*) +{ + int handle=0; + while (true) { + if (flag2) { + EXPECT_EQ(RM_OK,rm_register(cb2, NULL, &handle, NULL)); + + //alloc + rm_category_request_s *request = (rm_category_request_s*) malloc (sizeof(rm_category_request_s)); + memset((void*)request, 0, sizeof(rm_category_request_s)); + + request->request_num = 1; + request->category_id[0] = RM_CATEGORY_EXT_VIDEO_SRC; + request->category_option[0] = 0; + request->state[0] = RM_STATE_EXCLUSIVE; + + rm_device_return_s *allocated = (rm_device_return_s*) malloc (sizeof(rm_device_return_s)); + memset((void*)allocated, 0, sizeof(rm_device_return_s)); + EXPECT_EQ(RM_OK,rm_allocate_resources(handle, request, allocated)); + EXPECT_EQ(RM_OK, rm_unregister(handle)); + endflag=1; + pthread_exit(0); + } + usleep(1000*1000); + } +} + +/* default scenario + * 1. register and get a handle + * 2. query + * 3. request to alloc + * 4. request to dealloc + * 5. unregister + */ + +TEST(ut_rm_api, rm_default) +{ + int handle = 0; + + //register + EXPECT_EQ(RM_OK, rm_register(conflict_cb, NULL, &handle, NULL)); + + //query + rm_category_request_s *request = (rm_category_request_s*) malloc (sizeof(rm_category_request_s)); + memset((void*)request, 0, sizeof(rm_category_request_s)); + + request->request_num = 1; + request->category_id[0] = RM_CATEGORY_EXT_VIDEO_SRC; + request->category_option[0] = 0; + request->state[0] = RM_STATE_EXCLUSIVE; + + int result = 0; + + EXPECT_EQ(RM_OK, rm_query(handle, RM_QUERY_ALLOCATION, request, &result)); + EXPECT_EQ(1, result); + + //alloc + rm_device_return_s *allocated = (rm_device_return_s*) malloc (sizeof(rm_device_return_s)); + memset((void*)allocated, 0, sizeof(rm_device_return_s)); + + EXPECT_EQ(RM_OK, rm_allocate_resources(handle, request, allocated)); + + EXPECT_EQ(RM_OK, rm_query(handle, RM_QUERY_ALLOCATION, request, &result)); + EXPECT_EQ(0, result); + + //dealloc + rm_device_request_s *dealloc_request = (rm_device_request_s*) malloc (sizeof(rm_device_request_s)); + memset((void*) dealloc_request, 0, sizeof(rm_device_request_s)); + + dealloc_request->request_num = 1; + dealloc_request->device_id[0] = (int)RM_DEVICE_EXT_VIDEO_SRC; + + EXPECT_EQ(RM_OK, rm_deallocate_resources(handle, dealloc_request)); + + EXPECT_EQ(RM_OK, rm_query(handle, RM_QUERY_ALLOCATION, request, &result)); + EXPECT_EQ(1, result); + + //unregister + EXPECT_EQ(RM_OK, rm_unregister(handle)); + sleep(RM_TEST_SLEEP_TIME); +} + +/* default scenario + * 1. register and get a handle + * 2. query + * 3. unregister + */ + +TEST(ut_rm_api, rm_query_terminate) +{ + int handle = 0; + + //register + EXPECT_EQ(RM_OK, rm_register(conflict_cb, NULL, &handle, NULL)); + + //query + rm_category_request_s *request = (rm_category_request_s*) malloc (sizeof(rm_category_request_s)); + memset((void*)request, 0, sizeof(rm_category_request_s)); + + request->request_num = 0; + request->category_id[0] = RM_CATEGORY_NONE; + request->category_option[0] = 0; + request->state[0] = RM_STATE_EXCLUSIVE; + + int result = 0; + + EXPECT_EQ(RM_OK, rm_query(handle, RM_QUERY_TERMINATE, request, &result)); + + // this process has not been killed by resource manager. so result should be 0. + EXPECT_EQ(0, result); + + //unregister + EXPECT_EQ(RM_OK, rm_unregister(handle)); + sleep(RM_TEST_SLEEP_TIME); + +} + +/* conflict scenario + * 1. [consumer#1] register and get a handle + * 2. [consumer#1] request to alloc + * 3. [consumer#2] register and get a handle + * 4. [consumer#2] request to alloc + * ----- resource conflict is occured!! ----- + * 5. [consumer#1] get cb message and dealloc + * 6. [consumer#2] alloc success + * 7. [consumer#2] dealoc + * 8. [consumer#1] unregister + * 9. [consumer#2] unregister + */ +TEST(ut_rm_api, rm_conflict) +{ + RM_TEST_MSG("rm_conflict start..."); + + TCPlayer *player = new TCPlayer(); + player->AddResource(RM_CATEGORY_EXT_VIDEO_SRC, RM_STATE_EXCLUSIVE); + + EXPECT_EQ(RM_OK, player->Register()); + EXPECT_EQ(RM_OK, player->AllocateResources()); + + TCPlayer *player2 = new TCPlayer(); + player2->AddResource(RM_CATEGORY_EXT_VIDEO_SRC, RM_STATE_EXCLUSIVE); + + EXPECT_EQ(RM_OK, player2->Register()); + EXPECT_EQ(RM_OK, player2->AllocateResources()); + EXPECT_EQ(RM_OK, player2->ReleaseResources()); + + EXPECT_EQ(RM_OK, player->Unregister()); + EXPECT_EQ(RM_OK, player2->Unregister()); + + delete player; + delete player2; + + RM_TEST_MSG("rm_conflict end..."); + sleep(RM_TEST_SLEEP_TIME); +} + + +/* set priority scenario + * 1. register and get a handle + * 2. set priority + * 3. unregister + */ +TEST(ut_rm_api, rm_priority) +{ + int priority = 50; + + TCPlayer *player = new TCPlayer(); + + EXPECT_EQ(RM_OK, player->Register()); + EXPECT_EQ(RM_OK, player->SetPriority(priority)); + EXPECT_EQ(RM_OK, player->Unregister()); + + delete player; + sleep(RM_TEST_SLEEP_TIME); +} + +TEST(ut_rm_api, rm_unregister_invalid_handle01) +{ + //insert invalid rm handle + EXPECT_EQ(RM_ERROR, rm_unregister(99)); + sleep(RM_TEST_SLEEP_TIME); + +} + +TEST(ut_rm_api, rm_set_app_id) +{ + TCPlayer *player = new TCPlayer(); + + EXPECT_EQ(RM_OK, player->Register()); + EXPECT_EQ(RM_OK, player->SetAppId("org.tizen.rm.test")); + EXPECT_EQ(RM_OK, player->Unregister()); + + delete player; + sleep(RM_TEST_SLEEP_TIME); +} + +TEST(ut_rm_api, rm_set_app_id_max) +{ + const char *app_id = "org.tizen.test1test2test3test4test5test6test7test8test9test10test11test12test13test14test15test16test17test18test19test20test21test22test23test24test25test26test27test28test29test30test31test32test33test34test35test1test2test3test4test5test6test7test8test9test10test11test12test13test14test15test16test17test18test19test20test21test22test23test24test25test26test27test28test29test30test31test32test33test34test35test1test2test3test4test5test6test7test8test9test10test11test12test13test14test15test16test17test18test19test20test21test22test23test24test25test26test27test28test29test30test31test32test33test34test35test1test2test3test4test5test6test7test8test9test10test11test12test13test14test15test16test17test18test19test20test21test22test23test24test25test26test27test28test29test30test31test32test33test34test35test1test2test3test4test5test6test7test8test9test10test11test12test13test14test15test16test17test18test19test20test21test22test23test24test25test26test27test28test29test30test31test32test33test34test35test1test2test3test4test5test6test7test8test9test10test11test12test13test14test15test16test17test18test19test20test21test22test23test24test25test26test27test28test29test30test31test32test33test34test35"; + + RM_TEST_MSG("rm_set_app_id_max start"); + RM_TEST_MSG("app id len (%d)", strlen(app_id)); + + TCPlayer *player = new TCPlayer(); + + EXPECT_EQ(RM_OK, player->Register()); + EXPECT_NE(RM_OK, player->SetAppId(app_id)); + EXPECT_EQ(RM_OK, player->Unregister()); + + delete player; + + RM_TEST_MSG("rm_set_app_id_max end"); + sleep(RM_TEST_SLEEP_TIME); +} + +TEST(ut_rm_api, rm_set_app_id_with_invalid_handle) +{ + TCPlayer *player = new TCPlayer(); + + player->SetCustomHandle(1); + EXPECT_EQ(RM_ERROR, player->SetAppId("org.tizen.rm.test")); + + delete player; + sleep(RM_TEST_SLEEP_TIME); +} + +TEST(ut_rm_api, rm_set_app_id_with_invalid_id_null) +{ + int handle = 0; + + EXPECT_EQ(RM_OK, rm_register(conflict_cb, NULL, &handle, NULL)); + + EXPECT_EQ(RM_ERROR, rm_set_app_id(handle, NULL)); + + EXPECT_EQ(RM_OK, rm_unregister(handle)); + sleep(RM_TEST_SLEEP_TIME); + +} + +TEST(ut_rm_api, rm_set_app_id_with_invalid_id_long) +{ + int handle = 0; + char app_id[2048] = {0,}; + snprintf(app_id, 2048, "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s", "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"); + + EXPECT_EQ(RM_OK, rm_register(conflict_cb, NULL, &handle, NULL)); + + EXPECT_EQ(RM_ERROR, rm_set_app_id(handle, app_id)); + + EXPECT_EQ(RM_OK, rm_unregister(handle)); + sleep(RM_TEST_SLEEP_TIME); + +} + +TEST(ut_rm_api, ri_get_video_category_id_fhd) +{ + //MPEG1 + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_MPEG1_FHD_8BIT_30P, ri_get_video_category_id("MPEG1", 8, 1920, 30, RI_SAMPLING_FORMAT_420)); + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_MPEG1_FHD_8BIT_60P, ri_get_video_category_id("MPEG1", 8, 1920, 60, RI_SAMPLING_FORMAT_420)); + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_NOT_SUPPORTED, ri_get_video_category_id("MPEG1", 10, 1920, 60, RI_SAMPLING_FORMAT_420)); + + //MPEG2 + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_MPEG2_FHD_8BIT_30P, ri_get_video_category_id("MPEG2", 8, 1920, 30, RI_SAMPLING_FORMAT_420)); + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_MPEG2_FHD_8BIT_60P, ri_get_video_category_id("MPEG2", 8, 1920, 60, RI_SAMPLING_FORMAT_420)); + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_NOT_SUPPORTED, ri_get_video_category_id("MPEG2", 10, 1920, 60, RI_SAMPLING_FORMAT_420)); + + //MPEG4 + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_MPEG4_FHD_8BIT_30P, ri_get_video_category_id("MPEG4", 8, 1920, 30, RI_SAMPLING_FORMAT_420)); + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_MPEG4_FHD_8BIT_60P, ri_get_video_category_id("MPEG4", 8, 1920, 60, RI_SAMPLING_FORMAT_420)); + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_NOT_SUPPORTED, ri_get_video_category_id("MPEG4", 10, 1920, 60, RI_SAMPLING_FORMAT_420)); + + //H263 + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_H263_FHD_8BIT_30P, ri_get_video_category_id("H263", 8, 1920, 30, RI_SAMPLING_FORMAT_420)); + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_H263_FHD_8BIT_60P, ri_get_video_category_id("H263", 8, 1920, 60, RI_SAMPLING_FORMAT_420)); + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_NOT_SUPPORTED, ri_get_video_category_id("H263", 10, 1920, 60, RI_SAMPLING_FORMAT_420)); + + //H264 + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_H264_FHD_8BIT_30P, ri_get_video_category_id("H264", 8, 1920, 30, RI_SAMPLING_FORMAT_420)); + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_H264_FHD_8BIT_60P, ri_get_video_category_id("H264", 8, 1920, 60, RI_SAMPLING_FORMAT_420)); + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_NOT_SUPPORTED, ri_get_video_category_id("H264", 10, 1920, 60, RI_SAMPLING_FORMAT_420)); + + //HEVC + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_HEVC_FHD_8BIT_30P, ri_get_video_category_id("HEVC", 8, 1920, 30, RI_SAMPLING_FORMAT_420)); + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_HEVC_FHD_8BIT_60P, ri_get_video_category_id("HEVC", 8, 1920, 60, RI_SAMPLING_FORMAT_420)); + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_HEVC_FHD_10BIT_420_60P, ri_get_video_category_id("HEVC", 10, 1920, 60, RI_SAMPLING_FORMAT_420)); + + //VP8 + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_VP8_FHD_8BIT_30P, ri_get_video_category_id("VP8", 8, 1920, 30, RI_SAMPLING_FORMAT_420)); + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_VP8_FHD_8BIT_60P, ri_get_video_category_id("VP8", 8, 1920, 60, RI_SAMPLING_FORMAT_420)); + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_NOT_SUPPORTED, ri_get_video_category_id("VP8", 10, 1920, 60, RI_SAMPLING_FORMAT_420)); + + //VP9 + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_VP9_FHD_8BIT_30P, ri_get_video_category_id("VP9", 8, 1920, 30, RI_SAMPLING_FORMAT_420)); + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_VP9_FHD_8BIT_60P, ri_get_video_category_id("VP9", 8, 1920, 60, RI_SAMPLING_FORMAT_420)); + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_VP9_FHD_10BIT_60P, ri_get_video_category_id("VP9", 10, 1920, 60, RI_SAMPLING_FORMAT_420)); + + //RV + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_RV_FHD_8BIT_30P, ri_get_video_category_id("RV", 8, 1920, 30, RI_SAMPLING_FORMAT_420)); + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_RV_FHD_8BIT_60P, ri_get_video_category_id("RV", 8, 1920, 60, RI_SAMPLING_FORMAT_420)); + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_NOT_SUPPORTED, ri_get_video_category_id("RV", 10, 1920, 60, RI_SAMPLING_FORMAT_420)); + + //WMV9 + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_WMV9_FHD_8BIT_30P, ri_get_video_category_id("WMV", 8, 1920, 30, RI_SAMPLING_FORMAT_420)); + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_WMV9_FHD_8BIT_60P, ri_get_video_category_id("WMV", 8, 1920, 60, RI_SAMPLING_FORMAT_420)); + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_NOT_SUPPORTED, ri_get_video_category_id("WMV", 10, 1920, 60, RI_SAMPLING_FORMAT_420)); + + //AVS + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_AVS_FHD_8BIT_30P, ri_get_video_category_id("AVS", 8, 1920, 30, RI_SAMPLING_FORMAT_420)); + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_AVS_FHD_8BIT_60P, ri_get_video_category_id("AVS", 8, 1920, 60, RI_SAMPLING_FORMAT_420)); + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_NOT_SUPPORTED, ri_get_video_category_id("AVS", 10, 1920, 60, RI_SAMPLING_FORMAT_420)); + + //AVS+ + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_AVS_PLUS_FHD_8BIT_30P, ri_get_video_category_id("AVS+", 8, 1920, 30, RI_SAMPLING_FORMAT_420)); + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_AVS_PLUS_FHD_8BIT_60P, ri_get_video_category_id("AVS+", 8, 1920, 60, RI_SAMPLING_FORMAT_420)); + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_NOT_SUPPORTED, ri_get_video_category_id("AVS+", 10, 1920, 60, RI_SAMPLING_FORMAT_420)); + + //H264_MVC + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_H264_FHD_8BIT_30P, ri_get_video_category_id("H264_MVC", 8, 1920, 30, RI_SAMPLING_FORMAT_420)); + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_H264_FHD_8BIT_60P, ri_get_video_category_id("H264_MVC", 8, 1920, 60, RI_SAMPLING_FORMAT_420)); + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_NOT_SUPPORTED, ri_get_video_category_id("H264_MVC", 10, 1920, 60, RI_SAMPLING_FORMAT_420)); +} + +TEST(ut_rm_api, ri_get_jpeg_category_id) +{ + EXPECT_EQ(RI_CATEGORY_MJPEG_DECODER_FHD, ri_get_jpeg_category_id("MJPEG", 1920)); + EXPECT_EQ(RI_CATEGORY_MJPEG_DECODER_NOT_SUPPORTED, ri_get_jpeg_category_id("JPEG", 1920)); + sleep(RM_TEST_SLEEP_TIME); +} + + +TEST(ut_rm_api, ri_get_sub_jpeg_category_id) +{ + EXPECT_EQ(RI_CATEGORY_JPEG_DECODER_FHD, ri_get_sub_jpeg_category_id("JPEG", 1920, 1080)); + + int expected_result = RI_CATEGORY_JPEG_DECODER_UHD; + EXPECT_EQ(expected_result, ri_get_sub_jpeg_category_id("JPEG", 3840, 1920)); +} + +//assign available video decoder +TEST(ut_rm_api, rm_allocate_available_vdec) +{ + + RM_TEST_MSG("rm_allocate_available_vdec start..."); + + TCPlayer *player = new TCPlayer(); + player->AddResource(RM_CATEGORY_VIDEO_DECODER, RM_DEVICE_OPT_MAIN, RM_STATE_EXCLUSIVE); + + EXPECT_EQ(RM_OK, player->Register()); + EXPECT_EQ(RM_OK, player->AllocateResources()); + EXPECT_EQ((int) RI_DEVICE_VIDEO_DECODER_MAIN, player->GetAllocatedResourceId(1)); + + TCPlayer *player2 = new TCPlayer(); + player2->AddResource(RM_CATEGORY_VIDEO_DECODER, 0, RM_STATE_EXCLUSIVE); + + EXPECT_EQ(RM_OK, player2->Register()); + EXPECT_EQ(RM_OK, player2->AllocateResources()); + EXPECT_EQ((int) RI_DEVICE_VIDEO_DECODER_SUB, player2->GetAllocatedResourceId(1)); + + EXPECT_EQ(RM_OK, player->ReleaseResources()); + EXPECT_EQ(RM_OK, player2->ReleaseResources()); + + EXPECT_EQ(RM_OK, player->Unregister()); + EXPECT_EQ(RM_OK, player2->Unregister()); + + delete player; + delete player2; + + sleep(RM_TEST_SLEEP_TIME); + RM_TEST_MSG("rm_allocate_available_vdec end..."); +} + +//assign main video decoder +TEST(ut_rm_api, rm_allocate_main_vdec) +{ + TCPlayer *player = new TCPlayer(); + player->AddResource(RM_CATEGORY_VIDEO_DECODER, RM_DEVICE_OPT_MAIN, RM_STATE_EXCLUSIVE); + + EXPECT_EQ(RM_OK, player->Register()); + EXPECT_EQ(RM_OK, player->AllocateResources()); + EXPECT_EQ((int) RI_DEVICE_VIDEO_DECODER_MAIN, player->GetAllocatedResourceId(1)); + + TCPlayer *player2 = new TCPlayer(); + player2->AddResource(RM_CATEGORY_VIDEO_DECODER, RM_DEVICE_OPT_MAIN, RM_STATE_EXCLUSIVE); + + EXPECT_EQ(RM_OK, player2->Register()); + EXPECT_EQ(RM_OK, player2->AllocateResources()); + EXPECT_EQ((int) RI_DEVICE_VIDEO_DECODER_MAIN, player2->GetAllocatedResourceId(1)); + + EXPECT_EQ(RM_OK, player2->ReleaseResources()); + + EXPECT_EQ(RM_OK, player->Unregister()); + EXPECT_EQ(RM_OK, player2->Unregister()); + + delete player; + delete player2; + + sleep(RM_TEST_SLEEP_TIME); +} + +#define RMS_HANDLE_MIN 101 +#define RMS_HANDLE_NUM_MAX 100 + +TEST(ut_rm_api, rm_handle_assignment) +{ + const int rms_handle_max_num = 100; + int handle[rms_handle_max_num]; + + for (int i = 0; i < rms_handle_max_num; i++) + handle[i] = -1; + + // STEP#1 allocate 50 handles + for (int i = 0; i < 50; i++) { + EXPECT_EQ(RM_OK, rm_register(conflict_cb, NULL, &handle[i], NULL)); + EXPECT_LE(RMS_HANDLE_MIN, handle[i]); + EXPECT_GE(RMS_HANDLE_MIN+RMS_HANDLE_NUM_MAX, handle[i]); + } + + // STEP#2 release 5 handles + for (int i = 0; i < 5; i++) { + EXPECT_EQ(RM_OK, rm_unregister(handle[i])); + handle[i] = -1; + } + + // STEP#3 allocate 50 handles + for (int i = 50; i < 100; i++) { + EXPECT_EQ(RM_OK, rm_register(conflict_cb, NULL, &handle[i], NULL)); + EXPECT_LE(RMS_HANDLE_MIN, handle[i]); + EXPECT_GE(RMS_HANDLE_MIN+RMS_HANDLE_NUM_MAX, handle[i]); + } + + // STEP#4 release 95 handles + for (int i = 5; i < 100; i++) { + EXPECT_EQ(RM_OK, rm_unregister(handle[i])); + handle[i] = -1; + } + + // STEP#5 allocate 50 handles + for (int i = 0; i < 50; i++) { + EXPECT_EQ(RM_OK, rm_register(conflict_cb, NULL, &handle[i], NULL)); + EXPECT_LE(RMS_HANDLE_MIN, handle[i]); + EXPECT_GE(RMS_HANDLE_MIN+RMS_HANDLE_NUM_MAX, handle[i]); + } + + // STEP#6 release 15 handles + for (int i = 0; i < 15; i++) { + EXPECT_EQ(RM_OK, rm_unregister(handle[i])); + handle[i] = -1; + } + + // STEP#7 allocate 50 handles + for (int i = 50; i < 100; i++) { + EXPECT_EQ(RM_OK, rm_register(conflict_cb, NULL, &handle[i], NULL)); + EXPECT_LE(RMS_HANDLE_MIN, handle[i]); + EXPECT_GE(RMS_HANDLE_MIN+RMS_HANDLE_NUM_MAX, handle[i]); + } + + // STEP#8 free all allocated handles + for (int i = 0; i < 100; i++) { + if (handle[i] != -1) { + EXPECT_EQ(RM_OK, rm_unregister(handle[i])); + handle[i] = -1; + } + } + + sleep(RM_TEST_SLEEP_TIME); + +} + +/* scenario + * 1. allocate mfd0 + * 2. allocate mfd1 + * 3. request allocate dvde0 (vp9 uhd 60p) + * 4. mfd0 is deallocated + * 5. allocated dvde0 + */ +TEST(ut_rm_api, rm_conflict02) +{ + RM_TEST_MSG("rm_conflict02 start..."); + + TCPlayer *player = new TCPlayer(); + player->AddResource(RM_CATEGORY_VIDEO_DECODER, RM_CATEGORY_VIDEO_DECODER_MPEG4_FHD_8BIT_30P, RM_STATE_EXCLUSIVE); + + EXPECT_EQ(RM_OK, player->Register()); + EXPECT_EQ(RM_OK, player->AllocateResources()); + + TCPlayer *player2 = new TCPlayer(); + player2->AddResource(RM_CATEGORY_VIDEO_DECODER, RM_CATEGORY_VIDEO_DECODER_MPEG4_FHD_8BIT_30P, RM_STATE_EXCLUSIVE); + + EXPECT_EQ(RM_OK, player2->Register()); + EXPECT_EQ(RM_OK, player2->AllocateResources()); + + TCPlayer *player3 = new TCPlayer(); + player3->AddResource(RM_CATEGORY_VIDEO_DECODER, RM_CATEGORY_VIDEO_DECODER_VP9_UHD_8BIT_60P, RM_STATE_EXCLUSIVE); + + EXPECT_EQ(RM_OK, player3->Register()); + if (is_support_4k()) { + EXPECT_EQ(RM_OK, player3->AllocateResources()); + } else { + EXPECT_NE(RM_OK, player3->AllocateResources()); + } + + EXPECT_EQ(RM_OK, player->Unregister()); + EXPECT_EQ(RM_OK, player2->Unregister()); + EXPECT_EQ(RM_OK, player3->Unregister()); + + delete player; + delete player2; + delete player3; + + sleep(RM_TEST_SLEEP_TIME); + RM_TEST_MSG("rm_conflict02 end..."); +} + +/* issue : category does not return retirable consumer if free state resource exists + *** scenario + * 1. allocate demux & scaler : by tv main stream(handle1) + * 2. allocate sub scaler : by other app(handle2) + * 3. request allocate demux & sub scaler : by tv pip stream(handle3) + * 4. only sub scaler is deallocated + * 5. successfully allcated demux & sub scaler without demux conflict + */ +TEST(ut_rm_api, rm_conflict03) +{ + TCPlayer *player = new TCPlayer(); + player->AddResource(RM_CATEGORY_DEMUX, RM_STATE_EXCLUSIVE); + player->AddResource(RM_CATEGORY_SCALER, RM_STATE_EXCLUSIVE); + + EXPECT_EQ(RM_OK, player->Register()); + EXPECT_EQ(RM_OK, player->AllocateResources()); + + TCPlayer *player2 = new TCPlayer(); + player2->AddResource(RM_CATEGORY_SCALER_SUB, RM_STATE_EXCLUSIVE); + + EXPECT_EQ(RM_OK, player2->Register()); + EXPECT_EQ(RM_OK, player2->AllocateResources()); + + TCPlayer *player3 = new TCPlayer(); + player3->AddResource(RM_CATEGORY_DEMUX, RM_STATE_EXCLUSIVE); + player3->AddResource(RM_CATEGORY_SCALER_SUB, RM_STATE_EXCLUSIVE); + + EXPECT_EQ(RM_OK, player3->Register()); + EXPECT_EQ(RM_OK, player3->AllocateResources()); + + EXPECT_EQ(RM_OK, player->Unregister()); + EXPECT_EQ(RM_OK, player2->Unregister()); + EXPECT_EQ(RM_OK, player3->Unregister()); + + delete player; + delete player2; + delete player3; + + sleep(RM_TEST_SLEEP_TIME); + +} +/* issue : same consumer allocates same resources including video decoder(main only opt) + *** scenario + * 1. allocate mainout and a.dec + * 2. allocate v.dec(main only) and scaler + * 3. allocate mainout and a.dec again => expected result : alloc failure + * 4. allocate v.dec(main only) and scaler again => expected result : alloc failure + */ +TEST(ut_rm_api, rm_conflict04) +{ + RM_TEST_MSG("rm_conflict04 start..."); + + TCPlayer *player = new TCPlayer(); + player->AddResource(RM_CATEGORY_AUDIO_MAIN_OUT, RM_STATE_EXCLUSIVE); + player->AddResource(RM_CATEGORY_AUDIO_DECODER, RM_STATE_EXCLUSIVE); + + EXPECT_EQ(RM_OK, player->Register()); + EXPECT_EQ(RM_OK, player->AllocateResources()); + + TCPlayer *player2 = new TCPlayer(); + player2->AddResource(RM_CATEGORY_VIDEO_DECODER, RM_DEVICE_OPT_MAIN, RM_STATE_EXCLUSIVE); + player2->AddResource(RM_CATEGORY_SCALER, RM_STATE_EXCLUSIVE); + + EXPECT_EQ(RM_OK, player2->Register()); + EXPECT_EQ(RM_OK, player2->AllocateResources()); + + EXPECT_EQ(RM_ERROR, player->AllocateResources()); + EXPECT_EQ(RM_ERROR, player2->AllocateResources()); + + EXPECT_EQ(RM_OK, player->Unregister()); + EXPECT_EQ(RM_OK, player2->Unregister()); + + delete player; + delete player2; + + sleep(RM_TEST_SLEEP_TIME); + RM_TEST_MSG("rm_conflict04 end..."); + +} + +TEST(ut_rm_api, rm_conflict05) +{ + TCPlayer *player = new TCPlayer(); + player->AddResource(RM_CATEGORY_VIDEO_DECODER, RM_CATEGORY_VIDEO_DECODER_HEVC_UHD_8BIT_30P, RM_STATE_EXCLUSIVE); + player->AddResource(RM_CATEGORY_DEMUX, RM_STATE_EXCLUSIVE); + + EXPECT_EQ(RM_OK, player->Register()); + + if (is_support_4k()) + EXPECT_EQ(RM_OK, player->AllocateResources()); + else + EXPECT_NE(RM_OK, player->AllocateResources()); + + TCPlayer *player2 = new TCPlayer(); + player2->AddResource(RM_CATEGORY_VIDEO_DECODER, RM_DEVICE_OPT_MAIN, RM_STATE_EXCLUSIVE); + + EXPECT_EQ(RM_OK, player2->Register()); + EXPECT_EQ(RM_OK, player2->AllocateResources()); + + EXPECT_EQ(RM_OK, player->Unregister()); + EXPECT_EQ(RM_OK, player2->Unregister()); + + delete player; + delete player2; + + sleep(RM_TEST_SLEEP_TIME); +} + +/* issue : video decoder(mem cluster) conflict + */ +TEST(ut_rm_api, rm_conflict09) +{ + RM_TEST_MSG("rm_conflict09 start..."); + + TCPlayer *player = new TCPlayer(); + player->AddResource(RM_CATEGORY_VIDEO_DECODER, RM_DEVICE_OPT_MAIN, RM_STATE_EXCLUSIVE); + player->AddResource(RM_CATEGORY_DEMUX, RM_STATE_EXCLUSIVE); + + EXPECT_EQ(RM_OK, player->Register()); + EXPECT_EQ(RM_OK, player->AllocateResources()); + + TCPlayer *player2 = new TCPlayer(); + player2->AddResource(RM_CATEGORY_VIDEO_DECODER, RM_DEVICE_OPT_MAIN, RM_STATE_EXCLUSIVE); + + EXPECT_EQ(RM_OK, player2->Register()); + EXPECT_EQ(RM_OK, player2->AllocateResources()); + + EXPECT_EQ(1, player->GetConflictNum()); + EXPECT_EQ(1, player->GetConflictedResourcesNum()); + + EXPECT_EQ(RM_OK, player->Unregister()); + EXPECT_EQ(RM_OK, player2->Unregister()); + + delete player; + delete player2; + + sleep(RM_TEST_SLEEP_TIME); + + RM_TEST_MSG("rm_conflict09 end..."); +} + +/* issue : video decoder(mem cluster) conflict + */ +TEST(ut_rm_api, rm_conflict10) +{ + RM_TEST_MSG("rm_conflict10 start..."); + + TCPlayer *player = new TCPlayer(); + player->AddResource(RM_CATEGORY_VIDEO_DECODER, RM_DEVICE_OPT_MAIN, RM_STATE_EXCLUSIVE); + player->AddResource(RM_CATEGORY_DEMUX, RM_STATE_EXCLUSIVE); + + EXPECT_EQ(RM_OK, player->Register()); + EXPECT_EQ(RM_OK, player->AllocateResources()); + + TCPlayer *player2 = new TCPlayer(); + player2->AddResource(RM_CATEGORY_VIDEO_DECODER, RM_DEVICE_OPT_MAIN, RM_STATE_EXCLUSIVE); + player2->AddResource(RM_CATEGORY_DEMUX, RM_STATE_EXCLUSIVE); + + EXPECT_EQ(RM_OK, player2->Register()); + EXPECT_EQ(RM_OK, player2->AllocateResources()); + + EXPECT_EQ(1, player->GetConflictNum()); + EXPECT_EQ(1, player->GetConflictedResourcesNum()); + + EXPECT_EQ(RM_OK, player->Unregister()); + EXPECT_EQ(RM_OK, player2->Unregister()); + + delete player; + delete player2; + + sleep(RM_TEST_SLEEP_TIME); + RM_TEST_MSG("rm_conflict10 end..."); +} + + + +/* issue : no conflict + */ +TEST(ut_rm_api, rm_conflict12) +{ + RM_TEST_MSG("rm_conflict12 start..."); + + TCPlayer *player = new TCPlayer(); + player->AddResource(RM_CATEGORY_VIDEO_DECODER, RM_DEVICE_OPT_MAIN, RM_STATE_EXCLUSIVE); + player->AddResource(RM_CATEGORY_DEMUX, RM_STATE_EXCLUSIVE); + + EXPECT_EQ(RM_OK, player->Register()); + EXPECT_EQ(RM_OK, player->AllocateResources()); + + TCPlayer *player2 = new TCPlayer(); + player2->AddResource(RM_CATEGORY_VIDEO_DECODER, RM_STATE_EXCLUSIVE); + + EXPECT_EQ(RM_OK, player2->Register()); + EXPECT_EQ(RM_OK, player2->AllocateResources()); + + EXPECT_EQ(0, player->GetConflictNum()); + EXPECT_EQ(0, player->GetConflictedResourcesNum()); + + EXPECT_EQ(RM_OK, player->Unregister()); + EXPECT_EQ(RM_OK, player2->Unregister()); + + delete player; + delete player2; + + sleep(RM_TEST_SLEEP_TIME); + + RM_TEST_MSG("rm_conflict12 end..."); +} + +/* issue : no conflict + */ +TEST(ut_rm_api, rm_conflict13) +{ + TCPlayer *player = new TCPlayer(); + player->AddResource(RM_CATEGORY_VIDEO_DECODER, RM_DEVICE_OPT_MAIN, RM_STATE_EXCLUSIVE); + player->AddResource(RM_CATEGORY_DEMUX, RM_STATE_EXCLUSIVE); + + EXPECT_EQ(RM_OK, player->Register()); + EXPECT_EQ(RM_OK, player->AllocateResources()); + + TCPlayer *player2 = new TCPlayer(); + player2->AddResource(RM_CATEGORY_VIDEO_DECODER, RM_STATE_EXCLUSIVE); + player2->AddResource(RM_CATEGORY_DEMUX, RM_STATE_EXCLUSIVE); + + EXPECT_EQ(RM_OK, player2->Register()); + EXPECT_EQ(RM_OK, player2->AllocateResources()); + + EXPECT_EQ(0, player->GetConflictNum()); + EXPECT_EQ(0, player->GetConflictedResourcesNum()); + + EXPECT_EQ(RM_OK, player->Unregister()); + EXPECT_EQ(RM_OK, player2->Unregister()); + + delete player; + delete player2; + + sleep(RM_TEST_SLEEP_TIME); +} + +/* issue : no conflict + */ +TEST(ut_rm_api, rm_conflict15) +{ + TCPlayer *player = new TCPlayer(); + player->AddResource(RM_CATEGORY_VIDEO_DECODER, RM_STATE_EXCLUSIVE); + player->AddResource(RM_CATEGORY_DEMUX, RM_STATE_EXCLUSIVE); + + EXPECT_EQ(RM_OK, player->Register()); + EXPECT_EQ(RM_OK, player->AllocateResources()); + + TCPlayer *player2 = new TCPlayer(); + player2->AddResource(RM_CATEGORY_VIDEO_DECODER, RM_STATE_EXCLUSIVE); + + EXPECT_EQ(RM_OK, player2->Register()); + EXPECT_EQ(RM_OK, player2->AllocateResources()); + + EXPECT_EQ(0, player->GetConflictNum()); + EXPECT_EQ(0, player->GetConflictedResourcesNum()); + + EXPECT_EQ(RM_OK, player->Unregister()); + EXPECT_EQ(RM_OK, player2->Unregister()); + + delete player; + delete player2; + + sleep(RM_TEST_SLEEP_TIME); +} + +/* issue : 2 video decoders are allocated + */ +TEST(ut_rm_api, rm_alloc_2_vdecs1) +{ + TCPlayer *player = new TCPlayer(); + player->AddResource(RM_CATEGORY_VIDEO_DECODER, RM_STATE_EXCLUSIVE); + player->AddResource(RM_CATEGORY_VIDEO_DECODER, RM_STATE_EXCLUSIVE); + + EXPECT_EQ(RM_OK, player->Register()); + EXPECT_EQ(RM_OK, player->AllocateResources()); + EXPECT_EQ(RM_OK, player->Unregister()); + + delete player; + sleep(RM_TEST_SLEEP_TIME); +} + +/* issue : 2 video decoders are allocated + */ +TEST(ut_rm_api, rm_alloc_2_vdecs2) +{ + TCPlayer *player = new TCPlayer(); + player->AddResource(RM_CATEGORY_VIDEO_DECODER, RM_STATE_EXCLUSIVE); + + EXPECT_EQ(RM_OK, player->Register()); + EXPECT_EQ(RM_OK, player->AllocateResources()); + + player->RemoveResources(); + player->AddResource(RM_CATEGORY_VIDEO_DECODER, RM_STATE_EXCLUSIVE); + EXPECT_EQ(RM_OK, player->AllocateResources()); + + EXPECT_EQ(RM_OK, player->Unregister()); + + delete player; + sleep(RM_TEST_SLEEP_TIME); +} + +//t1 and t2 cause resource conflict and t3 request while force allocation(send internal msgq) +TEST(ut_rm_api, rm_conflict_internal_msg_q) +{ + pthread_create(&t1,NULL,&thread_main1,(void*)1); + pthread_create(&t2,NULL,&thread_main2,(void*)2); + pthread_create(&t3,NULL,&thread_main3,(void*)3); + int status=0; + pthread_join(t1,(void**)&status); + pthread_join(t2,(void**)&status); + pthread_join(t3,(void**)&status); + + sleep(RM_TEST_SLEEP_TIME); +} + +TEST(ut_rm_api, rm_test_request_of_invisible_app) +{ + TCPlayer *player = new TCPlayer(); + player->AddResource(RM_CATEGORY_EXT_VIDEO_SRC, RM_STATE_EXCLUSIVE); + + EXPECT_EQ(RM_OK, player->Register()); + EXPECT_EQ(RM_OK, player->AllocateResources()); + + TCPlayer *player2 = new TCPlayer(); + player2->AddResource(RM_CATEGORY_EXT_VIDEO_SRC, RM_STATE_EXCLUSIVE); + + EXPECT_EQ(RM_OK, player2->Register()); + EXPECT_EQ(RM_OK, player2->SetAppId("Invalid_AppID")); + EXPECT_NE(RM_OK, player2->AllocateResources()); + + EXPECT_EQ(0, player->GetConflictNum()); + + EXPECT_EQ(RM_OK, player->Unregister()); + EXPECT_EQ(RM_OK, player2->Unregister()); + + delete player; + delete player2; + + sleep(RM_TEST_SLEEP_TIME); +} + + +TEST(ut_rm_api, rm_test_alloc_sub_vdec) +{ + TCPlayer *player = new TCPlayer(); + player->AddResource(RM_CATEGORY_VIDEO_DECODER_SUB, (RM_CATEGORY_VIDEO_DECODER_MPEG2_FHD_8BIT_30P | RM_DEVICE_OPT_SUB), RM_STATE_EXCLUSIVE); + + EXPECT_EQ(RM_OK, player->Register()); + EXPECT_EQ(RM_OK, player->AllocateResources()); + EXPECT_EQ(1, player->GetAllocatedResourcesNum()); + EXPECT_EQ(RM_DEVICE_VIDEO_DECODER_SUB, player->GetAllocatedResourceId(1)); + + TCPlayer *player2 = new TCPlayer(); + player2->AddResource(RM_CATEGORY_VIDEO_DECODER_SUB, (RM_CATEGORY_VIDEO_DECODER_MPEG2_FHD_8BIT_30P | RM_DEVICE_OPT_SUB), RM_STATE_EXCLUSIVE); + + EXPECT_EQ(RM_OK, player2->Register()); + EXPECT_EQ(RM_OK, player2->AllocateResources()); + EXPECT_EQ(1, player2->GetAllocatedResourcesNum()); + EXPECT_EQ(RM_DEVICE_VIDEO_DECODER_SUB, player2->GetAllocatedResourceId(1)); + + EXPECT_EQ(1, player->GetConflictNum()); + + EXPECT_EQ(RM_OK, player->Unregister()); + EXPECT_EQ(RM_OK, player2->Unregister()); + + delete player; + delete player2; +} + +void template_exceptional_test_case(int vdec1, int vdec2) +{ + TCPlayer *player = new TCPlayer(); + player->AddResource(RM_CATEGORY_VIDEO_DECODER, (vdec1 | RM_DEVICE_OPT_MAIN), RM_STATE_EXCLUSIVE); + + EXPECT_EQ(RM_OK, player->Register()); + EXPECT_EQ(RM_OK, player->AllocateResources()); + + TCPlayer *player2 = new TCPlayer(); + player2->AddResource(RM_CATEGORY_VIDEO_DECODER, vdec2, RM_STATE_EXCLUSIVE); + + EXPECT_EQ(RM_OK, player2->Register()); + EXPECT_EQ(RM_OK, player2->AllocateResources()); + + EXPECT_EQ(RM_OK, player->Unregister()); + EXPECT_EQ(RM_OK, player2->Unregister()); + + delete player; + delete player2; + + sleep(RM_TEST_SLEEP_TIME); + +} + +static int local_handle = 0; + +rm_cb_result conflict_cb_test_async_unregister(int handle, rm_callback_type event, rm_device_request_s *info, void *data) +{ + EXPECT_EQ(RM_OK, rm_unregister(local_handle)); + usleep(2000*1000); + EXPECT_EQ(RM_OK, rm_deallocate_resources(handle, info)); + return RM_CB_RESULT_OK; +} + +TEST(ut_rm_api, rm_async_unregister) +{ + //consumer#local + EXPECT_EQ(RM_OK, rm_register(conflict_cb, NULL, &local_handle, NULL)); + + //alloc + rm_category_request_s *request = (rm_category_request_s*) malloc (sizeof(rm_category_request_s)); + memset((void*)request, 0, sizeof(rm_category_request_s)); + + request->request_num = 1; + request->category_id[0] = RM_CATEGORY_SCALER_SUB; + request->category_option[0] = 0; + request->state[0] = RM_STATE_EXCLUSIVE; + + rm_device_return_s *allocated = (rm_device_return_s*) malloc (sizeof(rm_device_return_s)); + memset((void*)allocated, 0, sizeof(rm_device_return_s)); + + EXPECT_EQ(RM_OK, rm_allocate_resources(local_handle, request, allocated)); + + //consumer#1 + int handle1 = 0; + EXPECT_EQ(RM_OK, rm_register(conflict_cb_test_async_unregister, NULL, &handle1, NULL)); + + //alloc + rm_category_request_s *request1 = (rm_category_request_s*) malloc (sizeof(rm_category_request_s)); + memset((void*)request1, 0, sizeof(rm_category_request_s)); + + request1->request_num = 1; + request1->category_id[0] = RM_CATEGORY_CAMERA; + request1->category_option[0] = 0; + request1->state[0] = RM_STATE_EXCLUSIVE; + + rm_device_return_s *allocated1 = (rm_device_return_s*) malloc (sizeof(rm_device_return_s)); + memset((void*)allocated1, 0, sizeof(rm_device_return_s)); + + EXPECT_EQ(RM_OK, rm_allocate_resources(handle1, request1, allocated1)); + + //consumer#2 + int handle2 = 0; + EXPECT_EQ(RM_OK, rm_register(conflict_cb, NULL, &handle2, NULL)); + + rm_device_return_s *allocated2 = (rm_device_return_s*) malloc (sizeof(rm_device_return_s)); + memset((void*)allocated2, 0, sizeof(rm_device_return_s)); + + EXPECT_EQ(RM_OK, rm_allocate_resources(handle2, request1, allocated2)); + rm_unregister(handle1); + rm_unregister(handle2); + + sleep(RM_TEST_SLEEP_TIME); +} + + + +TEST(ut_rm_api, vdapi_rm_allocate_invalid_resource_n) +{ + TCPlayer *player = new TCPlayer(); + player->AddResource(RM_CATEGORY_AUDIO_SPDIF_ES_OUTPUT, RM_STATE_EXCLUSIVE); + + EXPECT_EQ(RM_OK, player->Register()); + EXPECT_NE(RM_OK, player->AllocateResources()); + EXPECT_EQ(RM_OK, player->Unregister()); + + delete player; + sleep(RM_TEST_SLEEP_TIME); +} + +TEST(ut_rm_api, rm_allocate_with_low_priority) +{ + TCPlayer *player = new TCPlayer(); + player->AddResource(RM_CATEGORY_EXT_VIDEO_SRC, RM_STATE_EXCLUSIVE); + + EXPECT_EQ(RM_OK, player->Register()); + EXPECT_EQ(RM_OK, player->SetPriority(10000)); + EXPECT_EQ(RM_OK, player->AllocateResources()); + + TCPlayer *player2 = new TCPlayer(); + player2->AddResource(RM_CATEGORY_EXT_VIDEO_SRC, RM_STATE_EXCLUSIVE); + + EXPECT_EQ(RM_OK, player2->Register()); + EXPECT_EQ(RM_OK, player2->SetPriority(10)); + EXPECT_NE(RM_OK, player2->AllocateResources()); + + EXPECT_EQ(RM_OK, player->Unregister()); + EXPECT_EQ(RM_OK, player2->Unregister()); + + delete player; + delete player2; + + sleep(RM_TEST_SLEEP_TIME); +} + +TEST(ut_rm_api, rm_alloc_uhd_jpeg_conflict) +{ + if (ri_get_max_video_decoder_num() >=4 ) + return; + + if (is_oscars_unified_jpeg_decoder()) + return; + + if (!is_support_4k()) + return; + + RM_TEST_MSG("rm_alloc_uhd_jpeg_conflict start"); + + TCPlayer *player = new TCPlayer(); + player->AddResource(RM_CATEGORY_VIDEO_DECODER, (RM_CATEGORY_VIDEO_DECODER_HEVC_UHD_10BIT_420_30P | RM_DEVICE_OPT_MAIN), RM_STATE_EXCLUSIVE); + + EXPECT_EQ(RM_OK, player->Register()); + EXPECT_EQ(RM_OK, player->AllocateResources()); + + TCPlayer *player2 = new TCPlayer(); + player2->AddResource(RM_CATEGORY_JPEG_DECODER, RM_CATEGORY_JPEG_DECODER_UHD, RM_STATE_EXCLUSIVE); + + EXPECT_EQ(RM_OK, player2->Register()); + EXPECT_EQ(RM_OK, player2->AllocateResources()); + + EXPECT_EQ(1, player->GetConflictNum()); + EXPECT_EQ(1, player->GetConflictedResourcesNum()); + + EXPECT_EQ(RM_OK, player->Unregister()); + EXPECT_EQ(RM_OK, player2->Unregister()); + + delete player; + delete player2; + + RM_TEST_MSG("rm_alloc_uhd_jpeg_conflict end"); + sleep(RM_TEST_SLEEP_TIME); +} + +TEST(ut_rm_api, rm_test_mem_cluster_conflict_by_invisible_app_request) +{ + RM_TEST_MSG("rm_test_mem_cluster_conflict_by_invisible_app_request start..."); + + TCPlayer *player = new TCPlayer(); + player->AddResource(RM_CATEGORY_AUDIO_DECODER, RM_STATE_EXCLUSIVE); + + EXPECT_EQ(RM_OK, player->Register()); + EXPECT_EQ(RM_OK, player->AllocateResources()); + + TCPlayer *player2 = new TCPlayer(); + player2->AddResource(RM_CATEGORY_AUDIO_DECODER_PRIMARY, RM_STATE_EXCLUSIVE); + + EXPECT_EQ(RM_OK, player2->Register()); + EXPECT_EQ(RM_OK, player2->SetAppId("Invalid_AppID")); + EXPECT_NE(RM_OK, player2->AllocateResources()); + + EXPECT_EQ(0, player->GetConflictNum()); + + EXPECT_EQ(RM_OK, player->Unregister()); + EXPECT_EQ(RM_OK, player2->Unregister()); + + delete player; + delete player2; + + sleep(RM_TEST_SLEEP_TIME); + + RM_TEST_MSG("rm_test_mem_cluster_conflict_by_invisible_app_request end..."); +} + +TEST(ut_rm_api, rm_exlusive_conditional_2) +{ + int handle; + EXPECT_EQ(RM_OK, rm_register(rm_cb_for_conditional_check, NULL, &handle, NULL)); + + rm_category_request_s request; + rm_device_return_s allocated; + + memset((void*)&allocated, 0, sizeof(rm_device_return_s)); + memset((void*)&request, 0, sizeof(rm_category_request_s)); + + // Get 60p decoder to make other consumer release resources + request.request_num = 1; + request.category_id[0] = RM_CATEGORY_VIDEO_DECODER; + request.category_option[0] = ri_get_video_category_id("MPEG2", 8, 1920, 60, 0); + request.state[0] = RM_STATE_EXCLUSIVE; + + EXPECT_EQ(RM_OK, rm_allocate_resources(handle, &request, &allocated)); + + rm_device_request_s release_request; + + memset((void*)&release_request, 0, sizeof(rm_device_request_s)); + + release_request.request_num = 1; + release_request.device_id[0] = allocated.device_id[0]; + + EXPECT_EQ(RM_OK, rm_deallocate_resources(handle, &release_request)); + + memset((void*)&allocated, 0, sizeof(rm_device_return_s)); + memset((void*)&request, 0, sizeof(rm_category_request_s)); + + request.request_num = 1; + request.category_id[0] = RM_CATEGORY_VIDEO_DECODER; + request.category_option[0] = ri_get_video_category_id("MPEG2", 8, 1920, 30, 0); + request.state[0] = RM_STATE_EXCLUSIVE_CONDITIONAL; + + EXPECT_EQ(RM_OK, rm_allocate_resources(handle, &request, &allocated)); + + EXPECT_EQ(RM_OK, rm_unregister(handle)); + + sleep(RM_TEST_SLEEP_TIME); + +} + +TEST(ut_rm_api, rm_clear_msgq_on_allocate) +{ + int handle; + rm_register(conflict_cb, NULL, &handle, NULL); + int temphandle = handle; + rm_unregister(handle); + int message_queue_tx = msgget((key_t)8212, 0666| IPC_CREAT); + rms_msg_response response; + memset(&response, 0, sizeof(rms_msg_response)); + response.handle = temphandle; + response.data_type = temphandle; + response.type = 3; + response.result = 1; + + for (int i = 0; i < 13; i++) { + msgsnd(message_queue_tx, (void*) (&response), sizeof(rms_msg_response) - sizeof(long), 0) ; + usleep(10000); + } + + int prev_handle = -1; + + while (1) { + if (rm_register(conflict_cb, NULL, &handle, NULL) != RM_OK) { + RM_TEST_MSG("failed to get a new handle"); + break; + } + + if (prev_handle != -1) + rm_unregister(prev_handle); + + if (handle == temphandle) + break; + + prev_handle = handle; + } + + rm_category_request_s request; + memset(&request, 0, sizeof(rm_category_request_s)); + request.request_num = 1; + request.category_id[0] = RM_CATEGORY_CAMERA; + request.category_option[0] = 0; + request.state[0] = RM_STATE_EXCLUSIVE; + + rm_device_return_s allocated; + memset(&allocated, 0, sizeof(rm_device_return_s)); + EXPECT_EQ(RM_OK, rm_allocate_resources(handle,&request,&allocated)); + + rm_unregister(temphandle); + + sleep(RM_TEST_SLEEP_TIME); + +} + + +TEST(ut_rm_api, conflict_cb_should_not_be_called_on_same_consumer) +{ + int handle; + rm_device_return_s allocated; + rm_category_request_s request; + + conflicted = 0; + + RM_TEST_MSG("conflict_cb_should_not_be_called_on_same_consumer start"); + + memset((void*)&allocated, 0, sizeof(rm_device_return_s)); + memset((void*)&request, 0, sizeof(rm_category_request_s)); + + rm_register(conflict_cb, NULL, &handle, NULL); + + ri_video_category_option_request_s *opt = (ri_video_category_option_request_s*) malloc(sizeof(ri_video_category_option_request_s)); + opt->codec_name = "MPEG2"; + opt->color_depth = 8; + opt->framerate = 30; + opt->h_size = 1920; + opt->v_size = 1080; + opt->sampling_format = RI_SAMPLING_FORMAT_420; + + request.request_num = 1; + request.category_id[0] = RM_CATEGORY_VIDEO_DECODER; + request.category_option[0] = ri_get_capable_video_category_id(opt); + request.state[0] = RM_STATE_EXCLUSIVE; + + EXPECT_EQ(RM_OK, rm_allocate_resources(handle, &request, &allocated)); + EXPECT_EQ(RM_OK, rm_allocate_resources(handle, &request, &allocated)); + EXPECT_NE(RM_OK, rm_allocate_resources(handle, &request, &allocated)); + EXPECT_EQ(0, conflicted); + + free(opt); + + rm_unregister(handle); + + RM_TEST_MSG("conflict_cb_should_not_be_called_on_same_consumer done"); + + sleep(RM_TEST_SLEEP_TIME); +} + +TEST(ut_rm_api, should_be_able_to_take_mem_conflicted_resource_and_conflict_cb_should_not_be_called_on_same_consumer) +{ + int handle; + int handle2; + rm_device_return_s allocated; + rm_category_request_s request; + + conflicted = 0; + conflicted4 = 0; + + RM_TEST_MSG("should_be_able_to_take_mem_conflicted_resource_and_conflict_cb_should_not_be_called_on_same_consumer start"); + + memset((void*)&allocated, 0, sizeof(rm_device_return_s)); + memset((void*)&request, 0, sizeof(rm_category_request_s)); + + rm_register(conflict_cb4, NULL, &handle, NULL); + + RM_TEST_MSG("assigned handle : %d", handle); + + ri_video_category_option_request_s *opt = (ri_video_category_option_request_s*) malloc(sizeof(ri_video_category_option_request_s)); + opt->codec_name = "MPEG2"; + opt->color_depth = 8; + opt->framerate = 30; + opt->h_size = 1920; + opt->v_size = 1080; + opt->sampling_format = RI_SAMPLING_FORMAT_420; + + request.request_num = 1; + request.category_id[0] = RM_CATEGORY_VIDEO_DECODER; + request.category_option[0] = ri_get_capable_video_category_id(opt); + request.state[0] = RM_STATE_EXCLUSIVE; + + EXPECT_EQ(RM_OK, rm_allocate_resources(handle, &request, &allocated)); + + rm_register(conflict_cb, NULL, &handle2, NULL); + + RM_TEST_MSG("assigned handle2 : %d", handle2); + + opt->codec_name = "H264"; + opt->color_depth = 8; + opt->framerate = 30; + opt->h_size = 1920; + opt->v_size = 1080; + opt->sampling_format = RI_SAMPLING_FORMAT_420; + + request.request_num = 1; + request.category_id[0] = RM_CATEGORY_VIDEO_DECODER; + request.category_option[0] = ri_get_capable_video_category_id(opt); + request.state[0] = RM_STATE_EXCLUSIVE; + + EXPECT_EQ(RM_OK, rm_allocate_resources(handle2, &request, &allocated)); + EXPECT_EQ(RM_OK, rm_allocate_resources(handle2, &request, &allocated)); + EXPECT_EQ(0, conflicted); + EXPECT_EQ(1, conflicted4); + + free(opt); + + rm_unregister(handle); + rm_unregister(handle2); + + RM_TEST_MSG("should_be_able_to_take_mem_conflicted_resource_and_conflict_cb_should_not_be_called_on_same_consumer done"); + + sleep(RM_TEST_SLEEP_TIME); + + +} + +TEST(ut_rm_api, ri_get_jpeg_category_id_p) +{ + EXPECT_EQ(RI_CATEGORY_MJPEG_DECODER_FHD, ri_get_jpeg_category_id("MJPEG", 1920)); + EXPECT_EQ(RI_CATEGORY_MJPEG_DECODER_NOT_SUPPORTED, ri_get_jpeg_category_id("JPEG", 1920)); +} + + +TEST(ut_rm_api, ri_get_sub_jpeg_category_id_p) +{ + EXPECT_EQ(RI_CATEGORY_JPEG_DECODER_FHD, ri_get_sub_jpeg_category_id("JPEG", 1920, 1080)); + + int expected_result = RI_CATEGORY_JPEG_DECODER_UHD; + EXPECT_EQ(expected_result, ri_get_sub_jpeg_category_id("JPEG", 3840, 1920)); +} + +TEST(ut_rm_api, ri_get_device_path_by_device_id_p) +{ + char *path = NULL; + EXPECT_EQ(RI_OK, ri_get_device_path_by_device_id(RI_DEVICE_AUDIO_MAIN_OUT,&path)); + EXPECT_STREQ("alsa_control_main_out",path); +} + +TEST(ut_rm_api, ri_get_omx_comp_name_by_device_id_p) +{ + char *name = NULL; + EXPECT_EQ(RI_OK, ri_get_omx_comp_name_by_device_id(RI_DEVICE_AUDIO_DECODER,&name)); + EXPECT_STREQ("OMX.SDP.AUDIO.DECODER.INST0",name); +} + +TEST(ut_rm_api, ri_get_category_type_by_device_id_p) +{ + int category_id = 0; + EXPECT_EQ(RI_OK, ri_get_category_type_by_device_id(RI_DEVICE_AUDIO_MAIN_OUT, &category_id)); + EXPECT_EQ(RI_CATEGORY_AUDIO_MAIN_OUT,category_id); +} + +TEST(ut_rm_api, ri_get_device_list_p) +{ + int num_of_device = 0; + ri_device_common_attr_s *device_list = NULL; + EXPECT_EQ(RI_OK, ri_get_device_list(&num_of_device, &device_list)); +} + +TEST(ut_rm_api, ri_get_device_id_p) +{ + char path[22] = "alsa_control_main_out"; + EXPECT_EQ(RI_DEVICE_AUDIO_MAIN_OUT, ri_get_device_id(path)); +} + +TEST(ut_rm_api, ri_get_device_info_for_fastboot_p) +{ + char *node = NULL; + ri_rsc_category_e cat = RI_CATEGORY_DEMUX; + EXPECT_EQ(RI_OK, ri_get_device_info_for_fastboot(cat, &node)); +} + +TEST(ut_rm_api, ri_get_video_category_id_by_codec_p) +{ + ri_category_option_request_s request_opt; + ri_category_option_return_s return_opt; + memset(&request_opt,0,sizeof(ri_category_option_request_s)); + request_opt.codec_name = "HEVC"; + request_opt.preferred_mode = RI_VDEC_MODE_SPECIFIC; + EXPECT_EQ(RI_OK,ri_get_video_category_id_by_codec(&request_opt, &return_opt)); +} + +TEST(ut_rm_api, ri_get_capable_video_category_id_p) +{ + ri_video_category_option_request_s *opt = (ri_video_category_option_request_s*) malloc(sizeof(ri_video_category_option_request_s)); + opt->codec_name = "HEVC"; + opt->color_depth = 8; + opt->framerate = 30; + opt->h_size = 1920; + opt->v_size = 1080; + opt->sampling_format = RI_SAMPLING_FORMAT_420; + + int id = ri_get_capable_video_category_id(opt); + EXPECT_EQ(id, RI_CATEGORY_VIDEO_DECODER_HEVC_FHD_8BIT_30P); + + opt->h_size = 1920; + opt->v_size = 1090; + id = ri_get_capable_video_category_id(opt); + + int expected_result = (is_support_4k()) ? RI_CATEGORY_VIDEO_DECODER_HEVC_UHD_8BIT_30P:RI_CATEGORY_VIDEO_DECODER_NOT_SUPPORTED; + EXPECT_EQ(id, expected_result); + + opt->h_size = 2000; + opt->v_size = 1088; + id = ri_get_capable_video_category_id(opt); + EXPECT_EQ(id, expected_result); + + opt->h_size = 4096; + opt->v_size = 2160; + id = ri_get_capable_video_category_id(opt); + EXPECT_EQ(id, expected_result); + +} + +TEST(ut_rm_api, ri_get_capable_video_category_id_mpeg1) +{ + RM_TEST_MSG("ri_get_capable_video_category_id_mpeg1 start..."); + + TCPlayer *player = new TCPlayer(); + + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_MPEG1_FHD_8BIT_30P, player->GetCapableVideoCategory("MPEG1", 1920, 1080, 8, RI_SAMPLING_FORMAT_420, 30)); + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_MPEG1_FHD_8BIT_60P, player->GetCapableVideoCategory("MPEG1", 1920, 1080, 8, RI_SAMPLING_FORMAT_420, 60)); + + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_NOT_SUPPORTED, player->GetCapableVideoCategory("MPEG1", 1920, 1080, 10, RI_SAMPLING_FORMAT_420, 30)); + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_NOT_SUPPORTED, player->GetCapableVideoCategory("MPEG1", 3840, 2160, 8, RI_SAMPLING_FORMAT_420, 30)); + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_NOT_SUPPORTED, player->GetCapableVideoCategory("MPEG1", 3840, 2160, 8, RI_SAMPLING_FORMAT_420, 60)); + + delete player; + RM_TEST_MSG("ri_get_capable_video_category_id_mpeg1 end..."); +} + +TEST(ut_rm_api, ri_get_capable_video_category_id_mpeg2) +{ + RM_TEST_MSG("ri_get_capable_video_category_id_mpeg2 start..."); + + TCPlayer *player = new TCPlayer(); + + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_MPEG2_FHD_8BIT_30P, player->GetCapableVideoCategory("MPEG2", 1920, 1080, 8, RI_SAMPLING_FORMAT_420, 30)); + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_MPEG2_FHD_8BIT_60P, player->GetCapableVideoCategory("MPEG2", 1920, 1080, 8, RI_SAMPLING_FORMAT_420, 60)); + + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_NOT_SUPPORTED, player->GetCapableVideoCategory("MPEG2", 1920, 1080, 10, RI_SAMPLING_FORMAT_420, 30)); + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_NOT_SUPPORTED, player->GetCapableVideoCategory("MPEG2", 3840, 2160, 8, RI_SAMPLING_FORMAT_420, 30)); + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_NOT_SUPPORTED, player->GetCapableVideoCategory("MPEG2", 3840, 2160, 8, RI_SAMPLING_FORMAT_420, 60)); + + delete player; + RM_TEST_MSG("ri_get_capable_video_category_id_mpeg2 end..."); +} + +TEST(ut_rm_api, ri_get_capable_video_category_id_mpeg4) +{ + RM_TEST_MSG("ri_get_capable_video_category_id_mpeg4 start..."); + + TCPlayer *player = new TCPlayer(); + + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_MPEG4_FHD_8BIT_30P, player->GetCapableVideoCategory("MPEG4", 1920, 1080, 8, RI_SAMPLING_FORMAT_420, 30)); + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_MPEG4_FHD_8BIT_60P, player->GetCapableVideoCategory("MPEG4", 1920, 1080, 8, RI_SAMPLING_FORMAT_420, 60)); + + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_NOT_SUPPORTED, player->GetCapableVideoCategory("MPEG4", 1920, 1080, 10, RI_SAMPLING_FORMAT_420, 30)); + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_NOT_SUPPORTED, player->GetCapableVideoCategory("MPEG4", 3840, 2160, 8, RI_SAMPLING_FORMAT_420, 30)); + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_NOT_SUPPORTED, player->GetCapableVideoCategory("MPEG4", 3840, 2160, 10, RI_SAMPLING_FORMAT_420, 60)); + + delete player; + RM_TEST_MSG("ri_get_capable_video_category_id_mpeg4 end..."); +} + +TEST(ut_rm_api, ri_get_capable_video_category_id_h263) +{ + RM_TEST_MSG("ri_get_capable_video_category_id_h263 start..."); + + TCPlayer *player = new TCPlayer(); + + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_H263_FHD_8BIT_30P, player->GetCapableVideoCategory(RI_CODEC_NAME_H263, 1920, 1080, 8, RI_SAMPLING_FORMAT_420, 30)); + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_H263_FHD_8BIT_60P, player->GetCapableVideoCategory(RI_CODEC_NAME_H263, 1920, 1080, 8, RI_SAMPLING_FORMAT_420, 60)); + + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_NOT_SUPPORTED, player->GetCapableVideoCategory(RI_CODEC_NAME_H263, 1920, 1080, 10, RI_SAMPLING_FORMAT_420, 30)); + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_NOT_SUPPORTED, player->GetCapableVideoCategory(RI_CODEC_NAME_H263, 3840, 2160, 8, RI_SAMPLING_FORMAT_420, 30)); + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_NOT_SUPPORTED, player->GetCapableVideoCategory(RI_CODEC_NAME_H263, 3840, 2160, 10, RI_SAMPLING_FORMAT_420, 60)); + + delete player; + RM_TEST_MSG("ri_get_capable_video_category_id_h263 end..."); +} + +TEST(ut_rm_api, ri_get_capable_video_category_id_vp8) +{ + RM_TEST_MSG("ri_get_capable_video_category_id_vp8 start..."); + + TCPlayer *player = new TCPlayer(); + + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_VP8_FHD_8BIT_30P, player->GetCapableVideoCategory(RI_CODEC_NAME_VP8, 1920, 1080, 8, RI_SAMPLING_FORMAT_420, 30)); + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_VP8_FHD_8BIT_60P, player->GetCapableVideoCategory(RI_CODEC_NAME_VP8, 1920, 1080, 8, RI_SAMPLING_FORMAT_420, 60)); + + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_NOT_SUPPORTED, player->GetCapableVideoCategory(RI_CODEC_NAME_VP8, 3840, 2160, 8, RI_SAMPLING_FORMAT_420, 30)); + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_NOT_SUPPORTED, player->GetCapableVideoCategory(RI_CODEC_NAME_VP8, 3840, 2160, 8, RI_SAMPLING_FORMAT_420, 60)); + + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_NOT_SUPPORTED, player->GetCapableVideoCategory(RI_CODEC_NAME_VP8, 1920, 1080, 10, RI_SAMPLING_FORMAT_420, 30)); + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_NOT_SUPPORTED, player->GetCapableVideoCategory(RI_CODEC_NAME_VP8, 3840, 2160, 10, RI_SAMPLING_FORMAT_420, 30)); + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_NOT_SUPPORTED, player->GetCapableVideoCategory(RI_CODEC_NAME_VP8, 3840, 2160, 10, RI_SAMPLING_FORMAT_422, 60)); + + delete player; + RM_TEST_MSG("ri_get_capable_video_category_id_vp8 end..."); +} + +TEST(ut_rm_api, ri_get_capable_video_category_id_vp9) +{ + RM_TEST_MSG("ri_get_capable_video_category_id_vp9 start..."); + + TCPlayer *player = new TCPlayer(); + + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_VP9_FHD_8BIT_30P, player->GetCapableVideoCategory(RI_CODEC_NAME_VP9, 1920, 1080, 8, RI_SAMPLING_FORMAT_420, 30)); + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_VP9_FHD_8BIT_60P, player->GetCapableVideoCategory(RI_CODEC_NAME_VP9, 1920, 1080, 8, RI_SAMPLING_FORMAT_420, 60)); + + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_VP9_UHD_8BIT_30P, player->GetCapableVideoCategory(RI_CODEC_NAME_VP9, 3840, 2160, 8, RI_SAMPLING_FORMAT_420, 30)); + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_VP9_UHD_8BIT_60P, player->GetCapableVideoCategory(RI_CODEC_NAME_VP9, 3840, 2160, 8, RI_SAMPLING_FORMAT_420, 60)); + + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_VP9_FHD_10BIT_30P, player->GetCapableVideoCategory(RI_CODEC_NAME_VP9, 1920, 1080, 10, RI_SAMPLING_FORMAT_420, 30)); + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_VP9_UHD_10BIT_30P, player->GetCapableVideoCategory(RI_CODEC_NAME_VP9, 3840, 2160, 10, RI_SAMPLING_FORMAT_420, 30)); + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_NOT_SUPPORTED, player->GetCapableVideoCategory(RI_CODEC_NAME_VP9, 3840, 2160, 10, RI_SAMPLING_FORMAT_422, 60)); + + delete player; + RM_TEST_MSG("ri_get_capable_video_category_id_vp9 end..."); +} + +TEST(ut_rm_api, ri_get_capable_video_category_id_rv) +{ + RM_TEST_MSG("ri_get_capable_video_category_id_rv start..."); + + TCPlayer *player = new TCPlayer(); + + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_RV_FHD_8BIT_30P, player->GetCapableVideoCategory(RI_CODEC_NAME_RV, 1920, 1080, 8, RI_SAMPLING_FORMAT_420, 30)); + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_RV_FHD_8BIT_60P, player->GetCapableVideoCategory(RI_CODEC_NAME_RV, 1920, 1080, 8, RI_SAMPLING_FORMAT_420, 60)); + + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_NOT_SUPPORTED, player->GetCapableVideoCategory(RI_CODEC_NAME_RV, 3840, 2160, 8, RI_SAMPLING_FORMAT_420, 30)); + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_NOT_SUPPORTED, player->GetCapableVideoCategory(RI_CODEC_NAME_RV, 3840, 2160, 8, RI_SAMPLING_FORMAT_420, 60)); + + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_NOT_SUPPORTED, player->GetCapableVideoCategory(RI_CODEC_NAME_RV, 1920, 1080, 10, RI_SAMPLING_FORMAT_420, 30)); + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_NOT_SUPPORTED, player->GetCapableVideoCategory(RI_CODEC_NAME_RV, 3840, 2160, 10, RI_SAMPLING_FORMAT_420, 30)); + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_NOT_SUPPORTED, player->GetCapableVideoCategory(RI_CODEC_NAME_RV, 3840, 2160, 10, RI_SAMPLING_FORMAT_422, 60)); + + delete player; + RM_TEST_MSG("ri_get_capable_video_category_id_rv end..."); +} + +TEST(ut_rm_api, ri_get_capable_video_category_id_wmv) +{ + RM_TEST_MSG("ri_get_capable_video_category_id_wmv start..."); + + TCPlayer *player = new TCPlayer(); + + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_WMV9_FHD_8BIT_30P, player->GetCapableVideoCategory(RI_CODEC_NAME_WMV, 1920, 1080, 8, RI_SAMPLING_FORMAT_420, 30)); + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_WMV9_FHD_8BIT_60P, player->GetCapableVideoCategory(RI_CODEC_NAME_WMV, 1920, 1080, 8, RI_SAMPLING_FORMAT_420, 60)); + + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_NOT_SUPPORTED, player->GetCapableVideoCategory(RI_CODEC_NAME_WMV, 3840, 2160, 8, RI_SAMPLING_FORMAT_420, 30)); + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_NOT_SUPPORTED, player->GetCapableVideoCategory(RI_CODEC_NAME_WMV, 3840, 2160, 8, RI_SAMPLING_FORMAT_420, 60)); + + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_NOT_SUPPORTED, player->GetCapableVideoCategory(RI_CODEC_NAME_WMV, 1920, 1080, 10, RI_SAMPLING_FORMAT_420, 30)); + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_NOT_SUPPORTED, player->GetCapableVideoCategory(RI_CODEC_NAME_WMV, 3840, 2160, 10, RI_SAMPLING_FORMAT_420, 30)); + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_NOT_SUPPORTED, player->GetCapableVideoCategory(RI_CODEC_NAME_WMV, 3840, 2160, 10, RI_SAMPLING_FORMAT_422, 60)); + + delete player; + RM_TEST_MSG("ri_get_capable_video_category_id_wmv end..."); +} + +TEST(ut_rm_api, ri_get_capable_video_category_id_avs) +{ + RM_TEST_MSG("ri_get_capable_video_category_id_avs start..."); + + TCPlayer *player = new TCPlayer(); + + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_AVS_FHD_8BIT_30P, player->GetCapableVideoCategory(RI_CODEC_NAME_AVS, 1920, 1080, 8, RI_SAMPLING_FORMAT_420, 30)); + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_AVS_FHD_8BIT_60P, player->GetCapableVideoCategory(RI_CODEC_NAME_AVS, 1920, 1080, 8, RI_SAMPLING_FORMAT_420, 60)); + + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_NOT_SUPPORTED, player->GetCapableVideoCategory(RI_CODEC_NAME_AVS, 3840, 2160, 8, RI_SAMPLING_FORMAT_420, 30)); + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_NOT_SUPPORTED, player->GetCapableVideoCategory(RI_CODEC_NAME_AVS, 3840, 2160, 8, RI_SAMPLING_FORMAT_420, 60)); + + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_NOT_SUPPORTED, player->GetCapableVideoCategory(RI_CODEC_NAME_AVS, 1920, 1080, 10, RI_SAMPLING_FORMAT_420, 30)); + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_NOT_SUPPORTED, player->GetCapableVideoCategory(RI_CODEC_NAME_AVS, 3840, 2160, 10, RI_SAMPLING_FORMAT_420, 30)); + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_NOT_SUPPORTED, player->GetCapableVideoCategory(RI_CODEC_NAME_AVS, 3840, 2160, 10, RI_SAMPLING_FORMAT_422, 60)); + + delete player; + RM_TEST_MSG("ri_get_capable_video_category_id_avs end..."); +} + +TEST(ut_rm_api, ri_get_capable_video_category_id_avs_plus) +{ + RM_TEST_MSG("ri_get_capable_video_category_id_avs_plus start..."); + + TCPlayer *player = new TCPlayer(); + + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_AVS_PLUS_FHD_8BIT_30P, player->GetCapableVideoCategory(RI_CODEC_NAME_AVS_PLUS, 1920, 1080, 8, RI_SAMPLING_FORMAT_420, 30)); + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_AVS_PLUS_FHD_8BIT_60P, player->GetCapableVideoCategory(RI_CODEC_NAME_AVS_PLUS, 1920, 1080, 8, RI_SAMPLING_FORMAT_420, 60)); + + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_NOT_SUPPORTED, player->GetCapableVideoCategory(RI_CODEC_NAME_AVS_PLUS, 3840, 2160, 8, RI_SAMPLING_FORMAT_420, 30)); + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_NOT_SUPPORTED, player->GetCapableVideoCategory(RI_CODEC_NAME_AVS_PLUS, 3840, 2160, 8, RI_SAMPLING_FORMAT_420, 60)); + + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_NOT_SUPPORTED, player->GetCapableVideoCategory(RI_CODEC_NAME_AVS_PLUS, 1920, 1080, 10, RI_SAMPLING_FORMAT_420, 30)); + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_NOT_SUPPORTED, player->GetCapableVideoCategory(RI_CODEC_NAME_AVS_PLUS, 3840, 2160, 10, RI_SAMPLING_FORMAT_420, 30)); + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_NOT_SUPPORTED, player->GetCapableVideoCategory(RI_CODEC_NAME_AVS_PLUS, 3840, 2160, 10, RI_SAMPLING_FORMAT_422, 60)); + + delete player; + RM_TEST_MSG("ri_get_capable_video_category_id_avs_plus end..."); +} + +TEST(ut_rm_api, ri_get_capable_video_category_id_av1) +{ + RM_TEST_MSG("ri_get_capable_video_category_id_av1 start..."); + + TCPlayer *player = new TCPlayer(); + + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_AV1_FHD_8BIT_30P, player->GetCapableVideoCategory(RI_CODEC_NAME_AV1, 1920, 1080, 8, RI_SAMPLING_FORMAT_420, 30)); + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_AV1_FHD_8BIT_60P, player->GetCapableVideoCategory(RI_CODEC_NAME_AV1, 1920, 1080, 8, RI_SAMPLING_FORMAT_420, 60)); + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_AV1_UHD_8BIT_30P, player->GetCapableVideoCategory(RI_CODEC_NAME_AV1, 3840, 2160, 8, RI_SAMPLING_FORMAT_420, 30)); + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_AV1_UHD_8BIT_60P, player->GetCapableVideoCategory(RI_CODEC_NAME_AV1, 3840, 2160, 8, RI_SAMPLING_FORMAT_420, 60)); + + if (is_support_av1_120p()) + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_AV1_UHD_8BIT_120P, player->GetCapableVideoCategory(RI_CODEC_NAME_AV1, 3840, 2160, 8, RI_SAMPLING_FORMAT_420, 120)); + else + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_NOT_SUPPORTED, player->GetCapableVideoCategory(RI_CODEC_NAME_AV1, 3840, 2160, 8, RI_SAMPLING_FORMAT_420, 120)); + + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_AV1_FHD_10BIT_30P, player->GetCapableVideoCategory(RI_CODEC_NAME_AV1, 1920, 1080, 10, RI_SAMPLING_FORMAT_OTHERS, 30)); + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_AV1_FHD_10BIT_60P, player->GetCapableVideoCategory(RI_CODEC_NAME_AV1, 1920, 1080, 10, RI_SAMPLING_FORMAT_OTHERS, 60)); + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_AV1_UHD_10BIT_30P, player->GetCapableVideoCategory(RI_CODEC_NAME_AV1, 3840, 2160, 10, RI_SAMPLING_FORMAT_OTHERS, 30)); + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_AV1_UHD_10BIT_60P, player->GetCapableVideoCategory(RI_CODEC_NAME_AV1, 3840, 2160, 10, RI_SAMPLING_FORMAT_OTHERS, 60)); + + if (is_support_av1_120p()) + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_AV1_UHD_10BIT_120P, player->GetCapableVideoCategory(RI_CODEC_NAME_AV1, 3840, 2160, 10, RI_SAMPLING_FORMAT_420, 120)); + else + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_NOT_SUPPORTED, player->GetCapableVideoCategory(RI_CODEC_NAME_AV1, 3840, 2160, 10, RI_SAMPLING_FORMAT_OTHERS, 120)); + + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_AV1_FHD_10BIT_30P, player->GetCapableVideoCategory(RI_CODEC_NAME_AV1, 1920, 1080, 10, RI_SAMPLING_FORMAT_420, 30)); + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_AV1_FHD_10BIT_60P, player->GetCapableVideoCategory(RI_CODEC_NAME_AV1, 1920, 1080, 10, RI_SAMPLING_FORMAT_420, 60)); + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_AV1_UHD_10BIT_30P, player->GetCapableVideoCategory(RI_CODEC_NAME_AV1, 3840, 2160, 10, RI_SAMPLING_FORMAT_420, 30)); + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_AV1_UHD_10BIT_60P, player->GetCapableVideoCategory(RI_CODEC_NAME_AV1, 3840, 2160, 10, RI_SAMPLING_FORMAT_420, 60)); + + if (is_support_av1_120p()) + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_AV1_UHD_10BIT_120P, player->GetCapableVideoCategory(RI_CODEC_NAME_AV1, 3840, 2160, 10, RI_SAMPLING_FORMAT_420, 120)); + else + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_NOT_SUPPORTED, player->GetCapableVideoCategory(RI_CODEC_NAME_AV1, 3840, 2160, 10, RI_SAMPLING_FORMAT_420, 120)); + + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_AV1_FHD_10BIT_30P, player->GetCapableVideoCategory(RI_CODEC_NAME_AV1, 1920, 1080, 10, RI_SAMPLING_FORMAT_422, 30)); + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_AV1_FHD_10BIT_60P, player->GetCapableVideoCategory(RI_CODEC_NAME_AV1, 1920, 1080, 10, RI_SAMPLING_FORMAT_422, 60)); + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_AV1_UHD_10BIT_30P, player->GetCapableVideoCategory(RI_CODEC_NAME_AV1, 3840, 2160, 10, RI_SAMPLING_FORMAT_422, 30)); + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_AV1_UHD_10BIT_60P, player->GetCapableVideoCategory(RI_CODEC_NAME_AV1, 3840, 2160, 10, RI_SAMPLING_FORMAT_422, 60)); + + if (is_support_av1_120p()) + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_AV1_UHD_10BIT_120P, player->GetCapableVideoCategory(RI_CODEC_NAME_AV1, 3840, 2160, 10, RI_SAMPLING_FORMAT_420, 120)); + else + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_NOT_SUPPORTED, player->GetCapableVideoCategory(RI_CODEC_NAME_AV1, 3840, 2160, 10, RI_SAMPLING_FORMAT_422, 120)); + + if (is_support_8k()) { + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_AV1_8K_8BIT_30P, player->GetCapableVideoCategory(RI_CODEC_NAME_AV1, 7680, 4320, 8, RI_SAMPLING_FORMAT_420, 30)); + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_AV1_8K_8BIT_60P, player->GetCapableVideoCategory(RI_CODEC_NAME_AV1, 7680, 4320, 8, RI_SAMPLING_FORMAT_420, 60)); + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_NOT_SUPPORTED, player->GetCapableVideoCategory(RI_CODEC_NAME_AV1, 7680, 4320, 8, RI_SAMPLING_FORMAT_420, 120)); + + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_AV1_8K_10BIT_30P, player->GetCapableVideoCategory(RI_CODEC_NAME_AV1, 7680, 4320, 10, RI_SAMPLING_FORMAT_OTHERS, 30)); + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_AV1_8K_10BIT_60P, player->GetCapableVideoCategory(RI_CODEC_NAME_AV1, 7680, 4320, 10, RI_SAMPLING_FORMAT_OTHERS, 60)); + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_NOT_SUPPORTED, player->GetCapableVideoCategory(RI_CODEC_NAME_AV1, 7680, 4320, 10, RI_SAMPLING_FORMAT_OTHERS, 120)); + + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_AV1_8K_10BIT_30P, player->GetCapableVideoCategory(RI_CODEC_NAME_AV1, 7680, 4320, 10, RI_SAMPLING_FORMAT_420, 30)); + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_AV1_8K_10BIT_60P, player->GetCapableVideoCategory(RI_CODEC_NAME_AV1, 7680, 4320, 10, RI_SAMPLING_FORMAT_420, 60)); + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_NOT_SUPPORTED, player->GetCapableVideoCategory(RI_CODEC_NAME_AV1, 7680, 4320, 10, RI_SAMPLING_FORMAT_420, 120)); + + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_AV1_8K_10BIT_30P, player->GetCapableVideoCategory(RI_CODEC_NAME_AV1, 7680, 4320, 10, RI_SAMPLING_FORMAT_422, 30)); + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_AV1_8K_10BIT_60P, player->GetCapableVideoCategory(RI_CODEC_NAME_AV1, 7680, 4320, 10, RI_SAMPLING_FORMAT_422, 60)); + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_NOT_SUPPORTED, player->GetCapableVideoCategory(RI_CODEC_NAME_AV1, 7680, 4320, 10, RI_SAMPLING_FORMAT_422, 120)); + } else { + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_NOT_SUPPORTED, player->GetCapableVideoCategory(RI_CODEC_NAME_AV1, 7680, 4320, 8, RI_SAMPLING_FORMAT_420, 30)); + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_NOT_SUPPORTED, player->GetCapableVideoCategory(RI_CODEC_NAME_AV1, 7680, 4320, 8, RI_SAMPLING_FORMAT_420, 60)); + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_NOT_SUPPORTED, player->GetCapableVideoCategory(RI_CODEC_NAME_AV1, 7680, 4320, 8, RI_SAMPLING_FORMAT_420, 120)); + + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_NOT_SUPPORTED, player->GetCapableVideoCategory(RI_CODEC_NAME_AV1, 7680, 4320, 8, RI_SAMPLING_FORMAT_OTHERS, 30)); + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_NOT_SUPPORTED, player->GetCapableVideoCategory(RI_CODEC_NAME_AV1, 7680, 4320, 8, RI_SAMPLING_FORMAT_OTHERS, 60)); + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_NOT_SUPPORTED, player->GetCapableVideoCategory(RI_CODEC_NAME_AV1, 7680, 4320, 8, RI_SAMPLING_FORMAT_OTHERS, 120)); + + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_NOT_SUPPORTED, player->GetCapableVideoCategory(RI_CODEC_NAME_AV1, 7680, 4320, 10, RI_SAMPLING_FORMAT_420, 30)); + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_NOT_SUPPORTED, player->GetCapableVideoCategory(RI_CODEC_NAME_AV1, 7680, 4320, 10, RI_SAMPLING_FORMAT_420, 60)); + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_NOT_SUPPORTED, player->GetCapableVideoCategory(RI_CODEC_NAME_AV1, 7680, 4320, 10, RI_SAMPLING_FORMAT_420, 120)); + + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_NOT_SUPPORTED, player->GetCapableVideoCategory(RI_CODEC_NAME_AV1, 7680, 4320, 10, RI_SAMPLING_FORMAT_422, 30)); + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_NOT_SUPPORTED, player->GetCapableVideoCategory(RI_CODEC_NAME_AV1, 7680, 4320, 10, RI_SAMPLING_FORMAT_422, 60)); + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_NOT_SUPPORTED, player->GetCapableVideoCategory(RI_CODEC_NAME_AV1, 7680, 4320, 10, RI_SAMPLING_FORMAT_422, 120)); + } + + delete player; + RM_TEST_MSG("ri_get_capable_video_category_id_av1 end..."); +} + +TEST(ut_rm_api, ri_get_capable_video_category_id_av1_vr360) +{ + RM_TEST_MSG("ri_get_capable_video_category_id_av1_vr360 start..."); + + TCPlayer *player = new TCPlayer(); + + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_AV1_VR360_FHD_8BIT_30P, player->GetCapableVideoCategory(RI_CODEC_NAME_AV1_VR360, 1920, 1080, 8, RI_SAMPLING_FORMAT_420, 30)); + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_AV1_VR360_FHD_8BIT_60P, player->GetCapableVideoCategory(RI_CODEC_NAME_AV1_VR360, 1920, 1080, 8, RI_SAMPLING_FORMAT_420, 60)); + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_AV1_VR360_UHD_8BIT_30P, player->GetCapableVideoCategory(RI_CODEC_NAME_AV1_VR360, 3840, 2160, 8, RI_SAMPLING_FORMAT_420, 30)); + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_AV1_VR360_UHD_8BIT_60P, player->GetCapableVideoCategory(RI_CODEC_NAME_AV1_VR360, 3840, 2160, 8, RI_SAMPLING_FORMAT_420, 60)); + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_NOT_SUPPORTED, player->GetCapableVideoCategory(RI_CODEC_NAME_AV1_VR360, 3840, 2160, 8, RI_SAMPLING_FORMAT_420, 120)); + + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_AV1_VR360_FHD_10BIT_30P, player->GetCapableVideoCategory(RI_CODEC_NAME_AV1_VR360, 1920, 1080, 10, RI_SAMPLING_FORMAT_OTHERS, 30)); + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_AV1_VR360_FHD_10BIT_60P, player->GetCapableVideoCategory(RI_CODEC_NAME_AV1_VR360, 1920, 1080, 10, RI_SAMPLING_FORMAT_OTHERS, 60)); + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_AV1_VR360_UHD_10BIT_30P, player->GetCapableVideoCategory(RI_CODEC_NAME_AV1_VR360, 3840, 2160, 10, RI_SAMPLING_FORMAT_OTHERS, 30)); + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_AV1_VR360_UHD_10BIT_60P, player->GetCapableVideoCategory(RI_CODEC_NAME_AV1_VR360, 3840, 2160, 10, RI_SAMPLING_FORMAT_OTHERS, 60)); + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_NOT_SUPPORTED, player->GetCapableVideoCategory(RI_CODEC_NAME_AV1_VR360, 3840, 2160, 10, RI_SAMPLING_FORMAT_OTHERS, 120)); + + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_AV1_VR360_FHD_10BIT_30P, player->GetCapableVideoCategory(RI_CODEC_NAME_AV1_VR360, 1920, 1080, 10, RI_SAMPLING_FORMAT_420, 30)); + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_AV1_VR360_FHD_10BIT_60P, player->GetCapableVideoCategory(RI_CODEC_NAME_AV1_VR360, 1920, 1080, 10, RI_SAMPLING_FORMAT_420, 60)); + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_AV1_VR360_UHD_10BIT_30P, player->GetCapableVideoCategory(RI_CODEC_NAME_AV1_VR360, 3840, 2160, 10, RI_SAMPLING_FORMAT_420, 30)); + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_AV1_VR360_UHD_10BIT_60P, player->GetCapableVideoCategory(RI_CODEC_NAME_AV1_VR360, 3840, 2160, 10, RI_SAMPLING_FORMAT_420, 60)); + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_NOT_SUPPORTED, player->GetCapableVideoCategory(RI_CODEC_NAME_AV1_VR360, 3840, 2160, 10, RI_SAMPLING_FORMAT_420, 120)); + + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_NOT_SUPPORTED, player->GetCapableVideoCategory(RI_CODEC_NAME_AV1_VR360, 1920, 1080, 10, RI_SAMPLING_FORMAT_422, 30)); + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_NOT_SUPPORTED, player->GetCapableVideoCategory(RI_CODEC_NAME_AV1_VR360, 1920, 1080, 10, RI_SAMPLING_FORMAT_422, 60)); + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_NOT_SUPPORTED, player->GetCapableVideoCategory(RI_CODEC_NAME_AV1_VR360, 3840, 2160, 10, RI_SAMPLING_FORMAT_422, 30)); + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_NOT_SUPPORTED, player->GetCapableVideoCategory(RI_CODEC_NAME_AV1_VR360, 3840, 2160, 10, RI_SAMPLING_FORMAT_422, 60)); + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_NOT_SUPPORTED, player->GetCapableVideoCategory(RI_CODEC_NAME_AV1_VR360, 3840, 2160, 10, RI_SAMPLING_FORMAT_422, 120)); + + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_NOT_SUPPORTED, player->GetCapableVideoCategory(RI_CODEC_NAME_AV1_VR360, 7680, 4320, 8, RI_SAMPLING_FORMAT_420, 30)); + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_NOT_SUPPORTED, player->GetCapableVideoCategory(RI_CODEC_NAME_AV1_VR360, 7680, 4320, 8, RI_SAMPLING_FORMAT_420, 60)); + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_NOT_SUPPORTED, player->GetCapableVideoCategory(RI_CODEC_NAME_AV1_VR360, 7680, 4320, 8, RI_SAMPLING_FORMAT_420, 120)); + + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_NOT_SUPPORTED, player->GetCapableVideoCategory(RI_CODEC_NAME_AV1_VR360, 7680, 4320, 8, RI_SAMPLING_FORMAT_OTHERS, 30)); + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_NOT_SUPPORTED, player->GetCapableVideoCategory(RI_CODEC_NAME_AV1_VR360, 7680, 4320, 8, RI_SAMPLING_FORMAT_OTHERS, 60)); + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_NOT_SUPPORTED, player->GetCapableVideoCategory(RI_CODEC_NAME_AV1_VR360, 7680, 4320, 8, RI_SAMPLING_FORMAT_OTHERS, 120)); + + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_NOT_SUPPORTED, player->GetCapableVideoCategory(RI_CODEC_NAME_AV1_VR360, 7680, 4320, 10, RI_SAMPLING_FORMAT_420, 30)); + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_NOT_SUPPORTED, player->GetCapableVideoCategory(RI_CODEC_NAME_AV1_VR360, 7680, 4320, 10, RI_SAMPLING_FORMAT_420, 60)); + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_NOT_SUPPORTED, player->GetCapableVideoCategory(RI_CODEC_NAME_AV1_VR360, 7680, 4320, 10, RI_SAMPLING_FORMAT_420, 120)); + + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_NOT_SUPPORTED, player->GetCapableVideoCategory(RI_CODEC_NAME_AV1_VR360, 7680, 4320, 10, RI_SAMPLING_FORMAT_422, 30)); + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_NOT_SUPPORTED, player->GetCapableVideoCategory(RI_CODEC_NAME_AV1_VR360, 7680, 4320, 10, RI_SAMPLING_FORMAT_422, 60)); + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_NOT_SUPPORTED, player->GetCapableVideoCategory(RI_CODEC_NAME_AV1_VR360, 7680, 4320, 10, RI_SAMPLING_FORMAT_422, 120)); + + delete player; + RM_TEST_MSG("ri_get_capable_video_category_id_av1_vr360 end..."); +} + + +static rm_cb_result callback_default(int handle, rm_callback_type event, rm_device_request_s *info, void *data) +{ + rm_deallocate_resources(handle, info); + + return RM_CB_RESULT_OK; +} + +TEST(ut_rm_api, allocate_audio_decoder) +{ + conflicted = 0; + num_of_dealloc_rsc = 0; + + //consumer#1 + int handle1 = 0; + EXPECT_EQ(RM_OK, rm_register(conflict_cb2, NULL, &handle1, NULL)); + + //alloc + rm_category_request_s *request = (rm_category_request_s*) malloc (sizeof(rm_category_request_s)); + memset((void*)request, 0, sizeof(rm_category_request_s)); + + request->request_num = 1; + request->category_id[0] = RM_CATEGORY_AUDIO_DECODER; + request->category_option[0] = 0; + request->state[0] = RM_STATE_EXCLUSIVE; + + rm_device_return_s *allocated = (rm_device_return_s*) malloc (sizeof(rm_device_return_s)); + memset((void*)allocated, 0, sizeof(rm_device_return_s)); + + EXPECT_EQ(RM_OK, rm_allocate_resources(handle1, request, allocated)); + + //unregister + EXPECT_EQ(RM_OK, rm_unregister(handle1)); + + sleep(RM_TEST_SLEEP_TIME); +} + +TEST(ut_rm_api, allocate_audio_decoder_not_supported) +{ + conflicted = 0; + num_of_dealloc_rsc = 0; + + RM_TEST_MSG("allocate_audio_decoder_not_supported begin"); + + //consumer#1 + int handle1 = 0; + EXPECT_EQ(RM_OK, rm_register(conflict_cb2, NULL, &handle1, NULL)); + + //alloc + rm_category_request_s *request = (rm_category_request_s*) malloc (sizeof(rm_category_request_s)); + memset((void*)request, 0, sizeof(rm_category_request_s)); + + request->request_num = 1; + request->category_id[0] = RM_CATEGORY_AUDIO_DECODER; + request->category_option[0] = RM_CATEGORY_AUDIO_DECODER_NOT_SUPPORTED; + request->state[0] = RM_STATE_EXCLUSIVE; + + rm_device_return_s *allocated = (rm_device_return_s*) malloc (sizeof(rm_device_return_s)); + memset((void*)allocated, 0, sizeof(rm_device_return_s)); + + EXPECT_NE(RM_OK, rm_allocate_resources(handle1, request, allocated)); + + //unregister + EXPECT_EQ(RM_OK, rm_unregister(handle1)); + + RM_TEST_MSG("allocate_audio_decoder_not_supported end"); + + sleep(RM_TEST_SLEEP_TIME); +} + +TEST(ut_rm_api, allocate_failure_reason) +{ + conflicted = 0; + num_of_dealloc_rsc = 0; + + //consumer#1 + int handle1 = 0; + EXPECT_EQ(RM_OK, rm_register(conflict_cb2, NULL, &handle1, NULL)); + + //alloc + rm_category_request_s *request = (rm_category_request_s*) malloc (sizeof(rm_category_request_s)); + memset((void*)request, 0, sizeof(rm_category_request_s)); + + request->request_num = 1; + request->category_id[0] = RM_CATEGORY_AUDIO_DECODER; + request->category_option[0] = RM_CATEGORY_AUDIO_DECODER_NOT_SUPPORTED; + request->state[0] = RM_STATE_EXCLUSIVE; + + rm_device_return_s *allocated = (rm_device_return_s*) malloc (sizeof(rm_device_return_s)); + memset((void*)allocated, 0, sizeof(rm_device_return_s)); + + EXPECT_NE(RM_OK, rm_allocate_resources(handle1, request, allocated)); + EXPECT_EQ(RM_ERR_TYPE_REQUESTED_RESOURCE_DOES_NOT_EXIST, allocated->error_type); + + //unregister + EXPECT_EQ(RM_OK, rm_unregister(handle1)); + + sleep(RM_TEST_SLEEP_TIME); +} + +TEST(ut_rm_api, alloc_preference_p1) +{ + /* + * 1. Allocate the following resources with preference mode at once + * RM_CATEGORY_VIDEO_DECODER_MPEG1_FHD_8BIT_30P + * RM_CATEGORY_VIDEO_DECODER_HEVC_UHD_8BIT_30P + * -> Alloc only RM_CATEGORY_VIDEO_DECODER_MPEG1_FHD_8BIT_30P + */ + + RM_TEST_MSG("alloc_preference_p1 start..."); + + conflicted = 0; + + int handle = 0; + + EXPECT_EQ(RM_OK, rm_register(conflict_cb3, NULL, &handle, NULL)); + + rm_category_request_s request; + memset(&request, 0, sizeof(rm_category_request_s)); + + rm_device_return_s return_devices; + memset(&return_devices, 0, sizeof(rm_device_return_s)); + + request.request_num = 2; + + request.category_id[0] = RM_CATEGORY_VIDEO_DECODER; + request.category_option[0] = RM_CATEGORY_VIDEO_DECODER_MPEG1_FHD_8BIT_30P; + request.state[0] = RM_STATE_EXCLUSIVE_PREFERENCE; + + request.category_id[1] = RM_CATEGORY_VIDEO_DECODER; + request.category_option[1] = RM_CATEGORY_VIDEO_DECODER_HEVC_UHD_8BIT_30P; + request.state[1] = RM_STATE_EXCLUSIVE_PREFERENCE; + + EXPECT_EQ(RM_OK, rm_allocate_resources(handle, &request, &return_devices)); + + EXPECT_EQ(request.request_num, return_devices.allocated_num); + EXPECT_LT(RM_DEVICE_NONE, return_devices.device_id[0]); // RM_DEVICE_NONE < return_devices.device_id[0] + EXPECT_EQ(RM_DEVICE_NONE, return_devices.device_id[1]); + + EXPECT_EQ(0, conflicted); + conflicted = 0; + + EXPECT_EQ(RM_OK, rm_unregister(handle)); + + sleep(RM_TEST_SLEEP_TIME); + + RM_TEST_MSG("alloc_preference_p1 end..."); +} + +TEST(ut_rm_api, alloc_preference_p2) +{ + /* + * 1. Allocate the following resources with preference mode at once + * RM_CATEGORY_VIDEO_DECODER_HEVC_UHD_8BIT_30P + * RM_CATEGORY_VIDEO_DECODER_MPEG1_FHD_8BIT_30P + * -> Alloc only RM_CATEGORY_VIDEO_DECODER_HEVC_UHD_8BIT_30P + */ + + RM_TEST_MSG("alloc_preference_p2 start..."); + + conflicted = 0; + + int handle = 0; + + EXPECT_EQ(RM_OK, rm_register(conflict_cb3, NULL, &handle, NULL)); + + rm_category_request_s request; + memset(&request, 0, sizeof(rm_category_request_s)); + + rm_device_return_s return_devices; + memset(&return_devices, 0, sizeof(rm_device_return_s)); + + request.request_num = 2; + + request.category_id[0] = RM_CATEGORY_VIDEO_DECODER; + request.category_option[0] = RM_CATEGORY_VIDEO_DECODER_HEVC_UHD_8BIT_30P; + request.state[0] = RM_STATE_EXCLUSIVE_PREFERENCE; + + request.category_id[1] = RM_CATEGORY_VIDEO_DECODER; + request.category_option[1] = RM_CATEGORY_VIDEO_DECODER_MPEG1_FHD_8BIT_30P; + request.state[1] = RM_STATE_EXCLUSIVE_PREFERENCE; + + EXPECT_EQ(RM_OK, rm_allocate_resources(handle, &request, &return_devices)); + + EXPECT_EQ(request.request_num, return_devices.allocated_num); + + if (is_support_4k()) { + EXPECT_LT(RM_DEVICE_NONE, return_devices.device_id[0]); // RM_DEVICE_NONE < return_devices.device_id[0] + EXPECT_EQ(RM_DEVICE_NONE, return_devices.device_id[1]); + } else { + EXPECT_EQ(RM_DEVICE_NONE, return_devices.device_id[0]); + EXPECT_LT(RM_DEVICE_NONE, return_devices.device_id[1]); // RM_DEVICE_NONE < return_devices.device_id[0] + } + EXPECT_EQ(0, conflicted); + conflicted = 0; + + EXPECT_EQ(RM_OK, rm_unregister(handle)); + + sleep(RM_TEST_SLEEP_TIME); + + RM_TEST_MSG("alloc_preference_p2 end..."); + +} + +TEST(ut_rm_api, alloc_preference_p3) +{ + /* + * 1. Allocate the following resources with preference mode at once + * RM_CATEGORY_VIDEO_DECODER_HEVC_UHD_8BIT_30P + * RM_CATEGORY_VIDEO_DECODER_HEVC_UHD_8BIT_60P + * -> Alloc only RM_CATEGORY_VIDEO_DECODER_HEVC_UHD_8BIT_30P + */ + + RM_TEST_MSG("alloc_preference_p3 start..."); + + conflicted = 0; + + int handle = 0; + + EXPECT_EQ(RM_OK, rm_register(conflict_cb3, NULL, &handle, NULL)); + + rm_category_request_s request; + memset(&request, 0, sizeof(rm_category_request_s)); + + rm_device_return_s return_devices; + memset(&return_devices, 0, sizeof(rm_device_return_s)); + + request.request_num = 2; + + request.category_id[0] = RM_CATEGORY_VIDEO_DECODER; + request.category_option[0] = RM_CATEGORY_VIDEO_DECODER_HEVC_UHD_8BIT_30P; + request.state[0] = RM_STATE_EXCLUSIVE_PREFERENCE; + + request.category_id[1] = RM_CATEGORY_VIDEO_DECODER; + request.category_option[1] = RM_CATEGORY_VIDEO_DECODER_HEVC_UHD_8BIT_60P; + request.state[1] = RM_STATE_EXCLUSIVE_PREFERENCE; + + if (is_support_4k()) { + EXPECT_EQ(RM_OK, rm_allocate_resources(handle, &request, &return_devices)); + EXPECT_EQ(request.request_num, return_devices.allocated_num); + EXPECT_LT(RM_DEVICE_NONE, return_devices.device_id[0]); // RM_DEVICE_NONE < return_devices.device_id[0] + EXPECT_EQ(RM_DEVICE_NONE, return_devices.device_id[1]); + } else { + EXPECT_NE(RM_OK, rm_allocate_resources(handle, &request, &return_devices)); + EXPECT_NE(request.request_num, return_devices.allocated_num); + EXPECT_EQ(RM_DEVICE_NONE, return_devices.device_id[0]); + EXPECT_EQ(RM_DEVICE_NONE, return_devices.device_id[1]); + } + + EXPECT_EQ(0, conflicted); + conflicted = 0; + + EXPECT_EQ(RM_OK, rm_unregister(handle)); + + sleep(RM_TEST_SLEEP_TIME); + + RM_TEST_MSG("alloc_preference_p3 end..."); + +} + +TEST(ut_rm_api, alloc_preference_n1) +{ + /* + * 1. Allocate the following resources with exclusive mode + * RM_CATEGORY_VIDEO_DECODER_HEVC_UHD_8BIT_30P -> Alloc + * 2. Allocate the following resources with preference mode at once + * RM_CATEGORY_VIDEO_DECODER_HEVC_UHD_8BIT_60P + * RM_CATEGORY_VIDEO_DECODER_HEVC_UHD_8BIT_30P + * -> Alloc : Fail + */ + + if (ri_get_max_video_decoder_num() >= 4) + return; + + if (is_oscars_unified_jpeg_decoder()) + return; + + RM_TEST_MSG("alloc_preference_n1 start..."); + + conflicted = 0; + + int handle = 0; + + EXPECT_EQ(RM_OK, rm_register(conflict_cb3, NULL, &handle, NULL)); + + rm_category_request_s request; + memset(&request, 0, sizeof(rm_category_request_s)); + + rm_device_return_s return_devices; + memset(&return_devices, 0, sizeof(rm_device_return_s)); + + request.request_num = 1; + + request.category_id[0] = RM_CATEGORY_VIDEO_DECODER; + request.category_option[0] = RM_CATEGORY_VIDEO_DECODER_HEVC_UHD_8BIT_30P; + request.state[0] = RM_STATE_EXCLUSIVE_PREFERENCE; + + if (is_support_4k()) { + EXPECT_EQ(RM_OK, rm_allocate_resources(handle, &request, &return_devices)); + EXPECT_EQ(request.request_num, return_devices.allocated_num); + EXPECT_LT(RM_DEVICE_NONE, return_devices.device_id[0]); // RM_DEVICE_NONE < return_devices.device_id[0] + } else { + EXPECT_NE(RM_OK, rm_allocate_resources(handle, &request, &return_devices)); + EXPECT_NE(request.request_num, return_devices.allocated_num); + EXPECT_EQ(RM_DEVICE_NONE, return_devices.device_id[0]); + } + + EXPECT_EQ(0, conflicted); + conflicted = 0; + + int handle2 = 0; + + EXPECT_EQ(RM_OK, rm_register(conflict_cb3, NULL, &handle2, NULL)); + + memset(&request, 0, sizeof(rm_category_request_s)); + memset(&return_devices, 0, sizeof(rm_device_return_s)); + + request.request_num = 2; + + request.category_id[0] = RM_CATEGORY_VIDEO_DECODER; + request.category_option[0] = RM_CATEGORY_VIDEO_DECODER_HEVC_UHD_8BIT_60P; + request.state[0] = RM_STATE_EXCLUSIVE_PREFERENCE; + + request.category_id[1] = RM_CATEGORY_VIDEO_DECODER; + request.category_option[1] = RM_CATEGORY_VIDEO_DECODER_HEVC_UHD_8BIT_30P; + request.state[1] = RM_STATE_EXCLUSIVE_PREFERENCE; + + EXPECT_NE(RM_OK, rm_allocate_resources(handle2, &request, &return_devices)); + + EXPECT_EQ(0, return_devices.allocated_num); + EXPECT_EQ(RM_DEVICE_NONE, return_devices.device_id[0]); + EXPECT_EQ(RM_DEVICE_NONE, return_devices.device_id[1]); + EXPECT_EQ(0, conflicted); + conflicted = 0; + + EXPECT_EQ(RM_OK, rm_unregister(handle)); + EXPECT_EQ(RM_OK, rm_unregister(handle2)); + + sleep(RM_TEST_SLEEP_TIME); + + RM_TEST_MSG("alloc_preference_n1 end..."); + +} + +TEST(ut_rm_api, alloc_preference_n2) +{ + /* + * 1. Allocate the following resources at once + * RM_CATEGORY_VIDEO_DECODER_HEVC_UHD_8BIT_30P with preference mode + * RM_CATEGORY_VIDEO_DECODER_HEVC_UHD_8BIT_60P with exclusive mode + * -> Alloc : fail + */ + + RM_TEST_MSG("alloc_preference_n2 start..."); + + conflicted = 0; + + int handle = 0; + + EXPECT_EQ(RM_OK, rm_register(conflict_cb3, NULL, &handle, NULL)); + + rm_category_request_s request; + memset(&request, 0, sizeof(rm_category_request_s)); + + rm_device_return_s return_devices; + memset(&return_devices, 0, sizeof(rm_device_return_s)); + + request.request_num = 2; + + request.category_id[0] = RM_CATEGORY_VIDEO_DECODER; + request.category_option[0] = RM_CATEGORY_VIDEO_DECODER_HEVC_UHD_8BIT_30P; + request.state[0] = RM_STATE_EXCLUSIVE_PREFERENCE; + + request.category_id[1] = RM_CATEGORY_VIDEO_DECODER; + request.category_option[1] = RM_CATEGORY_VIDEO_DECODER_HEVC_UHD_8BIT_60P; + request.state[1] = RM_STATE_EXCLUSIVE; + + EXPECT_NE(RM_OK, rm_allocate_resources(handle, &request, &return_devices)); + + EXPECT_EQ(0, return_devices.allocated_num); + EXPECT_EQ(RM_DEVICE_NONE, return_devices.device_id[0]); + EXPECT_EQ(RM_DEVICE_NONE, return_devices.device_id[1]); + + EXPECT_EQ(0, conflicted); + conflicted = 0; + + EXPECT_EQ(RM_OK, rm_unregister(handle)); + + sleep(RM_TEST_SLEEP_TIME); + + RM_TEST_MSG("alloc_preference_n2 end..."); + +} + + + +TEST(ut_rm_api, alloc_audio_dec_with_legacy_method_p1) +{ + /* + * 1. Allocate an Audio decoder with Legacy method (app_id : app1) -> Alloc : No conflict : Main audio decoder + * 2. Allocate an Audio decoder with Legacy method (app_id : app2) -> Alloc : Conflict with handle#1 : Main audio decoder + * 3. Allocate an Audio decoder with Legacy method (app_id : app3) -> Alloc : Conflict with handle#2 : Main audio decoder + */ + + RM_TEST_MSG("alloc_audio_dec_with_legacy_method_p1 start..."); + + int handle = 0; + + conflicted = 0; + + EXPECT_EQ(RM_OK, rm_register(conflict_cb3, NULL, &handle, NULL)); + + rm_category_request_s request; + memset(&request, 0, sizeof(rm_category_request_s)); + + request.request_num = 1; + request.category_id[0] = RM_CATEGORY_AUDIO_DECODER; + request.state[0] = RM_STATE_EXCLUSIVE; + + rm_device_return_s allocated; + memset(&allocated, 0, sizeof(rm_device_return_s)); + + const char *app_id1 = "app1"; + + EXPECT_EQ(RM_OK, rm_set_app_id(handle, (char*) app_id1)); + EXPECT_EQ(RM_OK, rm_allocate_resources(handle, &request, &allocated)); + EXPECT_EQ(RM_DEVICE_AUDIO_DECODER, allocated.device_id[0]); + EXPECT_EQ(1, allocated.allocated_num); + EXPECT_EQ(0, conflicted); + conflicted = 0; + + int handle2 = 0; + + EXPECT_EQ(RM_OK, rm_register(conflict_cb3, NULL, &handle2, NULL)); + + memset(&request, 0, sizeof(rm_category_request_s)); + + request.request_num = 1; + request.category_id[0] = RM_CATEGORY_AUDIO_DECODER; + request.state[0] = RM_STATE_EXCLUSIVE; + + const char *app_id2 = "app2"; + + EXPECT_EQ(RM_OK, rm_set_app_id(handle2, (char*) app_id2)); + EXPECT_EQ(RM_OK, rm_allocate_resources(handle2, &request, &allocated)); + EXPECT_EQ(RM_DEVICE_AUDIO_DECODER, allocated.device_id[0]); + EXPECT_EQ(1, allocated.allocated_num); + EXPECT_EQ(1, conflicted); + conflicted = 0; + + int handle3 = 0; + + EXPECT_EQ(RM_OK, rm_register(conflict_cb3, NULL, &handle3, NULL)); + + memset(&request, 0, sizeof(rm_category_request_s)); + + request.request_num = 1; + request.category_id[0] = RM_CATEGORY_AUDIO_DECODER; + request.state[0] = RM_STATE_EXCLUSIVE; + + const char *app_id3 = "app3"; + + EXPECT_EQ(RM_OK, rm_set_app_id(handle3, (char*) app_id3)); + EXPECT_EQ(RM_OK, rm_allocate_resources(handle3, &request, &allocated)); + EXPECT_EQ(RM_DEVICE_AUDIO_DECODER, allocated.device_id[0]); + EXPECT_EQ(1, allocated.allocated_num); + EXPECT_EQ(1, conflicted); + conflicted = 0; + + sleep(RM_TEST_SLEEP_TIME); + + EXPECT_EQ(RM_OK, rm_unregister(handle)); + EXPECT_EQ(RM_OK, rm_unregister(handle2)); + EXPECT_EQ(RM_OK, rm_unregister(handle3)); + + RM_TEST_MSG("alloc_audio_dec_with_legacy_method_p1 end..."); +} + +TEST(ut_rm_api, alloc_audio_dec_with_legacy_method_p2) +{ + /* + * 1. Allocate a sub Audio decoder with Legacy method (app_id : app1) -> Alloc : No conflict : Sub audio decoder + * 2. Allocate a sub Audio decoder with Legacy method (app_id : app2) -> Alloc : Conflict with handle#1 : Sub audio decoder + * 3. Allocate a sub Audio decoder with Legacy method (app_id : app3) -> Alloc : Conflict with handle#2 : Sub audio decoder + */ + + RM_TEST_MSG("alloc_audio_dec_with_legacy_method_p2 start..."); + + int handle = 0; + + conflicted = 0; + + EXPECT_EQ(RM_OK, rm_register(conflict_cb3, NULL, &handle, NULL)); + + rm_category_request_s request; + memset(&request, 0, sizeof(rm_category_request_s)); + + request.request_num = 1; + request.category_id[0] = RM_CATEGORY_AUDIO_DECODER_SUB; + request.state[0] = RM_STATE_EXCLUSIVE; + + rm_device_return_s allocated; + memset(&allocated, 0, sizeof(rm_device_return_s)); + + const char *app_id1 = "app1"; + + EXPECT_EQ(RM_OK, rm_set_app_id(handle, (char*) app_id1)); + EXPECT_EQ(RM_OK, rm_allocate_resources(handle, &request, &allocated)); + EXPECT_EQ(RM_DEVICE_AUDIO_DECODER_SUB, allocated.device_id[0]); + EXPECT_EQ(1, allocated.allocated_num); + EXPECT_EQ(0, conflicted); + conflicted = 0; + + int handle2 = 0; + + EXPECT_EQ(RM_OK, rm_register(conflict_cb3, NULL, &handle2, NULL)); + + memset(&request, 0, sizeof(rm_category_request_s)); + + request.request_num = 1; + request.category_id[0] = RM_CATEGORY_AUDIO_DECODER_SUB; + request.state[0] = RM_STATE_EXCLUSIVE; + + const char *app_id2 = "app2"; + + EXPECT_EQ(RM_OK, rm_set_app_id(handle2, (char*) app_id2)); + EXPECT_EQ(RM_OK, rm_allocate_resources(handle2, &request, &allocated)); + EXPECT_EQ(RM_DEVICE_AUDIO_DECODER_SUB, allocated.device_id[0]); + EXPECT_EQ(1, allocated.allocated_num); + EXPECT_EQ(1, conflicted); + conflicted = 0; + + int handle3 = 0; + + EXPECT_EQ(RM_OK, rm_register(conflict_cb3, NULL, &handle3, NULL)); + + memset(&request, 0, sizeof(rm_category_request_s)); + + request.request_num = 1; + request.category_id[0] = RM_CATEGORY_AUDIO_DECODER_SUB; + request.state[0] = RM_STATE_EXCLUSIVE; + + const char *app_id3 = "app3"; + + EXPECT_EQ(RM_OK, rm_set_app_id(handle3, (char*) app_id3)); + EXPECT_EQ(RM_OK, rm_allocate_resources(handle3, &request, &allocated)); + EXPECT_EQ(RM_DEVICE_AUDIO_DECODER_SUB, allocated.device_id[0]); + EXPECT_EQ(1, allocated.allocated_num); + EXPECT_EQ(1, conflicted); + conflicted = 0; + + sleep(RM_TEST_SLEEP_TIME); + + EXPECT_EQ(RM_OK, rm_unregister(handle)); + EXPECT_EQ(RM_OK, rm_unregister(handle2)); + EXPECT_EQ(RM_OK, rm_unregister(handle3)); + + RM_TEST_MSG("alloc_audio_dec_with_legacy_method_p2 end..."); +} + +TEST(ut_rm_api, alloc_audio_dec_with_legacy_method_p3) +{ + /* + * 1. Allocate a main Audio decoder with Legacy method (app_id : app1) -> Alloc : No conflict : Main audio decoder + * 2. Allocate a sub Audio decoder with Legacy method (app_id : app2) -> Alloc : No conflict : Sub audio decoder + * 3. Allocate a main Audio decoder with Legacy method (app_id : app3) -> Alloc : Conflict with handle#1 : Main audio decoder + */ + + RM_TEST_MSG("alloc_audio_dec_with_legacy_method_p3 start..."); + + int handle = 0; + + conflicted = 0; + + EXPECT_EQ(RM_OK, rm_register(conflict_cb3, NULL, &handle, NULL)); + + rm_category_request_s request; + memset(&request, 0, sizeof(rm_category_request_s)); + + request.request_num = 1; + request.category_id[0] = RM_CATEGORY_AUDIO_DECODER; + request.state[0] = RM_STATE_EXCLUSIVE; + + rm_device_return_s allocated; + memset(&allocated, 0, sizeof(rm_device_return_s)); + + const char *app_id1 = "app1"; + + EXPECT_EQ(RM_OK, rm_set_app_id(handle, (char*) app_id1)); + EXPECT_EQ(RM_OK, rm_allocate_resources(handle, &request, &allocated)); + EXPECT_EQ(RM_DEVICE_AUDIO_DECODER, allocated.device_id[0]); + EXPECT_EQ(1, allocated.allocated_num); + EXPECT_EQ(0, conflicted); + conflicted = 0; + + int handle2 = 0; + + EXPECT_EQ(RM_OK, rm_register(conflict_cb3, NULL, &handle2, NULL)); + + memset(&request, 0, sizeof(rm_category_request_s)); + + request.request_num = 1; + request.category_id[0] = RM_CATEGORY_AUDIO_DECODER_SUB; + request.state[0] = RM_STATE_EXCLUSIVE; + + const char *app_id2 = "app2"; + + EXPECT_EQ(RM_OK, rm_set_app_id(handle2, (char*) app_id2)); + EXPECT_EQ(RM_OK, rm_allocate_resources(handle2, &request, &allocated)); + EXPECT_EQ(RM_DEVICE_AUDIO_DECODER_SUB, allocated.device_id[0]); + EXPECT_EQ(1, allocated.allocated_num); + EXPECT_EQ(0, conflicted); + conflicted = 0; + + int handle3 = 0; + + EXPECT_EQ(RM_OK, rm_register(conflict_cb3, NULL, &handle3, NULL)); + + memset(&request, 0, sizeof(rm_category_request_s)); + + request.request_num = 1; + request.category_id[0] = RM_CATEGORY_AUDIO_DECODER; + request.state[0] = RM_STATE_EXCLUSIVE; + + const char *app_id3 = "app3"; + + EXPECT_EQ(RM_OK, rm_set_app_id(handle3, (char*) app_id3)); + EXPECT_EQ(RM_OK, rm_allocate_resources(handle3, &request, &allocated)); + EXPECT_EQ(RM_DEVICE_AUDIO_DECODER, allocated.device_id[0]); + EXPECT_EQ(1, allocated.allocated_num); + EXPECT_EQ(1, conflicted); + conflicted = 0; + + sleep(RM_TEST_SLEEP_TIME); + + EXPECT_EQ(RM_OK, rm_unregister(handle)); + EXPECT_EQ(RM_OK, rm_unregister(handle2)); + EXPECT_EQ(RM_OK, rm_unregister(handle3)); + + RM_TEST_MSG("alloc_audio_dec_with_legacy_method_p3 end..."); +} + + +rm_cb_result conflict_cb_count_num_of_conflicts(int handle, rm_callback_type event, rm_device_request_s *info, void *data) +{ + ++conflicted; + num_of_dealloc_rsc = info->request_num; + + EXPECT_EQ(RM_OK, rm_deallocate_resources(handle, info)); + return RM_CB_RESULT_OK; +} + +static int handle_during_reclaim; + +rm_cb_result conflict_cb_normal(int handle, rm_callback_type event, rm_device_request_s *info, void *data) +{ + EXPECT_EQ(RM_OK, rm_deallocate_resources(handle, info)); + return RM_CB_RESULT_OK; +} + +rm_cb_result conflict_cb_count_trying_to_register(int handle, rm_callback_type event, rm_device_request_s *info, void *data) +{ + EXPECT_EQ(RM_OK, rm_register(conflict_cb_normal, NULL, &handle_during_reclaim, NULL)); + EXPECT_EQ(RM_OK, rm_deallocate_resources(handle, info)); + return RM_CB_RESULT_OK; +} + +TEST(ut_rm_api, register_consumer_during_reclaim_p1) +{ + if (!is_support_4k()) + return; + + if (ri_get_max_video_decoder_num() >=4) + return; + + if (is_oscars_unified_jpeg_decoder()) + return; + + RM_TEST_MSG("register_consumer_during_reclaim_p1 start..."); + + int handle1 = 0; + conflicted = 0; + + EXPECT_EQ(RM_OK, rm_register(conflict_cb_count_trying_to_register, NULL, &handle1, NULL)); + + rm_category_request_s request; + memset(&request, 0, sizeof(rm_category_request_s)); + + ri_video_category_option_request_s option; + memset(&option, 0, sizeof(ri_video_category_option_request_s)); + + option.codec_name = "VP9"; + option.color_depth = 8; + option.framerate = 30; + option.h_size = 3840; + option.v_size = 2160; + option.sampling_format = RI_SAMPLING_FORMAT_420; + + request.request_num = 1; + request.category_id[0] = RM_CATEGORY_VIDEO_DECODER; + request.category_option[0] = ri_get_capable_video_category_id(&option); + request.state[0] = RM_STATE_EXCLUSIVE; + + rm_device_return_s allocated; + memset(&allocated, 0, sizeof(rm_device_return_s)); + + EXPECT_EQ(RM_OK, rm_allocate_resources(handle1, &request, &allocated)); + EXPECT_EQ(1, allocated.allocated_num); + EXPECT_EQ(RM_DEVICE_VIDEO_DECODER_DVDE0, allocated.device_id[0]); + EXPECT_EQ(0, conflicted); + conflicted = 0; + + int handle2 = 0; + EXPECT_EQ(RM_OK, rm_register(conflict_cb_normal, NULL, &handle2, NULL)); + + memset(&allocated, 0, sizeof(rm_device_return_s)); + + request.request_num = 1; + request.category_id[0] = RM_CATEGORY_VIDEO_DECODER; + request.category_option[0] = ri_get_capable_video_category_id(&option); + request.state[0] = RM_STATE_EXCLUSIVE; + + EXPECT_EQ(RM_OK, rm_allocate_resources(handle2, &request, &allocated)); + EXPECT_EQ(1, allocated.allocated_num); + + EXPECT_EQ(RM_DEVICE_VIDEO_DECODER_DVDE0, allocated.device_id[0]); + EXPECT_EQ(0, conflicted); + conflicted = 0; + + memset(&allocated, 0, sizeof(rm_device_return_s)); + + request.request_num = 1; + request.category_id[0] = RM_CATEGORY_VIDEO_DECODER; + request.category_option[0] = ri_get_capable_video_category_id(&option); + request.state[0] = RM_STATE_EXCLUSIVE; + + EXPECT_EQ(RM_OK, rm_allocate_resources(handle_during_reclaim, &request, &allocated)); + EXPECT_EQ(1, allocated.allocated_num); + + EXPECT_EQ(RM_DEVICE_VIDEO_DECODER_DVDE0, allocated.device_id[0]); + conflicted = 0; + + EXPECT_EQ(RM_OK, rm_unregister(handle1)); + EXPECT_EQ(RM_OK, rm_unregister(handle2)); + EXPECT_EQ(RM_OK, rm_unregister(handle_during_reclaim)); + + handle_during_reclaim = -1; + RM_TEST_MSG("register_consumer_during_reclaim_p1 end..."); +} + +static int handle_to_unregister; + +rm_cb_result conflict_cb_unregister_all_consumers(int handle, rm_callback_type event, rm_device_request_s *info, void *data) +{ + conflicted++; + rm_device_request_s rscs; + memset(&rscs, 0, sizeof(rm_device_request_s)); + rscs.request_num = 1; + rscs.device_id[0] = RM_DEVICE_AUDIO_MAIN_OUT; + + EXPECT_EQ(RM_OK, rm_deallocate_resources(handle_to_unregister, &rscs)); + EXPECT_EQ(RM_OK, rm_unregister(handle_to_unregister)); + EXPECT_EQ(RM_OK, rm_deallocate_resources(handle, info)); + EXPECT_EQ(RM_OK, rm_unregister(handle)); + return RM_CB_RESULT_OK; +} + +rm_cb_result conflict_cb_count(int handle, rm_callback_type event, rm_device_request_s *info, void *data) +{ + conflicted++; + EXPECT_EQ(RM_OK, rm_deallocate_resources(handle, info)); + return RM_CB_RESULT_OK; +} + +TEST(ut_rm_api, unregister_consumer_during_reclaim_p1) +{ + if (!is_support_4k()) + return; + + if (ri_get_max_video_decoder_num() >=4) + return; + + if (is_oscars_unified_jpeg_decoder()) + return; + + RM_TEST_MSG("unregister_consumer_during_reclaim_p1 start..."); + + int handle1 = 0; + conflicted = 0; + + EXPECT_EQ(RM_OK, rm_register(conflict_cb_unregister_all_consumers, NULL, &handle1, NULL)); + + rm_category_request_s request; + memset(&request, 0, sizeof(rm_category_request_s)); + + ri_video_category_option_request_s option; + memset(&option, 0, sizeof(ri_video_category_option_request_s)); + + option.codec_name = "VP9"; + option.color_depth = 8; + option.framerate = 30; + option.h_size = 3840; + option.v_size = 2160; + option.sampling_format = RI_SAMPLING_FORMAT_420; + + request.request_num = 1; + request.category_id[0] = RM_CATEGORY_VIDEO_DECODER; + request.category_option[0] = ri_get_capable_video_category_id(&option); + request.state[0] = RM_STATE_EXCLUSIVE; + + rm_device_return_s allocated; + memset(&allocated, 0, sizeof(rm_device_return_s)); + + EXPECT_EQ(RM_OK, rm_allocate_resources(handle1, &request, &allocated)); + EXPECT_EQ(1, allocated.allocated_num); + EXPECT_EQ(RM_DEVICE_VIDEO_DECODER_DVDE0, allocated.device_id[0]); + EXPECT_EQ(0, conflicted); + conflicted = 0; + + int handle2 = 0; + EXPECT_EQ(RM_OK, rm_register(conflict_cb_count, NULL, &handle2, NULL)); + handle_to_unregister = handle2; + + memset(&allocated, 0, sizeof(rm_device_return_s)); + + request.request_num = 1; + request.category_id[0] = RM_CATEGORY_AUDIO_MAIN_OUT; + request.state[0] = RM_STATE_EXCLUSIVE; + + EXPECT_EQ(RM_OK, rm_allocate_resources(handle2, &request, &allocated)); + EXPECT_EQ(1, allocated.allocated_num); + + EXPECT_EQ(RM_DEVICE_AUDIO_MAIN_OUT, allocated.device_id[0]); + EXPECT_EQ(0, conflicted); + conflicted = 0; + + int handle3 = 0; + EXPECT_EQ(RM_OK, rm_register(conflict_cb_normal, NULL, &handle3, NULL)); + + memset(&allocated, 0, sizeof(rm_device_return_s)); + + request.request_num = 2; + request.category_id[0] = RM_CATEGORY_VIDEO_DECODER; + request.category_option[0] = ri_get_capable_video_category_id(&option); + request.state[0] = RM_STATE_EXCLUSIVE; + request.category_id[1] = RM_CATEGORY_AUDIO_MAIN_OUT; + request.state[1] = RM_STATE_EXCLUSIVE; + + EXPECT_EQ(RM_OK, rm_allocate_resources(handle3, &request, &allocated)); + EXPECT_EQ(2, allocated.allocated_num); + EXPECT_EQ(1, conflicted); // because one of callbacks is not called + + EXPECT_EQ(RM_DEVICE_VIDEO_DECODER_DVDE0, allocated.device_id[0]); + EXPECT_EQ(RM_DEVICE_AUDIO_MAIN_OUT, allocated.device_id[1]); + conflicted = 0; + + EXPECT_NE(RM_OK, rm_unregister(handle1)); + EXPECT_NE(RM_OK, rm_unregister(handle2)); + EXPECT_EQ(RM_OK, rm_unregister(handle3)); + + handle_to_unregister = -1; + RM_TEST_MSG("unregister_consumer_during_reclaim_p1 end..."); +} + +TEST(ut_rm_api, ri_category_not_permitted_p1) +{ + RM_TEST_MSG("ri_category_not_permitted_p1 start..."); + + int handle; + EXPECT_EQ(0, rm_register(callback_default, NULL, &handle, NULL)); + + rm_category_request_s req; + memset(&req, 0, sizeof(rm_category_request_s)); + + req.request_num = 1; + req.category_id[0] = RM_CATEGORY_AUDIO_DECODER; + req.category_option[0] = RI_CATEGORY_NOT_PERMITTED; + req.state[0] = RM_STATE_EXCLUSIVE; + + rm_device_return_s allocated; + memset(&allocated, 0, sizeof(rm_device_return_s)); + + EXPECT_NE(0, rm_allocate_resources(handle, &req, &allocated)); + EXPECT_EQ(RM_ERR_TYPE_NOT_PERMITTED, allocated.error_type); + + EXPECT_EQ(RM_OK, rm_unregister(handle)); + RM_TEST_MSG("ri_category_not_permitted_p1 end..."); +} + +TEST(ut_rm_api, ri_category_not_permitted_p2) +{ + RM_TEST_MSG("ri_category_not_permitted_p2 start..."); + + int handle; + EXPECT_EQ(0, rm_register(callback_default, NULL, &handle, NULL)); + + rm_category_request_s req; + memset(&req, 0, sizeof(rm_category_request_s)); + + req.request_num = 1; + req.category_id[0] = RM_CATEGORY_AUDIO_MAIN_OUT; + req.category_option[0] = RI_CATEGORY_NOT_PERMITTED; + req.state[0] = RM_STATE_EXCLUSIVE; + + rm_device_return_s allocated; + memset(&allocated, 0, sizeof(rm_device_return_s)); + + EXPECT_NE(0, rm_allocate_resources(handle, &req, &allocated)); + EXPECT_EQ(RM_ERR_TYPE_NOT_PERMITTED, allocated.error_type); + + EXPECT_EQ(RM_OK, rm_unregister(handle)); + RM_TEST_MSG("ri_category_not_permitted_p2 end..."); +} + +TEST(ut_rm_api, ri_category_not_permitted_p3) +{ + RM_TEST_MSG("ri_category_not_permitted_p3 start..."); + + int handle; + EXPECT_EQ(0, rm_register(callback_default, NULL, &handle, NULL)); + + rm_category_request_s req; + memset(&req, 0, sizeof(rm_category_request_s)); + + req.request_num = 1; + req.category_id[0] = RM_CATEGORY_AUDIO_SUB_OUT; + req.category_option[0] = RI_CATEGORY_NOT_PERMITTED; + req.state[0] = RM_STATE_EXCLUSIVE; + + rm_device_return_s allocated; + memset(&allocated, 0, sizeof(rm_device_return_s)); + + EXPECT_NE(0, rm_allocate_resources(handle, &req, &allocated)); + EXPECT_EQ(RM_ERR_TYPE_NOT_PERMITTED, allocated.error_type); + + EXPECT_EQ(RM_OK, rm_unregister(handle)); + RM_TEST_MSG("ri_category_not_permitted_p3 end..."); +} + +static rm_cb_result callback_pending_5sec(int handle, rm_callback_type event, rm_device_request_s *info, void *data) +{ + sleep(5); + rm_deallocate_resources(handle, info); + + return RM_CB_RESULT_OK; +} + +static int n_state_checker = 0; +static gboolean _get_resource_state(gpointer data) +{ + rm_resource_state_e state; + EXPECT_EQ(RM_OK, rm_get_resource_state(RM_DEVICE_TUNER, &state)); + n_state_checker++; + RM_TEST_MSG("n_state_checker(%d)", n_state_checker); + sleep(1); + return (n_state_checker < 5) ? G_SOURCE_CONTINUE:G_SOURCE_REMOVE; +} + +TEST(ut_rm_api, ri_process_dbus_msg_during_conflict_p1) +{ + RM_TEST_MSG("ri_process_dbus_msg_during_conflict_p1 start..."); + + int handle; + EXPECT_EQ(RM_OK, rm_register(callback_pending_5sec, NULL, &handle, NULL)); + + rm_category_request_s req; + memset(&req, 0, sizeof(rm_category_request_s)); + + req.request_num = 1; + req.category_id[0] = RM_CATEGORY_TUNER; + req.state[0] = RM_STATE_EXCLUSIVE; + + rm_device_return_s allocated; + memset(&allocated, 0, sizeof(rm_device_return_s)); + + EXPECT_EQ(RM_OK, rm_allocate_resources(handle, &req, &allocated)); + + int handle2; + EXPECT_EQ(RM_OK, rm_register(callback_default, NULL, &handle2, NULL)); + + n_state_checker = 0; + //g_idle_add(_get_resource_state, NULL); + + GMainContext *context = get_callback_thread_context(); + GSource *idle_source = g_idle_source_new(); + + g_source_set_callback(idle_source, _get_resource_state, NULL, NULL); + g_source_attach(idle_source, context); + g_source_unref(idle_source); + + EXPECT_EQ(RM_OK, rm_allocate_resources(handle2, &req, &allocated)); + EXPECT_LT(3, n_state_checker); + + EXPECT_EQ(RM_OK, rm_unregister(handle)); + EXPECT_EQ(RM_OK, rm_unregister(handle2)); + + RM_TEST_MSG("ri_process_dbus_msg_during_conflict_p1 end..."); +} + +TEST(ut_rm_api, rm_get_app_id_p1) +{ + RM_TEST_MSG("rm_get_app_id_p1 start..."); + + int handle; + std::string app_id = "org.tizen.viewer"; + EXPECT_EQ(RM_OK, rm_register(conflict_cb, NULL, &handle, NULL)); + EXPECT_EQ(RM_OK, rm_set_app_id(handle, (char*) app_id.c_str())); + + char *app_id_ret = NULL; + EXPECT_EQ(RM_OK, rm_get_app_id(handle, &app_id_ret)); + EXPECT_STREQ(app_id.c_str(), app_id_ret); + + EXPECT_EQ(RM_OK, rm_unregister(handle)); + + RM_TEST_MSG("rm_get_app_id_p1 end..."); +} + +TEST(ut_rm_api, rm_get_app_id_p2) +{ + RM_TEST_MSG("rm_get_app_id_p2 start..."); + + int handle; + std::string bin_name = "resource-manager-ut"; + EXPECT_EQ(RM_OK, rm_register(conflict_cb, NULL, &handle, NULL)); + + char *app_id_ret = NULL; + EXPECT_EQ(RM_OK, rm_get_app_id(handle, &app_id_ret)); + EXPECT_STREQ(bin_name.c_str(), app_id_ret); + + EXPECT_EQ(RM_OK, rm_unregister(handle)); + + RM_TEST_MSG("rm_get_app_id_p2 end..."); +} + +TEST(ut_rm_api, rm_get_app_id_n1) +{ + RM_TEST_MSG("rm_get_app_id_n1 start..."); + + int handle = 78; + char *app_id_ret = NULL; + + EXPECT_NE(RM_OK, rm_get_app_id(handle, &app_id_ret)); + + RM_TEST_MSG("rm_get_app_id_n1 end..."); +} + +TEST(ut_rm_api, rm_allocate_resources_n1) +{ + RM_TEST_MSG("rm_get_app_id_n1 start..."); + + int handle; + EXPECT_EQ(RM_OK, rm_register(conflict_cb, NULL, &handle, NULL)); + + rm_category_request_s req; + memset(&req, 0, sizeof(rm_category_request_s)); + rm_device_return_s rscs; + memset(&rscs, 0, sizeof(rm_device_return_s)); + + req.request_num = 11; + req.category_id[0] = RM_CATEGORY_SCALER; + req.state[0] = RM_STATE_EXCLUSIVE; + + EXPECT_NE(RM_OK, rm_allocate_resources(handle, &req, &rscs)); + EXPECT_EQ(RM_OK, rm_unregister(handle)); + + RM_TEST_MSG("rm_get_app_id_n1 end..."); +} + +TEST(ut_rm_api, rm_deallocate_resources_n1) +{ + RM_TEST_MSG("rm_deallocate_resources_n1 start..."); + + int handle; + EXPECT_EQ(RM_OK, rm_register(conflict_cb, NULL, &handle, NULL)); + + rm_category_request_s req; + memset(&req, 0, sizeof(rm_category_request_s)); + rm_device_return_s rscs; + memset(&rscs, 0, sizeof(rm_device_return_s)); + + req.request_num = 1; + req.category_id[0] = RM_CATEGORY_SCALER; + req.state[0] = RM_STATE_EXCLUSIVE; + + EXPECT_EQ(RM_OK, rm_allocate_resources(handle, &req, &rscs)); + + rm_device_request_s req_rel; + memset(&req_rel, 0, sizeof(rm_device_request_s)); + + req_rel.request_num = 12; + req_rel.device_id[0] = RM_DEVICE_SCALER; + + EXPECT_NE(RM_OK, rm_deallocate_resources(handle, &req_rel)); + + EXPECT_EQ(RM_OK, rm_unregister(handle)); + + RM_TEST_MSG("rm_deallocate_resources_n1 end..."); +} + +TEST(ut_rm_api, rm_query_n1) +{ + RM_TEST_MSG("rm_query_n1 start..."); + + int handle; + int result; + + EXPECT_EQ(RM_OK, rm_register(conflict_cb, NULL, &handle, NULL)); + + rm_category_request_s req; + memset(&req, 0, sizeof(rm_category_request_s)); + + req.request_num = 11; + req.category_id[0] = RM_CATEGORY_SCALER; + req.state[0] = RM_STATE_EXCLUSIVE; + + EXPECT_NE(RM_OK, rm_query(handle, RM_QUERY_ALLOCATION, &req, &result)); + EXPECT_EQ(RM_OK, rm_unregister(handle)); + + RM_TEST_MSG("rm_query_n1 end..."); +} diff --git a/ut/testcase/ut_tc_8k.cpp b/ut/testcase/ut_tc_8k.cpp new file mode 100644 index 0000000..9d8d6e3 --- /dev/null +++ b/ut/testcase/ut_tc_8k.cpp @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2024 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 "gtest/gtest.h" +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +/* + * The test cases for 8K model. + * 1. 8K model specific features + */ + +TEST(ut_rm_api, dependency_between_8k_jpeg_decoder_and_bg_scaler) +{ + /* + * 1. Allocate a RI_CATEGORY_JPEG_DECODER_8K -> Alloc : No conflict + * 2. Allocate a RI_CATEGORY_SCALER_BG -> Alloc : (No conflict in 8K not supported model, conflict in 8k model) + */ + + RM_TEST_MSG("dependency_between_8k_jpeg_decoder_and_bg_scaler start..."); + + rm_tc_reset_conflict_num(); + rm_tc_reset_conflicted_resources_num(); + + // Allocate a RI_CATEGORY_JPEG_DECODER_8K + int handle1 = 0; + EXPECT_EQ(RM_OK, rm_register(rm_cb_counting_conflicted, NULL, &handle1, NULL)); + + rm_category_request_s request; + memset(&request, 0, sizeof(rm_category_request_s)); + + request.request_num = 1; + request.category_id[0] = RM_CATEGORY_JPEG_DECODER; + request.category_option[0] = ri_get_sub_jpeg_category_id("JPEG", 7680, 4320); + request.state[0] = RM_STATE_EXCLUSIVE; + + rm_device_return_s allocated; + memset(&allocated, 0, sizeof(rm_device_return_s)); + + EXPECT_EQ(RM_OK, rm_allocate_resources(handle1, &request, &allocated)); + EXPECT_EQ(0, rm_tc_get_conflict_num()); + + // Allocate a RI_CATEGORY_SCALER_BG + int handle2 = 0; + EXPECT_EQ(RM_OK, rm_register(rm_cb_counting_conflicted, NULL, &handle2, NULL)); + + memset(&request, 0, sizeof(rm_category_request_s)); + memset(&allocated, 0, sizeof(sizeof(rm_device_return_s))); + + request.request_num = 1; + request.category_id[0] = RM_CATEGORY_SCALER_BG; + request.category_option[0] = 0; + request.state[0] = RM_STATE_EXCLUSIVE; + + int expected_result = RM_OK; // bg scaler exists in 8k model only + int expected_conflict = 1; // bg scaler should be conflicted with 8k jpeg decoder + + EXPECT_EQ(expected_result, rm_allocate_resources(handle2, &request, &allocated)); + EXPECT_EQ(expected_conflict, rm_tc_get_conflict_num()); + + rm_tc_reset_conflict_num(); + + EXPECT_EQ(RM_OK, rm_unregister(handle1)); + EXPECT_EQ(RM_OK, rm_unregister(handle2)); + + sleep(RM_TEST_SLEEP_TIME); + + RM_TEST_MSG("dependency_between_8k_jpeg_decoder_and_bg_scaler end..."); +} diff --git a/ut/testcase/ut_tc_interaction_sound.cpp b/ut/testcase/ut_tc_interaction_sound.cpp new file mode 100644 index 0000000..760d395 --- /dev/null +++ b/ut/testcase/ut_tc_interaction_sound.cpp @@ -0,0 +1,1211 @@ +/* + * Copyright (c) 2024 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 "gtest/gtest.h" +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +TEST(ut_rm_api, allocate_audio_decoder_mpeg_InteractionSound) +{ + rm_tc_clear_audio_decoders(); + + /* + * 1. Allocate a RI_CATEGORY_AUDIO_DECODER_MPEG (appid : user1)-> Alloc : No conflict + * 2. Allocate a RI_CATEGORY_AUDIO_DECODER_MPEG (appid : user1)-> Alloc : No conflict + * 3. Allocate a RI_CATEGORY_AUDIO_DECODER_MPEG (appid : user1)-> Alloc : Conflict with handle#1 + */ + + RM_TEST_MSG("allocate_audio_decoder_mpeg_InteractionSound start..."); + + const char *app_id = "user1"; + rm_tc_reset_conflict_num(); + rm_tc_reset_conflicted_resources_num(); + + // Allocate a RI_CATEGORY_AUDIO_DECODER_MPEG + int handle1 = 0; + EXPECT_EQ(RM_OK, rm_register(rm_cb_set_conflict_flag, NULL, &handle1, NULL)); + EXPECT_EQ(RM_OK, rm_set_app_id(handle1, (char*)app_id)); + + rm_category_request_s *request = (rm_category_request_s*) malloc (sizeof(rm_category_request_s)); + memset((void*)request, 0, sizeof(rm_category_request_s)); + + ri_audio_category_option_request_s opt; + memset(&opt, 0, sizeof(ri_audio_category_option_request_s)); + + opt.codec_name = RI_AUDIO_CODEC_NAME_MPEG; + opt.mixing_mode = RI_MIXING_MODE_INTERACTION_SOUND; + + request->request_num = 1; + request->category_id[0] = RM_CATEGORY_AUDIO_DECODER; + request->category_option[0] = ri_get_capable_audio_category_id(&opt); + request->state[0] = RM_STATE_EXCLUSIVE; + + rm_device_return_s *allocated = (rm_device_return_s*) malloc (sizeof(rm_device_return_s)); + memset((void*)allocated, 0, sizeof(rm_device_return_s)); + + EXPECT_EQ(RM_OK, rm_allocate_resources(handle1, request, allocated)); + + EXPECT_EQ(0, rm_tc_get_conflict_num()); + + // Allocate a RI_CATEGORY_AUDIO_DECODER_MPEG + int handle2 = 0; + EXPECT_EQ(RM_OK, rm_register(rm_cb_set_conflict_flag, NULL, &handle2, NULL)); + EXPECT_EQ(RM_OK, rm_set_app_id(handle2, (char*)app_id)); + + //alloc + memset((void*)request, 0, sizeof(rm_category_request_s)); + memset(&opt, 0, sizeof(ri_audio_category_option_request_s)); + + opt.codec_name = RI_AUDIO_CODEC_NAME_MPEG; + opt.mixing_mode = RI_MIXING_MODE_INTERACTION_SOUND; + + request->request_num = 1; + request->category_id[0] = RM_CATEGORY_AUDIO_DECODER; + request->category_option[0] = ri_get_capable_audio_category_id(&opt); + request->state[0] = RM_STATE_EXCLUSIVE; + + memset((void*)allocated, 0, sizeof(rm_device_return_s)); + + EXPECT_EQ(RM_OK, rm_allocate_resources(handle2, request, allocated)); + + EXPECT_EQ(0, rm_tc_get_conflict_num()); + + // Allocate a RI_CATEGORY_AUDIO_DECODER_MPEG + + int handle3 = 0; + EXPECT_EQ(RM_OK, rm_register(rm_cb_set_conflict_flag, NULL, &handle3, NULL)); + EXPECT_EQ(RM_OK, rm_set_app_id(handle3, (char*)app_id)); + + //alloc + memset((void*)request, 0, sizeof(rm_category_request_s)); + memset(&opt, 0, sizeof(ri_audio_category_option_request_s)); + + opt.codec_name = RI_AUDIO_CODEC_NAME_MPEG; + opt.mixing_mode = RI_MIXING_MODE_INTERACTION_SOUND; + + request->request_num = 1; + request->category_id[0] = RM_CATEGORY_AUDIO_DECODER; + request->category_option[0] = ri_get_capable_audio_category_id(&opt); + request->state[0] = RM_STATE_EXCLUSIVE; + + memset((void*)allocated, 0, sizeof(rm_device_return_s)); + + EXPECT_EQ(RM_OK, rm_allocate_resources(handle3, request, allocated)); + EXPECT_EQ(1, rm_tc_get_conflict_num()); + rm_tc_reset_conflict_num(); + + EXPECT_EQ(RM_OK, rm_unregister(handle1)); + EXPECT_EQ(RM_OK, rm_unregister(handle2)); + EXPECT_EQ(RM_OK, rm_unregister(handle3)); + + sleep(RM_TEST_SLEEP_TIME); + + RM_TEST_MSG("allocate_audio_decoder_mpeg_InteractionSound end..."); +} + +TEST(ut_rm_api, allocate_audio_decoder_mpeg_with_differnt_type_of_resources_InteractionSound) +{ + /* + * 1. Allocate a RI_CATEGORY_AUDIO_DECODER_MPEG (appid : user1)-> Alloc : No conflict + * 2. Allocate a RI_CATEGORY_AUDIO_DECODER_MPEG (appid : user1)-> Alloc : No conflict + * 3. Allocate a RI_CATEGORY_AUDIO_DECODER_MPEG (appid : user1)-> Alloc : Conflict with handle#1 + */ + + RM_TEST_MSG("allocate_audio_decoder_mpeg_with_differnt_type_of_resources_InteractionSound start..."); + + const char *app_id = "user1"; + rm_tc_reset_conflict_num(); + rm_tc_reset_conflicted_resources_num(); + + // Allocate a RI_CATEGORY_AUDIO_DECODER_MPEG + int handle1 = 0; + EXPECT_EQ(RM_OK, rm_register(rm_cb_set_conflict_flag, NULL, &handle1, NULL)); + EXPECT_EQ(RM_OK, rm_set_app_id(handle1, (char*)app_id)); + + rm_category_request_s *request = (rm_category_request_s*) malloc (sizeof(rm_category_request_s)); + memset((void*)request, 0, sizeof(rm_category_request_s)); + + ri_audio_category_option_request_s opt; + memset(&opt, 0, sizeof(ri_audio_category_option_request_s)); + + opt.codec_name = RI_AUDIO_CODEC_NAME_MPEG; + opt.mixing_mode = RI_MIXING_MODE_INTERACTION_SOUND; + + request->request_num = 1; + request->category_id[0] = RM_CATEGORY_AUDIO_DECODER; + request->category_option[0] = ri_get_capable_audio_category_id(&opt); + request->state[0] = RM_STATE_EXCLUSIVE; + + rm_device_return_s *allocated = (rm_device_return_s*) malloc (sizeof(rm_device_return_s)); + memset((void*)allocated, 0, sizeof(rm_device_return_s)); + + EXPECT_EQ(RM_OK, rm_allocate_resources(handle1, request, allocated)); + + EXPECT_EQ(0, rm_tc_get_conflict_num()); + + // Allocate a RI_CATEGORY_AUDIO_DECODER_MPEG + int handle2 = 0; + EXPECT_EQ(RM_OK, rm_register(rm_cb_set_conflict_flag, NULL, &handle2, NULL)); + EXPECT_EQ(RM_OK, rm_set_app_id(handle2, (char*)app_id)); + + //alloc + memset((void*)request, 0, sizeof(rm_category_request_s)); + memset(&opt, 0, sizeof(ri_audio_category_option_request_s)); + + opt.codec_name = RI_AUDIO_CODEC_NAME_MPEG; + opt.mixing_mode = RI_MIXING_MODE_INTERACTION_SOUND; + + request->request_num = 1; + request->category_id[0] = RM_CATEGORY_AUDIO_DECODER; + request->category_option[0] = ri_get_capable_audio_category_id(&opt); + request->state[0] = RM_STATE_EXCLUSIVE; + + memset((void*)allocated, 0, sizeof(rm_device_return_s)); + + EXPECT_EQ(RM_OK, rm_allocate_resources(handle2, request, allocated)); + + EXPECT_EQ(0, rm_tc_get_conflict_num()); + + // Allocate a RI_CATEGORY_AUDIO_DECODER_MPEG + + int handle3 = 0; + EXPECT_EQ(RM_OK, rm_register(rm_cb_set_conflict_flag, NULL, &handle3, NULL)); + EXPECT_EQ(RM_OK, rm_set_app_id(handle3, (char*)app_id)); + + //alloc + memset((void*)request, 0, sizeof(rm_category_request_s)); + memset(&opt, 0, sizeof(ri_audio_category_option_request_s)); + + opt.codec_name = RI_AUDIO_CODEC_NAME_MPEG; + opt.mixing_mode = RI_MIXING_MODE_INTERACTION_SOUND; + + request->request_num = 1; + request->category_id[0] = RM_CATEGORY_AUDIO_DECODER; + request->category_option[0] = ri_get_capable_audio_category_id(&opt); + request->state[0] = RM_STATE_EXCLUSIVE; + + memset((void*)allocated, 0, sizeof(rm_device_return_s)); + + EXPECT_EQ(RM_OK, rm_allocate_resources(handle3, request, allocated)); + + EXPECT_EQ(1, rm_tc_get_conflict_num()); + rm_tc_reset_conflict_num(); + + EXPECT_EQ(RM_OK, rm_unregister(handle1)); + EXPECT_EQ(RM_OK, rm_unregister(handle2)); + EXPECT_EQ(RM_OK, rm_unregister(handle3)); + + sleep(RM_TEST_SLEEP_TIME); + + RM_TEST_MSG("allocate_audio_decoder_mpeg_with_differnt_type_of_resources_InteractionSound end..."); +} + + +TEST(ut_rm_api, allocate_audio_decoder_ac3_interactionSound) +{ + /* + * 1. Allocate a RI_CATEGORY_AUDIO_DECODER_AC3 (appid : user1) -> Alloc : No conflict + * 2. Allocate a RI_CATEGORY_AUDIO_DECODER_AC3 (appid : user1) -> Alloc : No conflict + * 3. Allocate a RI_CATEGORY_AUDIO_DECODER_AC3 (appid : user1) -> Alloc : Conflict with handle#1 + */ + + RM_TEST_MSG("allocate_audio_decoder_ac3_interactionSound start..."); + + const char *app_id = "user1"; + rm_tc_reset_conflict_num(); + rm_tc_reset_conflicted_resources_num(); + + // Allocate a RI_CATEGORY_AUDIO_DECODER_AC3 + int handle1 = 0; + EXPECT_EQ(RM_OK, rm_register(rm_cb_set_conflict_flag, NULL, &handle1, NULL)); + EXPECT_EQ(RM_OK, rm_set_app_id(handle1, (char*)app_id)); + + rm_category_request_s *request = (rm_category_request_s*) malloc (sizeof(rm_category_request_s)); + memset((void*)request, 0, sizeof(rm_category_request_s)); + + ri_audio_category_option_request_s opt; + memset(&opt, 0, sizeof(ri_audio_category_option_request_s)); + + opt.codec_name = RI_AUDIO_CODEC_NAME_AC3; + opt.mixing_mode = RI_MIXING_MODE_INTERACTION_SOUND; + + request->request_num = 1; + request->category_id[0] = RM_CATEGORY_AUDIO_DECODER; + request->category_option[0] = ri_get_capable_audio_category_id(&opt); + request->state[0] = RM_STATE_EXCLUSIVE; + + rm_device_return_s *allocated = (rm_device_return_s*) malloc (sizeof(rm_device_return_s)); + memset((void*)allocated, 0, sizeof(rm_device_return_s)); + + EXPECT_EQ(RM_OK, rm_allocate_resources(handle1, request, allocated)); + + EXPECT_EQ(0, rm_tc_get_conflict_num()); + + // Allocate a RI_CATEGORY_AUDIO_DECODER_AC3 + int handle2 = 0; + EXPECT_EQ(RM_OK, rm_register(rm_cb_set_conflict_flag, NULL, &handle2, NULL)); + EXPECT_EQ(RM_OK, rm_set_app_id(handle2, (char*)app_id)); + + //alloc + memset((void*)request, 0, sizeof(rm_category_request_s)); + memset(&opt, 0, sizeof(ri_audio_category_option_request_s)); + + opt.codec_name = RI_AUDIO_CODEC_NAME_AC3; + opt.mixing_mode = RI_MIXING_MODE_INTERACTION_SOUND; + + request->request_num = 1; + request->category_id[0] = RM_CATEGORY_AUDIO_DECODER; + request->category_option[0] = ri_get_capable_audio_category_id(&opt); + request->state[0] = RM_STATE_EXCLUSIVE; + + memset((void*)allocated, 0, sizeof(rm_device_return_s)); + + EXPECT_EQ(RM_OK, rm_allocate_resources(handle2, request, allocated)); + + EXPECT_EQ(0, rm_tc_get_conflict_num()); + + // Allocate a RI_CATEGORY_AUDIO_DECODER_AC3 + + int handle3 = 0; + EXPECT_EQ(RM_OK, rm_register(rm_cb_set_conflict_flag, NULL, &handle3, NULL)); + EXPECT_EQ(RM_OK, rm_set_app_id(handle3, (char*)app_id)); + + //alloc + memset((void*)request, 0, sizeof(rm_category_request_s)); + memset(&opt, 0, sizeof(ri_audio_category_option_request_s)); + + opt.codec_name = RI_AUDIO_CODEC_NAME_AC3; + opt.mixing_mode = RI_MIXING_MODE_INTERACTION_SOUND; + + request->request_num = 1; + request->category_id[0] = RM_CATEGORY_AUDIO_DECODER; + request->category_option[0] = ri_get_capable_audio_category_id(&opt); + request->state[0] = RM_STATE_EXCLUSIVE; + + memset((void*)allocated, 0, sizeof(rm_device_return_s)); + + EXPECT_EQ(RM_OK, rm_allocate_resources(handle3, request, allocated)); + + EXPECT_EQ(1, rm_tc_get_conflict_num()); + + EXPECT_EQ(RM_OK, rm_unregister(handle1)); + EXPECT_EQ(RM_OK, rm_unregister(handle2)); + EXPECT_EQ(RM_OK, rm_unregister(handle3)); + + sleep(RM_TEST_SLEEP_TIME); + + RM_TEST_MSG("allocate_audio_decoder_ac3_interactionSound end..."); +} + +TEST(ut_rm_api, allocate_audio_decoder_ac4_interactionSound) +{ + /* + * 1. Allocate a RI_CATEGORY_AUDIO_DECODER_AC4 (appid : user1) -> Alloc : No conflict + * 2. Allocate a RI_CATEGORY_AUDIO_DECODER_AC4 (appid : user1) -> Alloc : No conflict + */ + + RM_TEST_MSG("allocate_audio_decoder_ac4_interactionSound start..."); + + rm_tc_reset_conflict_num(); + rm_tc_reset_conflicted_resources_num(); + + // Allocate a RI_CATEGORY_AUDIO_DECODER_AC4 + int handle1 = 0; + EXPECT_EQ(RM_OK, rm_register(rm_cb_set_conflict_flag, NULL, &handle1, NULL)); + + rm_category_request_s *request = (rm_category_request_s*) malloc (sizeof(rm_category_request_s)); + memset((void*)request, 0, sizeof(rm_category_request_s)); + + ri_audio_category_option_request_s opt; + memset(&opt, 0, sizeof(ri_audio_category_option_request_s)); + + opt.codec_name = RI_AUDIO_CODEC_NAME_AC4; + opt.mixing_mode = RI_MIXING_MODE_INTERACTION_SOUND; + + request->request_num = 1; + request->category_id[0] = RM_CATEGORY_AUDIO_DECODER; + request->category_option[0] = ri_get_capable_audio_category_id(&opt); + request->state[0] = RM_STATE_EXCLUSIVE; + + rm_device_return_s *allocated = (rm_device_return_s*) malloc (sizeof(rm_device_return_s)); + memset((void*)allocated, 0, sizeof(rm_device_return_s)); + + EXPECT_EQ(RM_OK, rm_allocate_resources(handle1, request, allocated)); + EXPECT_EQ(0, rm_tc_get_conflict_num()); + + int handle2 = 0; + + EXPECT_EQ(RM_OK, rm_register(rm_cb_set_conflict_flag, NULL, &handle2, NULL)); + + memset((void*)request, 0, sizeof(rm_category_request_s)); + memset(&opt, 0, sizeof(ri_audio_category_option_request_s)); + + opt.codec_name = RI_AUDIO_CODEC_NAME_AC4; + opt.mixing_mode = RI_MIXING_MODE_INTERACTION_SOUND; + + request->request_num = 1; + request->category_id[0] = RM_CATEGORY_AUDIO_DECODER; + request->category_option[0] = ri_get_capable_audio_category_id(&opt); + request->state[0] = RM_STATE_EXCLUSIVE; + + memset((void*)allocated, 0, sizeof(rm_device_return_s)); + + EXPECT_EQ(RM_OK, rm_allocate_resources(handle2, request, allocated)); + EXPECT_EQ(0, rm_tc_get_conflict_num()); + + EXPECT_EQ(RM_OK, rm_unregister(handle1)); + EXPECT_EQ(RM_OK, rm_unregister(handle2)); + + sleep(RM_TEST_SLEEP_TIME); + + RM_TEST_MSG("allocate_audio_decoder_ac4_interactionSound end..."); +} + +TEST(ut_rm_api, allocate_audio_decoder_trueHD_interactionSound) +{ + /* + * 1. Allocate a RI_CATEGORY_AUDIO_DECODER_TRUEHD (appid : user1) -> Alloc : No conflict + * 2. Allocate a RI_CATEGORY_AUDIO_DECODER_TRUEHD (appid : user1) -> Alloc : No conflict + */ + + RM_TEST_MSG("allocate_audio_decoder_trueHD_interactionSound start..."); + + rm_tc_reset_conflict_num(); + rm_tc_reset_conflicted_resources_num(); + + // Allocate a RI_CATEGORY_AUDIO_DECODER_TRUEHD + int handle1 = 0; + EXPECT_EQ(RM_OK, rm_register(rm_cb_set_conflict_flag, NULL, &handle1, NULL)); + + rm_category_request_s *request = (rm_category_request_s*) malloc (sizeof(rm_category_request_s)); + memset((void*)request, 0, sizeof(rm_category_request_s)); + + ri_audio_category_option_request_s opt; + memset(&opt, 0, sizeof(ri_audio_category_option_request_s)); + + opt.codec_name = RI_AUDIO_CODEC_NAME_TRUEHD; + opt.mixing_mode = RI_MIXING_MODE_INTERACTION_SOUND; + + request->request_num = 1; + request->category_id[0] = RM_CATEGORY_AUDIO_DECODER; + request->category_option[0] = ri_get_capable_audio_category_id(&opt); + request->state[0] = RM_STATE_EXCLUSIVE; + + rm_device_return_s *allocated = (rm_device_return_s*) malloc (sizeof(rm_device_return_s)); + memset((void*)allocated, 0, sizeof(rm_device_return_s)); + + EXPECT_EQ(RM_OK, rm_allocate_resources(handle1, request, allocated)); + EXPECT_EQ(0, rm_tc_get_conflict_num()); + + int handle2 = 0; + + EXPECT_EQ(RM_OK, rm_register(rm_cb_set_conflict_flag, NULL, &handle2, NULL)); + + memset((void*)request, 0, sizeof(rm_category_request_s)); + memset(&opt, 0, sizeof(ri_audio_category_option_request_s)); + + opt.codec_name = RI_AUDIO_CODEC_NAME_TRUEHD; + opt.mixing_mode = RI_MIXING_MODE_INTERACTION_SOUND; + + request->request_num = 1; + request->category_id[0] = RM_CATEGORY_AUDIO_DECODER; + request->category_option[0] = ri_get_capable_audio_category_id(&opt); + request->state[0] = RM_STATE_EXCLUSIVE; + + memset((void*)allocated, 0, sizeof(rm_device_return_s)); + + EXPECT_EQ(RM_OK, rm_allocate_resources(handle2, request, allocated)); + EXPECT_EQ(0, rm_tc_get_conflict_num()); + + EXPECT_EQ(RM_OK, rm_unregister(handle1)); + EXPECT_EQ(RM_OK, rm_unregister(handle2)); + + sleep(RM_TEST_SLEEP_TIME); + + RM_TEST_MSG("allocate_audio_decoder_trueHD_interactionSound end..."); +} + +TEST(ut_rm_api, allocate_audio_decoder_PCM_interactionSound) +{ + /* + * 1. Allocate a RI_CATEGORY_AUDIO_DECODER_PCM -> Alloc : Alloc (Mixing mode is supported) + */ + + RM_TEST_MSG("allocate_audio_decoder_PCM_interactionSound start..."); + + rm_tc_reset_conflict_num(); + rm_tc_reset_conflicted_resources_num(); + + // Allocate a RI_CATEGORY_AUDIO_DECODER_PCM + int handle1 = 0; + EXPECT_EQ(RM_OK, rm_register(rm_cb_set_conflict_flag, NULL, &handle1, NULL)); + + rm_category_request_s *request = (rm_category_request_s*) malloc (sizeof(rm_category_request_s)); + memset((void*)request, 0, sizeof(rm_category_request_s)); + + ri_audio_category_option_request_s opt; + memset(&opt, 0, sizeof(ri_audio_category_option_request_s)); + + opt.codec_name = RI_AUDIO_CODEC_NAME_PCM; + opt.mixing_mode = RI_MIXING_MODE_INTERACTION_SOUND; + + request->request_num = 1; + request->category_id[0] = RM_CATEGORY_AUDIO_DECODER; + request->category_option[0] = ri_get_capable_audio_category_id(&opt); + request->state[0] = RM_STATE_EXCLUSIVE; + + rm_device_return_s *allocated = (rm_device_return_s*) malloc (sizeof(rm_device_return_s)); + memset((void*)allocated, 0, sizeof(rm_device_return_s)); + + EXPECT_EQ(RM_OK, rm_allocate_resources(handle1, request, allocated)); + EXPECT_EQ(0, rm_tc_get_conflict_num()); + + EXPECT_EQ(RM_OK, rm_unregister(handle1)); + + sleep(RM_TEST_SLEEP_TIME); + + RM_TEST_MSG("allocate_audio_decodallocate_audio_decoder_PCM_interactionSounder_PCM end..."); +} + + +TEST(ut_rm_api, allocate_audio_decoder_G2Cook_trueHD_interactionSound) +{ + /* + * 1. Allocate a RI_CATEGORY_AUDIO_DECODER_G2COOK -> Alloc : No conflict + */ + + RM_TEST_MSG("allocate_audio_decoder_G2Cook_trueHD_interactionSound start..."); + + rm_tc_reset_conflict_num(); + rm_tc_reset_conflicted_resources_num(); + + // Allocate a RI_CATEGORY_AUDIO_DECODER_G2COOK + int handle1 = 0; + EXPECT_EQ(RM_OK, rm_register(rm_cb_set_conflict_flag, NULL, &handle1, NULL)); + + rm_category_request_s *request = (rm_category_request_s*) malloc (sizeof(rm_category_request_s)); + memset((void*)request, 0, sizeof(rm_category_request_s)); + + ri_audio_category_option_request_s opt; + memset(&opt, 0, sizeof(ri_audio_category_option_request_s)); + + opt.codec_name = RI_AUDIO_CODEC_NAME_G2COOK; + opt.mixing_mode = RI_MIXING_MODE_INTERACTION_SOUND; + + request->request_num = 1; + request->category_id[0] = RM_CATEGORY_AUDIO_DECODER; + request->category_option[0] = ri_get_capable_audio_category_id(&opt); + request->state[0] = RM_STATE_EXCLUSIVE; + + rm_device_return_s *allocated = (rm_device_return_s*) malloc (sizeof(rm_device_return_s)); + memset((void*)allocated, 0, sizeof(rm_device_return_s)); + + EXPECT_EQ(RM_OK, rm_allocate_resources(handle1, request, allocated)); + + EXPECT_EQ(0, rm_tc_get_conflict_num()); + + EXPECT_EQ(RM_OK, rm_unregister(handle1)); + + sleep(RM_TEST_SLEEP_TIME); + + RM_TEST_MSG("allocate_audio_decoder_G2Cook_trueHD_interactionSound end..."); +} + +TEST(ut_rm_api, allocate_audio_decoder_G2Cook_trueHD2_interactionSound) +{ + /* + * 1. Allocate a RI_CATEGORY_AUDIO_DECODER_G2COOK -> Alloc (appid : user1) : No conflict + * 2. Allocate a RI_CATEGORY_AUDIO_DECODER_G2COOK -> Alloc (appid : user1) : No conflict + * 3. Allocate a RI_CATEGORY_AUDIO_DECODER_TRUEHD -> Alloc (appid : user2) : Alloc conflict with consumer#1 + */ + + RM_TEST_MSG("allocate_audio_decoder_G2Cook_trueHD2_interactionSound start..."); + + rm_tc_reset_conflict_num(); + rm_tc_reset_conflicted_resources_num(); + const char *app_id1 = "user1"; + const char *app_id2 = "user2"; + + // Allocate a RI_CATEGORY_AUDIO_DECODER_G2COOK + int handle1 = 0; + EXPECT_EQ(RM_OK, rm_register(rm_cb_counting_conflicted, NULL, &handle1, NULL)); + EXPECT_EQ(RM_OK, rm_set_app_id(handle1, (char*)app_id1)); + + rm_category_request_s *request = (rm_category_request_s*) malloc (sizeof(rm_category_request_s)); + memset((void*)request, 0, sizeof(rm_category_request_s)); + + ri_audio_category_option_request_s opt; + memset(&opt, 0, sizeof(ri_audio_category_option_request_s)); + + opt.codec_name = RI_AUDIO_CODEC_NAME_G2COOK; + opt.mixing_mode = RI_MIXING_MODE_INTERACTION_SOUND; + + request->request_num = 1; + request->category_id[0] = RM_CATEGORY_AUDIO_DECODER; + request->category_option[0] = ri_get_capable_audio_category_id(&opt); + request->state[0] = RM_STATE_EXCLUSIVE; + + rm_device_return_s *allocated = (rm_device_return_s*) malloc (sizeof(rm_device_return_s)); + memset((void*)allocated, 0, sizeof(rm_device_return_s)); + + EXPECT_EQ(RM_OK, rm_allocate_resources(handle1, request, allocated)); + + EXPECT_EQ(0, rm_tc_get_conflict_num()); + + // Allocate a RI_CATEGORY_AUDIO_DECODER_G2COOK + int handle2 = 0; + EXPECT_EQ(RM_OK, rm_register(rm_cb_counting_conflicted, NULL, &handle2, NULL)); + EXPECT_EQ(RM_OK, rm_set_app_id(handle2, (char*) app_id1)); + + //alloc + memset((void*)request, 0, sizeof(rm_category_request_s)); + memset(&opt, 0, sizeof(ri_audio_category_option_request_s)); + + opt.codec_name = RI_AUDIO_CODEC_NAME_G2COOK; + opt.mixing_mode = RI_MIXING_MODE_INTERACTION_SOUND; + + request->request_num = 1; + request->category_id[0] = RM_CATEGORY_AUDIO_DECODER; + request->category_option[0] = ri_get_capable_audio_category_id(&opt); + request->state[0] = RM_STATE_EXCLUSIVE; + + memset((void*)allocated, 0, sizeof(rm_device_return_s)); + + EXPECT_EQ(RM_OK, rm_allocate_resources(handle2, request, allocated)); + + EXPECT_EQ(0, rm_tc_get_conflict_num()); + + // Allocate a RI_CATEGORY_AUDIO_DECODER_TRUEHD + + int handle3 = 0; + EXPECT_EQ(RM_OK, rm_register(rm_cb_set_conflict_flag, NULL, &handle3, NULL)); + EXPECT_EQ(RM_OK, rm_set_app_id(handle3, (char*)app_id2)); + + //alloc + memset((void*)request, 0, sizeof(rm_category_request_s)); + memset(&opt, 0, sizeof(ri_audio_category_option_request_s)); + + opt.codec_name = RI_AUDIO_CODEC_NAME_TRUEHD; + opt.mixing_mode = RI_MIXING_MODE_INTERACTION_SOUND; + + request->request_num = 1; + request->category_id[0] = RM_CATEGORY_AUDIO_DECODER; + request->category_option[0] = ri_get_capable_audio_category_id(&opt); + request->state[0] = RM_STATE_EXCLUSIVE; + + memset((void*)allocated, 0, sizeof(rm_device_return_s)); + + EXPECT_EQ(RM_OK, rm_allocate_resources(handle3, request, allocated)); + EXPECT_EQ(1, rm_tc_get_conflict_num()); + + EXPECT_EQ(RM_OK, rm_unregister(handle1)); + EXPECT_EQ(RM_OK, rm_unregister(handle2)); + EXPECT_EQ(RM_OK, rm_unregister(handle3)); + + sleep(RM_TEST_SLEEP_TIME); + + RM_TEST_MSG("allocate_audio_decoder_G2Cook_trueHD2_interactionSound end..."); +} + +TEST(ut_rm_api, allocate_audio_decoder_G2Cook_MPEG_interactionSound) +{ + /* + * 1. Allocate a RI_CATEGORY_AUDIO_DECODER_G2COOK -> Alloc (appid : user1) : No conflict + * 2. Allocate a RI_CATEGORY_AUDIO_DECODER_G2COOK -> Alloc (appid : user1) : No conflict + * 3. Allocate a RI_CATEGORY_AUDIO_DECODER_MPEG -> Alloc (appid : user2) : Alloc conflict with consumer#1 + */ + + RM_TEST_MSG("allocate_audio_decoder_G2Cook_MPEG_interactionSound start..."); + + rm_tc_reset_conflict_num(); + rm_tc_reset_conflicted_resources_num(); + const char *app_id1 = "user1"; + const char *app_id2 = "user2"; + + // Allocate a RI_CATEGORY_AUDIO_DECODER_G2COOK + int handle1 = 0; + EXPECT_EQ(RM_OK, rm_register(rm_cb_counting_conflicted, NULL, &handle1, NULL)); + EXPECT_EQ(RM_OK, rm_set_app_id(handle1, (char*)app_id1)); + + rm_category_request_s *request = (rm_category_request_s*) malloc (sizeof(rm_category_request_s)); + memset((void*)request, 0, sizeof(rm_category_request_s)); + + ri_audio_category_option_request_s opt; + memset(&opt, 0, sizeof(ri_audio_category_option_request_s)); + + opt.codec_name = RI_AUDIO_CODEC_NAME_G2COOK; + opt.mixing_mode = RI_MIXING_MODE_INTERACTION_SOUND; + + request->request_num = 1; + request->category_id[0] = RM_CATEGORY_AUDIO_DECODER; + request->category_option[0] = ri_get_capable_audio_category_id(&opt); + request->state[0] = RM_STATE_EXCLUSIVE; + + rm_device_return_s *allocated = (rm_device_return_s*) malloc (sizeof(rm_device_return_s)); + memset((void*)allocated, 0, sizeof(rm_device_return_s)); + + EXPECT_EQ(RM_OK, rm_allocate_resources(handle1, request, allocated)); + + EXPECT_EQ(0, rm_tc_get_conflict_num()); + + // Allocate a RI_CATEGORY_AUDIO_DECODER_G2COOK + int handle2 = 0; + EXPECT_EQ(RM_OK, rm_register(rm_cb_counting_conflicted, NULL, &handle2, NULL)); + EXPECT_EQ(RM_OK, rm_set_app_id(handle2, (char*) app_id1)); + + //alloc + memset((void*)request, 0, sizeof(rm_category_request_s)); + memset(&opt, 0, sizeof(ri_audio_category_option_request_s)); + + opt.codec_name = RI_AUDIO_CODEC_NAME_G2COOK; + opt.mixing_mode = RI_MIXING_MODE_INTERACTION_SOUND; + + request->request_num = 1; + request->category_id[0] = RM_CATEGORY_AUDIO_DECODER; + request->category_option[0] = ri_get_capable_audio_category_id(&opt); + request->state[0] = RM_STATE_EXCLUSIVE; + + memset((void*)allocated, 0, sizeof(rm_device_return_s)); + + EXPECT_EQ(RM_OK, rm_allocate_resources(handle2, request, allocated)); + + EXPECT_EQ(0, rm_tc_get_conflict_num()); + + // Allocate a RI_AUDIO_CODEC_NAME_MPEG + + int handle3 = 0; + EXPECT_EQ(RM_OK, rm_register(rm_cb_set_conflict_flag, NULL, &handle3, NULL)); + EXPECT_EQ(RM_OK, rm_set_app_id(handle3, (char*)app_id2)); + + //alloc + memset((void*)request, 0, sizeof(rm_category_request_s)); + memset(&opt, 0, sizeof(ri_audio_category_option_request_s)); + + opt.codec_name = RI_AUDIO_CODEC_NAME_MPEG; + opt.mixing_mode = RI_MIXING_MODE_INTERACTION_SOUND; + + request->request_num = 1; + request->category_id[0] = RM_CATEGORY_AUDIO_DECODER; + request->category_option[0] = ri_get_capable_audio_category_id(&opt); + request->state[0] = RM_STATE_EXCLUSIVE; + + memset((void*)allocated, 0, sizeof(rm_device_return_s)); + + EXPECT_EQ(RM_OK, rm_allocate_resources(handle3, request, allocated)); + + EXPECT_EQ(1, rm_tc_get_conflict_num()); + + EXPECT_EQ(RM_OK, rm_unregister(handle1)); + EXPECT_EQ(RM_OK, rm_unregister(handle2)); + EXPECT_EQ(RM_OK, rm_unregister(handle3)); + + sleep(RM_TEST_SLEEP_TIME); + + RM_TEST_MSG("allocate_audio_decoder_G2Cook_MPEG_interactionSound end..."); +} + +TEST(ut_rm_api, allocate_audio_decoder_MPEG_MPEG_interactionSound) +{ + /* + * 1. Allocate a RI_CATEGORY_AUDIO_DECODER_MPEG -> Alloc (appid : user1) : No conflict + * 2. Allocate a RI_CATEGORY_AUDIO_DECODER_MPEG -> Alloc (appid : user2) : No conflict + */ + + RM_TEST_MSG("allocate_audio_decoder_MPEG_MPEG_interactionSound start..."); + + rm_tc_reset_conflict_num(); + rm_tc_reset_conflicted_resources_num(); + const char *app_id1 = "user1"; + const char *app_id2 = "user2"; + + // Allocate a RI_CATEGORY_AUDIO_DECODER_MPEG + int handle1 = 0; + EXPECT_EQ(RM_OK, rm_register(rm_cb_counting_conflicted, NULL, &handle1, NULL)); + EXPECT_EQ(RM_OK, rm_set_app_id(handle1, (char*)app_id1)); + + rm_category_request_s *request = (rm_category_request_s*) malloc (sizeof(rm_category_request_s)); + memset((void*)request, 0, sizeof(rm_category_request_s)); + + ri_audio_category_option_request_s opt; + memset(&opt, 0, sizeof(ri_audio_category_option_request_s)); + + opt.codec_name = RI_AUDIO_CODEC_NAME_MPEG; + opt.mixing_mode = RI_MIXING_MODE_INTERACTION_SOUND; + + request->request_num = 1; + request->category_id[0] = RM_CATEGORY_AUDIO_DECODER; + request->category_option[0] = ri_get_capable_audio_category_id(&opt); + request->state[0] = RM_STATE_EXCLUSIVE; + + rm_device_return_s *allocated = (rm_device_return_s*) malloc (sizeof(rm_device_return_s)); + memset((void*)allocated, 0, sizeof(rm_device_return_s)); + + EXPECT_EQ(RM_OK, rm_allocate_resources(handle1, request, allocated)); + + EXPECT_EQ(0, rm_tc_get_conflict_num()); + + // Allocate a RI_AUDIO_CODEC_NAME_MPEG + + int handle3 = 0; + EXPECT_EQ(RM_OK, rm_register(rm_cb_set_conflict_flag, NULL, &handle3, NULL)); + EXPECT_EQ(RM_OK, rm_set_app_id(handle3, (char*)app_id2)); + + //alloc + memset((void*)request, 0, sizeof(rm_category_request_s)); + memset(&opt, 0, sizeof(ri_audio_category_option_request_s)); + + opt.codec_name = RI_AUDIO_CODEC_NAME_MPEG; + opt.mixing_mode = RI_MIXING_MODE_INTERACTION_SOUND; + + request->request_num = 1; + request->category_id[0] = RM_CATEGORY_AUDIO_DECODER; + request->category_option[0] = ri_get_capable_audio_category_id(&opt); + request->state[0] = RM_STATE_EXCLUSIVE; + + memset((void*)allocated, 0, sizeof(rm_device_return_s)); + + EXPECT_EQ(RM_OK, rm_allocate_resources(handle3, request, allocated)); + + EXPECT_EQ(0, rm_tc_get_conflict_num()); + + EXPECT_EQ(RM_OK, rm_unregister(handle1)); + EXPECT_EQ(RM_OK, rm_unregister(handle3)); + + sleep(RM_TEST_SLEEP_TIME); + + RM_TEST_MSG("allocate_audio_decoder_MPEG_MPEG_interactionSound end..."); +} + + +TEST(ut_rm_api, allocate_multi_audio_decoders_by_same_consumer1_interactionSound) +{ + /* + * 1. Allocate a RI_CATEGORY_AUDIO_DECODER_G2COOK with consumer id#1 -> Alloc : No conflict + * 2. Allocate a RI_CATEGORY_AUDIO_DECODER_ADPCM with consumer id#1 -> Alloc : No conflict + */ + + RM_TEST_MSG("allocate_multi_audio_decoders_by_same_consumer1_interactionSound start..."); + + rm_tc_reset_conflict_num(); + rm_tc_reset_conflicted_resources_num(); + const char *user_id = "user1"; + + // Allocate two RI_CATEGORY_AUDIO_DECODER_G2COOK + int handle1 = 0; + EXPECT_EQ(RM_OK, rm_register(rm_cb_counting_conflicted, NULL, &handle1, NULL)); + EXPECT_EQ(RM_OK, rm_set_app_id(handle1, (char*)user_id)); + + rm_category_request_s *request = (rm_category_request_s*) malloc (sizeof(rm_category_request_s)); + memset((void*)request, 0, sizeof(rm_category_request_s)); + + ri_audio_category_option_request_s opt; + memset(&opt, 0, sizeof(ri_audio_category_option_request_s)); + + opt.codec_name = RI_AUDIO_CODEC_NAME_G2COOK; + opt.mixing_mode = RI_MIXING_MODE_INTERACTION_SOUND; + + request->request_num = 1; + request->category_id[0] = RM_CATEGORY_AUDIO_DECODER; + request->category_option[0] = ri_get_capable_audio_category_id(&opt); + request->state[0] = RM_STATE_EXCLUSIVE; + + rm_device_return_s *allocated = (rm_device_return_s*) malloc (sizeof(rm_device_return_s)); + memset((void*)allocated, 0, sizeof(rm_device_return_s)); + + EXPECT_EQ(RM_OK, rm_allocate_resources(handle1, request, allocated)); + EXPECT_EQ(0, rm_tc_get_conflict_num()); + + + // Allocate a RI_CATEGORY_AUDIO_DECODER_ADPCM + memset((void*)request, 0, sizeof(rm_category_request_s)); + memset(&opt, 0, sizeof(ri_audio_category_option_request_s)); + + opt.codec_name = RI_AUDIO_CODEC_NAME_ADPCM; + opt.mixing_mode = RI_MIXING_MODE_INTERACTION_SOUND; + + request->request_num = 1; + request->category_id[0] = RM_CATEGORY_AUDIO_DECODER; + request->category_option[0] = ri_get_capable_audio_category_id(&opt); + request->state[0] = RM_STATE_EXCLUSIVE; + + memset((void*)allocated, 0, sizeof(rm_device_return_s)); + + EXPECT_EQ(RM_OK, rm_allocate_resources(handle1, request, allocated)); + EXPECT_EQ(0, rm_tc_get_conflict_num()); + + EXPECT_EQ(RM_OK, rm_unregister(handle1)); + + sleep(RM_TEST_SLEEP_TIME); + + RM_TEST_MSG("allocate_multi_audio_decoders_by_same_consumer1_interactionSound end..."); +} + +TEST(ut_rm_api, allocate_multi_audio_decoders_by_same_consumer2_interactionSound) +{ + /* + * 1. Allocate a RI_CATEGORY_AUDIO_DECODER_G2COOK with consumer id#1 -> Alloc : No conflict + * 2. Allocate a RI_CATEGORY_AUDIO_DECODER_G2COOK with consumer id#1 -> Alloc : No conflict + * 3. Allocate a RI_CATEGORY_AUDIO_DECODER_G2COOK with consumer id#1 -> Alloc : Fail + */ + + RM_TEST_MSG("allocate_multi_audio_decoders_by_same_consumer2_interactionSound start..."); + + rm_tc_reset_conflict_num(); + rm_tc_reset_conflicted_resources_num(); + const char *user_id = "user1"; + + // Allocate two RI_CATEGORY_AUDIO_DECODER_G2COOK + int handle1 = 0; + EXPECT_EQ(RM_OK, rm_register(rm_cb_counting_conflicted, NULL, &handle1, NULL)); + EXPECT_EQ(RM_OK, rm_set_app_id(handle1, (char*)user_id)); + + rm_category_request_s *request = (rm_category_request_s*) malloc (sizeof(rm_category_request_s)); + memset((void*)request, 0, sizeof(rm_category_request_s)); + + ri_audio_category_option_request_s opt; + memset(&opt, 0, sizeof(ri_audio_category_option_request_s)); + + opt.codec_name = RI_AUDIO_CODEC_NAME_G2COOK; + opt.mixing_mode = RI_MIXING_MODE_INTERACTION_SOUND; + + request->request_num = 2; + request->category_id[0] = RM_CATEGORY_AUDIO_DECODER; + request->category_option[0] = ri_get_capable_audio_category_id(&opt); + request->state[0] = RM_STATE_EXCLUSIVE; + + request->category_id[1] = RM_CATEGORY_AUDIO_DECODER; + request->category_option[1] = ri_get_capable_audio_category_id(&opt); + request->state[1] = RM_STATE_EXCLUSIVE; + + rm_device_return_s *allocated = (rm_device_return_s*) malloc (sizeof(rm_device_return_s)); + memset((void*)allocated, 0, sizeof(rm_device_return_s)); + + EXPECT_EQ(RM_OK, rm_allocate_resources(handle1, request, allocated)); + + EXPECT_EQ(0, rm_tc_get_conflict_num()); + + // Allocate a RI_CATEGORY_AUDIO_DECODER_G2COOK + //alloc + memset((void*)request, 0, sizeof(rm_category_request_s)); + memset(&opt, 0, sizeof(ri_audio_category_option_request_s)); + + opt.codec_name = RI_AUDIO_CODEC_NAME_G2COOK; + opt.mixing_mode = RI_MIXING_MODE_INTERACTION_SOUND; + + request->request_num = 1; + request->category_id[0] = RM_CATEGORY_AUDIO_DECODER; + request->category_option[0] = ri_get_capable_audio_category_id(&opt); + request->state[0] = RM_STATE_EXCLUSIVE; + + memset((void*)allocated, 0, sizeof(rm_device_return_s)); + + EXPECT_NE(RM_OK, rm_allocate_resources(handle1, request, allocated)); + EXPECT_EQ(0, rm_tc_get_conflict_num()); + + EXPECT_EQ(RM_OK, rm_unregister(handle1)); + + sleep(RM_TEST_SLEEP_TIME); + + RM_TEST_MSG("allocate_multi_audio_decoders_by_same_consumer2_interactionSound end..."); +} + +TEST(ut_rm_api, allocate_reclaim_resource_had_been_allocated_first_interactionSound) +{ + /* + * 1. Allocate a RI_CATEGORY_AUDIO_DECODER_G2COOK with consumer id#1 -> Alloc : No conflict -> main audio decoder + * 2. Allocate a RI_CATEGORY_AUDIO_DECODER_G2COOK with consumer id#2 -> Alloc : No conflict -> sub audio decoder + * 3. Release main audio decoder -> released + * 4. Allocate a RI_CATEGORY_AUDIO_DECODER_G2COOK with consumer id#3 -> Alloc : No conflict -> main audio decoder + * 5. Allocate a RI_CATEGORY_AUDIO_DECODER_G2COOK with consumer id#4 -> Alloc : conflict with handle#2 -> sub audio decoder + */ + + RM_TEST_MSG("allocate_reclaim_resource_had_been_allocated_first_interactionSound start..."); + + rm_tc_reset_conflict_num(); + rm_tc_reset_conflicted_resources_num(); + const char *user_id = "user1"; + + // Allocate two RI_CATEGORY_AUDIO_DECODER_G2COOK + int handle1 = 0; + EXPECT_EQ(RM_OK, rm_register(rm_cb_counting_conflicted, NULL, &handle1, NULL)); + EXPECT_EQ(RM_OK, rm_set_app_id(handle1, (char*)user_id)); + + rm_category_request_s *request = (rm_category_request_s*) malloc (sizeof(rm_category_request_s)); + memset((void*)request, 0, sizeof(rm_category_request_s)); + + ri_audio_category_option_request_s opt; + memset(&opt, 0, sizeof(ri_audio_category_option_request_s)); + + opt.codec_name = RI_AUDIO_CODEC_NAME_G2COOK; + opt.mixing_mode = RI_MIXING_MODE_INTERACTION_SOUND; + + request->request_num = 1; + request->category_id[0] = RM_CATEGORY_AUDIO_DECODER; + request->category_option[0] = ri_get_capable_audio_category_id(&opt); + request->state[0] = RM_STATE_EXCLUSIVE; + + rm_device_return_s *allocated = (rm_device_return_s*) malloc (sizeof(rm_device_return_s)); + memset((void*)allocated, 0, sizeof(rm_device_return_s)); + + EXPECT_EQ(RM_OK, rm_allocate_resources(handle1, request, allocated)); + EXPECT_EQ(RM_DEVICE_AUDIO_DECODER, allocated->device_id[0]); + EXPECT_EQ(0, rm_tc_get_conflict_num()); + + // Allocate a RI_CATEGORY_AUDIO_DECODER_G2COOK + + int handle2 = 0; + EXPECT_EQ(RM_OK, rm_register(rm_cb_counting_conflicted, NULL, &handle2, NULL)); + + memset((void*)request, 0, sizeof(rm_category_request_s)); + memset(&opt, 0, sizeof(ri_audio_category_option_request_s)); + + opt.codec_name = RI_AUDIO_CODEC_NAME_G2COOK; + opt.mixing_mode = RI_MIXING_MODE_INTERACTION_SOUND; + + request->request_num = 1; + request->category_id[0] = RM_CATEGORY_AUDIO_DECODER; + request->category_option[0] = ri_get_capable_audio_category_id(&opt); + request->state[0] = RM_STATE_EXCLUSIVE; + + memset((void*)allocated, 0, sizeof(rm_device_return_s)); + + EXPECT_EQ(RM_OK, rm_allocate_resources(handle2, request, allocated)); + EXPECT_EQ(RM_DEVICE_AUDIO_DECODER_SUB, allocated->device_id[0]); + EXPECT_EQ(0, rm_tc_get_conflict_num()); + + // release main audio decoder + EXPECT_EQ(RM_OK, rm_unregister(handle1)); + + int handle3 = 0; + EXPECT_EQ(RM_OK, rm_register(rm_cb_counting_conflicted, NULL, &handle3, NULL)); + + memset((void*)request, 0, sizeof(rm_category_request_s)); + memset(&opt, 0, sizeof(ri_audio_category_option_request_s)); + + opt.codec_name = RI_AUDIO_CODEC_NAME_G2COOK; + opt.mixing_mode = RI_MIXING_MODE_INTERACTION_SOUND; + + request->request_num = 1; + request->category_id[0] = RM_CATEGORY_AUDIO_DECODER; + request->category_option[0] = ri_get_capable_audio_category_id(&opt); + request->state[0] = RM_STATE_EXCLUSIVE; + + memset((void*)allocated, 0, sizeof(rm_device_return_s)); + + EXPECT_EQ(RM_OK, rm_allocate_resources(handle3, request, allocated)); + EXPECT_EQ(RM_DEVICE_AUDIO_DECODER, allocated->device_id[0]); + EXPECT_EQ(0, rm_tc_get_conflict_num()); + + int handle4 = 0; + EXPECT_EQ(RM_OK, rm_register(rm_cb_counting_conflicted, NULL, &handle4, NULL)); + + memset((void*)request, 0, sizeof(rm_category_request_s)); + memset(&opt, 0, sizeof(ri_audio_category_option_request_s)); + + opt.codec_name = RI_AUDIO_CODEC_NAME_G2COOK; + opt.mixing_mode = RI_MIXING_MODE_INTERACTION_SOUND; + + request->request_num = 1; + request->category_id[0] = RM_CATEGORY_AUDIO_DECODER; + request->category_option[0] = ri_get_capable_audio_category_id(&opt); + request->state[0] = RM_STATE_EXCLUSIVE; + + memset((void*)allocated, 0, sizeof(rm_device_return_s)); + + EXPECT_EQ(RM_OK, rm_allocate_resources(handle4, request, allocated)); + EXPECT_EQ(RM_DEVICE_AUDIO_DECODER_SUB, allocated->device_id[0]); + EXPECT_EQ(1, rm_tc_get_conflict_num()); + + EXPECT_EQ(RM_OK, rm_unregister(handle2)); + EXPECT_EQ(RM_OK, rm_unregister(handle3)); + EXPECT_EQ(RM_OK, rm_unregister(handle4)); + + sleep(RM_TEST_SLEEP_TIME); + + RM_TEST_MSG("allocate_reclaim_resource_had_been_allocated_first_interactionSound end..."); +} + + +TEST(ut_rm_api, allocate_multi_audio_decoders_by_same_consumer_at_once_interactionSound) +{ + /* + * 1. Allocate RI_CATEGORY_AUDIO_DECODER_G2COOK and RI_CATEGORY_AUDIO_DECODER_TRUEHD with consumer id#1 at once -> Alloc + */ + + RM_TEST_MSG("allocate_multi_audio_decoders_by_same_consumer_at_once_interactionSound start..."); + + rm_tc_reset_conflict_num(); + rm_tc_reset_conflicted_resources_num(); + const char *user_id = "user1"; + + // Allocate RI_CATEGORY_AUDIO_DECODER_G2COOK and RI_CATEGORY_AUDIO_DECODER_TRUEHD at once. + int handle1 = 0; + EXPECT_EQ(RM_OK, rm_register(rm_cb_counting_conflicted, NULL, &handle1, NULL)); + EXPECT_EQ(RM_OK, rm_set_app_id(handle1,(char*) user_id)); + + rm_category_request_s *request = (rm_category_request_s*) malloc (sizeof(rm_category_request_s)); + memset((void*)request, 0, sizeof(rm_category_request_s)); + + ri_audio_category_option_request_s opt; + memset(&opt, 0, sizeof(ri_audio_category_option_request_s)); + + opt.codec_name = RI_AUDIO_CODEC_NAME_G2COOK; + opt.mixing_mode = RI_MIXING_MODE_INTERACTION_SOUND; + + request->request_num = 2; + request->category_id[0] = RM_CATEGORY_AUDIO_DECODER; + request->category_option[0] = ri_get_capable_audio_category_id(&opt); + request->state[0] = RM_STATE_EXCLUSIVE; + + opt.codec_name = RI_AUDIO_CODEC_NAME_TRUEHD; + opt.mixing_mode = RI_MIXING_MODE_INTERACTION_SOUND; + + request->category_id[1] = RM_CATEGORY_AUDIO_DECODER; + request->category_option[1] = ri_get_capable_audio_category_id(&opt); + request->state[1] = RM_STATE_EXCLUSIVE; + + rm_device_return_s *allocated = (rm_device_return_s*) malloc (sizeof(rm_device_return_s)); + memset((void*)allocated, 0, sizeof(rm_device_return_s)); + + EXPECT_EQ(RM_OK, rm_allocate_resources(handle1, request, allocated)); + EXPECT_EQ(0, rm_tc_get_conflict_num()); + + EXPECT_EQ(RM_OK, rm_unregister(handle1)); + + sleep(RM_TEST_SLEEP_TIME); + + RM_TEST_MSG("allocate_multi_audio_decoders_by_same_consumer_at_once_interactionSound end..."); +} + +TEST(ut_rm_api, allocate_mixing_not_supported_codec_interactionSound) +{ + /* + * 1. Allocate RI_CATEGORY_AUDIO_DECODER_MPEG_H -> Alloc (Mixing is not supported but allocate) + */ + + RM_TEST_MSG("allocate_mixing_not_supported_codec_interactionSound start..."); + + rm_tc_reset_conflict_num(); + rm_tc_reset_conflicted_resources_num(); + const char *user_id = "user1"; + + // Allocate RI_CATEGORY_AUDIO_DECODER_MPEG_H + int handle1 = 0; + EXPECT_EQ(RM_OK, rm_register(rm_cb_counting_conflicted, NULL, &handle1, NULL)); + EXPECT_EQ(RM_OK, rm_set_app_id(handle1,(char*) user_id)); + + rm_category_request_s *request = (rm_category_request_s*) malloc (sizeof(rm_category_request_s)); + memset((void*)request, 0, sizeof(rm_category_request_s)); + + ri_audio_category_option_request_s opt; + memset(&opt, 0, sizeof(ri_audio_category_option_request_s)); + + opt.codec_name = RI_AUDIO_CODEC_NAME_MPEG_H; + opt.mixing_mode = RI_MIXING_MODE_INTERACTION_SOUND; + + request->request_num = 1; + request->category_id[0] = RM_CATEGORY_AUDIO_DECODER; + request->category_option[0] = ri_get_capable_audio_category_id(&opt); + request->state[0] = RM_STATE_EXCLUSIVE; + + rm_device_return_s *allocated = (rm_device_return_s*) malloc (sizeof(rm_device_return_s)); + memset((void*)allocated, 0, sizeof(rm_device_return_s)); + + EXPECT_EQ(RM_OK, rm_allocate_resources(handle1, request, allocated)); + EXPECT_EQ(0, rm_tc_get_conflict_num()); + + EXPECT_EQ(RM_OK, rm_unregister(handle1)); + + sleep(RM_TEST_SLEEP_TIME); + + RM_TEST_MSG("allocate_mixing_not_supported_codec_interactionSound end..."); +} + +TEST(ut_rm_api, allocate_mixing_not_supported_codec2_interactionSound) +{ + /* + * 1. Allocate RI_CATEGORY_AUDIO_DECODER_G2COOK -> Alloc + * 2. Allocate RI_CATEGORY_AUDIO_DECODER_MPEG_H -> Alloc conflict with handle#1 (Mixing is not supported) + */ + + RM_TEST_MSG("allocate_mixing_not_supported_codec2_interactionSound start..."); + + rm_tc_reset_conflict_num(); + rm_tc_reset_conflicted_resources_num(); + const char *user_id = "user1"; + + int handle1 = 0; + EXPECT_EQ(RM_OK, rm_register(rm_cb_counting_conflicted, NULL, &handle1, NULL)); + EXPECT_EQ(RM_OK, rm_set_app_id(handle1,(char*) user_id)); + + rm_category_request_s *request = (rm_category_request_s*) malloc (sizeof(rm_category_request_s)); + memset((void*)request, 0, sizeof(rm_category_request_s)); + + ri_audio_category_option_request_s opt; + memset(&opt, 0, sizeof(ri_audio_category_option_request_s)); + + opt.codec_name = RI_AUDIO_CODEC_NAME_G2COOK; + opt.mixing_mode = RI_MIXING_MODE_INTERACTION_SOUND; + + request->request_num = 1; + request->category_id[0] = RM_CATEGORY_AUDIO_DECODER; + request->category_option[0] = ri_get_capable_audio_category_id(&opt); + request->state[0] = RM_STATE_EXCLUSIVE; + + rm_device_return_s *allocated = (rm_device_return_s*) malloc (sizeof(rm_device_return_s)); + memset((void*)allocated, 0, sizeof(rm_device_return_s)); + + EXPECT_EQ(RM_OK, rm_allocate_resources(handle1, request, allocated)); + EXPECT_EQ(0, rm_tc_get_conflict_num()); + + int handle2 = 0; + EXPECT_EQ(RM_OK, rm_register(rm_cb_counting_conflicted, NULL, &handle2, NULL)); + EXPECT_EQ(RM_OK, rm_set_app_id(handle2, (char*) user_id)); + + memset((void*)request, 0, sizeof(rm_category_request_s)); + memset(&opt, 0, sizeof(ri_audio_category_option_request_s)); + + opt.codec_name = RI_AUDIO_CODEC_NAME_MPEG_H; + opt.mixing_mode = RI_MIXING_MODE_INTERACTION_SOUND; + + request->request_num = 1; + request->category_id[0] = RM_CATEGORY_AUDIO_DECODER; + request->category_option[0] = ri_get_capable_audio_category_id(&opt); + request->state[0] = RM_STATE_EXCLUSIVE; + + memset((void*)allocated, 0, sizeof(rm_device_return_s)); + + EXPECT_EQ(RM_OK, rm_allocate_resources(handle2, request, allocated)); + EXPECT_EQ(1, rm_tc_get_conflict_num()); + + EXPECT_EQ(RM_OK, rm_unregister(handle1)); + EXPECT_EQ(RM_OK, rm_unregister(handle2)); + + sleep(RM_TEST_SLEEP_TIME); + + RM_TEST_MSG("allocate_mixing_not_supported_codec2_interactionSound end..."); +} \ No newline at end of file diff --git a/ut/testcase/ut_tc_multiview.cpp b/ut/testcase/ut_tc_multiview.cpp new file mode 100644 index 0000000..740ece1 --- /dev/null +++ b/ut/testcase/ut_tc_multiview.cpp @@ -0,0 +1,691 @@ +/* + * Copyright (c) 2024 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 "gtest/gtest.h" +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + + +TEST(ut_rm_api, alloc_main_audio_dec_p1_multiview) +{ + /* + * 1. Allocate a RI_CATEGORY_AUDIO_DECODER_G2COOK with main option -> Alloc : No conflict + */ + + RM_TEST_MSG("alloc_main_audio_dec_p1_multiview start..."); + + int handle = 0; + + rm_tc_reset_conflict_num(); + + EXPECT_EQ(RM_OK, rm_register(rm_cb_counting_conflicted, NULL, &handle, NULL)); + + rm_category_request_s request; + memset(&request, 0, sizeof(rm_category_request_s)); + + ri_audio_category_option_request_s opt; + memset(&opt, 0, sizeof(ri_audio_category_option_request_s)); + + opt.codec_name = RI_AUDIO_CODEC_NAME_G2COOK; + opt.mixing_mode = RI_MIXING_MODE_MULTIVIEW; + + request.request_num = 1; + request.category_id[0] = RM_CATEGORY_AUDIO_DECODER; + request.category_option[0] = ri_get_capable_audio_category_id(&opt) | RM_DEVICE_OPT_MAIN; + request.state[0] = RM_STATE_EXCLUSIVE; + + rm_device_return_s allocated; + memset(&allocated, 0, sizeof(rm_device_return_s)); + + EXPECT_EQ(RM_OK, rm_allocate_resources(handle, &request, &allocated)); + EXPECT_EQ(RM_DEVICE_AUDIO_DECODER, allocated.device_id[0]); + EXPECT_EQ(1, allocated.allocated_num); + EXPECT_EQ(0, rm_tc_get_conflict_num()); + + rm_tc_reset_conflict_num(); + + sleep(RM_TEST_SLEEP_TIME); + + EXPECT_EQ(RM_OK, rm_unregister(handle)); + + RM_TEST_MSG("alloc_main_audio_dec_p1_multiview end..."); +} + +TEST(ut_rm_api, alloc_sub_audio_dec_p1_multiview) +{ + /* + * 1. Allocate a RI_CATEGORY_AUDIO_DECODER_G2COOK with sub option -> Alloc : No conflict + */ + + RM_TEST_MSG("alloc_sub_audio_dec_p1_multiview start..."); + + int handle = 0; + + rm_tc_reset_conflict_num(); + + EXPECT_EQ(RM_OK, rm_register(rm_cb_counting_conflicted, NULL, &handle, NULL)); + + rm_category_request_s request; + memset(&request, 0, sizeof(rm_category_request_s)); + + ri_audio_category_option_request_s opt; + memset(&opt, 0, sizeof(ri_audio_category_option_request_s)); + + opt.codec_name = RI_AUDIO_CODEC_NAME_G2COOK; + opt.mixing_mode = RI_MIXING_MODE_MULTIVIEW; + + request.request_num = 1; + request.category_id[0] = RM_CATEGORY_AUDIO_DECODER_SUB; + request.category_option[0] = ri_get_capable_audio_category_id(&opt) | RM_DEVICE_OPT_SUB; + request.state[0] = RM_STATE_EXCLUSIVE; + + rm_device_return_s allocated; + memset(&allocated, 0, sizeof(rm_device_return_s)); + + EXPECT_EQ(RM_OK, rm_allocate_resources(handle, &request, &allocated)); + EXPECT_EQ(RM_DEVICE_AUDIO_DECODER_SUB, allocated.device_id[0]); + EXPECT_EQ(1, allocated.allocated_num); + EXPECT_EQ(0, rm_tc_get_conflict_num()); + + rm_tc_reset_conflict_num(); + + sleep(RM_TEST_SLEEP_TIME); + + EXPECT_EQ(RM_OK, rm_unregister(handle)); + + RM_TEST_MSG("alloc_sub_audio_dec_p1_multiview end..."); +} + +TEST(ut_rm_api, alloc_three_video_decoders_in_multiview_p1) +{ + rm_tc_clear_video_decoders(); + + RM_TEST_MSG("alloc_three_video_decoders_in_multiview_p1 start..."); + + int handle1 = 0; + rm_tc_reset_conflict_num(); + + EXPECT_EQ(RM_OK, rm_register(rm_cb_counting_conflicted, NULL, &handle1, NULL)); + + rm_category_request_s request; + memset(&request, 0, sizeof(rm_category_request_s)); + + ri_video_category_option_request_s option; + memset(&option, 0, sizeof(ri_video_category_option_request_s)); + + option.codec_name = "H264"; + option.color_depth = 8; + option.framerate = 30; + option.h_size = 1920; + option.v_size = 1080; + option.sampling_format = RI_SAMPLING_FORMAT_420; + + request.request_num = 2; + request.category_id[0] = RM_CATEGORY_VIDEO_DECODER; + request.category_option[0] = 0; + request.state[0] = RM_STATE_EXCLUSIVE; + + request.category_id[1] = RM_CATEGORY_SCALER; + request.state[1] = RM_STATE_EXCLUSIVE; + + rm_device_return_s allocated; + memset(&allocated, 0, sizeof(rm_device_return_s)); + + EXPECT_EQ(RM_OK, rm_allocate_resources(handle1, &request, &allocated)); + EXPECT_EQ(2, allocated.allocated_num); + // The mfc0 shall be allocated first + EXPECT_EQ(RM_DEVICE_VIDEO_DECODER_MAIN, allocated.device_id[0]); + EXPECT_EQ(0, rm_tc_get_conflict_num()); + rm_tc_reset_conflict_num(); + + rm_device_request_s req_rel; + memset(&req_rel, 0, sizeof(rm_device_request_s)); + + req_rel.request_num = 1; + req_rel.device_id[0] = allocated.device_id[1]; + + EXPECT_EQ(RM_OK, rm_deallocate_resources(handle1, &req_rel)); + + int handle2 = 0; + EXPECT_EQ(RM_OK, rm_register(rm_cb_counting_conflicted, NULL, &handle2, NULL)); + + memset(&allocated, 0, sizeof(rm_device_return_s)); + + request.request_num = 2; + request.category_id[0] = RM_CATEGORY_VIDEO_DECODER; + request.category_option[0] = ri_get_capable_video_category_id(&option); + request.state[0] = RM_STATE_EXCLUSIVE; + + request.category_id[1] = RM_CATEGORY_SCALER_SUB; + request.state[1] = RM_STATE_EXCLUSIVE; + + EXPECT_EQ(RM_OK, rm_allocate_resources(handle2, &request, &allocated)); + EXPECT_EQ(2, allocated.allocated_num); + + // The mfc1 shall be allocated later + EXPECT_EQ(RM_DEVICE_VIDEO_DECODER_SUB, allocated.device_id[0]); + EXPECT_EQ(RI_VIRTUAL_ID_SCALER + 1, allocated.device_id[1]); + EXPECT_EQ(RM_DEVICE_SCALER_SUB, rm_find_device_id(allocated.device_id[1])); + EXPECT_EQ(0, rm_tc_get_conflict_num()); + rm_tc_reset_conflict_num(); + + int handle3 = 0; + EXPECT_EQ(RM_OK, rm_register(rm_cb_counting_conflicted, NULL, &handle3, NULL)); + + memset(&allocated, 0, sizeof(rm_device_return_s)); + + request.request_num = 2; + request.category_id[0] = RM_CATEGORY_VIDEO_DECODER_SUB; + request.category_option[0] = (ri_get_capable_video_category_id(&option) | RM_DEVICE_OPT_SUB); + request.state[0] = RM_STATE_EXCLUSIVE; + + request.category_id[1] = RM_CATEGORY_SCALER_SUB; + request.state[1] = RM_STATE_EXCLUSIVE; + + EXPECT_EQ(RM_OK, rm_allocate_resources(handle3, &request, &allocated)); + EXPECT_EQ(2, allocated.allocated_num); + + // The mfc0 shall be allocated + EXPECT_EQ(RM_DEVICE_VIDEO_DECODER_SUB, allocated.device_id[0]); + EXPECT_EQ(RI_VIRTUAL_ID_SCALER + 1, allocated.device_id[1]); + EXPECT_EQ(RM_DEVICE_SCALER_SUB, rm_find_device_id(allocated.device_id[1])); + EXPECT_EQ(1, rm_tc_get_conflict_num()); + rm_tc_reset_conflict_num(); + + EXPECT_EQ(RM_OK, rm_unregister(handle1)); + EXPECT_EQ(RM_OK, rm_unregister(handle2)); + EXPECT_EQ(RM_OK, rm_unregister(handle3)); + + RM_TEST_MSG("alloc_three_video_decoders_in_multiview_p1 end..."); +} + +TEST(ut_rm_api, multiview_audio_decoder_conflict_p2) +{ + RM_TEST_MSG("multiview_audio_decoder_conflict_p2 start..."); + + rm_tc_reset_conflict_num(); + + int handle1; + EXPECT_EQ(RM_OK, rm_register(rm_cb_counting_conflicted, NULL, &handle1, NULL)); + + rm_category_request_s request; + memset(&request, 0, sizeof(rm_category_request_s)); + + request.request_num = 1; + request.category_id[0] = RM_CATEGORY_AUDIO_DECODER; + request.category_option[0] = (RI_CATEGORY_AUDIO_DECODER_AAC | RM_DEVICE_OPT_MAIN); + request.state[0] = RM_STATE_EXCLUSIVE; + + rm_device_return_s allocated; + memset(&allocated, 0, sizeof(rm_device_return_s)); + + EXPECT_EQ(RM_OK, rm_allocate_resources(handle1, &request, &allocated)); + EXPECT_EQ(1, allocated.allocated_num); + EXPECT_EQ(RM_DEVICE_AUDIO_DECODER, allocated.device_id[0]); + EXPECT_EQ(0, rm_tc_get_conflict_num()); + + sleep(2); + + rm_tc_reset_conflict_num(); + int handle2; + EXPECT_EQ(RM_OK, rm_register(rm_cb_counting_conflicted, NULL, &handle2, NULL)); + + memset(&request, 0, sizeof(rm_category_request_s)); + + request.request_num = 1; + request.category_id[0] = RM_CATEGORY_AUDIO_DECODER_SUB; + request.category_option[0] = 0; + request.state[0] = RM_STATE_EXCLUSIVE; + + memset(&allocated, 0, sizeof(rm_device_return_s)); + + EXPECT_EQ(RM_OK, rm_allocate_resources(handle2, &request, &allocated)); + EXPECT_EQ(1, allocated.allocated_num); + EXPECT_EQ(RM_DEVICE_AUDIO_DECODER_SUB, allocated.device_id[0]); + EXPECT_EQ(0, rm_tc_get_conflict_num()); + + rm_tc_reset_conflict_num(); + + int handle3; + EXPECT_EQ(RM_OK, rm_register(rm_cb_counting_conflicted, NULL, &handle3, NULL)); + + memset(&request, 0, sizeof(rm_category_request_s)); + + request.request_num = 1; + request.category_id[0] = RM_CATEGORY_AUDIO_DECODER_SUB; + request.category_option[0] = 0; + request.state[0] = RM_STATE_EXCLUSIVE; + + memset(&allocated, 0, sizeof(rm_device_return_s)); + + EXPECT_EQ(RM_OK, rm_allocate_resources(handle3, &request, &allocated)); + EXPECT_EQ(1, allocated.allocated_num); + EXPECT_EQ(RM_DEVICE_AUDIO_DECODER_SUB, allocated.device_id[0]); + EXPECT_EQ(1, rm_tc_get_conflict_num()); + + rm_tc_reset_conflict_num(); + + EXPECT_EQ(RM_OK, rm_unregister(handle1)); + EXPECT_EQ(RM_OK, rm_unregister(handle2)); + EXPECT_EQ(RM_OK, rm_unregister(handle3)); + + RM_TEST_MSG("multiview_audio_decoder_conflict_p2 end..."); +} + +TEST(ut_rm_api, alloc_audio_sub_out_p) +{ + /* + * 1. Allocate the following resource with handle#1 + * RM_CATEGORY_AUDIO_SUB_OUT with RM_STATE_EXCLUSIVE -> Alloc + */ + + RM_TEST_MSG("alloc_audio_sub_out_p start..."); + + rm_tc_reset_conflict_num(); + + int handle = 0; + + EXPECT_EQ(RM_OK, rm_register(rm_cb_counting_conflicted, NULL, &handle, NULL)); + + rm_category_request_s request; + memset(&request, 0, sizeof(rm_category_request_s)); + + rm_device_return_s allocated_devices; + memset(&allocated_devices, 0, sizeof(rm_device_return_s)); + + request.request_num = 1; + + request.category_id[0] = RM_CATEGORY_AUDIO_SUB_OUT; + request.state[0] = RM_STATE_EXCLUSIVE; + + EXPECT_EQ(RM_OK, rm_allocate_resources(handle, &request, &allocated_devices)); + + EXPECT_EQ(1, allocated_devices.allocated_num); + EXPECT_EQ(RM_DEVICE_AUDIO_SUB_OUT, allocated_devices.device_id[0]); + EXPECT_EQ(0, rm_tc_get_conflict_num()); + + rm_tc_reset_conflict_num(); + + EXPECT_EQ(RM_OK, rm_unregister(handle)); + + sleep(RM_TEST_SLEEP_TIME); + + RM_TEST_MSG("alloc_audio_sub_out_p end..."); +} + +TEST(ut_rm_api, alloc_audio_sub_out_conflict_1) +{ + /* + * 1. Allocate the following resource with handle#1 + * RM_CATEGORY_AUDIO_SUB_OUT with RM_STATE_EXCLUSIVE -> Alloc + * 2. Allocate the following resource with handle#2 + * RM_CATEGORY_AUDIO_MAIN_OUT with RM_STATE_EXCLUSIVE -> Alloc : No conflict + */ + + RM_TEST_MSG("alloc_audio_sub_out_conflict_1 start..."); + + rm_tc_reset_conflict_num(); + + int handle = 0; + + EXPECT_EQ(RM_OK, rm_register(rm_cb_counting_conflicted, NULL, &handle, NULL)); + + rm_category_request_s request; + memset(&request, 0, sizeof(rm_category_request_s)); + + rm_device_return_s allocated_devices; + memset(&allocated_devices, 0, sizeof(rm_device_return_s)); + + request.request_num = 1; + + request.category_id[0] = RM_CATEGORY_AUDIO_SUB_OUT; + request.state[0] = RM_STATE_EXCLUSIVE; + + EXPECT_EQ(RM_OK, rm_allocate_resources(handle, &request, &allocated_devices)); + + EXPECT_EQ(1, allocated_devices.allocated_num); + EXPECT_EQ(RM_DEVICE_AUDIO_SUB_OUT, allocated_devices.device_id[0]); + EXPECT_EQ(0, rm_tc_get_conflict_num()); + + int handle2 = 0; + + EXPECT_EQ(RM_OK, rm_register(rm_cb_counting_conflicted, NULL, &handle2, NULL)); + + memset(&request, 0, sizeof(rm_category_request_s)); + memset(&allocated_devices, 0, sizeof(rm_device_return_s)); + + request.request_num = 1; + request.category_id[0] = RM_CATEGORY_AUDIO_MAIN_OUT; + request.state[0] = RM_STATE_EXCLUSIVE; + + EXPECT_EQ(RM_OK, rm_allocate_resources(handle2, &request, &allocated_devices)); + + EXPECT_EQ(1, allocated_devices.allocated_num); + EXPECT_EQ(RM_DEVICE_AUDIO_MAIN_OUT, allocated_devices.device_id[0]); + EXPECT_EQ(0, rm_tc_get_conflict_num()); + + rm_tc_reset_conflict_num(); + + EXPECT_EQ(RM_OK, rm_unregister(handle)); + EXPECT_EQ(RM_OK, rm_unregister(handle2)); + + sleep(RM_TEST_SLEEP_TIME); + + RM_TEST_MSG("alloc_audio_sub_out_conflict_1 end..."); +} + +TEST(ut_rm_api, alloc_audio_sub_out_conflict_2) +{ + /* + * 1. Allocate the following resource with handle#1 + * RM_CATEGORY_AUDIO_SUB_OUT with RM_STATE_EXCLUSIVE -> Alloc + * 2. Allocate the following resource with handle#2 + * RM_CATEGORY_AUDIO_MAIN_OUT with RM_STATE_EXCLUSIVE -> Alloc : No conflict + */ + + RM_TEST_MSG("alloc_audio_sub_out_conflict_2 start..."); + + rm_tc_reset_conflict_num(); + + int handle = 0; + + EXPECT_EQ(RM_OK, rm_register(rm_cb_counting_conflicted, NULL, &handle, NULL)); + + rm_category_request_s request; + memset(&request, 0, sizeof(rm_category_request_s)); + + rm_device_return_s allocated_devices; + memset(&allocated_devices, 0, sizeof(rm_device_return_s)); + + request.request_num = 1; + + request.category_id[0] = RM_CATEGORY_AUDIO_SUB_OUT; + request.state[0] = RM_STATE_EXCLUSIVE; + + EXPECT_EQ(RM_OK, rm_allocate_resources(handle, &request, &allocated_devices)); + + EXPECT_EQ(1, allocated_devices.allocated_num); + EXPECT_EQ(RM_DEVICE_AUDIO_SUB_OUT, allocated_devices.device_id[0]); + EXPECT_EQ(0, rm_tc_get_conflict_num()); + + int handle2 = 0; + + EXPECT_EQ(RM_OK, rm_register(rm_cb_counting_conflicted, NULL, &handle2, NULL)); + + memset(&request, 0, sizeof(rm_category_request_s)); + memset(&allocated_devices, 0, sizeof(rm_device_return_s)); + + request.request_num = 1; + request.category_id[0] = RM_CATEGORY_AUDIO_MAIN_OUT; + request.state[0] = RM_STATE_EXCLUSIVE; + + EXPECT_EQ(RM_OK, rm_allocate_resources(handle2, &request, &allocated_devices)); + + EXPECT_EQ(1, allocated_devices.allocated_num); + EXPECT_EQ(RM_DEVICE_AUDIO_MAIN_OUT, allocated_devices.device_id[0]); + EXPECT_EQ(0, rm_tc_get_conflict_num()); + + rm_tc_reset_conflict_num(); + + EXPECT_EQ(RM_OK, rm_unregister(handle)); + EXPECT_EQ(RM_OK, rm_unregister(handle2)); + + sleep(RM_TEST_SLEEP_TIME); + + RM_TEST_MSG("alloc_audio_sub_out_conflict_2 end..."); +} + + +TEST(ut_rm_api, multiview_scaler_to_main_p1) +{ + RM_TEST_MSG("multiview_scaler_to_main_p1 start..."); + + int handle = 0; + EXPECT_EQ(RM_OK, rm_register(rm_cb_counting_conflicted, NULL, &handle, NULL)); + + rm_category_request_s request; + memset(&request, 0, sizeof(rm_category_request_s)); + + request.request_num = 1; + request.category_id[0] = RM_CATEGORY_SCALER; + request.category_option[0] = (RM_CATEGORY_SCALER | RM_FORCE_TO_MAIN); + request.state[0] = RM_STATE_EXCLUSIVE; + + rm_device_return_s allocated; + memset(&allocated, 0, sizeof(rm_device_return_s)); + EXPECT_EQ(RM_OK, rm_allocate_resources(handle, &request, &allocated)); + + EXPECT_EQ(1, allocated.allocated_num); + EXPECT_EQ(RI_VIRTUAL_ID_SCALER, allocated.device_id[0]); + EXPECT_EQ(RM_DEVICE_SCALER, rm_find_device_id(allocated.device_id[0])); + + EXPECT_EQ(RM_OK, rm_unregister(handle)); + + RM_TEST_MSG("multiview_scaler_to_main_p1 end..."); +} + +TEST(ut_rm_api, multiview_scaler_to_main_p2) +{ + RM_TEST_MSG("multiview_scaler_to_main_p2 start..."); + + int handle = 0; + EXPECT_EQ(RM_OK, rm_register(rm_cb_counting_conflicted, NULL, &handle, NULL)); + + rm_category_request_s request; + memset(&request, 0, sizeof(rm_category_request_s)); + + request.request_num = 1; + request.category_id[0] = RM_CATEGORY_SCALER_SUB; + request.category_option[0] = (RM_CATEGORY_SCALER_SUB | RM_FORCE_TO_MAIN); + request.state[0] = RM_STATE_EXCLUSIVE; + + rm_device_return_s allocated; + memset(&allocated, 0, sizeof(rm_device_return_s)); + EXPECT_EQ(RM_OK, rm_allocate_resources(handle, &request, &allocated)); + + EXPECT_EQ(1, allocated.allocated_num); + EXPECT_EQ(RI_VIRTUAL_ID_SCALER, allocated.device_id[0]); + EXPECT_EQ(RM_DEVICE_SCALER, rm_find_device_id(allocated.device_id[0])); + + EXPECT_EQ(RM_OK, rm_unregister(handle)); + + RM_TEST_MSG("multiview_scaler_to_main_p2 end..."); +} + +TEST(ut_rm_api, multiview_scaler_to_sub_p1) +{ + RM_TEST_MSG("multiview_scaler_to_sub_p1 start..."); + + int handle = 0; + EXPECT_EQ(RM_OK, rm_register(rm_cb_counting_conflicted, NULL, &handle, NULL)); + + rm_category_request_s request; + memset(&request, 0, sizeof(rm_category_request_s)); + + request.request_num = 1; + request.category_id[0] = RM_CATEGORY_SCALER; + request.category_option[0] = (RM_CATEGORY_SCALER | RM_FORCE_TO_SUB); + request.state[0] = RM_STATE_EXCLUSIVE; + + rm_device_return_s allocated; + memset(&allocated, 0, sizeof(rm_device_return_s)); + EXPECT_EQ(RM_OK, rm_allocate_resources(handle, &request, &allocated)); + + EXPECT_EQ(1, allocated.allocated_num); + EXPECT_EQ(RI_VIRTUAL_ID_SCALER + 1, allocated.device_id[0]); + EXPECT_EQ(RM_DEVICE_SCALER_SUB, rm_find_device_id(allocated.device_id[0])); + + EXPECT_EQ(RM_OK, rm_unregister(handle)); + + RM_TEST_MSG("multiview_scaler_to_sub_p1 end..."); +} + +TEST(ut_rm_api, multiview_audio_out_to_main_p1) +{ + RM_TEST_MSG("multiview_audio_out_to_main_p1 start..."); + + int handle = 0; + EXPECT_EQ(RM_OK, rm_register(rm_cb_counting_conflicted, NULL, &handle, NULL)); + + rm_category_request_s request; + memset(&request, 0, sizeof(rm_category_request_s)); + + request.request_num = 1; + request.category_id[0] = RM_CATEGORY_AUDIO_MAIN_OUT; + request.category_option[0] = (RM_CATEGORY_AUDIO_MAIN_OUT | RM_FORCE_TO_MAIN); + request.state[0] = RM_STATE_EXCLUSIVE; + + rm_device_return_s allocated; + memset(&allocated, 0, sizeof(rm_device_return_s)); + EXPECT_EQ(RM_OK, rm_allocate_resources(handle, &request, &allocated)); + + EXPECT_EQ(1, allocated.allocated_num); + EXPECT_EQ(RM_DEVICE_AUDIO_MAIN_OUT, allocated.device_id[0]); + + EXPECT_EQ(RM_OK, rm_unregister(handle)); + + RM_TEST_MSG("multiview_audio_out_to_main_p1 end..."); +} + +TEST(ut_rm_api, multiview_audio_out_to_main_p2) +{ + RM_TEST_MSG("multiview_audio_out_to_main_p2 start..."); + + int handle = 0; + EXPECT_EQ(RM_OK, rm_register(rm_cb_counting_conflicted, NULL, &handle, NULL)); + + rm_category_request_s request; + memset(&request, 0, sizeof(rm_category_request_s)); + + request.request_num = 1; + request.category_id[0] = RM_CATEGORY_AUDIO_MAIN_OUT; + request.category_option[0] = (RM_CATEGORY_AUDIO_MAIN_OUT | RM_FORCE_TO_SUB); + request.state[0] = RM_STATE_EXCLUSIVE; + + rm_device_return_s allocated; + memset(&allocated, 0, sizeof(rm_device_return_s)); + EXPECT_EQ(RM_OK, rm_allocate_resources(handle, &request, &allocated)); + + EXPECT_EQ(1, allocated.allocated_num); + EXPECT_EQ(RM_DEVICE_AUDIO_SUB_OUT, allocated.device_id[0]); + + EXPECT_EQ(RM_OK, rm_unregister(handle)); + + RM_TEST_MSG("multiview_audio_out_to_main_p2 end..."); +} + +TEST(ut_rm_api, multiview_audio_decoder_main_p1) +{ + RM_TEST_MSG("multiview_audio_decoder_main_p1 start..."); + + int handle = 0; + EXPECT_EQ(RM_OK, rm_register(rm_cb_counting_conflicted, NULL, &handle, NULL)); + + rm_category_request_s request; + memset(&request, 0, sizeof(rm_category_request_s)); + + request.request_num = 1; + request.category_id[0] = RM_CATEGORY_AUDIO_DECODER; + request.category_option[0] = (RM_CATEGORY_AUDIO_DECODER | RM_DEVICE_OPT_MAIN | RM_FORCE_TO_MAIN); + request.state[0] = RM_STATE_EXCLUSIVE; + + rm_device_return_s allocated; + memset(&allocated, 0, sizeof(rm_device_return_s)); + EXPECT_EQ(RM_OK, rm_allocate_resources(handle, &request, &allocated)); + + EXPECT_EQ(1, allocated.allocated_num); + EXPECT_EQ(RM_DEVICE_AUDIO_DECODER, allocated.device_id[0]); + + EXPECT_EQ(RM_OK, rm_unregister(handle)); + + RM_TEST_MSG("multiview_audio_decoder_main_p1 end..."); +} + +TEST(ut_rm_api, multiview_audio_decoder_main_p2) +{ + RM_TEST_MSG("multiview_audio_decoder_main_p2 start..."); + + int handle = 0; + EXPECT_EQ(RM_OK, rm_register(rm_cb_counting_conflicted, NULL, &handle, NULL)); + + rm_category_request_s request; + memset(&request, 0, sizeof(rm_category_request_s)); + + request.request_num = 1; + request.category_id[0] = RM_CATEGORY_AUDIO_DECODER; + request.category_option[0] = (RM_CATEGORY_AUDIO_DECODER | RM_DEVICE_OPT_SUB | RM_FORCE_TO_SUB); + request.state[0] = RM_STATE_EXCLUSIVE; + + rm_device_return_s allocated; + memset(&allocated, 0, sizeof(rm_device_return_s)); + EXPECT_EQ(RM_OK, rm_allocate_resources(handle, &request, &allocated)); + + EXPECT_EQ(1, allocated.allocated_num); + EXPECT_EQ(RM_DEVICE_AUDIO_DECODER_SUB, allocated.device_id[0]); + + EXPECT_EQ(RM_OK, rm_unregister(handle)); + + RM_TEST_MSG("multiview_audio_decoder_main_p2 end..."); +} + +TEST(ut_rm_api, rm_active_audio_out_p1) +{ + RM_TEST_MSG("rm_active_audio_out_p1 start..."); + + TCPlayer *player = new TCPlayer(); + EXPECT_EQ(RM_OK, player->Register()); + + EXPECT_EQ(RM_AUDIO_OUT_NONE, player->GetActiveAudioOut()); + + // Allocate audio main out + player->AddResource(RM_CATEGORY_AUDIO_MAIN_OUT, RM_STATE_EXCLUSIVE); + EXPECT_EQ(RM_OK, player->AllocateResources()); + EXPECT_EQ(RM_AUDIO_OUT_MAIN, player->GetActiveAudioOut()); + + // Allocate audio sub out + player->RemoveResources(); + player->AddResource(RM_CATEGORY_AUDIO_SUB_OUT, RM_STATE_EXCLUSIVE); + EXPECT_EQ(RM_OK, player->AllocateResources()); + EXPECT_EQ((RM_AUDIO_OUT_MAIN | RM_AUDIO_OUT_SUB), player->GetActiveAudioOut()); + + // Release audio main & sub out + player->RemoveResources(); + EXPECT_EQ(RM_OK, player->ReleaseResources()); + EXPECT_EQ(RM_AUDIO_OUT_NONE, player->GetActiveAudioOut()); + + // Allocate audio sub out + player->AddResource(RM_CATEGORY_AUDIO_SUB_OUT, RM_STATE_EXCLUSIVE); + EXPECT_EQ(RM_OK, player->AllocateResources()); + EXPECT_EQ(RM_AUDIO_OUT_SUB, player->GetActiveAudioOut()); + + EXPECT_EQ(RM_OK, player->Unregister()); + delete player; + + RM_TEST_MSG("rm_active_audio_out_p1 end..."); +} diff --git a/ut/testcase/ut_tc_multiview_not_support.cpp b/ut/testcase/ut_tc_multiview_not_support.cpp new file mode 100644 index 0000000..2d47a14 --- /dev/null +++ b/ut/testcase/ut_tc_multiview_not_support.cpp @@ -0,0 +1,158 @@ +/* + * Copyright (c) 2024 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 "gtest/gtest.h" +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +TEST(ut_rm_api, alloc_audio_dec_in_mixing_not_supported_model_p1) +{ + /* + * 1. Allocate an Audio decoder with MultiView mixing mode in mixing not supported model (app_id : app1) -> Alloc : No conflict : Main audio decoder + * 2. Allocate an Audio decoder with MultiView mixing mode in mixing not supported model (app_id : app2) -> Alloc : conflict with player1: Main audio decoder + * 3. Allocate a sub Audio decoder with MultiView mixing mode in mixing not supported model (app_id : app3) -> Alloc : No conflict : Sub audio decoder + * 4. Allocate a sub Audio decoder with MultiView mixing mode in mixing not supported model (app_id : app4) -> Alloc : conflict with player3 : Sub audio decoder + */ + + RM_TEST_MSG("alloc_audio_dec_in_mixing_not_supported_model_p1 start..."); + + ri_audio_category_option_request_s audio_option; + memset(&audio_option, 0, sizeof(ri_audio_category_option_request_s)); + + // player1 + audio_option.codec_name = RI_AUDIO_CODEC_NAME_MPEG; + audio_option.mixing_mode = RI_MIXING_MODE_MULTIVIEW; + + TCPlayer *player = new TCPlayer(); + player->AddResource(RM_CATEGORY_AUDIO_DECODER, (ri_get_capable_audio_category_id(&audio_option) | RM_DEVICE_OPT_MAIN), RM_STATE_EXCLUSIVE); + + EXPECT_EQ(RM_OK, player->Register()); + EXPECT_EQ(RM_OK, player->AllocateResources()); + + EXPECT_EQ(RM_DEVICE_AUDIO_DECODER, player->GetAllocatedResourceId(1)); + + // player2 + TCPlayer *player2 = new TCPlayer(); + player2->AddResource(RM_CATEGORY_AUDIO_DECODER, ri_get_capable_audio_category_id(&audio_option), RM_STATE_EXCLUSIVE); + + EXPECT_EQ(RM_OK, player2->Register()); + EXPECT_EQ(RM_OK, player2->AllocateResources()); + + EXPECT_EQ(RM_DEVICE_AUDIO_DECODER, player2->GetAllocatedResourceId(1)); + EXPECT_EQ(1, player->GetConflictNum()); + + // player3 + TCPlayer *player3 = new TCPlayer(); + player3->AddResource(RM_CATEGORY_AUDIO_DECODER_SUB, (ri_get_capable_audio_category_id(&audio_option) | RM_DEVICE_OPT_SUB), RM_STATE_EXCLUSIVE); + + EXPECT_EQ(RM_OK, player3->Register()); + EXPECT_EQ(RM_OK, player3->AllocateResources()); + + EXPECT_EQ(RM_DEVICE_AUDIO_DECODER_SUB, player3->GetAllocatedResourceId(1)); + EXPECT_EQ(1, player->GetConflictNum()); + EXPECT_EQ(0, player2->GetConflictNum()); + + // player4 + TCPlayer *player4 = new TCPlayer(); + player4->AddResource(RM_CATEGORY_AUDIO_DECODER_SUB, ri_get_capable_audio_category_id(&audio_option), RM_STATE_EXCLUSIVE); + + EXPECT_EQ(RM_OK, player4->Register()); + EXPECT_EQ(RM_OK, player4->AllocateResources()); + + EXPECT_EQ(RM_DEVICE_AUDIO_DECODER_SUB, player4->GetAllocatedResourceId(1)); + EXPECT_EQ(1, player->GetConflictNum()); + EXPECT_EQ(0, player2->GetConflictNum()); + EXPECT_EQ(1, player3->GetConflictNum()); + + EXPECT_EQ(RM_OK, player->Unregister()); + EXPECT_EQ(RM_OK, player2->Unregister()); + EXPECT_EQ(RM_OK, player3->Unregister()); + EXPECT_EQ(RM_OK, player4->Unregister()); + + delete player; + delete player2; + delete player3; + delete player4; + + sleep(RM_TEST_SLEEP_TIME); + + RM_TEST_MSG("alloc_audio_dec_in_mixing_not_supported_model_p1 end..."); +} + +TEST(ut_rm_api, allocate_audio_decoder_with_legacy_one_not_support_multiview) +{ + /* + * 1. Allocate a RI_CATEGORY_AUDIO_DECODER -> Alloc : No conflict -> audio main decoder + * 2. Allocate a RI_CATEGORY_AUDIO_DECODER_WMA -> Alloc : conflict with Consumer#1 -> audio main decoder + * 3. Allocate a RI_CATEGORY_AUDIO_DECODER -> Alloc : conflict with Consumer#2 -> audio main decoder + */ + + RM_TEST_MSG("allocate_audio_decoder_with_legacy_one_not_support_multiview start..."); + + TCPlayer *player = new TCPlayer(); + player->AddResource(RM_CATEGORY_AUDIO_DECODER, RM_STATE_EXCLUSIVE); + + EXPECT_EQ(RM_OK, player->Register()); + EXPECT_EQ(RM_OK, player->SetAppId("user1")); + EXPECT_EQ(RM_OK, player->AllocateResources()); + EXPECT_EQ(RM_DEVICE_AUDIO_DECODER, player->GetAllocatedResourceId(1)); + + // As a resource of GetAudioCategory(), RI_CATEGORY_NONE shall be returned because audio mixing is not supported + TCPlayer *player2 = new TCPlayer(); + player2->AddResource(RM_CATEGORY_AUDIO_DECODER, player2->GetAudioCategory(RI_AUDIO_CODEC_NAME_WMA, 0), RM_STATE_EXCLUSIVE); + + EXPECT_EQ(RM_OK, player2->Register()); + EXPECT_EQ(RM_OK, player2->SetAppId("user2")); + EXPECT_EQ(RM_OK, player2->AllocateResources()); + EXPECT_EQ(RM_DEVICE_AUDIO_DECODER, player2->GetAllocatedResourceId(1)); + + EXPECT_EQ(1, player->GetConflictNum()); + + TCPlayer *player3 = new TCPlayer(); + player3->AddResource(RM_CATEGORY_AUDIO_DECODER, RM_STATE_EXCLUSIVE); + + EXPECT_EQ(RM_OK, player3->Register()); + EXPECT_EQ(RM_OK, player3->SetAppId("user3")); + EXPECT_EQ(RM_OK, player3->AllocateResources()); + EXPECT_EQ(RM_DEVICE_AUDIO_DECODER, player3->GetAllocatedResourceId(1)); + + EXPECT_EQ(1, player->GetConflictNum()); + EXPECT_EQ(1, player2->GetConflictNum()); + + EXPECT_EQ(RM_OK, player->Unregister()); + EXPECT_EQ(RM_OK, player2->Unregister()); + EXPECT_EQ(RM_OK, player3->Unregister()); + + delete player; + delete player2; + delete player3; + + sleep(RM_TEST_SLEEP_TIME); + + RM_TEST_MSG("allocate_audio_decoder_with_legacy_one_not_support_multiview end..."); +} diff --git a/ut/testcase/ut_tc_resource.cpp b/ut/testcase/ut_tc_resource.cpp new file mode 100644 index 0000000..f79eb6d --- /dev/null +++ b/ut/testcase/ut_tc_resource.cpp @@ -0,0 +1,676 @@ +/* + * Copyright (c) 2024 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 "gtest/gtest.h" +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + + +TEST(ut_rm_api, rm_rsc_state_p1) +{ + RM_TEST_MSG("rm_rsc_state_p1 start..."); + + rm_resource_state_e state; + int ret = rm_get_resource_state(RM_DEVICE_AUDIO_ENCODER, &state); + + EXPECT_EQ(RM_OK, ret); + EXPECT_EQ(RM_RSC_STATE_FREE, state); + + RM_TEST_MSG("rm_rsc_state_p1 end..."); +} + +TEST(ut_rm_api, rm_rsc_state_n1) +{ + RM_TEST_MSG("rm_rsc_state_n1 start..."); + + rm_resource_state_e state; + int ret = rm_get_resource_state(9999999, &state); + + EXPECT_NE(RM_OK, ret); + + RM_TEST_MSG("rm_rsc_state_n1 end..."); +} + +TEST(ut_rm_api, rm_rsc_state_n2) +{ + RM_TEST_MSG("rm_rsc_state_n2 start..."); + + rm_resource_state_e state; + int ret = rm_get_resource_state(-1, &state); + + EXPECT_NE(RM_OK, ret); + + RM_TEST_MSG("rm_rsc_state_n2 end..."); +} + +TEST(ut_rm_api, rm_rsc_state_n3) +{ + RM_TEST_MSG("rm_rsc_state_n2 start..."); + + int ret = rm_get_resource_state(RM_DEVICE_AUDIO_ENCODER, NULL); + + EXPECT_NE(RM_OK, ret); + + RM_TEST_MSG("rm_rsc_state_n3 end..."); +} + +TEST(ut_rm_api, rm_rsc_get_resource_list_p1) +{ + RM_TEST_MSG("rm_rsc_get_resource_list_p1 start..."); + + rm_resource_list_h rsc_list; + int ret = rm_get_resource_list(RM_CATEGORY_DEMUX, &rsc_list); + + EXPECT_EQ(RM_OK, ret); + + rm_resource_h resource; + EXPECT_EQ(6, rm_resource_list_get_count(rsc_list)); + + resource = rm_resource_list_get_first(rsc_list); + EXPECT_EQ(RM_DEVICE_DEMUX0, rm_resource_get_id(resource)); + EXPECT_STREQ("/dev/dvb/adapter0/demux0", rm_resource_get_node(resource)); + + resource = rm_resource_list_get_next(rsc_list); + EXPECT_EQ(RM_DEVICE_DEMUX1, rm_resource_get_id(resource)); + EXPECT_STREQ("/dev/dvb/adapter0/demux1", rm_resource_get_node(resource)); + + resource = rm_resource_list_get_next(rsc_list); + EXPECT_EQ(RM_DEVICE_DEMUX2, rm_resource_get_id(resource)); + EXPECT_STREQ("/dev/dvb/adapter0/demux2", rm_resource_get_node(resource)); + + resource = rm_resource_list_get_next(rsc_list); + EXPECT_EQ(RM_DEVICE_DEMUX3, rm_resource_get_id(resource)); + EXPECT_STREQ("/dev/dvb/adapter0/demux3", rm_resource_get_node(resource)); + + resource = rm_resource_list_get_next(rsc_list); + EXPECT_EQ(RM_DEVICE_DEMUX4, rm_resource_get_id(resource)); + EXPECT_STREQ("/dev/dvb/adapter0/demux4", rm_resource_get_node(resource)); + + resource = rm_resource_list_get_next(rsc_list); + EXPECT_EQ(RM_DEVICE_DEMUX5, rm_resource_get_id(resource)); + EXPECT_STREQ("/dev/dvb/adapter0/demux5", rm_resource_get_node(resource)); + + EXPECT_EQ(0, rm_resource_list_get_next(rsc_list)); + + resource = rm_resource_list_get_last(rsc_list); + EXPECT_EQ(RM_DEVICE_DEMUX5, rm_resource_get_id(resource)); + EXPECT_STREQ("/dev/dvb/adapter0/demux5", rm_resource_get_node(resource)); + + resource = rm_resource_list_get_prev(rsc_list); + EXPECT_EQ(RM_DEVICE_DEMUX4, rm_resource_get_id(resource)); + EXPECT_STREQ("/dev/dvb/adapter0/demux4", rm_resource_get_node(resource)); + + resource = rm_resource_list_get_prev(rsc_list); + EXPECT_EQ(RM_DEVICE_DEMUX3, rm_resource_get_id(resource)); + EXPECT_STREQ("/dev/dvb/adapter0/demux3", rm_resource_get_node(resource)); + + resource = rm_resource_list_get_prev(rsc_list); + EXPECT_EQ(RM_DEVICE_DEMUX2, rm_resource_get_id(resource)); + EXPECT_STREQ("/dev/dvb/adapter0/demux2", rm_resource_get_node(resource)); + + resource = rm_resource_list_get_prev(rsc_list); + EXPECT_EQ(RM_DEVICE_DEMUX1, rm_resource_get_id(resource)); + EXPECT_STREQ("/dev/dvb/adapter0/demux1", rm_resource_get_node(resource)); + + resource = rm_resource_list_get_prev(rsc_list); + EXPECT_EQ(RM_DEVICE_DEMUX0, rm_resource_get_id(resource)); + EXPECT_STREQ("/dev/dvb/adapter0/demux0", rm_resource_get_node(resource)); + + EXPECT_EQ(0, rm_resource_list_get_prev(rsc_list)); + + rm_free_resource_list(rsc_list); + + RM_TEST_MSG("rm_rsc_get_resource_list_p1 end..."); +} + +TEST(ut_rm_api, rm_rsc_get_resource_list_p2) +{ + RM_TEST_MSG("rm_rsc_get_resource_list_p2 start..."); + + TCPlayer *player = new TCPlayer(); + player->AddResource(RM_CATEGORY_SCALER, RM_STATE_EXCLUSIVE); + + EXPECT_EQ(RM_OK, player->Register()); + EXPECT_EQ(RM_OK, player->AllocateResources()); + + EXPECT_EQ(RI_VIRTUAL_ID_SCALER, player->GetAllocatedResourceId(1)); + EXPECT_EQ(RM_DEVICE_SCALER, rm_find_device_id(player->GetAllocatedResourceId(1))); + + rm_resource_list_h rsc_list; + int ret = rm_get_resource_list(RM_CATEGORY_SCALER, &rsc_list); + + EXPECT_EQ(RM_OK, ret); + + rm_resource_h resource; + EXPECT_EQ(1, rm_resource_list_get_count(rsc_list)); + resource = rm_resource_list_get_first(rsc_list); + EXPECT_EQ(RM_DEVICE_SCALER, rm_resource_get_id(resource)); + EXPECT_STREQ("/dev/dri/card0", rm_resource_get_node(resource)); + EXPECT_EQ(RM_RSC_STATE_EXCLUSIVE, rm_resource_get_state(resource)); + + EXPECT_EQ(0, rm_resource_list_get_next(rsc_list)); + + resource = rm_resource_list_get_last(rsc_list); + EXPECT_EQ(RM_DEVICE_SCALER, rm_resource_get_id(resource)); + EXPECT_STREQ("/dev/dri/card0", rm_resource_get_node(resource)); + EXPECT_EQ(RM_RSC_STATE_EXCLUSIVE, rm_resource_get_state(resource)); + + EXPECT_EQ(0, rm_resource_list_get_prev(rsc_list)); + + rm_free_resource_list(rsc_list); + + EXPECT_EQ(RM_OK, player->Unregister()); + delete player; + + ret = rm_get_resource_list(RM_CATEGORY_SCALER, &rsc_list); + EXPECT_EQ(RM_OK, ret); + + EXPECT_EQ(1, rm_resource_list_get_count(rsc_list)); + resource = rm_resource_list_get_first(rsc_list); + EXPECT_EQ(RM_DEVICE_SCALER, rm_resource_get_id(resource)); + EXPECT_STREQ("/dev/dri/card0", rm_resource_get_node(resource)); + EXPECT_EQ(RM_RSC_STATE_FREE, rm_resource_get_state(resource)); + + EXPECT_EQ(0, rm_resource_list_get_next(rsc_list)); + + resource = rm_resource_list_get_last(rsc_list); + EXPECT_EQ(RM_DEVICE_SCALER, rm_resource_get_id(resource)); + EXPECT_STREQ("/dev/dri/card0", rm_resource_get_node(resource)); + EXPECT_EQ(RM_RSC_STATE_FREE, rm_resource_get_state(resource)); + + EXPECT_EQ(0, rm_resource_list_get_prev(rsc_list)); + + rm_free_resource_list(rsc_list); + + RM_TEST_MSG("rm_rsc_get_resource_list_p2 end..."); +} + +TEST(ut_rm_api, rm_rsc_get_resource_list_p3) +{ + if (!is_support_audio_dual_decoding()) + return; + + RM_TEST_MSG("rm_rsc_get_resource_list_p3 start..."); + + rm_resource_list_h rsc_list; + int ret = rm_get_resource_list(RM_CATEGORY_AUDIO_SUB_OUT, &rsc_list); + + EXPECT_EQ(RM_OK, ret); + + rm_resource_h resource; + EXPECT_EQ(1, rm_resource_list_get_count(rsc_list)); + resource = rm_resource_list_get_first(rsc_list); + EXPECT_EQ(RM_DEVICE_AUDIO_SUB_OUT, rm_resource_get_id(resource)); + EXPECT_STREQ("", rm_resource_get_app_id(resource)); + EXPECT_EQ(0, rm_resource_list_get_next(rsc_list)); + + resource = rm_resource_list_get_last(rsc_list); + EXPECT_EQ(RM_DEVICE_AUDIO_SUB_OUT, rm_resource_get_id(resource)); + + EXPECT_EQ(0, rm_resource_list_get_prev(rsc_list)); + + rm_free_resource_list(rsc_list); + + RM_TEST_MSG("rm_rsc_get_resource_list_p3 end..."); +} + +TEST(ut_rm_api, rm_rsc_get_resource_list_p4) +{ + if (!is_support_audio_dual_decoding()) + return; + + RM_TEST_MSG("rm_rsc_get_resource_list_p4 start..."); + + TCPlayer *player = new TCPlayer(); + player->AddResource(RM_CATEGORY_AUDIO_SUB_OUT, RM_STATE_EXCLUSIVE); + + EXPECT_EQ(RM_OK, player->Register()); + EXPECT_EQ(RM_OK, player->SetAppId("org.tizen.viewer")); + EXPECT_EQ(RM_OK, player->AllocateResources()); + + EXPECT_EQ(RM_DEVICE_AUDIO_SUB_OUT, player->GetAllocatedResourceId(1)); + + rm_resource_list_h rsc_list; + int ret = rm_get_resource_list(RM_CATEGORY_AUDIO_SUB_OUT, &rsc_list); + + EXPECT_EQ(RM_OK, ret); + + rm_resource_h resource; + EXPECT_EQ(1, rm_resource_list_get_count(rsc_list)); + resource = rm_resource_list_get_first(rsc_list); + EXPECT_EQ(RM_DEVICE_AUDIO_SUB_OUT, rm_resource_get_id(resource)); + EXPECT_STREQ("org.tizen.viewer", rm_resource_get_app_id(resource)); + EXPECT_EQ(0, rm_resource_list_get_next(rsc_list)); + + resource = rm_resource_list_get_last(rsc_list); + EXPECT_EQ(RM_DEVICE_AUDIO_SUB_OUT, rm_resource_get_id(resource)); + + EXPECT_EQ(0, rm_resource_list_get_prev(rsc_list)); + + rm_free_resource_list(rsc_list); + + EXPECT_EQ(RM_OK, player->Unregister()); + delete player; + + RM_TEST_MSG("rm_rsc_get_resource_list_p4 end..."); +} + + +TEST(ut_rm_api, rm_rsc_get_resource_list_n1) +{ + RM_TEST_MSG("rm_rsc_get_resource_list_n1 start..."); + + rm_resource_list_h rsc_list; + int ret = rm_get_resource_list((rm_rsc_category_e) -10, &rsc_list); + + EXPECT_EQ(RM_OK, ret); + rm_free_resource_list(rsc_list); + + RM_TEST_MSG("rm_rsc_get_resource_list_n1 end..."); +} + +TEST(ut_rm_api, rm_rsc_get_resource_list_n2) +{ + RM_TEST_MSG("rm_rsc_get_resource_list_n2 start..."); + + int ret = rm_get_resource_list(RM_CATEGORY_DEMUX, NULL); + + EXPECT_NE(RM_OK, ret); + + RM_TEST_MSG("rm_rsc_get_resource_list_n2 end..."); +} + +TEST(ut_rm_api, rm_resource_get_id_n1) +{ + RM_TEST_MSG("rm_resource_get_id_n1 start..."); + EXPECT_EQ(-1, rm_resource_get_id(NULL)); + RM_TEST_MSG("rm_resource_get_id_n1 end..."); +} + +TEST(ut_rm_api, rm_resource_get_node_n1) +{ + RM_TEST_MSG("rm_resource_get_node_n1 start..."); + EXPECT_EQ(0, rm_resource_get_node(NULL)); + RM_TEST_MSG("rm_resource_get_node_n1 end..."); +} + +TEST(ut_rm_api, rm_resource_list_get_prev_n1) +{ + RM_TEST_MSG("rm_resource_list_get_prev_n1 start..."); + EXPECT_EQ(0, rm_resource_list_get_prev(NULL)); + rm_resource_list_h list = NULL; + EXPECT_EQ(0, rm_resource_list_get_prev(list)); + RM_TEST_MSG("rm_resource_list_get_prev_n1 end..."); +} + +TEST(ut_rm_api, rm_get_resource_collection_state_p1) +{ + RM_TEST_MSG("rm_get_resource_collection_state_p1 start..."); + + rm_resource_list_h rsc_list = NULL; + + EXPECT_EQ(0, rm_get_resource_collection_state(RM_RSC_COLLECTION_MAIN, &rsc_list)); + + // MFD0, DVDE0, MAIN SCALER, MAIN AUDIO DECODER, MAIN AUDIO OUT + EXPECT_EQ(5, rm_resource_list_get_count(rsc_list)); + + rm_resource_h resource = rm_resource_list_get_first(rsc_list); + + EXPECT_EQ(RM_DEVICE_AUDIO_MAIN_OUT, rm_resource_get_id(resource)); + EXPECT_EQ(RM_RSC_STATE_FREE, rm_resource_get_state(resource)); + EXPECT_EQ(-1, rm_resource_get_consumer(resource)); + EXPECT_STREQ("", rm_resource_get_app_id(resource)); + EXPECT_EQ(RM_CATEGORY_AUDIO_MAIN_OUT, rm_resource_get_category(resource)); + + resource = rm_resource_list_get_next(rsc_list); + + EXPECT_EQ(RM_DEVICE_SCALER, rm_resource_get_id(resource)); + EXPECT_EQ(RM_RSC_STATE_FREE, rm_resource_get_state(resource)); + EXPECT_EQ(-1, rm_resource_get_consumer(resource)); + EXPECT_STREQ("", rm_resource_get_app_id(resource)); + EXPECT_EQ(RM_CATEGORY_SCALER, rm_resource_get_category(resource)); + + resource = rm_resource_list_get_next(rsc_list); + + EXPECT_EQ(RM_DEVICE_AUDIO_DECODER, rm_resource_get_id(resource)); + EXPECT_EQ(RM_RSC_STATE_FREE, rm_resource_get_state(resource)); + EXPECT_EQ(-1, rm_resource_get_consumer(resource)); + EXPECT_STREQ("", rm_resource_get_app_id(resource)); + EXPECT_EQ(RM_CATEGORY_AUDIO_DECODER, rm_resource_get_category(resource)); + + resource = rm_resource_list_get_next(rsc_list); + + EXPECT_EQ(RM_DEVICE_VIDEO_DECODER_MAIN, rm_resource_get_id(resource)); + EXPECT_EQ(RM_RSC_STATE_FREE, rm_resource_get_state(resource)); + EXPECT_EQ(-1, rm_resource_get_consumer(resource)); + EXPECT_STREQ("", rm_resource_get_app_id(resource)); + EXPECT_LE(RM_CATEGORY_VIDEO_DECODER, rm_resource_get_category(resource)); + + resource = rm_resource_list_get_next(rsc_list); + + EXPECT_EQ(RM_DEVICE_VIDEO_DECODER_DVDE0, rm_resource_get_id(resource)); + EXPECT_EQ(RM_RSC_STATE_FREE, rm_resource_get_state(resource)); + EXPECT_EQ(-1, rm_resource_get_consumer(resource)); + EXPECT_STREQ("", rm_resource_get_app_id(resource)); + EXPECT_LE(RM_CATEGORY_VIDEO_DECODER_UHD, rm_resource_get_category(resource)); + + rm_free_resource_list(rsc_list); + + RM_TEST_MSG("rm_get_resource_collection_state_p1 end..."); +} + +TEST(ut_rm_api, rm_get_resource_collection_state_p2) +{ + RM_TEST_MSG("rm_get_resource_collection_state_p2 start..."); + + int handle = 0; + const char *app_id = "org.tizen.test"; + EXPECT_EQ(0, rm_register(rm_cb_set_conflict_flag, NULL, &handle, NULL)); + EXPECT_EQ(0, rm_set_app_id(handle, (char*) app_id)); + + rm_category_request_s req; + memset(&req, 0, sizeof(req)); + + req.request_num = 1; + req.category_id[0] = RM_CATEGORY_SCALER; + req.state[0] = RM_STATE_EXCLUSIVE; + + rm_device_return_s allocated; + memset(&allocated, 0, sizeof(allocated)); + + EXPECT_EQ(0, rm_allocate_resources(handle, &req, &allocated)); + + EXPECT_EQ(1, allocated.allocated_num); + + rm_resource_list_h rsc_list = NULL; + + EXPECT_EQ(0, rm_get_resource_collection_state(RM_RSC_COLLECTION_MAIN, &rsc_list)); + + // MFD0, DVDE0, MAIN SCALER, MAIN AUDIO DECODER, MAIN AUDIO OUT + EXPECT_EQ(5, rm_resource_list_get_count(rsc_list)); + + rm_resource_h resource = rm_resource_list_get_first(rsc_list); + + EXPECT_EQ(RM_DEVICE_AUDIO_MAIN_OUT, rm_resource_get_id(resource)); + EXPECT_EQ(RM_RSC_STATE_FREE, rm_resource_get_state(resource)); + EXPECT_EQ(-1, rm_resource_get_consumer(resource)); + EXPECT_STREQ("", rm_resource_get_app_id(resource)); + EXPECT_EQ(RM_CATEGORY_AUDIO_MAIN_OUT, rm_resource_get_category(resource)); + + resource = rm_resource_list_get_next(rsc_list); + + EXPECT_EQ(RM_DEVICE_SCALER, rm_resource_get_id(resource)); + EXPECT_EQ(RM_RSC_STATE_EXCLUSIVE, rm_resource_get_state(resource)); + EXPECT_EQ(handle, rm_resource_get_consumer(resource)); + EXPECT_STREQ(app_id, rm_resource_get_app_id(resource)); + EXPECT_EQ(RM_CATEGORY_SCALER, rm_resource_get_category(resource)); + + resource = rm_resource_list_get_next(rsc_list); + + EXPECT_EQ(RM_DEVICE_AUDIO_DECODER, rm_resource_get_id(resource)); + EXPECT_EQ(RM_RSC_STATE_FREE, rm_resource_get_state(resource)); + EXPECT_EQ(-1, rm_resource_get_consumer(resource)); + EXPECT_STREQ("", rm_resource_get_app_id(resource)); + EXPECT_EQ(RM_CATEGORY_AUDIO_DECODER, rm_resource_get_category(resource)); + + resource = rm_resource_list_get_next(rsc_list); + + EXPECT_EQ(RM_DEVICE_VIDEO_DECODER_MAIN, rm_resource_get_id(resource)); + EXPECT_EQ(RM_RSC_STATE_FREE, rm_resource_get_state(resource)); + EXPECT_EQ(-1, rm_resource_get_consumer(resource)); + EXPECT_STREQ("", rm_resource_get_app_id(resource)); + EXPECT_LE(RM_CATEGORY_VIDEO_DECODER, rm_resource_get_category(resource)); + + resource = rm_resource_list_get_next(rsc_list); + + EXPECT_EQ(RM_DEVICE_VIDEO_DECODER_DVDE0, rm_resource_get_id(resource)); + EXPECT_EQ(RM_RSC_STATE_FREE, rm_resource_get_state(resource)); + EXPECT_EQ(-1, rm_resource_get_consumer(resource)); + EXPECT_STREQ("", rm_resource_get_app_id(resource)); + EXPECT_LE(RM_CATEGORY_VIDEO_DECODER_UHD, rm_resource_get_category(resource)); + + rm_free_resource_list(rsc_list); + + EXPECT_EQ(0, rm_unregister(handle)); + + RM_TEST_MSG("rm_get_resource_collection_state_p2 end..."); +} + + +static void tc_resource_state_change_cb1(rm_resource_state_h state, void *data) +{ + +} + +static void tc_resource_state_change_cb2(rm_resource_state_h state, void *data) +{ + +} + +static void tc_resource_state_change_cb3(rm_resource_state_h state, void *data) +{ + +} + +TEST(ut_rm_api, rm_resource_state_change_p1) +{ + RM_TEST_MSG("rm_resource_state_change_p1 start..."); + + EXPECT_EQ(RM_OK, rm_subscribe_resource_state_change(RM_CATEGORY_CAMERA, tc_resource_state_change_cb1, NULL)); + EXPECT_EQ(RM_ERROR, rm_subscribe_resource_state_change(RM_CATEGORY_CAMERA, tc_resource_state_change_cb1, NULL)); + EXPECT_EQ(RM_ERROR, rm_subscribe_resource_state_change(RM_CATEGORY_CAMERA, tc_resource_state_change_cb1, NULL)); + EXPECT_EQ(RM_OK, rm_subscribe_resource_state_change(RM_CATEGORY_CAMERA, tc_resource_state_change_cb2, NULL)); + EXPECT_EQ(RM_OK, rm_subscribe_resource_state_change(RM_CATEGORY_CAMERA, tc_resource_state_change_cb3, NULL)); + + EXPECT_EQ(RM_OK, rm_unsubscribe_resource_state_change(RM_CATEGORY_CAMERA, tc_resource_state_change_cb3)); + EXPECT_EQ(RM_OK, rm_unsubscribe_resource_state_change(RM_CATEGORY_CAMERA, tc_resource_state_change_cb2)); + EXPECT_EQ(RM_OK, rm_unsubscribe_resource_state_change(RM_CATEGORY_CAMERA, tc_resource_state_change_cb1)); + + RM_TEST_MSG("rm_resource_state_change_p1 end..."); +} + +TEST(ut_rm_api, rm_resource_state_change_p2) +{ + RM_TEST_MSG("rm_resource_state_change_p2 start..."); + + EXPECT_EQ(RM_OK, rm_subscribe_resource_state_change(RM_CATEGORY_CAMERA, tc_resource_state_change_cb1, NULL)); + EXPECT_EQ(RM_OK, rm_subscribe_resource_state_change(RM_CATEGORY_SCALER, tc_resource_state_change_cb1, NULL)); + EXPECT_EQ(RM_OK, rm_subscribe_resource_state_change(RM_CATEGORY_SCALER_BG, tc_resource_state_change_cb1, NULL)); + EXPECT_EQ(RM_OK, rm_subscribe_resource_state_change(RM_CATEGORY_SCALER_SUB, tc_resource_state_change_cb1, NULL)); + + EXPECT_EQ(RM_OK, rm_unsubscribe_resource_state_change(RM_CATEGORY_CAMERA, tc_resource_state_change_cb1)); + EXPECT_EQ(RM_OK, rm_unsubscribe_resource_state_change(RM_CATEGORY_SCALER, tc_resource_state_change_cb1)); + EXPECT_EQ(RM_OK, rm_unsubscribe_resource_state_change(RM_CATEGORY_SCALER_BG, tc_resource_state_change_cb1)); + EXPECT_EQ(RM_OK, rm_unsubscribe_resource_state_change(RM_CATEGORY_SCALER_SUB, tc_resource_state_change_cb1)); + + RM_TEST_MSG("rm_resource_state_change_p2 end..."); +} + +TEST(ut_rm_api, rm_resource_state_change_p3) +{ + RM_TEST_MSG("rm_resource_state_change_p3 start..."); + + EXPECT_EQ(RM_ERROR, rm_unsubscribe_resource_state_change(RM_CATEGORY_CAMERA, tc_resource_state_change_cb1)); + EXPECT_EQ(RM_ERROR, rm_unsubscribe_resource_state_change(RM_CATEGORY_SCALER, tc_resource_state_change_cb1)); + EXPECT_EQ(RM_ERROR, rm_unsubscribe_resource_state_change(RM_CATEGORY_SCALER_BG, tc_resource_state_change_cb1)); + EXPECT_EQ(RM_ERROR, rm_unsubscribe_resource_state_change(RM_CATEGORY_SCALER_SUB, tc_resource_state_change_cb1)); + + EXPECT_EQ(RM_OK, rm_subscribe_resource_state_change(RM_CATEGORY_CAMERA, tc_resource_state_change_cb1, NULL)); + EXPECT_EQ(RM_OK, rm_subscribe_resource_state_change(RM_CATEGORY_SCALER, tc_resource_state_change_cb1, NULL)); + EXPECT_EQ(RM_OK, rm_subscribe_resource_state_change(RM_CATEGORY_SCALER_BG, tc_resource_state_change_cb1, NULL)); + EXPECT_EQ(RM_OK, rm_subscribe_resource_state_change(RM_CATEGORY_SCALER_SUB, tc_resource_state_change_cb1, NULL)); + + EXPECT_EQ(RM_OK, rm_unsubscribe_resource_state_change(RM_CATEGORY_CAMERA, tc_resource_state_change_cb1)); + EXPECT_EQ(RM_OK, rm_unsubscribe_resource_state_change(RM_CATEGORY_SCALER, tc_resource_state_change_cb1)); + EXPECT_EQ(RM_OK, rm_unsubscribe_resource_state_change(RM_CATEGORY_SCALER_BG, tc_resource_state_change_cb1)); + EXPECT_EQ(RM_OK, rm_unsubscribe_resource_state_change(RM_CATEGORY_SCALER_SUB, tc_resource_state_change_cb1)); + + RM_TEST_MSG("rm_resource_state_change_p3 end..."); +} + +TEST(ut_rm_api, rm_resource_state_change_n1) +{ + RM_TEST_MSG("rm_resource_state_change_n1 start..."); + + EXPECT_EQ(RM_ERROR, rm_unsubscribe_resource_state_change(RM_CATEGORY_CAMERA, NULL)); + EXPECT_EQ(RM_ERROR, rm_subscribe_resource_state_change(RM_CATEGORY_CAMERA, NULL, NULL)); + + RM_TEST_MSG("rm_resource_state_change_n1 end..."); +} + +typedef struct{ + char *app_id; + int consumer_id; + int device_id; + int category_id; +} expected_conflict_event; + +void conflict_event_cb(rm_conflict_resource_h resource, void *data) +{ + RM_TEST_MSG("conflict event cb invoked!"); + if (!data) + return; + + expected_conflict_event *expected = (expected_conflict_event*) data; + + EXPECT_EQ(expected->category_id, rm_conflict_get_category_id(resource)); + EXPECT_EQ(expected->device_id, rm_conflict_get_device_id(resource)); + EXPECT_EQ(expected->consumer_id, rm_conflict_get_consumer_id(resource)); + EXPECT_STREQ(expected->app_id, rm_conflict_get_app_id(resource)); +} + +void conflict_event_cb2(rm_conflict_resource_h resource, void *data) +{ + +} + +TEST(ut_rm_api, rm_conflict_event_cb_p1) +{ + RM_TEST_MSG("rm_conflict_event_cb_p1 start..."); + + EXPECT_EQ(RM_OK, rm_subscribe_resource_conflict_event(conflict_event_cb, NULL)); + EXPECT_EQ(RM_ERROR, rm_subscribe_resource_conflict_event(conflict_event_cb, NULL)); + EXPECT_EQ(RM_OK, rm_unsubscribe_resource_conflict_event(conflict_event_cb)); + EXPECT_EQ(RM_ERROR, rm_unsubscribe_resource_conflict_event(conflict_event_cb)); + + RM_TEST_MSG("rm_conflict_event_cb_p1 end..."); +} + + +rm_cb_result resource_conflict_cb(int handle, rm_callback_type event, rm_device_request_s *info, void *data) +{ + RM_TEST_MSG("resource conflict cb invoked!"); + EXPECT_EQ(RM_OK, rm_deallocate_resources(handle, info)); + return RM_CB_RESULT_OK; +} + +TEST(ut_rm_api, rm_conflict_event_cb_p2) +{ + RM_TEST_MSG("rm_conflict_event_cb_p2 start..."); + + int handle1 = 0; + rm_consumer_info *consumer_info1 = (rm_consumer_info*) calloc(1, sizeof(rm_consumer_info)); + snprintf(consumer_info1->app_id, 1024, "%s", "org.tizen.rm.test"); + + EXPECT_EQ(RM_OK, rm_register(resource_conflict_cb, NULL, &handle1, consumer_info1)); + + rm_category_request_s request; + memset(&request, 0, sizeof(rm_category_request_s)); + + request.request_num = 1; + request.category_id[0] = RM_CATEGORY_JPEG_DECODER; + request.category_option[0] = ri_get_sub_jpeg_category_id("JPEG", 7680, 4320); + request.state[0] = RM_STATE_EXCLUSIVE; + + rm_device_return_s allocated; + memset(&allocated, 0, sizeof(rm_device_return_s)); + + EXPECT_EQ(RM_OK, rm_allocate_resources(handle1, &request, &allocated)); + + expected_conflict_event *expected = (expected_conflict_event*) calloc(1, sizeof(expected_conflict_event)); + expected->app_id = strdup("org.tizen.rm.test"); + + if (use_unified_jpeg_decoder()) + expected->category_id = RM_CATEGORY_JPEG_DECODER_8K; + else if (is_oscars_unified_jpeg_decoder()) + expected->category_id = RM_CATEGORY_JPEG_DECODER; + else + expected->category_id = RM_CATEGORY_JPEG_DECODER_UHD; + + expected->consumer_id = handle1; + expected->device_id = allocated.device_id[0]; + EXPECT_EQ(RM_OK, rm_subscribe_resource_conflict_event(conflict_event_cb, (void*) expected)); + + int handle2 = 0; + EXPECT_EQ(RM_OK, rm_register(resource_conflict_cb, NULL, &handle2, NULL)); + + memset(&request, 0, sizeof(rm_category_request_s)); + request.request_num = 1; + request.category_id[0] = RM_CATEGORY_JPEG_DECODER; + request.category_option[0] = ri_get_sub_jpeg_category_id("JPEG", 7680, 4320); + request.state[0] = RM_STATE_EXCLUSIVE; + + memset(&allocated, 0, sizeof(rm_device_return_s)); + EXPECT_EQ(RM_OK, rm_allocate_resources(handle2, &request, &allocated)); + + sleep(5); + + EXPECT_EQ(RM_OK, rm_unsubscribe_resource_conflict_event(conflict_event_cb)); + + free(consumer_info1); + consumer_info1 = NULL; + + EXPECT_EQ(RM_OK, rm_unregister(handle1)); + EXPECT_EQ(RM_OK, rm_unregister(handle2)); + + RM_TEST_MSG("rm_conflict_event_cb_p2 end..."); +} + +TEST(ut_rm_api, rm_conflict_event_cb_n1) +{ + RM_TEST_MSG("rm_conflict_event_cb_n1 start..."); + + EXPECT_EQ(RM_ERROR, rm_subscribe_resource_conflict_event(NULL, NULL)); + EXPECT_EQ(RM_ERROR, rm_unsubscribe_resource_conflict_event(NULL)); + + RM_TEST_MSG("rm_conflict_event_cb_n1 end..."); +} + +TEST(ut_rm_api, rm_conflict_event_cb_p3) +{ + RM_TEST_MSG("rm_conflict_event_cb_p3 start..."); + + EXPECT_EQ(RM_OK, rm_subscribe_resource_conflict_event(conflict_event_cb, NULL)); + EXPECT_EQ(RM_OK, rm_subscribe_resource_conflict_event(conflict_event_cb2, NULL)); + + EXPECT_EQ(RM_OK, rm_unsubscribe_resource_conflict_event(conflict_event_cb2)); + EXPECT_EQ(RM_OK, rm_unsubscribe_resource_conflict_event(conflict_event_cb)); + + RM_TEST_MSG("rm_conflict_event_cb_p3 end..."); +} diff --git a/ut/testcase/ut_tc_resource_scaler.cpp b/ut/testcase/ut_tc_resource_scaler.cpp new file mode 100644 index 0000000..9d6de5e --- /dev/null +++ b/ut/testcase/ut_tc_resource_scaler.cpp @@ -0,0 +1,253 @@ +/* + * Copyright (c) 2024 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 "gtest/gtest.h" +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +rm_cb_result rsc_conflict_cb(int handle, rm_callback_type event, rm_device_request_s *info, void *data) +{ + RM_TEST_MSG("resource conflict cb invoked!"); + EXPECT_EQ(RM_OK, rm_deallocate_resources(handle, info)); + return RM_CB_RESULT_OK; +} + +TEST(ut_rm_api, rm_get_scaler_state_p1) +{ + RM_TEST_MSG("rm_get_scaler_state_p1 start..."); + + int handle; + + EXPECT_EQ(RM_OK, rm_register(rsc_conflict_cb, NULL, &handle, NULL)); + + rm_category_request_s req; + memset(&req, 0, sizeof(req)); + + req.request_num = 1; + req.category_id[0] = RM_CATEGORY_SCALER; + req.state[0] = RM_STATE_EXCLUSIVE; + + rm_device_return_s allocated; + memset(&allocated, 0, sizeof(allocated)); + + EXPECT_EQ(RM_OK, rm_allocate_resources(handle, &req, &allocated)); + + EXPECT_EQ(1, allocated.allocated_num); + EXPECT_EQ(RI_VIRTUAL_ID_SCALER, allocated.device_id[0]); + EXPECT_EQ(RM_DEVICE_SCALER, rm_find_device_id(allocated.device_id[0])); + + EXPECT_EQ(RM_OK, rm_unregister(handle)); + + rm_resource_list_h scaler_list_h; + int result = rm_get_scaler_state(&scaler_list_h); + EXPECT_EQ(RM_OK, result); + + if (result != RM_OK) { + RM_TEST_MSG("rm_get_scaler_state_p1 end..."); + rm_free_resource_list(scaler_list_h); + return; + } + + EXPECT_EQ(2, rm_resource_list_get_count(scaler_list_h)); + + // main scaler + rm_resource_h rsc = rm_resource_list_get_first(scaler_list_h); + EXPECT_EQ(RM_CATEGORY_SCALER, rm_resource_get_category(rsc)); + EXPECT_EQ(RM_DEVICE_SCALER, rm_resource_get_id(rsc)); + EXPECT_EQ(RM_RSC_STATE_FREE, rm_resource_get_state(rsc)); + EXPECT_EQ(-1, rm_resource_get_consumer(rsc)); + EXPECT_STREQ("", rm_resource_get_app_id(rsc)); + + // sub scaler + rsc = rm_resource_list_get_next(scaler_list_h); + EXPECT_EQ(RM_CATEGORY_SCALER_SUB, rm_resource_get_category(rsc)); + EXPECT_EQ(RM_DEVICE_SCALER_SUB, rm_resource_get_id(rsc)); + EXPECT_EQ(RM_RSC_STATE_FREE, rm_resource_get_state(rsc)); + EXPECT_EQ(-1, rm_resource_get_consumer(rsc)); + EXPECT_STREQ("", rm_resource_get_app_id(rsc)); + + rm_free_resource_list(scaler_list_h); + + RM_TEST_MSG("rm_get_scaler_state_p1 end..."); +} + +TEST(ut_rm_api, rm_get_scaler_state_p2) +{ + RM_TEST_MSG("rm_get_scaler_state_p2 start..."); + + int handle; + char *app_id1 = (char*) "org.tizen.rsc.test"; + + EXPECT_EQ(RM_OK, rm_register(rsc_conflict_cb, NULL, &handle, NULL)); + EXPECT_EQ(RM_OK, rm_set_app_id(handle, app_id1)); + + rm_category_request_s req; + memset(&req, 0, sizeof(req)); + + req.request_num = 1; + req.category_id[0] = RM_CATEGORY_SCALER; + req.state[0] = RM_STATE_EXCLUSIVE; + + rm_device_return_s allocated; + memset(&allocated, 0, sizeof(allocated)); + + EXPECT_EQ(RM_OK, rm_allocate_resources(handle, &req, &allocated)); + + EXPECT_EQ(1, allocated.allocated_num); + EXPECT_EQ(RI_VIRTUAL_ID_SCALER, allocated.device_id[0]); + EXPECT_EQ(RM_DEVICE_SCALER, rm_find_device_id(allocated.device_id[0])); + + + rm_resource_list_h scaler_list_h; + int result = rm_get_scaler_state(&scaler_list_h); + EXPECT_EQ(RM_OK, result); + + if (result != RM_OK) { + EXPECT_EQ(RM_OK, rm_unregister(handle)); + rm_free_resource_list(scaler_list_h); + RM_TEST_MSG("rm_get_scaler_state_p2 end..."); + return; + } + + EXPECT_EQ(2, rm_resource_list_get_count(scaler_list_h)); + + // main scaler + rm_resource_h rsc = rm_resource_list_get_first(scaler_list_h); + EXPECT_EQ(RM_CATEGORY_SCALER, rm_resource_get_category(rsc)); + EXPECT_EQ(RM_DEVICE_SCALER, rm_resource_get_id(rsc)); + EXPECT_EQ(RM_RSC_STATE_EXCLUSIVE, rm_resource_get_state(rsc)); + EXPECT_EQ(handle, rm_resource_get_consumer(rsc)); + EXPECT_STREQ(app_id1, rm_resource_get_app_id(rsc)); + + // sub scaler + rsc = rm_resource_list_get_next(scaler_list_h); + EXPECT_EQ(RM_CATEGORY_SCALER_SUB, rm_resource_get_category(rsc)); + EXPECT_EQ(RM_DEVICE_SCALER_SUB, rm_resource_get_id(rsc)); + EXPECT_EQ(RM_RSC_STATE_FREE, rm_resource_get_state(rsc)); + EXPECT_EQ(-1, rm_resource_get_consumer(rsc)); + EXPECT_STREQ("", rm_resource_get_app_id(rsc)); + + rm_free_resource_list(scaler_list_h); + + EXPECT_EQ(RM_OK, rm_unregister(handle)); + RM_TEST_MSG("rm_get_scaler_state_p2 end..."); +} + +/* issue : video decoder(mem cluster) conflict & rsc(sub scaler) conflict + */ +TEST(ut_rm_api, rm_conflict11) +{ + RM_TEST_MSG("rm_conflict11 start..."); + + TCPlayer *player = new TCPlayer(); + player->AddResource(RM_CATEGORY_VIDEO_DECODER, RM_DEVICE_OPT_MAIN, RM_STATE_EXCLUSIVE); + player->AddResource(RM_CATEGORY_SCALER_SUB, RM_STATE_EXCLUSIVE); + + EXPECT_EQ(RM_OK, player->Register()); + EXPECT_EQ(RM_OK, player->AllocateResources()); + + TCPlayer *player2 = new TCPlayer(); + player2->AddResource(RM_CATEGORY_VIDEO_DECODER, RM_DEVICE_OPT_MAIN, RM_STATE_EXCLUSIVE); + player2->AddResource(RM_CATEGORY_SCALER_SUB, RM_STATE_EXCLUSIVE); + + EXPECT_EQ(RM_OK, player2->Register()); + EXPECT_EQ(RM_OK, player2->AllocateResources()); + + EXPECT_EQ(1, player->GetConflictNum()); + EXPECT_EQ(2, player->GetConflictedResourcesNum()); + + EXPECT_EQ(RM_OK, player->Unregister()); + EXPECT_EQ(RM_OK, player2->Unregister()); + + delete player; + delete player2; + + sleep(RM_TEST_SLEEP_TIME); + RM_TEST_MSG("rm_conflict11 end..."); +} + +/* issue : rsc(sub scaler) conflict + */ +TEST(ut_rm_api, rm_conflict14) +{ + TCPlayer *player = new TCPlayer(); + player->AddResource(RM_CATEGORY_VIDEO_DECODER, RM_DEVICE_OPT_MAIN, RM_STATE_EXCLUSIVE); + player->AddResource(RM_CATEGORY_SCALER_SUB, RM_STATE_EXCLUSIVE); + + EXPECT_EQ(RM_OK, player->Register()); + EXPECT_EQ(RM_OK, player->AllocateResources()); + + TCPlayer *player2 = new TCPlayer(); + player2->AddResource(RM_CATEGORY_VIDEO_DECODER, RM_CATEGORY_VIDEO_DECODER_MPEG4_FHD_8BIT_30P, RM_STATE_EXCLUSIVE); + player2->AddResource(RM_CATEGORY_SCALER_SUB, RM_STATE_EXCLUSIVE); + + EXPECT_EQ(RM_OK, player2->Register()); + EXPECT_EQ(RM_OK, player2->AllocateResources()); + + EXPECT_EQ(1, player->GetConflictNum()); + EXPECT_EQ(1, player->GetConflictedResourcesNum()); + + EXPECT_EQ(RM_OK, player->Unregister()); + EXPECT_EQ(RM_OK, player2->Unregister()); + + delete player; + delete player2; + + sleep(RM_TEST_SLEEP_TIME); +} + +/* issue : rsc(sub scaler) conflict + */ +TEST(ut_rm_api, rm_conflict16) +{ + TCPlayer *player = new TCPlayer(); + player->AddResource(RM_CATEGORY_VIDEO_DECODER, RM_CATEGORY_VIDEO_DECODER_MPEG4_FHD_8BIT_30P, RM_STATE_EXCLUSIVE); + player->AddResource(RM_CATEGORY_SCALER_SUB, RM_STATE_EXCLUSIVE); + + EXPECT_EQ(RM_OK, player->Register()); + EXPECT_EQ(RM_OK, player->AllocateResources()); + + TCPlayer *player2 = new TCPlayer(); + player2->AddResource(RM_CATEGORY_VIDEO_DECODER, RM_CATEGORY_VIDEO_DECODER_MPEG4_FHD_8BIT_30P, RM_STATE_EXCLUSIVE); + player2->AddResource(RM_CATEGORY_SCALER_SUB, RM_STATE_EXCLUSIVE); + + EXPECT_EQ(RM_OK, player2->Register()); + EXPECT_EQ(RM_OK, player2->AllocateResources()); + + EXPECT_EQ(1, player->GetConflictNum()); + EXPECT_EQ(1, player->GetConflictedResourcesNum()); + + EXPECT_EQ(RM_OK, player->Unregister()); + EXPECT_EQ(RM_OK, player2->Unregister()); + + delete player; + delete player2; + + sleep(RM_TEST_SLEEP_TIME); +} \ No newline at end of file diff --git a/ut/testcase/ut_tc_video_dec_ai.cpp b/ut/testcase/ut_tc_video_dec_ai.cpp new file mode 100644 index 0000000..e64d593 --- /dev/null +++ b/ut/testcase/ut_tc_video_dec_ai.cpp @@ -0,0 +1,341 @@ +/* + * Copyright (c) 2024 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 "gtest/gtest.h" +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +TEST(ut_rm_api, alloc_ai_video_dec_hevc_fhd_p1) +{ + RM_TEST_MSG("alloc_ai_video_dec_hevc_fhd_p1 start..."); + + int handle = 0; + rm_tc_reset_conflict_num(); + + EXPECT_EQ(RM_OK, rm_register(rm_cb_counting_conflicted, NULL, &handle, NULL)); + + rm_category_request_s request; + memset(&request, 0, sizeof(rm_category_request_s)); + + ri_video_category_option_request_s option; + memset(&option, 0, sizeof(ri_video_category_option_request_s)); + + option.codec_name = "HEVC"; + option.color_depth = 8; + option.framerate = 30; + option.h_size = 1920; + option.v_size = 1080; + option.sampling_format = RI_SAMPLING_FORMAT_420; + + request.request_num = 1; + request.category_id[0] = RM_CATEGORY_VIDEO_DECODER; + request.category_option[0] = ri_get_ai_decoder_category_id(ri_get_capable_video_category_id(&option)); + request.state[0] = RM_STATE_EXCLUSIVE; + + rm_device_return_s allocated; + memset(&allocated, 0, sizeof(rm_device_return_s)); + + EXPECT_EQ(RM_OK, rm_allocate_resources(handle, &request, &allocated)); + EXPECT_EQ(1, allocated.allocated_num); + + int expected = is_support_8k() ? RM_DEVICE_VIDEO_DECODER_HEVC_8K : RM_DEVICE_VIDEO_DECODER_DVDE0; + + EXPECT_EQ(expected, allocated.device_id[0]); + EXPECT_EQ(0, rm_tc_get_conflict_num()); + rm_tc_reset_conflict_num(); + + EXPECT_EQ(RM_OK, rm_unregister(handle)); + + RM_TEST_MSG("alloc_ai_video_dec_hevc_fhd_p1 end..."); +} + +TEST(ut_rm_api, alloc_ai_video_dec_hevc_uhd_p1) +{ + RM_TEST_MSG("alloc_ai_video_dec_hevc_uhd_p1 start..."); + + int handle = 0; + rm_tc_reset_conflict_num(); + + EXPECT_EQ(RM_OK, rm_register(rm_cb_counting_conflicted, NULL, &handle, NULL)); + + rm_category_request_s request; + memset(&request, 0, sizeof(rm_category_request_s)); + + ri_video_category_option_request_s option; + memset(&option, 0, sizeof(ri_video_category_option_request_s)); + + option.codec_name = "HEVC"; + option.color_depth = 8; + option.framerate = 30; + option.h_size = 3840; + option.v_size = 2160; + option.sampling_format = RI_SAMPLING_FORMAT_420; + + request.request_num = 1; + request.category_id[0] = RM_CATEGORY_VIDEO_DECODER; + request.category_option[0] = ri_get_ai_decoder_category_id(ri_get_capable_video_category_id(&option)); + request.state[0] = RM_STATE_EXCLUSIVE; + + rm_device_return_s allocated; + memset(&allocated, 0, sizeof(rm_device_return_s)); + + EXPECT_EQ(RM_OK, rm_allocate_resources(handle, &request, &allocated)); + EXPECT_EQ(1, allocated.allocated_num); + + int expected = is_support_8k() ? RM_DEVICE_VIDEO_DECODER_HEVC_8K : RM_DEVICE_VIDEO_DECODER_DVDE0; + + EXPECT_EQ(expected, allocated.device_id[0]); + EXPECT_EQ(0, rm_tc_get_conflict_num()); + rm_tc_reset_conflict_num(); + + EXPECT_EQ(RM_OK, rm_unregister(handle)); + + RM_TEST_MSG("alloc_ai_video_dec_hevc_uhd_p1 end..."); +} + +TEST(ut_rm_api, alloc_ai_video_dec_hevc_8k_p1) +{ + RM_TEST_MSG("alloc_ai_video_dec_hevc_8k_p1 start..."); + + int handle = 0; + rm_tc_reset_conflict_num(); + + EXPECT_EQ(RM_OK, rm_register(rm_cb_counting_conflicted, NULL, &handle, NULL)); + + rm_category_request_s request; + memset(&request, 0, sizeof(rm_category_request_s)); + + ri_video_category_option_request_s option; + memset(&option, 0, sizeof(ri_video_category_option_request_s)); + + option.codec_name = "HEVC"; + option.color_depth = 8; + option.framerate = 60; + option.h_size = 7680; + option.v_size = 4320; + option.sampling_format = RI_SAMPLING_FORMAT_420; + + request.request_num = 1; + request.category_id[0] = RM_CATEGORY_VIDEO_DECODER; + request.category_option[0] = ri_get_capable_video_category_id(&option); + request.state[0] = RM_STATE_EXCLUSIVE; + + rm_device_return_s allocated; + memset(&allocated, 0, sizeof(rm_device_return_s)); + + if (is_support_8k()) { + EXPECT_EQ(RM_OK, rm_allocate_resources(handle, &request, &allocated)); + EXPECT_EQ(1, allocated.allocated_num); + EXPECT_EQ(RM_DEVICE_VIDEO_DECODER_HEVC_8K, allocated.device_id[0]); + } else { + EXPECT_NE(RM_OK, rm_allocate_resources(handle, &request, &allocated)); + EXPECT_EQ(0, allocated.allocated_num); + } + + EXPECT_EQ(0, rm_tc_get_conflict_num()); + rm_tc_reset_conflict_num(); + + EXPECT_EQ(RM_OK, rm_unregister(handle)); + + RM_TEST_MSG("alloc_ai_video_dec_hevc_8k_p1 end..."); +} + +TEST(ut_rm_api, alloc_ai_video_dec_av1_fhd_p1) +{ + RM_TEST_MSG("alloc_ai_video_dec_av1_fhd_p1 start..."); + + int handle = 0; + rm_tc_reset_conflict_num(); + + EXPECT_EQ(RM_OK, rm_register(rm_cb_counting_conflicted, NULL, &handle, NULL)); + + rm_category_request_s request; + memset(&request, 0, sizeof(rm_category_request_s)); + + ri_video_category_option_request_s option; + memset(&option, 0, sizeof(ri_video_category_option_request_s)); + + option.codec_name = "AV1"; + option.color_depth = 8; + option.framerate = 30; + option.h_size = 1920; + option.v_size = 1080; + option.sampling_format = RI_SAMPLING_FORMAT_420; + + request.request_num = 1; + request.category_id[0] = RM_CATEGORY_VIDEO_DECODER; + request.category_option[0] = ri_get_ai_decoder_category_id(ri_get_capable_video_category_id(&option)); + request.state[0] = RM_STATE_EXCLUSIVE; + + rm_device_return_s allocated; + memset(&allocated, 0, sizeof(rm_device_return_s)); + + EXPECT_EQ(RM_OK, rm_allocate_resources(handle, &request, &allocated)); + EXPECT_EQ(1, allocated.allocated_num); + + int expected = is_support_8k() ? RM_DEVICE_VIDEO_DECODER_HEVC_8K : RM_DEVICE_VIDEO_DECODER_DVDE0; + + EXPECT_EQ(expected, allocated.device_id[0]); + EXPECT_EQ(0, rm_tc_get_conflict_num()); + rm_tc_reset_conflict_num(); + + EXPECT_EQ(RM_OK, rm_unregister(handle)); + + RM_TEST_MSG("alloc_ai_video_dec_av1_fhd_p1 end..."); +} + +TEST(ut_rm_api, alloc_ai_video_dec_av1_uhd_p1) +{ + RM_TEST_MSG("alloc_ai_video_dec_av1_uhd_p1 start..."); + + int handle = 0; + rm_tc_reset_conflict_num(); + + EXPECT_EQ(RM_OK, rm_register(rm_cb_counting_conflicted, NULL, &handle, NULL)); + + rm_category_request_s request; + memset(&request, 0, sizeof(rm_category_request_s)); + + ri_video_category_option_request_s option; + memset(&option, 0, sizeof(ri_video_category_option_request_s)); + + option.codec_name = "AV1"; + option.color_depth = 8; + option.framerate = 30; + option.h_size = 3840; + option.v_size = 2160; + option.sampling_format = RI_SAMPLING_FORMAT_420; + + request.request_num = 1; + request.category_id[0] = RM_CATEGORY_VIDEO_DECODER; + request.category_option[0] = ri_get_ai_decoder_category_id(ri_get_capable_video_category_id(&option)); + request.state[0] = RM_STATE_EXCLUSIVE; + + rm_device_return_s allocated; + memset(&allocated, 0, sizeof(rm_device_return_s)); + + EXPECT_EQ(RM_OK, rm_allocate_resources(handle, &request, &allocated)); + EXPECT_EQ(1, allocated.allocated_num); + + int expected = is_support_8k() ? RM_DEVICE_VIDEO_DECODER_HEVC_8K : RM_DEVICE_VIDEO_DECODER_DVDE0; + + EXPECT_EQ(expected, allocated.device_id[0]); + EXPECT_EQ(0, rm_tc_get_conflict_num()); + rm_tc_reset_conflict_num(); + + EXPECT_EQ(RM_OK, rm_unregister(handle)); + + RM_TEST_MSG("alloc_ai_video_dec_av1_uhd_p1 end..."); +} + +TEST(ut_rm_api, alloc_ai_video_dec_av1_8k_p1) +{ + RM_TEST_MSG("alloc_ai_video_dec_av1_8k_p1 start..."); + + int handle = 0; + rm_tc_reset_conflict_num(); + + EXPECT_EQ(RM_OK, rm_register(rm_cb_counting_conflicted, NULL, &handle, NULL)); + + rm_category_request_s request; + memset(&request, 0, sizeof(rm_category_request_s)); + + ri_video_category_option_request_s option; + memset(&option, 0, sizeof(ri_video_category_option_request_s)); + + option.codec_name = "AV1"; + option.color_depth = 8; + option.framerate = 60; + option.h_size = 7680; + option.v_size = 4320; + option.sampling_format = RI_SAMPLING_FORMAT_420; + + request.request_num = 1; + request.category_id[0] = RM_CATEGORY_VIDEO_DECODER; + request.category_option[0] = ri_get_capable_video_category_id(&option); + request.state[0] = RM_STATE_EXCLUSIVE; + + rm_device_return_s allocated; + memset(&allocated, 0, sizeof(rm_device_return_s)); + + if (is_support_8k()) { + EXPECT_EQ(RM_OK, rm_allocate_resources(handle, &request, &allocated)); + EXPECT_EQ(1, allocated.allocated_num); + EXPECT_EQ(RM_DEVICE_VIDEO_DECODER_HEVC_8K, allocated.device_id[0]); + } else { + EXPECT_NE(RM_OK, rm_allocate_resources(handle, &request, &allocated)); + EXPECT_EQ(0, allocated.allocated_num); + } + + EXPECT_EQ(0, rm_tc_get_conflict_num()); + rm_tc_reset_conflict_num(); + + EXPECT_EQ(RM_OK, rm_unregister(handle)); + + RM_TEST_MSG("alloc_ai_video_dec_av1_8k_p1 end..."); +} + +TEST(ut_rm_api, alloc_ai_video_dec_h264_n1) +{ + RM_TEST_MSG("alloc_ai_video_dec_h264_n1 start..."); + + int handle = 0; + rm_tc_reset_conflict_num(); + + EXPECT_EQ(RM_OK, rm_register(rm_cb_counting_conflicted, NULL, &handle, NULL)); + + rm_category_request_s request; + memset(&request, 0, sizeof(rm_category_request_s)); + + ri_video_category_option_request_s option; + memset(&option, 0, sizeof(ri_video_category_option_request_s)); + + option.codec_name = "H264"; + option.color_depth = 8; + option.framerate = 30; + option.h_size = 1920; + option.v_size = 1080; + option.sampling_format = RI_SAMPLING_FORMAT_420; + + request.request_num = 1; + request.category_id[0] = RM_CATEGORY_VIDEO_DECODER; + request.category_option[0] = ri_get_ai_decoder_category_id(ri_get_capable_video_category_id(&option)); + request.state[0] = RM_STATE_EXCLUSIVE; + + rm_device_return_s allocated; + memset(&allocated, 0, sizeof(rm_device_return_s)); + + EXPECT_EQ(RM_OK, rm_allocate_resources(handle, &request, &allocated)); + EXPECT_EQ(1, allocated.allocated_num); + EXPECT_NE(RM_DEVICE_VIDEO_DECODER_DVDE0, allocated.device_id[0]); + EXPECT_EQ(0, rm_tc_get_conflict_num()); + rm_tc_reset_conflict_num(); + + EXPECT_EQ(RM_OK, rm_unregister(handle)); + + RM_TEST_MSG("alloc_ai_video_dec_h264_n1 end..."); +} diff --git a/ut/testcase/ut_tc_video_dec_portrait.cpp b/ut/testcase/ut_tc_video_dec_portrait.cpp new file mode 100644 index 0000000..ff3a0d1 --- /dev/null +++ b/ut/testcase/ut_tc_video_dec_portrait.cpp @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2024 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 "gtest/gtest.h" +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +TEST(ut_rm_api, video_decoder_portrait_dtv_1080_1920) +{ + ri_video_category_option_request_s option; + memset(&option, 0, sizeof(ri_video_category_option_request_s)); + + option.codec_name = "HEVC"; + option.color_depth = 8; + option.framerate = 30; + option.h_size = 1080; + option.v_size = 1920; // Max height supported by mfc is 1080 + option.sampling_format = RI_SAMPLING_FORMAT_420; + + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_HEVC_UHD_8BIT_30P , ri_get_capable_video_category_id(&option)); +} + +TEST(ut_rm_api, video_decoder_portrait_dtv_720_1280) +{ + ri_video_category_option_request_s option; + memset(&option, 0, sizeof(ri_video_category_option_request_s)); + + option.codec_name = "HEVC"; + option.color_depth = 8; + option.framerate = 30; + option.h_size = 720; + option.v_size = 1280; // Max height supported by mfc is 1080 + option.sampling_format = RI_SAMPLING_FORMAT_420; + + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_HEVC_UHD_8BIT_30P , ri_get_capable_video_category_id(&option)); +} + +TEST(ut_rm_api, video_decoder_portrait_dtv_480_640) +{ + ri_video_category_option_request_s option; + memset(&option, 0, sizeof(ri_video_category_option_request_s)); + + option.codec_name = "HEVC"; + option.color_depth = 8; + option.framerate = 30; + option.h_size = 480; + option.v_size = 640; // Max height supported by mfc is 1080 + option.sampling_format = RI_SAMPLING_FORMAT_420; + + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_HEVC_FHD_8BIT_30P , ri_get_capable_video_category_id(&option)); +} + +TEST(ut_rm_api, video_decoder_portrait_dtv_2160_3840) +{ + ri_video_category_option_request_s option; + memset(&option, 0, sizeof(ri_video_category_option_request_s)); + + option.codec_name = "HEVC"; + option.color_depth = 8; + option.framerate = 30; + option.h_size = 2160; + option.v_size = 3840; // Max height supported by dvde is 2160 + option.sampling_format = RI_SAMPLING_FORMAT_420; + + EXPECT_EQ(RI_CATEGORY_VIDEO_DECODER_NOT_SUPPORTED , ri_get_capable_video_category_id(&option)); +} \ No newline at end of file diff --git a/ut/testcase/ut_tc_virtual_scaler.cpp b/ut/testcase/ut_tc_virtual_scaler.cpp new file mode 100644 index 0000000..26a8676 --- /dev/null +++ b/ut/testcase/ut_tc_virtual_scaler.cpp @@ -0,0 +1,632 @@ +/* + * Copyright (c) 2024 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 "gtest/gtest.h" +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +static int cb_handle = 0; +static int cb_time = 0; + +rm_cb_result _conflict_cb(int handle, rm_callback_type event, rm_device_request_s *info, void *data) +{ + cb_handle = handle; + cb_time++; + rm_unregister(handle); + return RM_CB_RESULT_OK; +} + +void _reset_cb_info(void) +{ + cb_handle = -1; + cb_time = 0; +} + +int _get_conflict_num(void) +{ + return cb_time; +} + +int _get_conflict_handle(void) +{ + return cb_handle; +} + +TEST(ut_rm_api, rm_virtual_scaler_p1) +{ + RM_TEST_MSG("rm_virtual_scaler_p1 start..."); + + int handle = 0; + + EXPECT_EQ(RM_OK, rm_register(_conflict_cb, NULL, &handle, NULL)); + + rm_category_request_s req; + memset(&req, 0, sizeof(rm_category_request_s)); + + req.request_num = 1; + req.category_id[0] = RM_CATEGORY_SCALER; + req.state[0] = RM_STATE_EXCLUSIVE; + + rm_device_return_s allocated; + memset(&allocated, 0, sizeof(rm_device_return_s)); + + EXPECT_EQ(RM_OK, rm_allocate_resources(handle, &req, &allocated)); + + EXPECT_EQ(1, allocated.allocated_num); + EXPECT_EQ(RI_VIRTUAL_ID_SCALER, allocated.device_id[0]); + EXPECT_EQ(RM_DEVICE_SCALER, rm_find_device_id(allocated.device_id[0])); + + rm_resource_state_e state; + EXPECT_EQ(RM_OK, rm_get_resource_state(RM_DEVICE_SCALER, &state)); + EXPECT_EQ(RM_RSC_STATE_EXCLUSIVE, state); + + rm_device_request_s req_release; + memset(&req_release, 0, sizeof(rm_device_request_s)); + + req_release.request_num = 1; + req_release.device_id[0] = allocated.device_id[0]; + + EXPECT_EQ(RM_OK, rm_deallocate_resources(handle, &req_release)); + + EXPECT_EQ(RM_OK, rm_get_resource_state(RM_DEVICE_SCALER, &state)); + EXPECT_EQ(RM_RSC_STATE_FREE, state); + + EXPECT_EQ(RM_OK, rm_unregister(handle)); + + RM_TEST_MSG("rm_virtual_scaler_p1 end..."); +} + +TEST(ut_rm_api, rm_virtual_scaler_p2) +{ + RM_TEST_MSG("rm_virtual_scaler_p2 start..."); + + // Step#1 Allocate main scaler + int handle = 0; + + EXPECT_EQ(RM_OK, rm_register(_conflict_cb, NULL, &handle, NULL)); + + rm_category_request_s req; + memset(&req, 0, sizeof(rm_category_request_s)); + + req.request_num = 1; + req.category_id[0] = RM_CATEGORY_SCALER; + req.state[0] = RM_STATE_EXCLUSIVE; + + rm_device_return_s allocated; + memset(&allocated, 0, sizeof(rm_device_return_s)); + + EXPECT_EQ(RM_OK, rm_allocate_resources(handle, &req, &allocated)); + + EXPECT_EQ(1, allocated.allocated_num); + EXPECT_EQ(RI_VIRTUAL_ID_SCALER, allocated.device_id[0]); + EXPECT_EQ(RM_DEVICE_SCALER, rm_find_device_id(allocated.device_id[0])); + + rm_resource_state_e state; + EXPECT_EQ(RM_OK, rm_get_resource_state(RM_DEVICE_SCALER, &state)); + EXPECT_EQ(RM_RSC_STATE_EXCLUSIVE, state); + + // Step#2 Allocate sub scaler + int handle2 = 0; + + EXPECT_EQ(RM_OK, rm_register(_conflict_cb, NULL, &handle2, NULL)); + + memset(&req, 0, sizeof(rm_category_request_s)); + + req.request_num = 1; + req.category_id[0] = RM_CATEGORY_SCALER_SUB; + req.state[0] = RM_STATE_EXCLUSIVE; + + rm_device_return_s allocated2; + memset(&allocated2, 0, sizeof(rm_device_return_s)); + + EXPECT_EQ(RM_OK, rm_allocate_resources(handle2, &req, &allocated2)); + + EXPECT_EQ(1, allocated2.allocated_num); + EXPECT_EQ((RI_VIRTUAL_ID_SCALER + 1), allocated2.device_id[0]); + EXPECT_EQ(RM_DEVICE_SCALER_SUB, rm_find_device_id(allocated2.device_id[0])); + + EXPECT_EQ(RM_OK, rm_get_resource_state(RM_DEVICE_SCALER_SUB, &state)); + EXPECT_EQ(RM_RSC_STATE_EXCLUSIVE, state); + + // Step#3 Release main scaler + rm_device_request_s req_release; + memset(&req_release, 0, sizeof(rm_device_request_s)); + + req_release.request_num = 1; + req_release.device_id[0] = allocated.device_id[0]; + + EXPECT_EQ(RM_OK, rm_deallocate_resources(handle, &req_release)); + + EXPECT_EQ(RM_OK, rm_get_resource_state(RM_DEVICE_SCALER, &state)); + EXPECT_EQ(RM_RSC_STATE_FREE, state); + + // Step#4 Release sub scaler + memset(&req_release, 0, sizeof(rm_device_request_s)); + + req_release.request_num = 1; + req_release.device_id[0] = allocated2.device_id[0]; + + EXPECT_EQ(RM_OK, rm_deallocate_resources(handle2, &req_release)); + + EXPECT_EQ(RM_OK, rm_get_resource_state(RM_DEVICE_SCALER_SUB, &state)); + EXPECT_EQ(RM_RSC_STATE_FREE, state); + + EXPECT_EQ(RM_OK, rm_unregister(handle)); + EXPECT_EQ(RM_OK, rm_unregister(handle2)); + + RM_TEST_MSG("rm_virtual_scaler_p2 end..."); +} + +TEST(ut_rm_api, rm_virtual_scaler_p3) +{ + RM_TEST_MSG("rm_virtual_scaler_p3 start..."); + + // Step#1 Allocate sub scaler + int handle = 0; + + EXPECT_EQ(RM_OK, rm_register(_conflict_cb, NULL, &handle, NULL)); + + rm_category_request_s req; + memset(&req, 0, sizeof(rm_category_request_s)); + + req.request_num = 1; + req.category_id[0] = RM_CATEGORY_SCALER_SUB; + req.state[0] = RM_STATE_EXCLUSIVE; + + rm_device_return_s allocated; + memset(&allocated, 0, sizeof(rm_device_return_s)); + + EXPECT_EQ(RM_OK, rm_allocate_resources(handle, &req, &allocated)); + + EXPECT_EQ(1, allocated.allocated_num); + EXPECT_EQ(RI_VIRTUAL_ID_SCALER + 1, allocated.device_id[0]); + EXPECT_EQ(RM_DEVICE_SCALER_SUB, rm_find_device_id(allocated.device_id[0])); + + rm_resource_state_e state; + EXPECT_EQ(RM_OK, rm_get_resource_state(RM_DEVICE_SCALER_SUB, &state)); + EXPECT_EQ(RM_RSC_STATE_EXCLUSIVE, state); + + // Step#2 Allocate main scaler + int handle2 = 0; + + EXPECT_EQ(RM_OK, rm_register(_conflict_cb, NULL, &handle2, NULL)); + + memset(&req, 0, sizeof(rm_category_request_s)); + + req.request_num = 1; + req.category_id[0] = RM_CATEGORY_SCALER; + req.state[0] = RM_STATE_EXCLUSIVE; + + rm_device_return_s allocated2; + memset(&allocated2, 0, sizeof(rm_device_return_s)); + + EXPECT_EQ(RM_OK, rm_allocate_resources(handle2, &req, &allocated2)); + + EXPECT_EQ(1, allocated2.allocated_num); + EXPECT_EQ(RI_VIRTUAL_ID_SCALER, allocated2.device_id[0]); + EXPECT_EQ(RM_DEVICE_SCALER, rm_find_device_id(allocated2.device_id[0])); + + EXPECT_EQ(RM_OK, rm_get_resource_state(RM_DEVICE_SCALER, &state)); + EXPECT_EQ(RM_RSC_STATE_EXCLUSIVE, state); + + // Step#3 Release sub scaler + rm_device_request_s req_release; + memset(&req_release, 0, sizeof(rm_device_request_s)); + + req_release.request_num = 1; + req_release.device_id[0] = allocated.device_id[0]; + + EXPECT_EQ(RM_OK, rm_deallocate_resources(handle, &req_release)); + + EXPECT_EQ(RM_OK, rm_get_resource_state(RM_DEVICE_SCALER_SUB, &state)); + EXPECT_EQ(RM_RSC_STATE_FREE, state); + + // Step#4 Release main scaler + memset(&req_release, 0, sizeof(rm_device_request_s)); + + req_release.request_num = 1; + req_release.device_id[0] = allocated2.device_id[0]; + + EXPECT_EQ(RM_OK, rm_deallocate_resources(handle2, &req_release)); + + EXPECT_EQ(RM_OK, rm_get_resource_state(RM_DEVICE_SCALER, &state)); + EXPECT_EQ(RM_RSC_STATE_FREE, state); + + EXPECT_EQ(RM_OK, rm_unregister(handle)); + EXPECT_EQ(RM_OK, rm_unregister(handle2)); + + RM_TEST_MSG("rm_virtual_scaler_p3 end..."); +} + +TEST(ut_rm_api, rm_virtual_scaler_p4) +{ + RM_TEST_MSG("rm_virtual_scaler_p4 start..."); + _reset_cb_info(); + + /* TEST SCENARIO + * 1. Allocate main scaler + * 2. Allocate main scaler (conflict with player 1) + */ + + TCPlayer *player = new TCPlayer(); + player->AddResource(RM_CATEGORY_SCALER, RM_STATE_EXCLUSIVE); + + EXPECT_EQ(RM_OK, player->Register()); + EXPECT_EQ(RM_OK, player->AllocateResources()); + + EXPECT_EQ(RI_VIRTUAL_ID_SCALER, player->GetAllocatedResourceId(1)); + EXPECT_EQ(RM_DEVICE_SCALER, rm_find_device_id(player->GetAllocatedResourceId(1))); + + rm_resource_state_e state; + EXPECT_EQ(RM_OK, rm_get_resource_state(RM_DEVICE_SCALER, &state)); + EXPECT_EQ(RM_RSC_STATE_EXCLUSIVE, state); + + TCPlayer *player2 = new TCPlayer(); + player2->AddResource(RM_CATEGORY_SCALER, RM_STATE_EXCLUSIVE); + + EXPECT_EQ(RM_OK, player2->Register()); + EXPECT_EQ(RM_OK, player2->AllocateResources()); + + EXPECT_EQ(RI_VIRTUAL_ID_SCALER, player2->GetAllocatedResourceId(1)); + EXPECT_EQ(RM_DEVICE_SCALER, rm_find_device_id(player2->GetAllocatedResourceId(1))); + + EXPECT_EQ(RM_OK, rm_get_resource_state(RM_DEVICE_SCALER, &state)); + EXPECT_EQ(RM_RSC_STATE_EXCLUSIVE, state); + + EXPECT_EQ(1, player->GetConflictNum()); + EXPECT_EQ(1, player->GetConflictedResourcesNum()); + EXPECT_EQ(RI_VIRTUAL_ID_SCALER, player->GetConflictedResourceId(1)); + + EXPECT_NE(RM_OK, player->ReleaseResource(1)); + EXPECT_EQ(RM_OK, player2->ReleaseResource(1)); + + EXPECT_EQ(RM_OK, player->Unregister()); + EXPECT_EQ(RM_OK, player2->Unregister()); + + delete player; + delete player2; + + RM_TEST_MSG("rm_virtual_scaler_p4 end..."); +} + +TEST(ut_rm_api, rm_virtual_scaler_swap_p1) +{ + RM_TEST_MSG("rm_virtual_scaler_swap_p1 start..."); + + /************************************************ + * 1. Allocate sub scaler (handle1) + * 2. Allocate main scaler (handle2) + * 3. Swap main scaler with sub + * 4. Release main scaler (handle1) + * 5. Release sub scaler (handle2) + *************************************************/ + + // Step#1 Allocate sub scaler + int handle = 0; + + EXPECT_EQ(RM_OK, rm_register(_conflict_cb, NULL, &handle, NULL)); + + rm_category_request_s req; + memset(&req, 0, sizeof(rm_category_request_s)); + + req.request_num = 1; + req.category_id[0] = RM_CATEGORY_SCALER_SUB; + req.state[0] = RM_STATE_EXCLUSIVE; + + rm_device_return_s allocated; + memset(&allocated, 0, sizeof(rm_device_return_s)); + + EXPECT_EQ(RM_OK, rm_allocate_resources(handle, &req, &allocated)); + + EXPECT_EQ(1, allocated.allocated_num); + EXPECT_EQ(RI_VIRTUAL_ID_SCALER + 1, allocated.device_id[0]); + EXPECT_EQ(RM_DEVICE_SCALER_SUB, rm_find_device_id(allocated.device_id[0])); + + rm_resource_state_e state; + EXPECT_EQ(RM_OK, rm_get_resource_state(RM_DEVICE_SCALER_SUB, &state)); + EXPECT_EQ(RM_RSC_STATE_EXCLUSIVE, state); + + // Step#2 Allocate main scaler + int handle2 = 0; + + EXPECT_EQ(RM_OK, rm_register(_conflict_cb, NULL, &handle2, NULL)); + + memset(&req, 0, sizeof(rm_category_request_s)); + + req.request_num = 1; + req.category_id[0] = RM_CATEGORY_SCALER; + req.state[0] = RM_STATE_EXCLUSIVE; + + rm_device_return_s allocated2; + memset(&allocated2, 0, sizeof(rm_device_return_s)); + + EXPECT_EQ(RM_OK, rm_allocate_resources(handle2, &req, &allocated2)); + + EXPECT_EQ(1, allocated2.allocated_num); + EXPECT_EQ(RI_VIRTUAL_ID_SCALER, allocated2.device_id[0]); + EXPECT_EQ(RM_DEVICE_SCALER, rm_find_device_id(allocated2.device_id[0])); + + EXPECT_EQ(RM_OK, rm_get_resource_state(RM_DEVICE_SCALER, &state)); + EXPECT_EQ(RM_RSC_STATE_EXCLUSIVE, state); + + // Step#3 Swap main scaler with sub + EXPECT_EQ(RM_OK, rm_swap_resources(RM_DEVICE_SCALER, RM_DEVICE_SCALER_SUB)); + + // Step#4 Release main scaler + rm_device_request_s req_release; + memset(&req_release, 0, sizeof(rm_device_request_s)); + + req_release.request_num = 1; + req_release.device_id[0] = allocated.device_id[0]; + + EXPECT_EQ(RM_OK, rm_deallocate_resources(handle, &req_release)); + + EXPECT_EQ(RM_OK, rm_get_resource_state(RM_DEVICE_SCALER, &state)); + EXPECT_EQ(RM_RSC_STATE_FREE, state); + + // Step#5 Release sub scaler + memset(&req_release, 0, sizeof(rm_device_request_s)); + + req_release.request_num = 1; + req_release.device_id[0] = allocated2.device_id[0]; + + EXPECT_EQ(RM_OK, rm_deallocate_resources(handle2, &req_release)); + + EXPECT_EQ(RM_OK, rm_get_resource_state(RM_DEVICE_SCALER_SUB, &state)); + EXPECT_EQ(RM_RSC_STATE_FREE, state); + + EXPECT_EQ(RM_OK, rm_unregister(handle)); + EXPECT_EQ(RM_OK, rm_unregister(handle2)); + + // restore + EXPECT_EQ(RM_OK, rm_swap_resources(RM_DEVICE_SCALER, RM_DEVICE_SCALER_SUB)); + + RM_TEST_MSG("rm_virtual_scaler_swap_p1 end..."); +} + +TEST(ut_rm_api, rm_virtual_scaler_swap_p2) +{ + RM_TEST_MSG("rm_virtual_scaler_swap_p2 start..."); + + /************************************************ + * 1. Allocate sub scaler (handle1) 10000:sub + * 2. Allocate main scaler (handle2) 10001:main + * 3. Swap main scaler with sub : 10000:main 10001:sub + * 4. Try to allocate main scaler (handle3) + * - Conflict with handle1 + * 4. Release main scaler (handle3) + * 5. Release sub scaler (handle2) + *************************************************/ + + _reset_cb_info(); + + // Step#1 Allocate sub scaler + int handle = 0; + + EXPECT_EQ(RM_OK, rm_register(_conflict_cb, NULL, &handle, NULL)); + + rm_category_request_s req; + memset(&req, 0, sizeof(rm_category_request_s)); + + req.request_num = 1; + req.category_id[0] = RM_CATEGORY_SCALER_SUB; + req.state[0] = RM_STATE_EXCLUSIVE; + + rm_device_return_s allocated; + memset(&allocated, 0, sizeof(rm_device_return_s)); + + EXPECT_EQ(RM_OK, rm_allocate_resources(handle, &req, &allocated)); + + EXPECT_EQ(1, allocated.allocated_num); + EXPECT_EQ(RI_VIRTUAL_ID_SCALER + 1, allocated.device_id[0]); + EXPECT_EQ(RM_DEVICE_SCALER_SUB, rm_find_device_id(allocated.device_id[0])); + + rm_resource_state_e state; + EXPECT_EQ(RM_OK, rm_get_resource_state(RM_DEVICE_SCALER_SUB, &state)); + EXPECT_EQ(RM_RSC_STATE_EXCLUSIVE, state); + + // Step#2 Allocate main scaler + int handle2 = 0; + + EXPECT_EQ(RM_OK, rm_register(_conflict_cb, NULL, &handle2, NULL)); + + memset(&req, 0, sizeof(rm_category_request_s)); + + req.request_num = 1; + req.category_id[0] = RM_CATEGORY_SCALER; + req.state[0] = RM_STATE_EXCLUSIVE; + + rm_device_return_s allocated2; + memset(&allocated2, 0, sizeof(rm_device_return_s)); + + EXPECT_EQ(RM_OK, rm_allocate_resources(handle2, &req, &allocated2)); + + EXPECT_EQ(1, allocated2.allocated_num); + EXPECT_EQ(RI_VIRTUAL_ID_SCALER, allocated2.device_id[0]); + EXPECT_EQ(RM_DEVICE_SCALER, rm_find_device_id(allocated2.device_id[0])); + + EXPECT_EQ(RM_OK, rm_get_resource_state(RM_DEVICE_SCALER, &state)); + EXPECT_EQ(RM_RSC_STATE_EXCLUSIVE, state); + + // Step#3 Swap main scaler with sub + EXPECT_EQ(RM_OK, rm_swap_resources(RM_DEVICE_SCALER, RM_DEVICE_SCALER_SUB)); + + // Step#4 Try to allocate main scaler (handle3) + int handle3 = 0; + + EXPECT_EQ(RM_OK, rm_register(_conflict_cb, NULL, &handle3, NULL)); + + memset(&req, 0, sizeof(rm_category_request_s)); + req.request_num = 1; + req.category_id[0] = RM_CATEGORY_SCALER; + req.state[0] = RM_STATE_EXCLUSIVE; + + rm_device_return_s allocated3; + memset(&allocated3, 0, sizeof(rm_device_return_s)); + + EXPECT_EQ(RM_OK, rm_allocate_resources(handle3, &req, &allocated3)); + + sleep(1); + + EXPECT_EQ(1, allocated3.allocated_num); + EXPECT_EQ(RI_VIRTUAL_ID_SCALER + 1, allocated3.device_id[0]); + EXPECT_EQ(RM_DEVICE_SCALER, rm_find_device_id(allocated3.device_id[0])); + + EXPECT_EQ(RM_OK, rm_get_resource_state(RM_DEVICE_SCALER, &state)); + EXPECT_EQ(RM_RSC_STATE_EXCLUSIVE, state); + + EXPECT_EQ(handle, _get_conflict_handle()); + EXPECT_EQ(1, _get_conflict_num()); + + // Step#5 Release main scaler (handle3) + rm_device_request_s req_release; + memset(&req_release, 0, sizeof(rm_device_request_s)); + + req_release.request_num = 1; + req_release.device_id[0] = allocated.device_id[0]; + + EXPECT_EQ(RM_OK, rm_deallocate_resources(handle3, &req_release)); + + EXPECT_EQ(RM_OK, rm_get_resource_state(RM_DEVICE_SCALER, &state)); + EXPECT_EQ(RM_RSC_STATE_FREE, state); + + // Step#6 Release sub scaler (handle2) + memset(&req_release, 0, sizeof(rm_device_request_s)); + + req_release.request_num = 1; + req_release.device_id[0] = allocated2.device_id[0]; + + EXPECT_EQ(RM_OK, rm_deallocate_resources(handle2, &req_release)); + + EXPECT_EQ(RM_OK, rm_get_resource_state(RM_DEVICE_SCALER_SUB, &state)); + EXPECT_EQ(RM_RSC_STATE_FREE, state); + + EXPECT_NE(RM_OK, rm_unregister(handle)); // already unregistered by callback + EXPECT_EQ(RM_OK, rm_unregister(handle2)); + EXPECT_EQ(RM_OK, rm_unregister(handle3)); + + //restore + EXPECT_EQ(RM_OK, rm_swap_resources(RM_DEVICE_SCALER, RM_DEVICE_SCALER_SUB)); + + RM_TEST_MSG("rm_virtual_scaler_swap_p2 end..."); +} + + + +TEST(ut_rm_api, rm_virtual_scaler_swap_n1) +{ + RM_TEST_MSG("rm_virtual_scaler_swap_n1 start..."); + + EXPECT_NE(RM_OK, rm_swap_resources(RM_DEVICE_SCALER, RM_DEVICE_TUNER)); + + RM_TEST_MSG("rm_virtual_scaler_swap_n1 end..."); +} + +TEST(ut_rm_api, rm_virtual_scaler_swap_n2) +{ + RM_TEST_MSG("rm_virtual_scaler_swap_n2 start..."); + + EXPECT_NE(RM_OK, rm_swap_resources(RM_DEVICE_VIDEO_DECODER_MAIN, RM_DEVICE_VIDEO_DECODER_SUB)); + + RM_TEST_MSG("rm_virtual_scaler_swap_n2 end..."); +} + +TEST(ut_rm_api, rm_scaler_changed_cb_p1) +{ + RM_TEST_MSG("rm_scaler_changed_cb_p1 start..."); + + TCCallbackListener *listener = new TCCallbackListener(); + + EXPECT_EQ(RM_OK, listener->RegisterScalerStateChangeCb()); + EXPECT_EQ(RM_OK, listener->UnregisterScalerStateChangeCb()); + + delete listener; + + RM_TEST_MSG("rm_scaler_changed_cb_p1 end..."); +} + +TEST(ut_rm_api, rm_scaler_changed_cb_n1) +{ + RM_TEST_MSG("rm_scaler_changed_cb_n1 start..."); + + TCCallbackListener *listener = new TCCallbackListener(); + + EXPECT_EQ(RM_OK, listener->RegisterScalerStateChangeCb()); + EXPECT_NE(RM_OK, listener->RegisterScalerStateChangeCb()); + + EXPECT_EQ(RM_OK, listener->UnregisterScalerStateChangeCb()); + EXPECT_NE(RM_OK, listener->UnregisterScalerStateChangeCb()); + + delete listener; + + RM_TEST_MSG("rm_scaler_changed_cb_n1 end..."); +} + +int _get_source_id(int device_id) +{ + if (device_id == RM_DEVICE_SCALER) + return 0; + if (device_id == RM_DEVICE_SCALER_SUB) + return 1; + return 99; +} + +#if 0 // Resource manager server doesn't send a dbus signal (disabled feature) +TEST(ut_rm_api, rm_scaler_changed_cb_p2) +{ + RM_TEST_MSG("rm_scaler_changed_cb_p2 start..."); + + TCCallbackListener *listener = new TCCallbackListener(); + + EXPECT_EQ(RM_OK, listener->RegisterScalerStateChangeCb()); + + EXPECT_EQ(RM_OK, rm_swap_resources(RM_DEVICE_SCALER, RM_DEVICE_SCALER_SUB)); + + sleep(2); + + EXPECT_EQ(1, listener->GetNotificationNum()); + EXPECT_EQ(1, listener->IsIncluded(RI_VIRTUAL_ID_SCALER + 1, _get_source_id(RM_DEVICE_SCALER))); + EXPECT_EQ(1, listener->IsIncluded(RI_VIRTUAL_ID_SCALER, _get_source_id(RM_DEVICE_SCALER_SUB))); + + EXPECT_EQ(RM_OK, rm_swap_resources(RM_DEVICE_SCALER, RM_DEVICE_SCALER_SUB)); + + sleep(2); + + EXPECT_EQ(2, listener->GetNotificationNum()); + EXPECT_EQ(1, listener->IsIncluded(RI_VIRTUAL_ID_SCALER, _get_source_id(RM_DEVICE_SCALER))); + EXPECT_EQ(1, listener->IsIncluded(RI_VIRTUAL_ID_SCALER + 1, _get_source_id(RM_DEVICE_SCALER_SUB))); + + EXPECT_EQ(RM_OK, listener->UnregisterScalerStateChangeCb()); + + delete listener; + + RM_TEST_MSG("rm_scaler_changed_cb_p2 end..."); +} +#endif//0 diff --git a/ut/testcase/ut_tc_vr360.cpp b/ut/testcase/ut_tc_vr360.cpp new file mode 100644 index 0000000..a4ca039 --- /dev/null +++ b/ut/testcase/ut_tc_vr360.cpp @@ -0,0 +1,242 @@ +/* + * Copyright (c) 2024 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 "gtest/gtest.h" +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +TEST(ut_rm_api, alloc_video_dec_av1_vr360_p1) +{ + RM_TEST_MSG("alloc_video_dec_av1_vr360_p1 start..."); + + int handle = 0; + rm_tc_reset_conflict_num(); + + EXPECT_EQ(RM_OK, rm_register(rm_cb_counting_conflicted, NULL, &handle, NULL)); + + rm_category_request_s request; + memset(&request, 0, sizeof(rm_category_request_s)); + + ri_video_category_option_request_s option; + memset(&option, 0, sizeof(ri_video_category_option_request_s)); + + option.codec_name = "AV1_VR360"; + option.color_depth = 8; + option.framerate = 30; + option.h_size = 1920; + option.v_size = 1080; + option.sampling_format = RI_SAMPLING_FORMAT_420; + + request.request_num = 1; + request.category_id[0] = RM_CATEGORY_VIDEO_DECODER; + request.category_option[0] = ri_get_capable_video_category_id(&option); + request.state[0] = RM_STATE_EXCLUSIVE; + + rm_device_return_s allocated; + memset(&allocated, 0, sizeof(rm_device_return_s)); + + EXPECT_EQ(RM_OK, rm_allocate_resources(handle, &request, &allocated)); + EXPECT_EQ(1, allocated.allocated_num); + EXPECT_EQ(RM_DEVICE_VIDEO_DECODER_VR360DEC, allocated.device_id[0]); + EXPECT_EQ(0, rm_tc_get_conflict_num()); + rm_tc_reset_conflict_num(); + + EXPECT_EQ(RM_OK, rm_unregister(handle)); + + RM_TEST_MSG("alloc_video_dec_av1_vr360_p1 end..."); +} + +TEST(ut_rm_api, alloc_video_dec_av1_vr360_p2) +{ + RM_TEST_MSG("alloc_video_dec_av1_vr360_p2 start..."); + + int handle = 0; + rm_tc_reset_conflict_num(); + + EXPECT_EQ(RM_OK, rm_register(rm_cb_counting_conflicted, NULL, &handle, NULL)); + + rm_category_request_s request; + memset(&request, 0, sizeof(rm_category_request_s)); + + ri_video_category_option_request_s option; + memset(&option, 0, sizeof(ri_video_category_option_request_s)); + + option.codec_name = "AV1_VR360"; + option.color_depth = 8; + option.framerate = 60; + option.h_size = 3840; + option.v_size = 2160; + option.sampling_format = RI_SAMPLING_FORMAT_420; + + request.request_num = 1; + request.category_id[0] = RM_CATEGORY_VIDEO_DECODER; + request.category_option[0] = ri_get_capable_video_category_id(&option); + request.state[0] = RM_STATE_EXCLUSIVE; + + rm_device_return_s allocated; + memset(&allocated, 0, sizeof(rm_device_return_s)); + + if (is_support_4k()) { + EXPECT_EQ(RM_OK, rm_allocate_resources(handle, &request, &allocated)); + EXPECT_EQ(1, allocated.allocated_num); + EXPECT_EQ(RM_DEVICE_VIDEO_DECODER_VR360DEC, allocated.device_id[0]); + EXPECT_EQ(0, rm_tc_get_conflict_num()); + } else { + EXPECT_NE(RM_OK, rm_allocate_resources(handle, &request, &allocated)); + EXPECT_EQ(0, allocated.allocated_num); + EXPECT_EQ(0, rm_tc_get_conflict_num()); + } + rm_tc_reset_conflict_num(); + + EXPECT_EQ(RM_OK, rm_unregister(handle)); + + RM_TEST_MSG("alloc_video_dec_av1_vr360_p2 end..."); +} + +TEST(ut_rm_api, alloc_video_dec_h264_vr360_p1) +{ + RM_TEST_MSG("alloc_video_dec_h264_vr360_p1 start..."); + + int handle = 0; + rm_tc_reset_conflict_num(); + + EXPECT_EQ(RM_OK, rm_register(rm_cb_counting_conflicted, NULL, &handle, NULL)); + + rm_category_request_s request; + memset(&request, 0, sizeof(rm_category_request_s)); + + ri_video_category_option_request_s option; + memset(&option, 0, sizeof(ri_video_category_option_request_s)); + + option.codec_name = "H264_VR360"; + option.color_depth = 8; + option.framerate = 60; + option.h_size = 1920; + option.v_size = 1080; + option.sampling_format = RI_SAMPLING_FORMAT_420; + + request.request_num = 1; + request.category_id[0] = RM_CATEGORY_VIDEO_DECODER; + request.category_option[0] = ri_get_capable_video_category_id(&option); + request.state[0] = RM_STATE_EXCLUSIVE; + + rm_device_return_s allocated; + memset(&allocated, 0, sizeof(rm_device_return_s)); + + EXPECT_EQ(RM_OK, rm_allocate_resources(handle, &request, &allocated)); + EXPECT_EQ(1, allocated.allocated_num); + EXPECT_EQ(RM_DEVICE_VIDEO_DECODER_VR360DEC, allocated.device_id[0]); + EXPECT_EQ(0, rm_tc_get_conflict_num()); + rm_tc_reset_conflict_num(); + + EXPECT_EQ(RM_OK, rm_unregister(handle)); + + RM_TEST_MSG("alloc_video_dec_h264_vr360_p1 end..."); +} + +TEST(ut_rm_api, alloc_video_dec_vp9_vr360_p1) +{ + RM_TEST_MSG("alloc_video_dec_vp9_vr360_p1 start..."); + + int handle = 0; + rm_tc_reset_conflict_num(); + + EXPECT_EQ(RM_OK, rm_register(rm_cb_counting_conflicted, NULL, &handle, NULL)); + + rm_category_request_s request; + memset(&request, 0, sizeof(rm_category_request_s)); + + ri_video_category_option_request_s option; + memset(&option, 0, sizeof(ri_video_category_option_request_s)); + + option.codec_name = "VP9_VR360"; + option.color_depth = 8; + option.framerate = 60; + option.h_size = 1920; + option.v_size = 1080; + option.sampling_format = RI_SAMPLING_FORMAT_420; + + request.request_num = 1; + request.category_id[0] = RM_CATEGORY_VIDEO_DECODER; + request.category_option[0] = ri_get_capable_video_category_id(&option); + request.state[0] = RM_STATE_EXCLUSIVE; + + rm_device_return_s allocated; + memset(&allocated, 0, sizeof(rm_device_return_s)); + + EXPECT_EQ(RM_OK, rm_allocate_resources(handle, &request, &allocated)); + EXPECT_EQ(1, allocated.allocated_num); + EXPECT_EQ(RM_DEVICE_VIDEO_DECODER_VR360DEC, allocated.device_id[0]); + EXPECT_STREQ("OMX.SDP.video_decoder.vr360dec", allocated.omx_comp_name[0]); + EXPECT_EQ(0, rm_tc_get_conflict_num()); + rm_tc_reset_conflict_num(); + + EXPECT_EQ(RM_OK, rm_unregister(handle)); + + RM_TEST_MSG("alloc_video_dec_vp9_vr360_p1 end..."); +} + +TEST(ut_rm_api, alloc_video_dec_hevc_vr360_p1) +{ + RM_TEST_MSG("alloc_video_dec_hevc_vr360_p1 start..."); + + int handle = 0; + rm_tc_reset_conflict_num(); + + EXPECT_EQ(RM_OK, rm_register(rm_cb_counting_conflicted, NULL, &handle, NULL)); + + rm_category_request_s request; + memset(&request, 0, sizeof(rm_category_request_s)); + + ri_video_category_option_request_s option; + memset(&option, 0, sizeof(ri_video_category_option_request_s)); + + option.codec_name = "HEVC_VR360"; + option.color_depth = 8; + option.framerate = 60; + option.h_size = 1920; + option.v_size = 1080; + option.sampling_format = RI_SAMPLING_FORMAT_420; + + request.request_num = 1; + request.category_id[0] = RM_CATEGORY_VIDEO_DECODER; + request.category_option[0] = ri_get_capable_video_category_id(&option); + request.state[0] = RM_STATE_EXCLUSIVE; + + rm_device_return_s allocated; + memset(&allocated, 0, sizeof(rm_device_return_s)); + + EXPECT_EQ(RM_OK, rm_allocate_resources(handle, &request, &allocated)); + EXPECT_EQ(1, allocated.allocated_num); + EXPECT_EQ(RM_DEVICE_VIDEO_DECODER_VR360DEC, allocated.device_id[0]); + EXPECT_EQ(0, rm_tc_get_conflict_num()); + rm_tc_reset_conflict_num(); + + EXPECT_EQ(RM_OK, rm_unregister(handle)); + + RM_TEST_MSG("alloc_video_dec_hevc_vr360_p1 end..."); +}