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