diff options
author | Eunhye Choi <eunhae1.choi@samsung.com> | 2022-12-01 14:53:55 +0900 |
---|---|---|
committer | Eunhye Choi <eunhae1.choi@samsung.com> | 2022-12-01 14:56:52 +0900 |
commit | 8ad50c3da5dda256bb4a9b48e05620eb3ee3b0b8 (patch) | |
tree | f6bbe5685069bc352498adb7de0ce65751f44e8f | |
parent | 491650f900c9095f041576266f2448cbd36ca80d (diff) | |
download | mediatransporter-8ad50c3da5dda256bb4a9b48e05620eb3ee3b0b8.tar.gz mediatransporter-8ad50c3da5dda256bb4a9b48e05620eb3ee3b0b8.tar.bz2 mediatransporter-8ad50c3da5dda256bb4a9b48e05620eb3ee3b0b8.zip |
[1.0.11] add rtsp receiver ut
- add rtsp receiver ut
- fix rtsp sender crash by unexpected server unref
- fix server resource leak at ut_rtsp_sender_to_server
- use once_flag to avoid duplicated setting of promise value
at dataPacketCb
Change-Id: I2d2e2f016f5e13ca718155ed25b9e9a0d90a9592
-rw-r--r-- | packaging/capi-media-transporter.spec | 2 | ||||
-rw-r--r-- | src/MediaTransporterSenderRtsp.cpp | 5 | ||||
-rw-r--r-- | unittest/CMakeLists.txt | 1 | ||||
-rw-r--r-- | unittest/ut_rist_receiver.cpp | 12 | ||||
-rw-r--r-- | unittest/ut_rtsp_receiver.cpp | 389 | ||||
-rw-r--r-- | unittest/ut_rtsp_sender_to_server.cpp | 33 | ||||
-rw-r--r-- | unittest/ut_srt_receiver.cpp | 12 |
7 files changed, 431 insertions, 23 deletions
diff --git a/packaging/capi-media-transporter.spec b/packaging/capi-media-transporter.spec index 0e12abb..278b5ea 100644 --- a/packaging/capi-media-transporter.spec +++ b/packaging/capi-media-transporter.spec @@ -1,6 +1,6 @@ Name: capi-media-transporter Summary: A Media Transporter library in Tizen Native API -Version: 1.0.10 +Version: 1.0.11 Release: 0 Group: Multimedia/API License: Apache-2.0 diff --git a/src/MediaTransporterSenderRtsp.cpp b/src/MediaTransporterSenderRtsp.cpp index 9cb118c..5a62024 100644 --- a/src/MediaTransporterSenderRtsp.cpp +++ b/src/MediaTransporterSenderRtsp.cpp @@ -200,9 +200,7 @@ void MediaTransporterSenderRtsp::stopRtspServer() g_source_remove(_sourceId); _sourceId = 0; - guint ref_cnt = GST_OBJECT_REFCOUNT_VALUE(server); - for (guint i = 0; i < ref_cnt; i++) - gst_object_unref(server); + gst_object_unref(server); _rtspServer = NULL; _rtspMountPoint.clear(); @@ -245,7 +243,6 @@ void MediaTransporterSenderRtsp::_mediaPreparedCb(GstRTSPMedia* media, gpointer g_signal_connect(session, "on-sender-ssrc-active", G_CALLBACK(_onSenderSsrcActive), media); } - /* REF: pipeline ref count +1, it will be unref at stopPipeline() */ handle->_rtspPipeline = gst_rtsp_media_get_pipeline(media); diff --git a/unittest/CMakeLists.txt b/unittest/CMakeLists.txt index 1b0882d..98d4a91 100644 --- a/unittest/CMakeLists.txt +++ b/unittest/CMakeLists.txt @@ -49,6 +49,7 @@ SET(UT_SRC ut_rist_receiver.cpp ut_rtsp_sender.cpp ut_rtsp_sender_to_server.cpp + ut_rtsp_receiver.cpp ut_srt_sender.cpp ut_srt_receiver.cpp ut_main.cpp diff --git a/unittest/ut_rist_receiver.cpp b/unittest/ut_rist_receiver.cpp index 3b34d35..ca8b5ea 100644 --- a/unittest/ut_rist_receiver.cpp +++ b/unittest/ut_rist_receiver.cpp @@ -47,9 +47,13 @@ static void dataPacketCb(mtpr_h mtpr, mtpr_media_type_e type, unsigned int id, media_packet_h packet, void *user_data) { LOGD("callback is invoked. type: %d, id: %d", type, id); - auto p = static_cast<std::promise<bool>*>(user_data); - assert(p); - p->set_value(true); + static std::once_flag flag; + + std::call_once(flag, [&](){ + auto p = static_cast<std::promise<bool>*>(user_data); + assert(p); + p->set_value(true); + }); } static bool waitDataPacket(std::future<bool>& f) { @@ -84,7 +88,6 @@ public: mtpr_state_e state = MTPR_STATE_IDLE; LOGD("Enter"); - stop_rist_sender(); if (_mtpr) { ret = mtpr_get_state(_mtpr, &state); @@ -98,6 +101,7 @@ public: ASSERT_EQ(ret, MTPR_ERROR_NONE); } + stop_rist_sender(); LOGD("Leave"); } diff --git a/unittest/ut_rtsp_receiver.cpp b/unittest/ut_rtsp_receiver.cpp new file mode 100644 index 0000000..3f40f00 --- /dev/null +++ b/unittest/ut_rtsp_receiver.cpp @@ -0,0 +1,389 @@ +/* + * Copyright (c) 2022 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 <gst/gst.h> +#include "ut_base.hpp" + +static GMainLoop* mainloop; + +using namespace std::chrono_literals; + +static void* _run_rtsp_sender(void* ptr) { + mtpr_h mtpr; + unsigned int src_id = 0; + mtpr_create(MTPR_CONNECTION_TYPE_RTSP_SENDER, &mtpr); + mtpr_set_sender_address(mtpr, "rtsp://127.0.0.1:8554/test"); + mtpr_add_media_source(mtpr, MTPR_SOURCE_TYPE_VIDEOTEST, &src_id); + mtpr_start(mtpr); + + mainloop = g_main_loop_new(NULL, FALSE); + + LOGD("rtsp sender ready"); + g_main_loop_run(mainloop); + + LOGD("rtsp sender terminated"); + g_main_loop_unref(mainloop); + + mtpr_stop(mtpr); + mtpr_destroy(mtpr); + + return NULL; +} + +static void dataPacketCb(mtpr_h mtpr, mtpr_media_type_e type, + unsigned int id, media_packet_h packet, void *user_data) { + LOGD("callback is invoked. type: %d, id: %d", type, id); + + static std::once_flag flag; + + std::call_once(flag, [&](){ + auto p = static_cast<std::promise<bool>*>(user_data); + assert(p); + p->set_value(true); + }); +} + +static bool waitDataPacket(std::future<bool>& f) { + LOGI("start waiting for packet arrival..."); + + if (f.wait_for(10s) != std::future_status::ready) { + LOGW("timeout(10s)!!!"); + return false; + } + + LOGI("ready to get the result!"); + return f.get(); +} + +class MediaTransporterTestRtspReceiverWithSender : public MediaTransporterTestBase { +public: + MediaTransporterTestRtspReceiverWithSender() = default; + ~MediaTransporterTestRtspReceiverWithSender() = default; + + void SetUp() override { + LOGD("Enter"); + start_rtsp_sender(); + + int ret = mtpr_create(MTPR_CONNECTION_TYPE_RTSP_RECEIVER, &_mtpr); + ASSERT_EQ(ret, MTPR_ERROR_NONE); + + LOGD("Leave"); + } + + void TearDown() override { + int ret = MTPR_ERROR_NONE; + mtpr_state_e state = MTPR_STATE_IDLE; + + LOGD("Enter"); + + if (_mtpr) { + ret = mtpr_get_state(_mtpr, &state); + ASSERT_EQ(ret, MTPR_ERROR_NONE); + + if (state != MTPR_STATE_IDLE) { + ret = mtpr_stop(_mtpr); + ASSERT_EQ(ret, MTPR_ERROR_NONE); + } + ret = mtpr_destroy(_mtpr); + ASSERT_EQ(ret, MTPR_ERROR_NONE); + } + + stop_rtsp_sender(); + LOGD("Leave"); + } + +protected: + const std::string _senderPath = "rtsp://127.0.0.1:8554/test"; + + void start_rtsp_sender() { + _rtspSender = g_thread_try_new("rtsp_sender", _run_rtsp_sender, NULL, NULL); + std::this_thread::sleep_for(std::chrono::seconds(1)); + } + + void stop_rtsp_sender() { + if (mainloop) + g_main_loop_quit(mainloop); + if (_rtspSender) + g_thread_join(_rtspSender); + } + + GThread* _rtspSender {nullptr}; +}; + +class MediaTransporterTestRtspReceiver : public MediaTransporterTestBase { +public: + MediaTransporterTestRtspReceiver() = default; + ~MediaTransporterTestRtspReceiver() = default; + + void SetUp() override { + LOGD("Enter"); + + int ret = mtpr_create(MTPR_CONNECTION_TYPE_RTSP_RECEIVER, &_mtpr); + ASSERT_EQ(ret, MTPR_ERROR_NONE); + + LOGD("Leave"); + } + + void TearDown() override { + int ret = MTPR_ERROR_NONE; + mtpr_state_e state = MTPR_STATE_IDLE; + LOGD("Enter"); + + if (_mtpr) { + ret = mtpr_get_state(_mtpr, &state); + ASSERT_EQ(ret, MTPR_ERROR_NONE); + + if (state != MTPR_STATE_IDLE) { + ret = mtpr_stop(_mtpr); + ASSERT_EQ(ret, MTPR_ERROR_NONE); + } + ret = mtpr_destroy(_mtpr); + ASSERT_EQ(ret, MTPR_ERROR_NONE); + } + LOGD("Leave"); + } + +protected: + const std::string _senderPath = "rtsp://127.0.0.1:8554/test"; +}; + +// MediaTransporterTestRtspReceiver + +TEST_F(MediaTransporterTestRtspReceiver, set_address_p) +{ + int ret = mtpr_set_sender_address(_mtpr, _senderPath.c_str()); + ASSERT_EQ(ret, MTPR_ERROR_NONE); +} + +TEST_F(MediaTransporterTestRtspReceiver, set_address_n1) +{ + int ret = MTPR_ERROR_NONE; + + ret = mtpr_set_sender_address(NULL, _senderPath.c_str()); + ASSERT_EQ(ret, MTPR_ERROR_INVALID_PARAMETER); + + ret = mtpr_set_sender_address(_mtpr, NULL); + ASSERT_EQ(ret, MTPR_ERROR_INVALID_PARAMETER); + + ret = mtpr_set_sender_address(NULL, NULL); + ASSERT_EQ(ret, MTPR_ERROR_INVALID_PARAMETER); +} + +TEST_F(MediaTransporterTestRtspReceiver, set_address_n2) +{ + int ret = mtpr_set_receiver_address(_mtpr, _senderPath.c_str()); + ASSERT_EQ(ret, MTPR_ERROR_INVALID_OPERATION); +} + +TEST_F(MediaTransporterTestRtspReceiver, get_address_p) +{ + int ret = MTPR_ERROR_NONE; + char *address = NULL; + + ret = mtpr_set_sender_address(_mtpr, _senderPath.c_str()); + ASSERT_EQ(ret, MTPR_ERROR_NONE); + + ret = mtpr_get_sender_address(_mtpr, &address); + ASSERT_EQ(ret, MTPR_ERROR_NONE); + ASSERT_TRUE(address); + ASSERT_STREQ(_senderPath.c_str(), address); +} + +TEST_F(MediaTransporterTestRtspReceiver, get_address_n1) +{ + int ret = MTPR_ERROR_NONE; + char *address = NULL; + + ret = mtpr_set_sender_address(_mtpr, _senderPath.c_str()); + ASSERT_EQ(ret, MTPR_ERROR_NONE); + + ret = mtpr_get_sender_address(NULL, &address); + ASSERT_EQ(ret, MTPR_ERROR_INVALID_PARAMETER); + + ret = mtpr_get_sender_address(_mtpr, NULL); + ASSERT_EQ(ret, MTPR_ERROR_INVALID_PARAMETER); + + ret = mtpr_get_sender_address(NULL, NULL); + ASSERT_EQ(ret, MTPR_ERROR_INVALID_PARAMETER); +} + +TEST_F(MediaTransporterTestRtspReceiver, get_address_n2) +{ + char *address = NULL; + + int ret = mtpr_get_sender_address(_mtpr, &address); + ASSERT_EQ(ret, MTPR_ERROR_NO_DATA); +} + +TEST_F(MediaTransporterTestRtspReceiver, get_address_n3) +{ + int ret = MTPR_ERROR_NONE; + char *address = NULL; + + ret = mtpr_set_sender_address(_mtpr, _senderPath.c_str()); + ASSERT_EQ(ret, MTPR_ERROR_NONE); + + ret = mtpr_get_receiver_address(_mtpr, &address); + ASSERT_EQ(ret, MTPR_ERROR_INVALID_OPERATION); +} + +TEST_F(MediaTransporterTestRtspReceiver, get_connection_type_p) +{ + mtpr_connection_type_e type; + + int ret = mtpr_get_connection_type(_mtpr, &type); + ASSERT_EQ(ret, MTPR_ERROR_NONE); + ASSERT_EQ(type, MTPR_CONNECTION_TYPE_RTSP_RECEIVER); +} + +TEST_F(MediaTransporterTestRtspReceiver, get_connection_type_n1) +{ + int ret = MTPR_ERROR_NONE; + mtpr_connection_type_e type; + + ret = mtpr_get_connection_type(NULL, &type); + ASSERT_EQ(ret, MTPR_ERROR_INVALID_PARAMETER); + + ret = mtpr_get_connection_type(_mtpr, NULL); + ASSERT_EQ(ret, MTPR_ERROR_INVALID_PARAMETER); + + ret = mtpr_get_connection_type(NULL, NULL); + ASSERT_EQ(ret, MTPR_ERROR_INVALID_PARAMETER); +} + +TEST_F(MediaTransporterTestRtspReceiver, start_n1) +{ + int ret = MTPR_ERROR_NONE; + + ret = mtpr_start(_mtpr); + ASSERT_EQ(ret, MTPR_ERROR_INVALID_OPERATION); +} + +TEST_F(MediaTransporterTestRtspReceiver, start_n2) +{ + int ret = MTPR_ERROR_NONE; + + ret = mtpr_set_sender_address(_mtpr, _senderPath.c_str()); + ASSERT_EQ(ret, MTPR_ERROR_NONE); + + ret = mtpr_start(NULL); + ASSERT_EQ(ret, MTPR_ERROR_INVALID_PARAMETER); +} + +TEST_F(MediaTransporterTestRtspReceiver, stop_n) +{ + int ret = mtpr_stop(_mtpr); + ASSERT_EQ(ret, MTPR_ERROR_INVALID_STATE); +} + +TEST_F(MediaTransporterTestRtspReceiver, get_state_p) +{ + mtpr_state_e state = MTPR_STATE_IDLE; + + int ret = mtpr_get_state(_mtpr, &state); + ASSERT_EQ(ret, MTPR_ERROR_NONE); + ASSERT_EQ(state, MTPR_STATE_IDLE); +} + +TEST_F(MediaTransporterTestRtspReceiver, get_state_n) +{ + int ret = MTPR_ERROR_NONE; + mtpr_state_e state = MTPR_STATE_IDLE; + + ret = mtpr_get_state(NULL, &state); + ASSERT_EQ(ret, MTPR_ERROR_INVALID_PARAMETER); + + ret = mtpr_get_state(_mtpr, NULL); + ASSERT_EQ(ret, MTPR_ERROR_INVALID_PARAMETER); + + ret = mtpr_get_state(NULL, NULL); + ASSERT_EQ(ret, MTPR_ERROR_INVALID_PARAMETER); +} + + +// MediaTransporterTestRtspReceiverWithSender + +TEST_F(MediaTransporterTestRtspReceiverWithSender, start_p) +{ + int ret = MTPR_ERROR_NONE; + + ret = mtpr_set_sender_address(_mtpr, _senderPath.c_str()); + ASSERT_EQ(ret, MTPR_ERROR_NONE); + + std::promise<bool> p; + std::future<bool> f = p.get_future(); + ret = mtpr_set_video_packet_cb(_mtpr, dataPacketCb, &p); + ASSERT_EQ(ret, MTPR_ERROR_NONE); + + ret = mtpr_start(_mtpr); + ASSERT_EQ(ret, MTPR_ERROR_NONE); + + ASSERT_TRUE(waitDataPacket(f)); + + ret = mtpr_unset_video_packet_cb(_mtpr); + ASSERT_EQ(ret, MTPR_ERROR_NONE); +} + +TEST_F(MediaTransporterTestRtspReceiverWithSender, stop_p) +{ + int ret = MTPR_ERROR_NONE; + + ret = mtpr_set_sender_address(_mtpr, _senderPath.c_str()); + ASSERT_EQ(ret, MTPR_ERROR_NONE); + + ret = mtpr_start(_mtpr); + ASSERT_EQ(ret, MTPR_ERROR_NONE); + + std::this_thread::sleep_for(std::chrono::seconds(1)); + + ret = mtpr_stop(_mtpr); + ASSERT_EQ(ret, MTPR_ERROR_NONE); +} + +TEST_F(MediaTransporterTestRtspReceiverWithSender, get_state_p1) +{ + int ret = MTPR_ERROR_NONE; + mtpr_state_e state = MTPR_STATE_IDLE; + + ret = mtpr_set_sender_address(_mtpr, _senderPath.c_str()); + ASSERT_EQ(ret, MTPR_ERROR_NONE); + + ret = mtpr_start(_mtpr); + ASSERT_EQ(ret, MTPR_ERROR_NONE); + + ret = mtpr_get_state(_mtpr, &state); + ASSERT_EQ(ret, MTPR_ERROR_NONE); + ASSERT_EQ(state, MTPR_STATE_PLAYING); +} + +TEST_F(MediaTransporterTestRtspReceiverWithSender, get_state_p2) +{ + int ret = MTPR_ERROR_NONE; + mtpr_state_e state = MTPR_STATE_IDLE; + + ret = mtpr_set_sender_address(_mtpr, _senderPath.c_str()); + ASSERT_EQ(ret, MTPR_ERROR_NONE); + + ret = mtpr_start(_mtpr); + ASSERT_EQ(ret, MTPR_ERROR_NONE); + + ret = mtpr_stop(_mtpr); + ASSERT_EQ(ret, MTPR_ERROR_NONE); + + ret = mtpr_get_state(_mtpr, &state); + ASSERT_EQ(ret, MTPR_ERROR_NONE); + ASSERT_EQ(state, MTPR_STATE_IDLE); +} diff --git a/unittest/ut_rtsp_sender_to_server.cpp b/unittest/ut_rtsp_sender_to_server.cpp index bde70f5..a3c55de 100644 --- a/unittest/ut_rtsp_sender_to_server.cpp +++ b/unittest/ut_rtsp_sender_to_server.cpp @@ -20,27 +20,30 @@ #include "ut_base.hpp" static GMainLoop* _mainloop; + +static void _clientConnectedCb(GstRTSPServer* server, GstRTSPClient* client) +{ + LOGD("client connected %p", client); +} + static void* _run_rtsp_server(void* ptr) { - GstRTSPServer* server; - GstRTSPMountPoints* mounts; - GstRTSPMediaFactory* factory; gst_init(NULL, NULL); _mainloop = g_main_loop_new(NULL, FALSE); - server = gst_rtsp_server_new(); - g_object_set(server, "service", "8554", NULL); - - mounts = gst_rtsp_server_get_mount_points(server); + GstRTSPServer* server = gst_rtsp_server_new(); + gst_rtsp_server_set_address(server, "127.0.0.1"); + gst_rtsp_server_set_service(server, "8554"); + g_signal_connect(server, "client-connected", G_CALLBACK(_clientConnectedCb), NULL); - factory = gst_rtsp_media_factory_new(); + GstRTSPMediaFactory* factory = gst_rtsp_media_factory_new(); gst_rtsp_media_factory_set_transport_mode(factory, GST_RTSP_TRANSPORT_MODE_RECORD); gst_rtsp_media_factory_set_launch(factory, "decodebin name=depay0 ! videoconvert ! tizenwlsink"); + GstRTSPMountPoints* mounts = gst_rtsp_server_get_mount_points(server); gst_rtsp_mount_points_add_factory(mounts, "/test", factory); - g_object_unref(mounts); - gst_rtsp_server_attach(server, NULL); + unsigned int sourceId = gst_rtsp_server_attach(server, NULL); LOGD("server ready"); g_main_loop_run(_mainloop); @@ -48,6 +51,16 @@ static void* _run_rtsp_server(void* ptr) { LOGD("server terminated"); g_main_loop_unref(_mainloop); + gst_rtsp_mount_points_remove_factory(mounts, "/test"); + g_object_unref(mounts); + + gst_rtsp_server_client_filter(server, NULL, NULL); + + if (sourceId > 0) + g_source_remove(sourceId); + + gst_object_unref(server); + return NULL; } diff --git a/unittest/ut_srt_receiver.cpp b/unittest/ut_srt_receiver.cpp index 612b66f..b06f7a4 100644 --- a/unittest/ut_srt_receiver.cpp +++ b/unittest/ut_srt_receiver.cpp @@ -47,9 +47,13 @@ static void dataPacketCb(mtpr_h mtpr, mtpr_media_type_e type, unsigned int id, media_packet_h packet, void *user_data) { LOGD("callback is invoked. type: %d, id: %d", type, id); - auto p = static_cast<std::promise<bool>*>(user_data); - assert(p); - p->set_value(true); + static std::once_flag flag; + + std::call_once(flag, [&](){ + auto p = static_cast<std::promise<bool>*>(user_data); + assert(p); + p->set_value(true); + }); } static bool waitDataPacket(std::future<bool>& f) { @@ -84,7 +88,6 @@ public: mtpr_state_e state = MTPR_STATE_IDLE; LOGD("Enter"); - stop_srt_sender(); if (_mtpr) { ret = mtpr_get_state(_mtpr, &state); @@ -98,6 +101,7 @@ public: ASSERT_EQ(ret, MTPR_ERROR_NONE); } + stop_srt_sender(); LOGD("Leave"); } |