弓小影 張 超
基于軟件的TS流多畫面合成器的實現
弓小影 張 超
為了在有限的網絡帶寬環境下同時進行多路TS視頻流遠程實時傳輸,并能在VLC播放器中以單一TS流的形式播放,達到電視墻的效果,提出了基于軟件設計的TS流多畫面合成的設計方法,該軟件使用VS2005(Visual Studio 2005)在Windows平臺下開發,但很容易移植到Linux平臺,主要從UDP數據接受、TS流過濾、FFMPEG編解碼、畫面縮放、YUV畫面合成、UDP組播、并發處理等多方面系統的論述了設計思想。軟件最終經過嚴格測試,完全符合預期目的,實現了TS流的多源合一和遠程實時傳輸。
多畫面合成從視頻源的角度分為模擬視頻源多畫面合成和數字視頻源多畫面合成,從實現方法角度又可分為硬件多畫面合成器和軟件多畫面合成器。硬件多畫面合成器多以模擬視頻源為主,主要用于安防和模擬電視監控領域,軟件多畫面合成多是基于H.323協議的網絡IP數字視頻源為主,主要在視頻會議中應用。目前,在國家大力推動三網融合的政策支持下,數字電視、IPTV業務得到飛速發展,而又由于視頻源的限制,傳統的多畫面合成技術無法應用到數字電視、IPTV監控領域中。為了解決三網融合背景下的信源監控問題,本文提出了基于軟件的TS流多畫面合成技術,最終通過軟件編程完成了產品試制。
本文所指的TS流多畫面合成是將通過UDP協議傳輸的多個TS流視頻源合成為一個統一的TS流視頻源,再經組播輸出,最終在VLC播放器中以多畫面形式播放,合成以后形成電視墻的效果,屬于用軟件方法實現的多源合一數字多畫面合成的一種,主要用于數字電視、IPTV、視頻會議、視頻監控等信源監控領域,由于合成后的畫面只占用一個TS流帶寬,相當于原流的1/n(n為畫面個數),特別適合遠程實時傳輸。輸入的TS流信號源可以是SPTS,也可以是MPTS,為了支持兩種情況,需要對信號源進行解復用,設置PID過濾器,來實現對單節目的解碼。合成以后的TS流只需保留視頻部分,音頻是不需要的。對信源的解碼,畫面縮放,以及視頻壓縮,使用跨平臺的多媒體開發庫FFMPEG SDK來實現。
畫面合成技術要求待合成源各幀率相同,在合成過程中,從每個解碼后的源各取一幅圖像,進行畫面合并,因此不同幀率的源是無法合成在一起的。
設計目標
支持單播,組播接收;
支持SPTS和MPTS兩種TS流,根據PID列表進行節目過濾;
支持MPEG2,H264的視頻解碼;
支持H264格式視頻編碼,并且可調整碼率與分辨率;
支持2x2,3x3,4x4等拼接模式的選擇;
支持動態源切換,系統啟動后,可以隨時將某個源替換為別的節目源;
支持編碼后的數據組播發送,使VLC正常播放,因為UDP流有最高的實時性;
高可靠性,信號不穩定的源不影響正常的畫面合成。
組件設計
畫面合成系統主要由UDP接收,視頻解碼,縮放,畫面拼接,視頻壓縮,UDP發送等主要部分組成(如圖1所示)。
FFMPEG本身支持UDP源,但不支持從MPTS中選擇一路進行解碼,因此需要設計實現UDP接收部分,進行PID過濾,通過FFMPEG的IO回調函數傳遞進行解碼。類似的,UDP發送在FFMPEG也是支持的,但FFMPEG的UDP發送沒有流量控制,輸出TS流PCR抖動過大,而VLC在播放UDP源時對輸入流精度要求很高,PCR抖動過大的TS流在播放時會造成緩沖的上溢或下溢,導致播放卡頓等問題,因此需要設計實現UDP發送來精確控制發送速度。
輸入
從單播/組播接收TS數據,根據設置的PID列表進行過濾,輸出單節目TS流,FFMPEG正常解碼需包含PAT、PMT、PCR、VIDEO四個PID的數據。包含這些PID的TS包都應送入FFMPEG解碼器。
FFMPEG編解碼
使用FFMPEG SDK進行視頻解碼,通常TS流
中可能包含MPEG2與H264兩種視頻類型,FFMPEG對兩種視頻的解碼都支持,并且在代碼實現過程中不需要在代碼上加以區分,相當于不必關心視頻類型,將解復用,視頻類型識別,視頻解碼封裝在一個黑盒中,解碼完畢后原始圖像被輸出到YUV緩沖,極大的方便了多媒體開發。
將多個畫面進行合成后的原始圖像需要進行
壓縮編碼,合成TS流后進行網絡發送。使用FFMPEG進行壓縮可以在壓縮完畢后直接打包為TS,不需要編碼進行容器封裝。因此輸入FFMPEG編碼器的數據為YUV,從編碼器輸出的數據為TS。在視頻類型的選擇上,我們使用“高級視頻編碼”AVC類型。進行AVC視頻壓縮較MPEG2耗費更多的CPU資源,但有著更高的壓縮率。當今CPU的發展,性能已不是限制使用AVC的瓶頸。

