Android自帶硬編解碼器MediaCodec使用必看
阿新 • • 發佈:2019-02-09
一、背景
隨著Android系統手機效能的不斷提升,現階段大部分手機都自帶GPU(承擔圖形顯示的專門硬體),大幅度提高手機顯示效能,在視訊顯示、遊戲畫面重新整理,和高分辨影象顯示方面必須使用GPU。GOOGLE在API 16 -4.1版本中增加MediaCodec類,專用於編解碼多媒體資料,
二、MediaCodec使用方式
MediaCodec總共有三種使用方法,如下圖所示:
同步資料處理(使用buffer arrays) 從Android4.1 api 16即可以使用;
同步資料處理 (使用buffers ) 從Android5.0 api 21 即可以使用;
非同步資料處理(使用buffers ) 從Android5.0 api 21 即可以使用;
同步與非同步處理資料的主要不同點是:對於同步處理是迴圈的將待處理資料交給編解碼器(不用理會編解碼器是否已經準備好接收資料),而非同步處理則是每次都會去等待編解碼器已經能夠處理資料時,才將待處理資料送給相應編解碼器。
MediaCodec is typically used like this in asynchronous mode:
- MediaCodec codec = MediaCodec.createByCodecName(name);
- MediaFormat mOutputFormat; // member variable
- codec.setCallback(new MediaCodec.Callback() {
- @Override
- void onInputBufferAvailable(MediaCodec mc, int inputBufferId) {
- ByteBuffer inputBuffer = codec.getInputBuffer(inputBufferId);
- // fill inputBuffer with valid data
- …
- codec.queueInputBuffer(inputBufferId, …);
- }
- @Override
- void onOutputBufferAvailable(MediaCodec mc, int outputBufferId, …) {
- ByteBuffer outputBuffer = codec.getOutputBuffer(outputBufferId);
- MediaFormat bufferFormat = codec.getOutputFormat(outputBufferId); // option A
- // bufferFormat is equivalent to mOutputFormat
- // outputBuffer is ready to be processed or rendered.
- …
- codec.releaseOutputBuffer(outputBufferId, …);
- }
- @Override
- void onOutputFormatChanged(MediaCodec mc, MediaFormat format) {
- // Subsequent data will conform to new format.
- // Can ignore if using getOutputFormat(outputBufferId)
- mOutputFormat = format; // option B
- }
- @Override
- void onError(…) {
- …
- }
- });
- codec.configure(format, …);
- mOutputFormat = codec.getOutputFormat(); // option B
- codec.start();
- // wait for processing to complete
- codec.stop();
- codec.release();
Synchronous Processing using Buffers
- MediaCodec codec = MediaCodec.createByCodecName(name);
- codec.configure(format, …);
- MediaFormat outputFormat = codec.getOutputFormat(); // option B
- codec.start();
- for (;;) {
- int inputBufferId = codec.dequeueInputBuffer(timeoutUs);
- if (inputBufferId >= 0) {
- ByteBuffer inputBuffer = codec.getInputBuffer(…);
- // fill inputBuffer with valid data
- …
- codec.queueInputBuffer(inputBufferId, …);
- }
- int outputBufferId = codec.dequeueOutputBuffer(…);
- if (outputBufferId >= 0) {
- ByteBuffer outputBuffer = codec.getOutputBuffer(outputBufferId);
- MediaFormat bufferFormat = codec.getOutputFormat(outputBufferId); // option A
- // bufferFormat is identical to outputFormat
- // outputBuffer is ready to be processed or rendered.
- …
- codec.releaseOutputBuffer(outputBufferId, …);
- } elseif (outputBufferId == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
- // Subsequent data will conform to new format.
- // Can ignore if using getOutputFormat(outputBufferId)
- outputFormat = codec.getOutputFormat(); // option B
- }
- }
- codec.stop();
- codec.release();
三、MediaCodec能夠硬編解碼的型別
其中對於視訊格式,MediaCodec支援的有vp8 、VP9 、H.264、H.265、MPEG4、H.263基本上涵蓋了現今流行的所有視訊格式,
對於音訊來說,MediaCodec支援的音訊格式有3gpp、amr-wb、amr-wb、amr-wb、g711-A、g711-U 、AAC(not packaged in LATM)
- "video/x-vnd.on2.vp8" - VP8 video (i.e. video in .webm)
- "video/x-vnd.on2.vp9" - VP9 video (i.e. video in .webm)
- "video/avc" - H.264/AVC video
- "video/hevc" - H.265/HEVC video
- "video/mp4v-es" - MPEG4 video
- "video/3gpp" - H.263 video
- "audio/3gpp" - AMR narrowband audio
- "audio/amr-wb" - AMR wideband audio
- "audio/amr-wb" - MPEG1/2 audio layer III
- "audio/mp4a-latm" - AAC audio (note, this is raw AAC packets, not packaged in LATM!)
- "audio/amr-wb" - vorbis audio
- "audio/g711-alaw" - G.711 alaw audio
- "audio/g711-mlaw" - G.711 ulaw audio
Format | Suitable key frame |
---|---|
VP9/VP8 | a suitable intraframe where no subsequent frames refer to frames prior to this frame. (There is no specific name for such key frame.) |
H.265 HEVC | IDR or CRA |
H.264 AVC | IDR |
MPEG-4 H.263 MPEG-2 | a suitable I-frame where no subsequent frames refer to frames prior to this frame. (There is no specific name for such key frame.) |