国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

FFmpeg源碼走讀之內(nèi)存管理模型

這篇具有很好參考價值的文章主要介紹了FFmpeg源碼走讀之內(nèi)存管理模型。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

1 FFmpeg內(nèi)存管理原理

數(shù)據(jù)包管理過程中當(dāng)數(shù)據(jù)轉(zhuǎn)移到新的數(shù)據(jù)包時存在兩種操作一種是數(shù)據(jù)包之間相互獨立,當(dāng)新創(chuàng)建一份數(shù)據(jù)包時,需要將原來的數(shù)據(jù)重新申請一個數(shù)據(jù)空間并且將數(shù)據(jù)拷貝到新的數(shù)據(jù)包中,具體過程如下圖所示。這種數(shù)據(jù)包的管理優(yōu)勢是在于數(shù)據(jù)之間相互獨立,不會存在數(shù)據(jù)干擾的問題,但是缺點也很明顯就是消耗的內(nèi)存大大增加,同時數(shù)據(jù)之間的拷貝也是耗時的。
FFmpeg源碼走讀之內(nèi)存管理模型
另一種內(nèi)存管理的方式是,只新增數(shù)據(jù)包對象,用于管理數(shù)據(jù)對象,對于數(shù)據(jù)本身采用同一個內(nèi)存空間進行管理,當(dāng)所有的內(nèi)存引用為0時釋放這片內(nèi)存空間,具體如下圖所示。這種方式的優(yōu)勢就是數(shù)據(jù)占用內(nèi)存最小化,同時大大減少數(shù)據(jù)拷貝的耗時問題;缺點是增加了內(nèi)存管理的難度。FFmpeg正是采用這種內(nèi)存管理的方式進行數(shù)據(jù)包和數(shù)據(jù)幀的管理。
FFmpeg源碼走讀之內(nèi)存管理模型

2 FFmpeg內(nèi)存管理實現(xiàn)

2.1 AVPacket實現(xiàn)

核心API 功能
av_packet_alloc 申請AVPacket
av_packet_free 釋放AVPacket
av_init_packet 初始化AVPacket
av_new_packet 申請AVBufferRef和AVBuffer數(shù)據(jù)空間,引用計數(shù)設(shè)置為1
av_buffer_ref 新申請AVBufferRef,AVBuffer引用計數(shù)加一
av_buffer_unref 釋放AVBufferRef,AVBuffer引用計數(shù)減一

AVPacket 內(nèi)存模型如下圖所示,AVBuffer存放具體數(shù)據(jù),AVBufferRef用于管理AVBuffer,AVPacket 是實際對外數(shù)據(jù)包體。
FFmpeg源碼走讀之內(nèi)存管理模型
引用計數(shù)加一和引用計數(shù)減一一個逆過程,具體如下圖所示,加一主要是增加AVBufferRef和引用計數(shù);減一主要是釋放AVBufferRef和引用計數(shù)減少。當(dāng)引用計數(shù)減到0時,需要釋放AVBuffer數(shù)據(jù)區(qū)。
FFmpeg源碼走讀之內(nèi)存管理模型
源碼走讀如下所示:

//1 申請AVPacket內(nèi)存,并初始化
AVPacket *av_packet_alloc(void)
{
	//1 分配AVPacket 內(nèi)存
	//2 將AVPacket解引用
	av_packet_unref
	{
		//AVPacket 初始化
		av_init_packet
	}
}
//釋放AVPacket內(nèi)存,引用減1
void av_packet_free(AVPacket **pkt);
//初始化AVPacket
void av_init_packet(AVPacket *pkt);
//新申請AVPacket的數(shù)據(jù)空間
int av_new_packet(AVPacket *pkt, int size)
{
	//分配AVBufferRef內(nèi)存空間
	packet_alloc
	{
		av_buffer_realloc
		{
			//分配AVBufferRef內(nèi)存
			av_buffer_create
			{
				//先分配AVBuffer,并且注冊釋放回調(diào)函數(shù),refcount引用計數(shù)加一
				//再分配AVBufferRef,并將指針與AVBuffer綁定
			}
		}
	}
}
//引用計數(shù)加一
AVBufferRef *av_buffer_ref(AVBufferRef *buf)
{
	//新分配一個AVBufferRef;將舊的AVBufferRef復(fù)制給它,同時引用計數(shù)加1
	*ret = *buf;//結(jié)構(gòu)體賦值的方式,淺拷貝
}
//引用計數(shù)減一
void av_buffer_unref(AVBufferRef **buf)
{
	//AVBufferRef釋放,同時AVBuffer計數(shù)減一,當(dāng)計數(shù)為1時釋放
	buffer_replace
	{
		//利用回調(diào)釋放數(shù)據(jù)
		b->free
	}
}

