Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android中直播視頻技術探究之---桌面屏幕視頻數據源采集功能分析

Android中直播視頻技術探究之---桌面屏幕視頻數據源采集功能分析

編輯:關於Android編程

一、前言

之前介紹了Android直播視頻中一種視頻源數據采集:攝像頭Camera視頻數據采集分析中介紹了利用Camera的回調機制,獲取攝像頭的每一幀數據,然後進行二次處理進行推流。現在我們在介紹另外一種視頻源類型,屏幕桌面視頻數據源,這個就是錄屏功能,這個在Android中的利用場景現階段也是很多的,比如像斗魚這些直播app,在錄制游戲的時候用的還是比較多的,因為現在的移動游戲也那麼火,游戲視頻直播也是一個很不錯的產業!

 

二、技術方案

下面先來分析一下Android中錄制屏幕采用的方案有哪些?現階段Android中錄制屏幕的話大致就兩種方案:

1、Android5.0以下,獲取root權限使用adb shell screenrecord命令功能進行錄制

2、Android5.0以上,使用系統Api功能:MediaProjection和VirtualDisplay

這兩種方式其實在底層的實現機制是一樣的,因為在5.0之前,Google可能介於錄制屏幕功能具有一定的危險性,所以就沒有開放此功能,但是不知為何5.0開放了,當然開放了就立馬產生了一個漏洞,這個下一篇文章中介紹。從安全角度考慮,在屏幕截屏和錄制功能不應該暴露出來,因為這個功能太危險了,之前有報道某某APP利用這個功能,在後台錄制屏幕,然後傳遞到服務端,那麼當一個用戶在輸入賬號信息的時候,全部被錄制了,那麼就存在非常大的風險。

 

三、使用命令功能錄制視頻

下面先來介紹一下Android5.0一下錄制屏幕功能

Android中在截屏時可以使用adb shell screencap命令,錄制視頻時可以使用adb shell screenrecord,先來看看這個命令的用法:

\

(1)、基本使用
錄制默認分辨率,默認4Mbps,默認180s的視頻,保存到sdcard上名為FILENAME.mp4
$adb shell screenrecord /sdcard/FILENAME.mp4

(2)、指定分辨率(參數:--size)
//分辨率為112x112,建議不要指定分辨率,使用默認分辨率效果最佳
$adb shell screenrecord --size 112x112 /sdcard/FILENAME.mp4
注意:
分辨率不是完全可以隨意定制的,比如在我手機上錄制100x100的會提示錯誤:
$adb shell screenrecord --size 100x100 /sdcard/FILENAME.mp4

(3)、指定比特率(參數:--bit-rate)
設置比特率為8Mbps,比特率越大,文件越大,畫面越清晰
$adb shell screenrecord --bit-rate 8000000 /sdcard/FILENAME.mp4

(4)、旋轉(參數:--rotate)
旋轉90度
$adb shell screenrecord --rotate /sdcard/FILENAME.mp4

注意:
不支持聲音,如有需要,另外獨立錄制。此命令需要root權限才可以使用,這個也是已非常大的局限性!

 

下面來看一下案例:

使用adb shell screenrecord /sdcard/capture.mp4 命令錄制視頻存到SD卡中,然後在使用adb pull導出到本地即可

\

看看效果:

\

 

功能我們可以看到了,可以發現其實這個功能測試用的比較多,他們在測試的時候,有時候復雜的測試場景難以重現,就可以使用錄制屏幕功能,來跟蹤問題。

那麼現在如果一個應用獲取到了root功能,就開始偷偷的在後台錄制視頻,然後把錄制之後的視頻文件發到服務端,然後進行分析,那麼是非常危險的。

雖然這個功能可以了,但是我們發現,在直播的時候,如何進行數據流采取然後推流到服務端呢?因為在視頻采集推流的時候,都是獲取視頻流數據,在底層使用rtmp進行數據打包發送服務端,那麼這裡有人會想,能不能一邊錄制視頻到本地文件,然後一邊在去讀取這個文件流字節,進行推流?其實這種想法是好的,但是沒有那麼做的,因為這效率問題,其次是文件讀寫不同步問題,這裡有一個思路就是,看看adb screenrecord命令的源碼了,因為他最終是采樣數據寫到本地文件的,那麼在這個之前我們可以進行獲取視頻流即可,但是這個不是本文的重點,因為這個要是介紹的話,那就太多了,而且隨著Android系統提升,未來用的多的是Android系統更高版本,所以這裡要注重介紹的是5.0加的MediaProjection類來進行屏幕錄制。

 

四、使用開放Api進行錄制視頻

Android5.0中添加了一套Api來進行屏幕錄制功能,就是MediaProjection+VirtualDiaplay,用法也是非常簡單的,在使用之前需要申請一下權限,然後獲取權限之後,就開始使用即可!

第一、使用流程介紹

下面來看看使用流程:

1》使用getSystemService(Context.MEDIA_PROJECTION_SERVICE)方法獲取MediaProjectionManager對象

2》開啟授權Intent:startActivityForResult(mProjectionManager.createScreenCaptureIntent(),PERMISSION_CODE);

3》授權之後在onActivityResult方法中進行處理:

\

這裡看到了,利用返回的resultCode和data數據,得到MediaProjection對象,在注冊一個回調接口,這個接口就是監聽錄制的狀態信息,最後在創建一個VirtualDisplay

