音频
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);
}
}
}