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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

ffmpeg推流

發(fā)布時(shí)間:2024/8/1 编程问答 23 豆豆
生活随笔 收集整理的這篇文章主要介紹了 ffmpeg推流 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.


流程詳解
av_register_all()
該方法初始化所有的封裝和解封裝。在使用FFmpeg的時(shí)候首先要調(diào)用這個(gè)方法。

static void register_all(void) {avcodec_register_all();/* (de)muxers */REGISTER_MUXER (A64, a64);REGISTER_DEMUXER (AA, aa);REGISTER_DEMUXER (AAC, aac); //... }

這里面就是進(jìn)行各種注冊(cè),而REGISTER_MUXER 、REGISTER_DEMUXER 是前面定義的宏。我們看到是靜態(tài)方法,說明該方法只能在所在的文件中使用,這也防止被注冊(cè)多次。

avformat_network_init()
網(wǎng)絡(luò)相關(guān)初始化。如果我們使用了網(wǎng)絡(luò)拉流和推流等等,要先初始化。

avformat_open_input()
聲明是

int avformat_open_input(AVFormatContext **ps, const char *url, AVInputFormat *fmt, AVDictionary **options);

定義在libavformat\utils.c中。主要功能
輸入輸出結(jié)構(gòu)體AVIOContext的初始化;
輸入數(shù)據(jù)的協(xié)議URLProtocol,通過函數(shù)指針的方式,與FFMPEG關(guān)聯(lián),剩下的就是調(diào)用該URLProtocol的函數(shù)進(jìn)行open,read等操作了

avformat_find_stream_info
int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options);
可以讀取視音頻數(shù)據(jù)并且獲得一些相關(guān)的信息。定義在libavformat\utils.c下

avformat_alloc_output_context2
int avformat_alloc_output_context2(AVFormatContext **ctx, AVOutputFormat *oformat,
const char *format_name, const char *filename);
定義在libavformat\mux.c中

ctx:函數(shù)調(diào)用成功之后創(chuàng)建的AVFormatContext結(jié)構(gòu)體。
oformat:指定AVFormatContext中的AVOutputFormat,用于確定輸出格式。如果指定為NULL,可以設(shè)定后兩個(gè)參數(shù)(format_name或者filename)由FFmpeg猜測(cè)輸出格式。
PS:使用該參數(shù)需要自己手動(dòng)獲取AVOutputFormat,相對(duì)于使用后兩個(gè)參數(shù)來說要麻煩一些。
format_name:指定輸出格式的名稱。根據(jù)格式名稱,FFmpeg會(huì)推測(cè)輸出格式。輸出格式可以是“flv”,“mkv”等等。
filename:指定輸出文件的名稱。根據(jù)文件名稱,FFmpeg會(huì)推測(cè)輸出格式。文件名稱可以是“xx.flv”,“yy.mkv”等等。
函數(shù)執(zhí)行成功的話,其返回值大于等于0。
內(nèi)部流程

調(diào)用avformat_alloc_context()初始化一個(gè)默認(rèn)的AVFormatContext。
如果指定了輸入的AVOutputFormat,則直接將輸入的AVOutputFormat賦值給AVOutputFormat的oformat。如果沒有指定輸入的AVOutputFormat,就需要根據(jù)文件格式名稱或者文件名推測(cè)輸出的AVOutputFormat。無論是通過文件格式名稱還是文件名推測(cè)輸出格式,都會(huì)調(diào)用一個(gè)函數(shù)av_guess_format()。
avio_open
打開FFmpeg的輸入輸出文件

int avio_open2(AVIOContext **s, const char *url, int flags,
const AVIOInterruptCB *int_cb, AVDictionary **options);
s:函數(shù)調(diào)用成功之后創(chuàng)建的AVIOContext結(jié)構(gòu)體。
url:輸入輸出協(xié)議的地址(文件也是一種“廣義”的協(xié)議,對(duì)于文件來說就是文件的路徑)。
flags:打開地址的方式。可以選擇只讀,只寫,或者讀寫。取值如下。
AVIO_FLAG_READ:只讀。
AVIO_FLAG_WRITE:只寫。
AVIO_FLAG_READ_WRITE:讀寫。
int_cb:不太清楚
options:不太清楚
avformat_write_header
寫視頻文件頭,av_write_trailer()用于寫視頻文件尾

av_read_frame
定義在libavformat\utils.c中
讀取碼流中的音頻若干幀或者視頻一幀。解碼視頻的時(shí)候,每解碼一個(gè)視頻幀,需要先調(diào)用 av_read_frame()獲得一幀視頻的壓縮數(shù)據(jù),然后才能對(duì)該數(shù)據(jù)進(jìn)行解碼(例如H.264中一幀壓縮數(shù)據(jù)通常對(duì)應(yīng)一個(gè)NAL)。
這里我貼上官方的注釋,很詳細(xì):

