Android視頻錄-MediaProjection

MediaProjection

android在5.0系統(tǒng)之前森爽,是沒有開放視頻錄制的接口的,如果要錄制視頻,必須要先root。
在5.0步做,Google終于開放了視頻錄制的接口(其實嚴格來說伦籍,是屏幕采集的接口)嫩舟,也就是MediaProjectionMediaProjectionManager声功。

首先來說MediaProjectionManager,它是一個系統(tǒng)級的服務(wù)执桌,類似WindowManager鄙皇,AlarmManager等,你可以通過getSystemService方法來獲取它的實例:

MediaProjectionManager mMediaProjectionManager = (MediaProjectionManager) getSystemService(MEDIA_PROJECTION_SERVICE);

獲取到實例后仰挣,錄像的過程如下
首先:

Intent captureIntent = mMediaProjectionManager.createScreenCaptureIntent();
startActivityForResult(captureIntent, REQUEST_CODE);

createScreenCaptureIntent方法的注釋如下:

/**
 * Returns an Intent that <b>must</b> passed to startActivityForResult()
 * in order to start screen capture. The activity will prompt
 * the user whether to allow screen capture.  The result of this
 * activity should be passed to getMediaProjection.
 */

大致意思是伴逸,這個方法會返回一個intent,你可以通過startActivityForResult方法來傳遞這個intent膘壶,為了能開始屏幕捕捉错蝴,activity會提示用戶是否允許屏幕捕捉(為了防止開發(fā)者做一個木馬洲愤,來捕獲用戶私人信息),你可以通過getMediaProjection來獲取屏幕捕捉的結(jié)果顷锰。

createScreenCaptureIntent的代碼我們可以看一下:

public Intent createScreenCaptureIntent() {
        Intent i = new Intent();
        i.setClassName("com.android.systemui",
"com.android.systemui.media.MediaProjectionPermissionActivity");
        return i;
}

所以這里是創(chuàng)建了一個隱式的intent柬赐,用來調(diào)用系統(tǒng)的錄屏程序。

然后正如上面的注釋所說官紫,我們通過startActivityForResult來傳遞這個intent肛宋,所以我們可以通過onActivityResult來獲取結(jié)果,通過getMediaProjection來取出intent中的數(shù)據(jù):

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (requestCode != PERMISSION_CODE) {
            Log.e(TAG, "Unknown request code: " + requestCode);
            return;
        }
        if (resultCode != RESULT_OK) {
            Toast.makeText(this,
                    "User denied screen sharing permission", Toast.LENGTH_SHORT).show();
            return;
        }
        mMediaProjection = mProjectionManager.getMediaProjection(resultCode, data);
        mMediaProjection.registerCallback(new MediaProjectionCallback(), null);
        mVirtualDisplay = createVirtualDisplay();
}

我們通過getMediaProjection獲取到mediaProjection束世,并注冊了一個callback回調(diào)酝陈。
看看createVirtualDisplay做了什么:

private VirtualDisplay createVirtualDisplay() {
        return mMediaProjection.createVirtualDisplay("ScreenSharingDemo",
                mDisplayWidth, mDisplayHeight, mScreenDensity,
                DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR,
                mSurface, null /*Callbacks*/, null /*Handler*/);
}

可以看到,我們調(diào)用了MediaProjection的createVirtualDisplay方法良狈,來創(chuàng)建了一個VirtualDisplay的實例后添,說幾個createVirtualDisplay的參數(shù)含義:

name: 是生成的VirtualDisplay實例的名稱笨枯; 
width, height: 分別是生成實例的寬高薪丁,必須大于0; 
dpi: 生成實例的像素密度馅精,必須大于0严嗜,一般都取1; 
surface: 這個比較重要洲敢,是你生成的VirtualDisplay的載體漫玄,
         我的理解是,VirtualDisplay的內(nèi)容是一幀幀的屏幕截圖(所以你看到是有寬高压彭,像素密度等設(shè)置)睦优,
         所以MediaProjection獲取到的其實是一幀幀的圖,然后通過          surface(surface你可以理解成是android的一個畫布壮不,
         默認它會以每秒60幀來刷新汗盘,這里我們不再展開細說),來順序播放這些圖片询一,形成視頻隐孽。

這樣,屏幕所捕獲的內(nèi)容健蕊,就顯示在這個SurfaceView上面了

Android 實現(xiàn)錄屏推流的方案整理

