当前位置: 首页 > news >正文

深入理解FFmpeg--软/硬件解码流程

FFmpeg是一款强大的多媒体处理工具,支持软件和硬件解码。软件解码利用CPU执行解码过程,适用于各种平台,但可能对性能要求较高。硬件解码则利用GPU或其他专用硬件加速解码,能显著降低CPU负载,提升解码效率和能效。FFmpeg结合这两种解码方式,提供了灵活的多媒体解决方案,适合于视频处理、流媒体和多媒体应用开发。

1、FFmpeg支持多种硬件加速类型,用于编解码视频,以提升性能和效率。以下是FFmpeg支持的主要硬件加速类型:

  1. NVIDIA NVENC/NVDEC:利用NVIDIA显卡进行视频编码(NVENC)和解码(NVDEC)。
  2. Intel Quick Sync Video (QSV):利用Intel处理器中的集成图形进行视频加速。
  3. AMD Video Coding Engine (VCE)和Video Decoding Acceleration (VDA):利用AMD显卡进行视频编码和解码。
  4. VAAPI (Video Acceleration API):适用于Intel和AMD硬件,通过通用的API接口进行硬件加速。
  5. VDPAU (Video Decode and Presentation API for Unix):主要用于NVIDIA显卡的硬件解码加速。
  6. DXVA2 (DirectX Video Acceleration):适用于Windows平台,利用DirectX进行视频加速。
  7. OpenMAX IL (Open Media Acceleration Integration Layer):用于移动设备和嵌入式系统的视频加速。
  8. 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是一款强大的多媒体处理工具&#xff0c;支持软件和硬件解码。软件解码利用CPU执行解码过程&#xff0c;适用于各种平台&#xff0c;但可能对性能要求较高。硬件解码则利用GPU或其他专用硬件加速解码&#xff0c;能显著降低CPU负载&#xff0c;提升解码效率和能效。FFmpe…...

新的铸造厂通过 PROFIBUS 技术实现完全自动化

钢铁生产商某钢以其在厚钢板类别中极高的产品质量而闻名。其原材料&#xff08;板坯连铸机&#xff09;在钢铁厂本地生产&#xff0c;该厂最近新建了一座垂直连铸厂。该项目的一个主要目标是从一开始就完全自动化这座新工厂和整个铸造过程&#xff0c;以高成本效率实现最佳产品…...

【UE5.1】NPC人工智能——04 NPC巡逻

效果 步骤 一、准备行为树和黑板 1. 对我们之前创建的AI控制器创建一个子蓝图类 这里命名为“BP_NPC_AIController_Lion”&#xff0c;表示专门用于控制狮子的AI控制器 2. 打开狮子蓝图“Character_Lion” 在类默认值中将“AI控制器类”修改为“BP_NPC_AIController_Lion” 3…...

计算机视觉主流框架及其应用方向

文章目录 前言一、计算机视觉领域的主要框架1、深度学习框架1.1、TensorFlow1.2、PyTorch 2、神经网络模型2.1、卷积神经网络&#xff08;CNN&#xff09;2.2、循环神经网络&#xff08;RNN&#xff09; 二、框架在计算机视觉任务中的应用1、TensorFlow1.1、概述&#xff1a;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)

由北京航空航天大学指导&#xff0c;北京航空航天大学自动化科学与电气工程学院主办&#xff0c;AEIC学术交流中心承办的第三届智能机械与人机交互技术学术会议&#xff08;IHCIT 2024&#xff09;将定于2024年7月27日于中国杭州召开。 大会面向基础与前沿、学科与产业&#xf…...

深入浅出WebRTC—NACK

WebRTC 中的 NACK&#xff08;Negative Acknowledgment&#xff09;机制是实时通信中处理网络丢包的关键组件。网络丢包是常见的现象&#xff0c;尤其是在无线网络或不稳定连接中。NACK 机制旨在通过请求重传丢失的数据包来减少这种影响&#xff0c;从而保持通信的连续性和质量…...

简单工厂模式、工厂模式和抽象工厂模式的区别

