火山RTC 7 获得远端裸数据

一、获得远端裸数据

1、获得h264数据

1)、远端编码后视频数据监测器

/*** @locale zh* @type callback* @region 视频管理* @brief 远端编码后视频数据监测器<br>* 注意:回调函数是在 SDK 内部线程(非 UI 线程)同步抛出来的,请不要做耗时操作或直接操作 UI,否则可能导致 app 崩溃。*/
/*** @locale en* @type callback* @region  video management* @brief  Remote encoded video data monitor<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 IRemoteEncodedVideoFrameObserver {
public:/*** @locale zh* @hidden constructor/destructor* @brief 析构函数*//*** @locale en* @hidden constructor/destructor* @brief  Destructor*/virtual ~IRemoteEncodedVideoFrameObserver() {}/*** @locale zh* @type callback* @region 视频数据回调* @brief 调用 registerRemoteEncodedVideoFrameObserver{@link #IRTCVideo#registerRemoteEncodedVideoFrameObserver} 后,SDK 监测到远端编码后视频数据时,触发该回调* @param stream_info 收到的远端流信息,参看 RemoteStreamKey{@link #RemoteStreamKey}* @param video_stream 收到的远端视频帧信息,参看 IEncodedVideoFrame{@link #IEncodedVideoFrame}*//*** @locale en* @type callback* @region  video data callback* @brief  Call registerRemoteEncodedVideoFrameObserver{@link #IRTCVideo#registerRemoteEncodedVideoFrameObserver}, the callback is triggered when the SDK detects the remote encoded video data* @param stream_info The received remote stream information. See RemoteStreamKey{@link #RemoteStreamKey}* @param video_stream The received remote video frame information. See IEncodedVideoFrame{@link #IEncodedVideoFrame}*/virtual void onRemoteEncodedVideoFrame(const RemoteStreamKey& stream_info, const IEncodedVideoFrame& video_stream) = 0;
};

2)、IRemoteEncodedVideoFrameObserver 派生


class ByteRTCEventHandler : public QObject,public bytertc::IRTCVideoEventHandler,public bytertc::IAudioEffectPlayerEventHandler,public bytertc::IMixedStreamObserver,public bytertc::IMediaPlayerEventHandler,public bytertc::IRemoteEncodedVideoFrameObserver,public bytertc::IVideoSink

 virtual void onRemoteEncodedVideoFrame(const bytertc::RemoteStreamKey& stream_info, const bytertc::IEncodedVideoFrame& video_stream) override;

void ByteRTCEventHandler::onRemoteEncodedVideoFrame(const bytertc::RemoteStreamKey& stream_info, const bytertc::IEncodedVideoFrame& video_stream) {}

std::unique_ptr<ByteRTCEventHandler> m_handler;

3)、registerRemoteEncodedVideoFrameObserver

/*** @locale zh* @type api* @region 视频管理* @brief 注册远端编码后视频数据回调。  <br>*        完成注册后,当 SDK 监测到远端编码后视频帧时,会触发 onRemoteEncodedVideoFrame{@link #IRemoteEncodedVideoFrameObserver#onRemoteEncodedVideoFrame} 回调* @param observer 远端编码后视频数据监测器,参看 IRemoteEncodedVideoFrameObserver{@link #IRemoteEncodedVideoFrameObserver}* @return  *        + 0: 调用成功。<br>*        + < 0 : 调用失败。查看 ReturnStatus{@link #ReturnStatus} 获得更多错误说明* @note  *       + 更多自定义解码功能说明参看 [自定义视频编解码](https://www.volcengine.com/docs/6348/82921#%E8%87%AA%E5%AE%9A%E4%B9%89%E8%A7%86%E9%A2%91%E8%A7%A3%E7%A0%81)。<br>*       + 该方法适用于手动订阅,并且进房前后均可调用,建议在进房前调用。 <br>*       + 引擎销毁前需取消注册,调用该方法将参数设置为 nullptr 即可。*//*** @locale en* @type api* @region video management* @brief Video data callback after registering remote encoding.   <br>*         After registration, when the SDK detects a remote encoded video frame, it will trigger the onRemoteEncodedVideoFrame{@link #IRemoteEncodedVideoFrameObserver#onRemoteEncodedVideoFrame} callback* @param observer Remote encoded video data monitor. See IRemoteEncodedVideoFrameObserver{@link #IRemoteEncodedVideoFrameObserver}* @return  *        + 0: Success.<br>*        + < 0 : Fail. See ReturnStatus{@link #ReturnStatus} for more details* @note *        + See [Custom Video Encoding and Decoding](https://docs.byteplus.com/byteplus-rtc/docs/82921#custom-video-decoding) for more details about custom video decoding. <br>*        + This method applys to manual subscription mode and can be called either before or after entering the Room. It is recommended to call it before entering the room. <br>*        + The engine needs to be unregistered before it is destroyed. Call this method to set the parameter to nullptr.*/virtual int registerRemoteEncodedVideoFrameObserver(IRemoteEncodedVideoFrameObserver* observer) = 0;

