ffmpeg库视频硬编码使用流程

一、硬件编码核心流程

  1. 硬件设备初始化

    // 创建CUDA硬件设备上下文‌
    AVBufferRef *hw_device_ctx = NULL;
    av_hwdevice_ctx_create(&hw_device_ctx, AV_HWDEVICE_TYPE_CUDA, NULL, NULL, 0);// 绑定硬件设备到编码器上下文‌
    codec_ctx->hw_device_ctx = av_buffer_ref(hw_device_ctx);
  2. 编码器选择与参数配置

    // 查找NVIDIA H.264硬件编码器‌
    const AVCodec *encoder = avcodec_find_encoder_by_name("h264_nvenc");// 设置编码参数(分辨率、码率、GOP等)‌
    codec_ctx->width = 1920;
    codec_ctx->height = 1080;
    codec_ctx->bit_rate = 5000000;
    codec_ctx->time_base = (AVRational){1, 30};
    codec_ctx->pix_fmt = AV_PIX_FMT_CUDA;  // 指定硬件像素格式‌// 设置编码预设参数(NVIDIA专用)‌
    av_opt_set(codec_ctx->priv_data, "preset", "llhp", 0);  // 低延迟高性能
  3. 硬件帧内存分配

    // 创建硬件帧并绑定GPU内存‌
    AVFrame *hw_frame = av_frame_alloc();
    hw_frame->format = codec_ctx->pix_fmt;
    hw_frame->width = codec_ctx->width;
    hw_frame->height = codec_ctx->height;
    av_hwframe_get_buffer(codec_ctx->hw_frames_ctx, hw_frame, 0);
  4. 编码数据流处理

    // 送入硬件编码器‌
    avcodec_send_frame(codec_ctx, hw_frame);// 接收编码后的数据包
    AVPacket *pkt = av_packet_alloc();
    while (avcodec_receive_packet(codec_ctx, pkt) >= 0) {av_interleaved_write_frame(output_ctx, pkt);  // 写入输出文件‌av_packet_unref(pkt);
    }

二、跨平台适配示例

硬件平台编码器名称像素格式初始化函数
NVIDIA GPUh264_nvencAV_PIX_FMT_CUDAav_hwdevice_ctx_create(..., AV_HWDEVICE_TYPE_CUDA)
Intel QSVh264_qsvAV_PIX_FMT_QSVav_hwdevice_ctx_create(..., AV_HWDEVICE_TYPE_QSV)
AMD AMFh264_amfAV_PIX_FMT_D3D11av_hwdevice_ctx_create(..., AV_HWDEVICE_TYPE_D3D11VA)

三、关键问题解决

  1. 编码器初始化失败

    • 检查FFmpeg编译时是否启用对应硬件加速选项(如--enable-nvenc--enable-libmfx)‌
    • 确认硬件驱动版本与FFmpeg兼容性‌
  2. CPU-GPU内存拷贝开销优化

    // 使用hwupload滤镜直接上传数据至GPU‌
    AVFilterContext *upload_filter;
    const AVFilter *hwupload = avfilter_get_by_name("hwupload");
    avfilter_graph_create_filter(&upload_filter, hwupload, "upload", NULL, NULL, filter_graph);

 ‌四、资源释放

av_buffer_unref(&hw_device_ctx);  // 释放硬件设备上下文‌
avcodec_free_context(&codec_ctx);  // 释放编码器上下文
av_frame_free(&hw_frame);          // 释放硬件帧
av_packet_free(&pkt);              // 释放数据包

五、编译依赖

  • NVIDIA平台‌:需安装CUDA Toolkit,编译时添加--enable-cuda --enable-nvenc
  • Intel平台‌:需安装Intel Media SDK,编译时添加--enable-libmfx

六、硬件编码示例代码

支持从本地YUV文件读取数据、GPU加速编码并输出H.264视频流到MP4文件。

