rtc_plugins/util/RTCContext.cpp

337 lines
13 KiB
C++
Raw Normal View History

2025-04-09 16:18:50 +08:00
#include "RTCContext.h"
void RTCContext::onRoom(uint32_t typeId, RTCENGINE_NAMESPACE::MRTCRoomInfo& roomInfo) {
//std::cout << "RTCContext::onRoom():" << roomInfo.roomId << "," << roomInfo.displayName << "," << roomInfo.userId << "," << roomInfo.message;
std::cout << "RTCContext::onRoom()" << std::endl;
std::lock_guard<std::mutex> lock(mutex_);
isOnRoom_ = true;
}
void RTCContext::onConsumer(uint32_t msgId, const char* roomId, const char* peerId, RTCENGINE_NAMESPACE::MRTCConsumerInfo& consumerInfo) {
std::cout << "RTCContext::onConsumer():" << consumerInfo.roomId << "," << consumerInfo.displayName << "," << consumerInfo.channelIndex;
std::lock_guard<std::mutex> lock(mutex_);
isOnConsumer_ = true;
//std::cout << "RTCContext::onConsumer()" << std::endl;
}
void RTCContext::onRender(const char* roomId, const char* peerId,
RTCENGINE_NAMESPACE::MRTCVideoSourceType sourceType, const RTCENGINE_NAMESPACE::MRTCVideoFrame& videoFrame) {
std::cout << "RTCContext::onRender()" << std::endl;
}
void RTCContext::onCallBackMessage(uint32_t msgId, const char* msg) {
std::lock_guard<std::mutex> lock(mutex_);
if (msgId == (uint32_t)mrtc::JOIN_MULTI_ROOM_SUCCESS) {
std::cout << "receive join multi room callback" << msgId;
isJoinMultiRoom_ = true;
}
std::cout << "RTCContext::onCallBackMessage(), msgId:" << msgId << ", msg:" << msg;
//std::cout << "RTCContext::onCallBackMessage()" << std::endl;
}
void RTCContext::onCallBackCustomData(RTCENGINE_NAMESPACE::MRTCCustomDataObject object) {
//std::cout << "RTCContext::onCallBackCustomData(), obj:" << object.peerId << "," << object.data << "," << object.data_length;
std::cout << "RTCContext::onCallBackCustomData()" << std::endl;
}
void RTCContext::onSoundLevelUpdate(const char* roomId, const char* peerId, uint16_t audioSourceType,
uint8_t channelIndex, uint16_t volume, int32_t vad)
{
std::cout << "RTCContext::onSoundLevelUpdate()" << std::endl;
}
2025-04-10 11:15:04 +08:00
/*
2025-04-09 16:18:50 +08:00
void RTCContext::onAudioProcess(const char* roomId, const char* peerId,
mrtc::MRTCAudioFrame& audioFrame, mrtc::MRTCAudioSourceType audioSourceType)
{
2025-04-09 18:17:40 +08:00
namespace py = boost::python;
2025-04-09 16:18:50 +08:00
std::cout << "-----------------------------------" << std::endl;
2025-04-10 11:06:40 +08:00
std::cout << "dataCount:" << audioFrame.dataCount << audioSourceType << std::endl;
2025-04-10 11:10:25 +08:00
if (audioFrame.data == nullptr) {
std::cout << "sudioFrame data is null" << std::endl;
} else if (!py_callback_.is_none()) {
2025-04-09 16:18:50 +08:00
std::cout << "python callback" << std::endl;
2025-04-09 18:13:36 +08:00
npy_intp dims[1] = {audioFrame.dataCount};
2025-04-10 11:06:40 +08:00
std::cout << "step1" << std::endl;
2025-04-09 18:13:36 +08:00
PyObject* pyArray = PyArray_SimpleNewFromData(1, dims, NPY_INT16, audioFrame.data);
2025-04-10 11:06:40 +08:00
std::cout << "step2" << std::endl;
2025-04-09 18:13:36 +08:00
py_callback_(py::handle<>(pyArray), audioFrame.dataCount, audioFrame.sampleRate, audioFrame.numChannels,
2025-04-09 16:18:50 +08:00
audioFrame.channelIndex);
2025-04-10 11:06:40 +08:00
std::cout << "step3" << std::endl;
2025-04-09 16:18:50 +08:00
}
}
2025-04-10 11:15:04 +08:00
*/
void RTCContext::onAudioProcess(const char* roomId, const char* peerId,
mrtc::MRTCAudioFrame& audioFrame,
mrtc::MRTCAudioSourceType audioSourceType)
{
namespace py = boost::python;
2025-04-10 11:34:01 +08:00
PyGILState_STATE gstate = PyGILState_Ensure();
2025-04-10 11:15:04 +08:00
try {
std::cout << "-----------------------------------" << std::endl;
std::cout << "dataCount:" << audioFrame.dataCount << std::endl;
2025-04-10 12:47:13 +08:00
std::cout << "dataCount value: " << audioFrame.dataCount
<< " (max: " << std::numeric_limits<npy_intp>::max() << ")" << std::endl;
2025-04-10 13:00:35 +08:00
2025-04-10 21:19:55 +08:00
std::cout << "onAudioProcess, numpyApi_:" << numpyApi_[93] << std::endl;
2025-04-10 20:51:28 +08:00
void** numpyApi = numpyApi_;
if (!numpyApi || !numpyApi[93]) { // 93是PyArray_SimpleNew的偏移量
2025-04-10 21:10:35 +08:00
std::cout << "numpyApi is null in onAudioProcess" << std::endl;
2025-04-10 20:51:28 +08:00
} else {
2025-04-10 21:13:44 +08:00
std::cout << "numpyApi is not null in onAudioProcess:" << numpyApi[93] << std::endl;
2025-04-10 20:51:28 +08:00
}
//auto numpyApi = RTCContext::numpy_api();
2025-04-10 18:18:56 +08:00
std::cout << "step1" << std::endl;
2025-04-10 17:47:00 +08:00
if (!numpyApi) {
2025-04-10 13:00:35 +08:00
PyGILState_Release(gstate);
throw std::runtime_error("NumPy C-API not initialized. Call import_array() in module init");
2025-04-10 12:50:09 +08:00
}
2025-04-10 18:18:56 +08:00
std::cout << "step2" << std::endl;
2025-04-10 17:47:00 +08:00
using PyArray_SimpleNew_t = PyObject*(*)(int, npy_intp*, int);
2025-04-10 18:18:56 +08:00
std::cout << "step3" << std::endl;
2025-04-10 20:51:28 +08:00
auto PyArray_SimpleNew = reinterpret_cast<PyArray_SimpleNew_t>(numpyApi[93]);
2025-04-10 21:13:44 +08:00
std::cout << "step4, PyArray_SimpleNew:" << PyArray_SimpleNew << std::endl;
2025-04-10 12:50:09 +08:00
2025-04-10 13:00:35 +08:00
// 3. 严格校验输入数据
2025-04-10 11:15:04 +08:00
if (!audioFrame.data || audioFrame.dataCount <= 0) {
2025-04-10 11:34:01 +08:00
PyGILState_Release(gstate);
2025-04-10 13:00:35 +08:00
throw std::invalid_argument("Invalid audio frame data");
}
2025-04-10 18:18:56 +08:00
std::cout << "step5" << std::endl;
2025-04-10 13:00:35 +08:00
// 4. 安全创建维度数组(带边界检查)
if (audioFrame.dataCount > std::numeric_limits<npy_intp>::max()) {
PyGILState_Release(gstate);
throw std::overflow_error("Audio frame size exceeds maximum limit");
2025-04-10 11:15:04 +08:00
}
2025-04-10 18:18:56 +08:00
std::cout << "step6" << std::endl;
2025-04-10 12:47:13 +08:00
npy_intp dims[1] = {static_cast<npy_intp>(audioFrame.dataCount)};
2025-04-10 11:15:04 +08:00
2025-04-10 18:18:56 +08:00
std::cout << "step7" << std::endl;
2025-04-10 13:00:35 +08:00
// 5. 创建NumPy数组带内存保护
PyObject* pyArray = nullptr;
2025-04-10 17:47:00 +08:00
pyArray = PyArray_SimpleNew(1, dims, NPY_INT16);
2025-04-10 18:18:56 +08:00
std::cout << "step8" << std::endl;
2025-04-10 17:47:00 +08:00
if (!pyArray) {
PyGILState_Release(gstate);
throw std::bad_alloc();
2025-04-10 13:00:35 +08:00
}
2025-04-10 18:18:56 +08:00
std::cout << "step9" << std::endl;
2025-04-10 13:00:35 +08:00
// 6. 安全拷贝数据(带对齐检查)
if (reinterpret_cast<uintptr_t>(audioFrame.data) % alignof(int16_t) != 0) {
Py_DECREF(pyArray);
2025-04-10 11:34:01 +08:00
PyGILState_Release(gstate);
2025-04-10 13:00:35 +08:00
throw std::runtime_error("Unaligned audio data pointer");
2025-04-10 11:15:04 +08:00
}
2025-04-10 18:18:56 +08:00
std::cout << "step10" << std::endl;
2025-04-10 13:00:35 +08:00
std::memcpy(PyArray_DATA(reinterpret_cast<PyArrayObject*>(pyArray)),
2025-04-10 11:34:01 +08:00
audioFrame.data,
audioFrame.dataCount * sizeof(int16_t));
2025-04-10 11:15:04 +08:00
2025-04-10 18:18:56 +08:00
std::cout << "step11" << std::endl;
2025-04-10 13:00:35 +08:00
// 7. 执行回调(带引用计数保护)
2025-04-10 20:51:28 +08:00
if (!pyCallback_.is_none()) {
2025-04-10 13:00:35 +08:00
try {
2025-04-10 20:51:28 +08:00
pyCallback_(
2025-04-10 13:00:35 +08:00
py::handle<>(pyArray), // 自动管理引用
audioFrame.dataCount,
audioFrame.sampleRate,
audioFrame.numChannels,
audioFrame.channelIndex
);
} catch (...) {
Py_DECREF(pyArray);
throw; // 重新抛出异常
}
2025-04-10 11:15:04 +08:00
}
2025-04-10 18:18:56 +08:00
std::cout << "step12" << std::endl;
2025-04-10 11:15:04 +08:00
2025-04-10 13:00:35 +08:00
// 8. 释放资源
2025-04-10 11:15:04 +08:00
Py_DECREF(pyArray);
2025-04-10 18:18:56 +08:00
std::cout << "step13" << std::endl;
2025-04-10 13:00:35 +08:00
PyGILState_Release(gstate);
2025-04-10 18:18:56 +08:00
std::cout << "step14" << std::endl;
2025-04-10 11:15:04 +08:00
} catch (const std::exception& e) {
std::cerr << "Audio process error: " << e.what() << std::endl;
PyErr_Print();
}
2025-04-10 18:26:13 +08:00
exit(0);
2025-04-10 11:15:04 +08:00
}
2025-04-09 16:18:50 +08:00
void RTCContext::onProducer(uint32_t msgId, mrtc::MRTCProducerInfo& info)
{
std::cout << "-----------------------------------" << std::endl;
std::cout << "RTCContext::onProducer()" << std::endl;
}
bool RTCContext::init(const char* selfUserId, const char* selfDisplayName, const char* selfRoomId)
{
2025-04-10 21:19:55 +08:00
std::cout << "init, numpyApi_:" << numpyApi_[93] << std::endl;
2025-04-10 20:51:28 +08:00
void** numpyApi = numpyApi_;
if (!numpyApi || !numpyApi[93]) { // 93是PyArray_SimpleNew的偏移量
2025-04-10 21:10:35 +08:00
std::cout << "numpyApi is null in init" << std::endl;
2025-04-10 16:38:26 +08:00
} else {
2025-04-10 21:10:35 +08:00
std::cout << "numpyApi is not null in init" << std::endl;
2025-04-10 16:38:26 +08:00
}
2025-04-09 16:18:50 +08:00
mrtc::IMRTCEngineFactory * rtcFactory = mrtc::getMRTCEngineFactory();
if (!rtcFactory)
{
return false;
}
rtcEngine_ = rtcFactory->produceMRTCEngine();
if (!rtcEngine_)
{
return false;
}
mrtc::MRTCEngineConfig engineConfig;
strcpy(engineConfig.domain, domain);
strcpy(engineConfig.applicationId, appid);
strcpy(engineConfig.appSecrectKey, appSecrectKey);
engineConfig.port = port;
if (0 != rtcEngine_->init(engineConfig, this))
{
std::cout << "RTCContext::instance().init() failed" << std::endl;
return false;
}
if (0 != rtcEngine_->setUserInfo(selfUserId, selfDisplayName, selfRoomId))
{
std::cout << "RTCContext::instance().setUserInfo() failed" << std::endl;
return false;
}
mrtc::MRTCJoinAuthority authority;
strcpy(authority.applicationId, appid);
strcpy(authority.appSecretKey, appSecrectKey);
mrtc::MRTCJoinConfig loginConfig;
if (0!= rtcEngine_->joinRoom(authority, loginConfig))
{
std::cout << "RTCContext::instance().joinRoom() failed" << std::endl;
return false;
}
if (0 != rtcEngine_->registerListener(mrtc::MRTCListenerType::TYPE_LISTENER_ROOM, this))
{
std::cout << "RTCContext::instance().registerListener() failed" << std::endl;
return false;
}
if (0 != rtcEngine_->registerListener(mrtc::MRTCListenerType::TYPE_LISTENER_CONSUMER, this))
{
std::cout << "RTCContext::instance().registerListener() failed" << std::endl;
return false;
}
return true;
}
bool RTCContext::initRecv(const char* destRoomId, const char* srcUserId, const int16_t destChannelIndex)
{
2025-04-10 21:19:55 +08:00
std::cout << "initRecv, numpyApi_:" << numpyApi_[93] << std::endl;
2025-04-10 20:51:28 +08:00
void** numpyApi = numpyApi_;
if (!numpyApi || !numpyApi[93]) { // 93是PyArray_SimpleNew的偏移量
2025-04-10 21:10:35 +08:00
std::cout << "numpyApi is null in initRecv" << std::endl;
2025-04-10 16:38:26 +08:00
} else {
2025-04-10 21:10:35 +08:00
std::cout << "numpyApi is not null in initRecv" << std::endl;
2025-04-10 16:38:26 +08:00
}
2025-04-09 16:18:50 +08:00
while (!isOnConsumer_)
{
std::cout << "wait for OnConsumer" << std::endl;
sleep(3);
}
std::cout << "registerSoundLevelListener" << std::endl;
int16_t ret1 = rtcEngine_->registerSoundLevelListener(mrtc::TYPE_AUDIO_SOURCE_CUSTOM, destRoomId,
srcUserId, destChannelIndex, this);
if (0 != ret1)
{
std::cout << "RTCContext::instance().registerSoundLevelListener() inUser failed, ret:" << ret1;
return false;
}
std::cout << "muteAudio" << std::endl;
int16_t ret2 = rtcEngine_->muteAudio(destRoomId, srcUserId, mrtc::TYPE_AUDIO_SOURCE_CUSTOM, false, destChannelIndex);
if (0 != ret2)
{
std::cout << "RTCContext::instance().muteAudio() failed, ret:" << ret2;
return false;
}
std::cout << "init recv succ" << std::endl;
return true;
}
bool RTCContext::initSend(const char* destRoomId, const int16_t destChannelIndex)
{
while (!isOnRoom_)
{
std::cout << "wait for OnRoom" << std::endl;
sleep(3);
}
std::cout << "join multi room" << std::endl;
int16_t ret1 = rtcEngine_->joinMultiRoom(destRoomId);
if (ret1 != 0)
{
std::cout << "joinMultiRoom fail, ret:" << ret1;
return false;
}
mrtc::MRTCAudioOption option;
strcpy(option.dstRoomId, destRoomId);
option.channelIndex = destChannelIndex;
std::cout << "startCustomAudio" << std::endl;
int16_t ret2 = rtcEngine_->startCustomAudio(option);
if (ret2 != 0)
{
std::cout << "startCustomAudio fail, ret:" << ret2;
return false;
}
std::cout << "init send succ" << std::endl;
return true;
}
void RTCContext::destorySend(const int16_t selfChannelIndex)
{
rtcEngine_->stopCustomAudio(selfChannelIndex);
}
int16_t RTCContext::sendAudioData(uint8_t channelIndex, const void* pData, int32_t nSampleRate, uint64_t nNumberOfChannels, uint64_t dataLength)
{
std::lock_guard<std::mutex> lock(mutex_);
if (pData_)
{
return rtcEngine_->sendCustomAudioData(channelIndex, pData, nSampleRate, nNumberOfChannels, dataLength);
}
return 0;
}
int16_t RTCContext::sendCustomAudioData(const int16_t channelIndex, void* customData, int32_t sampleRate,
uint64_t channelNum, uint64_t dataLen)
{
while(!isOnRoom_ || !isJoinMultiRoom_) {
std::cout << "wait for room and multi room before send" << std::endl;
sleep(3);
}
std::lock_guard<std::mutex> lock(mutex_);
2025-04-10 09:07:06 +08:00
if (customData == nullptr) {
std::cout << "customData is null" << std::endl;
return -1;
}
std::cout << "customData addr is:" << customData << std::endl;
2025-04-09 16:18:50 +08:00
return rtcEngine_->sendCustomAudioData(channelIndex, customData, sampleRate, channelNum, dataLen);
}
mrtc::IMRTCEngine* RTCContext::getRtcEngine() const
{
std::lock_guard<std::mutex> lock(mutex_);
return rtcEngine_;
}
void* RTCContext::getpData() const
{
std::lock_guard<std::mutex> lock(mutex_);
return pData_;
}
void RTCContext::setpData(void* pData)
{
std::lock_guard<std::mutex> lock(mutex_);
pData_ = pData;
}
void RTCContext::setPyCallback(boost::python::object callback) {
std::lock_guard<std::mutex> lock(mutex_);
2025-04-10 20:51:28 +08:00
pyCallback_ = callback;
}
void RTCContext::setNumpyApi(void **numpyApi) {
std::lock_guard<std::mutex> lock(mutex_);
numpyApi_ = numpyApi;
2025-04-10 21:19:55 +08:00
std::cout << "setNupyApi, numpyApi_:" << numpyApi_[93] << std::endl;
2025-04-09 16:18:50 +08:00
}