Android 用MediaCodec ,MediaExtractor解码播放MP4文件

上一篇讲了如何采集摄像头画面并且进行编码,再进行封装成MP4格式文件,如需了解可以看 安卓采集摄像头画面生成MP4文件
本篇博客,主要讲解如何对MP4文件进行解封装,再进行解H264码流,进行画面显示。
Android 使用MediaCodec进行视频编解码工作,这里解码当然还由其来完成,那从MP4文件中提取出H264码流的工作,由MediaExtractor完成
MediaExtractor的使用比较简单:

 mediaExtractor = new MediaExtractor();
 //设置MP4文件存放的位置
 mediaExtractor.setDataSource(path);
 Log.d(TAG, "getTrackCount: " + mediaExtractor.getTrackCount());
 for (int i = 0; i < mediaExtractor.getTrackCount(); i++) {
  MediaFormat format = mediaExtractor.getTrackFormat(i);
  String mime = format.getString(MediaFormat.KEY_MIME);
  //如果是video格式
  if (mime.startsWith("video")) {
      mediaFormat = format;
      mediaExtractor.selectTrack(i);
     }
 }

2、解码器MediaCodec初始化如下

    mediaCodec = MediaCodec.createDecoderByType("video/avc");
    mediaFormat = MediaFormat.createVideoFormat("video/avc", 1280, 720);
    Surface surface = MainActivity.surfaceHolder.getSurface();
    //必须配置一个surface,作为其输出解码显示画面
    mediaCodec.configure(mediaFormat, surface, null, 0);
    mediaCodec.start();

3、开启解码线程

  /**
     *  Play the MP4 file Thread
     */
    private class DecoderMP4Thread extends Thread {
        long pts = 0;

        @Override
        public void run() {
            super.run();
            while (!isDecodeFinish) {
                int inputIndex = mediaCodec.dequeueInputBuffer(-1);
                Log.d(TAG, "inputIndex: " + inputIndex);
                if (inputIndex >= 0) {
                    ByteBuffer byteBuffer = mediaCodec.getInputBuffer(inputIndex);
                    //读取一片或者一帧数据
                    int sampSize = mediaExtractor.readSampleData(byteBuffer,0);
                    //读取时间戳
                    long time = mediaExtractor.getSampleTime();
                    Log.d(TAG, "sampSize: " + sampSize + "time: " + time);
                    if (sampSize > 0 && time > 0) {
                        mediaCodec.queueInputBuffer(inputIndex, 0, sampSize, time, 0);
                        //读取一帧后必须调用,提取下一帧
                        mediaExtractor.advance();
                        //控制帧率在30帧左右
                        try {
                            sleep(30);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }

                }
                BufferInfo bufferInfo = new BufferInfo();
                int outIndex = mediaCodec.dequeueOutputBuffer(bufferInfo, 0);
                Log.d(TAG, "outIndex: " + outIndex);
                if (outIndex >= 0) {
                    mediaCodec.releaseOutputBuffer(outIndex, true);
                }
            }
        }

    }

4、最后结束的时候,别忘了释放资源


    public void close() {
        if (mediaCodec != null) {
            mediaCodec.stop();
            mediaCodec.release();
            isDecodeFinish=true;
        }
    }

Github地址
https://github.com/zxd1991/AndroidMedia

发布了24 篇原创文章 · 获赞 8 · 访问量 1万+
展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 大白 设计师: CSDN官方博客

分享到微信朋友圈

×

扫一扫,手机浏览