2.2 AVFrame實現(xiàn)

核心API 功能
av_frame_alloc 申請AVFrame
av_frame_free 釋放AVFrame
av_frame_get_buffer 申請AVBufferRef和AVFrame數(shù)據(jù)空間
av_frame_ref 新申請AVBufferRef,AVFrame引用計數(shù)加一
av_frame_unref 釋放AVBufferRef,AVFrame引用計數(shù)減一
av_frame_move_ref AVFrame轉(zhuǎn)移引用計數(shù)

AVFrame實現(xiàn)原理與AVPacket 一致,都是利用AVBufferRef進行引用計數(shù)的管理,同時數(shù)據(jù)存儲在AVBuffer中,只有保存一份,av_frame_ref負(fù)責(zé)將引用計數(shù)加一,av_frame_unref引用計數(shù)減一,當(dāng)引用計數(shù)減到0后,進行數(shù)據(jù)釋放。

3 FFmpeg內(nèi)存接口實踐

利用qt進行FFmpeg環(huán)境構(gòu)建,首先是下載FFmpeg依賴庫和頭文件,這里使用的是win32的已經(jīng)編譯好的FFmpeg庫,ffmpeg-4.2.1-win32-dev頭文件和庫。
首先構(gòu)建一個空的c項目,同時創(chuàng)建好需要測試的avpacket文件,在依賴項.pro文件需要添加對FFmpeg的依賴,包括兩部分一個是頭文件路徑,第二是庫路徑。具體如下所示。
FFmpeg源碼走讀之內(nèi)存管理模型

win32{
INCLUDEPATH += $$PWD/ffmpeg-4.2.1-win32-dev/include
LIBS += $$PWD/ffmpeg-4.2.1-win32-dev/lib/avformat.lib   \
        $$PWD/ffmpeg-4.2.1-win32-dev/lib/avcodec.lib    \
        $$PWD/ffmpeg-4.2.1-win32-dev/lib/avdevice.lib   \
        $$PWD/ffmpeg-4.2.1-win32-dev/lib/avfilter.lib   \
        $$PWD/ffmpeg-4.2.1-win32-dev/lib/avutil.lib     \
        $$PWD/ffmpeg-4.2.1-win32-dev/lib/postproc.lib   \
        $$PWD/ffmpeg-4.2.1-win32-dev/lib/swresample.lib \
        $$PWD/ffmpeg-4.2.1-win32-dev/lib/swscale.lib
}

注意ffmpeg-4.2.1-win32-dev文件放到項目的根路徑如下所示。
FFmpeg源碼走讀之內(nèi)存管理模型
接下來是測試FFmpeg是否可以正常使用,具體測試程序如下,獲取FFmpeg的版本。
FFmpeg源碼走讀之內(nèi)存管理模型
執(zhí)行效果如下所示:
FFmpeg源碼走讀之內(nèi)存管理模型
1 實現(xiàn)簡單的內(nèi)存分配和釋放操作
需要注意的點:

  • av_packet_alloc內(nèi)部會進行初始化,所以不需要再調(diào)用av_init_packet初始化;
  • av_packet_free內(nèi)部會進行解引用,所以不需要再調(diào)用av_packet_unref;
  • av_init_packet一定不能在av_new_packet之后使用會造成內(nèi)存泄漏
  • 對同一個AVPacket進行多次av_packet_ref而沒有av_packet_unref會造成內(nèi)存泄漏。