#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libavutil/imgutils.h>
#include <libavutil/hwcontext.h>
#include <libswscale/swscale.h>#define INPUT_FILE "input.yuv"
#define OUTPUT_FILE "output.mp4"
#define WIDTH      1280
#define HEIGHT     720
#define FRAME_RATE 30int main() {AVFormatContext *fmt_ctx = NULL;AVCodecContext *enc_ctx = NULL;AVBufferRef *hw_device_ctx = NULL;SwsContext *sws_ctx = NULL;int ret = 0;// 1. 初始化硬件设备上下文ret = av_hwdevice_ctx_create(&hw_device_ctx, AV_HWDEVICE_TYPE_CUDA, NULL, NULL, 0);  // ‌:ml-citation{ref="1,3" data="citationList"}if (ret < 0) {fprintf(stderr, "Failed to create CUDA device\n");goto cleanup;}// 2. 打开输出文件并配置封装格式avformat_alloc_output_context2(&fmt_ctx, NULL, NULL, OUTPUT_FILE);  // ‌:ml-citation{ref="8" data="citationList"}if (!fmt_ctx) {fprintf(stderr, "Failed to create output context\n");ret = -1;goto cleanup;}// 3. 查找并配置硬件编码器const AVCodec *encoder = avcodec_find_encoder_by_name("h264_nvenc");  // ‌:ml-citation{ref="1,4" data="citationList"}if (!encoder) {fprintf(stderr, "NVENC encoder not found\n");ret = -1;goto cleanup;}enc_ctx = avcodec_alloc_context3(encoder);enc_ctx->width = WIDTH;enc_ctx->height = HEIGHT;enc_ctx->time_base = (AVRational){1, FRAME_RATE};enc_ctx->pix_fmt = AV_PIX_FMT_CUDA;       // 硬件像素格式 ‌:ml-citation{ref="3,5" data="citationList"}enc_ctx->bit_rate = 4000000;              // 4Mbps码率 ‌:ml-citation{ref="5,8" data="citationList"}enc_ctx->hw_device_ctx = av_buffer_ref(hw_device_ctx);  // 绑定设备 ‌:ml-citation{ref="3,6" data="citationList"}// 4. 打开编码器并添加视频流if ((ret = avcodec_open2(enc_ctx, encoder, NULL)) < 0) {  // ‌:ml-citation{ref="4" data="citationList"}fprintf(stderr, "Failed to open encoder\n");goto cleanup;}AVStream *stream = avformat_new_stream(fmt_ctx, NULL);avcodec_parameters_from_context(stream->codecpar, enc_ctx);// 5. 打开输出文件并写入头信息if (!(fmt_ctx->oformat->flags & AVFMT_NOFILE)) {ret = avio_open(&fmt_ctx->pb, OUTPUT_FILE, AVIO_FLAG_WRITE);  // ‌:ml-citation{ref="8" data="citationList"}if (ret < 0) {fprintf(stderr, "Failed to open output file\n");goto cleanup;}}avformat_write_header(fmt_ctx, NULL);  // ‌:ml-citation{ref="8" data="citationList"}// 6. 初始化YUV到CUDA格式转换器sws_ctx = sws_getContext(WIDTH, HEIGHT, AV_PIX_FMT_YUV420P,WIDTH, HEIGHT, AV_PIX_FMT_CUDA,SWS_BILINEAR, NULL, NULL, NULL);  // ‌:ml-citation{ref="4,7" data="citationList"}// 7. 准备输入帧和硬件帧AVFrame *yuv_frame = av_frame_alloc();yuv_frame->width = WIDTH;yuv_frame->height = HEIGHT;yuv_frame->format = AV_PIX_FMT_YUV420P;av_frame_get_buffer(yuv_frame, 0);AVFrame *hw_frame = av_frame_alloc();hw_frame->format = enc_ctx->pix_fmt;hw_frame->width = WIDTH;hw_frame->height = HEIGHT;av_hwframe_get_buffer(enc_ctx->hw_frames_ctx, hw_frame, 0);  // ‌:ml-citation{ref="3,6" data="citationList"}// 8. 处理每一帧数据FILE *yuv_file = fopen(INPUT_FILE, "rb");AVPacket *pkt = av_packet_alloc();for (int i = 0; i < 100; i++) {  // 编码100帧测试// 从YUV文件读取数据fread(yuv_frame->data, 1, WIDTH*HEIGHT, yuv_file);          // Y分量fread(yuv_frame->data‌:ml-citation{ref="1" data="citationList"}, 1, (WIDTH/2)*(HEIGHT/2), yuv_file); // U分量fread(yuv_frame->data‌:ml-citation{ref="2" data="citationList"}, 1, (WIDTH/2)*(HEIGHT/2), yuv_file); // V分量// 转换到硬件帧sws_scale(sws_ctx, (const uint8_t**)yuv_frame->data, yuv_frame->linesize,0, HEIGHT, hw_frame->data, hw_frame->linesize);  // ‌:ml-citation{ref="4,7" data="citationList"}// 编码并写入文件avcodec_send_frame(enc_ctx, hw_frame);while (avcodec_receive_packet(enc_ctx, pkt) >= 0) {av_packet_rescale_ts(pkt, enc_ctx->time_base, stream->time_base);av_interleaved_write_frame(fmt_ctx, pkt);  // ‌:ml-citation{ref="8" data="citationList"}av_packet_unref(pkt);}}cleanup:// 9. 释放所有资源if (yuv_file) fclose(yuv_file);if (sws_ctx) sws_freeContext(sws_ctx);av_packet_free(&pkt);av_frame_free(&yuv_frame);av_frame_free(&hw_frame);if (fmt_ctx) avformat_free_context(fmt_ctx);avcodec_free_context(&enc_ctx);av_buffer_unref(&hw_device_ctx);return ret;
}

