Android MediaCodec “Decoded”

Android has a great media library allowing all sorts of things. Until recently though, there was no way to encode/decode audio/video giving developers the ability to do literally anything. Fortunately Jelly Bean release introduced the android.media.MediaCodec API.The API is designed following the same principles/architecture of  OpenMAX, a well known standard in the media Industry.Transitioning from a pure high level MediaPlayer to the encoder/decoder level can be a big pain though. There is a lot more to be aware of when you are manipulating the tiny little bits that make great media file:///C:/Users/Kimi/AppData/Local/youdao/ynote/images/F6ACB9CA72804E18A9E34F00B95C9B50/icon_smile.gifIn this post I will describe how to use the API, highlighting the essential things to be aware of.1.Get To Know Your MediaAnother new class introduced in Jelly Bean is theandroid.media.MediaExtractor. It is pretty clear what it is all about, extract the metadata from your media and a lot more.
AssetFileDescriptor sampleFD = getResources().openRawResourceFd(
                                R.raw.test);

                MediaExtractor extractor;
                MediaCodec codec;
                ByteBuffer[] codecInputBuffers;
                ByteBuffer[] codecOutputBuffers;

                extractor = new MediaExtractor();
                extractor.setDataSource(sampleFD.getFileDescriptor(),
                                sampleFD.getStartOffset(), sampleFD.getLength());
                Log.d(TAG, String.format("TRACKS #: %d", extractor.getTrackCount()));
                MediaFormat format = extractor.getTrackFormat(0);
                String mime = format.getString(MediaFormat.KEY_MIME);
                Log.d(TAG, String.format("MIME TYPE : %s", mime));


2. Create your DecoderA decoder is generally seen as a NODE with INPUT and OUTPUT buffers. You take an input buffer from it, fill it and give it back to the decoder for decoding to take place. On the other side of the NODE, you take an output buffer and “render” it. This example will play an audio sample file using theandroid.media.AudioTrack API.
[backcolor=initial !important] AssetFileDescriptor sampleFD = getResources().openRawResourceFd(
                                R.raw.test);

                MediaExtractor extractor;
                MediaCodec codec;
                ByteBuffer[] codecInputBuffers;
                ByteBuffer[] codecOutputBuffers;

                extractor = new MediaExtractor();
                extractor.setDataSource(sampleFD.getFileDescriptor(),
                                sampleFD.getStartOffset(), sampleFD.getLength());
                Log.d(TAG, String.format("TRACKS #: %d", extractor.getTrackCount()));
                MediaFormat format = extractor.getTrackFormat(0);
                String mime = format.getString(MediaFormat.KEY_MIME);
                Log.d(TAG, String.format("MIME TYPE : %s", mime));

3. It`s All About BuffersLet the Buffer party begin file:///C:/Users/Kimi/AppData/Local/youdao/ynote/images/928F1025FB274DA4AD6B4861A5CEF454/icon_smile.gif See bellow how the INPUT side of the decoder is managed:
int inputBufIndex = codec.dequeueInputBuffer(TIMEOUT_US);
                if (inputBufIndex >= 0) {
                        ByteBuffer dstBuf = codecInputBuffers[inputBufIndex];
                        int sampleSize = extractor.readSampleData(dstBuf, 0);
                        long presentationTimeUs = 0;
                        if (sampleSize < 0) {
                                sawInputEOS = true;
                                sampleSize = 0;
                        } else {
                                presentationTimeUs = extractor.getSampleTime();
                        }


                        codec.queueInputBuffer(inputBufIndex, 0, sampleSize,
                                        presentationTimeUs,
                                        sawInputEOS ? MediaCodec.BUFFER_FLAG_END_OF_STREAM : 0);
                        if(!sawInputEOS){
                                extractor.advance();
                        }


                }

And now how to pull OUTPUT buffers with the decoded media from the decoder:
final int res = codec.dequeueOutputBuffer(info, TIMEOUT_US);
                if(res >= 0){
                        int outputBufIndex = res;
                        ByteBuffer buf = codecOutputBuffers[outputBufIndex];
                        final byte[] chunk = new byte[info.size];
                        buf.get(chunk);
                        buf.clear();
                        if(chunk.length > 0){
                                audioTrack.write(chunk,0,chunk.length);
                        }
                        codec.releaseOutputBuffer(outputBufIndex, false);
                        if((info.flags && MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0){
                                sawOutputEOS = true;
                        }
                } else if(res == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED){
                        codecOutputBuffers = codec.getOutputBuffers();
                        
                } else if(res == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED){
                        final MediaFormat offormat = codec.getOutputFormat();
                        Log.d(TAG, "Output format has changed to" + offormat);
                        mAudioTrack.setPlaybackRate(oformat.getInteger(MediaFormat.KEY_SAMPLE_RATE));
                }

And that’s it. This is the most simple usage of this such powerful API. For further questions send me a note and I’ll give you more insights…
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值