av_buffer_unref 是 FFmpeg 中用于管理引用計數和內存釋放的核心函數,其內部實現機制如下:
?一、核心流程?
-
?引用計數遞減?
函數首先對?AVBufferRef
?的?buffer->refcount
?進行原子遞減操作(通過?atomic_fetch_add_explicit
?等機制保證線程安全)。 -
?引用計數檢查?
- 若遞減后?
refcount > 0
:僅釋放當前?AVBufferRef
?結構體,保留底層?AVBuffer
?和數據內存。 - 若遞減后?
refcount == 0
:觸發內存釋放流程(包括?AVBuffer
?自身及其數據)。
- 若遞減后?
-
?內存釋放邏輯?
- 調用?
buffer->free
?回調函數(如默認的?av_buffer_default_free
?或用戶自定義的釋放函數),釋放?buffer->data
?指向的數據內存。 - 若?
AVBuffer
?屬于內存池(AVBufferPool
),則通過?buffer_pool_release_buffer
?將內存塊返回池中以供復用。
- 調用?
-
?資源清理?
- 置空?
AVBufferRef->buffer
?指針,避免懸垂引用。 - 釋放?
AVBufferRef
?結構體本身的內存。
- 置空?
?二、關鍵設計細節?
-
?線程安全?
引用計數的增減操作通過原子指令實現,確保多線程環境下數據一致性26。 -
?內存池優化?
若?AVBuffer
?來自內存池,釋放時不會立即歸還給系統,而是通過鏈表管理復用,減少頻繁內存分配開銷。 -
?回調擴展性?
buffer->free
?允許注冊自定義釋放邏輯(如 GPU 內存釋放需調用特定驅動 API),支持異構硬件資源管理。
?三、代碼邏輯簡化示例?
void av_buffer_unref(AVBufferRef **ref) {if (!*ref)return;AVBuffer *buf = (*ref)->buffer;// 原子操作減少引用計數int refcount = atomic_fetch_sub_explicit(&buf->refcount, 1, memory_order_acq_rel);if (refcount == 1) { // 引用歸零if (buf->free) // 調用釋放回調buf->free(buf->opaque, buf->data);if (buf->pool) // 內存池回收邏輯buffer_pool_release_buffer(buf->pool, buf);av_free(buf); // 釋放AVBuffer結構體}av_freep(ref); // 釋放AVBufferRef并置空指針
}
?四、關聯機制?
-
?與?
av_buffer_ref
?的關系?
av_buffer_ref
?增加引用計數并復制?AVBufferRef
,而?av_buffer_unref
?負責遞減計數和釋放,兩者共同維護引用生命周期。 -
?與?
AVPacket/AVFrame
?的交互?
當?AVPacket
?或?AVFrame
?調用?av_packet_unref
?或?av_frame_unref
?時,內部最終通過?av_buffer_unref
?釋放底層數據內存。
通過上述機制,av_buffer_unref
?實現了高效且安全的內存管理,成為 FFmpeg 多模塊資源共享和生命周期控制的基礎。
av_freep ?和 av_freep函數的區別
-
?av_free(void * p)?
- ?參數類型?:接受?
void *
?類型的指針13。 - ?作用?:僅釋放指針指向的內存塊,?不修改指針本身的值?,釋放后指針仍指向原地址(即懸垂指針)
- ?參數類型?:接受?
????????????????
uint8_t *data = av_malloc(100);
av_free(data); // 釋放內存,但 data 仍指向已釋放的地址
-
?av_freep(
void ** p
)?- ?參數類型?:接受?
void **
?類型的指針地址12。 - ?作用?:
- 釋放指針指向的內存塊;
- ?將原指針置為?
NULL
?,避免懸垂指針問題12。
uint8_t *data = av_malloc(100); av_freep(&data); // 釋放內存,并將 data 置為 NULL
- ?參數類型?:接受?