android 视频缓存溢出导致视频黑屏,MediaMuxer+MediaCodec生成MP4视频黑屏

本文记录了一次解决Android开发中视频生成黑屏的问题,问题根源在于视频缓存溢出。通过分析源码,发现MediaMuxer在写入数据时出现异常,原因是BufferInfo的presentationTimeUs被意外修改。解决方案是在每次调用dequeueOutputBuffer时创建新的BufferInfo对象,避免影响后续写入。问题解决后,视频生成恢复正常。
摘要由CSDN通过智能技术生成

发表这篇文章目的是为了记录一次解决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

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值