zoukankan      html  css  js  c++  java
  • 【Android 多媒体应用】使用MediaCodec解码使用SurfaceView显示视频

    1.MainActivity.java

    import android.app.Activity;
    import android.os.Bundle;
    import android.os.Environment;
    import android.view.SurfaceHolder;
    import android.view.SurfaceView;
    
    /**
     * MediaCodec SurfaceHolder Example
     * @author taehwan
     *
     */
    public class MainActivity extends Activity implements SurfaceHolder.Callback {
        private VideoDecoderThread mVideoDecoder;
    
        private static final String FILE_PATH = Environment.getExternalStorageDirectory() + "/TopGirl.mp4";
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
    
            SurfaceView surfaceView = new SurfaceView(this);
            surfaceView.getHolder().addCallback(this);
            setContentView(surfaceView);
    
            mVideoDecoder = new VideoDecoderThread();
        }
    
        @Override
        public void surfaceCreated(SurfaceHolder holder) {
    
        }
    
        @Override
        public void surfaceChanged(SurfaceHolder holder, int format, int width,    int height) {
            if (mVideoDecoder != null) {
                if (mVideoDecoder.init(holder.getSurface(), FILE_PATH)) {
                    mVideoDecoder.start();
    
                } else {
                    mVideoDecoder = null;
                }
    
            }
        }
    
        @Override
        public void surfaceDestroyed(SurfaceHolder holder) {
            if (mVideoDecoder != null) {
                mVideoDecoder.close();
            }
        }
    
    }

    2.VideoDecoderThread.java

    import java.io.IOException;
    import java.nio.ByteBuffer;
    
    import android.media.MediaCodec;
    import android.media.MediaCodec.BufferInfo;
    import android.media.MediaExtractor;
    import android.media.MediaFormat;
    import android.util.Log;
    import android.view.Surface;
    
    public class VideoDecoderThread extends Thread {
        private static final String VIDEO = "video/";
        private static final String TAG = "VideoDecoder";
        private MediaExtractor mExtractor;
        private MediaCodec mDecoder;
    
        private boolean eosReceived;
    
        public boolean init(Surface surface, String filePath) {
            eosReceived = false;
            try {
                mExtractor = new MediaExtractor();
                mExtractor.setDataSource(filePath);
                //分离出音轨和视轨
                Log.d(TAG, "getTrackCount: " + mExtractor.getTrackCount() );
                for (int i = 0; i < mExtractor.getTrackCount(); i++) {
                    MediaFormat format = mExtractor.getTrackFormat(i);
    
                    String mime = format.getString(MediaFormat.KEY_MIME);
                    if (mime.startsWith(VIDEO)) {
                        mExtractor.selectTrack(i);
                        mDecoder = MediaCodec.createDecoderByType(mime);
                        try {
                            Log.d(TAG, "format : " + format);
                            mDecoder.configure(format, surface, null, 0 /* Decoder */);
    
                        } catch (IllegalStateException e) {
                            Log.e(TAG, "codec '" + mime + "' failed configuration. " + e);
                            return false;
                        }
    
                        mDecoder.start();
                        break;
                    }
                }
    
            } catch (IOException e) {
                e.printStackTrace();
            }
    
            return true;
        }
    
        @Override
        public void run() {
            BufferInfo info = new BufferInfo();
            ByteBuffer[] inputBuffers = mDecoder.getInputBuffers();
            mDecoder.getOutputBuffers();
    
            boolean isInput = true;
            boolean first = false;
            long startWhen = 0;
    
            while (!eosReceived) {
                if (isInput) {
                    int inputIndex = mDecoder.dequeueInputBuffer(10000);
                    if (inputIndex >= 0) {
                        // fill inputBuffers[inputBufferIndex] with valid data
                        ByteBuffer inputBuffer = inputBuffers[inputIndex];
    
                        int sampleSize = mExtractor.readSampleData(inputBuffer, 0);
    
                        if (mExtractor.advance() && sampleSize > 0) {
                            mDecoder.queueInputBuffer(inputIndex, 0, sampleSize, mExtractor.getSampleTime(), 0);
    
                        } else {
                            Log.d(TAG, "InputBuffer BUFFER_FLAG_END_OF_STREAM");
                            mDecoder.queueInputBuffer(inputIndex, 0, 0, 0, MediaCodec.BUFFER_FLAG_END_OF_STREAM);
                            isInput = false;
                        }
                    }
                }
    
                int outIndex = mDecoder.dequeueOutputBuffer(info, 10000);
                switch (outIndex) {
                    case MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED:
                        Log.d(TAG, "INFO_OUTPUT_BUFFERS_CHANGED");
                        mDecoder.getOutputBuffers();
                        break;
    
                    case MediaCodec.INFO_OUTPUT_FORMAT_CHANGED:
                        Log.d(TAG, "INFO_OUTPUT_FORMAT_CHANGED format : " + mDecoder.getOutputFormat());
                        break;
    
                    case MediaCodec.INFO_TRY_AGAIN_LATER:
    //                Log.d(TAG, "INFO_TRY_AGAIN_LATER");
                        break;
    
                    default:
                        if (!first) {
                            startWhen = System.currentTimeMillis();
                            first = true;
                        }
                        try {
                            long sleepTime = (info.presentationTimeUs / 1000) - (System.currentTimeMillis() - startWhen);
                            //Log.d(TAG, "info.presentationTimeUs : " + (info.presentationTimeUs / 1000) + " playTime: " + (System.currentTimeMillis() - startWhen) + " sleepTime : " + sleepTime);
    
                            if (sleepTime > 0)
                                Thread.sleep(sleepTime);
                        } catch (InterruptedException e) {
                            // TODO Auto-generated catch block
                            e.printStackTrace();
                        }
    
                        mDecoder.releaseOutputBuffer(outIndex, true /* Surface init */);
                        break;
                }
    
                // All decoded frames have been rendered, we can stop playing now
                if ((info.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {
                    Log.d(TAG, "OutputBuffer BUFFER_FLAG_END_OF_STREAM");
                    break;
                }
            }
    
            mDecoder.stop();
            mDecoder.release();
            mExtractor.release();
        }
    
        public void close() {
            eosReceived = true;
        }
    }
  • 相关阅读:
    Algs4-1.3链表实现泛型可迭代Stack
    Algs4-1.3链表实现科泛型可迭代Bag
    Algs4-1.3链表实现不定容泛型Queue不支持迭代
    Algs4-1.3不定容数组实现泛型栈支持迭代
    Algs4-1.3链表实现不定容泛型Stack不支持迭代
    Algs4-1.3不定容泛型栈(不可迭代)
    Algs4-1.3定容字符串栈
    Algs4-1.3定容泛型栈
    Algs4-1.3E.W.Dijkstra双栈算术表达式求值算法
    Algs4-1.2(非习题)可视化累加器
  • 原文地址:https://www.cnblogs.com/CoderTian/p/6221944.html
Copyright © 2011-2022 走看看