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.hardware.camera2.CameraDevice; 21 import android.hardware.camera2.CaptureRequest; 22 import android.os.Build.VERSION_CODES; 23 import android.util.Range; 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.burst.BurstTaker; 35 import com.android.camera.burst.BurstTakerImpl; 36 import com.android.camera.debug.Log.Tag; 37 import com.android.camera.debug.Logger; 38 import com.android.camera.debug.Loggers; 39 import com.android.camera.one.OneCamera; 40 import com.android.camera.one.OneCameraCharacteristics; 41 import com.android.camera.one.config.OneCameraFeatureConfig.CaptureSupportLevel; 42 import com.android.camera.one.v2.camera2proxy.AndroidImageReaderProxy; 43 import com.android.camera.one.v2.camera2proxy.CameraCaptureSessionProxy; 44 import com.android.camera.one.v2.camera2proxy.CameraDeviceProxy; 45 import com.android.camera.one.v2.camera2proxy.CameraDeviceRequestBuilderFactory; 46 import com.android.camera.one.v2.camera2proxy.ImageReaderProxy; 47 import com.android.camera.one.v2.camera2proxy.TotalCaptureResultProxy; 48 import com.android.camera.one.v2.commands.CameraCommandExecutor; 49 import com.android.camera.one.v2.commands.ZslPreviewCommandFactory; 50 import com.android.camera.one.v2.common.BasicCameraFactory; 51 import com.android.camera.one.v2.common.SimpleCaptureStream; 52 import com.android.camera.one.v2.core.FrameServer; 53 import com.android.camera.one.v2.core.FrameServerFactory; 54 import com.android.camera.one.v2.core.RequestTemplate; 55 import com.android.camera.one.v2.core.ResponseListener; 56 import com.android.camera.one.v2.core.ResponseListeners; 57 import com.android.camera.one.v2.errorhandling.FramerateJankDetector; 58 import com.android.camera.one.v2.errorhandling.RepeatFailureHandlerComponent; 59 import com.android.camera.one.v2.imagesaver.ImageSaver; 60 import com.android.camera.one.v2.initialization.CameraStarter; 61 import com.android.camera.one.v2.initialization.InitializedOneCameraFactory; 62 import com.android.camera.one.v2.photo.ZslPictureTakerFactory; 63 import com.android.camera.one.v2.sharedimagereader.ZslSharedImageReaderFactory; 64 import com.android.camera.stats.UsageStatistics; 65 import com.android.camera.util.AndroidContext; 66 import com.android.camera.util.ApiHelper; 67 import com.android.camera.util.GservicesHelper; 68 import com.android.camera.util.Provider; 69 import com.android.camera.util.Size; 70 import com.google.common.base.Supplier; 71 72 import java.util.ArrayList; 73 import java.util.Arrays; 74 import java.util.List; 75 import java.util.concurrent.ExecutorService; 76 import java.util.concurrent.Executors; 77 78 @TargetApi(VERSION_CODES.LOLLIPOP) 79 public class ZslOneCameraFactory implements OneCameraFactory { 80 private static Tag TAG = new Tag("ZslOneCamFactory"); 81 82 private final Logger mLogger; 83 private final int mImageFormat; 84 private final int mMaxImageCount; 85 private final int maxRingBufferSize; 86 ZslOneCameraFactory(int imageFormat, int maxImageCount)87 public ZslOneCameraFactory(int imageFormat, int maxImageCount) { 88 mImageFormat = imageFormat; 89 mMaxImageCount = maxImageCount; 90 mLogger = Loggers.tagFactory().create(TAG); 91 92 // Determines the maximum size of the ZSL ring-buffer. 93 // Note that this is *different* from mMaxImageCount. 94 // mMaxImageCount determines the size of the ImageReader used for large 95 // (typically YUV) images to be saved. It is correlated with the total 96 // number of in-progress captures which can simultaneously occur by 97 // buffering captured images. 98 // maxRingBufferSize determines the maximum size of the ring-buffer 99 // (which uses a subset of the capacity of the ImageReader). This is 100 // correlated to the maximum amount of look-back for zero-shutter-lag 101 // photography. If this is greater than mMaxImageCount - 2, then it 102 // places no additional constraints on ring-buffer size. That is, 103 // the ring-buffer will expand to fill the entire capacity of the 104 // ImageReader whenever possible. 105 106 // A value of 1 here is adequate for single-frame ZSL capture, but 107 // *must* be increased to support multi-frame burst capture with 108 // zero-shutter-lag. 109 maxRingBufferSize = 1; 110 } 111 112 /** 113 * Slows down the requested camera frame for Nexus 5 back camera issue. This 114 * hack is for the Back Camera for Nexus 5. Requesting on full YUV frames at 115 * 30 fps causes the video preview to deliver frames out of order, mostly 116 * likely due to the overloading of the ISP, and/or image bandwith. The 117 * short-term solution is to back off the frame rate to unadvertised, valid 118 * frame rate of 28 fps. The long-term solution is to advertise this [7,28] 119 * frame rate range in the HAL and get buy-in from the manufacturer to 120 * support and CTS this feature. Then framerate process can occur in more 121 * integrated manner. The tracking bug for this issue is b/18950682. 122 * 123 * @param requestTemplate Request template that will be applied to the 124 * current camera device 125 */ applyNexus5BackCameraFrameRateWorkaround(RequestTemplate requestTemplate)126 private void applyNexus5BackCameraFrameRateWorkaround(RequestTemplate requestTemplate) { 127 Range<Integer> frameRateBackOff = new Range<>(7, 28); 128 mLogger.v("Applying Nexus5 specific framerate backoff of " + frameRateBackOff); 129 requestTemplate.setParam(CaptureRequest.CONTROL_AE_TARGET_FPS_RANGE, frameRateBackOff); 130 } 131 132 @Override createOneCamera(final CameraDeviceProxy device, final OneCameraCharacteristics characteristics, CaptureSupportLevel featureConfig, final MainThread mainThread, 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)133 public OneCamera createOneCamera(final CameraDeviceProxy device, 134 final OneCameraCharacteristics characteristics, 135 CaptureSupportLevel featureConfig, 136 final MainThread mainThread, 137 Size pictureSize, 138 final ImageSaver.Builder imageSaverBuilder, 139 final Observable<OneCamera.PhotoCaptureParameters.Flash> flashSetting, 140 final Observable<Integer> exposureSetting, 141 final Observable<Boolean> hdrSceneSetting, 142 final BurstFacade burstFacade, 143 final FatalErrorHandler fatalErrorHandler) { 144 final Lifetime lifetime = new Lifetime(); 145 146 final ImageReaderProxy imageReader = new CloseWhenDoneImageReader( 147 new LoggingImageReader(AndroidImageReaderProxy.newInstance( 148 pictureSize.getWidth(), pictureSize.getHeight(), 149 mImageFormat, mMaxImageCount), Loggers.tagFactory())); 150 151 lifetime.add(imageReader); 152 lifetime.add(device); 153 154 List<Surface> outputSurfaces = new ArrayList<>(); 155 outputSurfaces.add(imageReader.getSurface()); 156 if (burstFacade.getInputSurface() != null) { 157 outputSurfaces.add(burstFacade.getInputSurface()); 158 } 159 160 /** 161 * Finishes constructing the camera when prerequisites, e.g. the preview 162 * stream and capture session, are ready. 163 */ 164 CameraStarter cameraStarter = new CameraStarter() { 165 @Override 166 public CameraControls startCamera(Lifetime cameraLifetime, 167 CameraCaptureSessionProxy cameraCaptureSession, 168 Surface previewSurface, 169 Observable<Float> zoomState, 170 Updatable<TotalCaptureResultProxy> metadataCallback, 171 Updatable<Boolean> readyStateCallback) { 172 // Create the FrameServer from the CaptureSession. 173 FrameServerFactory frameServerComponent = new FrameServerFactory(new Lifetime 174 (cameraLifetime), cameraCaptureSession, new HandlerFactory()); 175 176 FrameServer frameServer = frameServerComponent.provideFrameServer(); 177 FrameServer ephemeralFrameServer = frameServerComponent 178 .provideEphemeralFrameServer(); 179 180 // Create the shared image reader. 181 ZslSharedImageReaderFactory sharedImageReaderFactory = 182 new ZslSharedImageReaderFactory(new Lifetime(cameraLifetime), 183 imageReader, new HandlerFactory(), maxRingBufferSize); 184 185 CameraCommandExecutor cameraCommandExecutor = new CameraCommandExecutor( 186 Loggers.tagFactory(), 187 new Provider<ExecutorService>() { 188 @Override 189 public ExecutorService get() { 190 // Use a dynamically-expanding thread pool to 191 // allow any number of commands to execute 192 // simultaneously. 193 return Executors.newCachedThreadPool(); 194 } 195 }); 196 197 // Create the request builder used by all camera operations. 198 // Streams, ResponseListeners, and Parameters added to 199 // this will be applied to *all* requests sent to the camera. 200 RequestTemplate rootTemplate = new RequestTemplate( 201 new CameraDeviceRequestBuilderFactory(device)); 202 rootTemplate.addResponseListener(sharedImageReaderFactory 203 .provideGlobalResponseListener()); 204 rootTemplate.addResponseListener(ResponseListeners 205 .forFinalMetadata(metadataCallback)); 206 207 // Create the request builder for the preview warmup in order to workaround 208 // the face detection failure. This is a work around of the HAL face detection 209 // failure in b/20724126. 210 RequestTemplate previewWarmupTemplate = new RequestTemplate(rootTemplate); 211 previewWarmupTemplate.addStream(new SimpleCaptureStream(previewSurface)); 212 213 // Create the request builder for the ZSL stream 214 RequestTemplate zslTemplate = new RequestTemplate(rootTemplate); 215 zslTemplate.addStream(sharedImageReaderFactory.provideZSLStream()); 216 217 // Create the request builder that will be used by most camera 218 // operations. 219 RequestTemplate zslAndPreviewTemplate = new RequestTemplate(zslTemplate); 220 zslAndPreviewTemplate.addStream(new SimpleCaptureStream(previewSurface)); 221 222 boolean isBackCamera = characteristics.getCameraDirection() == 223 OneCamera.Facing.BACK; 224 225 if (isBackCamera && ApiHelper.IS_NEXUS_5) { 226 applyNexus5BackCameraFrameRateWorkaround(zslTemplate); 227 } 228 229 // Create basic functionality (zoom, AE, AF). 230 BasicCameraFactory basicCameraFactory = new BasicCameraFactory( 231 new Lifetime(cameraLifetime), 232 characteristics, 233 ephemeralFrameServer, 234 zslAndPreviewTemplate, 235 cameraCommandExecutor, 236 new ZslPreviewCommandFactory(ephemeralFrameServer, 237 previewWarmupTemplate, 238 zslTemplate), 239 flashSetting, 240 exposureSetting, 241 zoomState, 242 hdrSceneSetting, 243 CameraDevice.TEMPLATE_ZERO_SHUTTER_LAG); 244 245 lifetime.add(cameraCommandExecutor); 246 247 // Create the picture-taker. 248 ZslPictureTakerFactory pictureTakerFactory = ZslPictureTakerFactory.create( 249 Loggers.tagFactory(), 250 mainThread, 251 cameraCommandExecutor, 252 imageSaverBuilder, 253 frameServer, 254 basicCameraFactory.provideMeteredZoomedRequestBuilder(), 255 sharedImageReaderFactory.provideSharedImageReader(), 256 sharedImageReaderFactory.provideZSLStream(), 257 sharedImageReaderFactory.provideMetadataPool(), 258 flashSetting, 259 zslAndPreviewTemplate); 260 261 BurstTaker burstTaker = new BurstTakerImpl(cameraCommandExecutor, 262 frameServer, 263 basicCameraFactory.provideMeteredZoomedRequestBuilder(), 264 sharedImageReaderFactory.provideSharedImageReader(), 265 burstFacade.getInputSurface(), 266 basicCameraFactory.providePreviewUpdater(), 267 // ImageReader#acquireLatestImage() requires two images 268 // as the margin so 269 // specify that as the maximum number of images that can 270 // be used by burst. 271 mMaxImageCount - 2); 272 burstFacade.setBurstTaker(burstTaker); 273 274 if (isBackCamera && ApiHelper.IS_NEXUS_5) { 275 // Workaround for bug: 19061883 276 ResponseListener failureDetector = RepeatFailureHandlerComponent.create( 277 Loggers.tagFactory(), 278 fatalErrorHandler, 279 cameraCaptureSession, 280 cameraCommandExecutor, 281 basicCameraFactory.providePreviewUpdater(), 282 UsageStatistics.instance(), 283 10 /* consecutiveFailureThreshold */).provideResponseListener(); 284 zslTemplate.addResponseListener(failureDetector); 285 } 286 287 if (GservicesHelper.isJankStatisticsEnabled(AndroidContext.instance().get() 288 .getContentResolver())) { 289 // Don't add jank detection unless the preview is running. 290 zslAndPreviewTemplate.addResponseListener( 291 new FramerateJankDetector(Loggers.tagFactory(), 292 UsageStatistics.instance())); 293 } 294 295 final Observable<Integer> availableImageCount = sharedImageReaderFactory 296 .provideAvailableImageCount(); 297 final Observable<Boolean> frameServerAvailability = frameServerComponent 298 .provideReadyState(); 299 Observable<Boolean> readyObservable = Observables.transform( 300 Arrays.asList(availableImageCount, frameServerAvailability), 301 new Supplier<Boolean>() { 302 @Override 303 public Boolean get() { 304 boolean atLeastOneImageAvailable = availableImageCount.get() >= 1; 305 boolean frameServerAvailable = frameServerAvailability.get(); 306 return atLeastOneImageAvailable && frameServerAvailable; 307 } 308 }); 309 310 lifetime.add(Observables.addThreadSafeCallback(readyObservable, 311 readyStateCallback)); 312 313 basicCameraFactory.providePreviewUpdater().run(); 314 315 return new CameraControls( 316 pictureTakerFactory.providePictureTaker(), 317 basicCameraFactory.provideManualAutoFocus()); 318 } 319 }; 320 321 float maxZoom = characteristics.getAvailableMaxDigitalZoom(); 322 List<Size> supportedPreviewSizes = characteristics.getSupportedPreviewSizes(); 323 OneCamera.Facing direction = characteristics.getCameraDirection(); 324 return new InitializedOneCameraFactory(lifetime, cameraStarter, device, 325 outputSurfaces, mainThread, new HandlerFactory(), maxZoom, 326 supportedPreviewSizes, characteristics.getLensFocusRange(), 327 direction).provideOneCamera(); 328 } 329 } 330