雖然還有一年才畢業但畢業設計我已經作完了,大約用了3個月時間。我是個急性子並且對感興趣的知識有非常強烈的學習欲,另外總想多寫一些其他的知識,像
ARM,linux,網路我都高度興趣。這學期開始選題的時候我鬼使神差的選擇了視頻編碼,題目是基於DM642的H.264視頻編碼器實現與最佳化,開題
答辯的時候所長說重點應該放在實現和應用上,一般公司最佳化都是很多人去做的。做著做著我又對網路感興趣索性就加了網路部分,所以到最後基本上成為網路攝像
頭的雛形。
它的基本過程是採集網路攝影機視頻(YUV4:2:2),轉換成YUV4:2:0,採用H
.264編碼,PC機TELNET到DSP,發送命令,就可以接收到DSP傳來的碼流,最後解碼並顯示。視頻大小為QCIF,UDP協議,DHCP動態獲
得IP,PC端主程式解碼,另外建立兩個線程分別接受碼流和顯示映像。DSP採用DSP/BIOS系統架構,初始化網路和網路攝影機驅動之後就等待PC發命
令。
對DM642編程有點複雜,剛開始看常式無從下手,雖說是C語言,可是一堆的驅動以及CSL、BSL都需要慢慢熟悉。網路攝影機驅動FVID使用還算可
以,FVID_alloc(),FVID_exchange()就基本能滿足要求,加上一個while就構成主體迴圈。網路攝影機獲得的YUV422轉化為
YUV420,這裡我沒有採用標準的轉換,我當初就理解為隔行保留就可以了,所以就用DAT_copy()複製亮度和DAT_copy2d()簡單的從緩
沖區隔行複製色度到預編碼資料區。T264_encode()是編碼程式,其主體函數從T264中以dependent project
加入到主project中,我將其中大約50個c子程式用線性彙編或者內連函數改寫,可以達到17幀的編碼速度,主觀感覺編碼之後的視頻不卡。這裡我不得
不說對編碼程式的最佳化這一塊,另起一段吧。
我主要的精力都放在最佳化上了,但感覺就像個無底洞一樣,自己沒有能力也不想花太多的時間在這上面,編碼速度總是無法再有質的飛躍,當初從4幀提升到17幀
(對於highway.qcif這樣的視頻序列模擬甚至能達到21幀)著實把我高興壞了,對EDMA和CACHE的利用和最佳化好像總是隔著一層紗,深深感
到自己能力有限沒法體會精髓,我總想找個高手能指點我一下,一直不能如願,哎,真是人生得一知己足矣,一個志同道合的人只能是靠緣分了,可遇而不可求
啊!50個子函數的改寫也把我累壞了,想想那些個日子從早上8點到晚上11點都是在寫彙編函數,還真有點懷念,看見速度一點一點地提高是我最大最大的欣
慰。把50個函數都寫一遍後發現編碼之後的映像發生嚴重失真,肯定是彙編指令用錯了或者壓根程式就讓我編錯了,我不得不重新檢查每一個函數(當初我每一個
函數都會用一組資料分別測試原C函數和我改寫的組譯工具是否能達到一樣的結果,可還是大意了,有些程式雖然對大多數資料都能得到一樣的結果,但有些"極
端"資料卻不能達到一樣的結果,這也是後來才慢慢體會到的,使用彙編指令要對移位,溢出等情況詳加考慮,不然等著傻眼吧,像LDB和LDBU,ROTL和
SHL,SHR和SHRU等就是最容易用錯的),即使這樣這一遍過後映像還是有些失真,我又對一些函數排除檢查,終於達到良好的效果,我很欣慰。
網路部分參看NDK開發文檔,如果有WINDOWS下網路編程經驗就可以很輕鬆的上手,我就是先看了WINDOWS下socket編程,編了幾個TCP UDP的程式,然後就可以十分輕鬆的編程,痛點是初始化和熟悉過程。
PC機的解碼和顯示程式是T264內建的,看懂了程式架構之後加入網路線程,從DSP接收碼流然後解碼顯示,原始程式是從本地磁碟讀檔案解碼顯示。採用消
息驅動接收碼流,線程間共用碼流變數和一些同步變數,在這裡又對volatile和extern以及WIN32編程有了進一步理解。
所有這一切的前提是要熟讀H.264編碼通訊協定文檔,幾百頁吧,以及看懂T264編碼程式,我的編碼程式都加上了注釋,以後複習能更快上手。這其實是很費時間和精力的,但我樂在其中。