• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2014 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 android.hardware.camera2.cts;
18 
19 import android.graphics.ImageFormat;
20 import android.graphics.Rect;
21 import android.hardware.camera2.CameraCaptureSession;
22 import android.hardware.camera2.CameraCharacteristics;
23 import android.hardware.camera2.CameraDevice;
24 import android.hardware.camera2.CaptureRequest;
25 import android.hardware.camera2.CaptureResult;
26 import android.hardware.camera2.DngCreator;
27 import android.hardware.camera2.cts.helpers.StaticMetadata;
28 import android.hardware.camera2.cts.testcases.Camera2AndroidTestCase;
29 import android.location.Location;
30 import android.media.ExifInterface;
31 import android.media.Image;
32 import android.media.ImageReader;
33 import android.util.Log;
34 import android.util.Pair;
35 import android.util.Size;
36 import android.view.Surface;
37 
38 import java.io.ByteArrayOutputStream;
39 import java.io.FileOutputStream;
40 import java.util.ArrayList;
41 import java.util.List;
42 
43 import static android.hardware.camera2.cts.CameraTestUtils.configureCameraSession;
44 import static android.hardware.camera2.cts.helpers.AssertHelpers.*;
45 
46 /**
47  * Tests for the DngCreator API.
48  */
49 public class DngCreatorTest extends Camera2AndroidTestCase {
50     private static final String TAG = "DngCreatorTest";
51     private static final boolean VERBOSE = Log.isLoggable(TAG, Log.VERBOSE);
52     private static final String DEBUG_DNG_FILE = "raw16.dng";
53 
54     @Override
setUp()55     protected void setUp() throws Exception {
56         super.setUp();
57     }
58 
59     @Override
tearDown()60     protected void tearDown() throws Exception {
61         super.tearDown();
62     }
63 
64     /**
65      * Test basic raw capture and DNG saving functionality for each of the available cameras.
66      *
67      * <p>
68      * For each camera, capture a single RAW16 image at the first capture size reported for
69      * the raw format on that device, and save that image as a DNG file.  No further validation
70      * is done.
71      * </p>
72      *
73      * <p>
74      * Note: Enabling adb shell setprop log.tag.DngCreatorTest VERBOSE will also cause the
75      * raw image captured for the first reported camera device to be saved to an output file.
76      * </p>
77      */
testSingleImageBasic()78     public void testSingleImageBasic() throws Exception {
79         for (int i = 0; i < mCameraIds.length; i++) {
80             String deviceId = mCameraIds[i];
81             ImageReader captureReader = null;
82             FileOutputStream fileStream = null;
83             ByteArrayOutputStream outputStream = null;
84             try {
85                 openDevice(deviceId);
86 
87                 if (!mStaticInfo.isCapabilitySupported(
88                         CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_RAW)) {
89                     Log.i(TAG, "RAW capability is not supported in camera " + mCameraIds[i] +
90                             ". Skip the test.");
91                     continue;
92                 }
93 
94                 Size[] targetCaptureSizes =
95                         mStaticInfo.getAvailableSizesForFormatChecked(ImageFormat.RAW_SENSOR,
96                                 StaticMetadata.StreamDirection.Output);
97 
98                 assertTrue("No capture sizes available for RAW format!",
99                         targetCaptureSizes.length != 0);
100                 Rect activeArray = mStaticInfo.getActiveArraySizeChecked();
101                 Size activeArraySize = new Size(activeArray.width(), activeArray.height());
102                 assertTrue("Missing ActiveArraySize", activeArray.width() > 0 &&
103                         activeArray.height() > 0);
104                 // TODO: Allow PixelArraySize also.
105                 assertArrayContains("Available sizes for RAW format must include ActiveArraySize",
106                         targetCaptureSizes, activeArraySize);
107 
108                 // Create capture image reader
109                 CameraTestUtils.SimpleImageReaderListener captureListener
110                         = new CameraTestUtils.SimpleImageReaderListener();
111                 captureReader = createImageReader(activeArraySize, ImageFormat.RAW_SENSOR, 2,
112                         captureListener);
113                 Pair<Image, CaptureResult> resultPair = captureSingleRawShot(activeArraySize,
114                         captureReader, captureListener);
115                 CameraCharacteristics characteristics = mStaticInfo.getCharacteristics();
116 
117                 // Test simple writeImage, no header checks
118                 DngCreator dngCreator = new DngCreator(characteristics, resultPair.second);
119                 outputStream = new ByteArrayOutputStream();
120                 dngCreator.writeImage(outputStream, resultPair.first);
121 
122                 if (VERBOSE) {
123                     String filePath = DEBUG_FILE_NAME_BASE + "camera_" + deviceId + "_" +
124                             DEBUG_DNG_FILE;
125                     // Write out captured DNG file for the first camera device if setprop is enabled
126                     fileStream = new FileOutputStream(filePath);
127                     fileStream.write(outputStream.toByteArray());
128                     fileStream.flush();
129                     fileStream.close();
130                     Log.v(TAG, "Test DNG file for camera " + deviceId + " saved to " + filePath);
131                 }
132             } finally {
133                 closeDevice(deviceId);
134                 closeImageReader(captureReader);
135 
136                 if (outputStream != null) {
137                     outputStream.close();
138                 }
139 
140                 if (fileStream != null) {
141                     fileStream.close();
142                 }
143             }
144         }
145     }
146 
147     /**
148      * Test basic raw capture and DNG saving with a thumbnail, rotation, usercomment, and GPS tags
149      * set.
150      *
151      * <p>
152      * For each camera, capture a single RAW16 image at the first capture size reported for
153      * the raw format on that device, and save that image as a DNG file.  No further validation
154      * is done.
155      * </p>
156      *
157      * <p>
158      * Note: Enabling adb shell setprop log.tag.DngCreatorTest VERBOSE will also cause the
159      * raw image captured for the first reported camera device to be saved to an output file.
160      * </p>
161      */
testSingleImageThumbnail()162     public void testSingleImageThumbnail() throws Exception {
163         for (int i = 0; i < mCameraIds.length; i++) {
164             String deviceId = mCameraIds[i];
165             List<ImageReader> captureReaders = new ArrayList<ImageReader>();
166             List<CameraTestUtils.SimpleImageReaderListener> captureListeners =
167                     new ArrayList<CameraTestUtils.SimpleImageReaderListener>();
168             FileOutputStream fileStream = null;
169             ByteArrayOutputStream outputStream = null;
170             try {
171                 openDevice(deviceId);
172 
173                 if (!mStaticInfo.isCapabilitySupported(
174                         CameraCharacteristics.REQUEST_AVAILABLE_CAPABILITIES_RAW)) {
175                     Log.i(TAG, "RAW capability is not supported in camera " + mCameraIds[i] +
176                             ". Skip the test.");
177                     continue;
178                 }
179 
180                 Size[] targetCaptureSizes =
181                         mStaticInfo.getAvailableSizesForFormatChecked(ImageFormat.RAW_SENSOR,
182                                 StaticMetadata.StreamDirection.Output);
183 
184                 assertTrue("No capture sizes available for RAW format!",
185                         targetCaptureSizes.length != 0);
186                 Rect activeArray = mStaticInfo.getActiveArraySizeChecked();
187                 Size activeArraySize = new Size(activeArray.width(), activeArray.height());
188                 assertTrue("Missing ActiveArraySize", activeArray.width() > 0 &&
189                         activeArray.height() > 0);
190                 // TODO: Allow PixelArraySize also.
191                 assertArrayContains("Available sizes for RAW format must include ActiveArraySize",
192                         targetCaptureSizes, activeArraySize);
193 
194                 Size[] targetPreviewSizes =
195                         mStaticInfo.getAvailableSizesForFormatChecked(ImageFormat.YUV_420_888,
196                                 StaticMetadata.StreamDirection.Output);
197                 // Get smallest preview size
198                 Size previewSize = mOrderedPreviewSizes.get(mOrderedPreviewSizes.size() - 1);
199 
200                 // Create capture image reader
201                 CameraTestUtils.SimpleImageReaderListener captureListener
202                         = new CameraTestUtils.SimpleImageReaderListener();
203                 captureReaders.add(createImageReader(activeArraySize, ImageFormat.RAW_SENSOR, 2,
204                         captureListener));
205                 captureListeners.add(captureListener);
206 
207                 CameraTestUtils.SimpleImageReaderListener previewListener
208                         = new CameraTestUtils.SimpleImageReaderListener();
209 
210                 captureReaders.add(createImageReader(previewSize, ImageFormat.YUV_420_888, 2,
211                         previewListener));
212                 captureListeners.add(previewListener);
213 
214                 Pair<List<Image>, CaptureResult> resultPair = captureSingleRawShot(activeArraySize,
215                         captureReaders, captureListeners);
216                 CameraCharacteristics characteristics = mStaticInfo.getCharacteristics();
217 
218                 // Test simple writeImage, no header checks
219                 DngCreator dngCreator = new DngCreator(characteristics, resultPair.second);
220                 Location l = new Location("test");
221                 l.reset();
222                 l.setLatitude(37.420016);
223                 l.setLongitude(-122.081987);
224                 l.setTime(System.currentTimeMillis());
225                 dngCreator.setLocation(l);
226 
227                 dngCreator.setDescription("helloworld");
228                 dngCreator.setOrientation(ExifInterface.ORIENTATION_FLIP_VERTICAL);
229                 dngCreator.setThumbnail(resultPair.first.get(1));
230                 outputStream = new ByteArrayOutputStream();
231                 dngCreator.writeImage(outputStream, resultPair.first.get(0));
232 
233                 if (VERBOSE) {
234                     String filePath = DEBUG_FILE_NAME_BASE + "camera_" + deviceId + "_" +
235                             DEBUG_DNG_FILE;
236                     // Write out captured DNG file for the first camera device if setprop is enabled
237                     fileStream = new FileOutputStream(filePath);
238                     fileStream.write(outputStream.toByteArray());
239                     fileStream.flush();
240                     fileStream.close();
241                     Log.v(TAG, "Test DNG file for camera " + deviceId + " saved to " + filePath);
242                 }
243             } finally {
244                 closeDevice(deviceId);
245                 for (ImageReader r : captureReaders) {
246                     closeImageReader(r);
247                 }
248 
249                 if (outputStream != null) {
250                     outputStream.close();
251                 }
252 
253                 if (fileStream != null) {
254                     fileStream.close();
255                 }
256             }
257         }
258     }
259 
captureSingleRawShot(Size s, ImageReader captureReader, CameraTestUtils.SimpleImageReaderListener captureListener)260     private Pair<Image, CaptureResult> captureSingleRawShot(Size s, ImageReader captureReader,
261             CameraTestUtils.SimpleImageReaderListener captureListener) throws Exception {
262         List<ImageReader> readers = new ArrayList<ImageReader>();
263         readers.add(captureReader);
264         List<CameraTestUtils.SimpleImageReaderListener> listeners =
265                 new ArrayList<CameraTestUtils.SimpleImageReaderListener>();
266         listeners.add(captureListener);
267         Pair<List<Image>, CaptureResult> res = captureSingleRawShot(s, readers, listeners);
268         return new Pair<Image, CaptureResult>(res.first.get(0), res.second);
269     }
270 
271     /**
272      * Capture a single raw image.
273      *
274      * <p>Capture an raw image for a given size.</p>
275      *
276      * @param s The size of the raw image to capture.  Must be one of the available sizes for this
277      *          device.
278      * @return a pair containing the {@link Image} and {@link CaptureResult} used for this capture.
279      */
captureSingleRawShot(Size s, List<ImageReader> captureReaders, List<CameraTestUtils.SimpleImageReaderListener> captureListeners)280     private Pair<List<Image>, CaptureResult> captureSingleRawShot(Size s, List<ImageReader> captureReaders,
281             List<CameraTestUtils.SimpleImageReaderListener> captureListeners) throws Exception {
282         if (VERBOSE) {
283             Log.v(TAG, "captureSingleRawShot - Capturing raw image.");
284         }
285 
286         Size maxYuvSz = mOrderedPreviewSizes.get(0);
287         Size[] targetCaptureSizes =
288                 mStaticInfo.getAvailableSizesForFormatChecked(ImageFormat.RAW_SENSOR,
289                         StaticMetadata.StreamDirection.Output);
290 
291         // Validate size
292         boolean validSize = false;
293         for (int i = 0; i < targetCaptureSizes.length; ++i) {
294             if (targetCaptureSizes[i].equals(s)) {
295                 validSize = true;
296                 break;
297             }
298         }
299         assertTrue("Capture size is supported.", validSize);
300 
301 
302         // Capture images.
303         List<Surface> outputSurfaces = new ArrayList<Surface>();
304         for (ImageReader captureReader : captureReaders) {
305             Surface captureSurface = captureReader.getSurface();
306             outputSurfaces.add(captureSurface);
307         }
308 
309         CaptureRequest.Builder request = prepareCaptureRequestForSurfaces(outputSurfaces);
310         request.set(CaptureRequest.STATISTICS_LENS_SHADING_MAP_MODE,
311                 CaptureRequest.STATISTICS_LENS_SHADING_MAP_MODE_ON);
312         CameraTestUtils.SimpleCaptureCallback resultListener =
313                 new CameraTestUtils.SimpleCaptureCallback();
314 
315         startCapture(request.build(), /*repeating*/false, resultListener, mHandler);
316 
317         // Verify capture result and images
318         CaptureResult result = resultListener.getCaptureResult(CAPTURE_WAIT_TIMEOUT_MS);
319 
320         List<Image> resultImages = new ArrayList<Image>();
321         for (CameraTestUtils.SimpleImageReaderListener captureListener : captureListeners) {
322             Image captureImage = captureListener.getImage(CAPTURE_WAIT_TIMEOUT_MS);
323 
324             /*CameraTestUtils.validateImage(captureImage, s.getWidth(), s.getHeight(),
325                     ImageFormat.RAW_SENSOR, null);*/
326             resultImages.add(captureImage);
327         }
328         // Stop capture, delete the streams.
329         stopCapture(/*fast*/false);
330 
331         return new Pair<List<Image>, CaptureResult>(resultImages, result);
332     }
333 
prepareCaptureRequestForSurfaces(List<Surface> surfaces)334     private CaptureRequest.Builder prepareCaptureRequestForSurfaces(List<Surface> surfaces)
335             throws Exception {
336         createSession(surfaces);
337 
338         CaptureRequest.Builder captureBuilder =
339                 mCamera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
340         assertNotNull("Fail to get captureRequest", captureBuilder);
341         for (Surface surface : surfaces) {
342             captureBuilder.addTarget(surface);
343         }
344 
345         return captureBuilder;
346     }
347 }
348