# 视频管理

# 视频数据采集管理

# 设置要开启的摄像头

视频采集设置前,可以通过 JCMediaDevice 类中的 getCameras (opens new window) 方法获取摄像头列表。

std::list<JCMediaDeviceCamera>* cameras = JCManager::shared()->mediaDevice->getCameras();

摄像头列表获取后,调用 switchCamera (opens new window) 方法切换指定的摄像头。

/// 切换指定摄像头
JCManager::shared()->mediaDevice->switchCamera(cameras[0]);

# 设置摄像头采集分辨率

调用 setCameraProperty (opens new window) 接口自定义摄像头采集参数,如采集的高度、宽度和帧速率,以实现不同的采集分辨率。

JCManager::shared()->mediaDevice->setCameraProperty(640, 360, 24);

# 视频数据管理

# 原始视频数据

在视频传输过程中,可以对每帧视频数据进行图像处理,以实现美颜等需求。有以下两种处理时机:

  1. 在视频采集后编码前处理;会影响本地预览和对端接收视频。

  2. 在解码后渲染前处理;影响本地接收视频。

具体如下:

视频采集后,编码前处理

参考如下步骤,在您的项目中实现原始视频数据功能:

  1. 发起业务前通过 Zmf_VideoCaptureAddCallback 注册视频采集回调,并在该函数中实现一个 ZmfVideoCaptureCallback 类型的回调函数;

  2. 成功注册后,JC SDK 会在捕捉到每个视频帧时通过回调函数回调采集到的原始视频数据相对应参数;

  3. 用户拿到视频数据后,根据场景需要自行在回调函数中进行参数处理,处理后数据通过该回调函数返回给 JC SDK。

首先注册视频采集回调,在登录成功后即可调用。

/** add capture data callback
 * @param[in] pUser     the callback user data
 * @param[in] pfnCb     the callback
 * returns 0 on succeed, otherwise failed
 */
int Zmf_VideoCaptureAddCallback (void *pUser, ZmfVideoCaptureCallback pfnCb)

回调类型说明。

/** the callback to receive captured image
 * iImgAngle - iCamOrient equal to device rotate angle.
 * if encoder is NULL, the pixel format of buf must be ZmfPixelFormatI420
 *
 * @param[in] pUser     the user data registered by Zmf_VideoCaptureAddCallback
 * @param[in] captureId the id of captured image
 * @param[in] iFace     the capture Face @see ZmfVideoFaceType
 * @param[in] iImgAngle the image rotated angle (CW)
 * @param[in] iCaptureOrient the capturer fixed orient
 * @param[in,out] iWidth  the image width
 * @param[in,out] iHeight the image height
 * @param[in,out] buf     the image data I420 buffer
 * @param[in,out] encoder capture encoder
 */
 typedef void (*ZmfVideoCaptureCallback)(void* pUser, const char* captureId, int iFace,int iImgAngle, int iCaptureOrient, int* iWidth, int* iHeight,unsigned char *buf, ZmfVideoCaptureEncoder* encoder);

示例代码

static void zmfVideoCaptureCallback(void* pUser, const char* captureId, int iFace, int iImgAngle, int iCaptureOrient, int* iWidth, int* iHeight,unsigned char *buf, ZmfVideoCaptureEncoder* encoder) {
    cout << "视频数据处理" << endl;
}
void JCSampleDlg::OnBnClickedButtonCall()
{
    //注册回调
    Zmf_VideoCaptureAddCallback(void*pUser, zmfVideoCaptureCallback);
    //发起呼叫
    ...
}

注册后,每帧采集的视频数据通过 ZmfVideoCaptureCallback 回调,可以处理对应的视频数据。

如果想移除回调,调用下面的接口。

/** remove capture data callback
  * @param[in] pUser     the callback user data
  * returns 0 on succeed, otherwise failed
  */
int Zmf_VideoCaptureRemoveCallback (void *pUser)

示例代码

void JCSampleDlg::OnBnClickedButtonEndCall()
{
    //移除回调
    Zmf_VideoCaptureRemoveCallback(p);
    //挂断通话
    ...
}

解码后,渲染前处理

参考如下步骤,在您的项目中实现原始视频数据功能:

  1. 发起业务前通过 Zmf_VideoRenderAddCallback 注册视频输出回调,并在该函数中实现一个 ZmfVideoRenderCallback 类型的回调函数

  2. 成功注册后,JC SDK 会在捕捉到每个视频帧时通过回调函数回调输出的原始视频数据相对应参数

  3. 用户拿到视频数据后,根据场景需要自行在回调函数中进行参数处理,处理后数据通过该回调函数返回给JC SDK。

首先注册视频输出回调,在登录成功后即可调用。

/**
 * add render data callback
 *
 * @param[in] pUser      the callback user data
 * @param[in] pfnCb      the callback
 *
 * @return               0 on succeed, otherwise failed.
 */
int Zmf_VideoRenderAddCallback (void *pUser, ZmfVideoRenderCallback pfnCb);

