rtc_plugins/rtc_plugins.cpp

195 lines
6.4 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// rtc_plugins.cpp
//#include "./util/numpyConfig.h"
#include "./util/RTCContext.h"
#define PY_ARRAY_UNIQUE_SYMBOL RTC_PLUGINS_ARRAY_API_IMPL // 内部实现专用符号
#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION
#include <numpy/arrayobject.h>
// 提供转换接口
void** get_numpy_api() {
return (void**)RTC_PLUGINS_ARRAY_API_IMPL;
}
namespace py = boost::python;
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);
bool res = RTCContext::instance().init(selfUserId, selfDisplayName, selfRoomId);
if (res) {
return 0;
} else {
return -1;
}
}
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);
if (res) {
return 0;
} else {
return -1;
}
}
int initSend(const char* destRoomId, const int16_t destChannelIndex) {
bool res = RTCContext::instance().initSend(destRoomId, destChannelIndex);
if (res) {
return 0;
} else {
return -1;
}
}
py::object create_int16_array() {
// 1. 定义数组维度1维长度为 4
npy_intp dims[1] = {4};
// 2. 创建原生 C 数组int16_t 数据)
int16_t data[4] = {1, 2, -3, 4}; // 示例数据
// 3. 通过 NumPy C API 创建 PyObject*
PyObject* py_array = PyArray_SimpleNewFromData(
1, // 维度数
dims, // 各维度大小
NPY_INT16, // 数据类型np.int16
data // 数据指针
);
if (!py_array) {
throw std::runtime_error("Failed to create NumPy array");
}
// 4. 转换为 py::object自动管理引用计数
return py::object(py::handle<>(py_array));
}
int sendCustomAudioData(int16_t destChannelIndex, py::object pD,
int32_t sampleRate, uint64_t channelNum, uint64_t dataLen) {
try {
// 强制转换为 int16 连续数组
PyObject* py_array = PyArray_FROM_OTF(
pD.ptr(),
NPY_INT16,
NPY_ARRAY_IN_ARRAY | NPY_ARRAY_FORCECAST
);
if (!py_array) {
throw std::runtime_error("Failed to convert input to int16 array");
}
// 修复点:使用花括号初始化
py::object arr{py::handle<>(py_array)};
// 检查数据长度
PyArrayObject* npArray = reinterpret_cast<PyArrayObject*>(arr.ptr());
if (PyArray_SIZE(npArray) != static_cast<npy_intp>(dataLen)) {
Py_DECREF(py_array);
throw std::runtime_error("Array length does not match dataLen");
}
// 处理数据...
void* dataPtr = PyArray_DATA(npArray);
int ret = RTCContext::instance().sendCustomAudioData(
destChannelIndex, dataPtr, sampleRate, channelNum, dataLen
);
Py_DECREF(py_array); // 释放临时数组
return ret;
} catch (...) {
PyErr_SetString(PyExc_RuntimeError, "Invalid audio data");
return -1;
}
}
/*
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() {
// 直接调用底层函数,绕过宏的问题
if (_import_array() < 0) {
PyErr_SetString(PyExc_ImportError, "numpy.core.multiarray failed to import");
throw std::runtime_error("NumPy initialization failed");
}
std::cout << "NumPy API addr: " << PyArray_API << std::endl;
}
BOOST_PYTHON_MODULE(rtc_plugins) {
try {
init_numpy();
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("initRecv", &initRecv);
py::def("initSend", &initSend);
py::def("sendCustomAudioData", &sendCustomAudioData);
} catch (...) {
PyErr_SetString(PyExc_RuntimeError, "Module initialization failed");
}
}