安卓硬件编解码
来源:互联网 发布:删除数据库主键约束 编辑:程序博客网 时间:2024/06/10 17:38
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
0 0
- 安卓硬件编解码
- 视频硬件编解码
- 硬件编解码&软件编解码
- 安卓视频编解码(一)
- 安卓 基于speex 音频编 解码
- 硬件编解码(一)硬件编解码介绍
- ARM11硬件编解码例程
- iOS、安卓IM语音聊天(AMR编解码)
- ARM11硬件编解码(MFC)例程
- 有意思的硬件编解码问题
- 瑞芯微rk3128硬件编解码demo解析
- webrc ios 打开h264 硬件编解码
- ARM11硬件编解码(MFC)例程
- 硬件编解码(二)MediaCodec
- 硬件编解码(三)QuickSync
- 嵌入式Linux下基于FFmpeg的视频硬件编解码
- 三星 mfc 视频 硬件 编解码 终于搞定
- 嵌入式Linux下基于FFmpeg的视频硬件编解码
- SSD 之WA写入放大
- 下载文件的基本原理
- Android中自定义Dialog
- 排序:插入排序/选择排序/交换排序(冒泡法)
- 如何查看应用运行时虚拟机内存使用情况
- 安卓硬件编解码
- 学习笔记:粒度设计 粗粒度与细粒度 (-)
- 计算几何相关知识和算法概论
- Linux网络编程——tcp并发服务器(I/O复用之select)
- IOS开发模块总结(一)本地数据存储6 keychain使用介绍
- 腾讯使用移动应用解决方案,送代金券
- sscanf函数用法 和其中的正则表达式
- 反馈节点
- AutoLayout constraintsWithVisualFormat