Android 新API 之 MediaCodec使用笔记

来源:互联网 发布:删除文件 linux 编辑:程序博客网 时间:2024/04/29 14:05

转自: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变量为你自己的文件名称”,

[java] view plaincopy
  1. package io.vec.demo.mediacodec;  
  2.   
  3. import java.nio.ByteBuffer;  
  4.   
  5. import android.app.Activity;  
  6. import android.media.MediaCodec;  
  7. import android.media.MediaCodec.BufferInfo;  
  8. import android.media.MediaExtractor;  
  9. import android.media.MediaFormat;  
  10. import android.os.Bundle;  
  11. import android.os.Environment;  
  12. import android.util.Log;  
  13. import android.view.Surface;  
  14. import android.view.SurfaceHolder;  
  15. import android.view.SurfaceView;  
  16.   
  17. public class DecodeActivity extends Activity implements SurfaceHolder.Callback {  
  18.     private static final String SAMPLE = Environment.getExternalStorageDirectory() + "/video.mp4";  
  19.     private PlayerThread mPlayer = null;  
  20.   
  21.     @Override  
  22.     protected void onCreate(Bundle savedInstanceState) {  
  23.         super.onCreate(savedInstanceState);  
  24.         SurfaceView sv = new SurfaceView(this);  
  25.         sv.getHolder().addCallback(this);  
  26.         setContentView(sv);  
  27.     }  
  28.   
  29.     protected void onDestroy() {  
  30.         super.onDestroy();  
  31.     }  
  32.   
  33.     @Override  
  34.     public void surfaceCreated(SurfaceHolder holder) {  
  35.     }  
  36.   
  37.     @Override  
  38.     public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {  
  39.         if (mPlayer == null) {  
  40.             mPlayer = new PlayerThread(holder.getSurface());  
  41.             mPlayer.start();  
  42.         }  
  43.     }  
  44.   
  45.     @Override  
  46.     public void surfaceDestroyed(SurfaceHolder holder) {  
  47.         if (mPlayer != null) {  
  48.             mPlayer.interrupt();  
  49.         }  
  50.     }  
  51.   
  52.     private class PlayerThread extends Thread {  
  53.         private MediaExtractor extractor;  
  54.         private MediaCodec decoder;  
  55.         private Surface surface;  
  56.   
  57.         public PlayerThread(Surface surface) {  
  58.             this.surface = surface;  
  59.         }  
  60.   
  61.         @Override  
  62.         public void run() {  
  63.             extractor = new MediaExtractor();  
  64.             extractor.setDataSource(SAMPLE);  
  65.   
  66.             for (int i = 0; i < extractor.getTrackCount(); i++) {  
  67.                 MediaFormat format = extractor.getTrackFormat(i);  
  68.                 String mime = format.getString(MediaFormat.KEY_MIME);  
  69.                 if (mime.startsWith("video/")) {  
  70.                     extractor.selectTrack(i);  
  71.                     decoder = MediaCodec.createDecoderByType(mime);  
  72.                     decoder.configure(format, surface, null0);  
  73.                     break;  
  74.                 }  
  75.             }  
  76.   
  77.             if (decoder == null) {  
  78.                 Log.e("DecodeActivity""Can't find video info!");  
  79.                 return;  
  80.             }  
  81.   
  82.             decoder.start();  
  83.   
  84.             ByteBuffer[] inputBuffers = decoder.getInputBuffers();  
  85.             ByteBuffer[] outputBuffers = decoder.getOutputBuffers();  
  86.             BufferInfo info = new BufferInfo();  
  87.             boolean isEOS = false;  
  88.             long startMs = System.currentTimeMillis();  
  89.   
  90.             while (!Thread.interrupted()) {  
  91.                 if (!isEOS) {  
  92.                     int inIndex = decoder.dequeueInputBuffer(10000);  
  93.                     if (inIndex >= 0) {  
  94.                         ByteBuffer buffer = inputBuffers[inIndex];  
  95.                         int sampleSize = extractor.readSampleData(buffer, 0);  
  96.                         if (sampleSize < 0) {  
  97.                             // We shouldn't stop the playback at this point, just pass the EOS  
  98.                             // flag to decoder, we will get it again from the  
  99.                             // dequeueOutputBuffer  
  100.                             Log.d("DecodeActivity""InputBuffer BUFFER_FLAG_END_OF_STREAM");  
  101.                             decoder.queueInputBuffer(inIndex, 000, MediaCodec.BUFFER_FLAG_END_OF_STREAM);  
  102.                             isEOS = true;  
  103.                         } else {  
  104.                             decoder.queueInputBuffer(inIndex, 0, sampleSize, extractor.getSampleTime(), 0);  
  105.                             extractor.advance();  
  106.                         }  
  107.                     }  
  108.                 }  
  109.   
  110.                 int outIndex = decoder.dequeueOutputBuffer(info, 10000);  
  111.                 switch (outIndex) {  
  112.                 case MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED:  
  113.                     Log.d("DecodeActivity""INFO_OUTPUT_BUFFERS_CHANGED");  
  114.                     outputBuffers = decoder.getOutputBuffers();  
  115.                     break;  
  116.                 case MediaCodec.INFO_OUTPUT_FORMAT_CHANGED:  
  117.                     Log.d("DecodeActivity""New format " + decoder.getOutputFormat());  
  118.                     break;  
  119.                 case MediaCodec.INFO_TRY_AGAIN_LATER:  
  120.                     Log.d("DecodeActivity""dequeueOutputBuffer timed out!");  
  121.                     break;  
  122.                 default:  
  123.                     ByteBuffer buffer = outputBuffers[outIndex];  
  124.                     Log.v("DecodeActivity""We can't use this buffer but render it due to the API limit, " + buffer);  
  125.   
  126.                     // We use a very simple clock to keep the video FPS, or the video  
  127.                     // playback will be too fast  
  128.                     while (info.presentationTimeUs / 1000 > System.currentTimeMillis() - startMs) {  
  129.                         try {  
  130.                             sleep(10);  
  131.                         } catch (InterruptedException e) {  
  132.                             e.printStackTrace();  
  133.                             break;  
  134.                         }  
  135.                     }  
  136.                     decoder.releaseOutputBuffer(outIndex, true);  
  137.                     break;  
  138.                 }  
  139.   
  140.                 // All decoded frames have been rendered, we can stop playing now  
  141.                 if ((info.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {  
  142.                     Log.d("DecodeActivity""OutputBuffer BUFFER_FLAG_END_OF_STREAM");  
  143.                     break;  
  144.                 }  
  145.             }  
  146.   
  147.             decoder.stop();  
  148.             decoder.release();  
  149.             extractor.release();  
  150.         }  
  151.     }  
  152. }  

最後再奉上我修改過的代碼,增加了選擇文件的功能.

http://download.csdn.net/detail/shawnkong/6555857

0 0