FFmpeg 解码内存泄漏汇总,sws_getContext函数无法释放问题

音视频解码流程 我们都知道视频的存储方式一般都是MP4、avi、FLV等封装的格式,如果需要在设备进行播放视频,就需要对其进行相应的处理,图片一般需要yuv或rgb格式的图片数据才能进行显示,音频需要pcm的格式数据进行播放,所以这时候就需要对封装格式的视频进行解码,而ffmpeg提供了一套接口可以对视频进行处理。这边的ic是调用上面的初始化解封装器后获得的解封装上下文,里面包含了所有流的信息,nb_streams是一个有多少个流。下面是源码分享,主要是打印了流程中的一些信息,并没有对图像和音频进行显示。... 阅读详情

前面在使用atlas 200开发板进行ffmpeg库进行拉流+dvpp硬件解码+npu进行yuv转码rgb时,进行长时间连续解码和压力测试,会有明显内存增加问题。连续工作21个小时后就会被linux 内核kill掉。

通过逐步注掉代码、和华为技术人员沟通等方式。最后发现内存泄漏有几个地方,这里不讲npu转码部分,只提ffmpeg拉流和解码(本次没用到)可能存在的内存泄漏的风险:

一、av_read_frame的问题

av_read_frame有内存泄漏风险,av_read_frame 每次循环后必须执行av_packet_unref(pkt)进行释放。

对于多个 AVPacket 共享同一个缓存空间,FFmpeg 使用的引用计数的机制来管理(即浅拷贝机制)

  • AVBuffer是FFmpeg中的缓冲区,一开始时AVBuffer的引用计数(refcount)初始化为 0
  • 当有新的Packet引用共享的缓存空间时,就将引用计数再 +1
  • 当Packet释放掉对AVBuffer这块共享缓存空间的引用时,将引用计数 -1
  • 只有当refcount为 0 的时候,才会释放掉缓存空间AVBuffer

如果在循环内退出需要释放pkt,如果作为while的条件不成立时需要在while代码块之外也需要释放。最后需要执行av_packet_free和av_free再进行释放packet的外壳。

while (av_read_frame(pa->fmt_ctx, pkt) >= 0) 
{
    int64_t dts;
    if(pkt->stream_index != pa->videoStream)
    {
        av_packet_unref(pkt);     
        continue;
     }
    av_packet_unref(pkt);
}    
av_packet_unref(pkt);
if(pa->packet != NULL)
{
    av_packet_unref(pa->packet); 
}
av_packet_free(&pa->packet);
av_free(pa->packet);

 av_packet_alloc 和 av_packet_free 必须要配对使用,否则会造成内存泄漏。av_packet_free 实际是释放AVPacket 的空间。

FFmpeg 中 av_init_packet() 和 av_packet_alloc()av_packet_unref() 三者的区别以及用法

av_packet_alloc 中并没有调用 av_init_packet , 但av_packet_alloc 中调用了 av_packet_unref ,而 av_packet_unref 内部才调用 av_init_packet (老版本的 ffmpeg 中 av_packet_alloc 是直接调用 av_init_packet )

 在注意,在 av_init_packet 中初始化并不涉及 data 和 size 成员,它们必须分别初始化。

av_new_packet 的作用是为 pkt 分配一个指定大小的内存。av_new_packet 中为 pkt 的 buf 分配一个大小,且内部还调用了 av_init_packet 对 pkt 进行初始化。而且注意,该函数的返回值并不是引用计数,之前在网上看到有些博客写返回的是引用计数(是不对的),这个函数返回值永远都是 0,没有具体意义。

一般在开发过程中都会遵循以下几步
AVPacket *pkt = NULL;
pkt = av_packet_alloc();
ret = av_new_packet(pkt, MEM_ITEM_SIZE);
av_packet_free(&pkt);

下面通过一个测试示例来应用下这几个 API

#define MEM_ITEM_SIZE (20*1024*102)
void av_packet_test1()
{
    AVPacket *pkt = NULL;
    int ret = 0;

    pkt = av_packet_alloc();
    ret = av_new_packet(pkt, MEM_ITEM_SIZE);  
    //把数据写到data区域,  av_init_packet 内部初始化并不是涉及 data 和 size
    memccpy(pkt->data,(void*)&av_packet_test1,1,MEM_ITEM_SIZE);
    av_packet_free(&pkt);
}

av_packet_alloc 只是为 pkt 分配了内存空间,buf 依然为 NULL。在 av_new_packet 之后真正的为 buf 分配内存空间。

