在我的应用程序中,我们需要显示从服务器接收到我们的Android应用程序的视频帧,
服务器发送视频数据@ 50帧/秒,在WebM中编码,即使用libvpx对图像进行编码和解码,
现在从libvpx解码后得到YUV数据,我们可以在图像布局上显示,
目前的实现是这样的,
在JNI/Native C++代码中,我们将YUV数据转换为RGB数据在Android框架中调用
public Bitmap createImgae(byte[] bits, int width, int height, int scan) {
Bitmap bitmap=null;
System.out.println("video: creating bitmap");
//try{
bitmap = Bitmap.createBitmap(width, height,
Bitmap.Config.ARGB_8888);
bitmap.copyPixelsFromBuffer(ByteBuffer.wrap(bits));
//}catch(OutOfMemoryError ex){
//}
System.out.println("video: bitmap created");
return bitmap;
}
Run Code Online (Sandbox Code Playgroud)
要创建位图图像,
使用以下代码在imageView上显示图像,
img = createImgae(imgRaw, imgInfo[0], imgInfo[1], 1);
if(img!=null && !img.isRecycled()){
iv.setImageBitmap(img);
//img.recycle();
img=null;
System.out.println("video: image displayed");
}
Run Code Online (Sandbox Code Playgroud)
我的查询是,总的来说这个功能需要大约40毫秒,有没有办法优化它,
1 - 有没有办法向imageView显示YUV数据?
2 - 还有其他方法可以从RGB数据创建图像(位图图像),
3 - 我相信我总是在创建图像,但我想我应该只创建一次位图,并在我们收到时始终提供/提供新的缓冲区.
请分享您的观点.
通过 camera2 API,我们接收到格式为YUV_420_888的 Image 对象。然后我们使用以下函数转换为NV21:
private static byte[] YUV_420_888toNV21(Image image) {
byte[] nv21;
ByteBuffer yBuffer = image.getPlanes()[0].getBuffer();
ByteBuffer uBuffer = image.getPlanes()[1].getBuffer();
ByteBuffer vBuffer = image.getPlanes()[2].getBuffer();
int ySize = yBuffer.remaining();
int uSize = uBuffer.remaining();
int vSize = vBuffer.remaining();
nv21 = new byte[ySize + uSize + vSize];
//U and V are swapped
yBuffer.get(nv21, 0, ySize);
vBuffer.get(nv21, ySize, vSize);
uBuffer.get(nv21, ySize + vSize, uSize);
return nv21;
}
Run Code Online (Sandbox Code Playgroud)
虽然此函数与 配合良好cameraCaptureSessions.setRepeatingRequest,但在调用 时,我们会在进一步处理(在 JNI 端)中遇到分段错误cameraCaptureSessions.capture。两者都通过 ImageReader 请求 YUV_420_888 …