日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

ffmpeg的内部Video Buffer管理和传送机制

發(fā)布時(shí)間:2023/12/13 编程问答 23 豆豆
生活随笔 收集整理的這篇文章主要介紹了 ffmpeg的内部Video Buffer管理和传送机制 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

本文主要介紹ffmpeg解碼器內(nèi)部管理Video Buffer的原理和過程,ffmpeg的Videobuffer為內(nèi)部管理,其流程大致為:注冊(cè)處理函數(shù)->幀級(jí)釋放->幀級(jí)申請(qǐng)->清空。

1?注冊(cè)get_buffer()和release_buffer()

FFAPI_InitCodec()

avcodec_alloc_context()

avcodec_alloc_context2()

avcodec_get_context_default2(AVCodecContext *s,...){

......

s->get_buffer = avcodec_default_get_buffer;

s->release_buffer = avcodec_default_release_buffer;

......

}

2幀級(jí)的內(nèi)存申請(qǐng)和釋放調(diào)用

圖1幀級(jí)內(nèi)存申請(qǐng)和釋放的函數(shù)調(diào)用

2.1 FFAPI函數(shù)調(diào)用libavcodec相應(yīng)的codec(WMV3對(duì)應(yīng)的Codec是VC1)函數(shù)進(jìn)行解碼,過程中調(diào)用內(nèi)部buffer處理函數(shù)。其中buffer管理被統(tǒng)一封裝到Mpegvideo接口中(包括的codec有H.261, H.263, H.264, mpeg12, rv10,rv34, svq1和VC1)

FFAPI_Decode()

???????avcodec_decode_video2()

??????????????avctx->codec->decode()//初始化過程中注冊(cè)codec,wmv3的解碼函數(shù)是

??????????????vc1_decode_frame(){

???????decode_vc1_header;

???????MPV_frame_start();?????????????????????????????????????//2.2.2

???????vc1_decode_blocks();

???????MPV_frame_end();?????????????????????????????????????//2.2.3

}

2.2 MPV_frame_start()//通過調(diào)用get_buffer()申請(qǐng)當(dāng)前幀的video buffer。

MPV_frame_start()

???????//首先調(diào)用release_buffer()釋放非參考幀的video buffer

???????for(i=0; i<MAX_PICTURE_COUNT; i++)

if(s->picture[i].data[0] && !s->picture[i].reference)

free_frame_buffer(s, &s->picture[i]); //調(diào)用s->avctx->get_buffer(),回調(diào)avcodec_default_release_buffer()

?

???????ff_alloc_picture()

??????????????alloc_frame_buffer()

?????????????????????s->avctx->get_buffer()??????//回調(diào)avcodec_default_get_buffer()

2.3MPV_frame_end()??????????????????????????????????????????//完成視頻加邊等操作

?

3幀級(jí)的內(nèi)存申請(qǐng)和釋放處理方法

3.1內(nèi)部buffer數(shù)據(jù)結(jié)構(gòu)

–???typedef struct InternalBuffer{

–???????int last_pic_num;??????????????

–???????uint8_t *base[4];?????????????

–???????uint8_t *data[4];?????????????

–???????int linesize[4];???????????

–???????int width, height;????????????

–???????enum PixelFormat pix_fmt;???

–???}InternalBuffer;

–???typedef struct AVCodecContext {

–??????????……

–???int internal_buffer_count;?//記錄當(dāng)前內(nèi)部buffer的個(gè)數(shù),get_buffer和release_buffer時(shí)均需要對(duì)其進(jìn)行維護(hù)。

–???void *internal_buffer;//初始化為數(shù)組InternalBuffer [INTERNAL_BUFFER_SIZE]

–???……

–???}?AVCodecContext;

Codec通過維護(hù)internal_buffer_count和internal_buffer實(shí)現(xiàn)高效的內(nèi)存管理。

3.2參考幀管理相關(guān)數(shù)據(jù)結(jié)構(gòu)