FFmpeg源碼走讀之內(nèi)存管理模型
av_new_packet用于分配到:AVBufferRef引用管理,同時會分配數(shù)據(jù)部分AVBuffer,同時引用計數(shù)設(shè)置refcount為1.
FFmpeg源碼走讀之內(nèi)存管理模型
經(jīng)過av_packet_move_ref之后AVBufferRef整體被轉(zhuǎn)移到pkt2中,同時會調(diào)用av_init_packet初始化pkt;
FFmpeg源碼走讀之內(nèi)存管理模型
經(jīng)過av_packet_clone之后會主動分配一個AVPacket因此不需要事先分配alloc一個;clone后pkt和pkt2數(shù)據(jù)區(qū)都是指向同一個AVFrame數(shù)據(jù)區(qū)。
FFmpeg源碼走讀之內(nèi)存管理模型
經(jīng)過av_packet_ref后,pkt2首先需要av_packet_alloc一個AVPacket,然后經(jīng)過此函數(shù)后會分配AVBufferRef和將數(shù)據(jù)指向同一個AVFrame數(shù)據(jù)區(qū)。
FFmpeg源碼走讀之內(nèi)存管理模型
AVFrame幀的操作與packet分配原理一致,使用方式也類似。主要包括幾個步驟一個是av_frame_alloc分配一個AVFrame幀,然后稍微有點不同的是需要為幀進行初始化,然后來確認(rèn)是視頻幀還是音頻幀。第二步是av_frame_get_buffer獲取幀的數(shù)據(jù)區(qū)也就是AVBufferRef和AVBuffer這里有一個比較特殊的地方是這里預(yù)制了一個長度為8的AVBufferRef指針數(shù)組,主要是用于不同的數(shù)據(jù)存儲格式不一樣需要多個內(nèi)存空間。最后是確保AVFrame是可寫的,在進行數(shù)據(jù)操作。釋放利用av_frame_free。
FFmpeg源碼走讀之內(nèi)存管理模型
獲取分配數(shù)據(jù)幀的需要設(shè)置相關(guān)的參數(shù),幀的數(shù)據(jù)格式;如果是視頻需要設(shè)置分辨率;如果是音頻需要設(shè)置步長,通道數(shù)等參數(shù);主要原因是分配數(shù)據(jù)時根據(jù)這些參數(shù)計算分配數(shù)據(jù)空間大小。
FFmpeg源碼走讀之內(nèi)存管理模型文章來源地址http://www.zghlxwxcb.cn/news/detail-424080.html

到了這里,關(guān)于FFmpeg源碼走讀之內(nèi)存管理模型的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經(jīng)查實,立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費用

