火山RTC 4 音视频引擎 IRTCVideo,及 音视频引擎事件回调接口 IRTCVideoEventHandler
一、IRTCVideo、IRTCVideoEventHandler
音视频引擎 IRTCVideo,及 音视频引擎事件回调接口 IRTCVideoEventHandler
负责音视频管理、创建房间/获得房间实例
1、创建引擎、及事件回调示例
如:
void VideoConfigWidget::initRTCVideo()
{
m_handler.reset(new ByteRTCEventHandler());
connect(m_handler.get(), &ByteRTCEventHandler::sigLocalVideoSizeChanged, this, &VideoConfigWidget::onSigLocalVideoSizeChanged);
m_video = bytertc::createRTCVideo(g_appid.c_str(), m_handler.get(), nullptr);
m_video->startAudioCapture();
m_video->startVideoCapture();
QStringList list = {"createRTCVideo", "startAudioCapture", "startVideoCapture"};
appendAPI(list);
}
这里,关注了个本地视频大小改变回调
connect(m_handler.get(), &ByteRTCEventHandler::sigLocalVideoSizeChanged, this, &VideoConfigWidget::onSigLocalVideoSizeChanged);
1)、音视频回调接口
/**
* @locale zh
* @type callback
* @brief 音视频引擎事件回调接口<br>
* 注意:回调函数是在 SDK 内部线程(非 UI 线程)同步抛出来的,请不要做耗时操作或直接操作 UI,否则可能导致 app 崩溃。
*/
/**
* @locale en
* @type callback
* @brief Audio & video engine event callback interface<br>
* Note: Callback functions are thrown synchronously in a non-UI thread within the SDK. Therefore, you must not perform any time-consuming operations or direct UI operations within the callback function, as this may cause the app to crash.
*/
class IRTCVideoEventHandler {
public:
/**
* @locale zh
* @type callback
* @region 视频管理
* @brief 本地视频大小或旋转信息发生改变时,收到此回调。
* @param index 流属性。参看 StreamIndex{@link #StreamIndex}。
* @param info 视频帧信息。参看 VideoFrameInfo{@link #VideoFrameInfo}。
*/
/**
* @locale en
* @type callback
* @region video management
* @brief Receive this callback when the local video size or rotation configuration changes.
* @param index See StreamIndex{@link #StreamIndex}。
* @param info Video frame information. See VideoFrameInfo{@link #VideoFrameInfo}.
*/
virtual void onLocalVideoSizeChanged(StreamIndex index, const VideoFrameInfo& info) {
(void)index;
(void)info;
}
2)、派生这个回调接口类
class ByteRTCEventHandler : public QObject,
public bytertc::IRTCVideoEventHandler,
public bytertc::IAudioEffectPlayerEventHandler,
public bytertc::IMixedStreamObserver,
public bytertc::IMediaPlayerEventHandler
{
Q_OBJECT
public:
struct Stru_RemoteStreamKey {
std::string room_id;
std::string user_id;
bytertc::StreamIndex stream_index;
};
explicit ByteRTCEventHandler(QObject *parent = nullptr);
~ByteRTCEventHandler();
void setIsSupportClientPushStream(bool support);
private:
//from IRTCVideoEventHandler
void onWarning(int warn) override;
void onError(int err) override;
void onConnectionStateChanged(bytertc::ConnectionState state) override;
void onNetworkTypeChanged(bytertc::NetworkType type) override;
void onAudioDeviceStateChanged(const char* device_id, bytertc::RTCAudioDeviceType device_type,
bytertc::MediaDeviceState device_state, bytertc::MediaDeviceError device_error) override;
void onVideoDeviceStateChanged(const char* device_id, bytertc::RTCVideoDeviceType device_type,
bytertc::MediaDeviceState device_state, bytertc::MediaDeviceError device_error) override;
void onAudioDeviceWarning(const char* device_id, bytertc::RTCAudioDeviceType device_type,
bytertc::MediaDeviceWarning device_warning) override;
void onVideoDeviceWarning(const char* device_id, bytertc::RTCVideoDeviceType device_type,
bytertc::MediaDeviceWarning device_warning) override;
void onSysStats(const bytertc::SysStats& stats) override;
void onLocalVideoSizeChanged(bytertc::StreamIndex index,
const bytertc::VideoFrameInfo& info) override;
3)、设置signals
signals:
void sigLocalVideoSizeChanged(bytertc::StreamIndex index,
const bytertc::VideoFrameInfo info);
4)、绑定信息
m_handler.reset(new ByteRTCEventHandler());
connect(m_handler.get(), &ByteRTCEventHandler::sigLocalVideoSizeChanged, this, &VideoConfigWidget::onSigLocalVideoSizeChanged);
5)、收到回调 触发信号
void ByteRTCEventHandler::onLocalVideoSizeChanged(bytertc::StreamIndex index, const bytertc::VideoFrameInfo &info)
{
qDebug() << Q_FUNC_INFO << "index:" << index << ",w=" << info.width << ",h=" << info.height << ",rotation=" << info.rotation;
emit sigLocalVideoSizeChanged(index, info);
}
6)、处理
void VideoConfigWidget::onSigLocalVideoSizeChanged(bytertc::StreamIndex index, const bytertc::VideoFrameInfo info)
{
QString str = "onLocalVideoSizeChanged, w=" + QString::number(info.width) + ",h=" + QString::number(info.height) + ",rotation=" + QString::number(info.rotation);
appendCallback(str);
}
2、本地视频采集设置
void VideoConfigWidget::onBtnCaptureClicked()
{
int ret = 0;
bytertc::VideoCaptureConfig config;
config.width = ui->spinBox_c_w->value(); //采集宽度
config.height = ui->spinBox_c_h->value(); //采集高度
config.frame_rate = ui->spinBox_c_fps->value(); //采集帧率
config.capture_preference = getCapturePreference(); //采集偏好设置
if (m_video) {
//当分辨率或旋转角度发生变化时,回调 onLocalVideoSizeChanged
ret = m_video->setVideoCaptureConfig(config);
if (ret < 0) {
QMessageBox box(QMessageBox::Warning, QStringLiteral("提示"), QString("setVideoCaptureConfig error"), QMessageBox::Ok);
box.exec();
return;
}
appendAPI("setVideoCaptureConfig");
}
}
3、编码参数设置
void VideoConfigWidget::onBtnEncoderClicked()
{
int ret = 0;
if (m_video) {
bytertc::VideoEncoderConfig config;
config.width = ui->spinBox_e_w->value();
config.height = ui->spinBox_e_h->value();
config.frame_rate = ui->spinBox_e_fps->value();
config.encoder_preference = getEncoderPreference();
config.min_bitrate = ui->spinBox_e_bps_min->value();
config.max_bitrate = ui->spinBox_e_bps_max->value();
ret = m_video->setVideoEncoderConfig(config);
if (ret < 0) {
QMessageBox box(QMessageBox::Warning, QStringLiteral("提示"), QString("setVideoEncoderConfig error"), QMessageBox::Ok);
box.exec();
return;
}
appendAPI("setVideoEncoderConfig");
}
}
4、设置镜像
void VideoConfigWidget::onComboMirrorClicked(const QString& text) //镜像
{
if (m_video) {
bytertc::MirrorType type = getMirrorType();
int ret = m_video->setLocalVideoMirrorType(type);
if (ret < 0) {
QMessageBox box(QMessageBox::Warning, QStringLiteral("提示"), QString("setLocalVideoMirrorType error"), QMessageBox::Ok);
box.exec();
}
appendAPI("setLocalVideoMirrorType");
}
}
5、设置本地渲染
void VideoConfigWidget::onComboLocalRenderTextChanged(const QString &text) //本地渲染模式
{
if (m_video) {
int ret = 0;
bytertc::VideoCanvas cas;
cas.view = nullptr;
m_video->setLocalVideoCanvas(bytertc::kStreamIndexMain, cas);
cas.view = (void*)ui->widget->getWinId();
cas.render_mode = getRenderMode(ui->comboBox_c_render);
cas.background_color = 0xFFFFFF00;
// cas.background_color = 0xFFFFFF00; //默认黑色背景
ret = m_video->setLocalVideoCanvas(bytertc::kStreamIndexMain, cas);
if (ret < 0) {
QMessageBox box(QMessageBox::Warning, QStringLiteral("提示"), QString("setLocalVideoCanvas error"), QMessageBox::Ok);
box.exec();
}
appendAPI("setLocalVideoCanvas, mode=" + QString::number(cas.render_mode));
}
}
6、远端渲染设置
void VideoConfigWidget::onComboRemoteRenderTextChanged(const QString &text) //远端渲染模式
{
if (m_rendering.empty()) {
QMessageBox box(QMessageBox::Warning, QStringLiteral("提示"), QStringLiteral("没有远端流,无法修改渲染模式 error"), QMessageBox::Ok);
box.exec();
}
if (m_video) {
int ret = 0;
bytertc::VideoCanvas cas;
bytertc::RemoteStreamKey key;
key.room_id = m_roomid.c_str();
key.stream_index = bytertc::kStreamIndexMain;
key.user_id = m_rendering.c_str();
cas.background_color = 0;
cas.render_mode = getRenderMode(ui->comboBox_remote_render);
cas.view = nullptr;
m_video->setRemoteVideoCanvas(key, cas);
cas.view = (void*)ui->widget_2->getWinId();
ret = m_video->setRemoteVideoCanvas(key, cas);
ui->widget_2->setUserInfo(m_roomid, m_rendering);
if (ret < 0) {
QMessageBox box(QMessageBox::Warning, QStringLiteral("提示"), QString("setRemoteVideoCanvas error"), QMessageBox::Ok);
box.exec();
}
appendAPI("setRemoteVideoCanvas");
}
}
7、水印
void VideoConfigWidget::onCheckWaterClicked(int state) { //水印
if (m_video == nullptr) {
return;
}
int ret = 0;
bytertc::RTCWatermarkConfig config;
if (ui->checkBox_water->isChecked()) {
std::string path = QApplication::applicationDirPath().toStdString() + APIDemo::str_Video_Watermark;
bytertc::ByteWatermark mark;
config.visible_in_preview = true;
mark.x = 0;
mark.y = 0;
mark.width = 0.1;
mark.height = 0.1;
config.position_in_landscape_mode = mark;
config.position_in_portrait_mode = mark;
ret = m_video->setVideoWatermark(bytertc::kStreamIndexMain, path.c_str(), config);
if (ret < 0) {
QMessageBox box(QMessageBox::Warning, QStringLiteral("提示"), QString("setVideoWatermark error:") + QString::number(ret), QMessageBox::Ok);
box.exec();
}
appendAPI("setVideoWatermark");
}
else {
ret = m_video->clearVideoWatermark(bytertc::kStreamIndexMain);
if (ret < 0) {
QMessageBox box(QMessageBox::Warning, QStringLiteral("提示"), QString("clearVideoWatermark error") + QString::number(ret), QMessageBox::Ok);
box.exec();
}
appendAPI("clearVideoWatermark");
}
}
8、背景音乐
bytertc::MediaPlayerConfig config;
config.auto_play = true;
config.callback_on_progress_interval = 500;
config.play_count = 1;
config.start_pos = 0;
config.sync_progress_to_record_frame = true;
config.type = bytertc::kAudioMixingTypePlayoutAndPublish;
int ret = player->open(url.c_str(), config);
appendAPI("open");
if (ret < 0) {
QMessageBox box(QMessageBox::Warning, QStringLiteral("提示"), QString("open error:") + QString::number(ret), QMessageBox::Ok);
box.exec();
return;
}