简单工厂模式、工厂模式和抽象工厂模式都是创建型设计模式&#xff0c;它们之间在目的、实现方式和适用场景上存在显著的区别。以下是对这三种模式的详细比较&#xff1a; 一、定义与目的 简单工厂模式&#xff08;Simple Factory Pattern&#xff09; 定义&#xff1a; 简单工…...

JVM-垃圾回收与内存分配

目录 垃圾收集器与内存分配策略 引用 对象的访问方式有哪些?&#xff08;句柄和直接指针&#xff09; Java的引用有哪些类型? 如何判断对象是否是垃圾? 请列举一些可作为GC Roots的对象? 对象头了解吗? mark word&#xff08;hashcode、分代、锁标志位&#xff09;、…...

Jolt路线图

1. 引言 a16z crypto团队2024年7月更新了其Jolt路线图&#xff1a; 主要分为3大维度&#xff1a; 1&#xff09;链上验证维度&#xff1a; 1.1&#xff09;Zeromorph&#xff1a;见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”的文章。 以下为个人解析&#xff0c;非官方公开标准资料&#xff0c;可能有误&#xff0c;仅供参考。&#xff08;单词解释…...

docker 部署wechatbot-webhook 并获取接口实现微信群图片自动保存到chevereto图库等

功能如图&#xff1a; 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 固件之前&#xff0c;建议进行以下准备&#xff1a; 1、不要急于安装&#xff0c;慢慢来。如果在安装过程中出现奇怪之处&#xff0c;请先找到答案&#xff0c;然后再继续。 2、准备好设备的精确型号&#xff0c;以便能够选择正确的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使用教程(七)——期权相关操作

期权交易 可点击证券代码右侧的选&#xff0c;进入期权选择菜单。通过选择标的商品&#xff0c;认购期权和认沽期权中间的选项&#xff08;包括代码、成交价、幅度%、隐波%、内在价值、时间价值等&#xff09;&#xff0c;以及认购期权或认沽期权&#xff0c;选择所需的期权标的…...

TeamViewer关闭访问密码或固定一组密码不变

TeamViewer的新UI界面变化较大&#xff0c;网上的一些信息已经不再有效&#xff0c;更新后的访问密码在如下图所示&#xff1a; 演示的版本为7.21.4—— 设置每次你的设备访问的密码...

iMazing 3 换手机后苹果游戏数据还有吗 换iPhone怎么转移游戏数据

当你想要更换手机&#xff0c;无论是选择升级到最新款iPhone&#xff0c;或者换到“经典”旧款iPhone&#xff0c;单机游戏数据的转移总是让人发愁。本文将详细介绍换手机后苹果游戏数据还有吗&#xff0c;以及换iPhone怎么转移游戏数据&#xff0c;确保你能无缝继续你的游戏体…...

正则表达式:电子邮件地址的格式详解,及常见正则表达式符号的详细解释和匹配方式

一、第一部分是对该段电子邮件的详解 var Regex /^(?:\w\.?)*\w(?:\w\.)*\w$/; 1.^&#xff1a;这个符号表示匹配输入字符串的开始位置。 2.(?:...)&#xff1a;这是一个非捕获组&#xff08;non-capturing group&#xff09;&#xff0c;用于将正则表达式的一部分组合在…...

AWS全服务历史年表:发布日期、GA和服务概述一览(一)

我一直在尝试从各种角度撰写关于Amazon Web Services&#xff08;AWS&#xff09;的信息和魅力。由于我喜欢技术历史&#xff0c;这次我总结了AWS服务发布的历史年表。 虽然AWS官方也通过“Whats New”发布了官方公告&#xff0c;但我一直希望能有一篇文章将公告日期、GA日期&…...

现场可重构CPLD芯片应用案例—蓝牙音箱

我司英尚微提供的高性能数模混合现场可重构IC、通用可配置的模数混合芯片内部集成丰富的模拟资源和数字资源&#xff0c;可轻松替代电路中的各种标准器件&#xff0c;并按照客户要求组合成最优小型ASIC&#xff0c;缩短开发周期&#xff0c;降低成本。下面介绍LS98002现场可重构…...

利用最小二乘法找圆心和半径