关键代码说明:‌

组件功能说明依赖项
hw_device_ctx管理CUDA设备上下文,用于GPU内存分配和硬件加速操作CUDA驱动和NVENC支持 ‌
sws_ctx将CPU端的YUV420P数据转换为GPU端的CUDA格式(如NV12)libswscale库 
av_hwframe_get_buffer直接从GPU显存分配帧内存,避免CPU-GPU内存拷贝FFmpeg硬件帧支持
avcodec_send_frame将硬件帧送入编码器队列,触发异步编码操作编码器线程模型

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/73887.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【设计模式】3W 学习法全面解析 7 大结构型模式:Java 实战 + 开源框架应用

3W 学习法总结结构型模式&#xff08;附 Java 代码实战及开源框架应用&#xff09; 结构型模式 主要关注 类与对象的组合&#xff0c;确保不同组件之间能够高效协作&#xff0c;提高系统的灵活性和可维护性。本文采用 3W 学习法&#xff08;What、Why、How&#xff09;&#x…

在大数据开发中ETL是指什么?

hello宝子们...我们是艾斯视觉擅长ui设计和前端数字孪生、大数据、三维建模、三维动画10年经验!希望我的分享能帮助到您!如需帮助可以评论关注私信我们一起探讨!致敬感谢感恩! 在数字经济时代&#xff0c;数据已成为企业最核心的资产。然而&#xff0c;分散在业务系统、日志文件…

前端面试项目拷打

Axios相关 1.在Axios二次封装时&#xff0c;具体封装了哪些内容&#xff0c;如何处理请求拦截和响应拦截&#xff1f; axios二次封装的目的&#xff1a;为了统一处理请求和响应拦截器、错误处理、请求超时、请求头配置等&#xff0c;提高代码可维护性和复用性。 首先创建axios…

「JavaScript深入」Server-Sent Events (SSE):轻量级实时通信技术

Server-Sent Events&#xff08;SSE&#xff09; SSE 的特点1. 单向通信2. 简单易用&#xff0c;浏览器原生支持3. 持久连接4. 纯文本传输5. 自动重连机制6. 轻量级协议 SSE 的实现服务器端实现&#xff08;Node.js 示例&#xff09;1. HTTP 响应头设置2. 数据推送模式3. 服务器…

蓝桥杯2023年第十四届省赛真题-阶乘的和

蓝桥杯2023年第十四届省赛真题-阶乘的和 时间限制: 2s 内存限制: 320MB 提交: 3519 解决: 697 题目描述 给定 n 个数 Ai&#xff0c;问能满足 m! 为∑ni1(Ai!) 的因数的最大的 m 是多少。其中 m! 表示 m 的阶乘&#xff0c;即 1 2 3 m。 输入格式 输入的第一行包含一个整…

影刀RPA拓展-Python变量类型转换

1. Python变量类型转换概述 1.1 类型转换的必要性 Python作为一种动态类型语言&#xff0c;在编程过程中经常需要进行变量类型转换。这主要是因为不同数据类型在存储结构、运算规则和使用场景上存在差异&#xff0c;而在实际开发中&#xff0c;我们常常需要对不同类型的数据进…

Python pyqt+flask做一个简单实用的自动排班系统

这是一个基于Flask和PyQt的排班系统&#xff0c;可以将Web界面嵌入到桌面应用程序中。 系统界面&#xff1a; 功能特点&#xff1a; - 读取员工信息和现有排班表 - 自动生成排班表 - 美观的Web界面 - 独立的桌面应用程序 整体架构&#xff1a; 系统采用前后端分离的架构…

Pycharm接入DeepSeek,提升自动化脚本的写作效率

一.效果展示&#xff1a; 二.实施步骤&#xff1a; 1.DeepSeek官网创建API key&#xff1a; 创建成功后&#xff0c;会生成一个API key&#xff1a; 2. PyCharm工具&#xff0c;打开文件->设置->插件&#xff0c;搜索“Continue”&#xff0c;点击安装 3.安装完成后&…

Java:Arrays类:操作数组的工具类

