Home | History | Annotate | Download | only in v2
      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 
     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      */
    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
    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