Mediacodec

 SurfaceView surfaceView;
    SurfaceHolder holder;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        surfaceView = findViewById(R.id.surfaceView);
        holder = surfaceView.getHolder();
        /**
         * 視頻輸入
         */
        VideoThread videoThread = new VideoThread(holder);
        videoThread.start();

        /**
         * 音頻輸入
         */

       SecondThread secondThread = new SecondThread();
       secondThread.start();


    }
}
class VideoThread extends Thread{
    private SurfaceHolder holder;

    public VideoThread(SurfaceHolder holder){
        this.holder = holder;
    }


    @Override
    public void run() {
        try {
            final MediaExtractor extractor = new MediaExtractor();
            //設置視頻地址
            String path = Environment.getExternalStorageDirectory().getPath() + "/h265.mp4";
            extractor.setDataSource(path);
            extractor.seekTo(5000, SEEK_TO_NEXT_SYNC);
            //Count the number of tracks found in the data source.信道總數一般爲2 一個視頻一個音頻
            int numTrack = extractor.getTrackCount();
            for (int i = 0; i < numTrack; i++) {
                //Get the track format at the specified index
                final MediaFormat format = extractor.getTrackFormat(i);
                //得到數據信息 1.video/avc  2.audio/mp4a-latm
                String mimetype = format.getString(MediaFormat.KEY_MIME);
                Log.d("tag", mimetype);
                if (mimetype.startsWith("video")) {
                    //選擇頻道
                    extractor.selectTrack(i);

                    final MediaCodec mediaCodec = MediaCodec.createDecoderByType(mimetype);
//                    mPlayer = new AudioPlayer(format.getInteger(MediaFormat.KEY_SAMPLE_RATE), AudioFormat
//                            .CHANNEL_OUT_STEREO, AudioFormat.ENCODING_PCM_16BIT);
//                    mPlayer.init();
                    holder.addCallback(new SurfaceHolder.Callback() {
                        @Override
                        public void surfaceCreated(SurfaceHolder holder) {
                            mediaCodec.configure(format, holder.getSurface(), null, 0);
//                                    outputFormat = format;
                            mediaCodec.start();
                        }

                        @Override
                        public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {

                        }

                        @Override
                        public void surfaceDestroyed(SurfaceHolder holder) {

                        }
                    });
                    mediaCodec.setCallback(new MediaCodec.Callback() {
                        @Override
                        public void onInputBufferAvailable(MediaCodec codec, int index) {
                            ByteBuffer inputBuffer = codec.getInputBuffer(index);
                            inputBuffer.clear();
                            int readlen = extractor.readSampleData(inputBuffer, 0);
                            Log.d("tag", "視頻輸入" + inputBuffer.toString());
                            codec.queueInputBuffer(index, 0, readlen, 0, 0);
                            extractor.advance();//Advance to the next sample.進入下一幀 刷新


                        }

                        @Override
                        public void onOutputBufferAvailable(MediaCodec codec, int index, MediaCodec.BufferInfo info) {
                            Log.d("tag", "onOutputBufferAvailable:" + info.size);
                            ByteBuffer outputBuffer = codec.getOutputBuffer(index);
                            MediaFormat outformat = codec.getOutputFormat();
                            if (outputBuffer != null && info.size > 0) {
                                byte[] buffer = new byte[outputBuffer.remaining()];
                                outputBuffer.get(buffer);
//                                 mPlayer.play(buffer,0,info.size);
                                Log.d("tag", "Offer to queue failed, queue in full state");
                            }
                            codec.releaseOutputBuffer(index, true);
                        }

                        @Override
                        public void onError(MediaCodec codec, MediaCodec.CodecException e) {
                            Log.d("tag", "onError:" + e.getDiagnosticInfo());
                        }

                        @Override
                        public void onOutputFormatChanged(MediaCodec codec, MediaFormat format) {
                            Log.d("tag", "onOutputFormatChanged:");
//                                    outputFormat = format;
                        }
                    });

                }

            }

        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
class SecondThread extends Thread{
    AudioPlayer mPlayer;
    @Override
    public void run() {
        try {
            final MediaExtractor extractor = new MediaExtractor();
            //設置視頻地址
            String path = Environment.getExternalStorageDirectory().getPath() + "/h265.mp4";
            extractor.setDataSource(path);
            extractor.seekTo(5000, SEEK_TO_NEXT_SYNC);
            //Count the number of tracks found in the data source.信道總數一般爲2 一個視頻一個音頻
            int numTrack = extractor.getTrackCount();
            for (int i = 0; i < numTrack; i++) {
                //Get the track format at the specified index
                final MediaFormat format = extractor.getTrackFormat(i);
                //得到數據信息 1.video/avc  2.audio/mp4a-latm
                String mimetype = format.getString(MediaFormat.KEY_MIME);
                Log.d("tag", mimetype);
                if (mimetype.startsWith("audio")) {
                    //選擇頻道
                    extractor.selectTrack(i);

                    final MediaCodec mediaCodec = MediaCodec.createDecoderByType(mimetype);
                    mPlayer = new AudioPlayer(format.getInteger(MediaFormat.KEY_SAMPLE_RATE), AudioFormat
                            .CHANNEL_OUT_STEREO, AudioFormat.ENCODING_PCM_16BIT);
                    mPlayer.init();
                    mediaCodec.setCallback(new MediaCodec.Callback() {
                        @Override
                        public void onInputBufferAvailable(MediaCodec codec, int index) {
                            ByteBuffer inputBuffer = codec.getInputBuffer(index);
                            inputBuffer.clear();
                            int readlen = extractor.readSampleData(inputBuffer, 0);
                            Log.d("tag", "音頻輸入" + inputBuffer.toString());
                            codec.queueInputBuffer(index, 0, readlen, 0, 0);
                            extractor.advance();//Advance to the next sample.進入下一幀 刷新

                        }

                        @Override
                        public void onOutputBufferAvailable(MediaCodec codec, int index, MediaCodec.BufferInfo info) {
                            Log.d("tag", "onOutputBufferAvailable:" + info.size);
                            ByteBuffer outputBuffer = codec.getOutputBuffer(index);
                            MediaFormat outformat = codec.getOutputFormat();
                            if (outputBuffer != null && info.size > 0) {
                                byte[] buffer = new byte[outputBuffer.remaining()];
                                outputBuffer.get(buffer);
                                mPlayer.play(buffer, 0, info.size);
                                Log.d("tag", "Offer to queue failed, queue in full state");
                            }
                            codec.releaseOutputBuffer(index, true);
                        }

                        @Override
                        public void onError(MediaCodec codec, MediaCodec.CodecException e) {
                            Log.d("tag", "onError:" + e.getDiagnosticInfo());
                        }

                        @Override
                        public void onOutputFormatChanged(MediaCodec codec, MediaFormat format) {
                            Log.d("tag", "onOutputFormatChanged:");
//                                    outputFormat = format;
                        }
                    });
                    mediaCodec.configure(format, null, null, 0);
//                            outputFormat = format;
                    mediaCodec.start();
                }

            }

        } catch (IOException e) {
            e.printStackTrace();
        }
    }




public class AudioPlayer {

    private int mFrequency;// 採樣率
    private int mChannel;// 聲道
    private int mSampBit;// 採樣精度
    private AudioTrack mAudioTrack;

    public AudioPlayer(int frequency, int channel, int sampbit) {
        this.mFrequency = frequency;
        this.mChannel = channel;
        this.mSampBit = sampbit;
    }

    /**
     * 初始化
     */
    public void init() {
        if (mAudioTrack != null) {
            release();
        }
        // 獲得構建對象的最小緩衝區大小
        int minBufSize = AudioTrack.getMinBufferSize(mFrequency, mChannel, mSampBit);
        mAudioTrack = new AudioTrack(AudioManager.STREAM_MUSIC,
                mFrequency, mChannel, mSampBit, minBufSize, AudioTrack.MODE_STREAM);
        mAudioTrack.play();
    }

    /**
     * 釋放資源
     */
    private void release() {
        if (mAudioTrack != null) {
            mAudioTrack.stop();
            mAudioTrack.release();
        }
    }

    /**
     * 將解碼後的pcm數據寫入audioTrack播放
     *
     * @param data   數據
     * @param offset 偏移
     * @param length 需要播放的長度
     */
    public void play(byte[] data, int offset, int length) {
        if (data == null || data.length == 0) {
            return;
        }
        try {
            mAudioTrack.write(data, offset, length);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章