av_packet_free 先把 pkt 中的内容清空,然后再把指针清空,让 pkt 彻底无法使用了,如果需要重新使用,需要重新分配内存。

二、AVFrame* 结构体的释放

   AVFrame结构体需要

1、先执行av_frame_unref()释放内部

2、调用av_frame_free(&pa->srcFrame);释放外壳

三、注意释放顺序

  内存释放要按顺序进行释放。以防释放掉外壳后,内部就不能进行释放了。

如下面是释放上下文的顺序。

sws_freeContext(pSwsContext);               
av_frame_free(&pAVFrame);
avcodec_close(pAVCodecContext);
avformat_close_input(&pAVFormatContext);

四、sws_getContext函数无法释放问题

  经过反复查找,发现sws_getContext函数调用后存在内存泄漏问题。非常奇怪的是

程序中已调用了sws_freeContext(pa->sws_ctx)进行释放,内存依然泄漏。

     后发现有类型函数 sws_getCachedContext(),替换后发现内存不再泄漏!!!!

参考:FFmpeg开发笔记(四):ffmpeg解码的基本流程详解_ffmpeg3.x解码流程图_长沙红胖子Qt的博客-优快云博客

基于ffmpeg 对音视频进行编解码存在内存泄露问题记录 基于ffmpeg的api进行音视频开发,遇到的内存泄漏问题 阅读详情

相关推荐

ffmpeg图像变换函数sws_scale

SwsContext *context : 传入一个SwsContext结构体,判断传入是否context 是否和传入的参数是一致的,如果是一致的就直接返回。不一致的话,则会释放掉后再创建。srcStride:输入数据的每个通道一行的字节数,例如 rgb 为packed模式所以填 宽度 * 3, YUV420P为planar模式 所以填一个数组。例如线程1处理0~h/2的数据,线程2处理h/2 ~ h的数据。srcSlice :输入数据每个通道的指针,例如rgb只有一个通道,YUV数据则有3个通道。

weixin_42764231的博客 2020

ffmpeg中swscale 的用法

移植ffmpeg过程中,遇到swscale的用法问题,所以查到这篇文章。文章虽然已经过去很长时间,但是还有颇多可以借鉴之处。谢谢“咕咕鐘"。          转自:http://guguclock.blogspot.com/2009/12/ffmpeg-swscale.html          如果想將某個PixelFormat轉換至另一個PixelFormat,例如,將YUV420P

1万+

Windows C++集成FFmpeg解码H.264/H.265视频并渲染到窗口的完整实践

视频编码是多媒体技术的核心基础,它通过压缩算法大幅减少视频数据体积,H.264和H.265(HEVC)是当前应用最广泛的编码标准。其原理是利用帧内预测、帧间预测和熵编码等技术去除冗余信息。这项技术的价值在于,它支撑了从流媒体、视频会议到安防监控等几乎所有数字视频应用场景,是实现高效存储与传输的关键。在工程实践中,开发者常需在桌面应用中集成解码与渲染能力。本文聚焦于**FFmpeg**这一强大的多媒体处理框架,详细阐述如何在Windows平台使用C++调用其解码库,构建一个从文件解析、**H.265**解码到

weixin_30693683的博客 493

音视频从入门到精通——FFmpeg之sws_getContext处理图像函数分析

封装格式上下文结构体,也是统领全局的结构体,保存了视频文件封装格式相关信息。

mirana的专栏 3395

C++/Qt音视频开发入门:FFmpeg环境配置与核心解码流程详解

音视频开发的核心在于对多媒体数据的处理,涉及编解码、封装、传输与渲染等多个技术环节。其基本原理是通过解码器将压缩的音频和视频数据还原为原始帧,再经过格式转换后交由渲染引擎呈现。这项技术的价值在于能够高效处理海量多媒体数据,为实时通信、流媒体服务、视频编辑等应用提供基础支撑。在实际工程中,开发者常借助FFmpeg这类强大的开源库来处理复杂的编解码任务,并结合Qt框架构建跨平台的图形界面。本文聚焦于C++/Qt环境下集成FFmpeg的实践,详细解析了**第三方库集成**的配置方法、**中文路径与乱码问题**的解

464

基于FFmpeg与QT的跨平台C++播放器开发实战指南

音视频处理是现代软件开发中的核心技术,其核心原理在于对多媒体容器进行解封装,分离出独立的音视频流,再通过解码器将压缩数据转换为原始帧。这项技术的价值在于为流媒体、视频会议等应用提供了底层支持。在工程实践中,FFmpeg作为行业标准库,提供了完整的解封装、解码和格式转换API,而QT框架则以其跨平台特性和高效的GUI能力,简化了界面开发。结合多线程架构和生产者-消费者模型,可以构建出高性能、低延迟的播放引擎。本文聚焦于**FFmpeg核心API**的实战应用与**多线程架构**设计,详细解析了从数据读取、解码

