LogCatから次のエラーが表示されます。
10-30 00:31:51.494: D/CameraHal(1205): CameraHal setOverlay/1/00000000/00000000
10-30 00:31:51.494: E/CameraHal(1205): Trying to set overlay, but overlay is null!, line:3472
10-30 00:31:51.494: W/CameraService(1205): Overlay create failed - retrying
...
10-30 00:31:52.526: E/CameraService(1205): Overlay Creation Failed!
...
10-30 00:31:52.588: E/AndroidRuntime(5040): FATAL EXCEPTION: main
10-30 00:31:52.588: E/AndroidRuntime(5040): Java.lang.RuntimeException: startPreview failed
10-30 00:31:52.588: E/AndroidRuntime(5040): at Android.hardware.Camera.startPreview(Native Method)
10-30 00:31:52.588: E/AndroidRuntime(5040): at com.matthewmitchell.nightcam.CameraSurfaceView.surfaceCreated(CameraSurfaceView.Java:47)
10-30 00:31:52.588: E/AndroidRuntime(5040): at Android.view.SurfaceView.updateWindow(SurfaceView.Java:544)
10-30 00:31:52.588: E/AndroidRuntime(5040): at Android.view.SurfaceView.dispatchDraw(SurfaceView.Java:341)
10-30 00:31:52.588: E/AndroidRuntime(5040): at Android.view.ViewGroup.drawChild(ViewGroup.Java:1638)
10-30 00:31:52.588: E/AndroidRuntime(5040): at Android.view.ViewGroup.dispatchDraw(ViewGroup.Java:1367)
10-30 00:31:52.588: E/AndroidRuntime(5040): at Android.view.View.draw(View.Java:6743)
10-30 00:31:52.588: E/AndroidRuntime(5040): at Android.widget.FrameLayout.draw(FrameLayout.Java:352)
10-30 00:31:52.588: E/AndroidRuntime(5040): at Android.view.ViewGroup.drawChild(ViewGroup.Java:1640)
10-30 00:31:52.588: E/AndroidRuntime(5040): at Android.view.ViewGroup.dispatchDraw(ViewGroup.Java:1367)
10-30 00:31:52.588: E/AndroidRuntime(5040): at Android.view.ViewGroup.drawChild(ViewGroup.Java:1638)
10-30 00:31:52.588: E/AndroidRuntime(5040): at Android.view.ViewGroup.dispatchDraw(ViewGroup.Java:1367)
10-30 00:31:52.588: E/AndroidRuntime(5040): at Android.view.View.draw(View.Java:6743)
10-30 00:31:52.588: E/AndroidRuntime(5040): at Android.widget.FrameLayout.draw(FrameLayout.Java:352)
10-30 00:31:52.588: E/AndroidRuntime(5040): at com.Android.internal.policy.impl.PhoneWindow$DecorView.draw(PhoneWindow.Java:1876)
10-30 00:31:52.588: E/AndroidRuntime(5040): at Android.view.ViewRoot.draw(ViewRoot.Java:1407)
10-30 00:31:52.588: E/AndroidRuntime(5040): at Android.view.ViewRoot.performTraversals(ViewRoot.Java:1163)
10-30 00:31:52.588: E/AndroidRuntime(5040): at Android.view.ViewRoot.handleMessage(ViewRoot.Java:1727)
10-30 00:31:52.588: E/AndroidRuntime(5040): at Android.os.Handler.dispatchMessage(Handler.Java:99)
10-30 00:31:52.588: E/AndroidRuntime(5040): at Android.os.Looper.loop(Looper.Java:123)
10-30 00:31:52.588: E/AndroidRuntime(5040): at Android.app.ActivityThread.main(ActivityThread.Java:4627)
10-30 00:31:52.588: E/AndroidRuntime(5040): at Java.lang.reflect.Method.invokeNative(Native Method)
10-30 00:31:52.588: E/AndroidRuntime(5040): at Java.lang.reflect.Method.invoke(Method.Java:521)
10-30 00:31:52.588: E/AndroidRuntime(5040): at com.Android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.Java:868)
10-30 00:31:52.588: E/AndroidRuntime(5040): at com.Android.internal.os.ZygoteInit.main(ZygoteInit.Java:626)
10-30 00:31:52.588: E/AndroidRuntime(5040): at dalvik.system.NativeStart.main(Native Method)
Activityクラスは次のとおりです。
public class NightCamActivity extends Activity {
private GLSurfaceView mGLView;
CameraSurfaceView surface_view;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Create a GLSurfaceView instance and set it
// as the ContentView for this Activity
Debug.out("Welcome");
surface_view = new CameraSurfaceView(this);
mGLView = new MySurfaceView(this);
setContentView(mGLView);
addContentView(surface_view, new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT));
}
@Override
protected void onPause() {
super.onPause();
// The following call pauses the rendering thread.
// If your OpenGL application is memory intensive,
// you should consider de-allocating objects that
// consume significant memory here.
mGLView.onPause();
}
@Override
protected void onResume() {
super.onResume();
// The following call resumes a paused rendering thread.
// If you de-allocated graphic objects for onPause()
// this is a good place to re-allocate them.
mGLView.onResume();
}
}
MySurfaceViewクラス:
class MySurfaceView extends GLSurfaceView{
public MySurfaceView(NightCamActivity context){
super(context);
// Create an OpenGL ES 2.0 context.
Debug.out("Mysurfaceview welcome");
setEGLContextClientVersion(2);
// Set the Renderer for drawing on the GLSurfaceView
MyRenderer renderer = new MyRenderer();
renderer.takeContext(context);
context.surface_view.renderer = renderer;
setRenderer(renderer);
}
}
CameraSurfaceViewクラス:
public class CameraSurfaceView extends SurfaceView implements SurfaceHolder.Callback, PreviewCallback {
private Camera camera;
Camera.Size use_size;
MyRenderer renderer;
public CameraSurfaceView(Context context) {
super(context);
SurfaceHolder holder = getHolder();
holder.addCallback(this);
Debug.out("Init CSV");
camera = Camera.open();
}
public void surfaceCreated(SurfaceHolder holder) {
Debug.out("SC");
try {
camera.setPreviewDisplay(holder);
} catch (IOException e) {
Debug.out("Could not set preview display for camera.");
}
camera.setPreviewCallback(this);
}
public void surfaceDestroyed(SurfaceHolder holder) {
// Surface will be destroyed when we return, so stop the preview.
// Because the CameraDevice object is not a shared resource, it's very
// important to release it when the activity is paused.
try {
if (camera != null) {
camera.stopPreview();
camera.release();
}
} catch (Exception e) {
Debug.out("Camera release failure.");
}
}
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
Camera.Parameters parameters = camera.getParameters();
List<Camera.Size> supportedPreviewSizes = parameters.getSupportedPreviewSizes();
Camera.Size optimalPreviewSize = getOptimalPreviewSize(supportedPreviewSizes, w, h);
if (optimalPreviewSize != null) {
parameters.setPreviewSize(optimalPreviewSize.width, optimalPreviewSize.height);
camera.setParameters(parameters);
camera.startPreview();
}
}
static Camera.Size getOptimalPreviewSize(List<Camera.Size> sizes, int w, int h) {
final double ASPECT_TOLERANCE = 0.1;
final double MAX_DOWNSIZE = 1.5;
double targetRatio = (double) w / h;
if (sizes == null) return null;
Camera.Size optimalSize = null;
double minDiff = Double.MAX_VALUE;
int targetHeight = h;
// Try to find an size match aspect ratio and size
for (Camera.Size size : sizes) {
double ratio = (double) size.width / size.height;
double downsize = (double) size.width / w;
if (downsize > MAX_DOWNSIZE) {
//if the preview is a lot larger than our display surface ignore it
//reason - on some phones there is not enough heap available to show the larger preview sizes
continue;
}
if (Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE) continue;
if (Math.abs(size.height - targetHeight) < minDiff) {
optimalSize = size;
minDiff = Math.abs(size.height - targetHeight);
}
}
// Cannot find the one match the aspect ratio, ignore the requirement
//keep the max_downsize requirement
if (optimalSize == null) {
minDiff = Double.MAX_VALUE;
for (Camera.Size size : sizes) {
double downsize = (double) size.width / w;
if (downsize > MAX_DOWNSIZE) {
continue;
}
if (Math.abs(size.height - targetHeight) < minDiff) {
optimalSize = size;
minDiff = Math.abs(size.height - targetHeight);
}
}
}
//everything else failed, just take the closest match
if (optimalSize == null) {
minDiff = Double.MAX_VALUE;
for (Camera.Size size : sizes) {
if (Math.abs(size.height - targetHeight) < minDiff) {
optimalSize = size;
minDiff = Math.abs(size.height - targetHeight);
}
}
}
return optimalSize;
}
public void onPreviewFrame(byte[] data, Camera arg1) {
Debug.out("PREVIEW FRAME:");
byte[] pixels = new byte[use_size.width * use_size.height * 3]; ;
decodeYUV420SP(pixels, data, use_size.width, use_size.height);
renderer.bindCameraTexture(pixels, use_size.width, use_size.height);
}
void decodeYUV420SP(byte[] rgb, byte[] yuv420sp, int width, int height) {
final int frameSize = width * height;
for (int j = 0, yp = 0; j < height; j++) {
int uvp = frameSize + (j >> 1) * width, u = 0, v = 0;
for (int i = 0; i < width; i++, yp++) {
int y = (0xff & ((int) yuv420sp[yp])) - 16;
if (y < 0){
y = 0;
}
if ((i & 1) == 0) {
v = (0xff & yuv420sp[uvp++]) - 128;
u = (0xff & yuv420sp[uvp++]) - 128;
}
int y1192 = 1192 * y;
int r = (y1192 + 1634 * v);
int g = (y1192 - 833 * v - 400 * u);
int b = (y1192 + 2066 * u);
if (r < 0){
r = 0;
}else if (r > 262143){
r = 262143;
}
if (g < 0){
g = 0;
}else if (g > 262143){
g = 262143;
}
if (b < 0){
b = 0;
}else if (b > 262143){
b = 262143;
}
rgb[yp*3] = (byte) (b << 6);
rgb[yp*3 + 1] = (byte) (b >> 2);
rgb[yp*3 + 2] = (byte) (b >> 10);
}
}
}
}
最後に、MyRenderクラス:
public class MyRenderer implements GLSurfaceView.Renderer{
private FloatBuffer vertices;
private FloatBuffer texcoords;
private int mProgram;
private int maPositionHandle;
private int gvTexCoordHandle;
private int gvSamplerHandle;
private static Context context;
int[] camera_texture;
public void onSurfaceCreated(GL10 unused, EGLConfig config) {
initShapes();
GLES20.glClearColor(0.0f, 1.0f, 0.2f, 1.0f);
Debug.out("Hello init.");
//Shaders
int vertexShader = 0;
int fragmentShader = 0;
try {
vertexShader = loadShader(GLES20.GL_VERTEX_SHADER, readFile("vertex.vsh"));
fragmentShader = loadShader(GLES20.GL_FRAGMENT_SHADER, readFile("fragment.fsh"));
} catch (IOException e) {
Debug.out("The shaders could not be found.");
e.printStackTrace();
}
mProgram = GLES20.glCreateProgram(); // create empty OpenGL Program
GLES20.glAttachShader(mProgram, vertexShader); // add the vertex shader to program
GLES20.glAttachShader(mProgram, fragmentShader); // add the fragment shader to program
GLES20.glLinkProgram(mProgram); // creates OpenGL program executables
// get handles
maPositionHandle = GLES20.glGetAttribLocation(mProgram, "vPosition");
gvTexCoordHandle = GLES20.glGetAttribLocation(mProgram, "a_texCoord");
gvSamplerHandle = GLES20.glGetAttribLocation(mProgram, "s_texture");
GLES20.glPixelStorei(GLES20.GL_UNPACK_ALIGNMENT, 1);
camera_texture = null;
}
private void initShapes(){
float triangleCoords[] = {
// X, Y, Z
-1.0f, -1.0f, 0.0f,
1.0f, -1.0f, 0.0f,
-1.0f, 1.0f, 0.0f,
1.0f, 1.0f, 0.0f,
};
float texcoordf[] = {
// X, Y, Z
-1.0f,-1.0f,
1.0f,-1.0f,
-1.0f,1.0f,
1.0f,1.0f,
};
// initialize vertex Buffer for vertices
ByteBuffer vbb = ByteBuffer.allocateDirect(triangleCoords.length * 4);
vbb.order(ByteOrder.nativeOrder());// use the device hardware's native byte order
vertices = vbb.asFloatBuffer(); // create a floating point buffer from the ByteBuffer
vertices.put(triangleCoords); // add the coordinates to the FloatBuffer
vertices.position(0); // set the buffer to read the first coordinate
// initialize vertex Buffer for texcoords
vbb = ByteBuffer.allocateDirect(texcoordf.length * 4);
vbb.order(ByteOrder.nativeOrder());// use the device hardware's native byte order
texcoords = vbb.asFloatBuffer(); // create a floating point buffer from the ByteBuffer
texcoords.put(texcoordf); // add the coordinates to the FloatBuffer
texcoords.position(0); // set the buffer to read the first coordinate
}
private static String readFile(String path) throws IOException {
AssetManager assetManager = context.getAssets();
InputStream stream = assetManager.open(path);
try {
return new Scanner(stream).useDelimiter("\\A").next();
}
finally {
stream.close();
}
}
private int loadShader(int type, String shaderCode){
// create a vertex shader type (GLES20.GL_VERTEX_SHADER)
// or a fragment shader type (GLES20.GL_FRAGMENT_SHADER)
int shader = GLES20.glCreateShader(type);
// add the source code to the shader and compile it
GLES20.glShaderSource(shader, shaderCode);
GLES20.glCompileShader(shader);
return shader;
}
public void onDrawFrame(GL10 unused) {
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);
if(camera_texture == null){
return;
}
// Add program to OpenGL environment
GLES20.glUseProgram(mProgram);
// Prepare the triangle data
GLES20.glVertexAttribPointer(maPositionHandle, 3, GLES20.GL_FLOAT, false, 0, vertices);
GLES20.glVertexAttribPointer(gvTexCoordHandle, 2, GLES20.GL_FLOAT, false, 0, texcoords);
GLES20.glEnableVertexAttribArray(maPositionHandle);
GLES20.glEnableVertexAttribArray(gvTexCoordHandle);
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, camera_texture[0]);
GLES20.glUniform1i(gvSamplerHandle, 0);
// Draw the triangle
GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);
GLES20.glDisableVertexAttribArray(maPositionHandle);
GLES20.glDisableVertexAttribArray(gvTexCoordHandle);
}
public void onSurfaceChanged(GL10 unused, int width, int height) {
GLES20.glViewport(0, 0, width, height);
}
public void takeContext(Context ocontext) {
Debug.out("Take context");
context = ocontext;
}
void bindCameraTexture(byte[] data,int w,int h) {
byte[] pixels = new byte[256*256*3];
for(int x = 0;x < 256;x++){
for(int y = 0;x < 256;x++){
pixels[x*256+y] = data[x*w+y];
}
}
if (camera_texture==null){
camera_texture=new int[1];
}else{
GLES20.glDeleteTextures(1, camera_texture, 0);
}
GLES20.glGenTextures(1, camera_texture, 0);
int tex = camera_texture[0];
GLES20.glBindTexture(GL10.GL_TEXTURE_2D, tex);
GLES20.glTexImage2D(GL10.GL_TEXTURE_2D, 0, GL10.GL_RGB, 256, 256, 0, GL10.GL_RGB, GL10.GL_UNSIGNED_BYTE, ByteBuffer.wrap(pixels));
GLES20.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_LINEAR);
}
}
私はあなたのコードを受け取り、あなたと同じエラーを受け取りました。しかし、デバッグでは、幅と高さの寸法が間違った方法で丸められているように見えたため、プレビューが失敗しているように見えますが、向きも役割を果たしていると思うので、それらを切り替えるだけではありません。
とにかく、CameraSurfaceViewを自分のものに置き換えました(以下を参照)。例外はありませんが、画面は完全に明るい緑色です(これは、vertex.vshまたはfragment.vshファイルがないためだと思います。
package stackOverflow.test;
import Java.io.IOException;
import Java.util.List;
import Android.content.Context;
import Android.hardware.Camera;
import Android.hardware.Camera.Size;
import Android.util.AttributeSet;
import Android.util.Log;
import Android.view.Display;
import Android.view.Surface;
import Android.view.SurfaceHolder;
import Android.view.SurfaceView;
import Android.view.View;
import Android.view.ViewGroup;
import Android.view.WindowManager;
public class CameraSurfaceView extends ViewGroup implements SurfaceHolder.Callback
{
private Size mPreviewSize;
private List<Size> mSupportedPreviewSizes;
private Context mContext;
private SurfaceView mSurfaceView;
private SurfaceHolder mHolder;
private final String TAG = "CameraSurfaceView";
private Camera mCamera;
private List<String> mSupportedFlashModes;
public CameraSurfaceView(Context context)
{
super(context);
mContext = context;
mCamera = Camera.open();
setCamera(mCamera);
mSurfaceView = new SurfaceView(context);
addView(mSurfaceView, 0);
mHolder = mSurfaceView.getHolder();
mHolder.addCallback(this);
mHolder.setType(SurfaceHolder.SURFACE_TYPE_Push_BUFFERS);
mHolder.setKeepScreenOn(true);
}
public CameraSurfaceView(Context context, AttributeSet attrs)
{
super(context, attrs);
mContext = context;
}
public void setSupportedPreviewSizes(List<Size> supportedPreviewSizes)
{
mSupportedPreviewSizes = supportedPreviewSizes;
}
public Size getPreviewSize()
{
return mPreviewSize;
}
public void setCamera(Camera camera)
{
mCamera = camera;
if (mCamera != null)
{
mSupportedPreviewSizes = mCamera.getParameters().getSupportedPreviewSizes();
mSupportedFlashModes = mCamera.getParameters().getSupportedFlashModes();
// Set the camera to Auto Flash mode.
if (mSupportedFlashModes.contains(Camera.Parameters.FLASH_MODE_AUTO))
{
Camera.Parameters parameters = mCamera.getParameters();
parameters.setFlashMode(Camera.Parameters.FLASH_MODE_AUTO);
mCamera.setParameters(parameters);
}
}
requestLayout();
}
@Override
public void surfaceDestroyed(SurfaceHolder holder)
{
// Surface will be destroyed when we return, so stop the preview.
if (mCamera != null)
{
mCamera.stopPreview();
}
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height)
{
// Now that the size is known, set up the camera parameters and begin
// the preview.
if (mCamera != null)
{
Camera.Parameters parameters = mCamera.getParameters();
Size previewSize = getPreviewSize();
parameters.setPreviewSize(previewSize.width, previewSize.height);
mCamera.setParameters(parameters);
mCamera.startPreview();
}
}
@Override
public void surfaceCreated(SurfaceHolder holder)
{
// The Surface has been created, acquire the camera and tell it where
// to draw.
try
{
if (mCamera != null)
{
mCamera.setPreviewDisplay(holder);
}
}
catch (IOException exception)
{
Log.e(TAG, "IOException caused by setPreviewDisplay()", exception);
}
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
{
final int width = resolveSize(getSuggestedMinimumWidth(), widthMeasureSpec);
final int height = resolveSize(getSuggestedMinimumHeight(), heightMeasureSpec);
setMeasuredDimension(width, height);
if (mSupportedPreviewSizes != null)
{
mPreviewSize = getOptimalPreviewSize(mSupportedPreviewSizes, width, height);
}
}
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom)
{
if (changed)
{
final View cameraView = getChildAt(0);
final int width = right - left;
final int height = bottom - top;
int previewWidth = width;
int previewHeight = height;
if (mPreviewSize != null)
{
Display display = ((WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
switch (display.getRotation())
{
case Surface.ROTATION_0:
previewWidth = mPreviewSize.height;
previewHeight = mPreviewSize.width;
mCamera.setDisplayOrientation(90);
break;
case Surface.ROTATION_90:
previewWidth = mPreviewSize.width;
previewHeight = mPreviewSize.height;
break;
case Surface.ROTATION_180:
previewWidth = mPreviewSize.height;
previewHeight = mPreviewSize.width;
break;
case Surface.ROTATION_270:
previewWidth = mPreviewSize.width;
previewHeight = mPreviewSize.height;
mCamera.setDisplayOrientation(180);
break;
}
}
final int scaledChildHeight = previewHeight * width / previewWidth;
cameraView.layout(0, height - scaledChildHeight, width, height);
}
}
private Size getOptimalPreviewSize(List<Size> sizes, int width, int height)
{
Size optimalSize = null;
final double ASPECT_TOLERANCE = 0.1;
double targetRatio = (double) height / width;
// Try to find a size match which suits the whole screen minus the menu on the left.
for (Size size : sizes)
{
if (size.height != width) continue;
double ratio = (double) size.width / size.height;
if (ratio <= targetRatio + ASPECT_TOLERANCE && ratio >= targetRatio - ASPECT_TOLERANCE)
{
optimalSize = size;
}
}
// If we cannot find the one that matches the aspect ratio, ignore the requirement.
if (optimalSize == null)
{
// TODO : Backup in case we don't get a size.
}
return optimalSize;
}
public void previewCamera()
{
try
{
mCamera.setPreviewDisplay(mHolder);
mCamera.startPreview();
}
catch(Exception e)
{
Log.d(TAG, "Cannot start preview.", e);
}
}
/*public void onPreviewFrame(byte[] data, Camera arg1) {
Log.d("CameraSurfaceView", "PREVIEW FRAME:");
byte[] pixels = new byte[use_size.width * use_size.height * 3]; ;
decodeYUV420SP(pixels, data, use_size.width, use_size.height);
renderer.bindCameraTexture(pixels, use_size.width, use_size.height);
}*/
void decodeYUV420SP(byte[] rgb, byte[] yuv420sp, int width, int height) {
final int frameSize = width * height;
for (int j = 0, yp = 0; j < height; j++) {
int uvp = frameSize + (j >> 1) * width, u = 0, v = 0;
for (int i = 0; i < width; i++, yp++) {
int y = (0xff & ((int) yuv420sp[yp])) - 16;
if (y < 0){
y = 0;
}
if ((i & 1) == 0) {
v = (0xff & yuv420sp[uvp++]) - 128;
u = (0xff & yuv420sp[uvp++]) - 128;
}
int y1192 = 1192 * y;
int r = (y1192 + 1634 * v);
int g = (y1192 - 833 * v - 400 * u);
int b = (y1192 + 2066 * u);
if (r < 0){
r = 0;
}else if (r > 262143){
r = 262143;
}
if (g < 0){
g = 0;
}else if (g > 262143){
g = 262143;
}
if (b < 0){
b = 0;
}else if (b > 262143){
b = 262143;
}
rgb[yp*3] = (byte) (b << 6);
rgb[yp*3 + 1] = (byte) (b >> 2);
rgb[yp*3 + 2] = (byte) (b >> 10);
}
}
}
}
OnPreviewFrame()メソッドを実行して、context.surface_view.renderer = rendererという行を実行するためにコメントアウトしたことに気付くでしょう。
私はOpenGLライブラリに精通していませんが、おそらくこれはあなたが再び行くのに十分かもしれません。
私は同じ問題を抱えていたので、プレビューサイズの設定を削除/再生しても機能しませんでした。次のコード行で修正しました。
mHolder.setType(SurfaceHolder.SURFACE_TYPE_Push_BUFFERS);
今では私にとってはうまくいきます!
例外の直前に、logcatで次のようなものを確認してください。
11-02 09:25:44.305: ERROR/QualcommCameraHardware(56): failed to construct master heap for pmem pool /dev/pmem_adsp
11-02 09:25:44.305: ERROR/QualcommCameraHardware(56): initPreview X: could not initialize preview heap.
11-02 09:25:44.305: ERROR/QualcommCameraHardware(56): startPreview X initPreview failed. Not starting preview.
これは、1024x768のプレビューサイズを設定しようとすると、携帯電話で横向きになります。 getSupportedPreviewSizes()メソッドは、このサイズがサポートされていると言いますが、OSはこの大きさのプレビューに十分なメモリを割り当てられないようです。小さいサイズを設定しても機能します。
また、以下のコードを試してください。 SurfaceChanged()メソッドからstartPreview()を呼び出す必要があります。その時点で、SurfaceViewの寸法がわかっています。 surfaceCreated()から呼び出すのは早すぎます。
これを使用して、SurfaceViewの特定のサイズに最適なプレビューサイズを決定します(Google CameraPreviewサンプルから適応)
static Size getOptimalPreviewSize(List<Size> sizes, int w, int h) {
final double ASPECT_TOLERANCE = 0.1;
final double MAX_DOWNSIZE = 1.5;
double targetRatio = (double) w / h;
if (sizes == null) return null;
Size optimalSize = null;
double minDiff = Double.MAX_VALUE;
int targetHeight = h;
// Try to find an size match aspect ratio and size
for (Size size : sizes) {
double ratio = (double) size.width / size.height;
double downsize = (double) size.width / w;
if (downsize > MAX_DOWNSIZE) {
//if the preview is a lot larger than our display surface ignore it
//reason - on some phones there is not enough heap available to show the larger preview sizes
continue;
}
if (Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE) continue;
if (Math.abs(size.height - targetHeight) < minDiff) {
optimalSize = size;
minDiff = Math.abs(size.height - targetHeight);
}
}
// Cannot find the one match the aspect ratio, ignore the requirement
//keep the max_downsize requirement
if (optimalSize == null) {
minDiff = Double.MAX_VALUE;
for (Size size : sizes) {
double downsize = (double) size.width / w;
if (downsize > MAX_DOWNSIZE) {
continue;
}
if (Math.abs(size.height - targetHeight) < minDiff) {
optimalSize = size;
minDiff = Math.abs(size.height - targetHeight);
}
}
}
//everything else failed, just take the closest match
if (optimalSize == null) {
minDiff = Double.MAX_VALUE;
for (Size size : sizes) {
if (Math.abs(size.height - targetHeight) < minDiff) {
optimalSize = size;
minDiff = Math.abs(size.height - targetHeight);
}
}
}
return optimalSize;
}
次のように、surfaceChanged()メソッドから呼び出します。
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
Camera.Parameters parameters = camera.getParameters();
List<Size> supportedPreviewSizes = parameters.getSupportedPreviewSizes();
Size optimalPreviewSize = getOptimalPreviewSize(supportedPreviewSizes, w, h);
if (optimalPreviewSize != null) {
parameters.setPreviewSize(optimalPreviewSize.width, optimalPreviewSize.height);
camera.setParameters(parameters);
camera.startPreview();
}
}
InitCamera()でSurfaceのタイプを設定してみてください。
private void initCamera() {
mCamSV = (SurfaceView)findViewById(R.id.surface_camera);
mCamSH = mCamSV.getHolder();
mCamSH.addCallback(this);
**mCamSH.setType(SurfaceHolder.SURFACE_TYPE_Push_BUFFERS);**
}
編集1
Android 2.2 SDKで私のために働いたすべてのファイルをここにコピーしています
アクティビティ
package com.stack.camera;
import Java.io.IOException;
import Android.app.Activity;
import Android.hardware.Camera;
import Android.os.Bundle;
import Android.view.SurfaceHolder;
import Android.view.SurfaceView;
import Android.view.WindowManager;
import Android.widget.FrameLayout;
public class CameraStackActivity extends Activity implements SurfaceHolder.Callback {
private Camera mCam;
private SurfaceView mCamSV;
private SurfaceHolder mCamSH;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
setContentView(R.layout.main);
initCamera();
}
@Override
public void onDestroy() {
stopCamera();
}
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
startCamera(holder, width, height);
}
public void surfaceCreated(SurfaceHolder holder) {
// TODO Auto-generated method stub
mCam = Camera.open();
try {
mCam.setPreviewDisplay(holder);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void surfaceDestroyed(SurfaceHolder holder) {
// TODO Auto-generated method stub
}
private void initCamera() {
mCamSV = (SurfaceView)findViewById(R.id.surface_camera);
mCamSH = mCamSV.getHolder();
mCamSH.addCallback(this);
mCamSH.setType(SurfaceHolder.SURFACE_TYPE_Push_BUFFERS);
}
private void startCamera(SurfaceHolder sh, int width, int height) {
Camera.Parameters p = mCam.getParameters();
// Camera.Size s = p.getSupportedPreviewSizes().get(0);
p.setPreviewSize(width, height);
mCam.setParameters(p);
try {
mCam.setPreviewDisplay(sh);
} catch (Exception e) {
}
mCam.startPreview();
}
private void stopCamera() {
mCamSH.removeCallback(this);
mCam.stopPreview();
mCam.release();
}
}
レイアウト
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
Android:orientation="vertical" Android:layout_width="fill_parent"
Android:layout_height="fill_parent">
<SurfaceView Android:id="@+id/surface_camera"
Android:layout_width="fill_parent" Android:layout_height="fill_parent" />
</FrameLayout>
マニフェストファイル
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:Android="http://schemas.Android.com/apk/res/Android"
package="com.stack.camera"
Android:versionCode="1"
Android:versionName="1.0">
<uses-permission Android:name="Android.permission.CAMERA" />
<uses-feature Android:name="Android.hardware.camera" />
<uses-feature Android:name="Android.hardware.camera.autofocus" />
<application Android:icon="@drawable/icon" Android:label="@string/app_name">
<activity Android:name="CameraStackActivity"
Android:label="@string/app_name">
<intent-filter>
<action Android:name="Android.intent.action.MAIN" />
<category Android:name="Android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
OPの質問とはあまり関係ありませんが、それでも...
私は次の落とし穴が私に与えることを見たJava.io.IOException: setPreviewDisplay failed
:
ビデオと写真の両方を行う場合、camera.unlock()とcamera.reconnect()の2つの関数があります。ビデオを記録する前にcamera.unlock()および写真を撮る前にcamera.reconnect()を実行する必要があります。
簡単な解決策:CameraSurfaceView
クラスに次の行を追加します。
holder.setType(SurfaceHolder.SURFACE_TYPE_Push_BUFFERS);
これらの行の下:
SurfaceHolder holder = getHolder();
holder.addCallback(this);
私はこのゲームに少し遅れていますが、私はコルドバを実行していて、同時にカメラに登録しようとする2つのプラグインがありました。
これが私以外の人に役立つかどうかはわかりません。