Compare commits
31 Commits
Author | SHA1 | Date |
---|---|---|
|
7c64255cbd | |
|
9c8c15a924 | |
|
3dd6a84c5d | |
|
5179cc5aa7 | |
|
8d8c759e3e | |
|
3ac6763cba | |
|
356be092d4 | |
|
4043aae31a | |
|
ee855524dd | |
|
d4cf9b8d70 | |
|
81a6bc7c6f | |
|
9893ed5da2 | |
|
f8daa9c277 | |
|
34306dcaca | |
|
287bd759a1 | |
|
0bfb8fe405 | |
|
8eb7adb0fd | |
|
00672f25fe | |
|
aced2e2308 | |
|
2fd9f33a68 | |
|
012a95f475 | |
|
6a2639661f | |
|
35febd4b41 | |
|
dc9dd314d6 | |
|
7086e4cd21 | |
|
d10c751a06 | |
|
16962bf871 | |
|
f2299b38db | |
|
281bb13a73 | |
|
498932385e | |
|
5374dae17e |
|
@ -13,11 +13,7 @@ void** get_numpy_api() {
|
||||||
namespace py = boost::python;
|
namespace py = boost::python;
|
||||||
|
|
||||||
int init(const char* selfUserId, const char* selfDisplayName, const char* selfRoomId, boost::python::object callback) {
|
int init(const char* selfUserId, const char* selfDisplayName, const char* selfRoomId, boost::python::object callback) {
|
||||||
if (!PyArray_API) {
|
|
||||||
std::cout << "PyArray_API is null in outer init" << std::endl;
|
|
||||||
} else {
|
|
||||||
std::cout << "PyArray_API is not null in outer init" << std::endl;
|
|
||||||
}
|
|
||||||
RTCContext::instance().setPyCallback(callback);
|
RTCContext::instance().setPyCallback(callback);
|
||||||
bool res = RTCContext::instance().init(selfUserId, selfDisplayName, selfRoomId);
|
bool res = RTCContext::instance().init(selfUserId, selfDisplayName, selfRoomId);
|
||||||
if (res) {
|
if (res) {
|
||||||
|
@ -27,11 +23,7 @@ int init(const char* selfUserId, const char* selfDisplayName, const char* selfRo
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
int initRecv(const char* destRoomId, const char* srcUserId, const int16_t destChannelIndex) {
|
int initRecv(const char* destRoomId, const char* srcUserId, const int16_t destChannelIndex) {
|
||||||
if (!PyArray_API) {
|
|
||||||
std::cout << "PyArray_API is null in outer initRecv" << std::endl;
|
|
||||||
} else {
|
|
||||||
std::cout << "PyArray_API is not null in outer initRecv" << std::endl;
|
|
||||||
}
|
|
||||||
bool res = RTCContext::instance().initRecv(destRoomId, srcUserId, destChannelIndex);
|
bool res = RTCContext::instance().initRecv(destRoomId, srcUserId, destChannelIndex);
|
||||||
if (res) {
|
if (res) {
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -39,8 +31,8 @@ int initRecv(const char* destRoomId, const char* srcUserId, const int16_t destCh
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
int initSend(const char* srcRoomId, const char* destRoomId, const int16_t destChannelIndex) {
|
int initSend(const char* srcRoomId, const char* destRoomId, const int16_t destChannelIndex, const uint8_t channelNum) {
|
||||||
bool res = RTCContext::instance().initSend(srcRoomId, destRoomId, destChannelIndex);
|
bool res = RTCContext::instance().initSend(srcRoomId, destRoomId, destChannelIndex, channelNum);
|
||||||
if (res) {
|
if (res) {
|
||||||
return 0;
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
|
@ -107,62 +99,6 @@ int sendCustomAudioData(int16_t destChannelIndex, py::object pD,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
int sendCustomAudioData(const int16_t destChannelIndex, py::object pyData, int32_t sampleRate, uint64_t channelNum,
|
|
||||||
uint64_t dataLen) {
|
|
||||||
try {
|
|
||||||
//py::object pyData = create_int16_array();
|
|
||||||
std::cout << "step 1" << std::endl;
|
|
||||||
// 1. 检查输入有效性
|
|
||||||
if (pyData.ptr() == nullptr) {
|
|
||||||
throw std::runtime_error("Input data is NULL");
|
|
||||||
}
|
|
||||||
|
|
||||||
std::cout << "step 2" << std::endl;
|
|
||||||
std::cout << "pyData ptr is:" << pyData.ptr() << std::endl;
|
|
||||||
if (!pyData.ptr() || !Py_IsInitialized() || !PyObject_TypeCheck(pyData.ptr(), &PyBaseObject_Type)) {
|
|
||||||
throw std::runtime_error("Invalid Python object");
|
|
||||||
}
|
|
||||||
std::cout << "step 2" << std::endl;
|
|
||||||
// 2. 检查是否是 numpy 数组
|
|
||||||
if (!PyArray_Check(pyData.ptr())) {
|
|
||||||
std::cout << "input is notnumpy" << std::endl;
|
|
||||||
throw std::runtime_error("Input is not a numpy array");
|
|
||||||
}
|
|
||||||
|
|
||||||
std::cout << "step 3" << std::endl;
|
|
||||||
// 3. 转换为 PyArrayObject
|
|
||||||
PyArrayObject* npArray = reinterpret_cast<PyArrayObject*>(pyData.ptr());
|
|
||||||
|
|
||||||
std::cout << "step 4" << std::endl;
|
|
||||||
// 4. 检查数据类型是否为 int16
|
|
||||||
if (PyArray_TYPE(npArray) != NPY_INT16) {
|
|
||||||
throw std::runtime_error("Array must be of type int16 (np.int16)");
|
|
||||||
}
|
|
||||||
|
|
||||||
std::cout << "step 5" << std::endl;
|
|
||||||
// 5. 检查数据是否连续
|
|
||||||
if (!PyArray_ISCONTIGUOUS(npArray)) {
|
|
||||||
throw std::runtime_error("Array must be contiguous in memory");
|
|
||||||
}
|
|
||||||
std::cout << "step 6" << std::endl;
|
|
||||||
|
|
||||||
// 6. 获取数据指针
|
|
||||||
void* dataPtr = PyArray_DATA(npArray);
|
|
||||||
if (dataPtr == nullptr) {
|
|
||||||
throw std::runtime_error("Invalid data pointer");
|
|
||||||
}
|
|
||||||
std::cout << "step 7" << std::endl;
|
|
||||||
return RTCContext::instance().sendCustomAudioData(destChannelIndex, dataPtr, sampleRate, channelNum, dataLen);
|
|
||||||
|
|
||||||
} catch (const std::exception& e) {
|
|
||||||
std::cout << "error:" << e.what() << std::endl;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
void init_numpy() {
|
void init_numpy() {
|
||||||
// 直接调用底层函数,绕过宏的问题
|
// 直接调用底层函数,绕过宏的问题
|
||||||
if (_import_array() < 0) {
|
if (_import_array() < 0) {
|
||||||
|
@ -184,14 +120,6 @@ BOOST_PYTHON_MODULE(rtc_plugins) {
|
||||||
std::cout << "set numpyApi succ:" << numpyApi[93] << std::endl;
|
std::cout << "set numpyApi succ:" << numpyApi[93] << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
if (!PyArray_API) {
|
|
||||||
std::cout << "PyArray_API is null" << std::endl;
|
|
||||||
} else {
|
|
||||||
std::cout << "PyArray_API is not null" << std::endl;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
py::def("init", &init);
|
py::def("init", &init);
|
||||||
py::def("initRecv", &initRecv);
|
py::def("initRecv", &initRecv);
|
||||||
py::def("initSend", &initSend);
|
py::def("initSend", &initSend);
|
||||||
|
|
|
@ -17,7 +17,7 @@ ret = rtc_plugins.init(srcUserId, srcDisplayName, srcRoomId, my_callback)
|
||||||
if ret != 0:
|
if ret != 0:
|
||||||
print(f"init fail, ret:{ret}")
|
print(f"init fail, ret:{ret}")
|
||||||
exit(1)
|
exit(1)
|
||||||
ret = rtc_plugins.initSend(srcRoomId, destRoomId, destChannelIndex)
|
ret = rtc_plugins.initSend(srcRoomId, destRoomId, destChannelIndex, 1)
|
||||||
if ret != 0:
|
if ret != 0:
|
||||||
print(f"initSend fail, ret:{ret}")
|
print(f"initSend fail, ret:{ret}")
|
||||||
exit(1)
|
exit(1)
|
||||||
|
|
|
@ -18,22 +18,7 @@ destChannelIndex = 47
|
||||||
def my_callback(shmName, dataSize, dataCount, sampleRate, numChannels, channelIndex):
|
def my_callback(shmName, dataSize, dataCount, sampleRate, numChannels, channelIndex):
|
||||||
print(f"dataSize:{dataSize}, dataCount:{dataCount}, sampleRate:{sampleRate}, numChannels:{numChannels}, channelIndex:{channelIndex}")
|
print(f"dataSize:{dataSize}, dataCount:{dataCount}, sampleRate:{sampleRate}, numChannels:{numChannels}, channelIndex:{channelIndex}")
|
||||||
print(f"data:{shmName}")
|
print(f"data:{shmName}")
|
||||||
#fd = os.open(shmName, os.O_RDONLY)
|
|
||||||
#if fd == -1:
|
|
||||||
# raise RuntimeError(f"无法打开共享内存 {shmName}")
|
|
||||||
|
|
||||||
## 2. 创建内存映射
|
|
||||||
#shm = mmap.mmap(fd, dataSize, mmap.MAP_SHARED, mmap.PROT_READ)
|
|
||||||
|
|
||||||
## 3. 转换为numpy数组 (零拷贝)
|
|
||||||
#audio_data = np.frombuffer(shm, dtype=c_int16, count=dataCount)
|
|
||||||
#print(f" 前5个采样点: {audio_data[:5]}")
|
|
||||||
#audioData = np.array([0, 1, -1, 0], dtype=np.int16)
|
|
||||||
#ret = rtc_plugins.sendCustomAudioData(srcChannelIndex, audioData, 48000, 1, len(audioData))
|
|
||||||
#if ret != 0:
|
|
||||||
# print(f"resend fail, ret:{ret}")
|
|
||||||
#else:
|
|
||||||
# print("resend succ")
|
|
||||||
ret = rtc_plugins.init(destUserId, destDisplayName, destRoomId, my_callback)
|
ret = rtc_plugins.init(destUserId, destDisplayName, destRoomId, my_callback)
|
||||||
if ret != 0:
|
if ret != 0:
|
||||||
print(f"init fail, ret:{ret}")
|
print(f"init fail, ret:{ret}")
|
||||||
|
@ -42,17 +27,17 @@ ret = rtc_plugins.initRecv(destRoomId, srcUserId, destChannelIndex)
|
||||||
if ret != 0:
|
if ret != 0:
|
||||||
print(f"initRecv fail, ret:{ret}")
|
print(f"initRecv fail, ret:{ret}")
|
||||||
exit(1)
|
exit(1)
|
||||||
ret = rtc_plugins.initSend(destRoomId, srcRoomId, srcChannelIndex)
|
ret = rtc_plugins.initSend(destRoomId, srcRoomId, srcChannelIndex, 1)
|
||||||
if ret != 0:
|
if ret != 0:
|
||||||
print(f"initSend fail, ret:{ret}")
|
print(f"initSend fail, ret:{ret}")
|
||||||
exit(1)
|
exit(1)
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
print("recv")
|
print("recv")
|
||||||
audioData = np.array([0, 1, -1, 0], dtype=np.int16)
|
#audioData = np.array([0, 1, -1, 0], dtype=np.int16)
|
||||||
ret = rtc_plugins.sendCustomAudioData(srcChannelIndex, audioData, 48000, 1, len(audioData))
|
#ret = rtc_plugins.sendCustomAudioData(srcChannelIndex, audioData, 48000, 1, len(audioData))
|
||||||
if ret != 0:
|
#if ret != 0:
|
||||||
print(f"resend fail, ret:{ret}")
|
# print(f"resend fail, ret:{ret}")
|
||||||
else:
|
#else:
|
||||||
print("resend succ")
|
# print("resend succ")
|
||||||
time.sleep(30)
|
time.sleep(30)
|
||||||
|
|
|
@ -18,7 +18,7 @@ ret = rtc_plugins.init(srcUserId, srcDisplayName, srcRoomId, my_callback)
|
||||||
if ret != 0:
|
if ret != 0:
|
||||||
print(f"init fail, ret:{ret}")
|
print(f"init fail, ret:{ret}")
|
||||||
exit(1)
|
exit(1)
|
||||||
ret = rtc_plugins.initSend(srcRoomId, destRoomId, destChannelIndex)
|
ret = rtc_plugins.initSend(srcRoomId, destRoomId, destChannelIndex, 1)
|
||||||
if ret != 0:
|
if ret != 0:
|
||||||
print(f"initSend fail, ret:{ret}")
|
print(f"initSend fail, ret:{ret}")
|
||||||
exit(1)
|
exit(1)
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
#include "RTCContext.h"
|
#include "RTCContext.h"
|
||||||
|
#define GIL
|
||||||
|
|
||||||
void RTCContext::onRoom(uint32_t typeId, RTCENGINE_NAMESPACE::MRTCRoomInfo& roomInfo) {
|
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():" << roomInfo.roomId << "," << roomInfo.displayName << "," << roomInfo.userId << "," << roomInfo.message;
|
||||||
|
@ -6,11 +7,30 @@ void RTCContext::onRoom(uint32_t typeId, RTCENGINE_NAMESPACE::MRTCRoomInfo& room
|
||||||
std::lock_guard<std::mutex> lock(mutex_);
|
std::lock_guard<std::mutex> lock(mutex_);
|
||||||
isOnRoom_ = true;
|
isOnRoom_ = true;
|
||||||
}
|
}
|
||||||
void RTCContext::onConsumer(uint32_t msgId, const char* roomId, const char* peerId, RTCENGINE_NAMESPACE::MRTCConsumerInfo& consumerInfo) {
|
void RTCContext::onConsumer(uint32_t msgId, const char* roomId, const char* peerId,
|
||||||
std::cout << "RTCContext::onConsumer():" << consumerInfo.roomId << "," << consumerInfo.displayName << "," << consumerInfo.channelIndex;
|
RTCENGINE_NAMESPACE::MRTCConsumerInfo& consumerInfo) {
|
||||||
std::lock_guard<std::mutex> lock(mutex_);
|
std::cout << "RTCContext::onConsumer():" << consumerInfo.roomId << "," << consumerInfo.displayName << ","
|
||||||
isOnConsumer_ = true;
|
<< consumerInfo.channelIndex << std::endl;
|
||||||
//std::cout << "RTCContext::onConsumer()" << std::endl;
|
if (isRecv_) {
|
||||||
|
std::lock_guard<std::mutex> lock(mutex_);
|
||||||
|
std::cout << "registerSoundLevelListener" << std::endl;
|
||||||
|
int16_t ret1 = rtcEngine_->registerSoundLevelListener(mrtc::TYPE_AUDIO_SOURCE_CUSTOM, consumerInfo.roomId,
|
||||||
|
peerId, consumerInfo.channelIndex, this);
|
||||||
|
if (0 != ret1) {
|
||||||
|
std::cout << "RTCContext::instance().registerSoundLevelListener() inUser failed, ret:" << ret1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cout << "muteAudio" << std::endl;
|
||||||
|
int16_t ret2 = rtcEngine_->muteAudio(consumerInfo.roomId, peerId, mrtc::TYPE_AUDIO_SOURCE_CUSTOM,
|
||||||
|
false, consumerInfo.channelIndex);
|
||||||
|
if (0 != ret2) {
|
||||||
|
std::cout << "RTCContext::instance().muteAudio() failed, ret:" << ret2;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cout << "init recv succ" << std::endl;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
void RTCContext::onRender(const char* roomId, const char* peerId,
|
void RTCContext::onRender(const char* roomId, const char* peerId,
|
||||||
RTCENGINE_NAMESPACE::MRTCVideoSourceType sourceType, const RTCENGINE_NAMESPACE::MRTCVideoFrame& videoFrame) {
|
RTCENGINE_NAMESPACE::MRTCVideoSourceType sourceType, const RTCENGINE_NAMESPACE::MRTCVideoFrame& videoFrame) {
|
||||||
|
@ -20,12 +40,11 @@ void RTCContext::onCallBackMessage(uint32_t msgId, const char* msg) {
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(mutex_);
|
std::lock_guard<std::mutex> lock(mutex_);
|
||||||
if (msgId == (uint32_t)mrtc::JOIN_MULTI_ROOM_SUCCESS) {
|
if (msgId == (uint32_t)mrtc::JOIN_MULTI_ROOM_SUCCESS) {
|
||||||
std::cout << "receive join multi room callback" << msgId;
|
std::cout << "receive join multi room callback" << msgId << std::endl;
|
||||||
isJoinMultiRoom_ = true;
|
isJoinMultiRoom_ = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::cout << "RTCContext::onCallBackMessage(), msgId:" << msgId << ", msg:" << msg;
|
std::cout << "RTCContext::onCallBackMessage(), msgId:" << msgId << ", msg:" << msg << std::endl;
|
||||||
//std::cout << "RTCContext::onCallBackMessage()" << std::endl;
|
|
||||||
}
|
}
|
||||||
void RTCContext::onCallBackCustomData(RTCENGINE_NAMESPACE::MRTCCustomDataObject object) {
|
void RTCContext::onCallBackCustomData(RTCENGINE_NAMESPACE::MRTCCustomDataObject object) {
|
||||||
//std::cout << "RTCContext::onCallBackCustomData(), obj:" << object.peerId << "," << object.data << "," << object.data_length;
|
//std::cout << "RTCContext::onCallBackCustomData(), obj:" << object.peerId << "," << object.data << "," << object.data_length;
|
||||||
|
@ -36,254 +55,24 @@ void RTCContext::onSoundLevelUpdate(const char* roomId, const char* peerId, uint
|
||||||
{
|
{
|
||||||
std::cout << "RTCContext::onSoundLevelUpdate()" << std::endl;
|
std::cout << "RTCContext::onSoundLevelUpdate()" << std::endl;
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
void RTCContext::onAudioProcess(const char* roomId, const char* peerId,
|
|
||||||
mrtc::MRTCAudioFrame& audioFrame,
|
|
||||||
mrtc::MRTCAudioSourceType audioSourceType)
|
|
||||||
{
|
|
||||||
namespace py = boost::python;
|
|
||||||
|
|
||||||
PyGILState_STATE gstate = PyGILState_Ensure();
|
|
||||||
|
|
||||||
try {
|
|
||||||
std::cout << "-----------------------------------" << std::endl;
|
|
||||||
std::cout << "dataCount:" << audioFrame.dataCount << std::endl;
|
|
||||||
std::cout << "dataCount value: " << audioFrame.dataCount
|
|
||||||
<< " (max: " << std::numeric_limits<npy_intp>::max() << ")" << std::endl;
|
|
||||||
|
|
||||||
|
|
||||||
std::cout << "onAudioProcess, numpyApi_:" << numpyApi_[93] << std::endl;
|
|
||||||
if (!numpyApi_ || !numpyApi_[93]) { // 93是PyArray_SimpleNew的偏移量
|
|
||||||
std::cout << "numpyApi_ is null in onAudioProcess" << std::endl;
|
|
||||||
} else {
|
|
||||||
std::cout << "numpyApi_ is not null in onAudioProcess:" << numpyApi_[93] << std::endl;
|
|
||||||
}
|
|
||||||
//auto numpyApi = RTCContext::numpy_api();
|
|
||||||
std::cout << "step1" << std::endl;
|
|
||||||
if (!numpyApi_) {
|
|
||||||
PyGILState_Release(gstate);
|
|
||||||
throw std::runtime_error("NumPy C-API not initialized. Call import_array() in module init");
|
|
||||||
}
|
|
||||||
std::cout << "step2" << std::endl;
|
|
||||||
|
|
||||||
using PyArray_SimpleNew_t = PyObject*(*)(int, npy_intp*, int);
|
|
||||||
|
|
||||||
void* func_ptr = numpyApi_[93];
|
|
||||||
std::cout << "Raw function pointer: " << func_ptr << std::endl;
|
|
||||||
|
|
||||||
auto ptmp = (PyObject*(*)(int, npy_intp*, int))numpyApi_[93];
|
|
||||||
std::cout << "ptmp is:" << ptmp << std::endl;
|
|
||||||
std::cout << "Pointer sizes:\n"
|
|
||||||
<< "void*: " << sizeof(void*) << "\n"
|
|
||||||
<< "FunctionPtr: " << sizeof(PyObject*(*)(int, npy_intp*, int)) << std::endl;
|
|
||||||
|
|
||||||
// 2. 使用memcpy避免编译器优化问题
|
|
||||||
PyArray_SimpleNew_t PyArray_SimpleNew;
|
|
||||||
static_assert(sizeof(func_ptr) == sizeof(PyArray_SimpleNew),
|
|
||||||
"Pointer size mismatch");
|
|
||||||
std::cout << "step3" << std::endl;
|
|
||||||
memcpy(&PyArray_SimpleNew, &func_ptr, sizeof(func_ptr));
|
|
||||||
|
|
||||||
//auto PyArray_SimpleNew = reinterpret_cast<PyArray_SimpleNew_t>(numpyApi_[93]);
|
|
||||||
std::cout << "step4, PyArray_SimpleNew:" << PyArray_SimpleNew << std::endl;
|
|
||||||
|
|
||||||
// 3. 严格校验输入数据
|
|
||||||
if (!audioFrame.data || audioFrame.dataCount <= 0) {
|
|
||||||
PyGILState_Release(gstate);
|
|
||||||
throw std::invalid_argument("Invalid audio frame data");
|
|
||||||
}
|
|
||||||
std::cout << "step5" << std::endl;
|
|
||||||
|
|
||||||
// 4. 安全创建维度数组(带边界检查)
|
|
||||||
if (audioFrame.dataCount > std::numeric_limits<npy_intp>::max()) {
|
|
||||||
PyGILState_Release(gstate);
|
|
||||||
throw std::overflow_error("Audio frame size exceeds maximum limit");
|
|
||||||
}
|
|
||||||
std::cout << "step6" << std::endl;
|
|
||||||
npy_intp dims[1] = {static_cast<npy_intp>(audioFrame.dataCount)};
|
|
||||||
|
|
||||||
std::cout << "step7" << std::endl;
|
|
||||||
// 5. 创建NumPy数组(带内存保护)
|
|
||||||
PyObject* pyArray = nullptr;
|
|
||||||
pyArray = PyArray_SimpleNew(1, dims, NPY_INT16);
|
|
||||||
std::cout << "step8" << std::endl;
|
|
||||||
if (!pyArray) {
|
|
||||||
PyGILState_Release(gstate);
|
|
||||||
throw std::bad_alloc();
|
|
||||||
}
|
|
||||||
std::cout << "step9" << std::endl;
|
|
||||||
|
|
||||||
// 6. 安全拷贝数据(带对齐检查)
|
|
||||||
if (reinterpret_cast<uintptr_t>(audioFrame.data) % alignof(int16_t) != 0) {
|
|
||||||
Py_DECREF(pyArray);
|
|
||||||
PyGILState_Release(gstate);
|
|
||||||
throw std::runtime_error("Unaligned audio data pointer");
|
|
||||||
}
|
|
||||||
std::cout << "step10" << std::endl;
|
|
||||||
std::memcpy(PyArray_DATA(reinterpret_cast<PyArrayObject*>(pyArray)),
|
|
||||||
audioFrame.data,
|
|
||||||
audioFrame.dataCount * sizeof(int16_t));
|
|
||||||
|
|
||||||
std::cout << "step11" << std::endl;
|
|
||||||
// 7. 执行回调(带引用计数保护)
|
|
||||||
if (!pyCallback_.is_none()) {
|
|
||||||
try {
|
|
||||||
pyCallback_(
|
|
||||||
py::handle<>(pyArray), // 自动管理引用
|
|
||||||
audioFrame.dataCount,
|
|
||||||
audioFrame.sampleRate,
|
|
||||||
audioFrame.numChannels,
|
|
||||||
audioFrame.channelIndex
|
|
||||||
);
|
|
||||||
} catch (...) {
|
|
||||||
Py_DECREF(pyArray);
|
|
||||||
throw; // 重新抛出异常
|
|
||||||
}
|
|
||||||
}
|
|
||||||
std::cout << "step12" << std::endl;
|
|
||||||
|
|
||||||
// 8. 释放资源
|
|
||||||
Py_DECREF(pyArray);
|
|
||||||
std::cout << "step13" << std::endl;
|
|
||||||
PyGILState_Release(gstate);
|
|
||||||
std::cout << "step14" << std::endl;
|
|
||||||
|
|
||||||
} catch (const std::exception& e) {
|
|
||||||
std::cerr << "Audio process error: " << e.what() << std::endl;
|
|
||||||
PyErr_Print();
|
|
||||||
}
|
|
||||||
exit(0);
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
/*
|
|
||||||
void RTCContext::onAudioProcess(const char* roomId, const char* peerId,
|
void RTCContext::onAudioProcess(const char* roomId, const char* peerId,
|
||||||
mrtc::MRTCAudioFrame& audioFrame,
|
mrtc::MRTCAudioFrame& audioFrame,
|
||||||
mrtc::MRTCAudioSourceType audioSourceType)
|
mrtc::MRTCAudioSourceType audioSourceType)
|
||||||
{
|
{
|
||||||
|
namespace np = boost::python::numpy;
|
||||||
namespace py = boost::python;
|
namespace py = boost::python;
|
||||||
|
Py_Initialize(); // 初始化 Python
|
||||||
|
np::initialize();
|
||||||
std::cout << "=== 开始音频处理 ===" << std::endl;
|
std::cout << "=== 开始音频处理 ===" << std::endl;
|
||||||
|
|
||||||
// 1. 获取GIL
|
|
||||||
std::cout << "[1] 获取GIL锁..." << std::endl;
|
|
||||||
PyGILState_STATE gstate = PyGILState_Ensure();
|
|
||||||
|
|
||||||
try {
|
|
||||||
// 2. 输入参数校验
|
|
||||||
std::cout << "[2] 检查输入参数..." << std::endl;
|
|
||||||
std::cout << " dataCount: " << audioFrame.dataCount
|
|
||||||
<< " (max: " << std::numeric_limits<npy_intp>::max() << ")" << std::endl;
|
|
||||||
|
|
||||||
if (!audioFrame.data || audioFrame.dataCount <= 0) {
|
|
||||||
std::cout << "[ERROR] 无效音频数据指针或长度" << std::endl;
|
|
||||||
throw std::invalid_argument("Invalid audio frame data");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (audioFrame.dataCount > std::numeric_limits<npy_intp>::max()) {
|
|
||||||
std::cout << "[ERROR] 数据长度超过最大值" << std::endl;
|
|
||||||
throw std::overflow_error("Audio frame size exceeds maximum limit");
|
|
||||||
}
|
|
||||||
|
|
||||||
// 3. 准备数组维度
|
|
||||||
std::cout << "[3] 准备数组维度..." << std::endl;
|
|
||||||
npy_intp dims[1] = {static_cast<npy_intp>(audioFrame.dataCount)};
|
|
||||||
std::cout << " 维度设置完成: [" << dims[0] << "]" << std::endl;
|
|
||||||
|
|
||||||
// 4. 检查NumPy API状态
|
|
||||||
std::cout << "[4] 检查NumPy API状态..." << std::endl;
|
|
||||||
std::cout << " numpyApi_ 地址: " << numpyApi_ << std::endl;
|
|
||||||
if (!numpyApi_) {
|
|
||||||
throw std::runtime_error("NumPy C-API not initialized");
|
|
||||||
}
|
|
||||||
|
|
||||||
// 5. 获取PyArray_SimpleNew函数
|
|
||||||
std::cout << "[5] 获取PyArray_SimpleNew函数..." << std::endl;
|
|
||||||
using PyArray_SimpleNew_t = PyObject*(*)(int, npy_intp*, int);
|
|
||||||
PyArray_SimpleNew_t PyArray_SimpleNew =
|
|
||||||
reinterpret_cast<PyArray_SimpleNew_t>(numpyApi_[93]);
|
|
||||||
std::cout << " 函数地址: " << (void*)PyArray_SimpleNew << std::endl;
|
|
||||||
|
|
||||||
std::cout << "[5.1] 验证函数指针..." << std::endl;
|
|
||||||
void* func_ptr = numpyApi_[93];
|
|
||||||
if (reinterpret_cast<uintptr_t>(func_ptr) < 0x1000) { // 检查是否为合法地址
|
|
||||||
std::cerr << "非法函数指针: " << func_ptr << std::endl;
|
|
||||||
throw std::runtime_error("Invalid PyArray_SimpleNew pointer");
|
|
||||||
}
|
|
||||||
// 6. 创建NumPy数组
|
|
||||||
std::cout << "[6] 创建NumPy数组..." << std::endl;
|
|
||||||
PyObject* pyArray = PyArray_SimpleNew(1, dims, NPY_INT16);
|
|
||||||
std::cout << " 数组地址: " << pyArray << std::endl;
|
|
||||||
|
|
||||||
if (!pyArray) {
|
|
||||||
throw std::bad_alloc();
|
|
||||||
}
|
|
||||||
|
|
||||||
// 7. 检查内存对齐
|
|
||||||
std::cout << "[7] 检查内存对齐..." << std::endl;
|
|
||||||
std::cout << " 音频数据地址: " << (void*)audioFrame.data
|
|
||||||
<< " 对齐要求: " << alignof(int16_t) << std::endl;
|
|
||||||
|
|
||||||
if (reinterpret_cast<uintptr_t>(audioFrame.data) % alignof(int16_t) != 0) {
|
|
||||||
Py_DECREF(pyArray);
|
|
||||||
throw std::runtime_error("Unaligned audio data pointer");
|
|
||||||
}
|
|
||||||
|
|
||||||
// 8. 拷贝数据
|
|
||||||
std::cout << "[8] 拷贝音频数据..." << std::endl;
|
|
||||||
std::cout << " 目标地址: " << PyArray_DATA((PyArrayObject*)pyArray)
|
|
||||||
<< " 字节数: " << audioFrame.dataCount * sizeof(int16_t) << std::endl;
|
|
||||||
|
|
||||||
std::memcpy(PyArray_DATA((PyArrayObject*)pyArray),
|
|
||||||
audioFrame.data,
|
|
||||||
audioFrame.dataCount * sizeof(int16_t));
|
|
||||||
|
|
||||||
// 9. 执行回调
|
|
||||||
if (!pyCallback_.is_none()) {
|
|
||||||
std::cout << "[9] 准备执行Python回调..." << std::endl;
|
|
||||||
try {
|
|
||||||
pyCallback_(
|
|
||||||
py::handle<>(pyArray),
|
|
||||||
audioFrame.dataCount,
|
|
||||||
audioFrame.sampleRate,
|
|
||||||
audioFrame.numChannels,
|
|
||||||
audioFrame.channelIndex
|
|
||||||
);
|
|
||||||
std::cout << " 回调执行成功" << std::endl;
|
|
||||||
} catch (...) {
|
|
||||||
std::cout << "[ERROR] 回调执行失败" << std::endl;
|
|
||||||
Py_DECREF(pyArray);
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
std::cout << "[9] 无回调函数设置" << std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 10. 释放资源
|
|
||||||
std::cout << "[10] 释放资源..." << std::endl;
|
|
||||||
Py_DECREF(pyArray);
|
|
||||||
std::cout << "[11] 释放GIL..." << std::endl;
|
|
||||||
PyGILState_Release(gstate);
|
|
||||||
std::cout << "=== 音频处理完成 ===" << std::endl;
|
|
||||||
|
|
||||||
} catch (const std::exception& e) {
|
|
||||||
std::cout << "[EXCEPTION] 异常捕获: " << e.what() << std::endl;
|
|
||||||
PyGILState_Release(gstate);
|
|
||||||
PyErr_Print();
|
|
||||||
std::cerr << "Audio process error: " << e.what() << std::endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
void RTCContext::onAudioProcess(const char* roomId, const char* peerId,
|
|
||||||
mrtc::MRTCAudioFrame& audioFrame,
|
|
||||||
mrtc::MRTCAudioSourceType audioSourceType)
|
|
||||||
{
|
|
||||||
namespace py = boost::python;
|
|
||||||
std::cout << "=== 开始音频处理(共享内存版) ===" << std::endl;
|
|
||||||
std::cout << "audioFrame:" << audioFrame.dataCount << "," << audioFrame.sampleRate << "," <<
|
std::cout << "audioFrame:" << audioFrame.dataCount << "," << audioFrame.sampleRate << "," <<
|
||||||
audioFrame.numChannels << "," << audioFrame.channelIndex << std::endl;
|
audioFrame.numChannels << "," << audioFrame.channelIndex << std::endl;
|
||||||
|
|
||||||
// 1. 获取GIL
|
// 1. 获取GIL
|
||||||
std::cout << "[1] 获取GIL锁..." << std::endl;
|
std::cout << "[1] 获取GIL锁..." << std::endl;
|
||||||
|
#ifdef GIL
|
||||||
PyGILState_STATE gstate = PyGILState_Ensure();
|
PyGILState_STATE gstate = PyGILState_Ensure();
|
||||||
|
#endif
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// 2. 输入参数校验
|
// 2. 输入参数校验
|
||||||
|
@ -298,79 +87,51 @@ void RTCContext::onAudioProcess(const char* roomId, const char* peerId,
|
||||||
|
|
||||||
const size_t data_size = audioFrame.dataCount * sizeof(int16_t);
|
const size_t data_size = audioFrame.dataCount * sizeof(int16_t);
|
||||||
|
|
||||||
// 3. 创建共享内存
|
std::cout << "step1" << std::endl;
|
||||||
std::cout << "[3] 创建共享内存..." << std::endl;
|
|
||||||
char shm_name[32];
|
|
||||||
snprintf(shm_name, sizeof(shm_name), "/audio_shm_%d", getpid());
|
|
||||||
|
|
||||||
int fd = shm_open(shm_name, O_CREAT | O_RDWR, 0666);
|
|
||||||
if (fd == -1) {
|
|
||||||
std::cout << "[ERROR] shm_open失败: " << strerror(errno) << std::endl;
|
|
||||||
throw std::runtime_error("Failed to create shared memory");
|
|
||||||
}
|
|
||||||
std::cout << " 共享内存fd: " << fd << " 名称: " << shm_name << std::endl;
|
|
||||||
|
|
||||||
// 4. 设置共享内存大小
|
|
||||||
std::cout << "[4] 设置共享内存大小..." << std::endl;
|
|
||||||
if (ftruncate(fd, data_size) == -1) {
|
|
||||||
close(fd);
|
|
||||||
std::cout << "[ERROR] ftruncate失败: " << strerror(errno) << std::endl;
|
|
||||||
throw std::runtime_error("Failed to resize shared memory");
|
|
||||||
}
|
|
||||||
std::cout << " 内存大小: " << data_size << " bytes" << std::endl;
|
|
||||||
|
|
||||||
// 5. 内存映射
|
|
||||||
std::cout << "[5] 内存映射..." << std::endl;
|
|
||||||
void* ptr = mmap(NULL, data_size, PROT_WRITE, MAP_SHARED, fd, 0);
|
|
||||||
if (ptr == MAP_FAILED) {
|
|
||||||
close(fd);
|
|
||||||
std::cout << "[ERROR] mmap失败: " << strerror(errno) << std::endl;
|
|
||||||
throw std::runtime_error("Failed to map shared memory");
|
|
||||||
}
|
|
||||||
std::cout << " 映射地址: " << ptr << std::endl;
|
|
||||||
|
|
||||||
namespace py = boost::python;
|
namespace py = boost::python;
|
||||||
namespace np = boost::python::numpy;
|
namespace np = boost::python::numpy;
|
||||||
// 6. 拷贝数据到共享内存
|
|
||||||
std::cout << "[6] 拷贝音频数据到共享内存..." << std::endl;
|
|
||||||
memcpy(ptr, audioFrame.data, data_size);
|
|
||||||
std::cout << "step1" << std::endl;
|
|
||||||
npy_intp shape[1] = { static_cast<npy_intp>(audioFrame.dataCount) };
|
npy_intp shape[1] = { static_cast<npy_intp>(audioFrame.dataCount) };
|
||||||
std::cout << "step2" << std::endl;
|
std::cout << "step2" << std::endl;
|
||||||
np::dtype dtype = np::dtype::get_builtin<int16_t>();
|
|
||||||
std::cout << "step3" << std::endl;
|
|
||||||
np::ndarray audioArray = np::from_data(
|
|
||||||
audioFrame.data, // 数据指针
|
|
||||||
dtype, // 数据类型 (int16)
|
|
||||||
py::make_tuple(shape[0]), // 形状 (1D)
|
|
||||||
py::make_tuple(sizeof(int16_t)), // 步长
|
|
||||||
py::object() // 所有者(Python管理)
|
|
||||||
);
|
|
||||||
std::cout << " 数据拷贝完成" << std::endl;
|
|
||||||
|
|
||||||
// 7. 执行回调
|
// 7. 执行回调
|
||||||
if (!pyCallback_.is_none()) {
|
if (!pyCallback_.is_none()) {
|
||||||
std::cout << "[7] 准备执行Python回调..." << std::endl;
|
std::cout << "[7] 准备执行Python回调..." << std::endl;
|
||||||
// 增加引用计数防止提前释放
|
// 增加引用计数防止提前释放
|
||||||
Py_INCREF(pyCallback_.ptr());
|
//Py_INCREF(pyCallback_.ptr());
|
||||||
try {
|
try {
|
||||||
std::cout << " pyCallback_ type: " << Py_TYPE(pyCallback_.ptr())->tp_name << std::endl;
|
|
||||||
PyObject* repr = PyObject_Repr(pyCallback_.ptr());
|
//PyGILState_STATE gstate = PyGILState_Ensure();
|
||||||
if (repr) {
|
std::cout << "data:" << audioFrame.data << std::endl;
|
||||||
std::cout << " pyCallback_ repr: " << PyUnicode_AsUTF8(repr) << std::endl;
|
std::cout << "当前线程是否持有 GIL: " << PyGILState_Check() << std::endl;
|
||||||
Py_DECREF(repr); // 必须手动释放
|
np::dtype dtype = np::dtype::get_builtin<int16_t>();
|
||||||
|
std::cout << "init dtype" << std::endl;
|
||||||
|
if (!Py_IsInitialized()) {
|
||||||
|
std::cerr << "Python 解释器未初始化!" << std::endl;
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
/*
|
try {
|
||||||
// 传递共享内存信息
|
py::object str_repr = py::str(dtype);
|
||||||
pyCallback_(
|
std::cout << "str_repr" << std::endl;
|
||||||
py::str(shm_name), // 共享内存名称
|
if(str_repr.ptr() != Py_None) {
|
||||||
data_size, // 数据大小
|
std::cout << "str_repr is not null" << std::endl;
|
||||||
audioFrame.dataCount,
|
std::string dtype_str = py::extract<std::string>(str_repr);
|
||||||
audioFrame.sampleRate,
|
std::cout << "数据类型: " << dtype_str << std::endl;
|
||||||
audioFrame.numChannels,
|
} else {
|
||||||
audioFrame.channelIndex
|
std::cout << "数据类型: None" << std::endl;
|
||||||
|
}
|
||||||
|
} catch (const py::error_already_set&) {
|
||||||
|
std::cout<< "数据类型转换错误" << std::endl;
|
||||||
|
PyErr_Clear();
|
||||||
|
}
|
||||||
|
std::cout << "数据形状: " << shape[0] << std::endl;
|
||||||
|
np::ndarray audioArray = np::from_data(
|
||||||
|
audioFrame.data, // 数据指针
|
||||||
|
dtype, // 数据类型 (int16)
|
||||||
|
py::make_tuple(shape[0]), // 形状 (1D)
|
||||||
|
py::make_tuple(sizeof(int16_t)), // 步长
|
||||||
|
py::object() // 所有者(Python管理)
|
||||||
);
|
);
|
||||||
*/
|
std::cout << " 数据拷贝完成" << std::endl;
|
||||||
pyCallback_(
|
pyCallback_(
|
||||||
audioArray, // numpy 数组
|
audioArray, // numpy 数组
|
||||||
data_size, // 数据大小
|
data_size, // 数据大小
|
||||||
|
@ -409,35 +170,37 @@ void RTCContext::onAudioProcess(const char* roomId, const char* peerId,
|
||||||
<< PyUnicode_AsUTF8(PyObject_Str(value)) << std::endl;
|
<< PyUnicode_AsUTF8(PyObject_Str(value)) << std::endl;
|
||||||
PyErr_Restore(type, value, traceback);
|
PyErr_Restore(type, value, traceback);
|
||||||
}
|
}
|
||||||
Py_DECREF(pyCallback_.ptr());
|
//Py_DECREF(pyCallback_.ptr());
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
std::cout << "[ERROR] 回调执行失败" << std::endl;
|
std::cout << "[ERROR] 回调执行失败" << std::endl;
|
||||||
munmap(ptr, data_size);
|
|
||||||
close(fd);
|
//Py_DECREF(pyCallback_.ptr());
|
||||||
shm_unlink(shm_name);
|
|
||||||
Py_DECREF(pyCallback_.ptr());
|
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
Py_DECREF(pyCallback_.ptr());
|
//Py_DECREF(pyCallback_.ptr());
|
||||||
} else {
|
} else {
|
||||||
std::cout << "[7] 无回调函数设置" << std::endl;
|
std::cout << "[7] 无回调函数设置" << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 8. 释放资源
|
// 8. 释放资源
|
||||||
std::cout << "[8] 释放共享内存资源..." << std::endl;
|
std::cout << "[8] 释放共享内存资源..." << std::endl;
|
||||||
munmap(ptr, data_size);
|
|
||||||
close(fd);
|
|
||||||
shm_unlink(shm_name);
|
|
||||||
|
|
||||||
std::cout << "[9] 释放GIL..." << std::endl;
|
std::cout << "[9] 释放GIL..." << std::endl;
|
||||||
|
#ifdef GIL
|
||||||
PyGILState_Release(gstate);
|
PyGILState_Release(gstate);
|
||||||
|
#endif
|
||||||
std::cout << "=== 音频处理完成 ===" << std::endl;
|
std::cout << "=== 音频处理完成 ===" << std::endl;
|
||||||
|
|
||||||
} catch (const std::exception& e) {
|
} catch (const std::exception& e) {
|
||||||
std::cout << "[EXCEPTION] 异常捕获: " << e.what() << std::endl;
|
std::cout << "[EXCEPTION] 异常捕获: " << e.what() << std::endl;
|
||||||
|
#ifdef GIL
|
||||||
PyGILState_Release(gstate);
|
PyGILState_Release(gstate);
|
||||||
|
#endif
|
||||||
std::cerr << "Audio process error: " << e.what() << std::endl;
|
std::cerr << "Audio process error: " << e.what() << std::endl;
|
||||||
}
|
}
|
||||||
|
#ifdef GIL
|
||||||
|
PyGILState_Release(gstate);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void RTCContext::onProducer(uint32_t msgId, mrtc::MRTCProducerInfo& info)
|
void RTCContext::onProducer(uint32_t msgId, mrtc::MRTCProducerInfo& info)
|
||||||
|
@ -498,48 +261,20 @@ bool RTCContext::init(const char* selfUserId, const char* selfDisplayName, const
|
||||||
std::cout << "RTCContext::instance().registerListener() failed" << std::endl;
|
std::cout << "RTCContext::instance().registerListener() failed" << std::endl;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
namespace py = boost::python;
|
//namespace py = boost::python;
|
||||||
namespace np = boost::python::numpy;
|
//namespace np = boost::python::numpy;
|
||||||
Py_Initialize(); // 初始化 Python
|
//Py_Initialize(); // 初始化 Python
|
||||||
np::initialize();
|
//np::initialize();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
bool RTCContext::initRecv(const char* destRoomId, const char* srcUserId, const int16_t destChannelIndex)
|
bool RTCContext::initRecv(const char* destRoomId, const char* srcUserId, const int16_t destChannelIndex)
|
||||||
{
|
{
|
||||||
std::cout << "initRecv, numpyApi_:" << numpyApi_[93] << std::endl;
|
isRecv_ = true;
|
||||||
if (!numpyApi_ || !numpyApi_[93]) { // 93是PyArray_SimpleNew的偏移量
|
|
||||||
std::cout << "numpyApi_ is null in initRecv" << std::endl;
|
|
||||||
} else {
|
|
||||||
std::cout << "numpyApi_ is not null in initRecv" << std::endl;
|
|
||||||
}
|
|
||||||
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;
|
return true;
|
||||||
|
|
||||||
}
|
}
|
||||||
bool RTCContext::initSend(const char* srcRoomId, const char* destRoomId, const int16_t destChannelIndex)
|
bool RTCContext::initSend(const char* srcRoomId, const char* destRoomId, const int16_t destChannelIndex, uint8_t channelNum)
|
||||||
{
|
{
|
||||||
while (!isOnRoom_)
|
while (!isOnRoom_)
|
||||||
{
|
{
|
||||||
|
@ -560,6 +295,7 @@ bool RTCContext::initSend(const char* srcRoomId, const char* destRoomId, const i
|
||||||
}
|
}
|
||||||
|
|
||||||
mrtc::MRTCAudioOption option;
|
mrtc::MRTCAudioOption option;
|
||||||
|
option.channel = channelNum;
|
||||||
if (std::string(srcRoomId) != std::string(destRoomId)) {
|
if (std::string(srcRoomId) != std::string(destRoomId)) {
|
||||||
strcpy(option.dstRoomId, destRoomId);
|
strcpy(option.dstRoomId, destRoomId);
|
||||||
}
|
}
|
||||||
|
@ -574,12 +310,16 @@ bool RTCContext::initSend(const char* srcRoomId, const char* destRoomId, const i
|
||||||
std::cout << "init send succ" << std::endl;
|
std::cout << "init send succ" << std::endl;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
bool RTCContext::initGIL() {
|
||||||
|
isGIL_ = true;
|
||||||
|
}
|
||||||
|
|
||||||
void RTCContext::destorySend(const int16_t selfChannelIndex)
|
void RTCContext::destorySend(const int16_t selfChannelIndex)
|
||||||
{
|
{
|
||||||
rtcEngine_->stopCustomAudio(selfChannelIndex);
|
rtcEngine_->stopCustomAudio(selfChannelIndex);
|
||||||
}
|
}
|
||||||
int16_t RTCContext::sendAudioData(uint8_t channelIndex, const void* pData, int32_t nSampleRate, uint64_t nNumberOfChannels, uint64_t dataLength)
|
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_);
|
std::lock_guard<std::mutex> lock(mutex_);
|
||||||
if (pData_)
|
if (pData_)
|
||||||
|
@ -601,7 +341,8 @@ int16_t RTCContext::sendCustomAudioData(const int16_t channelIndex, void* custom
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
std::cout << "customData addr is:" << customData << std::endl;
|
std::cout << "customData addr is:" << customData << std::endl;
|
||||||
return rtcEngine_->sendCustomAudioData(channelIndex, customData, sampleRate, channelNum, dataLen);
|
return rtcEngine_->sendCustomAudioData(channelIndex, customData, sampleRate,
|
||||||
|
channelNum, dataLen);
|
||||||
}
|
}
|
||||||
mrtc::IMRTCEngine* RTCContext::getRtcEngine() const
|
mrtc::IMRTCEngine* RTCContext::getRtcEngine() const
|
||||||
{
|
{
|
||||||
|
|
|
@ -84,7 +84,8 @@ public:
|
||||||
mrtc::IMRTCEngine* getRtcEngine() const;
|
mrtc::IMRTCEngine* getRtcEngine() const;
|
||||||
bool init(const char* selfUserId, const char* selfDisplayName, const char* selfRoomId);
|
bool init(const char* selfUserId, const char* selfDisplayName, const char* selfRoomId);
|
||||||
bool initRecv(const char* destRoomId, const char* srcUserId, const int16_t destChannelIndex);
|
bool initRecv(const char* destRoomId, const char* srcUserId, const int16_t destChannelIndex);
|
||||||
bool initSend(const char* srcRoomId, const char* destRoomId, const int16_t destChannelIndex);
|
bool initSend(const char* srcRoomId, const char* destRoomId, const int16_t destChannelIndex, uint8_t channelNum);
|
||||||
|
bool initGIL();
|
||||||
|
|
||||||
void* getpData() const;
|
void* getpData() const;
|
||||||
void setpData(void* pData);
|
void setpData(void* pData);
|
||||||
|
@ -104,9 +105,10 @@ private:
|
||||||
mrtc::IMRTCEngine * rtcEngine_ = nullptr;
|
mrtc::IMRTCEngine * rtcEngine_ = nullptr;
|
||||||
void* pData_ = nullptr;
|
void* pData_ = nullptr;
|
||||||
bool isOnRoom_ = false;
|
bool isOnRoom_ = false;
|
||||||
bool isOnConsumer_ = false;
|
bool isRecv_ = false;
|
||||||
bool isJoinMultiRoom_ = false;
|
bool isJoinMultiRoom_ = false;
|
||||||
bool isMultiRoom_ = false;
|
bool isMultiRoom_ = false;
|
||||||
|
bool isGIL_ = false;
|
||||||
boost::python::object pyCallback_;
|
boost::python::object pyCallback_;
|
||||||
void ** numpyApi_;
|
void ** numpyApi_;
|
||||||
void onRoom(uint32_t typeId, RTCENGINE_NAMESPACE::MRTCRoomInfo& roomInfo);
|
void onRoom(uint32_t typeId, RTCENGINE_NAMESPACE::MRTCRoomInfo& roomInfo);
|
||||||
|
|
Loading…
Reference in New Issue