欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

MediaCodec 解码视频文件

程序员文章站 2022-03-05 09:59:38
...

首先初始化解码器: 其中包括视频解码器 和 音频解码器

  if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
            extractor = new MediaExtractor();
            audioExtractor = new MediaExtractor();
            try {
                extractor.setDataSource(path);


                audioExtractor.setDataSource(path);
                for (int i = 0; i < extractor.getTrackCount(); i++) {
                    MediaFormat format = extractor.getTrackFormat(i);
                    String mime = format.getString(MediaFormat.KEY_MIME);
                    Log.i(TAG, "mime: " + mime);
                    if (mime.startsWith("video/")) {
                        extractor.selectTrack(i);
                        decoder = MediaCodec.createDecoderByType(mime);
                        decoder.configure(format, surfaceHolder.getSurface(), null, 0);
                        //format.setInteger(MediaFormat.KEY_FRAME_RATE, 30);//帧率
                        //format.setInteger(MediaFormat.KEY_BIT_RATE, 17648);//设置比特率
                        decoder.start();
                        Log.i(TAG, "createDecoder mime: " + mime);
                        //break;
                    } else if (mime.startsWith("audio/")) {
                        audioExtractor.selectTrack(i);
                        audioDecoder = MediaCodec.createDecoderByType(mime);
                        //采样率
                        format.setInteger(MediaFormat.KEY_SAMPLE_RATE, 8000);
                        //声道个数
                        format.setInteger(MediaFormat.KEY_CHANNEL_COUNT, 1);
                        //比特率
                        format.setInteger(MediaFormat.KEY_BIT_RATE, 0);
                        format.setInteger(MediaFormat.KEY_AAC_PROFILE, MediaCodecInfo.CodecProfileLevel.AACObjectLC);
                        //ByteBuffer key(暂时不了解该参数的含义,但必须设置)
                        audioDecoder.configure(format, null, null, 0);
                        audioDecoder.start();
                    }
                }

                if (audioDecoder!=null){

                    audio = new AudioDecodecPlay();
                    audio.start();
                }
                if (decoder != null) {
                    DecodecPlay play = new DecodecPlay();
                    play.start();
                    Log.i(TAG, "initDecoder: 找不到解码器");
                    return false;
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        } else {
            Log.i(TAG, "initDecoder: failed");
            return false;
        }

初始化解码器就可以开始解码了:
视频解码线程

 private class DecodecPlay extends Thread {

        @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN)
        @Override
        public void run() {
            ByteBuffer[] inputBuffers = decoder.getInputBuffers();
            ByteBuffer[] outputBuffers = decoder.getOutputBuffers();
            MediaCodec.BufferInfo info = new MediaCodec.BufferInfo();
            boolean first = false;
            long startMs=0;
            boolean isEndOfStream = false;
            while (!Thread.interrupted()) {
                if (!isEndOfStream) {
                    int dequeueIndex = decoder.dequeueInputBuffer(1000);
                    Log.i(TAG, "dequeueIndex: " + dequeueIndex);
                    if (dequeueIndex > 0) {

                        ByteBuffer inputBuffer = inputBuffers[dequeueIndex];
                        int sampleSize = extractor.readSampleData(inputBuffer, 0);

                        if (sampleSize<0){
                            Log.e(TAG, "input buffer end of stream");
                            decoder.queueInputBuffer(dequeueIndex, 0, 0, 0, MediaCodec.BUFFER_FLAG_END_OF_STREAM);
                            isEndOfStream = true;
                        }else {
                            Log.i(TAG, "time: "+extractor.getSampleTime());
                            decoder.queueInputBuffer(dequeueIndex, 0, sampleSize, extractor.getSampleTime(), 0);
                            extractor.advance();
                        }
                    }

                }

                int outputIndex = decoder.dequeueOutputBuffer(info, 10000);
                switch (outputIndex){
                    case MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED:
                        Log.i(TAG, "--缓冲区已经更改");
                        outputBuffers = decoder.getOutputBuffers();
                        break;
                    case MediaCodec.INFO_OUTPUT_FORMAT_CHANGED:
                        Log.i(TAG, "--格式以及更改-----> "+decoder.getOutputFormat().getString(MediaFormat.KEY_MIME));
                        break;
                    case MediaCodec.INFO_TRY_AGAIN_LATER:
                        Log.i(TAG, "dequeueOutputBuffer  indicates that the call timed out.");
                        break;
                    default:
                        Log.i(TAG, "run: outputIndex01"+outputIndex);
                        if (!first){
                            startMs = System.currentTimeMillis();
                            first=true;
                        }
                        Log.i(TAG, "info.presentationTimeUs: "+info.presentationTimeUs/1000+"::::"+(System.currentTimeMillis() - startMs));
                        long sleepTime = (info.presentationTimeUs / 1000) - (System.currentTimeMillis() - startMs);
                        if (sleepTime>0){
                            try {
                                sleep(sleepTime);
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                        }

                        decoder.releaseOutputBuffer(outputIndex, true);
                        break;
                }

                if((info.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0){
                    Log.d(TAG, "Output buffer BUFFER_FLAG_END_OF_STREAM");
                    finish();
                    break;
                }


            }

            decoder.stop();
            decoder.release();
            extractor.release();

        }
    }

音频解码线程:

  private class AudioDecodecPlay extends Thread {

        @TargetApi(Build.VERSION_CODES.LOLLIPOP)
        @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN)
        @Override
        public void run() {
           boolean first=false;
            ByteBuffer[] inputBuffers = audioDecoder.getInputBuffers();
            ByteBuffer[] outputBuffers = audioDecoder.getOutputBuffers();
            MediaCodec.BufferInfo info = new MediaCodec.BufferInfo();
            boolean isEndOfStream = false;
            long startMs = 0;
            while (!Thread.interrupted()) {
                if (!isEndOfStream) {
                    int dequeueIndex = audioDecoder.dequeueInputBuffer(1000);
                    Log.i(TAG, "dequeueIndex: " + dequeueIndex);
                    if (dequeueIndex > 0) {

                        ByteBuffer inputBuffer = inputBuffers[dequeueIndex];
                        int sampleSize = audioExtractor.readSampleData(inputBuffer, 0);
                        if (sampleSize<0){
                            Log.e(TAG, "input buffer end of stream");
                            audioDecoder.queueInputBuffer(dequeueIndex, 0, 0, 0, MediaCodec.BUFFER_FLAG_END_OF_STREAM);
                            isEndOfStream = true;
                        }else {
                            audioDecoder.queueInputBuffer(dequeueIndex, 0, sampleSize, audioExtractor.getSampleTime(), 0);
                            audioExtractor.advance();
                        }
                    }

                }

                int outputIndex = audioDecoder.dequeueOutputBuffer(info, 10000);
                switch (outputIndex){
                    case MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED:
                        Log.i(TAG, "--缓冲区已经更改");
                        outputBuffers = audioDecoder.getOutputBuffers();
                        break;
                    case MediaCodec.INFO_OUTPUT_FORMAT_CHANGED:
                        Log.i(TAG, "--格式以及更改-----> "+decoder.getOutputFormat().getString(MediaFormat.KEY_MIME));
                        break;
                    case MediaCodec.INFO_TRY_AGAIN_LATER:
                        Log.i(TAG, "dequeueOutputBuffer  indicates that the call timed out.");
                        break;
                    default:
                        Log.i(TAG, "run: outputIndex02"+outputIndex);
                        if (!first){
                            startMs = System.currentTimeMillis();
                            first=true;
                        }
                        Log.i(TAG, "info.presentationTimeUs: "+info.presentationTimeUs/1000+"::::"+(System.currentTimeMillis() - startMs));
                        long sleepTime = (info.presentationTimeUs / 1000) - (System.currentTimeMillis() - startMs);
                        if (sleepTime>0){
                            try {
                                sleep(sleepTime);
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                        }
                        ByteBuffer buffer = outputBuffers[outputIndex];
                        byte[] data = new byte[buffer.remaining()];
                        buffer.get(data);
                        mPlayer.write(data,0,data.length);
                        audioDecoder.releaseOutputBuffer(outputIndex, false);
                        break;
                }

                if((info.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0){
                    Log.d(TAG, "Output buffer BUFFER_FLAG_END_OF_STREAM");
                    break;
                }


            }

            audioDecoder.stop();
            audioDecoder.release();
            audioExtractor.release();
        }
    }

关键代码就这么多!!!
解码后的音频可以使用AudioTrack播放

  mPlayer = new AudioTrack(AudioManager.STREAM_MUSIC,
                sampleRateInHz, channelConfig, audioFormat,2880,
                AudioTrack.MODE_STREAM);
        mPlayer.play();
相关标签: 解码