Android camera preview in surfaceview

17,815

Solution 1

I am facing same problem but I got this preview size by this method and now my camera preview working properly.

private Camera.Size getOptimalPreviewSize(List<Camera.Size> sizes, int w, int h) {
            final double ASPECT_TOLERANCE = 0.1;
            double targetRatio = (double) h / w;

            if (sizes == null)
                return null;

            Camera.Size optimalSize = null;
            double minDiff = Double.MAX_VALUE;

            int targetHeight = h;

            for (Camera.Size size : sizes) {
                double ratio = (double) size.height / size.width;
                if (Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE)
                    continue;

                if (Math.abs(size.height - targetHeight) < minDiff) {
                    optimalSize = size;
                    minDiff = Math.abs(size.height - targetHeight);
                }
            }

            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;
        }

    }

Solution 2

You have a choice to start "startPreview" inside a different thread ..

public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
    // Now that the size is known, set up the camera parameters and begin
    // the preview.
    Camera.Parameters parameters = camera.getParameters();
    parameters.setPreviewSize(80, 60);
    camera.setParameters(parameters);

    Thread preview_thread = new Thread(new Runnable() {
        @Override
        public void run() {
               camera.startPreview();
           }
        }, "preview_thread");
        preview_thread.start(); 
    }
Share:
17,815
Mihael Meklav
Author by

Mihael Meklav

Updated on June 04, 2022

Comments

  • Mihael Meklav
    Mihael Meklav almost 2 years

    I manage to put camera preview in surfaceview and this works great. But now i have problem with speed of other components. Because now it is really slow.

    Do i need to put camera in new thread? How to decrease fps or resolution? Because this what i have now does not work properly.

    My surface view:

    class KameraSurface extends SurfaceView implements SurfaceHolder.Callback {
        private static final String TAG = "Preview";
    
        SurfaceHolder mHolder;
        public Camera camera;
    
        KameraSurface(Context context) {
            super(context);
    
            // Install a SurfaceHolder.Callback so we get notified when the
            // underlying surface is created and destroyed.
            mHolder = getHolder();
            mHolder.addCallback(this);
            mHolder.setFormat(PixelFormat.RGB_332);
            mHolder.setType(SurfaceHolder.SURFACE_TYPE_GPU);
        }
    
        public void surfaceCreated(SurfaceHolder holder) {
            // The Surface has been created, acquire the camera and tell it where
            // to draw.
    
             camera = Camera.open();
    
             Camera.Parameters p = camera.getParameters();
             p.setPictureSize(80, 60);
             p.setColorEffect(android.hardware.Camera.Parameters.EFFECT_NONE);
             p.setJpegQuality(20);
             p.setPreviewFrameRate(1);
             p.setPreviewFpsRange(5, 10);
             p.setPreviewSize(80, 60);
             camera.setParameters(p);
    
    
    
            try {
                camera.setPreviewDisplay(holder);
    
    
                camera.setPreviewCallback(new PreviewCallback() {
    
                    public void onPreviewFrame(byte[] data, Camera arg1) {
                        //KameraSurface.this.invalidate();
                    }
                });
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    
        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.
            camera.stopPreview();
            camera = null;
        }
    public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
            // Now that the size is known, set up the camera parameters and begin
            // the preview.
            Camera.Parameters parameters = camera.getParameters();
            parameters.setPreviewSize(80, 60);
            camera.setParameters(parameters);
    
            camera.startPreview();
        }
    
        @Override
        public void draw(Canvas canvas) {
                super.draw(canvas);
                Paint p= new Paint(Color.RED);
                Log.d(TAG,"draw");
                canvas.drawText("PREVIEW", canvas.getWidth()/2, canvas.getHeight()/2, p );
        }
    }
    

    My xml:

    .
    .
    .
     <TableRow
                android:layout_width="match_parent"
                android:layout_height="fill_parent" >
    
                <FrameLayout
                    android:id="@+id/preview"
                    android:layout_width="133dp"
                    android:layout_height="100dp"
                    android:layout_margin="20dp" >
                </FrameLayout>
    .
    .
    .
    

    And how i call in main activity:

    KameraSurface preview = new KameraSurface(getApplicationContext());
                    ((FrameLayout) findViewById(R.id.preview)).addView(preview);
    
  • Daud Arfin
    Daud Arfin over 11 years
    why you have set frame rate as 1 .... standard frame rate for any camera device is atleast 15 fps ... try the same ..
  • Mihael Meklav
    Mihael Meklav over 11 years
    But there is no need to have 15fps.
  • Mihael Meklav
    Mihael Meklav over 11 years
    On goclever a103 tablet (ICS)
  • Graham Smith
    Graham Smith over 11 years
    Have you enabled Hardware acceleration? developer.android.com/guide/topics/graphics/hardware-accel.h‌​tml <application android:hardwareAccelerated="true" ...>
  • Mihael Meklav
    Mihael Meklav over 11 years
    I think that now is a little bit faster... Other half is probably because of a cheep tablet.
  • Graham Smith
    Graham Smith over 11 years
    Try running it on BlueStacks, the video playback is the only thing that doesnt work well but it links to your webcam to do camera work. Try it on there to see if is better. bluestacks.com