#include <stdio.h>
#include "FFmpegHWDecodeSample.h"
static AVBufferRef* hw_device_ctx = NULL;
static enum AVPixelFormat hw_pix_fmt;
static FILE* output_file = NULL;
/// 硬件加速初始化
static int hw_decoder_init(AVCodecContext* ctx, const enum AVHWDeviceType type)
{
int err = 0;
/// 创建一个硬件设备上下文
if ((err = av_hwdevice_ctx_create(&hw_device_ctx, type,
NULL, NULL, 0)) < 0) {
fprintf(stderr, "Failed to create specified HW device.\n");
return err;
}
ctx->hw_device_ctx = av_buffer_ref(hw_device_ctx);
return err;
}
/// 获取GPU硬件解码帧的格式
static enum AVPixelFormat get_hw_format(AVCodecContext* ctx,
const enum AVPixelFormat* pix_fmts)
{
const enum AVPixelFormat* p;
for (p = pix_fmts; *p != -1; p++) {
if (*p == hw_pix_fmt)
return *p;
}
fprintf(stderr, "Failed to get HW surface format.\n");
return AV_PIX_FMT_NONE;
}
/// 解码后数据格式转换,GPU到CPU拷贝,YUV数据dump到文件
static int decode_write(AVCodecContext* avctx, AVPacket* packet)
{
AVFrame* frame = NULL, * sw_frame = NULL;
AVFrame* tmp_frame = NULL;
uint8_t* buffer = NULL;
int size;
int ret = 0;
ret = avcodec_send_packet(avctx, packet);
if (ret < 0) {
fprintf(stderr, "Error during decoding\n");
return ret;
}
while (1) {
if (!(frame = av_frame_alloc()) || !(sw_frame = av_frame_alloc())) {
fprintf(stderr, "Can not alloc frame\n");
ret = AVERROR(ENOMEM);
goto fail;
}
ret = avcodec_receive_frame(avctx, frame);
if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
av_frame_free(&frame);
av_frame_free(&sw_frame);
return 0;
}
else if (ret < 0) {
fprintf(stderr, "Error while decoding\n");
goto fail;
}
if (frame->format == hw_pix_fmt) {
/// 将解码后的数据从GPU内存存格式转为CPU内存格式,并完成GPU到CPU内存的拷贝
if ((ret = av_hwframe_transfer_data(sw_frame, frame, 0)) < 0) {
fprintf(stderr, "Error transferring the data to system memory\n");
goto fail;
}
tmp_frame = sw_frame;
}
else
tmp_frame = frame;
///计算一张YUV图需要的内存 大小
size = av_image_get_buffer_size((AVPixelFormat)tmp_frame->format, tmp_frame->width,
tmp_frame->height, 1);
///分配内存
buffer = (uint8_t *)av_malloc(size);
if (!buffer) {
fprintf(stderr, "Can not alloc buffer\n");
ret = AVERROR(ENOMEM);
goto fail;
}
///将图片数据拷贝的buffer中(按行拷贝)
ret = av_image_copy_to_buffer(buffer, size,
(const uint8_t* const*)tmp_frame->data,
(const int*)tmp_frame->linesize, (AVPixelFormat)tmp_frame->format,
tmp_frame->width, tmp_frame->height, 1);
if (ret < 0) {
fprintf(stderr, "Can not copy image to buffer\n");
goto fail;
}
///buffer数据dump到文件
if ((ret = fwrite(buffer, 1, size, output_file)) < 0) {
fprintf(stderr, "Failed to dump raw data.\n");
goto fail;
}
fail:
av_frame_free(&frame);
av_frame_free(&sw_frame);
av_freep(&buffer);
if (ret < 0)
return ret;
}
}
int main(int argc,char * argv[])
{
AVFormatContext* input_ctx = NULL;
int video_stream, ret;
AVStream* video = NULL;
AVCodecContext* decoder_ctx = NULL;
AVCodec* decoder = NULL;
AVPacket packet;
enum AVHWDeviceType type;
int i;
if (argc < 4) {
fprintf(stderr, "Usage: %s <device type> <input file> <output file>\n", argv[0]);
return -1;
}
/// 设备类型为:cuda dxva2 qsv d3d11va opencl,通常在windows使用d3d11va或者dxva2
type = av_hwdevice_find_type_by_name(argv[1]); ///根据设备名找到设备类型
if (type == AV_HWDEVICE_TYPE_NONE) {
fprintf(stderr, "Device type %s is not supported.\n", argv[1]);
fprintf(stderr, "Available device types:");
while ((type = av_hwdevice_iterate_types(type)) != AV_HWDEVICE_TYPE_NONE)
fprintf(stderr, " %s", av_hwdevice_get_type_name(type));
fprintf(stderr, "\n");
return -1;
}
/// open the input file
if (avformat_open_input(&input_ctx, argv[2], NULL, NULL) != 0) {
fprintf(stderr, "Cannot open input file '%s'\n", argv[2]);
return -1;
}
if (avformat_find_stream_info(input_ctx, NULL) < 0) {
fprintf(stderr, "Cannot find input stream information.\n");
return -1;
}
/// find the video stream information
ret = av_find_best_stream(input_ctx, AVMEDIA_TYPE_VIDEO, -1, -1, &decoder, 0);
if (ret < 0) {
fprintf(stderr, "Cannot find a video stream in the input file\n");
return -1;
}
video_stream = ret;
///查找到对应硬件类型解码后的数据格式
for (i = 0;; i++) {
const AVCodecHWConfig* config = avcodec_get_hw_config(decoder, i);
if (!config) {
fprintf(stderr, "Decoder %s does not support device type %s.\n",
decoder->name, av_hwdevice_get_type_name(type));
return -1;
}
if (config->methods & AV_CODEC_HW_CONFIG_METHOD_HW_DEVICE_CTX &&
config->device_type == type) {
hw_pix_fmt = config->pix_fmt;
break;
}
}
if (!(decoder_ctx = avcodec_alloc_context3(decoder)))
return AVERROR(ENOMEM);
video = input_ctx->streams[video_stream];
if (avcodec_parameters_to_context(decoder_ctx, video->codecpar) < 0)
return -1;
decoder_ctx->get_format = get_hw_format;
///硬件加速初始化
if (hw_decoder_init(decoder_ctx, type) < 0)
return -1;
if ((ret = avcodec_open2(decoder_ctx, decoder, NULL)) < 0) {
fprintf(stderr, "Failed to open codec for stream #%u\n", video_stream);
return -1;
}
/// open the file to dump raw data
output_file = fopen(argv[3], "w+b");
/// actual decoding and dump the raw data
while (ret >= 0) {
if ((ret = av_read_frame(input_ctx, &packet)) < 0)
break;
if (video_stream == packet.stream_index)
ret = decode_write(decoder_ctx, &packet); ///解码并dump文件
av_packet_unref(&packet);
}
/// flush the decoder
packet.data = NULL;
packet.size = 0;
ret = decode_write(decoder_ctx, &packet);
av_packet_unref(&packet);
if (output_file)
fclose(output_file);
avcodec_free_context(&decoder_ctx);
avformat_close_input(&input_ctx);
av_buffer_unref(&hw_device_ctx);
return 0;
}
没有合适的资源?快使用搜索试试~ 我知道了~
基于ffmpeg实现硬件解码功能
共309个文件
h:231个
dll:16个
lib:16个
1星 需积分: 0 58 下载量 115 浏览量
2022-03-17
14:40:26
上传
评论 5
收藏 38.11MB RAR 举报
温馨提示
基于ffmpeg实现硬件解码,支持cuda/dxva2/qsv/d3dllva/opencl类型GPU设备。资源包括完成的vs工程代码,解压后可直接编译运行,依赖的ffmpeg开发包也在资源包中。
资源详情
资源评论
资源推荐
收起资源包目录
基于ffmpeg实现硬件解码功能 (309个子文件)
libavcodec.dll.a 866KB
libavcodec.dll.a 847KB
libavdevice.dll.a 445KB
libavdevice.dll.a 434KB
libavutil.dll.a 341KB
libavutil.dll.a 333KB
libavformat.dll.a 138KB
libavformat.dll.a 134KB
libavfilter.dll.a 47KB
libavfilter.dll.a 46KB
libswscale.dll.a 22KB
libswscale.dll.a 22KB
libswresample.dll.a 15KB
libswresample.dll.a 15KB
libpostproc.dll.a 7KB
libpostproc.dll.a 7KB
FFmpegHWDecodeSample.cpp 6KB
avutil-56.def 12KB
avutil-56.def 12KB
avcodec-58.def 6KB
avcodec-58.def 6KB
avformat-58.def 4KB
avformat-58.def 4KB
avfilter-7.def 2KB
avfilter-7.def 2KB
swscale-5.def 756B
swscale-5.def 756B
avdevice-58.def 544B
avdevice-58.def 544B
swresample-3.def 473B
swresample-3.def 473B
postproc-55.def 223B
postproc-55.def 223B
avcodec-58.dll 44.81MB
avcodec-58.dll 32.66MB
avformat-58.dll 9.84MB
avformat-58.dll 9.45MB
avfilter-7.dll 7.47MB
avfilter-7.dll 7.02MB
avdevice-58.dll 2.51MB
avdevice-58.dll 1.37MB
avutil-56.dll 775KB
avutil-56.dll 763KB
swscale-5.dll 532KB
swscale-5.dll 507KB
swresample-3.dll 419KB
swresample-3.dll 310KB
postproc-55.dll 132KB
postproc-55.dll 122KB
ffmpeg.exe 289KB
ffmpeg.exe 287KB
ffprobe.exe 170KB
ffprobe.exe 163KB
ffplay.exe 150KB
ffplay.exe 145KB
TestFFMpeg.exe 69KB
TestFFMpeg.exe 52KB
FFmpegHWDecodeSample.vcxproj.filters 1KB
avcodec.h 209KB
avcodec.h 209KB
avformat.h 116KB
avformat.h 116KB
avfilter.h 41KB
avfilter.h 41KB
opt.h 35KB
opt.h 35KB
pixfmt.h 33KB
pixfmt.h 33KB
frame.h 32KB
frame.h 32KB
avio.h 31KB
avio.h 31KB
mem.h 23KB
mem.h 23KB
hwcontext.h 22KB
hwcontext.h 22KB
swresample.h 21KB
swresample.h 21KB
intreadwrite.h 18KB
intreadwrite.h 18KB
avdevice.h 17KB
avdevice.h 17KB
common.h 16KB
common.h 16KB
pixdesc.h 16KB
pixdesc.h 16KB
avstring.h 14KB
avstring.h 14KB
hdr_dynamic_metadata.h 12KB
hdr_dynamic_metadata.h 12KB
swscale.h 12KB
swscale.h 12KB
imgutils.h 11KB
imgutils.h 11KB
log.h 11KB
log.h 11KB
buffer.h 10KB
buffer.h 10KB
samplefmt.h 10KB
samplefmt.h 10KB
共 309 条
- 1
- 2
- 3
- 4
小雷子
- 粉丝: 8
- 资源: 5
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功
评论2