–???typedef??struct Picture{

–???????uint8_t *data[4];

–???????int linesize[4];

–???????uint8_t *base[4];

–???????int reference;

–???????……

–???}?Picture;

–???typedef??struct MpegEncContext{

–???????……

–???????Picture* picture;???//初始化為數(shù)組Picture[INTERNAL_BUFFER_SIZE]

–???????Picture* last_picture_ptr;??????//指向前一幀

–???????Picture* next_picture_ptr;;????//雙向預(yù)測(cè)時(shí),指向后一幀

–???????Picture* current_picture_ptr;//指向當(dāng)前幀

–???……

–???}?MpegEncContext;?

3.3申請(qǐng)和釋放原理

圖2?內(nèi)存申請(qǐng)和釋放原理

(1)初始化時(shí)將internal_buffer全部清零

(2)釋放buffer時(shí),將釋放的buffer與最后一個(gè)有效buffer交換,而不是用av_free()釋放內(nèi)存。

avcodec_default_release_buffer(AVCodecContext *s, AVFrame *pic){

s->internal_buffer_count--;

????last = &((InternalBuffer*)s->internal_buffer)[s->internal_buffer_count];

????//將last buffer和要釋放的buffer交換,使last buffer變成無效buffer,在下次get_buffer時(shí)能被申請(qǐng)到。

FFSWAP(InternalBuffer, *buf, *last);

????for(i=0; i<4; i++){

????????pic->data[i]=NULL;

????}

}

(3)申請(qǐng)buffer時(shí),檢查internal_buffer[internal_buffer_count]的基址是否非空,若非空則直接使用internal_buffer[internal_buffer_count];若空,使用av_malloc()函數(shù)進(jìn)行申請(qǐng)。

這樣處理的好處是避免了頻繁的調(diào)用malloc()和free(),從而提升了效率。

avcodec_default_get_buffer(AVCodecContext *s, AVFrame *pic){

???????……

???????buf= &((InternalBuffer*)s->internal_buffer)[s->internal_buffer_count];

???????get_size_info(size[]);

???????buf->base[0, 1, 2] = av_malloc(size[0, 1, 2]);

???????buf->data[0, 1, 2] = buf->base[0, 1, 2] + padding_offset[0, 1, 2];

???????……

}

(4)決定輸出幀是在每幀解碼后,根據(jù)當(dāng)前幀的類型和參考信息決定輸出幀。

if (s->pict_type == FF_B_TYPE || s->low_delay) {

*pict= *(AVFrame*)s->current_picture_ptr;

} else if (s->last_picture_ptr != NULL) {

*pict= *(AVFrame*)s->last_picture_ptr;

}

3.4舉例——假設(shè)解碼IPBPB的非H.264碼流。

(1)初始化后的狀態(tài)如所示,IBC為ctx->internal_buffer_count,CurPtr為s->current_picture_ptr,LastPtr為s->last_picture_ptr,NextPtr為s->next_picture_ptr。

gpAVPicture指針為輸出圖像的指針。

圖3?初始化狀態(tài)

(2)解碼第一個(gè)I幀,過程中不會(huì)不調(diào)用release_buffer(),get_buffer()得到picture[0]?,此時(shí)不輸出任何圖像。

圖4解碼第一個(gè)I幀后的狀態(tài)

(3)解碼第一個(gè)P幀,過程中不調(diào)用release_buffer(),get_buffer()得到picture[1]?,輸出picture[0]。

圖5解碼第一個(gè)P幀后的狀態(tài)

(4)解碼第一個(gè)B幀,過程中不調(diào)用release_buffer(),get_buffer()得到picture[2]?,輸出picture[2]。

圖6解碼第一個(gè)B幀后的狀態(tài)

(5)解碼第二個(gè)P幀,調(diào)用release_buffer(&picture[2]),再調(diào)用get_buffer(),得到picture[2],?輸出picture[1]。

圖7解碼第二個(gè)P幀的狀態(tài)

總結(jié)

以上是生活随笔為你收集整理的ffmpeg的内部Video Buffer管理和传送机制的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。