WebRTC新增FFmpeg视频编解码模块

news2025/1/23 9:15:22

1、整体描述


目前webrtc内置的视频编解码器包括:VP8、VP9、AV1和H264。一般情况下载pc端基本可以满足大部分的需求,但是有时候为了进行编解码器的扩展包括支持H265或者是支持硬件编解码以提升效率时需要新增编解码模块。

2、新增外部编码器


编码器实现的要点包括两个部分:一是需要实现以VideoEncoder为基类的编码器对象,核心API实现如下:(1)初始化编码器,将编码参数传入进行初始化。

virtual int InitEncode(const VideoCodec* codec_settings,

const VideoEncoder::Settings& settings);

(2)回调函数的注册,用于编码后数据的回传。

virtual int32_t RegisterEncodeCompleteCallback(

EncodedImageCallback* callback) = 0;

(3)编码函数,将视频帧数据传入到解码器中,这个函数是实际编码接口;外部数据输入包括VideoFrame数据帧一般是kI420数据和帧类型(I帧、P帧…)

virtual int32_t Encode(const VideoFrame& frame,

const std::vector<VideoFrameType>* frame_types) = 0;

(4) QOS相关控制,设置码率和帧率等操作。

void SetRates(const RateControlParameters& parameters) override;

二是需要实现EncodedImageCallback回调基类来处理,编码后的数据回传到视频引擎。核心函数就是将编码后的数据转成EncodedImage结构回传到视频引擎。

2.1 编码器初始化

编码器的初始化主要是对编码器的基础参数包括分辨率,码率和荷载等基本数据,我们在完成编码器的初始化基本需要完成编码对象的创建和编码通道的创建等操作。这部分工作主要是在InitEncode完成,需要注意的是初始化函数可能被调用多次,因此这里需要保护防止多次创建造成,内存泄漏和系统资源冲突等问题。

以FFmpeg初始化编码器为例,基本需要包括四部分一是进行编码器的选择,根据codec类型, 寻找并创建编码器的上下文;第二是编码参数的初始化,根据上层传入的用户配置参数及自身对编码器的理解, 对所使用编码器参数进行的配置,可以进行参数的优化提高编码质量和用户体验;第三是编码帧的初始化,最后是开启编码器。

//编码器

AVCodec *avcodec_find_encoder(enum AVCodecID id);

//上下文获取

AVCodecContext *avcodec_alloc_context3(const AVCodec *codec);

//初始化视频帧

AVFrame *avcodec_alloc_frame(void);

//开启编码器

int avcodec_open(AVCodecContext *avctx, AVCodec *codec);

2.2 编码实现

编码阶段需要理解两方面数据,一方面是输入数据VideoFrame为原始的图像帧,一般情况为I420,我们需要进行内部转换转成FFmpeg编码的输入参数。

以FFmpeg为例,解码过程分为三步:一是将输入数据转换为I420数据,然后利用类内部接口获取YUV数据并组装成编码器需要的数据;

二是编码数据,一般是调用FFmpeg编码函数编码,内部会进一步根据不同编码类型进行编码;

三是编码结束后,需要根据重新将编码后的数据进行组装得到一个EncodedImage结构体,并且调用回调函数将结果返回给视频引擎处理。

//将原始视频数据,转成I420格式

input_frame.video_frame_buffer()->ToI420()

//获取YUV数据

frame_buffer->DataY();

//图片填充

int avpicture_fill(AVPicture *picture, const uint8_t *ptr,

enum AVPixelFormat pix_fmt, int width, int height);

//视频编码

int avcodec_encode_video(AVCodecContext *avctx, uint8_t *buf, int buf_size,

const AVFrame *pict);

//回调,数据返回

Encoded(EncodedImage& encodedImage,

const CodecSpecificInfo* codecSpecificInfo = NULL,

const RTPFragmentationHeader* fragmentation = NULL) = 0;

3、新增外部解码器


解码器实现与编码器类似,实现的要点包括两个部分:一是需要实现以VideoDecoder为基类的解码器对象,核心API实现如下:(1)初始化解码器,将解码参数传入进行初始化。

