标签:封装 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. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。