13ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin/* 23ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin * Copyright (C) 2016 The Android Open Source Project 33ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin * 43ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin * Licensed under the Apache License, Version 2.0 (the "License"); 53ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin * you may not use this file except in compliance with the License. 63ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin * You may obtain a copy of the License at 73ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin * 83ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin * http://www.apache.org/licenses/LICENSE-2.0 93ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin * 103ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin * Unless required by applicable law or agreed to in writing, software 113ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin * distributed under the License is distributed on an "AS IS" BASIS, 123ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 133ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin * See the License for the specific language governing permissions and 143ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin * limitations under the License. 153ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin */ 163ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin 173ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yinpackage com.android.mediaframeworktest.stress; 183ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin 193ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yinimport com.android.ex.camera2.blocking.BlockingSessionCallback; 203ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yinimport com.android.ex.camera2.exceptions.TimeoutRuntimeException; 213ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yinimport com.android.mediaframeworktest.Camera2SurfaceViewTestCase; 223ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yinimport com.android.mediaframeworktest.helpers.Camera2Focuser; 233ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yinimport com.android.mediaframeworktest.helpers.CameraTestUtils; 243ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yinimport com.android.mediaframeworktest.helpers.CameraTestUtils.SimpleCaptureCallback; 253ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin 263ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yinimport android.graphics.ImageFormat; 273ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yinimport android.graphics.Point; 283ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yinimport android.hardware.camera2.CameraCharacteristics; 293ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yinimport android.hardware.camera2.CameraCaptureSession.CaptureCallback; 303ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yinimport android.hardware.camera2.CameraConstrainedHighSpeedCaptureSession; 313ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yinimport android.hardware.camera2.CameraDevice; 323ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yinimport android.hardware.camera2.CameraAccessException; 333ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yinimport android.hardware.camera2.CameraCaptureSession; 343ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yinimport android.hardware.camera2.CaptureRequest; 353ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yinimport android.hardware.camera2.CaptureResult; 363ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yinimport android.hardware.camera2.DngCreator; 373ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yinimport android.hardware.camera2.params.MeteringRectangle; 383ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yinimport android.media.Image; 393ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yinimport android.media.ImageReader; 403ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yinimport android.media.CamcorderProfile; 413ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yinimport android.media.MediaExtractor; 423ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yinimport android.media.MediaFormat; 433ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yinimport android.media.MediaRecorder; 443ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yinimport android.os.ConditionVariable; 453ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yinimport android.os.Environment; 463ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yinimport android.util.Log; 473ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yinimport android.util.Pair; 483ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yinimport android.util.Rational; 493ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yinimport android.util.Size; 503ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yinimport android.view.Surface; 513ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yinimport android.hardware.camera2.params.StreamConfigurationMap; 523ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yinimport android.test.suitebuilder.annotation.LargeTest; 533ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yinimport android.util.Log; 543ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yinimport android.util.Range; 553ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin 563ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yinimport java.io.ByteArrayOutputStream; 573ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yinimport java.util.ArrayList; 583ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yinimport java.util.List; 593ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yinimport java.io.File; 603ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yinimport java.util.Arrays; 613ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yinimport java.util.HashMap; 623ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin 633ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yinimport static com.android.mediaframeworktest.helpers.CameraTestUtils.CAPTURE_IMAGE_TIMEOUT_MS; 643ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yinimport static com.android.mediaframeworktest.helpers.CameraTestUtils.MAX_READER_IMAGES; 653ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yinimport static com.android.mediaframeworktest.helpers.CameraTestUtils.SimpleImageReaderListener; 663ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yinimport static com.android.mediaframeworktest.helpers.CameraTestUtils.basicValidateJpegImage; 673ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yinimport static com.android.mediaframeworktest.helpers.CameraTestUtils.configureCameraSession; 683ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yinimport static com.android.mediaframeworktest.helpers.CameraTestUtils.dumpFile; 693ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yinimport static com.android.mediaframeworktest.helpers.CameraTestUtils.getDataFromImage; 703ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yinimport static com.android.mediaframeworktest.helpers.CameraTestUtils.getValueNotNull; 713ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yinimport static com.android.mediaframeworktest.helpers.CameraTestUtils.makeImageReader; 723ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yinimport static com.android.ex.camera2.blocking.BlockingSessionCallback.SESSION_CLOSED; 733ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yinimport static com.android.mediaframeworktest.helpers.CameraTestUtils.CAPTURE_IMAGE_TIMEOUT_MS; 743ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yinimport static com.android.mediaframeworktest.helpers.CameraTestUtils.SESSION_CLOSE_TIMEOUT_MS; 753ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yinimport static com.android.mediaframeworktest.helpers.CameraTestUtils.SIZE_BOUND_1080P; 763ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yinimport static com.android.mediaframeworktest.helpers.CameraTestUtils.SIZE_BOUND_2160P; 773ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yinimport static com.android.mediaframeworktest.helpers.CameraTestUtils.getSupportedVideoSizes; 783ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin 793ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yinimport com.android.ex.camera2.blocking.BlockingSessionCallback; 803ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yinimport com.android.mediaframeworktest.Camera2SurfaceViewTestCase; 813ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yinimport com.android.mediaframeworktest.helpers.CameraTestUtils; 823ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin 833ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yinimport junit.framework.AssertionFailedError; 843ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin 853ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin/** 863ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin * <p>Tests Back/Front camera switching and Camera/Video modes witching.</p> 873ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin * 883ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin * adb shell am instrument \ 893ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin * -e class com.android.mediaframeworktest.stress.Camera2SwitchPreviewTest \ 903ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin * -e iterations 200 \ 913ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin * -e waitIntervalMs 1000 \ 923ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin * -e resultToFile false \ 933ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin * -r -w com.android.mediaframeworktest/.Camera2InstrumentationTestRunner 943ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin */ 953ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yinpublic class Camera2SwitchPreviewTest extends Camera2SurfaceViewTestCase { 963ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin private static final String TAG = "SwitchPreviewTest"; 973ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin private static final boolean VERBOSE = Log.isLoggable(TAG, Log.VERBOSE); 983ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG); 993ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin // 60 second to accommodate the possible long exposure time. 1003ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin private static final int MAX_REGIONS_AE_INDEX = 0; 1013ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin private static final int MAX_REGIONS_AWB_INDEX = 1; 1023ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin private static final int MAX_REGIONS_AF_INDEX = 2; 1033ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin private static final int WAIT_FOR_FOCUS_DONE_TIMEOUT_MS = 6000; 1043ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin private static final double AE_COMPENSATION_ERROR_TOLERANCE = 0.2; 1053ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin // 5 percent error margin for resulting metering regions 1063ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin private static final float METERING_REGION_ERROR_PERCENT_DELTA = 0.05f; 1073ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin private final String VIDEO_FILE_PATH = Environment.getExternalStorageDirectory().getPath(); 1083ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin 1093ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin private static final boolean DEBUG_DUMP = Log.isLoggable(TAG, Log.DEBUG); 1103ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin private static final int RECORDING_DURATION_MS = 3000; 1113ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin private static final float DURATION_MARGIN = 0.2f; 1123ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin private static final double FRAME_DURATION_ERROR_TOLERANCE_MS = 3.0; 1133ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin private static final int BIT_RATE_1080P = 16000000; 1143ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin private static final int BIT_RATE_MIN = 64000; 1153ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin private static final int BIT_RATE_MAX = 40000000; 1163ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin private static final int VIDEO_FRAME_RATE = 30; 1173ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin private static final int[] mCamcorderProfileList = { 1183ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin CamcorderProfile.QUALITY_HIGH, 1193ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin CamcorderProfile.QUALITY_2160P, 1203ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin CamcorderProfile.QUALITY_1080P, 1213ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin CamcorderProfile.QUALITY_720P, 1223ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin CamcorderProfile.QUALITY_480P, 1233ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin CamcorderProfile.QUALITY_CIF, 1243ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin CamcorderProfile.QUALITY_QCIF, 1253ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin CamcorderProfile.QUALITY_QVGA, 1263ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin CamcorderProfile.QUALITY_LOW, 1273ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin }; 1283ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin private static final int MAX_VIDEO_SNAPSHOT_IMAGES = 5; 1293ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin private static final int BURST_VIDEO_SNAPSHOT_NUM = 3; 1303ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin private static final int SLOWMO_SLOW_FACTOR = 4; 1313ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin private static final int MAX_NUM_FRAME_DROP_INTERVAL_ALLOWED = 4; 1323ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin private List<Size> mSupportedVideoSizes; 1333ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin private Surface mRecordingSurface; 1343ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin private Surface mPersistentSurface; 1353ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin private MediaRecorder mMediaRecorder; 1363ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin private String mOutMediaFileName; 1373ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin private int mVideoFrameRate; 1383ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin private Size mVideoSize; 1393ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin private long mRecordingStartTime; 1403ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin 1413ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin @Override 1423ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin protected void setUp() throws Exception { 1433ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin super.setUp(); 1443ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin } 1453ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin 1463ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin @Override 1473ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin protected void tearDown() throws Exception { 1483ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin super.tearDown(); 1493ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin } 1503ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin 1513ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin /** 1523ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin * Test normal still preview switch. 1533ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin * <p> 1543ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin * Preview jpeg output streams are configured. Max still capture 1553ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin * size is used for jpeg capture. 1563ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin * </p> 1573ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin */ 1583ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin public void testPreviewSwitchBackFrontCamera() throws Exception { 1593ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin List<String> mCameraColorOutputIds = cameraColorOutputCheck(); 1603ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin // Test iteration starts... 1613ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin Log.i(TAG, "Testing preview switch back/front camera in still capture mode"); 1623ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin for (int iteration = 0; iteration < getIterationCount(); ++iteration) { 1633ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin for (String id : mCameraColorOutputIds) { 1643ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin try { 1653ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin openDevice(id); 1663ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin // Preview for basic still capture: 1673ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin Log.v(TAG, String.format("Preview pictures: %d/%d", iteration + 1, 1683ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin getIterationCount())); 1693ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin stillCapturePreviewPreparer(id); 1703ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin getResultPrinter().printStatus(getIterationCount(), iteration + 1, id); 1713ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin } finally { 1723ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin closeDevice(); 1733ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin closeImageReader(); 1743ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin } 1753ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin } 1763ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin } 1773ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin } 1783ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin 1793ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin /** 1803ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin * <p> 1813ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin * Test basic video preview switch. 1823ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin * </p> 1833ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin * <p> 1843ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin * This test covers the typical basic use case of video preview switch. 1853ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin * MediaRecorder is used to record the audio and video, CamcorderProfile is 1863ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin * used to configure the MediaRecorder. Preview is set to the video size. 1873ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin * </p> 1883ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin */ 1893ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin public void testPreviewSwitchBackFrontVideo() throws Exception { 1903ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin List<String> mCameraColorOutputIds = cameraColorOutputCheck(); 1913ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin // Test iteration starts... 1923ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin Log.i(TAG, "Testing preview switch back/front camera in video mode"); 1933ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin for (int iteration = 0; iteration < getIterationCount(); ++iteration) { 1943ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin for (String id : mCameraColorOutputIds) { 1953ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin try { 1963ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin openDevice(id); 1973ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin // Preview for basic video recording: 1983ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin Log.v(TAG, String.format("Preview for recording videos: %d/%d", iteration + 1, 1993ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin getIterationCount())); 2003ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin recordingPreviewPreparer(id); 2013ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin getResultPrinter().printStatus(getIterationCount(), iteration + 1, id); 2023ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin } finally { 2033ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin closeDevice(); 2043ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin releaseRecorder(); 2053ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin } 2063ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin } 2073ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin } 2083ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin } 2093ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin 2103ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin 2113ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin /** 2123ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin * Test back camera preview switch between still capture and recording mode. 2133ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin * <p> 2143ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin * This test covers the basic case of preview switch camera mode, between 2153ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin * still capture (photo) and recording (video) mode. The preview settings 2163ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin * are same with the settings in "testPreviewSwitchBackFrontCamera" and 2173ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin * "testPreviewSwitchBackFrontVideo" 2183ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin * </p> 2193ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin */ 2203ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin public void testPreviewSwitchBackCameraVideo() throws Exception { 2213ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin String id = mCameraIds[0]; 2223ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin openDevice(id); 2233ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin if (!mStaticInfo.isColorOutputSupported()) { 2243ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin Log.i(TAG, "Camera " + id + 2253ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin " does not support color outputs, skipping"); 2263ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin return; 2273ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin } 2283ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin closeDevice(); 2293ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin // Test iteration starts... 2303ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin Log.i(TAG, "Testing preview switch between still capture/video modes for back camera"); 2313ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin for (int iteration = 0; iteration < getIterationCount(); ++iteration) { 2323ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin try { 2333ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin openDevice(id); 2343ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin 2353ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin // Preview for basic still capture: 2363ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin Log.v(TAG, String.format("Preview pictures: %d/%d", iteration + 1, 2373ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin getIterationCount())); 2383ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin stillCapturePreviewPreparer(id); 2393ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin getResultPrinter().printStatus(getIterationCount(), iteration + 1, id); 2403ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin 2413ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin // Preview for basic video recording: 2423ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin Log.v(TAG, String.format("Preview for recording videos: %d/%d", iteration + 1, 2433ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin getIterationCount())); 2443ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin recordingPreviewPreparer(id); 2453ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin getResultPrinter().printStatus(getIterationCount(), iteration + 1, id); 2463ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin } finally { 2473ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin closeDevice(); 2483ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin closeImageReader(); 2493ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin } 2503ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin } 2513ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin } 2523ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin 2533ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin /** 2543ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin * Test front camera preview switch between still capture and recording mode. 2553ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin * <p> 2563ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin * This test covers the basic case of preview switch camera mode, between 2573ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin * still capture (photo) and recording (video) mode. The preview settings 2583ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin * are same with the settings in "testPreviewSwitchBackFrontCamera" and 2593ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin * "testPreviewSwitchBackFrontVideo" 2603ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin * </p> 2613ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin */ 2623ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin public void testPreviewSwitchFrontCameraVideo() throws Exception{ 2633ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin String id = mCameraIds[1]; 2643ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin openDevice(id); 2653ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin if (!mStaticInfo.isColorOutputSupported()) { 2663ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin Log.i(TAG, "Camera " + id + 2673ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin " does not support color outputs, skipping"); 2683ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin return; 2693ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin } 2703ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin closeDevice(); 2713ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin // Test iteration starts... 2723ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin Log.i(TAG, "Testing preview switch between still capture/video modes for front camera"); 2733ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin for (int iteration = 0; iteration < getIterationCount(); ++iteration) { 2743ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin try { 2753ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin openDevice(id); 2763ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin 2773ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin // Preview for basic still capture: 2783ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin Log.v(TAG, String.format("Preview pictures: %d/%d", iteration + 1, 2793ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin getIterationCount())); 2803ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin stillCapturePreviewPreparer(id); 2813ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin getResultPrinter().printStatus(getIterationCount(), iteration + 1, id); 2823ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin 2833ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin // Preview for basic video recording: 2843ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin Log.v(TAG, String.format("Preview for recording videos: %d/%d", iteration + 1, 2853ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin getIterationCount())); 2863ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin recordingPreviewPreparer(id); 2873ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin getResultPrinter().printStatus(getIterationCount(), iteration + 1, id); 2883ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin } finally { 2893ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin closeDevice(); 2903ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin closeImageReader(); 2913ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin } 2923ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin } 2933ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin } 2943ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin 2953ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin private void stillCapturePreviewPreparer(String id) throws Exception{ 2963ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin CaptureResult result; 2973ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin SimpleCaptureCallback resultListener = new SimpleCaptureCallback(); 2983ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin SimpleImageReaderListener imageListener = new SimpleImageReaderListener(); 2993ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin CaptureRequest.Builder previewRequest = 3003ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin mCamera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW); 3013ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin CaptureRequest.Builder stillRequest = 3023ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin mCamera.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE); 3033ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin // Preview Setup: 3043ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin prepareCapturePreview(previewRequest, stillRequest, resultListener, imageListener); 3053ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin 3063ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin Thread.sleep(getTestWaitIntervalMs()); 3073ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin } 3083ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin 3093ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin private void recordingPreviewPreparer(String id) throws Exception{ 3103ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin // Re-use the MediaRecorder object for the same camera device. 3113ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin mMediaRecorder = new MediaRecorder(); 3123ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin initSupportedVideoSize(id); 3133ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin // preview Setup: 3143ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin basicRecordingPreviewTestByCamera(mCamcorderProfileList); 3153ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin 3163ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin Thread.sleep(getTestWaitIntervalMs()); 3173ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin } 3183ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin 3193ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin 3203ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin /** 3213ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin * Initialize the supported video sizes. 3223ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin */ 3233ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin private void initSupportedVideoSize(String cameraId) throws Exception { 3243ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin Size maxVideoSize = SIZE_BOUND_1080P; 3253ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin if (CamcorderProfile.hasProfile(CamcorderProfile.QUALITY_2160P)) { 3263ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin maxVideoSize = SIZE_BOUND_2160P; 3273ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin } 3283ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin mSupportedVideoSizes = 3293ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin getSupportedVideoSizes(cameraId, mCameraManager, maxVideoSize); 3303ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin } 3313ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin 3323ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin 3333ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin /** 3343ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin * Test camera recording preview by using each available CamcorderProfile for a 3353ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin * given camera. preview size is set to the video size. 3363ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin */ 3373ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin private void basicRecordingPreviewTestByCamera(int[] camcorderProfileList) 3383ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin throws Exception { 3393ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin Size maxPreviewSize = mOrderedPreviewSizes.get(0); 3403ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin List<Range<Integer> > fpsRanges = Arrays.asList( 3413ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin mStaticInfo.getAeAvailableTargetFpsRangesChecked()); 3423ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin int cameraId = Integer.parseInt(mCamera.getId()); 3433ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin int maxVideoFrameRate = -1; 3443ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin int profileId = camcorderProfileList[0]; 3453ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin if (!CamcorderProfile.hasProfile(cameraId, profileId) || 3463ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin allowedUnsupported(cameraId, profileId)) { 3473ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin return; 3483ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin } 3493ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin 3503ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin CamcorderProfile profile = CamcorderProfile.get(cameraId, profileId); 3513ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin Size videoSz = new Size(profile.videoFrameWidth, profile.videoFrameHeight); 3523ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin Range<Integer> fpsRange = new Range(profile.videoFrameRate, profile.videoFrameRate); 3533ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin if (maxVideoFrameRate < profile.videoFrameRate) { 3543ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin maxVideoFrameRate = profile.videoFrameRate; 3553ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin } 3563ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin if (mStaticInfo.isHardwareLevelLegacy() && 3573ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin (videoSz.getWidth() > maxPreviewSize.getWidth() || 3583ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin videoSz.getHeight() > maxPreviewSize.getHeight())) { 3593ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin // Skip. Legacy mode can only do recording up to max preview size 3603ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin return; 3613ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin } 3623ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin assertTrue("Video size " + videoSz.toString() + " for profile ID " + profileId + 3633ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin " must be one of the camera device supported video size!", 3643ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin mSupportedVideoSizes.contains(videoSz)); 3653ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin assertTrue("Frame rate range " + fpsRange + " (for profile ID " + profileId + 3663ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin ") must be one of the camera device available FPS range!", 3673ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin fpsRanges.contains(fpsRange)); 3683ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin 3693ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin if (VERBOSE) { 3703ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin Log.v(TAG, "Testing camera recording with video size " + videoSz.toString()); 3713ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin } 3723ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin 3733ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin // Configure preview and recording surfaces. 3743ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin mOutMediaFileName = VIDEO_FILE_PATH + "/test_video.mp4"; 3753ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin if (DEBUG_DUMP) { 3763ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin mOutMediaFileName = VIDEO_FILE_PATH + "/test_video_" + cameraId + "_" 3773ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin + videoSz.toString() + ".mp4"; 3783ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin } 3793ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin 3803ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin prepareRecordingWithProfile(profile); 3813ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin 3823ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin // prepare preview surface by using video size. 3833ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin updatePreviewSurfaceWithVideo(videoSz, profile.videoFrameRate); 3843ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin 3853ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin CaptureRequest.Builder previewRequest = 3863ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin mCamera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW); 3873ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin CaptureRequest.Builder recordingRequest = 3883ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin mCamera.createCaptureRequest(CameraDevice.TEMPLATE_RECORD); 3893ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin 3903ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin SimpleCaptureCallback resultListener = new SimpleCaptureCallback(); 3913ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin SimpleImageReaderListener imageListener = new SimpleImageReaderListener(); 3923ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin 3933ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin prepareVideoPreview(previewRequest, recordingRequest, resultListener, imageListener); 3943ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin 3953ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin // Can reuse the MediaRecorder object after reset. 3963ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin mMediaRecorder.reset(); 3973ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin 3983ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin if (maxVideoFrameRate != -1) { 3993ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin // At least one CamcorderProfile is present, check FPS 4003ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin assertTrue("At least one CamcorderProfile must support >= 24 FPS", 4013ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin maxVideoFrameRate >= 24); 4023ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin } 4033ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin } 4043ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin 4053ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin private void releaseRecorder() { 4063ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin if (mMediaRecorder != null) { 4073ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin mMediaRecorder.release(); 4083ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin mMediaRecorder = null; 4093ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin } 4103ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin } 4113ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin 4123ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin private List<String> cameraColorOutputCheck() throws Exception { 4133ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin List<String> mCameraColorOutputIds = new ArrayList<String>(); 4143ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin for (String id : mCameraIds) { 4153ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin openDevice(id); 4163ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin if (!mStaticInfo.isColorOutputSupported()) { 4173ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin Log.i(TAG, "Camera " + id + 4183ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin " does not support color outputs, skipping"); 4193ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin continue; 4203ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin } 4213ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin mCameraColorOutputIds.add(id); 4223ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin closeDevice(); 4233ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin } 4243ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin return mCameraColorOutputIds; 4253ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin } 4263ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin 4273ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin /** 4283ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin * Returns {@code true} if the {@link CamcorderProfile} ID is allowed to be unsupported. 4293ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin * 4303ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin * <p>This only allows unsupported profiles when using the LEGACY mode of the Camera API.</p> 4313ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin * 4323ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin * @param profileId a {@link CamcorderProfile} ID to check. 4333ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin * @return {@code true} if supported. 4343ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin */ 4353ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin private boolean allowedUnsupported(int cameraId, int profileId) { 4363ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin if (!mStaticInfo.isHardwareLevelLegacy()) { 4373ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin return false; 4383ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin } 4393ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin 4403ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin switch(profileId) { 4413ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin case CamcorderProfile.QUALITY_2160P: 4423ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin case CamcorderProfile.QUALITY_1080P: 4433ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin case CamcorderProfile.QUALITY_HIGH: 4443ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin return !CamcorderProfile.hasProfile(cameraId, profileId) || 4453ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin CamcorderProfile.get(cameraId, profileId).videoFrameWidth >= 1080; 4463ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin } 4473ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin return false; 4483ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin } 4493ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin 4503ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin /** 4513ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin * Configure MediaRecorder recording session with CamcorderProfile, prepare 4523ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin * the recording surface. 4533ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin */ 4543ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin private void prepareRecordingWithProfile(CamcorderProfile profile) 4553ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin throws Exception { 4563ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin // Prepare MediaRecorder. 4573ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.CAMCORDER); 4583ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE); 4593ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin mMediaRecorder.setProfile(profile); 4603ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin mMediaRecorder.setOutputFile(mOutMediaFileName); 4613ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin if (mPersistentSurface != null) { 4623ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin mMediaRecorder.setInputSurface(mPersistentSurface); 4633ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin mRecordingSurface = mPersistentSurface; 4643ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin } 4653ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin mMediaRecorder.prepare(); 4663ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin if (mPersistentSurface == null) { 4673ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin mRecordingSurface = mMediaRecorder.getSurface(); 4683ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin } 4693ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin assertNotNull("Recording surface must be non-null!", mRecordingSurface); 4703ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin mVideoFrameRate = profile.videoFrameRate; 4713ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin mVideoSize = new Size(profile.videoFrameWidth, profile.videoFrameHeight); 4723ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin } 4733ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin 4743ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin /** 4753ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin * Update preview size with video size. 4763ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin * 4773ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin * <p>Preview size will be capped with max preview size.</p> 4783ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin * 4793ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin * @param videoSize The video size used for preview. 4803ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin * @param videoFrameRate The video frame rate 4813ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin * 4823ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin */ 4833ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin private void updatePreviewSurfaceWithVideo(Size videoSize, int videoFrameRate) throws Exception { 4843ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin if (mOrderedPreviewSizes == null) { 4853ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin throw new IllegalStateException("supported preview size list is not initialized yet"); 4863ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin } 4873ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin final float FRAME_DURATION_TOLERANCE = 0.01f; 4883ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin long videoFrameDuration = (long) (1e9 / videoFrameRate * 4893ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin (1.0 + FRAME_DURATION_TOLERANCE)); 4903ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin HashMap<Size, Long> minFrameDurationMap = mStaticInfo. 4913ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin getAvailableMinFrameDurationsForFormatChecked(ImageFormat.PRIVATE); 4923ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin Size maxPreviewSize = mOrderedPreviewSizes.get(0); 4933ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin Size previewSize = null; 4943ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin if (videoSize.getWidth() > maxPreviewSize.getWidth() || 4953ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin videoSize.getHeight() > maxPreviewSize.getHeight()) { 4963ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin for (Size s : mOrderedPreviewSizes) { 4973ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin Long frameDuration = minFrameDurationMap.get(s); 4983ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin if (mStaticInfo.isHardwareLevelLegacy()) { 4993ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin // Legacy doesn't report min frame duration 5003ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin frameDuration = new Long(0); 5013ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin } 5023ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin assertTrue("Cannot find minimum frame duration for private size" + s, 5033ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin frameDuration != null); 5043ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin if (frameDuration <= videoFrameDuration && 5053ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin s.getWidth() <= videoSize.getWidth() && 5063ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin s.getHeight() <= videoSize.getHeight()) { 5073ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin Log.w(TAG, "Overwrite preview size from " + videoSize.toString() + 5083ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin " to " + s.toString()); 5093ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin previewSize = s; 5103ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin break; 5113ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin // If all preview size doesn't work then we fallback to video size 5123ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin } 5133ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin } 5143ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin } 5153ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin if (previewSize == null) { 5163ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin previewSize = videoSize; 5173ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin } 5183ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin 5193ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin updatePreviewSurface(previewSize); 5203ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin } 5213ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin 5223ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin protected void prepareVideoPreview(CaptureRequest.Builder previewRequest, 5233ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin CaptureRequest.Builder recordingRequest, 5243ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin CaptureCallback resultListener, 5253ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin ImageReader.OnImageAvailableListener imageListener) throws Exception { 5263ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin 5273ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin // Configure output streams with preview and jpeg streams. 5283ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin List<Surface> outputSurfaces = new ArrayList<Surface>(); 5293ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin outputSurfaces.add(mPreviewSurface); 5303ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin outputSurfaces.add(mRecordingSurface); 5313ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin 5323ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin mSessionListener = new BlockingSessionCallback(); 5333ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin mSession = configureCameraSession(mCamera, outputSurfaces, mSessionListener, mHandler); 5343ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin 5353ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin previewRequest.addTarget(mPreviewSurface); 5363ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin recordingRequest.addTarget(mPreviewSurface); 5373ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin recordingRequest.addTarget(mRecordingSurface); 5383ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin 5393ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin // Start preview. 5403ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin mSession.setRepeatingRequest(previewRequest.build(), null, mHandler); 5413ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin } 5423ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin 5433ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin protected void prepareCapturePreview(CaptureRequest.Builder previewRequest, 5443ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin CaptureRequest.Builder stillRequest, 5453ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin CaptureCallback resultListener, 5463ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin ImageReader.OnImageAvailableListener imageListener) throws Exception { 5473ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin 5483ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin Size captureSz = mOrderedStillSizes.get(0); 5493ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin Size previewSz = mOrderedPreviewSizes.get(1); 5503ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin 5513ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin if (VERBOSE) { 5523ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin Log.v(TAG, String.format("Prepare single capture (%s) and preview (%s)", 5533ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin captureSz.toString(), previewSz.toString())); 5543ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin } 5553ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin 5563ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin // Update preview size. 5573ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin updatePreviewSurface(previewSz); 5583ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin 5593ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin // Create ImageReader. 5603ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin createImageReader(captureSz, ImageFormat.JPEG, MAX_READER_IMAGES, imageListener); 5613ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin 5623ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin // Configure output streams with preview and jpeg streams. 5633ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin List<Surface> outputSurfaces = new ArrayList<Surface>(); 5643ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin outputSurfaces.add(mPreviewSurface); 5653ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin outputSurfaces.add(mReaderSurface); 5663ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin mSessionListener = new BlockingSessionCallback(); 5673ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin mSession = configureCameraSession(mCamera, outputSurfaces, mSessionListener, mHandler); 5683ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin 5693ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin // Configure the requests. 5703ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin previewRequest.addTarget(mPreviewSurface); 5713ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin stillRequest.addTarget(mPreviewSurface); 5723ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin stillRequest.addTarget(mReaderSurface); 5733ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin 5743ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin // Start preview. 5753ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin mSession.setRepeatingRequest(previewRequest.build(), resultListener, mHandler); 5763ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin } 5773ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin 5783ed27cc2b27a336590be6bd95e0ee4a75b25be70Hang Yin} 579