Android 與網路攝影機(2)

在可以播放以後,會想到的是能不能順便錄影?

Android 上的錄影在網路上可以找到的範例,多半是用既有的 MediaRecorder (Android 應用程式開發:如何錄製影片) 或是發 Intent 給可以錄影的 app (Recording Videos Simply) 來做。由於之前選用的是 Motion JPEG,這兩個方法都不可行。MediaCodec 似乎可用,但沒認真去找範例。

延續前篇,看了 MjpegView 原始碼,裏面的 MjpegViewThread 是使用 MjpegInputStream 在讀取 Motion JPEG,讀到一張圖,就畫在 SurfaceView 上。在 StackOverflow 上有看到 jcodec,可以餵給他 bitmap ,然後會壓縮出 H.264 影片。這正好是我所需要的,就拿來試試看了。

套用以後的結果放在 github 上,這裡就不貼程式碼了。實際上,jcodec 是合用,而且有特別針對 Android 提供一些方便的 Helper function,但是還是有缺點,第一個文件不是很齊全,StackOverflow 上能找到的 jcodec 範例或多或少都有點問題,建議是去下載最新的版本,然後參考裏面的 example 來使用;第二個是編碼後的影片不是每個裝置都能播放,電腦上播放倒是沒問題。第二個問題還蠻大的,關於這點,有人回報給 jcodec 的 issue tracker 了:Generate MP4 viewable on all versions of Android? · Issue #25 · jcodec/jcodec

後來沒繼續再深究下去,僅針對曾經有看過的部份做個筆記,就這樣。

Android 與網路攝影機(1)

大部份網路攝影機都會提供多種格式,例如 AVI、Motion JPEG 等等,這邊我選擇的是 Motion JPEG,主要原因是 Android 有直接支援這種格式 ,不會牽涉到「可能沒有解碼器」的問題。

首先是環境的準備,因為手頭沒有一般市售的網路攝影機,只好搭配手頭上有的 USB Cam ,克難的自己弄一個。 很幸運,正好有人用 python + OpenCV 寫了一個簡單的 Streaming Server,輸出格式正好就是 Motion JPEG ,網址是 https://gist.github.com/n3wtron/4624820

然後播放的部份,我是參考 StackOverflow 上的這篇 Android and MJPEG – Stack Overflow ,程式主要是繼承 SurfaceView 做出 MjpegView 來使用,MjpegView 裡則使用 thread 搭配 MjpegInputStream 去讀取指定位址的 Motion JPEG,進行播放。但這個程式有一個小問題,在 Android 3.0 以後,以 HttpClient (MjpegInputStream 裡使用了 HttpClient )去讀取網路資源時,會丟出 NetworkOnMainThreadException 。因此需要對程式進行改寫。

很幸運,StackOverflow 又有人提出解:Android ICS and MJPEG using AsyncTask – Stack Overflow 。這樣拼拼湊湊之下,要播放網路攝影機上的影像不是難事。

P.S. StackOverflow 上的範例程式有個問題,就是沒妥善處理 onPause/onResume,因此在按 Home 或切到別的程式再回來時,會沒辦法繼續播放。