/*** Return the next frame of a stream.* This function returns what is stored in the file, and does not validate* that what is there are valid frames for the decoder. It will split what is* stored in the file into frames and return one for each call. It will not* omit invalid data between valid frames so as to give the decoder the maximum* information possible for decoding.** If pkt->buf is NULL, then the packet is valid until the next* av_read_frame() or until avformat_close_input(). Otherwise the packet* is valid indefinitely. In both cases the packet must be freed with* av_packet_unref when it is no longer needed. For video, the packet contains* exactly one frame. For audio, it contains an integer number of frames if each* frame has a known fixed size (e.g. PCM or ADPCM data). If the audio frames* have a variable size (e.g. MPEG audio), then it contains one frame.** pkt->pts, pkt->dts and pkt->duration are always set to correct* values in AVStream.time_base units (and guessed if the format cannot* provide them). pkt->pts can be AV_NOPTS_VALUE if the video format* has B-frames, so it is better to rely on pkt->dts if you do not* decompress the payload.** @return 0 if OK, < 0 on error or end of file*/

總結(jié)起來每段的核心意思

讀取碼流中的音頻若干幀或者視頻一幀
如果pkt->buf是空,那么就要等待下一次av_read_frame調(diào)用。否則無法確定是否有效
pts dts duration通常被設(shè)置為正確的值。但如果視頻幀包括Bzh幀,那么pts可以是AV_NOPTS_VALUE。所以最好依賴dts。
av_interleaved_write_frame
輸出一幀視音頻數(shù)據(jù)

核心類
AVFormatContext
AVFormatContext是一個(gè)貫穿始終的數(shù)據(jù)結(jié)構(gòu),很多函數(shù)都要用到它作為參數(shù)。它是FFMPEG解封裝(flv,mp4,rmvb,avi)功能的結(jié)構(gòu)體。
內(nèi)部的成員變量,大家可以查看頭文件。這里我們列舉下一些常用重要的成員變量:

struct AVInputFormat *iformat:輸入數(shù)據(jù)的封裝格式
AVIOContext *pb:輸入數(shù)據(jù)的緩存
unsigned int nb_streams:視音頻流的個(gè)數(shù)
AVStream **streams:視音頻流
char filename[1024]:文件名
int64_t duration:時(shí)長(zhǎng)(單位:微秒us,轉(zhuǎn)換為秒需要除以1000000)
int bit_rate:比特率(單位bps,轉(zhuǎn)換為kbps需要除以1000)
AVDictionary *metadata:元數(shù)據(jù)
視頻的原數(shù)據(jù)(metadata)信息可以通過AVDictionary獲取。元數(shù)據(jù)存儲(chǔ)在AVDictionaryEntry結(jié)構(gòu)體中

typedef struct AVDictionaryEntry {
char *key;
char *value;
} AVDictionaryEntry;
每一條元數(shù)據(jù)分為key和value兩個(gè)屬性。
在ffmpeg中通過av_dict_get()函數(shù)獲得視頻的原數(shù)據(jù)。

cout << endl << endl << "======元信息=======" << endl; string meta, key, value; AVDictionaryEntry *m = NULL; while (m = av_dict_get(ictx->metadata, "", m, AV_DICT_IGNORE_SUFFIX)) {key=m->key;value=m->value;meta.append(key).append("\t:").append(value).append("\r\n"); } cout << meta.c_str() << endl;

AVStream
AVStream是存儲(chǔ)每一個(gè)視頻/音頻流信息的結(jié)構(gòu)體。

int index:標(biāo)識(shí)該視頻/音頻流
AVCodecContext codec:指向該視頻/音頻流的AVCodecContext(它們是一一對(duì)應(yīng)的關(guān)系)
AVRational time_base:時(shí)基。通過該值可以把PTS,DTS轉(zhuǎn)化為真正的時(shí)間。- FFMPEG其他結(jié)構(gòu)體中也有這個(gè)字段,但是根據(jù)我的經(jīng)驗(yàn),只有AVStream中的time_base是可用的。PTStime_base=真正的時(shí)間
int64_t duration:該視頻/音頻流長(zhǎng)度
AVDictionary *metadata:元數(shù)據(jù)信息
AVRational avg_frame_rate:幀率(注:對(duì)視頻來說,這個(gè)挺重要的)
AVPacket attached_pic:附帶的圖片。比如說一些MP3,AAC音頻文件附帶的專輯封面。
AVPacket
AVPacket是存儲(chǔ)壓縮編碼數(shù)據(jù)相關(guān)信息的結(jié)構(gòu)體。

uint8_t *data:壓縮編碼的數(shù)據(jù)。
例如對(duì)于H.264來說。1個(gè)AVPacket的data通常對(duì)應(yīng)一個(gè)NAL。
注意:在這里只是對(duì)應(yīng),而不是一模一樣。他們之間有微小的差別:使用FFMPEG類庫(kù)分離出多媒體文件中的H.264碼流
因此在使用FFMPEG進(jìn)行視音頻處理的時(shí)候,常常可以將得到的AVPacket的data數(shù)據(jù)直接寫成文件,從而得到視音頻的碼流文件。

int size:data的大小

int64_t pts:顯示時(shí)間戳

int64_t dts:解碼時(shí)間戳

int stream_index:標(biāo)識(shí)該AVPacket所屬的視頻/音頻流。

總結(jié)

以上是生活随笔為你收集整理的ffmpeg推流的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

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