深入理解FFmpeg--软/硬件解码流程
FFmpeg是一款强大的多媒体处理工具,支持软件和硬件解码。软件解码利用CPU执行解码过程,适用于各种平台,但可能对性能要求较高。硬件解码则利用GPU或其他专用硬件加速解码,能显著降低CPU负载,提升解码效率和能效。FFmpeg结合这两种解码方式,提供了灵活的多媒体解决方案,适合于视频处理、流媒体和多媒体应用开发。
1、FFmpeg支持多种硬件加速类型,用于编解码视频,以提升性能和效率。以下是FFmpeg支持的主要硬件加速类型:
- NVIDIA NVENC/NVDEC:利用NVIDIA显卡进行视频编码(NVENC)和解码(NVDEC)。
- Intel Quick Sync Video (QSV):利用Intel处理器中的集成图形进行视频加速。
- AMD Video Coding Engine (VCE)和Video Decoding Acceleration (VDA):利用AMD显卡进行视频编码和解码。
- VAAPI (Video Acceleration API):适用于Intel和AMD硬件,通过通用的API接口进行硬件加速。
- VDPAU (Video Decode and Presentation API for Unix):主要用于NVIDIA显卡的硬件解码加速。
- DXVA2 (DirectX Video Acceleration):适用于Windows平台,利用DirectX进行视频加速。
- OpenMAX IL (Open Media Acceleration Integration Layer):用于移动设备和嵌入式系统的视频加速。
- Vulkan:一种跨平台的图形和计算API,也可以用于视频加速。
这些硬件加速类型使FFmpeg在处理高分辨率视频时更加高效,减少了CPU负载,提高了多媒体处理的整体性能。
2、硬件解码流程图(软解流程比起硬解少一些步骤,就不单独画了):
3、代码示例:
Decode.h
#ifndef WINDOWS_FFMPEG_DECODE_H
#define WINDOWS_FFMPEG_DECODE_H
extern "C" {
#include "libavcodec/avcodec.h"
#include "libavformat/avformat.h"
};
#include <memory>class Decode {
public:Decode();~Decode();//初始化软解码//IN:AVCodecID, AVPixelFormatint InitSoftDecode(int VideoType, int PixFmt);//初始化硬解码//IN:AVFormatContext输入上下文, 硬解类型名称int InitHardDecode(AVFormatContext* input_ctx, const std::string& HWType);//解码视频数据int DecodePacket(AVPacket* packet, AVFrame* frame);private://解码器上下文的get_format函数static enum AVPixelFormat get_hw_format(AVCodecContext *ctx, const enum AVPixelFormat *pix_fmts);//初始化AVBufferRefstatic int hw_decoder_init(AVCodecContext *ctx, const enum AVHWDeviceType type);private:AVCodecContext* pDecodeCtx_;AVCodecParserContext* pParseCtx_;AVStream* pVStream_;const AVCodec* pCodec_;static enum AVPixelFormat ePixFmt_;static AVBufferRef* pDeviceCtx;bool bHWDecode_;
};#endif //WINDOWS_FFMPEG_DECODE_H
Decode.cpp
#include "Decode.h"
#include <iostream>
using namespace std;enum AVPixelFormat Decode::ePixFmt_;
AVBufferRef* Decode::pDeviceCtx;
Decode::Decode() {}Decode::~Decode() {}enum AVPixelFormat Decode::get_hw_format(AVCodecContext *ctx, const enum AVPixelFormat *pix_fmts) {const enum AVPixelFormat *p;for (p = pix_fmts; *p != -1; p++) {if (*p == ePixFmt_)return *p;}fprintf(stderr, "Failed to get HW surface format.\n");return AV_PIX_FMT_NONE;
}int Decode::hw_decoder_init(AVCodecContext *ctx, const enum AVHWDeviceType type) {int err = 0;if ((err = av_hwdevice_ctx_create(&pDeviceCtx, type,nullptr, nullptr, 0)) < 0) {fprintf(stderr, "Failed to create specified HW device.\n");return err;}ctx->hw_device_ctx = av_buffer_ref(pDeviceCtx);return err;
}int Decode::InitSoftDecode(int VideoType, int PixFmt) {pCodec_ = avcodec_find_decoder((AVCodecID)VideoType);if (!pCodec_) {std::cout<<"avcodec_find_decoder Failed"<<std::endl;return -1;}pParseCtx_ = av_parser_init(pCodec_->id);if (!pParseCtx_) {std::cout<<"av_parser_init Failed"<<std::endl;return -1;}pDecodeCtx_ = avcodec_alloc_context3(pCodec_);if (!pDecodeCtx_) {std::cout<<"avcodec_alloc_context3 Failed"<<std::endl;return -1;}pDecodeCtx_->pix_fmt = (AVPixelFormat)PixFmt;if (avcodec_open2(pDecodeCtx_, pCodec_, nullptr) < 0) {std::cout<<"avcodec_open2 Failed"<<std::endl;return -1;}bHWDecode_ = false;return 0;
}int Decode::InitHardDecode(AVFormatContext* input_ctx, const std::string& HWType) {enum AVHWDeviceType type;type = av_hwdevice_find_type_by_name(HWType.c_str());if (type == AV_HWDEVICE_TYPE_NONE) {std::cout<<"UnKnown HW Device Type"<<std::endl;while((type = av_hwdevice_iterate_types(type)) != AV_HWDEVICE_TYPE_NONE) {std::cout<< type <<std::endl;}return -1;}int video_index = av_find_best_stream(input_ctx, AVMEDIA_TYPE_VIDEO, -1 , -1, &pCodec_, 0);if (video_index < 0) {cout<<"Cannot find a video stream in the input file"<<endl;return -1;}for (int i = 0; ; i++) {const AVCodecHWConfig *config = avcodec_get_hw_config(pCodec_, i);if (!config) {cout<<"avcodec_get_hw_config Failed"<<i<<endl;return -1;}if (config->methods & AV_CODEC_HW_CONFIG_METHOD_HW_DEVICE_CTX &&config->device_type == type) {ePixFmt_ = config->pix_fmt;break;}}pDecodeCtx_ = avcodec_alloc_context3(pCodec_);if (!pDecodeCtx_) {cout<<"avcodec_alloc_context3 Failed"<<endl;return -1;}pVStream_ = input_ctx->streams[video_index];if (avcodec_parameters_to_context(pDecodeCtx_, pVStream_->codecpar) < 0) {cout<<"avcodec_parameters_to_context Failed"<<endl;return -1;}pDecodeCtx_->get_format = get_hw_format;if (hw_decoder_init(pDecodeCtx_, type) < 0) {return -1;}if (avcodec_open2(pDecodeCtx_, pCodec_, nullptr) < 0) {cout<<"avcodec_open2 Failed"<<endl;return -1;}bHWDecode_ = true;return 0;
}int Decode::DecodePacket(AVPacket* packet, AVFrame* frame) {//软解码if (!bHWDecode_) {int nRet = avcodec_send_packet(pDecodeCtx_, packet); //将AVPacket发送至解码器中if (nRet < 0) {cout<<"Error sending a packet for decoding"<<endl;return -1;}nRet = avcodec_receive_frame(pDecodeCtx_, frame); //从解码器中获取被解码后的帧数据AVFrameif (nRet == AVERROR(EAGAIN) || nRet == AVERROR_EOF)return 0;else if (nRet < 0) {cout<<"Error during decoding"<<endl;return -1;}return 0;} else { //硬解码AVFrame* tmpFrame = nullptr, *swFrame = nullptr;int nRet = avcodec_send_packet(pDecodeCtx_, packet); //将AVPacket发送至解码器中if (nRet < 0) {cout<<"Error sending a packet for decoding"<<endl;av_frame_free(&tmpFrame);av_frame_free(&swFrame);return -1;}if (!(tmpFrame = av_frame_alloc()) || !(swFrame = av_frame_alloc())) {cout<<"Can not alloc frame"<<endl;av_frame_free(&tmpFrame);av_frame_free(&swFrame);nRet = AVERROR(ENOMEM);return -1;}nRet = avcodec_receive_frame(pDecodeCtx_, tmpFrame); //从解码器中获取被解码后的帧数据AVFrameif (nRet == AVERROR(EAGAIN) || nRet == AVERROR_EOF) {av_frame_free(&tmpFrame);av_frame_free(&swFrame);return 0;} else if (nRet < 0) {cout<<"Error while decoding"<<endl;av_frame_free(&tmpFrame);av_frame_free(&swFrame);return -1;}if (frame->format == ePixFmt_) {/* 将GPU中的数据 移交到CPU中*/if (av_hwframe_transfer_data(swFrame, tmpFrame, 0) < 0) {cout<<"Error transferring the data to system memory"<<endl;av_frame_free(&tmpFrame);av_frame_free(&swFrame);return -1;}frame = swFrame;} else {frame = tmpFrame;}av_frame_free(&tmpFrame);av_frame_free(&swFrame);return 0;}
}
代码仅供参考,因为电脑太旧,硬解没识别出来支持的硬件,简单跟着深入理解FFmpeg写的Demo,有问题欢迎指正。
相关文章:
深入理解FFmpeg--软/硬件解码流程
FFmpeg是一款强大的多媒体处理工具,支持软件和硬件解码。软件解码利用CPU执行解码过程,适用于各种平台,但可能对性能要求较高。硬件解码则利用GPU或其他专用硬件加速解码,能显著降低CPU负载,提升解码效率和能效。FFmpe…...
新的铸造厂通过 PROFIBUS 技术实现完全自动化
钢铁生产商某钢以其在厚钢板类别中极高的产品质量而闻名。其原材料(板坯连铸机)在钢铁厂本地生产,该厂最近新建了一座垂直连铸厂。该项目的一个主要目标是从一开始就完全自动化这座新工厂和整个铸造过程,以高成本效率实现最佳产品…...
【UE5.1】NPC人工智能——04 NPC巡逻
效果 步骤 一、准备行为树和黑板 1. 对我们之前创建的AI控制器创建一个子蓝图类 这里命名为“BP_NPC_AIController_Lion”,表示专门用于控制狮子的AI控制器 2. 打开狮子蓝图“Character_Lion” 在类默认值中将“AI控制器类”修改为“BP_NPC_AIController_Lion” 3…...
计算机视觉主流框架及其应用方向
文章目录 前言一、计算机视觉领域的主要框架1、深度学习框架1.1、TensorFlow1.2、PyTorch 2、神经网络模型2.1、卷积神经网络(CNN)2.2、循环神经网络(RNN) 二、框架在计算机视觉任务中的应用1、TensorFlow1.1、概述:1.…...
群晖 搭建alist 记录
docker搭建 使用docker-compose 创建一个 docker-compose.yml version: 3.5services:qbittorrent:image: linuxserver/qbittorrent:latestcontainer_name: qbittorrent# network_mode: hostenvironment:- PUID1000- PGID100- TZAsia/Shanghai- WEBUI_PORT8181 # 将外部端口…...
【北航主办丨本届SPIE独立出版丨已确认ISSN号】第三届智能机械与人机交互技术学术会议(IHCIT 2024,7月27)
由北京航空航天大学指导,北京航空航天大学自动化科学与电气工程学院主办,AEIC学术交流中心承办的第三届智能机械与人机交互技术学术会议(IHCIT 2024)将定于2024年7月27日于中国杭州召开。 大会面向基础与前沿、学科与产业…...
深入浅出WebRTC—NACK
WebRTC 中的 NACK(Negative Acknowledgment)机制是实时通信中处理网络丢包的关键组件。网络丢包是常见的现象,尤其是在无线网络或不稳定连接中。NACK 机制旨在通过请求重传丢失的数据包来减少这种影响,从而保持通信的连续性和质量…...
简单工厂模式、工厂模式和抽象工厂模式的区别
简单工厂模式、工厂模式和抽象工厂模式都是创建型设计模式,它们之间在目的、实现方式和适用场景上存在显著的区别。以下是对这三种模式的详细比较: 一、定义与目的 简单工厂模式(Simple Factory Pattern) 定义: 简单工…...
JVM-垃圾回收与内存分配
目录 垃圾收集器与内存分配策略 引用 对象的访问方式有哪些?(句柄和直接指针) Java的引用有哪些类型? 如何判断对象是否是垃圾? 请列举一些可作为GC Roots的对象? 对象头了解吗? mark word(hashcode、分代、锁标志位)、…...
Jolt路线图
1. 引言 a16z crypto团队2024年7月更新了其Jolt路线图: 主要分为3大维度: 1)链上验证维度: 1.1)Zeromorph:见Aztec Labs团队2023年论文 Zeromorph: Zero-Knowledge Multilinear-Evaluation Proofs from…...
NEEP-EN2-2019-Text4
英二-2019-Text4摘自赫芬顿邮报《The Huffington Post》2018年6月的一篇名为“Let’s Stop Pretending Quitting Straws Will Solve Plastic Pollution”的文章。 以下为个人解析,非官方公开标准资料,可能有误,仅供参考。(单词解释…...
docker 部署wechatbot-webhook 并获取接口实现微信群图片自动保存到chevereto图库等
功能如图: docker部署 version: "3" services:excalidraw:image: dannicool/docker-wechatbot-webhook:latestcontainer_name: wechatbot-webhookdeploy:resources:limits:cpus: 0.15memory: 500Mreservations:cpus: 0.05memory: 80Mrestart: alwayspor…...
OpenWrt安装快速入门指南
在刷新 OpenWrt 固件之前,建议进行以下准备: 1、不要急于安装,慢慢来。如果在安装过程中出现奇怪之处,请先找到答案,然后再继续。 2、准备好设备的精确型号,以便能够选择正确的OpenWrt固件。 3、手上有关…...
AIGC Kolors可图IP-Adapter-Plus风格参考模型使用案例
参考: https://huggingface.co/Kwai-Kolors/Kolors-IP-Adapter-Plus 代码环境安装: git clone https://github.com/Kwai-Kolors/Kolors cd Kolors conda create --name kolors python=3.8 conda activate kolors pip install -r requirements.txt python3 setup.py install…...
从零开始学量化~Ptrade使用教程(七)——期权相关操作
期权交易 可点击证券代码右侧的选,进入期权选择菜单。通过选择标的商品,认购期权和认沽期权中间的选项(包括代码、成交价、幅度%、隐波%、内在价值、时间价值等),以及认购期权或认沽期权,选择所需的期权标的…...
TeamViewer关闭访问密码或固定一组密码不变
TeamViewer的新UI界面变化较大,网上的一些信息已经不再有效,更新后的访问密码在如下图所示: 演示的版本为7.21.4—— 设置每次你的设备访问的密码...
iMazing 3 换手机后苹果游戏数据还有吗 换iPhone怎么转移游戏数据
当你想要更换手机,无论是选择升级到最新款iPhone,或者换到“经典”旧款iPhone,单机游戏数据的转移总是让人发愁。本文将详细介绍换手机后苹果游戏数据还有吗,以及换iPhone怎么转移游戏数据,确保你能无缝继续你的游戏体…...
正则表达式:电子邮件地址的格式详解,及常见正则表达式符号的详细解释和匹配方式
一、第一部分是对该段电子邮件的详解 var Regex /^(?:\w\.?)*\w(?:\w\.)*\w$/; 1.^:这个符号表示匹配输入字符串的开始位置。 2.(?:...):这是一个非捕获组(non-capturing group),用于将正则表达式的一部分组合在…...
AWS全服务历史年表:发布日期、GA和服务概述一览(一)
我一直在尝试从各种角度撰写关于Amazon Web Services(AWS)的信息和魅力。由于我喜欢技术历史,这次我总结了AWS服务发布的历史年表。 虽然AWS官方也通过“Whats New”发布了官方公告,但我一直希望能有一篇文章将公告日期、GA日期&…...
现场可重构CPLD芯片应用案例—蓝牙音箱
我司英尚微提供的高性能数模混合现场可重构IC、通用可配置的模数混合芯片内部集成丰富的模拟资源和数字资源,可轻松替代电路中的各种标准器件,并按照客户要求组合成最优小型ASIC,缩短开发周期,降低成本。下面介绍LS98002现场可重构…...
vue2关于Object.defineProperty实现响应式
实现步骤: 1. 初始化阶段 当 Vue 实例化时,会遍历data 选项中的属性,并使用 Object.defineProperty 将它们转换为 getter 和 setter。这样一来,每当访问或修改这些属性时, Vue就能捕获到这些操作,从而实现…...
中英双语介绍一级市场(Primary Market)和二级市场(Secondary Market)
中文版 一级市场和二级市场是金融市场中的两个主要部分,分别对应证券发行和交易的不同阶段。 一级市场(Primary Market) 定义: 一级市场,又称新发行市场,是指证券首次发行和出售的市场。在一级市场中&am…...
OpenCV 轮廓检测
在 OpenCV 中,轮廓检测是一种用于查找图像中具有相似颜色或强度的连通像素组的技术,这些像素组通常代表了图像中的物体边缘。轮廓可以用来识别和分割图像中的物体,是计算机视觉应用中的一个重要步骤,如目标识别、形状分析等。 轮…...
ubuntu源码安装Odoo
序言:时间是我们最宝贵的财富,珍惜手上的每个时分 Odoo具有非常多的安装方式,除了我最爱用的 apt-get install,我们还可以使用git拉取Odoo源码进行安装。 本次示例于ubuntu20.04 Desktop上进行操作,理论上在ubuntu14.04之后都可以用此操作。 …...
大鲸鱼docker-compose单机容器集群编排工具
目录 一、Docker-compose 概述 二、Docker-compose简介 三、YML文件格式及编写注意事项 1.yml文件是什么 2.yml问价使用注意事项 3.yml文件的基本数据结构 四、Docker-compose 配置 1.Docker-Compose 配置常用字段 2.Docker Compose常用命令 3.使用Docker-compose创建…...
Dify中的高质量索引模式实现过程
思考在什么情况下会使用到高质量索引模式呢?第1种情况是在知识库中上传文档,文档被拆分为段落后需要进行编码(增加);第2种情况是在召回测试的时候,需要对query进行编码(查询);第3种情况是当文档中的段落增加和更新时需要进行编码(增加和更新)。索引模式是针对知识库…...
GO:Socket编程
目录 一、TCP/IP协议族和四层模型概述 1.1 互联网协议族(TCP/IP) 1.2 TCP/IP四层模型 1. 网络访问层(Network Access Layer) 2. 网络层(Internet Layer) 3. 传输层(Transport Layer&#…...
wls2下的centos使用桥接模式连接宿主机网络独立静态ip
前提:wsl2已安装,可正常更新 1.在控制面板中,打开开启或关闭windows功能,将里面的 Hyper-V功能打开,此处涉及重启 2. 按一下win键,输入hy,上面可以看到Hyper-V Manager,点进去 3.选择右边的 Vi…...
R语言实现神经网络ANN
# 常用激活函数 # 自定义Sigmoid函数 sigmod <- function(x){return(1/(1exp(-x))) } # 绘制Sigmoid曲线 x <- seq(-10,10,length.out 100) plot(x,sigmod(x),type l,col blue,lwd 2,xlab NA,ylab NA,main Sigmoid函数曲线)# 自定义Tanh函数 tanh <- function(…...
实战:shell脚本练习
高效编写Bash脚本的技巧 总结了10个实用技巧,帮助提高脚本的效率和可靠性,具体包括: 多写注释:在脚本中添加注释,以帮助理解脚本的不同部分。 当运行失败时使脚本退出:使用set -o errexit或set -e&#x…...
网站建设收费标准市场/网站统计数据
原创!ngxtop-监控nginx的利器!!! 无论名称还是界面,ngxtop的灵感均源自大名鼎鼎的top命令.ngxtop的功能就是,分析Nginx访问日志文件(以及其他日志文件,比如Apache2日志),并通过类似top的界面,实时显示分析后所得的结果.你可能吹嘘自己的综合监控工具拥有…...
富通建设有限公司网站/重庆百度推广开户
Javascript 文件操作 一、功能实现核心:FileSystemObject 对象 其实,要在Javascript中实现文件操作功能,主要就是依靠FileSystemobject对象。在详细介绍FileSystemobject对象的各个属性和方法的使用细节前,先来看看这个对象包括哪…...
宁波怎么做网站排名优化/永久免费自助建站系统
传输层的作用:1.保证可靠传输 2.流量控制 往返时间RTT UDP(User Datagram Protocol)是一种无连接的数据传输的协议 TCP (Transmission Control Protocol)是一种面向连接的传输协议 传输控制协议: 1.停等协议 细节:收到ACK之后再发送下一个数据…...
大连建站系统模板/外贸推广具体是做什么
Redis大数据处理:如何高效地利用Redis存储海量数据 Redis作为一款高性能的NoSQL内存数据库,被广泛应用于各种领域。当需要处理海量数据时,Redis也有许多优秀的解决方案。本文将介绍几种常见的Redis大数据处理方法,并给出相应的代码示例。 分布式存储Redis Cluster是Redis提…...
辉县网站建设/seo网站内部优化
资深敏捷专家Lisa Crispin在最近的讲座和参与合著的《Agile Testing – A Practical Guide for Testers and Agile Teams》中分享了敏捷软件测试的七个关键成功要素,包括使用团队整体参与的方法、采用敏捷测试思维、自动化回归测试、提供并获取反馈、构建核心实…...
徐州自助建站模板/山东进一步优化
不知道你是否有过这样的经历,导入一张位图为了去除某一张图背景,使用flash魔法棒工具那处理的效果不如在photoshop处理的效果好,这显然没有什么好比较的事情,flash的优势不在于处理位图而在于网络和动画方面的应用,而p…...