文章目录 Arrays类常见方法SetAll(); 代码排序如果数组中存储的是自定义对象 Arrays类 常见方法 SetAll(); 注意&#xff1a; 不能用新的数组接是因为修改的是原数组&#xff0c;所以完了要输出原数组发现会产生变化参数是数组下标变成灰色是因为还能简化&#xff08;Lambda…

2025-gazebo配置on vmware,wsl

ros2安装 # 安装ros2, 推荐鱼香ros一键式安装 wget http://fishros.com/install -O fishros && . fishros安装版本&#xff1a;ubuntu24.04 ros2 jazzy gazebo Getting Started with Gazebo? — Gazebo ionic documentation ros与gz的版本对应关系&#xff1a; ​…

格力地产更名“珠免集团“ 全面转型免税赛道

大湾区经济网品牌观察讯&#xff0c;3月18日&#xff0c;格力地产股份有限公司公告宣布&#xff0c;拟将公司名称变更为"珠海珠免集团股份有限公司"&#xff0c;证券简称同步变更为"珠免集团"。此次更名并非简单的品牌焕新&#xff0c;而是标志着这家曾以房…

网络编程--服务器双客户端聊天

写一个服务器和客户端 运行服务器和2个客户端&#xff0c;实现聊天功能 客户端1和客户端2进行聊天&#xff0c;客户端1将聊天数据发送给服务器&#xff0c;服务器将聊天数据转发给客户端2 要求&#xff1a; 服务器使用 select 模型实现 &#xff0c;客户端1使用 poll 模型实现…

k8s主要控制器简述(一)ReplicaSet与Deployment

目录 一、ReplicaSet 关键特性 示例 解释 支持的 Operator 二、Deployment 1. 声明式更新 示例 2. 滚动更新 示例 3. 回滚 示例 4. ReplicaSet 管理 示例 5. 自动恢复 示例 6. 扩展和缩容 示例 示例 一、ReplicaSet ReplicaSet 是 Kubernetes 中的一个核心控…

python中redis操作整理

下载redis命令 pip install redis 连接redis import redis # host是redis主机&#xff0c;需要redis服务端和客户端都起着 redis默认端口是6379 pool redis.ConnectionPool(hostlocalhost, port6379,decode_responsesTrue) r redis.Redis(connection_poolpool)操作字符串 …

自然语言处理入门4——RNN

一般来说&#xff0c;提到自然语言处理&#xff0c;我们都会涉及到循环神经网络&#xff08;RNN&#xff09;&#xff0c;这是因为自然语言可以被看作是一个时间序列&#xff0c;这个时间序列中的元素是一个个的token。传统的前馈神经网络结构简单&#xff0c;但是不能很好的处…

数据结构之链表(双链表)

目录 一、双向带头循环链表 概念 二、哨兵位的头节点 优点&#xff1a; 头节点的初始化 三、带头双向链表的实现 1.双链表的销毁 2.双链表的打印 3.双链表的尾插和头插 尾插&#xff1a; 头插&#xff1a; 4.双链表的尾删和头删 尾删&#xff1a; 头删&#xff1a; …

ASP3605同步降压调节器——满足汽车电子严苛要求的电源芯片方案

ASP3605高效同步降压调节器&#xff0c;通过AEC-Q100 Grade1认证&#xff0c;输入电压4V至15V&#xff0c;输出电流5A&#xff0c;峰值效率94%。车规级型号ASP3605A3U支持-40C至125C工作温度&#xff0c;适用于ADAS、车载信息娱乐系统等场景。 面向汽车电子的核心功能设计 1. …

vue3+Ts+elementPlus二次封装Table分页表格,表格内展示图片、switch开关、支持

目录 一.项目文件结构 二.实现代码 1.子组件&#xff08;表格组件&#xff09; 2.父组件&#xff08;使用表格&#xff09; 一.项目文件结构 1.表格组件&#xff08;子组件&#xff09;位置 2.使用表格组件的页面文件&#xff08;父组件&#xff09;位置 3.演示图片位置 ele…

[特殊字符]1.2.1 新型基础设施建设

&#x1f680; 新型基础设施建设全解析 &#x1f31f; 核心概念与定义 维度详细内容定义以新发展理念为引领&#xff0c;以技术创新为驱动&#xff0c;以信息网络为基础&#xff0c;提供数字转型、智能升级、融合创新服务的基础设施体系。提出背景2018年中央经济工作会议首次提…

SQL Server数据库慢SQL调优

SQL Server中慢SQL会显著降低系统性能并引发级联效应。首先&#xff0c;用户直接体验响应时间延长&#xff0c;核心业务操作&#xff08;如交易处理、报表生成&#xff09;效率下降&#xff0c;导致客户满意度降低甚至业务中断。其次&#xff0c;资源利用率失衡&#xff0c;CPU…