Skip to content

Most visited

Recently visited

navigation
Camera2Raw / src / com.example.android.camera2raw /

Camera2RawFragment.java

1
/*
2
 * Copyright 2015 The Android Open Source Project
3
 *
4
 * Licensed under the Apache License, Version 2.0 (the "License");
5
 * you may not use this file except in compliance with the License.
6
 * You may obtain a copy of the License at
7
 *
8
 *       http://www.apache.org/licenses/LICENSE-2.0
9
 *
10
 * Unless required by applicable law or agreed to in writing, software
11
 * distributed under the License is distributed on an "AS IS" BASIS,
12
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
 * See the License for the specific language governing permissions and
14
 * limitations under the License.
15
 */
16
 
17
package com.example.android.camera2raw;
18
 
19
import android.Manifest;
20
import android.app.Activity;
21
import android.app.AlertDialog;
22
import android.app.Dialog;
23
import android.app.DialogFragment;
24
import android.app.Fragment;
25
import android.content.Context;
26
import android.content.DialogInterface;
27
import android.content.pm.PackageManager;
28
import android.graphics.ImageFormat;
29
import android.graphics.Matrix;
30
import android.graphics.Point;
31
import android.graphics.RectF;
32
import android.graphics.SurfaceTexture;
33
import android.hardware.SensorManager;
34
import android.hardware.camera2.CameraAccessException;
35
import android.hardware.camera2.CameraCaptureSession;
36
import android.hardware.camera2.CameraCharacteristics;
37
import android.hardware.camera2.CameraDevice;
38
import android.hardware.camera2.CameraManager;
39
import android.hardware.camera2.CameraMetadata;
40
import android.hardware.camera2.CaptureFailure;
41
import android.hardware.camera2.CaptureRequest;
42
import android.hardware.camera2.CaptureResult;
43
import android.hardware.camera2.DngCreator;
44
import android.hardware.camera2.TotalCaptureResult;
45
import android.hardware.camera2.params.StreamConfigurationMap;
46
import android.media.Image;
47
import android.media.ImageReader;
48
import android.media.MediaScannerConnection;
49
import android.net.Uri;
50
import android.os.AsyncTask;
51
import android.os.Bundle;
52
import android.os.Environment;
53
import android.os.Handler;
54
import android.os.HandlerThread;
55
import android.os.Looper;
56
import android.os.Message;
57
import android.os.SystemClock;
58
import android.support.v13.app.FragmentCompat;
59
import android.support.v4.app.ActivityCompat;
60
import android.util.Log;
61
import android.util.Size;
62
import android.util.SparseIntArray;
63
import android.view.LayoutInflater;
64
import android.view.OrientationEventListener;
65
import android.view.Surface;
66
import android.view.TextureView;
67
import android.view.View;
68
import android.view.ViewGroup;
69
import android.widget.Toast;
70
 
71
import java.io.File;
72
import java.io.FileOutputStream;
73
import java.io.IOException;
74
import java.io.OutputStream;
75
import java.nio.ByteBuffer;
76
import java.text.SimpleDateFormat;
77
import java.util.ArrayList;
78
import java.util.Arrays;
79
import java.util.Collections;
80
import java.util.Comparator;
81
import java.util.Date;
82
import java.util.List;
83
import java.util.Locale;
84
import java.util.Map;
85
import java.util.TreeMap;
86
import java.util.concurrent.Semaphore;
87
import java.util.concurrent.TimeUnit;
88
import java.util.concurrent.atomic.AtomicInteger;
89
 
