調用av_buffer_pool_init函數
得到AVBufferPool指針pool, pool的refcount爲1,pool的pool變量值爲NULL,pool的nb_allocated爲0。
調用av_buffer_pool_get函數
調用get_pool返回NULL
!buf 成立,但refcount = 1 不小等於 nb_allocated (0),所以不進入if內。
由於!buf成立,返回pool_alloc_buffer返回值。在pool_alloc_buffer函數中創建一個
BufferPoolEntry實例,此實例的data指向新申請的內存空間,pool指針指向AVBufferPool。
pool的refcount爲2,pool的nb_allocated爲1。BufferPoolEntry指針賦值給AVBufferRef的buffer->opaque。
ret->buffer->free = pool_release_buffer;此句是關鍵,在buffer被free的時候,其又將free數據項的操作
交給了pool_release_buffer,而pool正是在此將申請的實際數據緩存存放到了pool的鏈表中。
調用av_buffer_unref函數
將AVBuffer及AVBufferRef結構體對應的內存空間都釋放掉,在釋放數據時,實際調用pool_release_buffer函數。
pool_release_buffer函數中,又調用add_to_pool將BufferPoolEntry(指向的數據)指針存放到pool中。
add_to_pool函數在代碼avpriv_atomic_ptr_cas((void * volatile *)&pool->pool, NULL, buf)中處理當pool爲NULL,則
使pool->pool指向buf。如果pool->pool不爲NULL,則進入while內操作,如果此data buffer是新申請出的,則最後完成的
鏈表連接順序是 1 2->1 3->2->1 4->3->2->1 其中pool->pool指向最後一次使用的BufferPoolEntry。
再調用av_buffer_pool_get函數
get_pool返回不爲NULL,然後調用add_to_pool(buf->next)將pool設置爲buf的next。如原來如果是4->3->2->1 則get_pool函數返回了4,
然後順序變成3->2->1。然後調用av_buffer_create函數使用此數據創建AVBuffer及AVBufferRef,然後返回。
pool的總體思路是:
如果pool中沒有buf數據,則新建。
buf使用完後,實際數據返回到pool中,由pool將buf鏈接起來。
如果再取數據,如果pool中有buf,則使用pool中的數據buf創建。
巧妙點:
1、將buffer的釋放數據的操作由指針函數完成,平時此指針函數默認爲av_buffer_default_free,用在pool時,此值爲pool_release_buffer。
2、通過給AVBuffer結構體定義一個opaque(模糊不確定)變量,然後將BufferPoolEntry指針存放在此opaque中,在調用AVBuffer的free函數時再
作爲參數傳遞。所以AVBuffer結構體的設計很巧妙。