自定义视频渲染指的是 SDK 向外部提供本地预览及远端拉流的视频帧数据,供用户自行渲染。
当开发者业务中出现以下情况时,我们推荐使用 SDK 的自定义视频渲染功能:
请参考 下载示例源码 获取源码。
相关源码请查看 “/ZegoExpressExample/Examples/AdvancedVideoProcessing/CustomVideoRendering” 目录下的文件。
自定义视频渲染的使用流程如下:
时序图如下:
bufferType
参数是枚举 ZegoVideoBufferType ,目前 SDK 仅支持 ZEGO_VIDEO_BUFFER_TYPE_RAWDATA
类型。
frameFormatSeries
参数是枚举 ZegoVideoFrameFormatSeries ,可指定开发者需要的自定义视频渲染视频帧数据格式,此参数只能指定 RGB
或 YUV
颜色空间大类,具体的数据格式不同平台间不一致,以回调中的参数为准,本文下半部分将会提到。
若回调中的数据格式与您预期不符,请联系 ZEGO 技术支持处理。
ZegoVideoFrameFormatSeriesRGB
:返回 BGRA。ZegoVideoFrameFormatSeriesYUV
:返回 I420。enableEngineRender 表示是否在要自定义视频渲染的同时,SDK 内部也渲染。如果为 false
,则引擎不会往预览接口 startPreview 和拉流接口 startPlayingStream 设置的 canvas 上渲染。
接口原型
// 自定义视频渲染配置
struct ZegoCustomVideoRenderConfig
{
// 自定义视频渲染视频帧数据类型
ZegoVideoBufferType bufferType;
// 自定义视频渲染视频帧数据格式
ZegoVideoFrameFormatSeries frameFormatSeries;
// 是否在自定义视频渲染的同时,引擎也渲染,默认为 [false]
bool enableEngineRender;
};
/**
* 开始或停止自定义视频渲染
*
* 必须在引擎启动前设置,即在调用 [startPreview]、[startPublishing]、[startPlayingStream] 之前设置;且在引擎停止之后才能修改配置
* 当开发者开启自定义渲染时,通过调用 [setCustomVideoRenderHandler] 可设置接收本地以及远端的视频帧数据以用于自定义渲染
*
* @param enable 是否开启
* @param config 自定义渲染配置
*/
virtual void enableCustomVideoRender(bool enable, ZegoCustomVideoRenderConfig* config) = 0;
创建 ZegoCustomVideoRenderConfig 对象并配置参数后,再调用 enableCustomVideoRender 接口开启自定义视频渲染。
调用示例
ZegoCustomVideoRenderConfig renderConfig;
renderConfig.bufferType = ZEGO_VIDEO_BUFFER_TYPE_RAWDATA;
renderConfig.frameFormatSeries = ZEGO_VIDEO_FRAME_FORMAT_SERIES_RGB;
renderConfig.enableEngineRender = false;
engine->enableCustomVideoRender(true, &renderConfig);
调用 setCustomVideoRenderHandler 接口来设置自定义视频渲染回调 IZegoCustomVideoRenderHandler 。
// 继承自 IZegoCustomVideoRenderHandler,实现自定义渲染回调
class MyCustomVideoRenderHandler: public IZegoCustomVideoRenderHandler{
/**
* 本地预览视频帧裸数据回调
*
* @param data 视频帧的裸数据(例:RGBA 只需考虑 data[0],I420 需考虑 data[0,1,2])
* @param dataLength 数据的长度(例:RGBA 只需考虑 dataLength[0],I420 需考虑 dataLength[0,1,2])
* @param param 视频帧参数
* @param flipMode 视频帧翻转模式
* @param channel 推流通道
*/
virtual void onCapturedVideoFrameRawData(unsigned char** /*data*/, unsigned int* /*dataLength*/, ZegoVideoFrameParam /*param*/, ZegoVideoFlipMode /*flipMode*/, ZegoPublishChannel /*channel*/) {
}
/**
* 远端拉流视频帧裸数据回调,通过 streamID 区分不同的流
*
* @param data 视频帧的裸数据(例:RGBA 只需考虑 data[0],I420 需考虑 data[0,1,2])
* @param dataLength 数据的长度(例:RGBA 只需考虑 dataLength[0],I420 需考虑 dataLength[0,1,2])
* @param param 视频帧参数
* @param streamID 拉流的流 ID
*/
virtual void onRemoteVideoFrameRawData(unsigned char** /*data*/, unsigned int* /*dataLength*/, ZegoVideoFrameParam /*param*/, const std::string& /*streamID*/) {
}
}
// 为引擎设置自定义渲染回调
engine->setCustomVideoRenderHandler(std::make_shared<MyCustomVideoRenderHandler>());
回调方法中的 param
(ZegoVideoFrameParam 对象)描述了该视频帧的一些参数,定义如下:
struct ZegoVideoFrameParam
{
// 视频帧的格式
ZegoVideoFrameFormat format;
// 每个平面一行字节数(例:RGBA 只需考虑 strides[0],I420 需考虑 strides[0,1,2])
int strides[4];
// 视频帧的画面宽
int width;
// 视频帧的画面高
int height;
// 视频旋转角度
int rotation;
};
其中 format
标识了该视频帧的具体数据格式;strides
为数组,描述每个平面一行字节数;size
描述视频帧的画面尺寸。
strides
和图像之间的关系如图:
开启本地预览或推流后,SDK 会将采集到的本地视频通过 onCapturedVideoFrameRawData 回调给用户。
开启拉流后,SDK 会将获取的远端流的视频数据通过 onRemoteVideoFrameRawData 回调给用户。
至此,App 成功获得 SDK 回调的视频帧数据,用于实际的渲染动作或者进行深加工操作。
自定义视频渲染,分了本地采集预览自定义视频渲染和远端拉流自定义视频渲染,分别有什么作用?什么场景下使用?
答:本地采集预览自定义视频渲染是让主播看到额外的渲染效果,在原视频画面基础上加上特效等;远端拉流自定义视频渲染是让观众看到不同的渲染画面,可以根据观众的喜好,在拉流画面的基础上加上特效。
如果自定义视频渲染在配置 ZegoCustomVideoRenderConfig 里的 enableEngineRender 参数为 false
时,预览接口 startPreview 及拉流接口 startPlayingStream 中的 canvas
参数填什么?
答:当 enableEngineRender 为 false
时,引擎不渲染,因此预览和拉流接口的 canvas
参数可置空 nullptr
。
推流时使用自定义视频渲染功能,处理过的预览视频数据 buffer
只会在本地展示吗?会加入到推流当中吗?
答:只会在本地展示,不影响推流出去的视频数据。
本地采集预览自定义视频渲染的视频帧的宽高是多少?
答:本地采集预览自定义视频渲染的视频帧的宽高会在回调中的 param 参数里返回,其值与 setVideoConfig 设置的分辨率相同。
自定义视频渲染出来的视频帧数据格式是什么?
答:根据选择的渲染数据格式系列 ZegoVideoFrameFormatSeries 以及软解/硬解码后直接返回的数据决定,即视频帧回调方法中的 ZegoVideoFrameParam 参数里的 format
参数。
视频帧数据格式 ZegoVideoFrameFormat 说明:
视频帧数据格式枚举值 | 说明 |
---|---|
ZEGO_VIDEO_FRAME_FORMAT_I420 |
YUV420P;一组 YUV 12bits;Y, U, V 三个平面,四个 Y 共用一组 UV。 |
ZEGO_VIDEO_FRAME_FORMAT_NV12 |
YUV420SP;一组 YUV 12bits;Y, UV 两个平面,UV 平面数据以先 U 后 V 顺序排列,四个 Y 共用一组 UV。 |
ZEGO_VIDEO_FRAME_FORMAT_NV21 |
YUV420SP;一组 YUV 12bits;Y, UV 两个平面,UV 平面数据以先 V 后 U 顺序排列,四个 Y 共用一组 UV。 |
ZEGO_VIDEO_FRAME_FORMAT_BGRA32 |
BGRA32。 |
ZEGO_VIDEO_FRAME_FORMAT_RGBA32 |
RGBA32。 |
ZEGO_VIDEO_FRAME_FORMAT_ARGB32 |
ARGB32。 |
ZEGO_VIDEO_FRAME_FORMAT_ABGR32 |
ABGR32。 |
ZEGO_VIDEO_FRAME_FORMAT_I422 |
YUV422P; 一组 YUV 16bits;两个 Y 共用一组 UV。 |
ZEGO_VIDEO_FRAME_FORMAT_BGR24 |
BGR24。 |
ZEGO_VIDEO_FRAME_FORMAT_RGB24 |
RGB24。 |
自定义视频渲染每秒回调的频率是多少?有什么需要注意的吗?
答:本地采集预览自定义视频渲染回调的频率一般是和推流时设置的帧率相同,但是如果开启了流量控制并且控制属性中包含帧率的话,本地采集预览自定义视频渲染的回调频率是会随之改变的;而远端拉流自定义视频渲染的回调频率也是会随着接收到的视频数据帧率改变的,比如推流端开启流量控制导致帧率改变、拉流端网络卡顿、拉流端网络恢复 SDK 开始追帧,都会影响拉流自定义视频渲染的回调频率。
自定义视频渲染如何拿到第一帧数据呢?
答:自定义视频渲染回调 IZegoCustomVideoRenderHandler 的第一次返回的数据即第一帧数据。
为什么收不到本地视频数据的回调?
答:需要在推流前先启动预览 startPreview ,否则收不到视频数据的回调。
本地预览自定义视频渲染,视频帧数据的画面为什么没有默认做水平镜像翻转?
答:自定义视频渲染的视频帧画面翻转需要开发者自行实现,可通过视频帧数据回调接口中的 flipMode 获知该帧是否需要翻转。
联系我们
文档反馈