FFmpeg硬件解码

使用FFmpeg进行硬件解码时,通常需要结合FFmpeg的API和硬件加速API(如CUDA、VAAPI、DXVA2等)。以下是一个简单的C++代码示例,展示如何使用FFmpeg进行硬件解码。这个示例使用了CUDA作为硬件加速的后端。

1. 安装FFmpeg和CUDA

确保你已经安装了FFmpeg和CUDA,并且在编译时链接了相关的库。

2. 示例代码

cpp 复制代码
extern "C" {
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libavutil/hwcontext.h>
#include <libavutil/hwcontext_cuda.h>
}

#include <iostream>
#include <stdexcept>

void decode(AVCodecContext* codec_ctx, AVPacket* pkt, AVFrame* frame) {
    int ret = avcodec_send_packet(codec_ctx, pkt);
    if (ret < 0) {
        throw std::runtime_error("Error sending a packet for decoding");
    }

    while (ret >= 0) {
        ret = avcodec_receive_frame(codec_ctx, frame);
        if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
            return;
        } else if (ret < 0) {
            throw std::runtime_error("Error during decoding");
        }

        // 处理解码后的帧
        std::cout << "Frame decoded, width: " << frame->width << ", height: " << frame->height << std::endl;
    }
}

int main(int argc, char* argv[]) {
    if (argc < 2) {
        std::cerr << "Usage: " << argv[0] << " <input file>" << std::endl;
        return 1;
    }

    const char* filename = argv[1];

    av_register_all();
    avformat_network_init();

    AVFormatContext* format_ctx = nullptr;
    if (avformat_open_input(&format_ctx, filename, nullptr, nullptr) != 0) {
        std::cerr << "Could not open file " << filename << std::endl;
        return 1;
    }

    if (avformat_find_stream_info(format_ctx, nullptr) < 0) {
        std::cerr << "Could not find stream information" << std::endl;
        return 1;
    }

    int video_stream_index = -1;
    for (unsigned int i = 0; i < format_ctx->nb_streams; i++) {
        if (format_ctx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
            video_stream_index = i;
            break;
        }
    }

    if (video_stream_index == -1) {
        std::cerr << "Could not find a video stream" << std::endl;
        return 1;
    }

    AVCodecParameters* codecpar = format_ctx->streams[video_stream_index]->codecpar;
    AVCodec* codec = avcodec_find_decoder(codecpar->codec_id);
    if (!codec) {
        std::cerr << "Unsupported codec" << std::endl;
        return 1;
    }

    AVCodecContext* codec_ctx = avcodec_alloc_context3(codec);
    if (!codec_ctx) {
        std::cerr << "Could not allocate video codec context" << std::endl;
        return 1;
    }

    if (avcodec_parameters_to_context(codec_ctx, codecpar) < 0) {
        std::cerr << "Could not copy codec parameters to codec context" << std::endl;
        return 1;
    }

    // 设置硬件加速
    AVBufferRef* hw_device_ctx = nullptr;
    if (av_hwdevice_ctx_create(&hw_device_ctx, AV_HWDEVICE_TYPE_CUDA, nullptr, nullptr, 0) < 0) {
        std::cerr << "Failed to create CUDA hardware device context" << std::endl;
        return 1;
    }
    codec_ctx->hw_device_ctx = av_buffer_ref(hw_device_ctx);

    if (avcodec_open2(codec_ctx, codec, nullptr) < 0) {
        std::cerr << "Could not open codec" << std::endl;
        return 1;
    }

    AVPacket* pkt = av_packet_alloc();
    AVFrame* frame = av_frame_alloc();
    if (!pkt || !frame) {
        std::cerr << "Could not allocate packet or frame" << std::endl;
        return 1;
    }

    while (av_read_frame(format_ctx, pkt) >= 0) {
        if (pkt->stream_index == video_stream_index) {
            decode(codec_ctx, pkt, frame);
        }
        av_packet_unref(pkt);
    }

    // 刷新解码器
    decode(codec_ctx, nullptr, frame);

    av_frame_free(&frame);
    av_packet_free(&pkt);
    avcodec_free_context(&codec_ctx);
    avformat_close_input(&format_ctx);
    av_buffer_unref(&hw_device_ctx);

    return 0;
}

3. 编译命令

假设你已经安装了FFmpeg和CUDA,并且它们的库和头文件在标准路径中,你可以使用以下命令编译代码:

bash 复制代码
g++ -o hw_decode hw_decode.cpp -lavcodec -lavformat -lavutil -lavdevice -lswscale -lavfilter -lavresample -lcuda

4. 运行

编译成功后,你可以运行生成的可执行文件,并传入一个视频文件作为参数:

bash 复制代码
./hw_decode input.mp4

5. 注意事项

  • 这个示例使用了CUDA作为硬件加速的后端。如果你使用其他硬件加速API(如VAAPI、DXVA2等),你需要相应地修改代码。

  • 确保你的系统支持所选的硬件加速API,并且已经正确安装了相关的驱动和库。

  • 这个示例仅展示了基本的硬件解码流程,实际应用中可能需要处理更多的细节,例如帧格式转换、错误处理等。

最后展示是一个qt的demo

https://download.csdn.net/download/qq_42805085/90262623

相关推荐
ZouZou老师5 小时前
FFmpeg性能优化经典案例
性能优化·ffmpeg
aqi008 小时前
FFmpeg开发笔记(九十)采用FFmpeg套壳的音视频转码百宝箱FFBox
ffmpeg·音视频·直播·流媒体
齐齐大魔王10 小时前
FFmpeg
ffmpeg
你好音视频11 小时前
FFmpeg RTSP拉流流程深度解析
ffmpeg
IFTICing1 天前
【环境配置】ffmpeg下载、安装、配置(Windows环境)
windows·ffmpeg
haiy20111 天前
FFmpeg 编译
ffmpeg
aqi001 天前
FFmpeg开发笔记(八十九)基于FFmpeg的直播视频录制工具StreamCap
ffmpeg·音视频·直播·流媒体
八月的雨季 最後的冰吻1 天前
FFmepg--28- 滤镜处理 YUV 视频帧:实现上下镜像效果
ffmpeg·音视频
ganqiuye1 天前
向ffmpeg官方源码仓库提交patch
大数据·ffmpeg·video-codec
草明1 天前
ffmpeg 把 ts 转换成 mp3
ffmpeg