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 */ 92 public SimpleOneCameraFactory(int imageFormat, int maxImageCount, 93 ImageRotationCalculator imageRotationCalculator) { 94 mImageFormat = imageFormat; 95 mMaxImageCount = maxImageCount; 96 mImageRotationCalculator = imageRotationCalculator; 97 } 98 99 @Override 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