SampleViewBase.java

Shishir Joshi, 2012-08-08 07:47 am

Download (7.1 kB)

 
1
package org.opencv.samples.tutorial3;
2
3
import java.io.IOException;
4
import java.util.List;
5
6
import android.content.Context;
7
import android.graphics.Bitmap;
8
import android.graphics.Canvas;
9
import android.graphics.ImageFormat;
10
/*import android.graphics.SurfaceTexture;*/
11
import android.hardware.Camera;
12
import android.hardware.Camera.PreviewCallback;
13
import android.os.Build;
14
import android.util.Log;
15
import android.view.SurfaceHolder;
16
import android.view.SurfaceView;
17
18
public abstract class SampleViewBase extends SurfaceView implements SurfaceHolder.Callback, Runnable {
19
    private static final String TAG = "Sample::SurfaceView";
20
21
    private int numberOfCameras;
22
    private Camera              mCamera;
23
    private SurfaceHolder       mHolder;
24
    private int                 mFrameWidth;
25
    private int                 mFrameHeight;
26
    private byte[]              mFrame;
27
    private boolean             mThreadRun;
28
    private byte[]              mBuffer;
29
30
31
    public SampleViewBase(Context context) {
32
        super(context);
33
        mHolder = getHolder();
34
        mHolder.addCallback(this);
35
        Log.i(TAG, "Instantiated new " + this.getClass());
36
    }
37
38
    public int getFrameWidth() {
39
        return mFrameWidth;
40
    }
41
42
    public int getFrameHeight() {
43
        return mFrameHeight;
44
    }
45
46
    public void setPreview() throws IOException {
47
        /*if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB)
48
            mCamera.setPreviewTexture( new SurfaceTexture(10) );
49
        else
50
                mCamera.setPreviewDisplay(null);*/
51
        }
52
53
    public void surfaceChanged(SurfaceHolder _holder, int format, int width, int height) {
54
        Log.i(TAG, "surfaceCreated");
55
        if (mCamera != null) {
56
            Camera.Parameters params = mCamera.getParameters();
57
            //List<Camera.Size> sizes = params.getSupportedPreviewSizes();
58
            mFrameWidth = 352;
59
            mFrameHeight = 288;
60
61
            // selecting optimal camera preview size
62
            /*{
63
                int  minDiff = Integer.MAX_VALUE;
64
                for (Camera.Size size : sizes) {
65
                    if (Math.abs(size.height - height) < minDiff) {
66
                        mFrameWidth = size.width;
67
                        mFrameHeight = size.height;
68
                        minDiff = Math.abs(size.height - height);
69
                    }
70
                }
71
            }*/
72
73
            params.setPreviewSize(getFrameWidth(), getFrameHeight());
74
75
            List<String> FocusModes = params.getSupportedFocusModes();
76
            if (FocusModes.contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO))
77
            {
78
                    params.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO);
79
            }
80
            
81
            mCamera.setParameters(params);
82
83
            /* Now allocate the buffer */
84
            params = mCamera.getParameters();
85
            int size = params.getPreviewSize().width * params.getPreviewSize().height;
86
            size  = size * ImageFormat.getBitsPerPixel(params.getPreviewFormat()) / 8;
87
            mBuffer = new byte[size];
88
            /* The buffer where the current frame will be coppied */
89
            mFrame = new byte [size];
90
            mCamera.addCallbackBuffer(mBuffer);
91
92
                        try {
93
                                setPreview();
94
                        } catch (IOException e) {
95
                                Log.e(TAG, "mCamera.setPreviewDisplay/setPreviewTexture fails: " + e);
96
                        }
97
98
            /* Notify that the preview is about to be started and deliver preview size */
99
            onPreviewStared(params.getPreviewSize().width, params.getPreviewSize().height);
100
101
            /* Now we can start a preview */
102
            mCamera.startPreview();
103
        }
104
    }
105
106
    public void surfaceCreated(SurfaceHolder holder) {
107
        Log.i(TAG, "surfaceCreated");
108
        int cameraCount = 0;
109
        boolean flag1 = true;
110
        Camera.CameraInfo cameraInfo = new Camera.CameraInfo();
111
        cameraCount = Camera.getNumberOfCameras();
112
        for ( int camIdx = 0; camIdx < cameraCount; camIdx++ ) {
113
            Camera.getCameraInfo( camIdx, cameraInfo );
114
            if ( cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_FRONT  ) 
115
            {
116
                try {
117
                    mCamera = Camera.open( camIdx );
118
                    flag1 = false;
119
                } catch (RuntimeException e) {
120
                    Log.e(TAG, "Camera failed to open: " + e.getLocalizedMessage());
121
                }
122
            }
123
        }
124
        if (flag1){ mCamera = Camera.open();}
125
126
        mCamera.setPreviewCallbackWithBuffer(new PreviewCallback() {
127
            public void onPreviewFrame(byte[] data, Camera camera) {
128
                synchronized (SampleViewBase.this) {
129
                    System.arraycopy(data, 0, mFrame, 0, data.length);
130
                    SampleViewBase.this.notify(); 
131
                }
132
                camera.addCallbackBuffer(mBuffer);
133
            }
134
        });
135
                    
136
        (new Thread(this)).start();
137
    }
138
139
    public void surfaceDestroyed(SurfaceHolder holder) {
140
        Log.i(TAG, "surfaceDestroyed");
141
        mThreadRun = false;
142
        if (mCamera != null) {
143
            synchronized (this) {
144
                mCamera.stopPreview();
145
                mCamera.setPreviewCallback(null);
146
                mCamera.release();
147
                mCamera = null;
148
            }
149
        }
150
        onPreviewStopped();
151
    }
152
153
    /* The bitmap returned by this method shall be owned by the child and released in onPreviewStopped() */
154
    protected abstract Bitmap processFrame(byte[] data);
155
156
    /**
157
     * This method is called when the preview process is being started. It is called before the first frame delivered and processFrame is called
158
     * It is called with the width and height parameters of the preview process. It can be used to prepare the data needed during the frame processing.
159
     * @param previewWidth - the width of the preview frames that will be delivered via processFrame
160
     * @param previewHeight - the height of the preview frames that will be delivered via processFrame
161
     */
162
    protected abstract void onPreviewStared(int previewWidtd, int previewHeight);
163
164
    /**
165
     * This method is called when preview is stopped. When this method is called the preview stopped and all the processing of frames already completed.
166
     * If the Bitmap object returned via processFrame is cached - it is a good time to recycle it.
167
     * Any other resourcses used during the preview can be released.
168
     */
169
    protected abstract void onPreviewStopped();
170
171
    public void run() {
172
        mThreadRun = true;
173
        Log.i(TAG, "Starting processing thread");
174
        while (mThreadRun) {
175
            Bitmap bmp = null;
176
177
            synchronized (this) {
178
                try {
179
                    this.wait();
180
                    bmp = processFrame(mFrame);
181
                } catch (InterruptedException e) {
182
                    e.printStackTrace();
183
                }
184
            }
185
186
            if (bmp != null) {
187
                Canvas canvas = mHolder.lockCanvas();
188
                if (canvas != null) {
189
                    canvas.drawBitmap(bmp, (canvas.getWidth() - getFrameWidth()) / 2, (canvas.getHeight() - getFrameHeight()) / 2, null);
190
                    mHolder.unlockCanvasAndPost(canvas);
191
                }
192
            }
193
        }
194
    }
195
}