2025/06/27 16:17:14
原始视频数据
本文介绍如何对采集到的原始视频数据进行前处理和后处理。
技术原理
视频传输过程中,你可以对采集到的视频数据进行前处理和后处理,获取想要的播放效果。
对于有自行处理视频数据需求的场景,声网提供原始数据功能。你可以在将数据发送给编码器前进行前处理,对捕捉到的视频帧进行修改;也可以在将数据发送给解码器后进行后处理,对接收到的视频帧进行修改。
前提条件
在进行操作之前,请确保你已经在项目中实现了基本的实时音视频功能。详见实现音视频互动。
实现方法
参考如下步骤,在你的项目中实现原始视频数据功能:
-
加入频道前,创建一个
IVideoFrameObserver
对象,并调用registerVideoFrameObserver
方法注册视频观测器。C++// 注册或取消视频观测器
BOOL CAgoraOriginalVideoDlg::RegisterVideoFrameObserver(
BOOL bEnable, IVideoFrameObserver *videoFrameObserver) {
// 创建使用 IMediaEngine 类为 template 的 AutoPtr 实例
agora::util::AutoPtr<agora::media::IMediaEngine> mediaEngine;
// AutoPtr 实例调用 queryInterface 方法,通过 IID 获取 IMediaEngine
// 实例的指针 AutoPtr 实例会通过箭头操作符访问 IMediaEngine 实例的指针并通过
// IMediaEngine 实例调用 registerVideoFrameObserver
mediaEngine.queryInterface(m_rtcEngine, AGORA_IID_MEDIA_ENGINE);
int nRet = 0;
agora::base::AParameter apm(*m_rtcEngine);
if (mediaEngine.get() == NULL) return FALSE;
if (bEnable) {
// 注册视频观测器
nRet = mediaEngine->registerVideoFrameObserver(videoFrameObserver);
} else {
// 取消注册视频观测器
nRet = mediaEngine->registerVideoFrameObserver(nullptr);
}
return nRet == 0 ? TRUE : FALSE;
} -
通过
onCaptureVideoFrame
和onRenderVideoFrame
回调获取视频数据后,你可以根据场景需要自行进行处理。注意建议你在修改
videoFrame
中的参数时,需确保修改后的参数跟视频帧缓冲区中的视频帧实际情况保持一致,否则可能导致本地预览画面和对端的视频画面出现非预期的旋转、失真等问题。C++// 通过 onCaptureVideoFrame
// 回调获取本地摄像头采集的原始视频数据,进行灰度处理,再发送回 SDK
bool CGrayVideoProcFrameObserver::onCaptureVideoFrame(VideoFrame &videoFrame) {
int nSize = videoFrame.height * videoFrame.width;
memset(videoFrame.uBuffer, 128, nSize / 4);
memset(videoFrame.vBuffer, 128, nSize / 4);
return true;
}
// 通过 onRenderVideoFrame 回调获取获取远端发送的视频数据
bool CGrayVideoProcFrameObserver::onRenderVideoFrame(const char *channelId,
rtc::uid_t remoteUid,
VideoFrame &videoFrame) {
return true;
}
bool CAverageFilterVideoProcFrameObserver::onCaptureVideoFrame(
VideoFrame &videoFrame) {
static int step = 1;
static bool flag = true;
if (flag) {
step += 2;
} else {
step -= 2;
}
if (step >= 151) {
flag = false;
step -= 4;
} else if (step <= 0) {
flag = true;
step += 4;
}
AverageFiltering((unsigned char *)videoFrame.yBuffer, videoFrame.width,
videoFrame.height, step);
AverageFiltering((unsigned char *)videoFrame.uBuffer, videoFrame.width / 2,
videoFrame.height / 2, step);
AverageFiltering((unsigned char *)videoFrame.vBuffer, videoFrame.width / 2,
videoFrame.height / 2, step);
return true;
}
// 通过 onScreenCaptureVideoFrame 回调获取从屏幕采集到的视频数据
bool CGrayVideoProcFrameObserver::onScreenCaptureVideoFrame(
VideoFrame &videoFrame) {
return true;
}
参考信息
示例项目
声网提供了开源的示例项目供你参考,你可以前往下载或查看其中的源代码。