ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Android 音视频数据播放封装类

2021-01-26 22:06:05  阅读:96  来源: 互联网

标签:封装 int mDecoder mAudioTrack 音视频 mDecodeStarted Android null public


音频

public class CAudioTrack {

    private final int mFrequency;
    private final int mChannel;
    private final int mAudioFormat;
    private AudioTrack mAudioTrack;

    public CAudioTrack(int frequency, int channel, int audioFormat) {
        this.mFrequency = frequency;
        this.mChannel = channel;
        this.mAudioFormat = audioFormat;
    }

    /**
     * 初始化
     */
    public void init() {
        if (mAudioTrack != null) {
            release();
        }
        // 获得构建对象的最小缓冲区大小
        int minBufSize = 2 * getMinBufferSize();
        mAudioTrack = new AudioTrack(AudioManager.STREAM_MUSIC,
                mFrequency, mChannel, mAudioFormat, minBufSize, AudioTrack.MODE_STREAM);
        mAudioTrack.play();
    }

    /**
     * 释放资源
     */
    public void release() {
        if (mAudioTrack != null) {
            mAudioTrack.stop();
            mAudioTrack.release();
        }
    }

    private int getMinBufferSize() {
        return AudioTrack.getMinBufferSize(mFrequency, mChannel, mAudioFormat);
    }


    public void write(byte[] data) {
        if (mAudioTrack != null) {
            mAudioTrack.write(data, 0, data.length);
        }
    }

}

视频

public class CVideoPlayer {

    private volatile MediaCodec mDecoder;
    private volatile boolean mDecodeStarted = false;
    final private ReentrantLock mPlayerLock = new ReentrantLock();

    /**
     * 打开视频播放器
     *
     * @param width   视频宽度
     * @param height  视频高度
     * @param surface 播放视频的surface
     * @return 是否开启成功
     */
    public boolean open(int width, int height, Surface surface) {
        try {
            mPlayerLock.lock();
            Logger.d("CVideoPlayer open, mDecodeStarted is " + mDecodeStarted + " width is " + width + " ; height is " + height);
            if (mDecodeStarted) {
                //已经open无需重复操作
                return true;
            }

            //电话终端会出现解码器释放失败的问题,影响下一次的创建和播放
            //这里如果不为空,说明上一次释放出现异常,再手动调用下close,能保证此次正常
            if (mDecoder != null) {
                close();
            }

            MediaFormat format = MediaFormat.createVideoFormat("video/avc", width, height);
            mDecoder = MediaCodec.createDecoderByType("video/avc");
            mDecoder.configure(format, surface, null, 0);
            mDecoder.start();

            mDecodeStarted = true;
            Logger.d("open CVideoPlayer success");
        } catch (Exception e) {
            Logger.e("open CVideoPlayer exception: " + e.getMessage());
            mDecodeStarted = false;
            mDecoder = null;
            return false;
        } finally {
            mPlayerLock.unlock();
        }
        return true;
    }

    /**
     * 关闭视频播放器,释放资源
     */
    public void close() {
        try {
            mPlayerLock.lock();
            Logger.d("close CVideoPlayer begin");
            mDecodeStarted = false;
            if (mDecoder != null) {
                mDecoder.stop();
                mDecoder.release();
                mDecoder = null;
            }
            Logger.d("close CVideoPlayer end");
        } catch (Exception e) {
            Logger.e("close CVideoPlayer error : " + e.getMessage());
        } finally {
            mPlayerLock.unlock();
        }
    }

    /**
     * 播放视频流数据
     * @param data ES流
     * @param length 数据长度
     * @param pts presentation time
     */
    public void play(byte[] data, int length, int pts) {
        try {
            mPlayerLock.lock();
            if (!mDecodeStarted || mDecoder == null) {
                Logger.e("decoder is null, mDecodeStarted is " + mDecodeStarted + "; mDecoder is " + mDecoder);
                return;
            }
            onFrame(data, length, pts);
        } catch (Exception e) {
            Logger.e("CVideoPlayer play exception: " + e.getMessage());
        } finally {
            mPlayerLock.unlock();
        }
    }

    public void onFrame(byte[] buf, int length, long pts) {
        // Get input buffer index
        int inputBufferIndex = mDecoder.dequeueInputBuffer(100);

        if (inputBufferIndex >= 0) {
            //ByteBuffer inputBuffer = inputBuffers[inputBufferIndex];
            ByteBuffer inputBuffer;

            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                inputBuffer = mDecoder.getInputBuffer(inputBufferIndex);
            } else {
                inputBuffer = mDecoder.getInputBuffers()[inputBufferIndex];
            }
            inputBuffer.clear();
            inputBuffer.put(buf, 0, length);
            mDecoder.queueInputBuffer(inputBufferIndex, 0, length, pts, 0);
        } else {
            return;
        }

        // Get output buffer index
        MediaCodec.BufferInfo bufferInfo = new MediaCodec.BufferInfo();
        int outputBufferIndex = mDecoder.dequeueOutputBuffer(bufferInfo, 100);
        while (outputBufferIndex >= 0) {
            mDecoder.releaseOutputBuffer(outputBufferIndex, true);
            outputBufferIndex = mDecoder.dequeueOutputBuffer(bufferInfo, 0);
        }
    }
}

 

标签:封装,int,mDecoder,mAudioTrack,音视频,mDecodeStarted,Android,null,public
来源: https://blog.csdn.net/u012758497/article/details/113198031

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有