重慶郵電大學(xué)光電工程學(xué)院 徐 賀 鄧宇靜
基于多線程的視頻采集系統(tǒng)
重慶郵電大學(xué)光電工程學(xué)院 徐 賀 鄧宇靜
使用windows的多線程技術(shù)設(shè)計(jì)和實(shí)現(xiàn)了的視頻采集系統(tǒng),為了保證數(shù)據(jù)的實(shí)時(shí)性和完整性,在程序中加入了對(duì)數(shù)據(jù)的隊(duì)列操作。實(shí)驗(yàn)證明該系統(tǒng)具有良好的靈活性、擴(kuò)展性。
多線程;視頻采集;視頻編碼
在實(shí)時(shí)視頻數(shù)據(jù)采集過程中,常常會(huì)有“響應(yīng)慢、卡頓”等問題,影響用戶體驗(yàn)及感受。“響應(yīng)慢” 往往是因?yàn)橄到y(tǒng)中部分經(jīng)常執(zhí)行的業(yè)務(wù)如圖像格式轉(zhuǎn)換、視頻編碼占用了大量的硬件資源。為此本文采用基于多線程和隊(duì)列的技術(shù),從軟件角度進(jìn)行了優(yōu)化,縮小了響應(yīng)延遲,提高了用戶體驗(yàn)。
在Windows操作系統(tǒng)下,每個(gè)線程被分配了不同的時(shí)間片,在某個(gè)時(shí)刻,CPU僅執(zhí)行一個(gè)時(shí)間片內(nèi)的線程,多個(gè)時(shí)間片中的相應(yīng)線程在CPU內(nèi)輪流執(zhí)行,由于每個(gè)時(shí)間片的時(shí)間很短,所以對(duì)用戶來說仿佛各個(gè)線程在計(jì)算機(jī)中時(shí)并行處理的一樣[1]。為此,我們不采用阻塞式同步消息處理機(jī)制,而采用異步的消息處理機(jī)制,其具體工作示意圖如下所示:
圖1 多線程下視頻采集系統(tǒng)示意圖
其中,視頻源包括攝像頭、Windows桌面,也可擴(kuò)展為本地文件。視頻采集線程、視頻編碼線程一直在后臺(tái)運(yùn)行,線程數(shù)據(jù)交互采用隊(duì)列的方式進(jìn)行,為了避免多線程下數(shù)據(jù)錯(cuò)誤造成程序死鎖等現(xiàn)象,采用關(guān)鍵代碼段進(jìn)行數(shù)據(jù)保護(hù),即使用臨界區(qū)時(shí),各個(gè)線程共享一個(gè)對(duì)象,無論哪個(gè)線程占用臨界區(qū)對(duì)象時(shí),都可以訪問受保護(hù)的數(shù)據(jù)。而其他線程需要等待,直到一個(gè)線程釋放了臨界區(qū),另一個(gè)線程才可以訪問。
3.1 異步多線程的優(yōu)缺點(diǎn)
可以將采集、編碼以及傳輸分成多個(gè)部分,每個(gè)部分僅處理當(dāng)前任務(wù),將暫時(shí)不需要處理的數(shù)據(jù)放入隊(duì)列中,下一部分將從隊(duì)列中進(jìn)行讀取數(shù)據(jù),并不直接響應(yīng)上次操作。所以可以充分的利用系統(tǒng)資源、有效的降低系統(tǒng)響應(yīng)時(shí)間,提高系統(tǒng)的穩(wěn)定性[2]。
與之對(duì)應(yīng)的異步多線程在本系統(tǒng)也存在著些缺點(diǎn),將一次任務(wù)分為多個(gè)步驟進(jìn)行執(zhí)行。用戶僅能從最后步驟中判斷結(jié)果是否正確。如果最后一個(gè)步驟中出現(xiàn)異常情況,就可能造成結(jié)果與期待結(jié)果不一致,所以采用異步多線程需要注意代碼的穩(wěn)定性。
3.2 線程間隊(duì)列技術(shù)
隊(duì)列是一種先入先出的線性表,在使用隊(duì)列時(shí)我們需要根據(jù)音視頻數(shù)據(jù)對(duì)隊(duì)列進(jìn)行格式封裝[3]。使隊(duì)列中,每個(gè)視頻幀單獨(dú)作為一個(gè)存儲(chǔ)塊,每個(gè)存儲(chǔ)塊包括數(shù)據(jù)大小、占用標(biāo)志位等信息,當(dāng)寫入信息時(shí),將數(shù)據(jù)保存到指定區(qū)域,并標(biāo)志位置1,當(dāng)讀出消息后,清空指定區(qū)域數(shù)據(jù),標(biāo)志位置0。等待下次使用,如果隊(duì)列大小不夠,使用遞歸的方式自動(dòng)擴(kuò)展隊(duì)列大小。其主要函數(shù)如下所示:(1)建立隊(duì)列 CreateQueue();(2)從隊(duì)列中寫入數(shù)據(jù) WriteToQueue();標(biāo)志位置1;(3)從隊(duì)列中讀取數(shù)據(jù) ReadFromQueue();標(biāo)志位置0。
3.3 異步多線程下的功能實(shí)現(xiàn)
根據(jù)異步多線程和隊(duì)列的特點(diǎn)。以視頻為例,本文主要利用ffmpeg開源庫(kù)進(jìn)行采集視頻數(shù)據(jù),然后利用libx264進(jìn)行編碼,然后通過相關(guān)網(wǎng)絡(luò)協(xié)議進(jìn)行網(wǎng)絡(luò)數(shù)據(jù)傳輸。
3.3.1 基于ffmpeg的視頻采集的實(shí)現(xiàn)
由于在此編碼器中,我們最終獲取到到的視頻分辨率為640*480,并且在使用libx264庫(kù)進(jìn)行編碼時(shí)需要輸入的數(shù)據(jù)為YUV420格式。而通過ffmpeg進(jìn)行采集生成的數(shù)據(jù)一般為YUV422格式,所以要利用ffmpeg庫(kù)函數(shù)sws_scale()進(jìn)行圖像尺寸和格式變化。
在使用sws_scale()函數(shù)之前,首先要對(duì)ffmpeg進(jìn)行初始化,注冊(cè)所有文件格式和編解碼器,利用avformat_open_input()打開視頻源,利用avformat_find_stream_info()查找到視頻流,利用avcodec_decode_ video2()進(jìn)行視頻解碼,最后在函數(shù)sws_scale()函數(shù)中使用雙三次插值算法得到Y(jié)UV420數(shù)據(jù),并將數(shù)據(jù)寫入到隊(duì)列中。
3.3.2 基于libx264的視頻編碼的實(shí)現(xiàn)
再使用libx264編碼器之前,首先要設(shè)置編碼器的碼率方式及大小、編碼像素格式、利用zerolatency方式設(shè)置實(shí)時(shí)性、利用定時(shí)器設(shè)置幀率。其中碼率采用恒定平均碼率ABR的方式進(jìn)行碼率控制,它是CBR和VBR的一種折中優(yōu)化方案。關(guān)鍵參數(shù)如下所示:
m_param.i_fps_num = 25;
m_param.i_fps_den = 1;
m_param.rc.i_bitrate = 330;
m_param.rc.i_rc_method = X264_RC_ABR;
打開編碼器后,利用x264_encoder_encode()函數(shù)將一幀圖像編碼為h.264格式,并以結(jié)構(gòu)體x264_nal_t的形式輸出即可。
本文詳細(xì)介紹了基于多線程的音視頻采集、編碼傳輸?shù)倪^程和實(shí)現(xiàn)方式。其中利用異步多線程有效的降低了系統(tǒng)響應(yīng)時(shí)間,提高了視頻轉(zhuǎn)播過程中實(shí)時(shí)性的要求,同時(shí)節(jié)約了系統(tǒng)資源;最后利用相關(guān)網(wǎng)絡(luò)協(xié)議進(jìn)行視頻網(wǎng)絡(luò)傳輸,實(shí)驗(yàn)表明,本模塊可以用于構(gòu)建實(shí)時(shí)采集轉(zhuǎn)播系統(tǒng)。
[1]常發(fā)亮,劉靜.多線程下多媒體定時(shí)器在快速數(shù)據(jù)采集中的應(yīng)用[J].計(jì)算機(jī)應(yīng)用,2003,23(S1):177-178.
[2]周方.基于隊(duì)列和多線程的異步消息處理[J].中國(guó)水運(yùn):理論版,2007,5(5):166-167.
[3]王孟祿,李浩,張鐳.基于多線程和隊(duì)列操作的TCM上位機(jī)系統(tǒng)設(shè)計(jì)[J].河南大學(xué)學(xué)報(bào)(自然版),2016,46(1):96-101.
徐賀【通訊作者】(1985—),男,黑龍江哈爾濱人,碩士,主要研究方向:流媒體及視頻編解碼。
鄧宇靜(1993—),女,重慶人,碩士,主要研究方向:流媒體及視頻編解碼。