90
/**
91
 * A fragment that demonstrates use of the Camera2 API to capture RAW and JPEG photos.
92
 * <p/>
93
 * In this example, the lifecycle of a single request to take a photo is:
94
 * <ul>
95
 * <li>
96
 * The user presses the "Picture" button, resulting in a call to {@link #takePicture()}.
97
 * </li>
98
 * <li>
99
 * {@link #takePicture()} initiates a pre-capture sequence that triggers the camera's built-in
100
 * auto-focus, auto-exposure, and auto-white-balance algorithms (aka. "3A") to run.
101
 * </li>
102
 * <li>
103
 * When the pre-capture sequence has finished, a {@link CaptureRequest} with a monotonically
104
 * increasing request ID set by calls to {@link CaptureRequest.Builder#setTag(Object)} is sent to
105
 * the camera to begin the JPEG and RAW capture sequence, and an
106
 * {@link ImageSaver.ImageSaverBuilder} is stored for this request in the
107
 * {@link #mJpegResultQueue} and {@link #mRawResultQueue}.
108
 * </li>
109
 * <li>
110
 * As {@link CaptureResult}s and {@link Image}s become available via callbacks in a background
111
 * thread, a {@link ImageSaver.ImageSaverBuilder} is looked up by the request ID in
112
 * {@link #mJpegResultQueue} and {@link #mRawResultQueue} and updated.
113
 * </li>
114
 * <li>
115
 * When all of the necessary results to save an image are available, the an {@link ImageSaver} is
116
 * constructed by the {@link ImageSaver.ImageSaverBuilder} and passed to a separate background
117
 * thread to save to a file.
118
 * </li>
119
 * </ul>
120
 */