相關(guān)文章

  • 【Kafka源碼走讀】Admin接口的客戶端與服務(wù)端的連接流程

    【Kafka源碼走讀】Admin接口的客戶端與服務(wù)端的連接流程

    注:本文對應(yīng)的kafka的源碼的版本是trunk分支。寫這篇文章的主要目的是當(dāng)作自己閱讀源碼之后的筆記,寫的有點凌亂,還望大佬們海涵,多謝! 最近在寫一個Web版的kafka客戶端工具,然后查看Kafka官網(wǎng),發(fā)現(xiàn)想要與Server端建立連接,只需要執(zhí)行 方法即可,但其內(nèi)部是如何工作

    2024年02月16日
    瀏覽(27)
  • 【Zookeeper源碼走讀】第三章 服務(wù)器處理客戶端請求的流程

    前一篇文章,已經(jīng)大致介紹了Server的啟動流程,在NIOServerCnxnFactory.start()方法中,啟動了多個線程,其中就有接收socket報文的線程,代碼如下: 注意這里,acceptThread是接收socket的線程(AcceptThread),acceptThread的初始化是在NIOServerCnxnFactory.configure()中實現(xiàn)的: NIOServerCnxnFactory.confi

    2024年02月02日
    瀏覽(28)
  • 【內(nèi)存管理】flink內(nèi)存管理(一):內(nèi)存管理概述:flink主動管理內(nèi)存原理、flink內(nèi)存模型

    【內(nèi)存管理】flink內(nèi)存管理(一):內(nèi)存管理概述:flink主動管理內(nèi)存原理、flink內(nèi)存模型

    本節(jié)從整體使用的角度了解Flink如何實現(xiàn)對內(nèi)存的積極管理,然后對比基于JVM帶來的內(nèi)存管理問題,介紹Flink如何抽象出合理內(nèi)存模型,解決大規(guī)模場景下的內(nèi)存使用問題。 在JVM上運行的系統(tǒng),需要將數(shù)據(jù)存儲到JVM堆內(nèi)存中進行處理和運算,借助JVM提供的GC能力能夠?qū)崿F(xiàn)內(nèi)存的

    2024年01月20日
    瀏覽(21)
  • 24.Netty源碼之合理管理堆內(nèi)存

    24.Netty源碼之合理管理堆內(nèi)存

    內(nèi)存使用目標(biāo) ?內(nèi)存占用少(空間) ?應(yīng)用速度快(時間) 即多快好省 對 Java 而言:減少 Full GC 的 STW(Stop the world)時間 內(nèi)存使用技巧 ? 減少對象本身大小 md 例 1:用基本類型就不要用包裝類。 例 2: 應(yīng)該定義成類變量(靜態(tài)變量)的不要定義為實例變量。 ? ?一個類 - 一個類變量

    2024年02月13日
    瀏覽(20)
  • 一個簡單的MCU內(nèi)存管理模塊(附源碼)

    一個簡單的MCU內(nèi)存管理模塊(附源碼)

    現(xiàn)在非常多的的MCU性能都還不錯,同時用戶也會去擴展一些外部RAM,那么如何高效便捷的管理這些內(nèi)存是一個重要話題。 今天給大家分享一份源碼:基于無操作系統(tǒng)的STM32單片機開發(fā),功能強大,可申請到地址空間連續(xù)的不同大小的內(nèi)存空間,且用戶接口簡單,使用方便。

    2024年02月08日
    瀏覽(23)
  • 根據(jù)源碼,模擬實現(xiàn) RabbitMQ - 內(nèi)存數(shù)據(jù)管理(4)

    根據(jù)源碼,模擬實現(xiàn) RabbitMQ - 內(nèi)存數(shù)據(jù)管理(4)

    目錄 一、內(nèi)存數(shù)據(jù)管理 1.1、需求分析 1.2、實現(xiàn)?MemoryDataCenter 類 1.2.1、ConcurrentHashMap 數(shù)據(jù)管理 1.2.2、封裝交換機操作 1.2.3、封裝隊列操作 1.2.4、封裝綁定操作 1.2.5、封裝消息操作 1.2.6、封裝未確認(rèn)消息操作 1.2.7、封裝恢復(fù)數(shù)據(jù)操作 當(dāng)前已經(jīng)使用 數(shù)據(jù)庫 管理了 交換機、綁定

    2024年02月11日
    瀏覽(18)
  • 【Linux 內(nèi)核源碼分析】內(nèi)存管理——Slab 分配器

    在Linux內(nèi)核中,伙伴分配器是一種內(nèi)存管理方式,以頁為單位進行內(nèi)存的管理和分配。但是在內(nèi)核中,經(jīng)常會面臨結(jié)構(gòu)體內(nèi)存分配問題,而這些結(jié)構(gòu)體的大小通常是小于一頁的。如果使用伙伴分配器來分配這些小內(nèi)存,將造成很大的內(nèi)存浪費。因此,為了解決這個問題,Sun公

    2024年02月22日
    瀏覽(26)
  • 手把手教你FreeRTOS源碼解析(一)——內(nèi)存管理

    手把手教你FreeRTOS源碼解析(一)——內(nèi)存管理

    FreeRTOS中一共有5種內(nèi)存分配的方法,分別在文件heap_1.c,heap_2.c, heap_3.c,heap_4.c,heap_5.c種。 雖然標(biāo)準(zhǔn)C庫中的 malloc()和 free()也可以實現(xiàn)動態(tài)內(nèi)存管理,但是它有以下缺陷: 1、在小型嵌入式系統(tǒng)種效率不高。 2、線程不安全。 3、具有不確定性,每次執(zhí)行的時間不同。 4、會導(dǎo)致內(nèi)

    2024年02月07日
    瀏覽(25)
  • 深入理解 Spark(四)Spark 內(nèi)存管理模型

    深入理解 Spark(四)Spark 內(nèi)存管理模型

    Executor 進程作為一個 JVM 進程,其內(nèi)存管理建立在 JVM 的內(nèi)存管理之上,整個大致包含兩種方式:堆內(nèi)內(nèi)存和堆外內(nèi)存。 一個 Executor 當(dāng)中的所有 Task 是共享堆內(nèi)內(nèi)存的。一個 Work 中的多個 Executor 中的多個 Task 是共享堆外內(nèi)存的。 堆內(nèi)內(nèi)存和堆外內(nèi)存 大數(shù)據(jù)領(lǐng)域兩個比較常見

    2024年01月24日
    瀏覽(23)
  • Linux內(nèi)存管理 | 四、物理地址空間設(shè)計模型

    Linux內(nèi)存管理 | 四、物理地址空間設(shè)計模型

    我的圈子: 高級工程師聚集地 我是董哥,高級嵌入式軟件開發(fā)工程師,從事嵌入式Linux驅(qū)動開發(fā)和系統(tǒng)開發(fā),曾就職于世界500強企業(yè)! 創(chuàng)作理念:專注分享高質(zhì)量嵌入式文章,讓大家讀有所得! 前面幾篇文章,主要講解了虛擬內(nèi)存空間的布局和管理,下面同步來聊聊物理內(nèi)

    2024年02月08日
    瀏覽(22)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包