virtual bool Configure(const Settings& settings) = 0;

(2)回调函数的注册,用于解码后数据的回传。

virtual int32_t Decode(const EncodedImage& input_image,

bool missing_frames,

int64_t render_time_ms) = 0;

(3)解码函数,将编码视频帧数据传入到解码器中,这个函数是实际解码接口;外部数据输入包括EncodedImage数据帧,渲染时间和是否丢帧等。

virtual int32_t Decode(const EncodedImage& input_image,

bool missing_frames,

int64_t render_time_ms) = 0;

(4) 与视频编码不一样的配置函数,包括视频的解码缓冲区大小和渲染分辨率的设置。

//设置解码缓冲区大小

void set_buffer_pool_size(absl::optional<int> value);

//设置渲染分辨率

void set_max_render_resolution(RenderResolution value);

二是需要实现DecodedImageCallback回调基类来处理,解码后的数据回传到视频引擎。核心函数就是将编码后的数据转成原始视频帧VideoFrame结构回传到视频引擎。

3.1 解码器初始化

解码器的初始化主要是对解码器的基础参数包括分辨率,码率和荷载等基本数据,我们在完成解码器的初始化基本需要完成解码对象的创建和解码通道的创建等操作。这部分工作主要是在Configure完成,需要注意的是初始化函数可能被调用多次,因此这里需要保护防止多次创建造成,内存泄漏和系统资源冲突等问题。

以FFmpeg初始化解码器为例,基本需要包括四部分第一是解码参数的初始化,根据上层传入的用户配置参数及自身对解码器的理解, 对所使用解码器参数进行的配置,可以进行参数的优化提高解码质量和用户体验;二是进行解码器的选择,根据codec类型, 寻找并创建解码器的上下文;第三是开启解码器,传入上下文配置和解码器;第四部分是分配一个解码帧,用于后续解码使用。

//上下文获取

AVCodecContext *avcodec_alloc_context3(const AVCodec *codec);

//解码器

AVCodec *avcodec_find_decoder(enum AVCodecID id);

//开启解码器

int avcodec_open2(AVCodecContext *avctx, const AVCodec *codec, AVDictionary **options);

//初始化视频帧

AVFrame *avcodec_alloc_frame(void);

3.2 解码实现

解码阶段需要理解两方面数据,一方面是输入数据EncodedImage为编码后的数据,需要转换会解码器需要的帧结构,然后进行解码操作;第二是解码后数据解释为VideoFrame帧后回调给视频引擎。

以FFmpeg为例,解码过程分为四步:一是将EncodedImage结构视频帧转换为AVPacket结构;第二是将配置上下文和AVPacket传入解码器解码;第三是获取解码后视频帧存入AVFrame中;第四是需要根据重新将解码后的数据进行组装得到一个VideoFrame结构体,并且调用回调函数将结果返回给视频引擎处理。

//分配一个packet空间

AVPacket *av_packet_alloc(void);

//将编码数据加入到解码队列

int avcodec_send_packet(AVCodecContext *avctx, const AVPacket *avpkt);

//获取解码后数据帧

int avcodec_receive_frame(AVCodecContext *avctx, AVFrame *frame);

//释放packet

void av_packet_free(AVPacket **pkt);

4、总结


webrtc编解码模块设计有较强的对称性,其实在发送和接收,音频和视频,编码和解码等等都在设计上比较接近,因此需要在学习的时候相互借鉴和理解。整个编解码模块的添加相对难度较低,主要是理解输入和输出的数据结构,可以将webrtc的数据结构转换为编解码器内部能够理解的数据,达到将数据编解码的目的。基本的设计理念就是定义好标准的输入和输出,屏蔽内部的处理细节,达到模块之间的相互独立。

原文链接;WebRTC新增FFmpeg视频编解码模块 - 资料 - 我爱音视频网 - 构建全国最权威的音视频技术交流分享论坛

★文末名片可以免费领取音视频开发学习资料,内容包括(FFmpeg ,webRTC ,rtmp ,hls ,rtsp ,ffplay ,srs)以及音视频学习路线图等等。

见下方!↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓

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

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

相关文章

亿万级海量数据去重软方法

