Android平台對H264視頻硬解碼

來源:互聯網
上載者:User

標籤:

  本文講述如何使用Android標準的API (MediaCodec)實現H264的硬體解碼。

  原本我們是用JNI調用平台提供的硬體解碼介面得到YUV幀,再放入opengl指令碼裡處理渲染的。可是換了新平台之後,沒有拿到底層的介面,所以這兩天找在Android上的H264解碼方案。前天在友人的提示下找到了MediaCodec這個類,Android developer上面有MediaCodec的描述和用法,還算詳細可以慢慢摸索。但是在網上關於這個類的用法是比較少。

  那在這裡貼代碼介紹一下。

 1 // Video Constants 2     private final static String MIME_TYPE = "video/avc"; // H.264 Advanced Video 3     private final static int VIDEO_WIDTH = 1280; 4     private final static int VIDEO_HEIGHT = 720; 5     private final static int TIME_INTERNAL = 30; 6  7     public void initDecoder() { 8  9         mCodec = MediaCodec.createDecoderByType(MIME_TYPE);10         MediaFormat mediaFormat = MediaFormat.createVideoFormat(MIME_TYPE,11                 VIDEO_WIDTH, VIDEO_HEIGHT);12         mCodec.configure(mediaFormat, mSurfaceView.getHolder().getSurface(),13                 null, 0);14         mCodec.start();15     }

 

  這是初始化解碼器操作,具體要設定解碼類型,高度,寬度,還有一個用於顯示視頻的surface。

 

 1     public boolean onFrame(byte[] buf, int offset, int length) { 2         Log.e("Media", "onFrame start"); 3         Log.e("Media", "onFrame Thread:" + Thread.currentThread().getId()); 4         // Get input buffer index 5         ByteBuffer[] inputBuffers = mCodec.getInputBuffers(); 6         int inputBufferIndex = mCodec.dequeueInputBuffer(100); 7  8         Log.e("Media", "onFrame index:" + inputBufferIndex); 9         if (inputBufferIndex >= 0) {10             ByteBuffer inputBuffer = inputBuffers[inputBufferIndex];11             inputBuffer.clear();12             inputBuffer.put(buf, offset, length);13             mCodec.queueInputBuffer(inputBufferIndex, 0, length, mCount14                     * TIME_INTERNAL, 0);15             mCount++;16         } else {17             return false;18         }19 20         // Get output buffer index21         MediaCodec.BufferInfo bufferInfo = new MediaCodec.BufferInfo();22         int outputBufferIndex = mCodec.dequeueOutputBuffer(bufferInfo, 100);23         while (outputBufferIndex >= 0) {24             mCodec.releaseOutputBuffer(outputBufferIndex, true);25             outputBufferIndex = mCodec.dequeueOutputBuffer(bufferInfo, 0);26         }27         Log.e("Media", "onFrame end");28         return true;29     }
具體流程:

  1.擷取一個可用的inputBuffer的索引(出列)

  2.將一幀資料放入inputBuffer

  3.將inputBuffer入列進行解碼

  4.獲得一個outputBuffer的索引(出列)

  5.釋放outputBuffer

  6.在4,5間迴圈直到沒有outputBuffer可出列為止

  這裡解碼器有多個輸入緩衝區(我測試是有3個),實現不卡頓。

常見的問題:

  dequeueInputBuffer和dequeueOutputBuffer經常會擷取不了緩衝區(跟機器的效能有關),如果參數為-1,則會一直等待;如果參數為正數,則等待相應的微秒後返回,沒有可用緩衝區就會返回-1。

結論:
  測試程式是讀取一個H264裸流檔案,識別每一幀然後將其放入解碼器解碼以及渲染。讀取和識別的代碼在Demo中。經測試,不同平台的解碼效果還挺大。我播放的是720p的H264檔案。最出色的居然是RK(瑞芯微)平台,緩衝區擷取很少失敗,但是會因為過熱重啟機器;高通平台試了幾台機器(鎚子、小米4、還有個別定製機),經常有拿不到緩衝區的情況。MTK的只有一台(TCL麼麼噠),直接初始化不瞭解碼器。。。
  這裡跟GPU效能有關,我們解的是720p8m碼率的視頻,換成較低碼率較低解析度的,大部分機器還是可以正常啟動並執行(除了麼麼噠)。當然或許有些平台的實現是軟解碼(使用cpu,ffmpeg方案),這我暫時還沒遇到。

Demo連結如下(注意裸流檔案要放置的路徑):
http://files.cnblogs.com/files/superping/H264Demo.zip

Android平台對H264視頻硬解碼

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.