C++實(shí)現(xiàn)RTMP協(xié)議發(fā)送H.264編碼及AAC編碼的音視頻

https://www.cnblogs.com/haibindev/archive/2011/12/29/2305712.html

C++實(shí)現(xiàn)RTMP協(xié)議發(fā)送H.264編碼及AAC編碼的音視頻郊闯,攝像頭直播

C++實(shí)現(xiàn)RTMP協(xié)議發(fā)送H.264編碼及AAC編碼的音視頻

RTMP(Real Time Messaging Protocol)是專(zhuān)門(mén)用來(lái)傳輸音視頻數(shù)據(jù)的流媒體協(xié)議妻献,最初由Macromedia 公司創(chuàng)建,后來(lái)歸Adobe公司所有团赁,是一種私有協(xié)議育拨,主要用來(lái)聯(lián)系Flash Player和RtmpServer,如FMS, Red5, crtmpserver等欢摄。RTMP協(xié)議可用于實(shí)現(xiàn)直播熬丧、點(diǎn)播應(yīng)用,通過(guò)FMLE(Flash Media Live Encoder)推送音視頻數(shù)據(jù)至RtmpServer怀挠,可實(shí)現(xiàn)攝像頭實(shí)時(shí)直播析蝴。不過(guò),畢竟FMLE應(yīng)用范圍有限绿淋,想要把它嵌入到自己的程序中闷畸,還是要自己來(lái)實(shí)現(xiàn)RTMP協(xié)議的推送。本人實(shí)現(xiàn)了一個(gè)RTMPLiveEncoder吞滞,通過(guò)采集攝像頭視頻和麥克風(fēng)音頻佑菩,并進(jìn)行H.264和AAC編碼盾沫,然后發(fā)送到FMS和crtmpserver上,實(shí)現(xiàn)實(shí)時(shí)直播殿漠,可以通過(guò)flash player正常觀看赴精,目前效果良好,延遲時(shí)間在2秒左右绞幌。本文就介紹一下RTMPLiveEncoder的主要思路和關(guān)鍵點(diǎn)蕾哟,以期對(duì)需要這方面技術(shù)的朋友有所幫助。

技術(shù)分析

要實(shí)現(xiàn)RTMPLiveEncoder啊奄,需要以下四種關(guān)鍵技術(shù):

  • 采集攝像頭視頻和麥克風(fēng)音頻
  • H264編碼和AAC編碼
  • 視頻和音頻數(shù)據(jù)封裝為可被流媒體服務(wù)器識(shí)別的可播放流
  • RTMP協(xié)議實(shí)現(xiàn)報(bào)文發(fā)送

其中渐苏,前兩項(xiàng)技術(shù)在我之前的文章“采集音頻和攝像頭視頻并實(shí)時(shí)H264編碼和AAC編碼”中已經(jīng)介紹過(guò)了,這里就不再啰嗦了菇夸。

把音視頻數(shù)據(jù)封裝為可播放流琼富,這個(gè)是一個(gè)難點(diǎn)。仔細(xì)研究一下庄新,你會(huì)發(fā)現(xiàn)鞠眉,RTMP Packet中封裝的音視頻數(shù)據(jù)流,其實(shí)和FLV封裝音頻和視頻數(shù)據(jù)的方式是相同的择诈,所以械蹋,我們只需要按照FLV封裝H264和AAC的方式,即可生成可播放流羞芍。

我們?cè)倏匆幌翿TMP協(xié)議哗戈。Adobe曾經(jīng)發(fā)布過(guò)一份文檔《RTMP Specification》,不過(guò)wikipedia指出這份文檔隱藏了很多細(xì)節(jié)荷科,單獨(dú)根據(jù)它是無(wú)法正確實(shí)現(xiàn)RTMP的唯咬。不過(guò),它還是有參考意義的畏浆。其實(shí)Adobe發(fā)布之前胆胰,RTMP協(xié)議就已經(jīng)被破解的差不多了,現(xiàn)在也已經(jīng)有比較完善的實(shí)現(xiàn)刻获,比如:RTMPDump蜀涨,它提供的是C語(yǔ)言的接口,這意味著可以很方便的在其他語(yǔ)言中調(diào)用蝎毡。

