从 Android 中的视频图像中获取帧
我已经实现了一个在屏幕上显示相机图片的简单应用程序.我现在喜欢做的是抓取一个帧并将其作为位图处理.据我所知,这并不是一件容易的事.
I've implemented a simple application which shows the camera picture on the screen. What I like to do now is grab a single frame and process it as bitmap. From what I could find out to this point it is not an easy thing to do.
我尝试使用 onPreviewFrame 方法将当前帧作为字节数组获取,并尝试使用 BitmapFactory 类对其进行解码,但它返回 null.帧的格式是无标题的 YUV,可以转换为位图,但在手机上花费的时间太长.此外,我还了解到 onPreviewFrame 方法对运行时有限制,如果耗时过长,应用程序可能会崩溃.
I've tried using the onPreviewFrame method with which you get the current frame as a byte array and tried to decode it with the BitmapFactory class but it returns null. The format of the frame is a headerless YUV which could be translated to bitmap but it takes too long on a phone. Also I've read that the onPreviewFrame method has contraints on the runtime, if it takes too long the application could crash.
那么正确的方法是什么?
So what is the right way to do this?
推荐答案
在 API 17+ 中,您可以使用 'ScriptIntrinsicYuvToRGB' RenderScript 从 NV21 转换为 RGBA888.这使您无需手动编码/解码帧即可轻松处理预览帧:
In API 17+, you can do conversion to RGBA888 from NV21 with the 'ScriptIntrinsicYuvToRGB' RenderScript. This allows you to easily process preview frames without manually encoding/decoding frames:
@Override
public void onPreviewFrame(byte[] data, Camera camera) {
Bitmap bitmap = Bitmap.createBitmap(r.width(), r.height(), Bitmap.Config.ARGB_8888);
Allocation bmData = renderScriptNV21ToRGBA888(
mContext,
r.width(),
r.height(),
data);
bmData.copyTo(bitmap);
}
public Allocation renderScriptNV21ToRGBA888(Context context, int width, int height, byte[] nv21) {
RenderScript rs = RenderScript.create(context);
ScriptIntrinsicYuvToRGB yuvToRgbIntrinsic = ScriptIntrinsicYuvToRGB.create(rs, Element.U8_4(rs));
Type.Builder yuvType = new Type.Builder(rs, Element.U8(rs)).setX(nv21.length);
Allocation in = Allocation.createTyped(rs, yuvType.create(), Allocation.USAGE_SCRIPT);
Type.Builder rgbaType = new Type.Builder(rs, Element.RGBA_8888(rs)).setX(width).setY(height);
Allocation out = Allocation.createTyped(rs, rgbaType.create(), Allocation.USAGE_SCRIPT);
in.copyFrom(nv21);
yuvToRgbIntrinsic.setInput(in);
yuvToRgbIntrinsic.forEach(out);
return out;
}
相关文章