发表这篇文章目的是为了记录一次解决Android开发中遇到的问题,总结解决思路及心得.这里要特别感谢指导我的刘老师,新项目的领导.
现象:配置(CPU)稍微偏低的手机生成视频播放时为黑屏.
初步分析:为写入视频时出错导致.
分析的思路如下:
下面是音视频混合代码:
EncoderVideoRunnable和MediaMuxerRunnable是两个线程,前者生成编码后的视频数据,后者将视频数据写入文件.
(AiMediaMuxer.java)
private class MediaMuxerRunnable implements Runnable {
@Override
public void run() {
initMuxer();
baseTimeStamp = System.nanoTime();
while (!isExit) {
// 混合器没有启动或数据缓存为空,则阻塞混合线程等待启动(数据输入)
if (isMuxerStarted) {
// 从缓存读取数据写入混合器中
if (mMuxerDatas.isEmpty()) {
// PaDebugUtil.i(TAG, "run--->混合器没有数据,阻塞线程等待");
synchronized (lock) {
try {
lock.wait();
} catch (Exception e) {
e.printStackTrace();
}
}
} else {
MuxerData data = mMuxerDatas.remove(0);
if (data != null) {
int track = 0;
try {
if (data.trackIndex == TRACK_VIDEO) {
track = videoTrack;
// PaDebugUtil.d(TAG, "---写入视频数据---");
} else if (data.trackIndex == TRACK_AUDIO) {
// PaDebugUtil.d(TAG, "---写入音频数据---");
track = audioTrack;
}
// PaDebugUtil.d(TAG, "before SampleData presentationTimeUs: "+data.bufferInfo.presentationTimeUs);
mMuxer.writeSampleData(track, data.byteBuf, data.bufferInfo);
prevOutputPTSUs = data.bufferInfo.presentationTimeUs;
} catch (Exception e) {
PaDebugUtil.e(TAG, "写入数据到混合器失败,track=" + track);
e.printStackTrace();
}
}
}
} else {
PaDebugUtil.i(TAG, "run--->混合器没有启动,阻塞线程等待");
synchronized (lock) {
try {
lock.wait();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
stopMuxer();
}
}
其中mMuxerDatas为自定义混合器数据集合,便于MediaMuxer.writeSampleData()使用.
private Vector mMuxerDatas;
/**
* 封装要混合器数据实体
*/
public static class MuxerData {
int trackIndex;
ByteBuffer byteBuf;
MediaCodec.BufferInfo bufferInfo;
public MuxerData(int trackIndex, ByteBuffer byteBuf, MediaCodec.BufferInfo bufferInfo) {
this.trackIndex = trackIndex;
this.byteBuf = byteBuf;
this.bufferInfo = bufferInfo;
}
}
组装数据的地方:
(EncoderVideoRunnable.java)
@SuppressLint("NewApi")
private void encoderBytes(byte[] rawFrame) {
ByteBuffer[] inputBuffers = mVideoEncodec.getInputBuffers();
ByteBuffer[] outputBuffers = mVideoEncodec.getOutputBuffers