回调类型说明。

/**
 * The callback to receive video render data
 *
 * @param[in] pUser         the user data registered by Zmf_AddVideoRenderCallback
 * @param[in] renderId      video render unique name
 * @param[in] sourceType    video render source type @see ZmfVideoSourceType
 * @param[in] iAngle the image angle
 * @param[in] iMirror the image mirror type
 * @param[in] iWidth  the image width
 * @param[in] iHeight  the image height
 * @param[in] buf           I420 render data
 *
 * @return                  if process render data should return > 0, other 0
 *
 * @remarks
 *  if buf == 0 or iWidth ==0 or iHeight == 0, means the render will close,
 *  so should call Zmf_OnVideoRenderRequestRemove.
 */
 typedef int  (*ZmfVideoRenderCallback)(void* pUser, const char* renderId, int sourceType, int iAngle,int iMirror, int* iWidth, int* iHeight, unsigned char *buf,unsigned long timeStamp);

注册后,每帧解码后的视频数据通过 ZmfVideoRenderCallback 回调,可以处理对应的视频数据。

示例代码

static void zmfVideoRenderCallback(void* pUser, const char* renderId, int sourceType, int iAngle,int iMirror, int* iWidth, int* iHeight, unsigned char *buf,unsigned long timeStamp) {
   cout << "视频数据处理" << endl;
}
void JCSampleDlg::OnBnClickedButtonCall()
{
    //注册回调
    Zmf_VideoRenderAddCallback(void*pUser, zmfVideoRenderCallback);
    //发起呼叫
    ...
}

如果想移除回调,调用下面的接口。

/**
 * remove render data callback
 *
 * @param[in] pUser      the callback user data
 * @return               0 on succeed, otherwise failed.
 */
int Zmf_VideoRenderRemoveCallback (void *pUser)

示例代码

void JCSampleDlg::OnBnClickedButtonEndCall()
{
    //移除回调
    Zmf_VideoRenderRemoveCallback(p);
    //挂断通话
    ...
}

# 自定义视频输入源

在视频通话中,您可以自定义视频输入源,菊风提供将视频文件作为视频源的方案以实现该功能:

  1. 调用 startVideoFile (opens new window) 开启该功能。(调用 stopVideoFile (opens new window) 关闭该功能)
  2. 调用 setVideoFileFrame (opens new window) 逐帧添加视频数据。
  3. 进行 视频画面渲染
// 开启以视频文件作为视频源的功能
JCManager::shared()->mediaDevice->startVideoFile();
// 添加视频数据源
JCManager::shared()->mediaDevice->setVideoFileFrame(data,JCMediaDevice.I420, "width","height","angle","mirror", "keyFrame");
// 渲染画面
...

TIP

startVideoFile() 函数会自动关闭摄像头。

参数介绍

参数 描述
data 画面二进制数据
format 视频像素格式。当 format 为 H264 (opens new window) 格式并且是关键帧,则需要将 0x67 0x68 0x41 的数据作为一帧传入,并且关键帧要以固定间隔传入,例如5秒,否则一开始可能有几秒对端无法显示视频。
width
height
angle 视频旋转角度,90 的倍数
mirror 0 不镜像,1进行左右镜像
keyFrame 是否为关键帧,针对 format 为 H264 (opens new window)
- true 是关键帧
- false 不是关键帧

# 视频渲染管理

渲染管理主要使用到 JCMediaDeviceVideoCanvas 类中的接口。包括更新视频渲染标识、暂停渲染以及恢复渲染。

# 更新视频渲染标识

调用 replace (opens new window) 接口更新视频渲染标识。

JCManager::shared()->mediaDeviceCanvas->replace(videoSource);

# 暂停渲染

调用 pause (opens new window) 接口暂停画面的渲染。

JCManager::shared()->mediaDeviceCanvas->pause();

# 恢复渲染

调用 resume (opens new window) 接口恢复已暂停的视频渲染。

JCManager::shared()->mediaDeviceCanvas->resume();

# 视频设备管理

视频设备管理主要用到 JCMediaDevice 类中的方法,具体如下:

# 开启/关闭摄像头

调用 startCamera (opens new window) 接口开启摄像头。

调用 stopCamera (opens new window) 接口关闭摄像头。

//开启摄像头
JCManager::shared()->mediaDevice->startCamera();
//关闭摄像头
JCManager::shared()->mediaDevice->stopCamera();

# 获取当前使用的摄像头

调用 getCamera (opens new window) 接口获取当前使用的摄像头。

JCMediaDeviceCamera camera = JCManager::shared()->mediaDevice->getCamera();

# 获取窗口列表

调用 getWindows (opens new window) 接口获取窗口列表。

std::list<JCMediaDeviceWindow>* windows = JCManager::shared()->mediaDevice->getWindows();

# 获取桌面列表

调用 getDesktops (opens new window) 接口获取桌面列表。

std::list<JCMediaDeviceWindow>* windows = JCManager::shared()->mediaDevice->getDesktops();