m_video->registerRemoteEncodedVideoFrameObserver(m_handler.get());

2、自定义视频渲染器

0)、IVideoSink 


/*** @locale zh* @type keytype* @brief 自定义视频渲染器*/
/*** @locale en* @type keytype* @brief Custom video renderer*/
class IVideoSink {
public:/*** @locale zh* @type keytype* @brief 视频帧编码格式*//*** @locale en* @type keytype* @brief Video frame encoding format*/enum PixelFormat {/*** @locale zh* @brief YUV I420 格式*//*** @locale en* @brief YUV I420 format*/kI420 = VideoPixelFormat::kVideoPixelFormatI420,/*** @locale zh* @brief RGBA 格式, 字节序为 R8 G8 B8 A8*//*** @locale en* @brief RGBA format*/kRGBA = VideoPixelFormat::kVideoPixelFormatRGBA,/*** @locale zh* @brief 原始视频帧格式*//*** @locale en* @brief Original format*/kOriginal = VideoPixelFormat::kVideoPixelFormatUnknown,};/*** @locale zh* @type callback* @brief 视频帧回调* @param [out] video_frame 视频帧结构类,参看 IVideoFrame{@link #IVideoFrame}* @return 返回值暂未使用*//*** @locale en* @type callback* @brief Video frame callback* @param [out] video_frame Video frame structure. See IVideoFrame{@link #IVideoFrame}.* @return Temporarily unavailable*/virtual bool onFrame(IVideoFrame* video_frame) = 0;/*** @locale zh* @type callback* @region 房间管理* @brief 获取外部渲染耗时。* @note 获取外部渲染耗时进行上报。开发者需要自己计算平均渲染耗时。*//*** @locale en* @type callback* @region Room Management* @brief Gets the time taken in custom rendering.* @note Gets the time taken in custom rendering and report. You need to calculate the average rendering time by yourself.*/virtual int getRenderElapse() = 0;/*** @locale zh* @type callback* @brief 释放渲染器。* @note 通知开发者渲染器即将被废弃。收到该返回通知后即可释放资源。*//*** @locale en* @type callback* @brief Releases the renderer.* @note Used to notify the user that the renderer is about to be deprecated. Resources can be released upon receipt of this notification.*/virtual void release() {}/*** @locale zh* @hidden constructor/destructor* @brief 析构函数*//*** @locale en* @hidden constructor/destructor* @brief Destructor*/virtual ~IVideoSink() = default;/*** @locale zh* @hidden sink id* @brief sink id*//*** @locale en* @hidden sink id* @brief sink id*/virtual void* uniqueId() const { return (void *)this; }
};

