rtc_plugins/util/RTCContext.cpp

315 lines
12 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.

#include "RTCContext.h"
#include <fstream>
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()" << std::endl;
std::cout << "RTCContext::onConsumer():msgId:" << msgId << ", roomId:" << consumerInfo.roomId << ", displayName:"
<< consumerInfo.displayName << ", type:" << consumerInfo.audioSourceType << ", channelIndex:" << (int)consumerInfo.channelIndex
<< std::endl;
if (msgId == RTCENGINE_NAMESPACE::MRTCConsumerStatusType::TYPE_STATUS_CONSUMER_START && std::string(consumerInfo.kind) == "audio") {
std::lock_guard <std::mutex> lock(mutex_);
isOnConsumer_ = true;
std::cout << "registerSoundLevelListener" << std::endl;
int16_t ret1 = rtcEngine_->registerSoundLevelListener(consumerInfo.audioSourceType, 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(roomId, peerId, consumerInfo.audioSourceType,
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,
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 << std::endl;
isJoinMultiRoom_ = true;
}
std::cout << "RTCContext::onCallBackMessage(), msgId:" << msgId << ", msg:" << msg << std::endl;
//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;
}
void printTimestamp() {
// 获取系统当前时间点
auto now = std::chrono::system_clock::now();
// 转换为时间戳(秒 + 毫秒)
auto timestamp = std::chrono::duration_cast<std::chrono::seconds>(
now.time_since_epoch()).count();
auto milliseconds = std::chrono::duration_cast<std::chrono::milliseconds>(
now.time_since_epoch()).count() % 1000;
// 转换为本地时间(可读格式)
std::time_t time = std::chrono::system_clock::to_time_t(now);
std::cout << "Timestamp: " << timestamp << "." << milliseconds << std::endl;
}
void RTCContext::onAudioProcess(const char* roomId, const char* peerId,
mrtc::MRTCAudioFrame& audioFrame,
mrtc::MRTCAudioSourceType audioSourceType)
{
//std::cout << "onAudioProcess, roomId:" << roomId << ", peerId:" << peerId << ", type:" << audioSourceType
// << ", datacount:" << audioFrame.dataCount << std::endl;
if (audioFrame.data == nullptr || audioFrame.dataCount <= 0) {
return;
}
// 以二进制追加模式打开文件
//std::ofstream outFile("audio_data.pcm", std::ios::binary | std::ios::app);
//if (!outFile.is_open()) {
// std::cerr << "Failed to open file for writing!" << std::endl;
// return;
//}
//// 写入数据int16_t格式
//outFile.write(reinterpret_cast<const char*>(audioFrame.data),
// audioFrame.dataCount);
setData(audioFrame);
}
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)
{
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)
{
while (!isOnConsumer_)
{
std::cout << "wait for OnConsumer" << std::endl;
sleep(3);
}
return true;
}
bool RTCContext::initSend(const char* srcRoomId, const char* destRoomId, const int16_t destChannelIndex,
const uint8_t channelNum)
{
while (!isOnRoom_)
{
std::cout << "wait for OnRoom" << std::endl;
sleep(3);
}
if (std::string(srcRoomId) != std::string(destRoomId)) {
isMultiRoom_ = true;
std::cout << "join multi room" << std::endl;
int16_t ret1 = rtcEngine_->joinMultiRoom(destRoomId);
if (ret1 != 0)
{
std::cout << "joinMultiRoom fail, ret:" << ret1;
return false;
}
} else {
isMultiRoom_ = false;
}
mrtc::MRTCAudioOption option;
if (std::string(srcRoomId) != std::string(destRoomId)) {
strcpy(option.dstRoomId, destRoomId);
}
option.channelIndex = destChannelIndex;
option.channel = channelNum;
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_ || (isMultiRoom_ && !isJoinMultiRoom_)) {
std::cout << "wait for room and multi room before send" << std::endl;
sleep(3);
}
std::lock_guard<std::mutex> lock(mutex_);
if (customData == nullptr) {
std::cout << "customData is null" << std::endl;
return -1;
}
std::cout << "customData addr is:" << customData << std::endl;
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::setData(const mrtc::MRTCAudioFrame& frame) {
std::lock_guard<std::mutex> lock(dataMutex_);
if (dataSize_ == totalSize_) {
bottom_ = (bottom_ + 1) % totalSize_;
dataSize_--;
}
RetAudioFrame newFrame;
newFrame.dataCount = frame.dataCount;
newFrame.sampleRate = frame.sampleRate;
newFrame.numChannels = frame.numChannels;
newFrame.channelIndex = frame.channelIndex;
newFrame.data = std::make_unique<int16_t[]>(frame.dataCount);
//std::memcpy(newFrame.data.get(), frame.data, frame.dataCount* sizeof(int16_t));
std::memcpy(newFrame.data.get(), frame.data, frame.dataCount);
data_[head_] = std::move(newFrame);
head_ = (head_ + 1) % totalSize_;
dataSize_++;
}
RetAudioFrame RTCContext::getData() {
//std::lock_guard<std::mutex> lock(dataMutex_);
if (dataSize_ > 0) {
RetAudioFrame frame = std::move(data_[bottom_]); // 移动而非拷贝
bottom_ = (bottom_ + 1) % totalSize_;
dataSize_--;
return frame; // 返回值优化(RVO)会生效
}
return {}; // 返回空对象
}
py::array_t<int16_t> RTCContext::getNumpyData() {
std::cout << "step1" << std::endl;
std::lock_guard<std::mutex> lock(dataMutex_);
RetAudioFrame frame = getData();
std::cout << "step2" << std::endl;
int16_t* dataPtr = frame.data.get(); // 你的数据指针
std::cout << "step3" << std::endl;
size_t length = frame.dataCount; // 数据长度
std::cout << "step4" << std::endl;
if (!dataPtr || length == 0) {
return py::array_t<int16_t>({0}); // 返回空数组
}
// 直接构造 pybind11 的 NumPy 数组(自动管理内存)
py::array_t<int16_t> result({static_cast<py::ssize_t>(length)});
auto buf = result.mutable_unchecked();
for (size_t i = 0; i < length; i++) {
buf[i] = dataPtr[i];
}
return result;
}
py::list RTCContext::getListData() {
std::lock_guard<std::mutex> lock(dataMutex_);
RetAudioFrame frame = getData();
py::list result;
if (frame.data) {
for (int i = 0; i < frame.dataCount/sizeof(int16_t); i++) {
result.append(frame.data.get()[i]);
}
}
return result;
}
int16_t RTCContext::getDataCount() {
std::lock_guard<std::mutex> lock(dataMutex_);
RetAudioFrame frame = getData();
return frame.dataCount;
}
int16_t RTCContext::getSize() {
std::lock_guard<std::mutex> lock(dataMutex_);
return dataSize_;
}