网站开发项目报告,孙红雷做的二手车网站,廊坊企业做网站,一键生成广告图FFmpeg是一款强大的多媒体处理工具#xff0c;支持软件和硬件解码。软件解码利用CPU执行解码过程#xff0c;适用于各种平台#xff0c;但可能对性能要求较高。硬件解码则利用GPU或其他专用硬件加速解码#xff0c;能显著降低CPU负载#xff0c;提升解码效率和能效。FFmpe…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 memoryclass 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::coutavcodec_find_decoder Failedstd::endl;return -1;}pParseCtx_ av_parser_init(pCodec_-id);if (!pParseCtx_) {std::coutav_parser_init Failedstd::endl;return -1;}pDecodeCtx_ avcodec_alloc_context3(pCodec_);if (!pDecodeCtx_) {std::coutavcodec_alloc_context3 Failedstd::endl;return -1;}pDecodeCtx_-pix_fmt (AVPixelFormat)PixFmt;if (avcodec_open2(pDecodeCtx_, pCodec_, nullptr) 0) {std::coutavcodec_open2 Failedstd::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::coutUnKnown HW Device Typestd::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) {coutCannot find a video stream in the input fileendl;return -1;}for (int i 0; ; i) {const AVCodecHWConfig *config avcodec_get_hw_config(pCodec_, i);if (!config) {coutavcodec_get_hw_config Failediendl;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_) {coutavcodec_alloc_context3 Failedendl;return -1;}pVStream_ input_ctx-streams[video_index];if (avcodec_parameters_to_context(pDecodeCtx_, pVStream_-codecpar) 0) {coutavcodec_parameters_to_context Failedendl;return -1;}pDecodeCtx_-get_format get_hw_format;if (hw_decoder_init(pDecodeCtx_, type) 0) {return -1;}if (avcodec_open2(pDecodeCtx_, pCodec_, nullptr) 0) {coutavcodec_open2 Failedendl;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) {coutError sending a packet for decodingendl;return -1;}nRet avcodec_receive_frame(pDecodeCtx_, frame); //从解码器中获取被解码后的帧数据AVFrameif (nRet AVERROR(EAGAIN) || nRet AVERROR_EOF)return 0;else if (nRet 0) {coutError during decodingendl;return -1;}return 0;} else { //硬解码AVFrame* tmpFrame nullptr, *swFrame nullptr;int nRet avcodec_send_packet(pDecodeCtx_, packet); //将AVPacket发送至解码器中if (nRet 0) {coutError sending a packet for decodingendl;av_frame_free(tmpFrame);av_frame_free(swFrame);return -1;}if (!(tmpFrame av_frame_alloc()) || !(swFrame av_frame_alloc())) {coutCan not alloc frameendl;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) {coutError while decodingendl;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) {coutError transferring the data to system memoryendl;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有问题欢迎指正。