0

有人可以为我提供使用 PreviewCallback 接口读取相机视频每一帧的示例代码或示例吗?

我想在不使用表面的情况下获取帧,因为我首先想要相机视频的帧而不显示在屏幕上,然后我可以将该帧传递给 cocos2dx 的 CCLayer。

4

1 回答 1

1

这是一个缓慢的过程,无法处理传递给预览回调的每一帧数据。仅当您对实时预览应用程序的要求无法显示来自相机的视频或来自带有模板类型覆盖的相机的视频时,才应使用它,并且您的显示器每秒只能容忍几帧和一些延迟。

一些重要步骤

  1. 您的 Activity 必须扩展 Surface Holder,并且您不应该在创建表面之前启动相机。
  2. 预览版仅支持每个设备上的特定尺寸(我检查的最后一个设备上的 480 x 320 - 一段时间前),但您的请求不会引起任何问题,它只会被忽略。当您最终收到预览回调时,请检查onPreviewFrame().
  3. byte[]发送到的数组数据onPreviewFrame()为 YCbCr_422_SP 格式。没有其他格式可用,即使您尝试设置它们。数据在这里描述:http ://groups.google.com/group/android-developers/msg/d3b29d3ddc8abf9b
  4. 不要尝试解码onPreviewFrame(). 没有足够的时间 - 如果您尝试在该功能中保持系统这么长时间,您将用软管冲洗相机。将数据复制到您自己的缓冲区并在单独的Thread.
  5. Thread 在处理任何特定帧时,您将不得不跳过对接收​​到的新帧的处理。等到Thread完成后再使用下一个可用帧中的数据。

解码 YUV 预览数据

// decode Y, U, and V values on the YUV 420 buffer 
// described as YCbCr_422_SP by Android - David Manpearl
public static void decodeYUV(int[] out, byte[] fg, int width, int 
height) throws NullPointerException, IllegalArgumentException { 
        final int sz = width * height; 
        if(out == null) throw new NullPointerException("buffer 'out' is null"); 
        if(out.length < sz) throw new IllegalArgumentException("buffer 'out' size " + out.length + " < minimum " + sz); 
        if(fg == null) throw new NullPointerException("buffer 'fg' is null"); 
        if(fg.length < sz) throw new IllegalArgumentException("buffer 'fg' size " + fg.length + " < minimum " + sz * 3/ 2); 
        int i, j; 
        int Y, Cr = 0, Cb = 0; 
        for(j = 0; j < height; j++) { 
                int pixPtr = j * width; 
                final int jDiv2 = j >> 1; 
                for(i = 0; i < width; i++) { 
                        Y = fg[pixPtr]; if(Y < 0) Y += 255; 
                        if((i & 0x1) != 1) { 
                                final int cOff = sz + jDiv2 * width + (i >> 1) * 2; 
                                Cb = fg[cOff]; 
                                if(Cb < 0) Cb += 127; else Cb -= 128; 
                                Cr = fg[cOff + 1]; 
                                if(Cr < 0) Cr += 127; else Cr -= 128; 
                        } 
                        int R = Y + Cr + (Cr >> 2) + (Cr >> 3) + (Cr >> 5); 
                        if(R < 0) R = 0; else if(R > 255) R = 255; 
                        int G = Y - (Cb >> 2) + (Cb >> 4) + (Cb >> 5) - (Cr >> 1) + (Cr >> 3) + (Cr >> 4) + (Cr >> 5); 
                        if(G < 0) G = 0; else if(G > 255) G = 255; 
                        int B = Y + Cb + (Cb >> 1) + (Cb >> 2) + (Cb >> 6); 
                        if(B < 0) B = 0; else if(B > 255) B = 255; 
                        out[pixPtr++] = 0xff000000 + (B << 16) + (G << 8) + R; 
                } 
        } 
} 

byte[]数组转换为Bitmap

Bitmap bitmap = BitmapFactory.decodeByteArray(out , 0, out.length);
于 2013-04-01T06:30:42.170 回答