一菱阵、錄屏推流實現(xiàn)的步驟

  1. 采集數(shù)據(jù)
    主要是采集屏幕獲得視頻數(shù)據(jù),采集麥克風獲得音頻數(shù)據(jù)缩功,如果可以實現(xiàn)的話晴及,我們還可以采集一些應(yīng)用內(nèi)置的音頻數(shù)據(jù)。

  2. 數(shù)據(jù)格式轉(zhuǎn)換
    主要是將獲取到的視頻和音頻轉(zhuǎn)換成常見的推流的標準格式嫡锌,這樣能保證讓觀看終端正常觀看抗俄。

  3. 編碼處理
    如果不進行編碼的話脆丁,數(shù)據(jù)量會非常大,這樣不僅浪費帶寬动雹,而且會浪費觀看終端的性能槽卫,所以需要對音視頻數(shù)據(jù)進行編碼處理

  4. 封包&推流
    這塊的邏輯可以采用和普通的直播方式進行封裝和推流胰蝠。

總結(jié):其實錄屏推流直播和普通的直播的區(qū)別就是采集源發(fā)生了變化歼培,而在技術(shù)層面來將真正需要我們做的事情就是將錄屏獲取到的數(shù)據(jù)處理成穩(wěn)定的編碼格式。

二茸塞、Android 實現(xiàn)錄屏的思路

  1. 主流實現(xiàn)思路: MediaProjection + VirtualDisplay方法
    在Android 5.0 發(fā)布后躲庄,谷歌開放了截屏的接口,我們可以通過VirtualDisplay來實現(xiàn)錄屏的視頻源數(shù)據(jù)的獲取钾虐。

  2. 需ROOT思路:讀取 /dev/graphics/fb0 方法 or screencap -p xxx.png/screenshot xxx.png 方法
    Android 基于 Linux噪窘,所以可以通過讀取 fb0 設(shè)備節(jié)點,即 framebuffer 中的幀數(shù)據(jù)來實現(xiàn)屏幕的錄制效扫。但是讀取這個設(shè)備節(jié)點需要 root 權(quán)限倔监。
    screencap 是 Android shell 的命令,可以通過該 shell 命令讀取到屏幕的幀數(shù)據(jù)來達到錄屏的功能菌仁。但該命令仍然需要 root 權(quán)限浩习。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市济丘,隨后出現(xiàn)的幾起案子谱秽,更是在濱河造成了極大的恐慌,老刑警劉巖摹迷,帶你破解...
    沈念sama閱讀 206,126評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件疟赊,死亡現(xiàn)場離奇詭異,居然都是意外死亡峡碉,警方通過查閱死者的電腦和手機近哟,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,254評論 2 382
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來异赫,“玉大人椅挣,你說我怎么就攤上這事∷” “怎么了鼠证?”我有些...
    開封第一講書人閱讀 152,445評論 0 341
  • 文/不壞的土叔 我叫張陵,是天一觀的道長靠抑。 經(jīng)常有香客問我量九,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,185評論 1 278
  • 正文 為了忘掉前任荠列,我火速辦了婚禮类浪,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘肌似。我一直安慰自己费就,他們只是感情好,可當我...
    茶點故事閱讀 64,178評論 5 371
  • 文/花漫 我一把揭開白布川队。 她就那樣靜靜地躺著力细,像睡著了一般。 火紅的嫁衣襯著肌膚如雪固额。 梳的紋絲不亂的頭發(fā)上眠蚂,一...
    開封第一講書人閱讀 48,970評論 1 284
  • 那天,我揣著相機與錄音斗躏,去河邊找鬼逝慧。 笑死,一個胖子當著我的面吹牛啄糙,可吹牛的內(nèi)容都是我干的笛臣。 我是一名探鬼主播,決...
    沈念sama閱讀 38,276評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼迈套,長吁一口氣:“原來是場噩夢啊……” “哼捐祠!你這毒婦竟也來了碱鳞?” 一聲冷哼從身側(cè)響起桑李,我...
    開封第一講書人閱讀 36,927評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎窿给,沒想到半個月后贵白,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,400評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡崩泡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,883評論 2 323
  • 正文 我和宋清朗相戀三年禁荒,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片角撞。...
    茶點故事閱讀 37,997評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡呛伴,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出谒所,到底是詐尸還是另有隱情热康,我是刑警寧澤,帶...
    沈念sama閱讀 33,646評論 4 322
  • 正文 年R本政府宣布劣领,位于F島的核電站姐军,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜奕锌,卻給世界環(huán)境...
    茶點故事閱讀 39,213評論 3 307
  • 文/蒙蒙 一著觉、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧惊暴,春花似錦饼丘、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,204評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至屡穗,卻和暖如春贴捡,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背村砂。 一陣腳步聲響...
    開封第一講書人閱讀 31,423評論 1 260
  • 我被黑心中介騙來泰國打工烂斋, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人础废。 一個月前我還...
    沈念sama閱讀 45,423評論 2 352
  • 正文 我出身青樓汛骂,卻偏偏與公主長得像,于是被迫代替她去往敵國和親评腺。 傳聞我的和親對象是個殘疾皇子帘瞭,可洞房花燭夜當晚...
    茶點故事閱讀 42,722評論 2 345

推薦閱讀更多精彩內(nèi)容