diff --git a/util/RTCContext.cpp b/util/RTCContext.cpp index 66d95d4..4d382b4 100644 --- a/util/RTCContext.cpp +++ b/util/RTCContext.cpp @@ -37,26 +37,6 @@ void RTCContext::onSoundLevelUpdate(const char* roomId, const char* peerId, uint 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; - std::cout << "-----------------------------------" << std::endl; - std::cout << "dataCount:" << audioFrame.dataCount << audioSourceType << std::endl; - if (audioFrame.data == nullptr) { - std::cout << "sudioFrame data is null" << std::endl; - } else if (!py_callback_.is_none()) { - std::cout << "python callback" << std::endl; - npy_intp dims[1] = {audioFrame.dataCount}; - std::cout << "step1" << std::endl; - PyObject* pyArray = PyArray_SimpleNewFromData(1, dims, NPY_INT16, audioFrame.data); - std::cout << "step2" << std::endl; - py_callback_(py::handle<>(pyArray), audioFrame.dataCount, audioFrame.sampleRate, audioFrame.numChannels, - audioFrame.channelIndex); - std::cout << "step3" << std::endl; - } -} -*/ void RTCContext::onAudioProcess(const char* roomId, const char* peerId, mrtc::MRTCAudioFrame& audioFrame, mrtc::MRTCAudioSourceType audioSourceType) @@ -173,6 +153,134 @@ void RTCContext::onAudioProcess(const char* roomId, const char* peerId, PyErr_Print(); } exit(0); +} + */ +void RTCContext::onAudioProcess(const char* roomId, const char* peerId, + mrtc::MRTCAudioFrame& audioFrame, + mrtc::MRTCAudioSourceType audioSourceType) +{ + namespace py = boost::python; + std::cout << "=== 开始音频处理 ===" << std::endl; + + PyGILState_STATE gstate = PyGILState_Ensure(); + std::cout << "[1] GIL 已获取" << std::endl; + + try { + // 1. 输入参数校验 + std::cout << "[2] 检查输入参数..." << std::endl; + std::cout << " dataCount: " << audioFrame.dataCount + << " (max: " << std::numeric_limits::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::max()) { + std::cout << "[ERROR] 数据长度超过最大值" << std::endl; + throw std::overflow_error("Audio frame size exceeds maximum limit"); + } + + // 2. 准备NumPy数组参数 + std::cout << "[3] 准备数组维度..." << std::endl; + npy_intp dims[1] = {static_cast(audioFrame.dataCount)}; + std::cout << " 维度设置完成: " << dims[0] << std::endl; + + // 3. 获取NumPy模块 + std::cout << "[4] 导入numpy.core.multiarray模块..." << std::endl; + PyObject* numpy_module = PyImport_ImportModule("numpy.core.multiarray"); + if (!numpy_module) { + std::cout << "[ERROR] 无法导入numpy模块" << std::endl; + throw std::runtime_error("Failed to import numpy.core"); + } + std::cout << " 模块导入成功: " << numpy_module << std::endl; + + // 4. 获取empty函数 + std::cout << "[5] 获取numpy.empty函数..." << std::endl; + PyObject* empty_func = PyObject_GetAttrString(numpy_module, "empty"); + if (!empty_func) { + Py_DECREF(numpy_module); + std::cout << "[ERROR] 无法获取empty函数" << std::endl; + throw std::runtime_error("Failed to get numpy.empty"); + } + std::cout << " 函数获取成功: " << empty_func << std::endl; + + // 5. 构建参数元组 + std::cout << "[6] 构建参数元组..." << std::endl; + PyObject* py_dims = PyTuple_New(1); + PyTuple_SetItem(py_dims, 0, PyLong_FromLong(dims[0])); + + PyObject* dtype = PyArray_DescrFromType(NPY_INT16); + PyObject* args = PyTuple_Pack(2, py_dims, dtype); + std::cout << " 参数构建完成: " << args << std::endl; + + // 6. 调用函数创建数组 + std::cout << "[7] 调用numpy.empty创建数组..." << std::endl; + PyObject* pyArray = PyObject_Call(empty_func, args, nullptr); + std::cout << " 数组创建结果: " << pyArray << std::endl; + + // 7. 清理临时对象 + std::cout << "[8] 清理临时Python对象..." << std::endl; + Py_DECREF(args); + Py_DECREF(py_dims); + Py_DECREF(dtype); + Py_DECREF(empty_func); + Py_DECREF(numpy_module); + + if (!pyArray) { + std::cout << "[ERROR] 数组创建失败" << std::endl; + throw std::bad_alloc(); + } + + // 8. 检查内存对齐 + std::cout << "[9] 检查内存对齐..." << std::endl; + if (reinterpret_cast(audioFrame.data) % alignof(int16_t) != 0) { + Py_DECREF(pyArray); + std::cout << "[ERROR] 内存未对齐" << std::endl; + throw std::runtime_error("Unaligned audio data pointer"); + } + + // 9. 拷贝音频数据 + std::cout << "[10] 拷贝音频数据到NumPy数组..." << std::endl; + std::memcpy(PyArray_DATA((PyArrayObject*)pyArray), + audioFrame.data, + audioFrame.dataCount * sizeof(int16_t)); + std::cout << " 数据拷贝完成" << std::endl; + + // 10. 执行Python回调 + if (!pyCallback_.is_none()) { + std::cout << "[11] 准备执行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 << "[11] 无回调函数设置" << std::endl; + } + + // 11. 清理资源 + std::cout << "[12] 释放Python数组资源..." << std::endl; + Py_DECREF(pyArray); + std::cout << "[13] 释放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::onProducer(uint32_t msgId, mrtc::MRTCProducerInfo& info) {