#include <iostream> #include <vector> #include <cmath> #include <Eigen/Dense> // 需安装Eigen库用于矩阵运算 // 定义点结构 struct Point { double x, y; Point(double x_, double y_) : x(x_), y(y_) {} }; // 最小二乘法求圆心和半径 …...

rknn优化教程(二)

文章目录 1. 前述2. 三方库的封装2.1 xrepo中的库2.2 xrepo之外的库2.2.1 opencv2.2.2 rknnrt2.2.3 spdlog 3. rknn_engine库 1. 前述 OK&#xff0c;开始写第二篇的内容了。这篇博客主要能写一下&#xff1a; 如何给一些三方库按照xmake方式进行封装&#xff0c;供调用如何按…...

K8S认证|CKS题库+答案| 11. AppArmor

目录 11. AppArmor 免费获取并激活 CKA_v1.31_模拟系统 题目 开始操作&#xff1a; 1&#xff09;、切换集群 2&#xff09;、切换节点 3&#xff09;、切换到 apparmor 的目录 4&#xff09;、执行 apparmor 策略模块 5&#xff09;、修改 pod 文件 6&#xff09;、…...

最新SpringBoot+SpringCloud+Nacos微服务框架分享

文章目录 前言一、服务规划二、架构核心1.cloud的pom2.gateway的异常handler3.gateway的filter4、admin的pom5、admin的登录核心 三、code-helper分享总结 前言 最近有个活蛮赶的&#xff0c;根据Excel列的需求预估的工时直接打骨折&#xff0c;不要问我为什么&#xff0c;主要…...

智能在线客服平台:数字化时代企业连接用户的 AI 中枢

随着互联网技术的飞速发展&#xff0c;消费者期望能够随时随地与企业进行交流。在线客服平台作为连接企业与客户的重要桥梁&#xff0c;不仅优化了客户体验&#xff0c;还提升了企业的服务效率和市场竞争力。本文将探讨在线客服平台的重要性、技术进展、实际应用&#xff0c;并…...

【快手拥抱开源】通过快手团队开源的 KwaiCoder-AutoThink-preview 解锁大语言模型的潜力

引言&#xff1a; 在人工智能快速发展的浪潮中&#xff0c;快手Kwaipilot团队推出的 KwaiCoder-AutoThink-preview 具有里程碑意义——这是首个公开的AutoThink大语言模型&#xff08;LLM&#xff09;。该模型代表着该领域的重大突破&#xff0c;通过独特方式融合思考与非思考…...

是否存在路径(FIFOBB算法)

题目描述 一个具有 n 个顶点e条边的无向图&#xff0c;该图顶点的编号依次为0到n-1且不存在顶点与自身相连的边。请使用FIFOBB算法编写程序&#xff0c;确定是否存在从顶点 source到顶点 destination的路径。 输入 第一行两个整数&#xff0c;分别表示n 和 e 的值&#xff08;1…...

以光量子为例,详解量子获取方式

光量子技术获取量子比特可在室温下进行。该方式有望通过与名为硅光子学&#xff08;silicon photonics&#xff09;的光波导&#xff08;optical waveguide&#xff09;芯片制造技术和光纤等光通信技术相结合来实现量子计算机。量子力学中&#xff0c;光既是波又是粒子。光子本…...

多模态图像修复系统:基于深度学习的图片修复实现

多模态图像修复系统:基于深度学习的图片修复实现 1. 系统概述 本系统使用多模态大模型(Stable Diffusion Inpainting)实现图像修复功能,结合文本描述和图片输入,对指定区域进行内容修复。系统包含完整的数据处理、模型训练、推理部署流程。 import torch import numpy …...

Xela矩阵三轴触觉传感器的工作原理解析与应用场景

Xela矩阵三轴触觉传感器通过先进技术模拟人类触觉感知&#xff0c;帮助设备实现精确的力测量与位移监测。其核心功能基于磁性三维力测量与空间位移测量&#xff0c;能够捕捉多维触觉信息。该传感器的设计不仅提升了触觉感知的精度&#xff0c;还为机器人、医疗设备和制造业的智…...