1)、setRemoteVideoSink

    /*** @locale zh* @type api* @deprecated since 3.57, use setRemoteVideoRender{@link #IRTCVideo#setRemoteVideoRender} instead.* @region 自定义视频采集渲染* @brief 将远端视频流与自定义渲染器绑定。* @param stream_key 远端流信息,用于指定需要渲染的视频流来源及属性,参看 RemoteStreamKey{@link #RemoteStreamKey}。* @param video_sink 自定义视频渲染器,参看 IVideoSink{@link #IVideoSink}。* @param required_format video_sink 适用的视频帧编码格式,参看 PixelFormat{@link #PixelFormat}。* @return  *        + 0: 调用成功。<br>*        + < 0 : 调用失败。查看 ReturnStatus{@link #ReturnStatus} 获得更多错误说明* @note  *        + RTC SDK 默认使用 RTC SDK 自带的渲染器(内部渲染器)进行视频渲染。<br>*        + 该方法进房前后均可以调用。若想在进房前调用,你需要在加入房间前获取远端流信息;若无法预先获取远端流信息,你可以在加入房间并通过 onUserPublishStream{@link #IRTCRoomEventHandler#onUserPublishStream} 回调获取到远端流信息之后,再调用该方法。<br>*        + 如果需要解除绑定,必须将 video_sink 设置为 null。退房时将清除绑定状态。<br>*        + 本方法获取的是后处理后的视频帧,如需获取其他位置的视频帧(如解码后的视频帧),请调用 setRemoteVideoRender{@link #IRTCVideo#setRemoteVideoRender}。*//*** @locale en* @type api* @region Custom Video Capturing & Rendering* @brief Binds the remote video stream to a custom renderer.* @param stream_key Remote stream information which specifys the source and type of the video stream to be rendered. See RemoteStreamKey{@link #RemoteStreamKey}.* @param video_sink Custom video renderer. See IVideoSink{@link #IVideoSink}.* @param required_format Encoding format which applys to the custom renderer. See PixelFormat{@link #PixelFormat}.* @return  *        + 0: Success.<br>*        + < 0 : Fail. See ReturnStatus{@link #ReturnStatus} for more details* @note   *        + RTC SDK uses its own renderer (internal renderer) for video rendering by default.  <br>*        + Joining or leaving the room will not affect the binding state. <br>*         + This API can be called before and after entering the room. To call before entering the room, you need to get the remote stream information before joining the room; if you cannot get the remote stream information in advance, you can call the API after joining the room and getting the remote stream information via onUserPublishStream{@link #IRTCRoomEventHandler#onUserPublishStream}.<br>*         + If you need to unbind, you must set videoSink to null.*/virtual int setRemoteVideoSink(RemoteStreamKey stream_key, IVideoSink* video_sink, IVideoSink::PixelFormat required_format) = 0;

2)、远端用户发布流时,设置渲染方式

注意:设置registerRemoteEncodedVideoFrameObserver 后,setRemoteVideoSink 不再起作用了

