美文网首页
MediaCodec编码变模糊,马赛克问题?

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

作者: 夏木友人 | 来源:发表于2022-09-20 11:17 被阅读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);
    

    相关文章

      网友评论

          本文标题:MediaCodec编码变模糊,马赛克问题?

          本文链接:https://www.haomeiwen.com/subject/icmbortx.html