-
Notifications
You must be signed in to change notification settings - Fork 44
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: expand the implementation of extension tester to allow it to be…
… used for testing the graph (#296) Co-authored-by: Hu Yueh-Wei <[email protected]>
- Loading branch information
Showing
41 changed files
with
1,676 additions
and
334 deletions.
There are no files selected for viewing
253 changes: 253 additions & 0 deletions
253
core/include/ten_runtime/binding/cpp/experimental/ten_client_proxy.h
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,253 @@ | ||
// | ||
// Copyright © 2024 Agora | ||
// This file is part of TEN Framework, an open source project. | ||
// Licensed under the Apache License, Version 2.0, with certain conditions. | ||
// Refer to the "LICENSE" file in the root directory for more information. | ||
// | ||
#pragma once | ||
|
||
#include "ten_runtime/binding/cpp/internal/test/env_tester_proxy.h" | ||
#include "ten_runtime/binding/cpp/internal/test/extension_tester.h" | ||
#include "ten_utils/log/log.h" | ||
|
||
namespace ten { | ||
|
||
using ten_client_proxy_send_cmd_result_handler_func_t = | ||
std::function<void(std::unique_ptr<ten::cmd_result_t>)>; | ||
|
||
class ten_client_proxy_event_handler_t { | ||
public: | ||
ten_client_proxy_event_handler_t() = default; | ||
virtual ~ten_client_proxy_event_handler_t() = default; | ||
|
||
ten_client_proxy_event_handler_t(const ten_client_proxy_event_handler_t &) = | ||
delete; | ||
ten_client_proxy_event_handler_t(ten_client_proxy_event_handler_t &&) = | ||
delete; | ||
ten_client_proxy_event_handler_t &operator=( | ||
const ten_client_proxy_event_handler_t &) = delete; | ||
ten_client_proxy_event_handler_t &operator=( | ||
const ten_client_proxy_event_handler_t &&) = delete; | ||
|
||
virtual void on_start() {} | ||
|
||
virtual void on_cmd(std::unique_ptr<cmd_t> cmd) {} | ||
|
||
virtual void on_data(std::unique_ptr<data_t> data) {} | ||
|
||
virtual void on_audio_frame(std::unique_ptr<audio_frame_t> audio_frame) {} | ||
|
||
virtual void on_video_frame(std::unique_ptr<video_frame_t> video_frame) {} | ||
}; | ||
|
||
namespace { | ||
|
||
class ten_client_proxy_internal_impl_t : public ten::extension_tester_t { | ||
protected: | ||
void on_start(ten::ten_env_tester_t &ten_env_tester) override { | ||
ten_env_tester_proxy_ = std::unique_ptr<ten::ten_env_tester_proxy_t>( | ||
ten::ten_env_tester_proxy_t::create(ten_env_tester)); | ||
TEN_ASSERT(ten_env_tester_proxy_, "Should not happen."); | ||
|
||
if (event_handler_ != nullptr) { | ||
event_handler_->on_start(); | ||
} | ||
|
||
ten_env_tester.on_start_done(); | ||
} | ||
|
||
void on_cmd(ten::ten_env_tester_t & /*ten_env_tester*/, | ||
std::unique_ptr<ten::cmd_t> cmd) override { | ||
if (event_handler_ != nullptr) { | ||
event_handler_->on_cmd(std::move(cmd)); | ||
} | ||
} | ||
|
||
void on_data(ten::ten_env_tester_t & /*ten_env_tester*/, | ||
std::unique_ptr<ten::data_t> data) override { | ||
if (event_handler_ != nullptr) { | ||
event_handler_->on_data(std::move(data)); | ||
} | ||
} | ||
|
||
void on_audio_frame( | ||
ten::ten_env_tester_t & /*ten_env_tester*/, | ||
std::unique_ptr<ten::audio_frame_t> audio_frame) override { | ||
if (event_handler_ != nullptr) { | ||
event_handler_->on_audio_frame(std::move(audio_frame)); | ||
} | ||
} | ||
|
||
void on_video_frame( | ||
ten::ten_env_tester_t & /*ten_env_tester*/, | ||
std::unique_ptr<ten::video_frame_t> video_frame) override { | ||
if (event_handler_ != nullptr) { | ||
event_handler_->on_video_frame(std::move(video_frame)); | ||
} | ||
} | ||
|
||
static void proxy_on_cmd_response( | ||
std::unique_ptr<ten::cmd_result_t> cmd_result, | ||
const ten::ten_client_proxy_send_cmd_result_handler_func_t | ||
&result_handler) { | ||
if (result_handler) { | ||
result_handler(std::move(cmd_result)); | ||
} | ||
} | ||
|
||
public: | ||
void register_callback(ten::ten_client_proxy_event_handler_t *event_handler) { | ||
event_handler_ = event_handler; | ||
} | ||
|
||
bool send_cmd( | ||
std::unique_ptr<ten::cmd_t> cmd, | ||
ten::ten_client_proxy_send_cmd_result_handler_func_t &&result_handler) { | ||
TEN_ASSERT(ten_env_tester_proxy_, "Invalid state."); | ||
|
||
if (ten_env_tester_proxy_ == nullptr) { | ||
TEN_LOGE("Failed to send_cmd: %s before started.", cmd->get_name()); | ||
return false; | ||
} | ||
|
||
auto cmd_shared = | ||
std::make_shared<std::unique_ptr<ten::cmd_t>>(std::move(cmd)); | ||
|
||
return ten_env_tester_proxy_->notify( | ||
[cmd_shared, result_handler](ten::ten_env_tester_t &ten_env_tester) { | ||
ten_env_tester.send_cmd( | ||
std::move(*cmd_shared), | ||
[result_handler](ten::ten_env_tester_t & /*ten_env_tester*/, | ||
std::unique_ptr<ten::cmd_result_t> cmd_result) { | ||
proxy_on_cmd_response(std::move(cmd_result), result_handler); | ||
}); | ||
}, | ||
nullptr); | ||
} | ||
|
||
bool send_data(std::unique_ptr<ten::data_t> data) { | ||
TEN_ASSERT(ten_env_tester_proxy_, "Invalid state."); | ||
|
||
if (ten_env_tester_proxy_ == nullptr) { | ||
TEN_LOGE("Failed to send_data before started."); | ||
return false; | ||
} | ||
|
||
auto data_shared = | ||
std::make_shared<std::unique_ptr<ten::data_t>>(std::move(data)); | ||
|
||
return ten_env_tester_proxy_->notify( | ||
[data_shared](ten::ten_env_tester_t &env_tester) { | ||
env_tester.send_data(std::move(*data_shared)); | ||
}, | ||
nullptr); | ||
} | ||
|
||
bool send_audio_frame(std::unique_ptr<ten::audio_frame_t> audio_frame) { | ||
TEN_ASSERT(ten_env_tester_proxy_, "Invalid state."); | ||
|
||
if (ten_env_tester_proxy_ == nullptr) { | ||
TEN_LOGE("Failed to send_audio_frame before started."); | ||
return false; | ||
} | ||
|
||
auto audio_frame_shared = | ||
std::make_shared<std::unique_ptr<ten::audio_frame_t>>( | ||
std::move(audio_frame)); | ||
|
||
return ten_env_tester_proxy_->notify( | ||
[audio_frame_shared](ten::ten_env_tester_t &env_tester) { | ||
env_tester.send_audio_frame(std::move(*audio_frame_shared)); | ||
}, | ||
nullptr); | ||
} | ||
|
||
bool send_video_frame(std::unique_ptr<ten::video_frame_t> video_frame) { | ||
TEN_ASSERT(ten_env_tester_proxy_, "Invalid state."); | ||
|
||
if (ten_env_tester_proxy_ == nullptr) { | ||
TEN_LOGE("Failed to send_video_frame before started."); | ||
return false; | ||
} | ||
|
||
auto video_frame_shared = | ||
std::make_shared<std::unique_ptr<ten::video_frame_t>>( | ||
std::move(video_frame)); | ||
|
||
return ten_env_tester_proxy_->notify( | ||
[video_frame_shared](ten::ten_env_tester_t &env_tester) { | ||
env_tester.send_video_frame(std::move(*video_frame_shared)); | ||
}, | ||
nullptr); | ||
} | ||
|
||
bool stop() { | ||
if (ten_env_tester_proxy_ == nullptr) { | ||
TEN_LOGE("Failed to stop before started."); | ||
return false; | ||
} | ||
|
||
return ten_env_tester_proxy_->notify( | ||
[](ten::ten_env_tester_t &env_tester) { env_tester.stop_test(); }, | ||
nullptr); | ||
} | ||
|
||
private: | ||
ten::ten_client_proxy_event_handler_t *event_handler_; | ||
|
||
// The thread-safety should be guaranteed by the caller. | ||
std::unique_ptr<ten::ten_env_tester_proxy_t> ten_env_tester_proxy_; | ||
}; | ||
|
||
} // namespace | ||
|
||
class ten_client_proxy_t { | ||
public: | ||
ten_client_proxy_t() = default; | ||
virtual ~ten_client_proxy_t() = default; | ||
|
||
ten_client_proxy_t(const ten_client_proxy_t &) = delete; | ||
ten_client_proxy_t(ten_client_proxy_t &&) = delete; | ||
ten_client_proxy_t &operator=(const ten_client_proxy_t &) = delete; | ||
ten_client_proxy_t &operator=(const ten_client_proxy_t &&) = delete; | ||
|
||
void add_addon_base_dir(const char *addon_path) { | ||
TEN_ASSERT(addon_path, "Invalid argument."); | ||
impl_.add_addon_base_dir(addon_path); | ||
} | ||
|
||
void start_graph(const char *graph_json) { | ||
TEN_ASSERT(graph_json, "Invalid argument."); | ||
impl_.set_test_mode_graph(graph_json); | ||
impl_.run(); | ||
} | ||
|
||
// These functions should be called after the on_start callback is received. | ||
|
||
void send_cmd( | ||
std::unique_ptr<cmd_t> cmd, | ||
ten_client_proxy_send_cmd_result_handler_func_t &&result_handler) { | ||
impl_.send_cmd(std::move(cmd), std::move(result_handler)); | ||
} | ||
|
||
void send_data(std::unique_ptr<data_t> data) { | ||
impl_.send_data(std::move(data)); | ||
} | ||
|
||
void send_audio_frame(std::unique_ptr<audio_frame_t> audio_frame) { | ||
impl_.send_audio_frame(std::move(audio_frame)); | ||
} | ||
|
||
void send_video_frame(std::unique_ptr<video_frame_t> video_frame) { | ||
impl_.send_video_frame(std::move(video_frame)); | ||
} | ||
|
||
void register_event_handler(ten_client_proxy_event_handler_t *event_handler) { | ||
impl_.register_callback(event_handler); | ||
} | ||
|
||
private: | ||
ten_client_proxy_internal_impl_t impl_; | ||
}; | ||
|
||
} // namespace ten |
Oops, something went wrong.