//远端用户发流
void QuickStartWidget::onSigUserPublishStream(std::string roomid, std::string uid, bytertc::MediaStreamType type)
{QString log_str = QString("onUserPublishStream,roomid:")+ QString::fromStdString(roomid)+ ",uid:" + QString::fromStdString(uid)+ ",type:" + QString::number(type);appendCallback(log_str);if (!m_remote_rendered) {if (0) {bytertc::VideoCanvas cas;bytertc::RemoteStreamKey key;key.room_id = roomid.c_str();key.user_id = uid.c_str();key.stream_index = bytertc::kStreamIndexMain;cas.background_color = 0;cas.render_mode = bytertc::kRenderModeHidden;cas.view = nullptr;m_video->setRemoteVideoCanvas(key, cas);cas.view = (void*)ui->widget_remote->getWinId();m_video->setRemoteVideoCanvas(key, cas);ui->widget_remote->setUserInfo(roomid, uid);m_remote_rendered = true;}else {bytertc::RemoteStreamKey key;key.room_id = roomid.c_str();key.user_id = uid.c_str();key.stream_index = bytertc::kStreamIndexMain;//  m_video->setRemoteVideoSink(key, m_handler.get(), bytertc::IVideoSink::PixelFormat::kRGBA);m_video->setRemoteVideoSink(key, m_handler.get(), bytertc::IVideoSink::PixelFormat::kRGBA);m_remote_rendered = true;}}
}

3)、获得远端裸数据


bool ByteRTCEventHandler::onFrame(bytertc::IVideoFrame* video_frame) {bytertc::VideoFrameType type= video_frame->frameType();bytertc::VideoPixelFormat   format=video_frame->pixelFormat();bytertc::VideoContentType contentType= video_frame->videoContentType();int width = video_frame->width();int height= video_frame->height();bytertc::VideoRotation rotation = video_frame->rotation();bytertc::ColorSpace space = video_frame->colorSpace();int numPlans = video_frame->numberOfPlanes();uint8_t* data = video_frame->getPlaneData(numPlans-1);SaveRGBAToPNG(data, width, height, "output.png");return true;
}

测试

#define STB_IMAGE_WRITE_IMPLEMENTATION
#include "stb_image_write.h"void SaveRGBAToPNG(uint8_t* rgbaData, int width, int height, const std::string& filePath) {// 第4个参数是每像素通道数,这里RGBA是4// 每行像素的跨度是 width * 4 字节stbi_write_png(filePath.c_str(), width, height, 4, rgbaData, width * 4);
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/82789.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

web 自动化之 Unittest 四大组件

文章目录 一、如何开展自动化测试1、项目需求分析&#xff0c;了解业务需求 web 功能纳入自动化测试2、选择何种方式实现自动化测试 二、Unittest 框架三、TestCase 测试用例四、TestFixture 测试夹具 执行测试用例前的前置操作及后置操作五、TestSuite 测试套件 & TestLoa…

42、在.NET 中能够将⾮静态的⽅法覆写成静态⽅法吗?

在.NET中&#xff0c;不能将非静态方法&#xff08;实例方法&#xff09;直接覆写&#xff08;Override&#xff09;为静态方法&#xff08;Static Method&#xff09;。以下是关键原因和解释&#xff1a; 1. 方法绑定的本质区别 实例方法&#xff1a;属于对象的实例&#xf…

8天Python从入门到精通【itheima】-1~5

目录 1节&#xff1a; 1.Python的优势&#xff1a; 2.Python的独具优势的特点&#xff1a; 2节-初识Python&#xff1a; 1.Python的起源 2.Python广泛的适用面&#xff1a; 3节-什么是编程语言&#xff1a; 1.编程语言的作用&#xff1a; 2.编程语言的好处&#xff1a;…

3D迷宫探险:伪3D渲染与运动控制的数学重构

目录 3D迷宫探险:伪3D渲染与运动控制的数学重构引言第一章 伪3D渲染引擎1.1 射线投射原理1.2 纹理透视校正第二章 迷宫生成算法2.1 图论生成模型2.2 复杂度控制第三章 第一人称控制3.1 运动微分方程3.2 鼠标视角控制第四章 碰撞检测优化4.1 层级检测体系4.2 滑动响应算法第五章…

mac一键安装gpt-sovit教程中,homebrew卡住不动的问题

mac一键安装gpt-sovit教程 仅作为安装过程中解决homebrew卡住问题的记录 资源地址 https://www.yuque.com/baicaigongchang1145haoyuangong/ib3g1e/znoph9dtetg437xb#mlAoP 下载一键包 下载后并解压&#xff0c;找到install for mac.sh&#xff0c;终端执行bash空格拖拽in…

git 远程仓库管理详解

Git 的远程仓库管理是多人协作和代码共享的核心功能。以下是 Git 远程仓库管理的详细说明&#xff0c;包括常用操作、命令和最佳实践。 1. 什么是远程仓库&#xff1f; 远程仓库&#xff08;Remote Repository&#xff09;&#xff1a;存储在网络服务器上的 Git 仓库&#xff0…

【超详细教程】安卓模拟器如何添加本地文件?音乐/照片/视频一键导入!

作为一名安卓开发者或手游爱好者&#xff0c;安卓模拟器是我们日常工作和娱乐的重要工具。但很多新手在使用过程中常常遇到一个共同问题&#xff1a;**如何将电脑本地的音乐、照片、视频等文件导入到安卓模拟器中&#xff1f;**今天&#xff0c;我将为大家带来一份全网最详细的…

使用vite重构vue-cli的vue3项目

一、修改依赖 首先修改 package.json&#xff0c;修改启动方式与相应依赖 移除vue-cli并下载vite相关依赖&#xff0c;注意一些peerDependency如fast-glob需要手动下载 # 移除 vue-cli 相关依赖 npm remove vue/cli-plugin-babel vue/cli-plugin-eslint vue/cli-plugin-rout…

uniapp|实现手机通讯录、首字母快捷导航功能、多端兼容(H5、微信小程序、APP)

基于uniapp实现带首字母快捷导航的通讯录功能,通过拼音转换库实现汉字姓名首字母提取与分类,结合uniapp的scroll-view组件与pageScrollTo API完成滚动定位交互,并引入uni-indexed-list插件优化索引栏性能。 目录 核心功能实现动态索引栏生成​联系人列表渲染​滚动定位联动性…

C#中SetProperty方法使用

SetProperty 是 MVVM&#xff08;Model-View-ViewModel&#xff09; 模式中用于实现 属性变更通知&#xff08;INotifyPropertyChanged&#xff09; 的核心方法&#xff0c;主要用于在属性值变化时自动更新 UI 绑定。 1. SetProperty 的基本作用 更新字段值&#xff1a;修改属性…

MYSQL 全量,增量备份与恢复

目录 一 数据备份的重要性 1 数据备份的重要性 2 数据库备份类型 2.1 从物理与逻辑的角度分类 2.2. 从数据库的备份策略角度分类从数据库的备份策略角度,数据库的备份可分为完全备份、差异备份和增量备份。 3 常见的备份方法 3.1 物理冷备份 物理冷备份时需要在数据库处…

豆瓣电影Top250数据工程实践:从爬虫到智能存储的技术演进(含完整代码)

目录 引言:当豆瓣榜单遇见大数据技术 项目文档 1.1 选题背景 1.2 项目目标 2. 项目概述 2.1 系统架构设计 2.2 技术选型 2.3 项目环境搭建 2.3.1 基础环境准备 2.3.2 爬虫环境配置 2.3.3 Docker安装ES连接Kibana 安装IK插件 2.3.4 vscode依赖服务安装 3. 核心模…

深度 |国产操作系统“破茧而出”:鸿蒙电脑填补自主生态空白

真心为国内能有像华为这样的技术型公司而自豪&#xff0c;一步步突围技术封锁。从这篇信息&#xff0c;可以给软件从业者一个启示&#xff1a;鸿蒙生态将是一个新的机会&#xff0c;值得好好把握。 鸿蒙电脑正成为中国电子信息技术新坐标。 超10亿鸿蒙生态设备、2800家鸿蒙智…

【网络安全】——大端序(Big-Endian)​​和​​小端序(Little-Endian)

字节序&#xff08;Endianness&#xff09;是计算机系统中多字节数据&#xff08;如整数、浮点数&#xff09;在内存中存储或传输时&#xff0c;​​字节排列顺序​​的规则。它分为两种类型&#xff1a;​​大端序&#xff08;Big-Endian&#xff09;​​和​​小端序&#xf…

六个仓库合并为一个仓库,保留master和develop分支的bat脚本

利用git subtree可以实现多个仓库合并为一个仓库&#xff0c;手动操作起来太麻烦了&#xff0c;今天花了点时间写了一个可执行的脚本&#xff0c;现在操作起来就方便多了。 1、本地新建setup.bat文件 2、用编辑器打开&#xff08;我用的是Notepad&#xff09; 3、把下面代码…

使用定时器监视当前PID 如果当前程序关闭 UI_Core.exe 也随之自动关闭实现方法

使用定时器监视当前PID 如果当前程序关闭 UI_Core.exe 也随之自动关闭实现方法 描述: C20 QT6.9 VS2022 中使用QProcess::startDetached(“UI_Core.exe”, QStringList(), QString(), &UI_Manage_pid);是启动目标程序 能否同时告诉目标程序当前宿主程序的PID,在UI_CORE.EX…

神经网络是如何工作的

人工智能最核心的技术之一&#xff0c;就是神经网络&#xff08;Neural Networks&#xff09;。但很多初学者会觉得它是个黑盒&#xff1a;为什么神经网络能识别图片、翻译语言&#xff0c;甚至生成文章&#xff1f; 本文用图解最小代码实现的方式&#xff0c;带你深入理解&am…

LeetCode热题100 两数之和

目录 两数之和题目解析方法一暴力求解代码 方法二哈希代码 感谢各位大佬对我的支持,如果我的文章对你有用,欢迎点击以下链接 &#x1f412;&#x1f412;&#x1f412; 个人主页 &#x1f978;&#x1f978;&#x1f978; C语言 &#x1f43f;️&#x1f43f;️&#x1f43f;…

在线服务器具体是指什么?

在线服务器主要是指一种能够随时进行网络连接、管理和操作的服务器&#xff0c;在线服务器是通过互联网或者是本地网络&#xff0c;来为企业和用户提供数据存储和网络服务的&#xff0c;在线服务器也可以是物理服务器或者是虚拟服务器&#xff0c;能够根据远程访问工具进行管理…

OSPF综合性实验

实验拓扑&#xff1a; 第一步&#xff1a;进行子网划分 172.16.0.0/17 172.16.0000 00 00.00000000 -- area1 172.16.0.1/22 -- AR1--G0/0/0 172.16.0.2/22 -- AR2--G0/0/0 172.16.0.3/22 -- AR3--G0/0/0 172.16.4.1/22 -- AR1-- Lo0 172.16.8.2/22 -- AR2-- Lo0 172.16.12.3/…