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;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);SurfaceView sv = new SurfaceView(this);sv.getHolder().addCallback(this);setContentView(sv);}protected void onDestroy() {super.onDestroy();}@Overridepublic void surfaceCreated(SurfaceHolder holder) {}@Overridepublic void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {if (mPlayer == null) {mPlayer = new PlayerThread(holder.getSurface());mPlayer.start();}}@Overridepublic 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;}@Overridepublic 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// dequeueOutputBufferLog.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 fastwhile (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 nowif ((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



最近从事手机iOS/Android直播、视频实时美颜方面的工作。

欢迎加群交流:496010189

更多相关文章

  1. Android(安卓)Accessibility(辅助功能) 学习
  2. Android中音视频合成的几种方案详析
  3. 浅谈新一代Android操作系统Android(安卓)L
  4. Xamarin android 使用RecyclerView结合SwipeRefreshLayout下拉刷
  5. Android中实现一键分享功能
  6. android试手——通讯录(附源码)
  7. 【Android】第5章(8) 图片库(Galery)
  8. 【Android游戏开发十六】Android(安卓)Gesture之【触摸屏手势识
  9. android 万能视频播放器

随机推荐

  1. Android中解析XML
  2. Android自动化测试工具——Monkey
  3. Android的nodpi,xhdpi,hdpi,mdpi,ldpi
  4. Android中的四种布局
  5. android recover 系统代码分析 -- 选择进
  6. 2020最新Android大厂面试真题大全(附答案)
  7. android横竖屏总结
  8. Android下 读写文件
  9. 搭建Android的开发环境
  10. 学习Android(安卓)Handler消息传递机制