畫面縮放
由于將多個源視頻畫面最終合并到一個屏幕
輸出,因此需要將解碼后的源視頻縮放,例如,輸出畫面大小為704x576,畫面拼接模式為2x2,那么每個源畫面都要縮放為寬:720/2 = 352,高:576/2=288。YUV縮放通過FFMPEG攜帶的libswscale庫實現。
基于YUV的畫面拼接
FFMPEG解碼縮放以后的原始圖像為YUV數據,因此為了避免多余的數據轉換,我們在YUV層進行畫面拼接。為了將源圖像每像素放置到目標圖像的對應位置,我們需要了解YUV圖像格式。
數字圖像原理
數字圖像由三原色:紅、綠、藍組成,即:RGB。每個像素由這三原色的不同取值確定,再由一定數量的像素組成完整圖像。以真彩色(24位)為例,每個像素由三個字節表示,三原色各占一個字節,這是RGB格式圖像在數據上的表示方式。由于人類對亮度信息更敏感,因此舍棄部分色度信息,在不明顯影響圖像效果的前提下,極大的降低了占用空間。YUV因此而生,YUV分為三個分量,“Y”表示明亮度(Luminance或Luma),也就是灰度值;而“U”和“V” 表示的則是色度(Chrominance或Chroma),作用是描述影像色彩及飽和度,用于指定像素的顏色。
YUV采樣方式
YUV碼流的存儲格式其實與其采樣的方式密切相關,主流的采樣方式有三種,YUV4∶4∶4,YUV4∶2∶2,YUV4∶2∶0,FFMPEG解碼后的屬于YUV4∶2∶0,這里我們需要關注的是如何根據其采樣格式來從碼流中還原每個像素點的YUV值,正確地還原每個像素點的YUV值。
用三個圖來直觀地表示采集的方式(如圖2所示),以黑點表示采樣該像素點的Y分量,以空心圓圈表示采用該像素點的UV分量。
YUV 4∶4∶4采樣,每一個Y對應一組UV分量。

圖2 YUV采樣方式

