MediaCodec编码变模糊,马赛克问题?

2022-09-20  本文已影响0人  夏木友人

一、预览数据是正常,MediaCodec编码之后出来视频会变模糊,变马赛克?

最近在使用camera2录制视频时,碰到过保存本地视频,一直有马赛克不清晰的问题,但是一直找不到问题所在??本来以为是MediaCodec编码参数设置有问题,但是不管我怎么改,码率调的多大都不管用,还是会糊。后来我把camera回调的数据一帧一帧保存图片在本地,发现图片并没有视频那样模糊。那就排除camera预览数据问题,剩下就是编码问题。

if (rotation == 90 || rotation == 270) {
    //设置视频宽高
   mediaFormat = MediaFormat.createVideoFormat(MediaFormat.MIMETYPE_VIDEO_AVC, videoHeight, videoWidth);
} else {
   mediaFormat = MediaFormat.createVideoFormat(MediaFormat.MIMETYPE_VIDEO_AVC, videoWidth, videoHeight);
}
  //图像数据格式 YUV420
  mediaFormat.setInteger(MediaFormat.KEY_COLOR_FORMAT,    MediaCodecInfo.CodecCapabilities.COLOR_FormatYUV420Flexible);
 //码率
 mediaFormat.setInteger(MediaFormat.KEY_BIT_RATE, videoWidth * videoHeight * 8);
 //每秒30帧
  mediaFormat.setInteger(MediaFormat.KEY_FRAME_RATE, frameRate);
  //1秒一个关键帧
  mediaFormat.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 10);
  videoMediaCodec = MediaCodec.createEncoderByType(MediaFormat.MIMETYPE_VIDEO_AVC);

编码时,我会先把nv21数据转成nv12,然后再去编码。

byte[] nv12 = new byte[nv21.length];
byte[] yuvI420 = new byte[nv21.length];
byte[] tempYuvI420 = new byte[nv21.length];
LibyuvUtil.convertNV21ToI420(nv21, yuvI420, videoWidth, videoHeight);
LibyuvUtil.compressI420(yuvI420, videoWidth, videoHeight, tempYuvI420, videoWidth, videoHeight, rotation, isFrontCamera);
LibyuvUtil.convertI420ToNV12(tempYuvI420, nv12, videoWidth, videoHeight);

//得到编码器的输入和输出流, 输入流写入源数据 输出流读取编码后的数据
//得到要使用的缓存序列角标
int inputIndex = videoMediaCodec.dequeueInputBuffer(TIMEOUT_USEC);
if (inputIndex >= 0) {
    ByteBuffer inputBuffer = videoMediaCodec.getInputBuffer(inputIndex);
    inputBuffer.clear();
    //把要编码的数据添加进去
    inputBuffer.put(nv12);
    //塞到编码序列中, 等待MediaCodec编码
   videoMediaCodec.queueInputBuffer(inputIndex, 0, nv12.length, timeData, 0);
}

而在nv21转nv12是会有一个耗时,就造成了此时的时间与原始画面的时间间隔存在差异,如果在此时获取stamptime传入传入queueInputBuffer(...),编码的帧在时间上不连续,形成马赛克

videoMediaCodec.queueInputBuffer(inputIndex, 0, nv12.length, System.currentTimeMillis(), 0);

后来传给编码的时间戳改成预览时摄像头回调的时间戳,这样录制的视频就正常,不会有马赛克

 videoMediaCodec.queueInputBuffer(inputIndex, 0, nv12.length, timeData, 0);
上一篇下一篇

猜你喜欢

热点阅读