4》創建VirtualDisplay虛擬畫面

\

參數說明:

* 第一個參數:虛擬畫面名稱
* 第二個參數:虛擬畫面的寬度
* 第三個參數:虛擬畫面的高度
* 第四個參數:虛擬畫面的標志
* 第五個參數:虛擬畫面輸出的Surface
* 第六個參數:虛擬畫面回調接口

其中最重要的就是第五個參數,錄制畫面輸出的地方,他這裡介紹的是一個Surface類型,那麼我們如果想介紹錄制之後的視頻數據,就需要創建一個Surface類型即可。在這裡有三個方式創建Surface類型:

1》如果想截屏,那麼可以使用ImageReader類的getSurface方法獲取

2》如果想錄制視頻進行編碼,可以使用MediaRecorder類的getSurface方法獲取

3》最後如果想錄制視頻進行編碼,並且獲取視頻流的話,使用MediaCodec的createInputSurface方法獲取

這裡我們先介紹前面兩個功能,後續的那個功能再詳細介紹!

 

第二、截圖功能介紹

先來看看截圖功能,其實在Android中截圖大體上就三種方式:

第一種使用adb shell screencap命令,但是需要root權限

第二種使用getWindow().getDecorView()獲取當前Activity頁面的View數據,然後進行保存Bitmap,但是這種方式有限制,一個是他只能截取當前應用的圖,而且截取的圖片不包括狀態欄。

第三種使用MediaProjection和ImageReader來進行截圖

 

下面就來詳細介紹如何使用MediaProjection來進行截圖

\

先聲明一個ImageReader類,參數比較簡單,不過要注意的是這裡的尺寸高寬要和下面創建VirtualDisplay一直:

\

然後把ImageReader的getSurface設置成畫面的輸出即可。接下來就開始截圖:

\

從ImageReader中獲取Image對象,然後得到圖片字節數據,生成一個Bitmap即可。

下面來看看效果:

\

這裡把狀態欄也成功截取了!到這裡就實現了MediaProjection的第一個功能實現屏幕截圖功能。

 

第三、屏幕錄制功能介紹

這裡先使用MediaRecorder類進行數據的編碼工作,而我們真正要進行推流的話需要使用MediaCodec,因為我們需要獲取到編碼之後的視頻流數據,而MediaRecorder是做不到這點的,但是本文只是先介紹錄制功能,下一篇文章在詳細介紹MediaCodec類功能!

使用MediaRecorder類很簡單,以及後面介紹MediaCodec都一樣,首先是初始化設置編碼器的參數信息,而這些參數信息就那些:

視頻尺寸高寬、視頻幀率,視頻采樣率(碼率),視頻編碼格式等

但是MediaRecorder還需要一些其他設置,比如設置視頻來源,這裡一般就兩個來源,一個是攝像頭Camera,一個是Surface類型,還有就是視頻的輸出格式,以及視頻的輸出文件路徑等,當然MediaRecorder還支持音頻錄制,參數設置和視頻差不多:

\

這裡有一些默認格式參數選擇:

視頻編碼格式:default,H263,H264,MPEG_4_SP
獲得視頻資源:default,CAMERA
音頻編碼格式:default,AAC,AMR_NB,AMR_WB
獲得音頻資源:defalut,camcorder,mic,voice_call,voice_communication,voice_downlink,voice_recognition, voice_uplink
輸出方式:amr_nb,amr_wb,default,mpeg_4,raw_amr,three_gpp

初始化完了MediaRecorder之後,需要在調用prepare方法做准備,不然後續再調用getSurface會報錯的:

\

在調用這個方法的時候總是遇到這種錯誤,大致原因就是這個方法必須在prepare方法和stop方法中間調用,或者是視頻源必須是Surface類型的。下面再來看看創建VirtualDisplay類:

\

調用getSurface方法獲取到VirtualDisplay的輸出畫面。然後就需要調用開始編碼方法start即可。

 

下面來看一下效果:

\

首先先需要系統進行授權,點擊立即開始,就開始錄制編碼了,這裡把編碼之後的文件保存到sd中,我們在使用adb pull命令導出來,效果這裡就不演示了,和上面的adb shell screenrecord命令產生的效果一樣!

 

五、技術概要

1、介紹adb shell screenrecord命令錄制視頻,但是有局限性就是需要root權限

2、介紹了MediaProjection+ImageReader類進行截圖功能

3、介紹了MediaProjection+MediaRecorder類進行視頻錄制功能

 

六、遺留問題

采用MediaProjection和MediaRecorder錄制視頻,或者是命令錄制都是保存到本地文件了,但是在真正推流的過程中需要獲取到視頻流數據,所以這種方式不適合後續的推流工作,下一篇文章就要介紹如何MediaCodec進行視頻編碼,這個編碼類是可以獲取到編碼之後的視頻流數據的。

 

七、總結

Android中在5.0之後放出了錄制屏幕功能的api,但是其安全性還是值得考慮的,後續一篇文章就詳細介紹一個關於MediaProjection的漏洞,導致用戶的屏幕操作信息可能被洩露,而這些信息被洩露那麼就代表這用戶的賬號信息存在很大的風險,但是既然有著api了,那麼今年又是直播年,在錄制游戲這個產業中,這個功能也是無可厚非的重要!

 

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved