2008年6月7日 星期六

Android上面呼叫 ffmpeg 解壓縮的播放程式


這禮拜五完成一支 可以在Android上面呼叫 ffmpeg 解壓縮的播放程式,這支程式的架構是目前計畫的目標,在 Android 上打出一條路徑可以讓硬體 執行解壓縮。

雖然之前就有做出雛形,但是因為 IPC 控制機制設計不好,所以程式容易 Crash ,另外也容易產生 memory leaking。

最後在本週五下班之前修改出來,每 110ms 可以解壓縮完一張 H.264的 Frame,程式不會 Crash。也能夠控制程式的關閉暫停等等,實在非常感動 努力了三個月終於有一支可以上檯面交差的程式了。( 備註一下 110ms 的時間測量方式 我是採用 clock() 這個 system call 測量得知的 )

在這段撰寫程式的這段時間中, 我遇到了 java threading、同步等兩大難題, 要在 java 裡面做 thread 控制,要在 jni 與 ffmpeg decoder 之間做 ipc 控制。

java threading 算是比較簡單且容易撰寫,但需要閱讀的文件也是最多的。不習慣 synchronized 這種 coding 方式。另外 Thread 要呼叫某個 class的方法必須透過 Android Handler,但是 Handler 沒有 message filter 的功能所以必須自己設計。這大概是我覺得重點的地方。

同步通訊的部份,我用 FIFO ( mkfifo ) 的方式,開通兩個 fifo 讓兩支程式做溝通,傳控制訊息。 至於解開後的 raw data ( RGB32 ) 則適用 memory mapping i/o 的方式,讓 jni 與 ffmpeg decoder 共用同一個 page 降低搬移與傳輸資料的成本。

這邊不得不提一下為何要用 RGB32,因為 FFmpeg 解壓縮的單位是 byte,如果你用 RGB16 就是佔兩個 bytes,RGB24 就是三個。但是 Android 的 Bitmap 可讀取資料來源 array 是 int 格式, 在 java 的定義中是佔了 4 bytes ,所以用 RGB32 可以避免掉 Align data 的時間。

如果加上 SetIntArrayRegion(env, iarr, 0, size, tmp); 就可以輕鬆的把解壓縮完後的 data 傳完 java (但是 Bitmap 那邊要選用 ARGB888 的 config )。

另外還有一件事情就是論文被通知 accept 。
最後感謝跟我一起工作的同事們,沒有你們互相切磋 這隻程式沒法完成,謝謝你們。
這一周真的既勞累又充實, 疲勞都被成功的喜悅給淹沒了。
(加班三天~~ 囧!!)

沒有留言: