使用FFmpeg庫做的項目,調試項目的時候發現,連續解視頻進行播放,會有明顯記憶體增加問題。連續工作10個小時後就會 被linux 內核kill掉。 通過逐步註掉代碼和網上查閱資料。最後發現記憶體泄漏有一些幾個地方: 一、av_read_frame的問題 從網上查閱大神們的經驗,主要是av_read_f ...
使用FFmpeg庫做的項目,調試項目的時候發現,連續解視頻進行播放,會有明顯記憶體增加問題。連續工作10個小時後就會
被linux 內核kill掉。
通過逐步註掉代碼和網上查閱資料。最後發現記憶體泄漏有一些幾個地方:
一、av_read_frame的問題
從網上查閱大神們的經驗,主要是av_read_frame有記憶體泄漏風險。
av_read_frame 每次迴圈後必須執行av_packet_unref(pkt)進行釋放。
如迴圈內退出需要釋放,不成立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);
二、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(),替換後發現記憶體不再泄漏!!!!
sws_getCachedContext
/** * Check if context can be reused, otherwise reallocate a new one. * * If context is NULL, just calls sws_getContext() to get a new * context. Otherwise, checks if the parameters are the ones already * saved in context. If that is the case, returns the current * context. Otherwise, frees context and gets a new context with * the new parameters. * * Be warned that srcFilter and dstFilter are not checked, they * are assumed to remain the same. */ struct SwsContext *sws_getCachedContext(struct SwsContext *context, int srcW, int srcH, enum AVPixelFormat srcFormat, int dstW, int dstH, enum AVPixelFormat dstFormat, int flags, SwsFilter *srcFilter, SwsFilter *dstFilter, const double *param); /*參數說明*/ int srcW, /* 輸入圖像的寬度 */ int srcH, /* 輸入圖像的寬度 */ enum AVPixelFormat srcFormat, /* 輸入圖像的像素格式 */ int dstW, /* 輸出圖像的寬度 */ int dstH, /* 輸出圖像的高度 */ enum AVPixelFormat dstFormat, /* 輸出圖像的像素格式 */ int flags,/* 選擇縮放演算法(只有當輸入輸出圖像大小不同時有效),一般選擇SWS_FAST_BILINEAR */ SwsFilter *srcFilter, /* 輸入圖像的濾波器信息, 若不需要傳NULL */ SwsFilter *dstFilter, /* 輸出圖像的濾波器信息, 若不需要傳NULL */ const double *param /* 特定縮放演算法需要的參數(?),預設為NULL */
參考資料:
https://blog.csdn.net/xiuxiuxiua/article/details/120370302
FFmpeg視頻轉換sws_getCachedContext|入門筆記 (rumenz.com)