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

FFmpeg使用GPU编解码,及在C++代码中实现FFmpeg使用GPU编解码

一.使用 GPU 进行编解码的常见方法

FFmpeg 是一个强大的多媒体处理工具,支持使用 GPU 进行编解码以加速视频处理。以下是使用 GPU 进行编解码的常见方法:

1. 使用 NVIDIA GPU(通过 NVENC/NVDEC)

NVIDIA 提供了 NVENC(编码)和 NVDEC(解码)硬件加速。

安装支持 GPU 的 FFmpeg

确保安装了支持 NVIDIA 的 FFmpeg 版本,可以通过编译 FFmpeg 时启用 --enable-nvenc--enable-cuda 选项。

常用命令
  • 编码(使用 NVENC)

    ffmpeg -i input.mp4 -c:v h264_nvenc -b:v 5M output.mp4
    

    其中 h264_nvenc 是 H.264 编码器,-b:v 指定视频比特率。

  • 解码(使用 NVDEC)

    ffmpeg -hwaccel cuda -i input.mp4 -c:v h264_nvenc output.mp4
    

    -hwaccel cuda 启用 CUDA 硬件加速解码。

2. 使用 AMD GPU(通过 AMF)

AMD 提供了 AMF(Advanced Media Framework)用于硬件加速。

安装支持 AMF 的 FFmpeg

编译 FFmpeg 时启用 --enable-amf 选项。

常用命令
  • 编码(使用 AMF)
    ffmpeg -i input.mp4 -c:v h264_amf -b:v 5M output.mp4
    
    h264_amf 是 H.264 编码器。

3. 使用 Intel GPU(通过 Quick Sync Video)

Intel 的 Quick Sync Video(QSV)提供硬件加速。

安装支持 QSV 的 FFmpeg

编译 FFmpeg 时启用 --enable-libmfx 选项。

常用命令
  • 编码(使用 QSV)
    ffmpeg -i input.mp4 -c:v h264_qsv -b:v 5M output.mp4
    
    h264_qsv 是 H.264 编码器。

4. 使用 VAAPI(适用于 Intel 和 AMD GPU)

VAAPI 是一种通用的硬件加速 API,支持 Intel 和 AMD GPU。

安装支持 VAAPI 的 FFmpeg

编译 FFmpeg 时启用 --enable-vaapi 选项。

常用命令
  • 编码(使用 VAAPI)
    ffmpeg -vaapi_device /dev/dri/renderD128 -i input.mp4 -vf 'format=nv12,hwupload' -c:v h264_vaapi -b:v 5M output.mp4
    
    -vaapi_device 指定 VAAPI 设备,-vf 指定视频滤镜。

5. 使用 OpenCL

FFmpeg 也支持通过 OpenCL 进行 GPU 加速。

安装支持 OpenCL 的 FFmpeg

编译 FFmpeg 时启用 --enable-opencl 选项。

常用命令
  • 使用 OpenCL 进行滤镜处理
    ffmpeg -i input.mp4 -vf "hwupload, hwmap, overlay_opencl=10:10, hwmap" output.mp4
    

总结

  • NVIDIA GPU:使用 NVENC/NVDEC,命令如 h264_nvenc
  • AMD GPU:使用 AMF,命令如 h264_amf
  • Intel GPU:使用 QSV 或 VAAPI,命令如 h264_qsvh264_vaapi
  • OpenCL:适用于通用 GPU 加速。

确保硬件和驱动支持相应的编解码器,并根据需要编译 FFmpeg。

二.在C++代码中实现FFmpeg使用GPU编解码

在 C++ 中使用 FFmpeg 进行 GPU 编解码需要结合 FFmpeg 的 API 和 GPU 相关的硬件加速 API(如 NVIDIA 的 NVENC/NVDEC、AMD 的 AMF、Intel 的 QSV 等)。以下是一个简单的示例,展示如何使用 FFmpeg 的 API 结合 NVIDIA 的 NVENC/NVDEC 进行 GPU 编解码。

环境准备

  1. 安装 FFmpeg:确保安装了支持 GPU 加速的 FFmpeg 版本。
  2. 安装 NVIDIA 驱动和 CUDA:确保安装了最新的 NVIDIA 驱动和 CUDA 工具包。
  3. 编译 FFmpeg:编译 FFmpeg 时启用 --enable-nvenc--enable-cuda 选项。

示例代码

以下是一个简单的 C++ 示例,使用 FFmpeg 和 NVENC/NVDEC 进行 GPU 编解码。

extern "C" {
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libavutil/opt.h>
#include <libavutil/hwcontext.h>
#include <libavutil/hwcontext_cuda.h>
}

#include <iostream>
#include <stdexcept>

void encode(AVCodecContext* enc_ctx, AVFrame* frame, AVPacket* pkt, FILE* outfile) {
    int ret = avcodec_send_frame(enc_ctx, frame);
    if (ret < 0) {
        throw std::runtime_error("Error sending frame to encoder");
    }

    while (ret >= 0) {
        ret = avcodec_receive_packet(enc_ctx, pkt);
        if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
            return;
        } else if (ret < 0) {
            throw std::runtime_error("Error encoding frame");
        }

        fwrite(pkt->data, 1, pkt->size, outfile);
        av_packet_unref(pkt);
    }
}

