1 /* 2 * Copyright (C) 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 com.android.camera.one.v2; 18 19 import android.annotation.TargetApi; 20 import android.graphics.ImageFormat; 21 import android.hardware.camera2.CameraDevice; 22 import android.hardware.camera2.CaptureRequest; 23 import android.os.Build; 24 import android.view.Surface; 25 26 import com.android.camera.FatalErrorHandler; 27 import com.android.camera.async.HandlerFactory; 28 import com.android.camera.async.Lifetime; 29 import com.android.camera.async.MainThread; 30 import com.android.camera.async.Observable; 31 import com.android.camera.async.Observables; 32 import com.android.camera.async.Updatable; 33 import com.android.camera.burst.BurstFacade; 34 import com.android.camera.debug.Loggers; 35 import com.android.camera.one.OneCamera; 36 import com.android.camera.one.OneCameraCharacteristics; 37 import com.android.camera.one.config.OneCameraFeatureConfig; 38 import com.android.camera.one.v2.camera2proxy.AndroidImageReaderProxy; 39 import com.android.camera.one.v2.camera2proxy.CameraCaptureSessionProxy; 40 import com.android.camera.one.v2.camera2proxy.CameraDeviceProxy; 41 import com.android.camera.one.v2.camera2proxy.CameraDeviceRequestBuilderFactory; 42 import com.android.camera.one.v2.camera2proxy.ImageReaderProxy; 43 import com.android.camera.one.v2.camera2proxy.TotalCaptureResultProxy; 44 import com.android.camera.one.v2.commands.CameraCommandExecutor; 45 import com.android.camera.one.v2.commands.BasicPreviewCommandFactory; 46 import com.android.camera.one.v2.common.BasicCameraFactory; 47 import com.android.camera.one.v2.common.SimpleCaptureStream; 48 import com.android.camera.one.v2.core.FrameServer; 49 import com.android.camera.one.v2.core.FrameServerFactory; 50 import com.android.camera.one.v2.core.RequestBuilder; 51 import com.android.camera.one.v2.core.RequestTemplate; 52 import com.android.camera.one.v2.core.ResponseListeners; 53 import com.android.camera.one.v2.errorhandling.FramerateJankDetector; 54 import com.android.camera.one.v2.imagesaver.ImageSaver; 55 import com.android.camera.one.v2.initialization.CameraStarter; 56 import com.android.camera.one.v2.initialization.InitializedOneCameraFactory; 57 import com.android.camera.one.v2.photo.ImageRotationCalculator; 58 import com.android.camera.one.v2.photo.LegacyPictureTakerFactory; 59 import com.android.camera.one.v2.photo.PictureTaker; 60 import com.android.camera.one.v2.photo.PictureTakerFactory; 61 import com.android.camera.one.v2.sharedimagereader.ManagedImageReader; 62 import com.android.camera.one.v2.sharedimagereader.SharedImageReaderFactory; 63 import com.android.camera.stats.UsageStatistics; 64 import com.android.camera.util.AndroidContext; 65 import com.android.camera.util.GservicesHelper; 66 import com.android.camera.util.Provider; 67 import com.android.camera.util.Size; 68 import com.google.common.base.Supplier; 69 70 import java.util.ArrayList; 71 import java.util.Arrays; 72 import java.util.List; 73 import java.util.concurrent.ExecutorService; 74 import java.util.concurrent.Executors; 75 76 /** 77 * Creates a camera which takes jpeg images using the hardware encoder with 78 * baseline functionality. 79 */ 80 @TargetApi(Build.VERSION_CODES.LOLLIPOP) 81 public class SimpleOneCameraFactory implements OneCameraFactory { 82 private final int mImageFormat; 83 private final int mMaxImageCount; 84 private final ImageRotationCalculator mImageRotationCalculator; 85 86 /** 87 * @param imageFormat The {@link ImageFormat} to use for full-size images to 88 * be saved. 89 * @param maxImageCount The size of the image reader to use for full-size 90 * images. 91 */ SimpleOneCameraFactory(int imageFormat, int maxImageCount, ImageRotationCalculator imageRotationCalculator)92 public SimpleOneCameraFactory(int imageFormat, int maxImageCount, 93 ImageRotationCalculator imageRotationCalculator) { 94 mImageFormat = imageFormat; 95 mMaxImageCount = maxImageCount; 96 mImageRotationCalculator = imageRotationCalculator; 97 } 98 99 @Override createOneCamera(final CameraDeviceProxy device, final OneCameraCharacteristics characteristics, final OneCameraFeatureConfig.CaptureSupportLevel supportLevel, final MainThread mainExecutor, final Size pictureSize, final ImageSaver.Builder imageSaverBuilder, final Observable<OneCamera.PhotoCaptureParameters.Flash> flashSetting, final Observable<Integer> exposureSetting, final Observable<Boolean> hdrSceneSetting, final BurstFacade burstFacade, final FatalErrorHandler fatalErrorHandler)100 public OneCamera createOneCamera(final CameraDeviceProxy device, 101 final OneCameraCharacteristics characteristics, 102 final OneCameraFeatureConfig.CaptureSupportLevel supportLevel, 103 final MainThread mainExecutor, 104 final Size pictureSize, 105 final ImageSaver.Builder imageSaverBuilder, 106 final Observable<OneCamera.PhotoCaptureParameters.Flash> flashSetting, 107 final Observable<Integer> exposureSetting, 108 final Observable<Boolean> hdrSceneSetting, 109 final BurstFacade burstFacade, 110 final FatalErrorHandler fatalErrorHandler) { 111 final Lifetime lifetime = new Lifetime(); 112 113 final ImageReaderProxy imageReader = new CloseWhenDoneImageReader(new LoggingImageReader( 114 AndroidImageReaderProxy.newInstance( 115 pictureSize.getWidth(), pictureSize.getHeight(), 116 mImageFormat, mMaxImageCount), 117 Loggers.tagFactory())); 118 119 lifetime.add(imageReader); 120 lifetime.add(device); 121 122 List<Surface> outputSurfaces = new ArrayList<>(); 123 outputSurfaces.add(imageReader.getSurface()); 124 125 /** 126 * Finishes constructing the camera when prerequisites, e.g. the preview 127 * stream and capture session, are ready. 128 */ 129 CameraStarter cameraStarter = new CameraStarter() { 130 @Override 131 public CameraStarter.CameraControls startCamera(Lifetime cameraLifetime, 132 CameraCaptureSessionProxy cameraCaptureSession, 133 Surface previewSurface, 134 Observable<Float> zoomState, 135 Updatable<TotalCaptureResultProxy> metadataCallback, 136 Updatable<Boolean> readyState) { 137 // Create the FrameServer from the CaptureSession. 138 FrameServerFactory frameServerComponent = new FrameServerFactory( 139 new Lifetime(cameraLifetime), cameraCaptureSession, new HandlerFactory()); 140 141 CameraCommandExecutor cameraCommandExecutor = new CameraCommandExecutor( 142 Loggers.tagFactory(), 143 new Provider<ExecutorService>() { 144 @Override 145 public ExecutorService get() { 146 // Use a dynamically-expanding thread pool to 147 // allow any number of commands to execute 148 // simultaneously. 149 return Executors.newCachedThreadPool(); 150 } 151 }); 152 153 // Create the shared image reader. 154 SharedImageReaderFactory sharedImageReaderFactory = 155 new SharedImageReaderFactory(new Lifetime(cameraLifetime), imageReader, 156 new HandlerFactory()); 157 Updatable<Long> globalTimestampCallback = 158 sharedImageReaderFactory.provideGlobalTimestampQueue(); 159 ManagedImageReader managedImageReader = 160 sharedImageReaderFactory.provideSharedImageReader(); 161 162 // Create the request builder used by all camera operations. 163 // Streams, ResponseListeners, and Parameters added to 164 // this will be applied to *all* requests sent to the camera. 165 RequestTemplate rootBuilder = new RequestTemplate 166 (new CameraDeviceRequestBuilderFactory(device)); 167 // The shared image reader must be wired to receive every 168 // timestamp for every image (including the preview). 169 rootBuilder.addResponseListener( 170 ResponseListeners.forTimestamps(globalTimestampCallback)); 171 rootBuilder.addStream(new SimpleCaptureStream(previewSurface)); 172 rootBuilder.addResponseListener(ResponseListeners.forFinalMetadata( 173 metadataCallback)); 174 175 FrameServer ephemeralFrameServer = 176 frameServerComponent.provideEphemeralFrameServer(); 177 178 // Create basic functionality (zoom, AE, AF). 179 BasicCameraFactory basicCameraFactory = new BasicCameraFactory(new Lifetime 180 (cameraLifetime), 181 characteristics, 182 ephemeralFrameServer, 183 rootBuilder, 184 cameraCommandExecutor, 185 new BasicPreviewCommandFactory(ephemeralFrameServer), 186 flashSetting, 187 exposureSetting, 188 zoomState, 189 hdrSceneSetting, 190 CameraDevice.TEMPLATE_PREVIEW); 191 192 // Register the dynamic updater via orientation supplier 193 rootBuilder.setParam(CaptureRequest.JPEG_ORIENTATION, 194 mImageRotationCalculator.getSupplier()); 195 196 if (GservicesHelper.isJankStatisticsEnabled(AndroidContext.instance().get() 197 .getContentResolver())) { 198 rootBuilder.addResponseListener( 199 new FramerateJankDetector(Loggers.tagFactory(), 200 UsageStatistics.instance())); 201 } 202 203 RequestBuilder.Factory meteredZoomedRequestBuilder = 204 basicCameraFactory.provideMeteredZoomedRequestBuilder(); 205 206 // Create the picture-taker. 207 PictureTaker pictureTaker; 208 if (supportLevel == OneCameraFeatureConfig.CaptureSupportLevel.LEGACY_JPEG) { 209 pictureTaker = new LegacyPictureTakerFactory(imageSaverBuilder, 210 cameraCommandExecutor, mainExecutor, 211 frameServerComponent.provideFrameServer(), 212 meteredZoomedRequestBuilder, managedImageReader).providePictureTaker(); 213 } else { 214 pictureTaker = PictureTakerFactory.create(Loggers.tagFactory(), mainExecutor, 215 cameraCommandExecutor, imageSaverBuilder, 216 frameServerComponent.provideFrameServer(), 217 meteredZoomedRequestBuilder, managedImageReader, flashSetting) 218 .providePictureTaker(); 219 } 220 221 // Wire-together ready-state. 222 final Observable<Integer> availableImageCount = sharedImageReaderFactory 223 .provideAvailableImageCount(); 224 final Observable<Boolean> frameServerAvailability = frameServerComponent 225 .provideReadyState(); 226 Observable<Boolean> ready = Observables.transform( 227 Arrays.asList(availableImageCount, frameServerAvailability), 228 new Supplier<Boolean>() { 229 @Override 230 public Boolean get() { 231 boolean atLeastOneImageAvailable = availableImageCount.get() >= 1; 232 boolean frameServerAvailable = frameServerAvailability.get(); 233 return atLeastOneImageAvailable && frameServerAvailable; 234 } 235 }); 236 237 lifetime.add(Observables.addThreadSafeCallback(ready, readyState)); 238 239 basicCameraFactory.providePreviewUpdater().run(); 240 241 return new CameraStarter.CameraControls( 242 pictureTaker, 243 basicCameraFactory.provideManualAutoFocus()); 244 } 245 }; 246 247 float maxZoom = characteristics.getAvailableMaxDigitalZoom(); 248 List<Size> supportedPreviewSizes = characteristics.getSupportedPreviewSizes(); 249 OneCamera.Facing direction = characteristics.getCameraDirection(); 250 251 return new InitializedOneCameraFactory(lifetime, cameraStarter, device, outputSurfaces, 252 mainExecutor, new HandlerFactory(), maxZoom, supportedPreviewSizes, 253 characteristics.getLensFocusRange(), direction) 254 .provideOneCamera(); 255 } 256 } 257