圖3 YV12,YU12格式存儲方式
YUV 4∶2∶2采樣,每兩個Y共用一組UV分量。
YUV 4∶2∶0采樣,每四個Y共用一組UV分量。
存儲方式
不同格式的YUV存儲方式不同,由于我們只用到YUV4∶2∶0格式,下面只給出這種格式的存儲方式,并在存儲方式后面附有取樣每個像素點的YUV數據的方法,其中,Cb、Cr的含義等同于U、V。
(1)YV12,YU12格式(屬于YUV420)如圖3所示。
YU12和YV12屬于YUV420格式,它是一種Plane模式,即打包模式,并不是將YUV數據交錯存儲,而是先存放所有的Y分量,然后存儲所有的U(Cb)分量,最后存儲所有的V(Cr)分量,如圖3所示。將Y、U、V分量分別打包,依次存儲。其每一個像素點的YUV數據提取遵循YUV420格式的提取方式,即4個Y分量共用一組UV。注意,上圖中,Y’00、Y’01、Y’10、Y’11共用Cr00、Cb00,其他依次類推。
(2)NV12、NV21(屬于YUV420)
NV12和NV21屬于YUV420格式,是一種twoplane模式,即Y和UV分為兩個Plane,但是UV(CbCr)為交錯存儲,而不是分為三個plane。其提取方式與上一種類似,即Y’00、Y’01、Y’10、Y’11共用Cr00、Cb00(如圖4所示)。
FFMPEG解碼后的屬于第一種Plane模式,這也是最常用的模式。
畫面拼接
基于Plane模式,畫面拼接時應先由源畫面大小、拼接模式確定輸出畫面大小,然后計算YUV各分量在源、目標畫面的位置,最后,將源YUV數據分別拷貝到目標圖像的對應行和列。圖5表示拼接后各畫面關系。
其中,計算畫面所占字節數方式為:
畫面大小 = ((寬*高*3)>>1)
計算YUV各分量寬高信息:
Y_Width= ImageWidth;
Y_Height= ImageHeight;
U_Width= ImageWidth>>1;
U_Height= ImageHeight>>1;;

計算YUV各分量在畫面中的偏移:


圖4 NV12、NV21格式存儲方式

圖5 拼接后畫面關系
根據每個源畫面所在字畫面的位置(所在行與列)計算各分量在目標畫面中的偏移:
iYStartDest=Dst_Y_Width*SrcImageHeight*row + Src_Y_Width*col;
iUStartDest=Dst_U_Offset+Dst_U_Width*Src_ U_Height*row + Src_U_Width*col;
iVStartDest = Dst_V_Offset + Dst_V_Width * Src_V_Height*row + Src_V_Width*col;
最后將各分量數據拷貝到目標畫面對應偏移地址。
拼接完畢后各YUV各分量間關系,如圖6所示。
輸出
FFMPEG輸出UDP精度問題
FFMPEG的UDP輸出沒有足夠的精度使VLC正常播放。可以使用TS分析工具EasyICE測量FFMPEG輸出UDP的PCR精度情況:
使用命令啟動FFMPEG進行轉碼:
ffmpeg -i udp∶//239.0.0.1∶1234 -c∶v h264 -f mpegts udp∶//239.0.0.2∶1234
上面的命令將使FFMPEG從239.0.0.1∶1234接收組播數據,進行轉碼后發送到239.0.0.2:1234,啟動EacyICE從239.0.0.2∶1234接收數據進行分析,可以看出PCR抖動比較大(如圖7所示)。
發送速度控制
為了進行精確的UDP推流,需要對發送速度進行控制。避免PCR抖動的關鍵在于根據TS流中的PCR時間計算出推流時間,使每個TS包都在精確的時刻到達。根據兩個PCR包的間隔,可計算出兩個PCR之間每個TS包的PCR間隔值:
PCR_Per_Packet = (PCR_Second - PCR_First) / TS_Packet_len
進一步可計算出某個TS包的PCR時間:
PCR=PCR_First+PCR_Per_Packet*Ts_ Packet_Counter

圖6 拼接完畢后各YUV各分量間關系