文章目录原理案例一需求&#xff1a;方法案例二需求&#xff1a;方法&#xff1a;参考原理 在大数据分布式计算框架生态下&#xff0c;提升计算效率的方法是尽可能的把计算分布式话、并行化&#xff0c;避免单节点计算过载&#xff0c;把计算分摊到各个节点。这样解释小白能够…

最新|移动机器人导航定位技术概述

前言目前工业界广泛落地使用的移动机器人&#xff0c;除了应用场景在餐厅、酒店、超市等小范围室内送餐机器人和消毒机器人外&#xff0c;另外一个“大赛道”应用场景就是在工厂、制造装配车间、电站或车站的物流搬运机器人和巡检机器人了。而在最开始&#xff0c;一切都得从AG…

spring cloud gateway (五)

Gateway简介 Spring Cloud Gateway是Spring公司基于Spring 5.0&#xff0c;Spring Boot 2.0 和 Project Reactor 等技术开发的网关&#xff0c;它旨在为微服务架构提供一种简单有效的统一的 API 路由管理方式。它的目标是替代Netflix Zuul&#xff0c;其不仅提供统一的路由方式…

java 字典

java 字典 数据结构总览 Map Map 描述的是一种映射关系&#xff0c;一个 key 对应一个 value&#xff0c;可以添加&#xff0c;删除&#xff0c;修改和获取 key/value&#xff0c;util 提供了多种 Map HashMap: hash 表实现的 map&#xff0c;插入删除查找性能都是 O(1)&…

MySQL跨服务器数据映射

MySQL跨服务器数据映射环境准备1. 首先是要查看数据库的federated引擎 开启/关闭 状态2. 打开任务管理器&#xff0c;并重启mysql服务3. 再次查看FEDERATED引擎状态&#xff0c;引擎已启动映射实现问题总结在日常的开发中经常进行跨数据库进行查询数据。 同服务器下跨数据库进…

【SpringCloud】SpringCloud详解之Feign实战

目录前言SpringCloud Feign远程服务调用一.需求二.两个服务的yml配置和访问路径三.使用RestTemplate远程调用(order服务内编写)四.使用Feign远程调用(order服务内配置)五.自定义Feign配置(order服务内配置)六.Feign配置日志(oder服务内配置)七.Feign调优(order服务内配置)八.抽…

STM32之 串口

串口通信串行接口简称串口&#xff0c;也称串行通信接口或串行通讯接口&#xff08;通常指COM接口&#xff09;&#xff0c;是采用串行通信方 式的扩展接口。串行接口&#xff08;Serial Interface&#xff09;是指数据一位一位地顺序传送。其特点是通信线路简 单&#xff0c;只…

Vue基础入门讲义(三)-指令

文章目录1.什么是指令&#xff1f;2.插值表达式2.1.花括号2.2.插值闪烁2.3.v-text和v-html3.v-model4.v-on4.1.基本用法4.2.事件修饰5.v-for5.1.遍历数组5.2.数组角标5.3.遍历对象6.key7.v-if和v-show7.1.基本使用7.2.与v-for结合7.3.v-else7.4.v-show8.v-bind8.1. 属性上使用v…

服务器处理发生异常:java.text.ParseException: Unparseable date

测试上传报文的时候遇见报错 服务器处理发生异常:java.text.ParseException: Unparseable date: “2023/03/03” 错误报文 实际需要的报文 错误原因 上传时间字段&#xff0c;与Date字段数据位数不匹配&#xff0c;Java类型&#xff1a;Date默认带有年月日 时分秒yyyy-mm-dd…

十年业务开发总结,如何做好高效高质量的价值交付

作者&#xff1a;杨博林 阿里大淘宝场景金融团队 软件交付是一个非常复杂的过程和体系&#xff0c;需要保障好每个阶段的质量和效率才能保障最终的质量和效率。本文将尝试从需求交付的前、中、后三个环节来阐述一下如何做高效高质量的价值交付。 一、背景 转眼间已经做了十年的…

JavaScript基础内容