程序框架

與我之前寫(xiě)的“采集音頻和攝像頭視頻并實(shí)時(shí)H264編碼和AAC編碼”這篇文章相同厚柳,采用DirectShow技術(shù)來(lái)實(shí)現(xiàn)音視頻采集,音頻編碼和視頻編碼顶掉,在各自線(xiàn)程(AudioEncoderThread和VideoEncoderThread)中循環(huán)進(jìn)行草娜,RTMP的推送另起一個(gè)線(xiàn)程(RtmpThread)。兩個(gè)編碼線(xiàn)程實(shí)時(shí)編碼音視頻數(shù)據(jù)后痒筒,將數(shù)據(jù)交與Rtmp線(xiàn)程,由Rtmp線(xiàn)程循環(huán)封裝為Rtmp Packet,然后發(fā)出去簿透。

線(xiàn)程之間的數(shù)據(jù)交換移袍,通過(guò)一個(gè)隊(duì)列DataBufferQueue來(lái)實(shí)現(xiàn)。AudioEncoderThread和VideoEncoderThread把數(shù)據(jù)指針post到DataBufferQueue之后老充,立即返回葡盗,這樣就可以避免因?yàn)榘l(fā)送Rtmp報(bào)文的而影響到編碼線(xiàn)程的正常執(zhí)行時(shí)間。

![image](https://upload-images.jianshu.io/upload_images/14807846-400c6dc91a09deb0.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

RtmpThread的主要工作就是發(fā)送音頻數(shù)據(jù)流的解碼信息頭和視頻數(shù)據(jù)流的解碼信息頭啡浊,并不斷從DataBufferQueue中取出數(shù)據(jù)觅够,封裝為RTMP Packet,發(fā)送出去巷嚣。流程如下列代碼所示:(process_buf_queue_喘先,即是上圖中的DataBufferQueue)

image

librtmp

一、編譯librtmp

下載rtmpdump的代碼廷粒,你會(huì)發(fā)現(xiàn)窘拯,它是一個(gè)地道的linux項(xiàng)目,除了一個(gè)簡(jiǎn)單的Makefile坝茎,其他什么都沒(méi)有涤姊。好像librtmp不依賴(lài)于系統(tǒng),我們可以不用費(fèi)太多功夫嗤放,把它在windows上編譯思喊。不過(guò),librtmp依賴(lài)于openssl和zlib次酌,我們需要首先編譯好它們恨课。

1. 編譯openssl1.0.0e

a) 下載并安裝ActivePerl

b) 下載并安裝nasm(http://nasm.sourceforge.net/)

c) 解壓openssl壓縮包

d) 運(yùn)行cmd命令行,切到openssl目錄和措,分別執(zhí)行以下命令

<pre style="margin: 15px 0px; white-space: pre-wrap; overflow-wrap: break-word; color: rgb(81, 98, 114); font-family: "Courier New" !important; font-size: 12px !important;">>perl Configure VC-WIN32 --prefix=c:\some\dir

ms\do_nasm</pre>

e) 運(yùn)行Visual Studio Command Prompt(2010)庄呈,切到openssl目錄,分別執(zhí)行以下命令派阱。

<pre style="margin: 15px 0px; white-space: pre-wrap; overflow-wrap: break-word; color: rgb(81, 98, 114); font-family: "Courier New" !important; font-size: 12px !important;">>nmake -f ms\nt.mak

nmake -f ms\nt.mak install</pre>

f) 編譯完畢后诬留,即可在第一個(gè)命令所指定的目錄下發(fā)現(xiàn)編譯好的sdk。

2. 編譯zlib

a) 解壓zlib壓縮包

b) 運(yùn)行Visual Studio Command Prompt(2010)贫母,切到openssl目錄文兑,分別執(zhí)行以下命令

<pre style="margin: 15px 0px; white-space: pre-wrap; overflow-wrap: break-word; color: rgb(81, 98, 114); font-family: "Courier New" !important; font-size: 12px !important;">>cd contrib\masmx86

bld_ml32.bat</pre>

c) 回到zlib目錄,進(jìn)入contrib\vstudio\vc10目錄腺劣,打開(kāi)vs2010解決方案文件绿贞,