int main() {
    av_register_all();
    avcodec_register_all();

    const char* filename = "output.h264";
    FILE* outfile = fopen(filename, "wb");
    if (!outfile) {
        std::cerr << "Could not open " << filename << std::endl;
        return 1;
    }

    const AVCodec* codec = avcodec_find_encoder_by_name("h264_nvenc");
    if (!codec) {
        std::cerr << "Codec h264_nvenc not found" << std::endl;
        return 1;
    }

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

    c->bit_rate = 400000;
    c->width = 640;
    c->height = 480;
    c->time_base = (AVRational){1, 25};
    c->framerate = (AVRational){25, 1};
    c->gop_size = 10;
    c->max_b_frames = 1;
    c->pix_fmt = AV_PIX_FMT_CUDA;

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

    AVFrame* frame = av_frame_alloc();
    if (!frame) {
        std::cerr << "Could not allocate video frame" << std::endl;
        return 1;
    }

    frame->format = c->pix_fmt;
    frame->width = c->width;
    frame->height = c->height;

    if (av_frame_get_buffer(frame, 0) < 0) {
        std::cerr << "Could not allocate the video frame data" << std::endl;
        return 1;
    }

    AVPacket* pkt = av_packet_alloc();
    if (!pkt) {
        std::cerr << "Could not allocate AVPacket" << std::endl;
        return 1;
    }

    for (int i = 0; i < 100; i++) {
        av_frame_make_writable(frame);

        // Fill frame with test pattern
        for (int y = 0; y < c->height; y++) {
            for (int x = 0; x < c->width; x++) {
                frame->data[0][y * frame->linesize[0] + x] = x + y + i * 3;
            }
        }

        frame->pts = i;

        encode(c, frame, pkt, outfile);
    }

    encode(c, NULL, pkt, outfile);

    fclose(outfile);

    avcodec_free_context(&c);
    av_frame_free(&frame);
    av_packet_free(&pkt);

    return 0;
}

代码说明

  1. 初始化 FFmpeg:调用 av_register_all()avcodec_register_all() 初始化 FFmpeg。
  2. 查找编码器:使用 avcodec_find_encoder_by_name("h264_nvenc") 查找 NVIDIA 的 H.264 编码器。
  3. 设置编码器参数:设置编码器的宽度、高度、比特率、帧率等参数。
  4. 分配帧和包:使用 av_frame_alloc()av_packet_alloc() 分配帧和包。
  5. 编码帧:使用 avcodec_send_frame()avcodec_receive_packet() 进行编码。
  6. 释放资源:编码完成后,释放编码器上下文、帧和包。

编译和运行

编译时需要链接 FFmpeg 的相关库。例如:

g++ -o gpu_encode gpu_encode.cpp -lavcodec -lavformat -lavutil -lswscale

运行生成的可执行文件,将会生成一个 H.264 编码的视频文件 output.h264

注意事项

  • 确保系统支持 NVIDIA 的 NVENC/NVDEC。
  • 根据实际需求调整编码器参数。
  • 如果需要解码,可以使用 h264_cuvid 解码器,并设置 AVCodecContexthw_device_ctx 为 CUDA 设备上下文。

通过这种方式,你可以在 C++ 中使用 FFmpeg 和 GPU 进行高效的视频编解码。


http://www.kler.cn/a/536664.html

相关文章:

  • 软件设计模式
  • 全面解析String类
  • Docker安装pypiserver私服
  • .net的一些知识点6
  • vite共享配置之---css相关
  • Ubuntu部署Deepseek-R1模型(8b)
  • C# LINQ与集合类 数据操作
  • postgresql-15(yum安装教程)
  • 让文物“活”起来,以3D数字化技术传承文物历史文化!
  • [RabbitMQ] 常见面试题汇总 工作流程 消息可靠性 消息顺序性 幂等性 高级特性 延迟队列 仲裁队列 工作模式 消息积压 推拉模式
  • easyxor
  • 赛博算命之 ”梅花易数“ 的 “JAVA“ 实现 ——从玄学到科学的探索
  • element-ui rate 组件源码分享
  • zsh: command not found: pip
  • Android Studio:键值对存储sharedPreferences
  • unity视频在场景中的使用
  • APP广告变现如何优化广告填充率,提升变现收益?
  • Mysql知识梳理(数据库的锁梳理,Mysql优化)
  • 回溯算法中关于剪枝的一些应用
  • PHP PDO 教程
  • 【Elasticsearch】date range聚合
  • 安卓/ios脚本开发按键精灵经验小分享
  • .net一些知识点5
  • VMware下Linux和macOS安装VSCode一些总结
  • 2025 IT职业发展方向及推荐
  • 基于SpringBoot养老院平台系统功能实现六