日升时奋斗&#xff0c;日落时自省 目录 1、基础语法 2、DOM 2.1、选中页面元素 2.2、获取/修改元素内容 3、JS案例 3.1、网页版本猜数字 3.2、网页版表白墙 JS最初只是为了进行前端页面的开发后来JS也被赋予了更多的功能&#xff0c;可以用来开发桌面程序&#xff0c;手…

RHCSA-重置root密码(3.3)

方法1&#xff1a;rd.break &#xff08;1&#xff09;首先重启系统&#xff0c;在此页面按e键&#xff0c;在屏幕上显示内核启动参数 &#xff08;2&#xff09;知道linux这行&#xff0c;末尾空格后输入rd.break&#xff0c;然后按ctrlx &#xff08;3&#xff09;查看&#…

电脑桌面上的图标不见了怎么办?5个完美的解决技巧

案例&#xff1a;电脑桌面不显示任何东西&#xff1f; “救命&#xff01;电脑打开后&#xff0c;只有桌面&#xff0c;任何图标都没有怎么办&#xff1f;心急&#xff0c;不知道该怎么解决&#xff1f;” 电脑桌面上的图标消失是一个比较常见的问题&#xff0c;许多用户都会…

Hadoop集群启动从节点没有DataNode

目录 一、问题背景 二、解决思路 三、解决办法&#xff1a; 一、问题背景 之前启动hadoop集群的时候都没有问题&#xff0c;今天启动hadoop集群的时候&#xff0c;从节点的DataNode没有启动起来。 二、解决思路 遇见节点起不来的情况&#xff0c;可以去看看当前节点的日志…

各大加密算法对比(原理、性能、安全、运用)

原理按加密可逆可以分为&#xff1a;加密可逆算法和加密不可逆算法。加密可逆算法又可以分为&#xff1a;对称加密和非对称加密。1、加密不可逆算法&#xff1a;一般采用hash算法加密&#xff0c;其原理一般是将原文长度补位成64的倍数&#xff0c;接着初始化固定长度的缓存值&…

大数据框架之Hadoop:MapReduce(五)Yarn资源调度器

Apache YARN (Yet Another Resource Negotiator) 是 hadoop 2.0 引入的集群资源管理系统。用户可以将各种服务框架部署在 YARN 上&#xff0c;由 YARN 进行统一地管理和资源分配。 简言之&#xff0c;Yarn是一个资源调度平台&#xff0c;负责为运算程序提供服务器运算资源&…

Windows Cannot Initialize Data Bindings 问题的解决方法

前言 拿到一个调试程序, 怎么折腾都打不开, 在客户那边, 尝试了几个系统版本, 发现Windows 10 21H2 版本可以正常运行。 尝试 系统篇 系统结果公司电脑 Windows 8有问题…下载安装 Windows10 22H2问题依旧下载安装 Windows10 21H2问题依旧家里的 笔记本Window 11正常 网上…

第三章 opengl之着色器

OpenGL着色器GLSLGLSL的数据类型向量输入与输出Uniform更多属性自己的着色器类着色器 着色器是运行在GPU上的小程序。着色器只是一种把输入转化为输出的程序。着色器也是一种非常独立的程序&#xff0c;因为它们之间不能相互通信&#xff1b;它们之间唯一的沟通只有通过输入和…

DC-DC模块电源隔离直流升压高压稳压输出5v12v24v转60v100v110v150v220v250v300v400v500v

特点效率高达80%以上1*1英寸标准封装单电压输出稳压输出工作温度: -40℃~85℃阻燃封装&#xff0c;满足UL94-V0 要求温度特性好可直接焊在PCB 上应用HRB 0.2~10W 系列模块电源是一种DC-DC升压变换器。该模块电源的输入电压分为&#xff1a;4.5~9V、9~18V、及18~36VDC标准&#…

软工第二次个人作业——软件案例分析

软工第二次个人作业——软件案例分析 项目内容这个作业属于哪个课程2023北航敏捷软件工程这个作业的要求在哪里个人作业-软件案例分析我在这个课程的目标是体验敏捷开发过程&#xff0c;掌握一些开发技能&#xff0c;为进一步发展作铺垫这个作业在哪个具体方面帮助我实现目标通…