121
public class Camera2RawFragment extends Fragment
122
        implements View.OnClickListener, FragmentCompat.OnRequestPermissionsResultCallback {
123
 
124
    /**
125
     * Conversion from screen rotation to JPEG orientation.
126
     */
127
    private static final SparseIntArray ORIENTATIONS = new SparseIntArray();
128
 
129
    static {
130
        ORIENTATIONS.append(Surface.ROTATION_0, 0);
131
        ORIENTATIONS.append(Surface.ROTATION_90, 90);
132
        ORIENTATIONS.append(Surface.ROTATION_180, 180);
133
        ORIENTATIONS.append(Surface.ROTATION_270, 270);
134
    }
135
 
136
    /**
137
     * Request code for camera permissions.
138
     */
139
    private static final int REQUEST_CAMERA_PERMISSIONS = 1;
140
 
141
    /**
142
     * Permissions required to take a picture.
143
     */
144
    private static final String[] CAMERA_PERMISSIONS = {
145
            Manifest.permission.CAMERA,
146
            Manifest.permission.READ_EXTERNAL_STORAGE,
147
            Manifest.permission.WRITE_EXTERNAL_STORAGE,
148
    };
149
 
150
    /**
151
     * Timeout for the pre-capture sequence.
152
     */
153
    private static final long PRECAPTURE_TIMEOUT_MS = 1000;
154
 
155
    /**
156
     * Tolerance when comparing aspect ratios.
157
     */
158
    private static final double ASPECT_RATIO_TOLERANCE = 0.005;
159
 
160
    /**
161
     * Max preview width that is guaranteed by Camera2 API
162
     */
163
    private static final int MAX_PREVIEW_WIDTH = 1920;
164
 
165
    /**
166
     * Max preview height that is guaranteed by Camera2 API
167
     */
168
    private static final int MAX_PREVIEW_HEIGHT = 1080;
169
 
170
    /**
171
     * Tag for the {@link Log}.
172
     */
173
    private static final String TAG = "Camera2RawFragment";
174
 
175
    /**
176
     * Camera state: Device is closed.
177
     */
178
    private static final int STATE_CLOSED = 0;
179
 
180
    /**
181
     * Camera state: Device is opened, but is not capturing.
182
     */
183
    private static final int STATE_OPENED = 1;
184
 
185
    /**
186
     * Camera state: Showing camera preview.
187
     */
188
    private static final int STATE_PREVIEW = 2;
189
 
190
    /**
191
     * Camera state: Waiting for 3A convergence before capturing a photo.
192
     */
193
    private static final int STATE_WAITING_FOR_3A_CONVERGENCE = 3;
194
 
195
    /**
196
     * An {@link OrientationEventListener} used to determine when device rotation has occurred.
197
     * This is mainly necessary for when the device is rotated by 180 degrees, in which case
198
     * onCreate or onConfigurationChanged is not called as the view dimensions remain the same,
199
     * but the orientation of the has changed, and thus the preview rotation must be updated.
200
     */
201
    private OrientationEventListener mOrientationListener;
202
 
203
    /**
204
     * {@link TextureView.SurfaceTextureListener} handles several lifecycle events of a
205
     * {@link TextureView}.
206
     */
207
    private final TextureView.SurfaceTextureListener mSurfaceTextureListener
208
            = new TextureView.SurfaceTextureListener() {
209
 
210
        @Override
211
        public void onSurfaceTextureAvailable(SurfaceTexture texture, int width, int height) {
212
            configureTransform(width, height);
213
        }
214
 
215
        @Override
216
        public void onSurfaceTextureSizeChanged(SurfaceTexture texture, int width, int height) {
217
            configureTransform(width, height);
218
        }
219
 
220
        @Override
221
        public boolean onSurfaceTextureDestroyed(SurfaceTexture texture) {
222
            synchronized (mCameraStateLock) {
223
                mPreviewSize = null;
224
            }
225
            return true;
226
        }
227
 
228
        @Override
229
        public void onSurfaceTextureUpdated(SurfaceTexture texture) {
230
        }
231
 
232
    };
233
 
234
    /**
235
     * An {@link AutoFitTextureView} for camera preview.
236
     */
237
    private AutoFitTextureView mTextureView;
238
 
239
    /**
240
     * An additional thread for running tasks that shouldn't block the UI.  This is used for all
241
     * callbacks from the {@link CameraDevice} and {@link CameraCaptureSession}s.
242
     */
243
    private HandlerThread mBackgroundThread;
244
 
245
    /**
246
     * A counter for tracking corresponding {@link CaptureRequest}s and {@link CaptureResult}s
247
     * across the {@link CameraCaptureSession} capture callbacks.
248
     */
249
    private final AtomicInteger mRequestCounter = new AtomicInteger();
250
 
251
    /**
252
     * A {@link Semaphore} to prevent the app from exiting before closing the camera.
253
     */
254
    private final Semaphore mCameraOpenCloseLock = new Semaphore(1);
255
 
256
    /**
257
     * A lock protecting camera state.
258
     */
259
    private final Object mCameraStateLock = new Object();
260
 
261
    // *********************************************************************************************
262
    // State protected by mCameraStateLock.
263
    //
264
    // The following state is used across both the UI and background threads.  Methods with "Locked"
265
    // in the name expect mCameraStateLock to be held while calling.
266
 
267
    /**
268
     * ID of the current {@link CameraDevice}.
269
     */
270
    private String mCameraId;
271
 
272
    /**
273
     * A {@link CameraCaptureSession } for camera preview.
274
     */
275
    private CameraCaptureSession mCaptureSession;
276
 
277
    /**
278
     * A reference to the open {@link CameraDevice}.
279
     */
280
    private CameraDevice mCameraDevice;
281
 
282
    /**
283
     * The {@link Size} of camera preview.
284
     */
285
    private Size mPreviewSize;
286
 
287
    /**
288
     * The {@link CameraCharacteristics} for the currently configured camera device.
289
     */
290
    private CameraCharacteristics mCharacteristics;
291
 
292
    /**
293
     * A {@link Handler} for running tasks in the background.
294
     */
295
    private Handler mBackgroundHandler;
296
 
297
    /**
298
     * A reference counted holder wrapping the {@link ImageReader} that handles JPEG image
299
     * captures. This is used to allow us to clean up the {@link ImageReader} when all background
300
     * tasks using its {@link Image}s have completed.
301
     */
302
    private RefCountedAutoCloseable<ImageReader> mJpegImageReader;
303
 
304
    /**
305
     * A reference counted holder wrapping the {@link ImageReader} that handles RAW image captures.
306
     * This is used to allow us to clean up the {@link ImageReader} when all background tasks using
307
     * its {@link Image}s have completed.
308
     */
309
    private RefCountedAutoCloseable<ImageReader> mRawImageReader;
310
 
311
    /**
312
     * Whether or not the currently configured camera device is fixed-focus.
313