如何在不丢失帧的情况下将 ByteBuffer 转换为位图,以及反之?

3

我有一个 ByteBuffer:

var rgbaData = JniUtil.nativeAllocateByteBuffer(frame.width * frame.height * 4)

其中框架是从实时流媒体中获取的VideoFrame。我想将HighPassSkinSmoothing滤镜应用于从上述缓冲区获取的位图,将位图转换回ByteArray,将其放入ByteBuffer中,然后释放回实时流媒体。我已经完成了以下工作:将缓冲区转换为位图,应用滤镜,然后再次将位图转换为ByteArray,并将其放入缓冲区。

应用HighPassSkinSmoothing滤镜:

val bitmap = getBitmapFromBuffer(frame.width, frame.height, rgbaData)

amniXSkinSmooth.storeBitmap(bitmap, false)
amniXSkinSmooth.initSdk()
amniXSkinSmooth.startSkinSmoothness(600F)
amniXSkinSmooth.startSkinWhiteness(2F)
//sometimes "amniXSkinSmooth.bitmapAndFree" is also null, might be due to wrong conversion process
rgbaData.put(getByteArrayFromBitmap(amniXSkinSmooth.bitmapAndFree))
amniXSkinSmooth.unInitSdk();

将 ByteBuffer 转换为 Bitmap:

private fun getBitmapFromBuffer(width: Int, height: Int, buffer: ByteBuffer): Bitmap {
    buffer.rewind()
    val bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888)
    bitmap.copyPixelsFromBuffer(buffer)
    return bitmap
}

将位图转换回字节数组:

private fun getByteArrayFromBitmap(b: Bitmap): ByteArray {
  val size: Int = b.byteCount
  val buffer = ByteBuffer.allocate(size)
  val bytes = ByteArray(size)
  b.copyPixelsToBuffer(buffer)
  buffer.rewind()
  buffer.get(bytes)
  return bytes
}

通过这样做,我失去了帧数,并且应用过滤器后实时流媒体也会出现延迟。有没有什么解决方法,让帧数不会下降,实时流媒体也不会延迟?
如果您对转换过程或其他任何事情有任何想法或知识,您的帮助将不胜感激。谢谢!!

你的 getByteArrayFromBitmap() 方法应该被命名为 getByteBufferFromBitmap(),因为它返回的是 ByteBuffer。不要让自己被自己的命名方案所迷惑。 - user207421
是的,我知道,并且在我的问题中已经很好地解释了这种情况。 - Pratik Adhikari
你尝试过使用协程进行转换吗?我曾经遇到过类似的情况,需要在位图上执行 AR 操作。使用协程可以消除抖动或帧率下降,但肯定会有一个小间隔,但这个间隔会非常一致。 - mohit48
即使使用协程,结果仍然是相同的。不知道,也许我用错了。您能否展示一下您是如何使用它的? - Pratik Adhikari
1个回答

0

我认为我们可以使用内存映射文件,例如MappedByteBuffer作为存储器来保存RGB字节缓冲区。现在,我们可以使用窗口机制,例如滑动窗口/跳跃窗口,并按照窗口方法处理数据。这样,我们就可以处理流数据。一旦处理完成,我们可以删除MappedByteBuffer的底层文件。窗口还可以保存MappedByteBuffer的起始/结束地址。此外,窗口的确切大小可能取决于网络带宽。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接