圖7 PCR抖動圖形
現在我們已經得出每個TS包應該在哪個時刻進行發送,如果時間沒到就進行等待。按照這種進行推流,可以得到高精度的推流質量。
在實際的應用過程中,每個TS包并不是單獨發送的,為了提高網絡利用率,每個UDP包攜帶若干個TS包,而避免網絡包分片,UDP包的大小應小于網卡的MTU大小。在linux,windows,osx等PC、服務器操作系統平臺,MTU值默認為1500,嵌入式設備可能較小。我們需要將數據發送到PC或服務器,因此面對的MTU為1500。除去IP頭:20字節,UDP頭:8字節,剩余1472字節,TS包大小為188,存放完整的TS包可以放7個。即,使用1316字節。剩余156字節不使用。
UDP發送時以7個TS包為單位,按照計算出的PCR時間與系統時間同步后控制發送時機,最終得到滿意的效果,VLC播放流暢,日志不再報告丟棄緩沖等錯誤。使用EasyICE測量輸出抖動情況,已經在很小的范圍:
整體抖動在10毫秒之內,已經是VLC等解碼器能夠接受的誤差。受網絡條件如路由選擇,系統條件如計算機時鐘精度,網卡延遲等影響,沒有誤差是不可能的。
并發處理
視頻解碼,視頻壓縮等都是比較耗費CPU資源的操作,而我們的系統需要實時處理,必須開展并行計算才能完成。在當今多核或多CPU的系統中,繁忙線程會被分配到空閑CPU核心去完成,充分的利用CPU資源。為此,將各模塊依據各自特性及依賴關系,分為多線程進行處理。
UDP源接收,解碼,縮放線程
每個解碼器有單獨的線程,FFMPEG解碼器通過讀取回調函數接收UDP,因此UDP接收需要采用異步模式。當一幅圖像解碼出來時,再進行YUV縮放,本線程最終輸出的是縮放以后的YUV畫面,他將這些畫面放入線程安全的緩沖中,以便進行下面的處理
畫面拼接,視頻壓縮線程
從緩沖獲取縮放后的YUV畫面,送入FFMPEG進行編碼。編碼產生的數據存入發送緩沖等待發送

圖8 合成效果圖

圖9 cpu占用情況

圖10 某個源失效后的合成圖
數據發送、流控線程
從緩沖獲取待發送數據,根據流控算法進行發送。
核心管理器
為實現動態源切換,適應不穩定的網絡源,需要設計核心管理器協調各組件間關系。核心管理器類似Directshow中Grahp的概念,而各組件相當于Filter。
核心管理器主要有以下功能:
協調各組件之間數據傳遞
協調各組件之間狀態的改變,從而支持不穩定的源以及源切換
提供動態源切換接口
由于各解碼線程不會在同一時間輸出畫面,一定有快有慢,為此需要等待YUV緩沖有輸出,而考慮到源不一定有效,例如某個源信號異常消失,又不能一直等待。因此需要有條件的等待,檢查數據可讀條件,有以下兩種情況可以進行讀取:
(1)YUV緩沖使用量超過門限,例如80%
(2)源可用,并且YUV緩沖不為空。
無論在任何情況下 ,如果某個源YUV緩沖已使用超過80%,則不再等待其他源,此時應到各路源中取畫面進行拼接、編碼。這種機制保障正常的源輸出一定不會延誤。第二種機制,如果某個正常解碼器還沒有畫面輸出,則進行等待。這種機制保障每個源的畫面都不會丟失。
當需要動態切換源時,先將新源準備就緒,然后替換指定源,銷毀被替換源解碼器,釋放資源。
等待新的源解碼成功需要一定時間,而且源不一定可用,可能收不到數據,或者其他異常導致無法解碼,因此等待新源準備就緒需設置超時時間,不能一直等待。
以2x2拼接模式為例,使用同一個源模擬四個不同源,首先測試四個源正常情況下的合成效果(如圖8所示)。
輸入視頻類型MPEG2,輸出畫面大小720x576情況下,Intel i7 CPU占用情況(如圖9所示)。
四路MPEG2解碼,一路H264實時壓縮,整體CPU使用率在30%以下。普通PC機就可以正常部署。
測試某個源失效的情況(如圖10所示)。
可以看出正常的源沒有受影響,正確輸
本文系統地論述了基于軟件實現的TS流多畫面合成的技術架構及關鍵流程,各個組件經過白盒測試工作正常。長時間運行測試及長時間頻繁進行動態源切換測試,程序沒有內存泄露。為了節省計算量,直接在YUV層進行畫面拼接,提高了運行效率,使用并發的開發模式,充分利用CPU資源。對輸出TS流根據PCR進行流控,提高了推流精度,彌補了FFMPEG輸出UDP抖動過大問題。最終實現了高效率,高可用性,高可靠性的TS流多畫面合成系統,可以廣泛應用于數字電視、IPTV、視頻會議、視頻監控,信號源檢測等領域。
10.3969/j.issn.1001-8972.2015.21.027