weixin_34214500的博客 415

FFmpeg4入门06:保存视频帧

上一篇介绍了解码的基本流程,获取了视频帧数,但是没有视频每一帧数据的解码操作。 我们从视频中取出每一帧进行操作,我们已经分配了AVFrame内存,当我们转换它颜色空间时仍然需要一个位置来放置原始数据。我们使用av_image_get_buffer_size来获得我们需要的大小,并手动分配空间: //一帧图像数据大小 int numBytes = av_image_get_buffer_size(AV_PIX_FMT_RGB32, codecCtx->width, codecCtx->height

qq_26056015的博客 2114

实战FFmpeg.AutoGen:C#调用C++库的指针转换与内存管理详解

本文详细介绍了如何在C#中使用FFmpeg.AutoGen进行C++库的指针转换与内存管理,解决音视频处理中的指针操作、内存管理和平台调用问题。通过实战示例和Demo源码,展示了如何安全转换指针、优化内存管理以及实现H264解码,帮助开发者高效处理音视频数据。

注重长远 天天积累 cqujsjcyj 466

C++ 视频库 ffmpeg

本文介绍了FFmpeg的基本概念、安装方法和使用方式。视频文件本质上是包含多组音视频流的容器,FFmpeg可对其进行编解码处理。文章首先说明如何通过命令行工具实现格式转换、视频截取、字幕添加和图片合成视频等常见操作。随后详细讲解了如何将FFmpeg作为库链接到C程序中,包括打开文件、存储数据帧、读取数据、资源释放等关键步骤的代码实现,最终完成视频分解为多张图片的功能。文中提供了完整的代码示例和编译执行说明,帮助开发者快速掌握FFmpeg的基础应用。

人无远虑,必有近忧 6839

基于FFmpeg与GDExtension的Godot跨格式视频播放方案

视频解码是多媒体应用开发中的核心技术,其原理是将压缩的编码数据还原为原始的音画帧。现代视频编码标准如H.264/AVC和H.265/HEVC,凭借高压缩效率,已成为MP4、MKV等主流封装格式的基石。在游戏开发领域,灵活的视频播放能力对于过场动画、教程演示至关重要,它直接影响用户体验与内容呈现。Godot引擎内置的视频播放支持有限,主要面向Ogg Theora格式,这促使开发者寻求更通用的解决方案。通过集成FFmpeg这一强大的多媒体处理库,并利用Godot 4的GDExtension扩展机制,可以构建一个

weixin_34288121的博客 387

UE5集成FFmpeg实现RTSP流媒体播放:从编译到渲染的完整指南

流媒体协议是实时传输音视频数据的基础技术,其核心原理在于通过特定的网络协议(如RTSP、RTMP)实现媒体数据的连续推送与接收。在游戏开发、虚拟仿真和数字孪生等领域,将外部实时视频流无缝集成至引擎场景具有重要价值,能极大增强场景的真实感与交互性。本文聚焦于如何在Unreal Engine 5中实现这一功能,针对UE5原生媒体框架对RTSP协议支持不足的痛点,深入探讨了集成FFmpeg这一核心多媒体处理库的方案。通过详细解析FFmpeg的编译配置、UE5插件创建、多线程解码与纹理动态更新的技术路径,并结合**

weixin_30516243的博客 286

C#调用FFmpeg API实现WinForm嵌入RTMP实时视频流

视频流处理是工业自动化与上位机开发中的常见场景,如何将实时网络摄像头画面稳定嵌入桌面客户端成为许多开发者面临的挑战。FFmpeg作为最流行的开源多媒体框架,提供了完整的音视频封装、解码与转换能力,而C#通过P/Invoke调用其Native API,能够在进程内直接完成拉流、解码与格式转换,避免外部进程和管道带来的延迟与资源管理问题。这种技术路线不仅适用于WinForm界面嵌入RTMP流,还可灵活扩展图像叠加、智能分析等业务逻辑。本文从RTMP拉流参数设置、解码主循环、YUV到BGR转换,到WinForm双

weixin_34378969的博客 357

C++视频字幕解析实战:FFmpeg+Tesseract实现硬字幕提取

