概述
转自:http://blog.csdn.net/shawnkong/article/details/16337381
Android的视频编解码一直让人有点纠结,SDK竟然不提供硬件编解码的API,如果你想自己做,只能通过JNI借助第三方编解码器,其都是使用的软解码,效率很难保证,这对想做视频通话的是一个不小的打击。
好了,说到google 新提供的SDK中出现的类MediaCodec,这个api限制在API 16后,也就是Android 4.1.2后才可以使用,如果你的系统低于这个版本,是不可以使用这个类的。MediaCodec这家伙能提供给你硬件编解码功能,当然得厂商支持在下层已经,如果厂商没做好,系统会提供给你软件编解码器,反正不用你操心,可以直接就拿来用的。
使用网上有人提供的Demo,可以解码mp4文件,具体情况还没研究,先放出Github链接,直接自己抓出来就可以用,
如果懒得去抓,下面贴出代码,就一个简单的Activity,一切搞定,
“记得修改文件名,SAMPLE变量为你自己的文件名称”,
- package io.vec.demo.mediacodec;
- import java.nio.ByteBuffer;
- import android.app.Activity;
- import android.media.MediaCodec;
- import android.media.MediaCodec.BufferInfo;
- import android.media.MediaExtractor;
- import android.media.MediaFormat;
- import android.os.Bundle;
- import android.os.Environment;
- import android.util.Log;
- import android.view.Surface;
- import android.view.SurfaceHolder;
- import android.view.SurfaceView;
- public class DecodeActivity extends Activity implements SurfaceHolder.Callback {
- private static final String SAMPLE = Environment.getExternalStorageDirectory() + "/video.mp4";
- private PlayerThread mPlayer = null;
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- SurfaceView sv = new SurfaceView(this);
- sv.getHolder().addCallback(this);
- setContentView(sv);
- }
- protected void onDestroy() {
- super.onDestroy();
- }
- @Override
- public void surfaceCreated(SurfaceHolder holder) {
- }
- @Override
- public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
- if (mPlayer == null) {
- mPlayer = new PlayerThread(holder.getSurface());
- mPlayer.start();
- }
- }
- @Override
- public void surfaceDestroyed(SurfaceHolder holder) {
- if (mPlayer != null) {
- mPlayer.interrupt();
- }
- }
- private class PlayerThread extends Thread {
- private MediaExtractor extractor;
- private MediaCodec decoder;
- private Surface surface;
- public PlayerThread(Surface surface) {
- this.surface = surface;
- }
- @Override
- public void run() {
- extractor = new MediaExtractor();
- extractor.setDataSource(SAMPLE);
- for (int i = 0; i < extractor.getTrackCount(); i++) {
- MediaFormat format = extractor.getTrackFormat(i);
- String mime = format.getString(MediaFormat.KEY_MIME);
- if (mime.startsWith("video/")) {
- extractor.selectTrack(i);
- decoder = MediaCodec.createDecoderByType(mime);
- decoder.configure(format, surface, null, 0);
- break;
- }
- }
- if (decoder == null) {
- Log.e("DecodeActivity", "Can't find video info!");
- return;
- }
- decoder.start();
- ByteBuffer[] inputBuffers = decoder.getInputBuffers();
- ByteBuffer[] outputBuffers = decoder.getOutputBuffers();
- BufferInfo info = new BufferInfo();
- boolean isEOS = false;
- long startMs = System.currentTimeMillis();
- while (!Thread.interrupted()) {
- if (!isEOS) {
- int inIndex = decoder.dequeueInputBuffer(10000);
- if (inIndex >= 0) {
- ByteBuffer buffer = inputBuffers[inIndex];
- int sampleSize = extractor.readSampleData(buffer, 0);
- if (sampleSize < 0) {
- // We shouldn't stop the playback at this point, just pass the EOS
- // flag to decoder, we will get it again from the
- // dequeueOutputBuffer
- Log.d("DecodeActivity", "InputBuffer BUFFER_FLAG_END_OF_STREAM");
- decoder.queueInputBuffer(inIndex, 0, 0, 0, MediaCodec.BUFFER_FLAG_END_OF_STREAM);
- isEOS = true;
- } else {
- decoder.queueInputBuffer(inIndex, 0, sampleSize, extractor.getSampleTime(), 0);
- extractor.advance();
- }
- }
- }
- int outIndex = decoder.dequeueOutputBuffer(info, 10000);
- switch (outIndex) {
- case MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED:
- Log.d("DecodeActivity", "INFO_OUTPUT_BUFFERS_CHANGED");
- outputBuffers = decoder.getOutputBuffers();
- break;
- case MediaCodec.INFO_OUTPUT_FORMAT_CHANGED:
- Log.d("DecodeActivity", "New format " + decoder.getOutputFormat());
- break;
- case MediaCodec.INFO_TRY_AGAIN_LATER:
- Log.d("DecodeActivity", "dequeueOutputBuffer timed out!");
- break;
- default:
- ByteBuffer buffer = outputBuffers[outIndex];
- Log.v("DecodeActivity", "We can't use this buffer but render it due to the API limit, " + buffer);
- // We use a very simple clock to keep the video FPS, or the video
- // playback will be too fast
- while (info.presentationTimeUs / 1000 > System.currentTimeMillis() - startMs) {
- try {
- sleep(10);
- } catch (InterruptedException e) {
- e.printStackTrace();
- break;
- }
- }
- decoder.releaseOutputBuffer(outIndex, true);
- break;
- }
- // All decoded frames have been rendered, we can stop playing now
- if ((info.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {
- Log.d("DecodeActivity", "OutputBuffer BUFFER_FLAG_END_OF_STREAM");
- break;
- }
- }
- decoder.stop();
- decoder.release();
- extractor.release();
- }
- }
- }
最後再奉上我修改過的代碼,增加了選擇文件的功能.
http://download.csdn.net/detail/shawnkong/6555857
最后
以上就是怕孤单冰淇淋为你收集整理的Android 新API 之 MediaCodec使用笔记的全部内容,希望文章能够帮你解决Android 新API 之 MediaCodec使用笔记所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复