在zlibstat工程屬性中,去掉預(yù)編譯宏 ZLIB_WINAPI

d) 選擇debug或release編譯即可

3. 編譯librtmp

a) 首先打開(kāi)visual studio 2010橘原,新建一個(gè)win32 console工程籍铁,指定為靜態(tài)鏈接庫(kù)

b) 將librtmp的代碼導(dǎo)入工程涡上,把openssl、zlib的頭文件和librtmp放在一起拒名,把編譯好的openssl和zlib的靜態(tài)庫(kù)放在一起

![image](https://upload-images.jianshu.io/upload_images/14807846-5338b3c3ec00743b.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

![image](https://upload-images.jianshu.io/upload_images/14807846-670e5ceddd7c59c5.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

c) 在工程設(shè)置中吩愧,添加之前編譯好的openssl和zlib的庫(kù),編譯即可增显。

![image](https://upload-images.jianshu.io/upload_images/14807846-d9882121d6fc4be0.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

二雁佳、librtmp的使用

首先初始化RTMP結(jié)構(gòu)

image

開(kāi)始之后,就要向RTMP Server發(fā)起握手連接報(bào)文

image

連接成功同云,就可以開(kāi)始循環(huán)發(fā)送報(bào)文了糖权,這里需要指定時(shí)戳和數(shù)據(jù)類(lèi)型(Audio、Video炸站、Metadata)星澳。這里有一點(diǎn)需要注意的是,在調(diào)用Send之前武契,buf中的數(shù)據(jù)募判,必須是已經(jīng)封裝好的H264或AAC數(shù)據(jù)流。

image

關(guān)閉

image

最后是釋放

image

H264和AAC數(shù)據(jù)流

本文提到過(guò)咒唆,RTMP推送的音視頻流的封裝形式和FLV格式相似届垫,由此可知,向FMS推送H264和AAC直播流全释,需要首先發(fā)送"AVC sequence header"和"AAC sequence header"装处,這兩項(xiàng)數(shù)據(jù)包含的是重要的編碼信息,沒(méi)有它們浸船,解碼器將無(wú)法解碼妄迁。

AVC sequence header就是AVCDecoderConfigurationRecord結(jié)構(gòu),該結(jié)構(gòu)在標(biāo)準(zhǔn)文檔“ISO-14496-15 AVC file format”中有詳細(xì)說(shuō)明李命。

![image](https://upload-images.jianshu.io/upload_images/14807846-1d0e6f0aa9b432ae.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

AAC sequence header存放的是AudioSpecificConfig結(jié)構(gòu)登淘,該結(jié)構(gòu)則在“ISO-14496-3 Audio”中描述。AudioSpecificConfig結(jié)構(gòu)的描述非常復(fù)雜封字,這里我做一下簡(jiǎn)化黔州,事先設(shè)定要將要編碼的音頻格式,其中阔籽,選擇"AAC-LC"為音頻編碼流妻,音頻采樣率為44100,于是AudioSpecificConfig簡(jiǎn)化為下表:

![image](https://upload-images.jianshu.io/upload_images/14807846-37b602840c196c3b.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

這樣笆制,AVC sequence header和AAC sequence header的內(nèi)容可以基本確定了绅这,更詳細(xì)的信息,大家可以去翻閱相關(guān)文檔在辆。

運(yùn)行效果

RtmpLiveEncoder開(kāi)始運(yùn)行

![image](https://upload-images.jianshu.io/upload_images/14807846-01ac1007bb9081a5.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

用FMS自帶的一個(gè)flash播放器播放

![image](https://upload-images.jianshu.io/upload_images/14807846-5189507b7f4a86c1.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末证薇,一起剝皮案震驚了整個(gè)濱河市度苔,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌棕叫,老刑警劉巖林螃,帶你破解...
    沈念sama閱讀 207,113評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件奕删,死亡現(xiàn)場(chǎng)離奇詭異俺泣,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)完残,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,644評(píng)論 2 381
  • 文/潘曉璐 我一進(jìn)店門(mén)伏钠,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人谨设,你說(shuō)我怎么就攤上這事熟掂。” “怎么了扎拣?”我有些...
    開(kāi)封第一講書(shū)人閱讀 153,340評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵赴肚,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我二蓝,道長(zhǎng)誉券,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,449評(píng)論 1 279
  • 正文 為了忘掉前任刊愚,我火速辦了婚禮踊跟,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘鸥诽。我一直安慰自己商玫,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,445評(píng)論 5 374
  • 文/花漫 我一把揭開(kāi)白布牡借。 她就那樣靜靜地躺著拳昌,像睡著了一般。 火紅的嫁衣襯著肌膚如雪钠龙。 梳的紋絲不亂的頭發(fā)上炬藤,一...
    開(kāi)封第一講書(shū)人閱讀 49,166評(píng)論 1 284
  • 那天,我揣著相機(jī)與錄音俊鱼,去河邊找鬼刻像。 笑死,一個(gè)胖子當(dāng)著我的面吹牛并闲,可吹牛的內(nèi)容都是我干的细睡。 我是一名探鬼主播,決...
    沈念sama閱讀 38,442評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼帝火,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼溜徙!你這毒婦竟也來(lái)了湃缎?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 37,105評(píng)論 0 261
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤蠢壹,失蹤者是張志新(化名)和其女友劉穎嗓违,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體图贸,經(jīng)...
    沈念sama閱讀 43,601評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡蹂季,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,066評(píng)論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了疏日。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片偿洁。...
    茶點(diǎn)故事閱讀 38,161評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖沟优,靈堂內(nèi)的尸體忽然破棺而出涕滋,到底是詐尸還是另有隱情,我是刑警寧澤挠阁,帶...
    沈念sama閱讀 33,792評(píng)論 4 323
  • 正文 年R本政府宣布宾肺,位于F島的核電站,受9級(jí)特大地震影響侵俗,放射性物質(zhì)發(fā)生泄漏锨用。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,351評(píng)論 3 307
  • 文/蒙蒙 一坡慌、第九天 我趴在偏房一處隱蔽的房頂上張望叨叙。 院中可真熱鬧雇卷,春花似錦触机、人聲如沸荠割。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,352評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)渣玲。三九已至,卻和暖如春弟晚,著一層夾襖步出監(jiān)牢的瞬間忘衍,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,584評(píng)論 1 261
  • 我被黑心中介騙來(lái)泰國(guó)打工卿城, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留枚钓,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,618評(píng)論 2 355
  • 正文 我出身青樓瑟押,卻偏偏與公主長(zhǎng)得像搀捷,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,916評(píng)論 2 344

推薦閱讀更多精彩內(nèi)容

  • H264中的sps pps iOS仿微信小視頻功能開(kāi)發(fā)優(yōu)化記錄【如何快速的開(kāi)發(fā)一個(gè)完整的iOS直播app】(原理篇...
    CharlyZheng閱讀 1,352評(píng)論 0 2
  • ### YUV顏色空間 視頻是由一幀一幀的數(shù)據(jù)連接而成嫩舟,而一幀視頻數(shù)據(jù)其實(shí)就是一張圖片氢烘。 yuv是一種圖片儲(chǔ)存格式...
    天使君閱讀 3,250評(píng)論 0 4
  • 要理解RTMP推流,我們就要知道詳細(xì)原理家厌,這方面的文章有很多播玖,我也看到過(guò)學(xué)習(xí)過(guò)很多這樣的文章,但是很多都沒(méi)有詳細(xì)的...
    RiemannLee_22dc閱讀 11,480評(píng)論 21 31
  • 實(shí)時(shí)消息協(xié)議---流的分塊 版權(quán)聲明: 版權(quán)(c)2009 Adobe系統(tǒng)有限公司饭于。全權(quán)所有蜀踏。 摘要: 本備忘錄描...
    一個(gè)人zy閱讀 1,887評(píng)論 0 9
  • 我叫一一,一個(gè)標(biāo)準(zhǔn)的巨蟹女镰绎,大大咧咧性格卻又敏感無(wú)比脓斩,從小立志找個(gè)白馬王子,他可以長(zhǎng)的不帥畴栖,但必須要高,可...
    漁一一閱讀 572評(píng)論 0 1