视频字幕解析是多媒体处理领域的基础技术,涉及音视频编解码、图像处理和光学字符识别(OCR)等核心原理。通过FFmpeg库进行视频解码与图像帧提取,结合Tesseract OCR引擎实现文字识别,能够将视频中的字幕信息转化为结构化文本数据。这项技术在视频内容分析、无障碍访问、媒体资产管理等场景具有重要价值。本文聚焦于C++工程实践,详细讲解如何利用FFmpeg和Tesseract构建高性能视频字幕解析程序,涵盖核心架构设计、多线程优化等关键技术要点,为开发者提供从理论到实践的完整实现路径。

cojm55771的博客 448

Godot引擎集成FFmpeg:跨平台编译与C++模块开发实战

在游戏开发中,多媒体处理是常见的需求,尤其是视频播放与解码。Godot引擎内置的视频播放器虽然方便,但在格式支持、性能表现和功能控制上存在局限。FFmpeg作为开源的多媒体处理库,提供了强大的音视频编解码能力,支持几乎所有主流格式。通过将FFmpeg集成到Godot中,开发者可以获得更灵活的视频处理方案,例如支持透明通道视频、精确帧定位和音视频分离。本文以实战为导向,详细介绍了如何通过C++模块将FFmpeg静态链接到Godot引擎中,涵盖跨平台编译、模块开发、GDScript封装等关键步骤。内容涉及FFm

weixin_33806300的博客 425

WebAssembly + FFmpeg 实现浏览器端 H.265 软解实战指南

视频编解码是多媒体处理的核心技术,其原理是通过特定算法对视频数据进行压缩与解压缩,以平衡画质与传输带宽。H.265(HEVC)作为新一代编码标准,凭借其高效的压缩率,在4K、高清视频传输与存储领域展现出巨大技术价值,尤其适用于在线点播、实时通信等对带宽敏感的应用场景。然而,浏览器环境对H.265的原生支持存在碎片化问题,为解决这一工程挑战,开发者常借助WebAssembly技术,将成熟的C/C++库(如FFmpeg)编译为可在浏览器中高效运行的模块,实现纯软件解码。本文聚焦于**WebAssembly**与

weixin_33806914的博客 491

C++项目集成FFmpeg:从环境配置到音视频处理核心流程详解

音视频处理是现代软件开发中的常见需求,其核心在于对多媒体数据进行高效的编解码、封装与转换。FFmpeg作为一套功能强大的开源多媒体处理库,提供了完整的解决方案,其价值在于为开发者提供了底层音视频处理的直接控制能力,避免了依赖命令行工具带来的性能损耗和灵活性限制。在工程实践中,将FFmpeg集成到C++项目中,尤其是在Windows平台进行开发时,涉及环境配置、库的获取(包括预编译库下载与自行编译)、CMake项目集成等关键步骤。掌握其核心API,如利用AVFormatContext进行解封装、通过AVCod

weixin_30394981的博客 410

基于Qt+FFmpeg+OpenCV+AI构建智能视频播放器:从解码到AI音视频处理

音视频处理是现代软件开发中的核心领域,涉及多媒体数据的解码、编辑与分析。其基本原理是通过编解码库(如FFmpeg)处理压缩的音视频流,将其转换为可操作的原始数据。在工程实践中,结合计算机视觉(OpenCV)与人工智能模型,能极大拓展应用场景,实现从“播放”到“理解”的跨越。例如,利用深度学习模型进行音频分离或视觉分析,可满足内容审核、智能剪辑、辅助创作等需求。本文聚焦于如何将Qt、FFmpeg、OpenCV与Demucs AI模型四大技术栈深度融合,构建一个具备实时视觉分析与AI音频分离能力的桌面级智能播放

weixin_30315435的博客 334

Unity集成海康摄像头:RTSP流解码与实时渲染实战指南

实时视频流处理是数字孪生、安防监控等领域的核心技术,其核心原理在于通过网络协议获取视频数据,经过解码与格式转换后渲染到应用界面。RTSP作为通用的流媒体协议,是实现设备对接的通用基础。在Unity引擎中,通过集成FFmpeg等解码库,可以将RTSP流转换为纹理数据,实现低延迟的实时播放,这为智慧园区、远程巡检等应用场景提供了关键的虚实融合能力。本文聚焦于海康摄像头RTSP流的集成方案,详细解析了从协议对接到Unity渲染的全流程,并针对多路播放与性能优化提供了实战经验,帮助开发者高效打通虚实世界的视觉桥梁。

weixin_30847939的博客 345
上一篇: git submodule 使用教程
下一篇: 【Linux驱动】内核模块编译 —— make modules 的使用(单模块编译、多模块编译)
土豆西瓜大芝麻
博客等级 码龄18年 1189粉丝 238原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值