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.sharedimagereader;
18 
19 import static com.android.camera.one.v2.core.ResponseListeners.forFinalMetadata;
20 import static com.android.camera.one.v2.core.ResponseListeners.forTimestamps;
21 
22 import com.android.camera.async.HandlerFactory;
23 import com.android.camera.async.Lifetime;
24 import com.android.camera.async.Observable;
25 import com.android.camera.async.Observables;
26 import com.android.camera.async.Updatable;
27 import com.android.camera.one.v2.camera2proxy.ImageReaderProxy;
28 import com.android.camera.one.v2.core.ResponseListener;
29 import com.android.camera.one.v2.core.ResponseListeners;
30 import com.android.camera.one.v2.sharedimagereader.imagedistributor.ImageDistributor;
31 import com.android.camera.one.v2.sharedimagereader.imagedistributor.ImageDistributorFactory;
32 import com.android.camera.one.v2.sharedimagereader.imagedistributor.ImageStream;
33 import com.android.camera.one.v2.sharedimagereader.metadatasynchronizer.MetadataPool;
34 import com.android.camera.one.v2.sharedimagereader.metadatasynchronizer.MetadataPoolFactory;
35 import com.android.camera.one.v2.sharedimagereader.ringbuffer.DynamicRingBufferFactory;
36 import com.android.camera.one.v2.sharedimagereader.ticketpool.FiniteTicketPool;
37 import com.android.camera.one.v2.sharedimagereader.ticketpool.TicketPool;
38 
39 /**
40  * Like {@link SharedImageReaderFactory}, but provides a single
41  * {@link ImageStream} with a dynamic capacity which changes depending on demand
42  * from the {@link ManagedImageReader}.
43  */
44 public class ZslSharedImageReaderFactory {
45     private final ManagedImageReader mSharedImageReader;
46     private final ImageStream mZslCaptureStream;
47     private final MetadataPool mMetadataPool;
48     private final Observable<Integer> mAvailableImageCount;
49     private final ResponseListener mResponseListener;
50 
51     /**
52      * @param lifetime The lifetime of the SharedImageReader, and other
53      *            components, to produce. Note that this may be shorter than the
54      *            lifetime of the provided ImageReader.
55      * @param imageReader The ImageReader to wrap. Note that this can outlive
56      *            the resulting SharedImageReader instance.
57      * @param handlerFactory Used for create handler threads on which to receive
58      *            callbacks from the platform.
59      * @param maxRingBufferSize Limits the size of the ring-buffer. This reduces
60      *            steady-state memory consumption since ImageReader images are
61      *            allocated on-demand, so no more than maxRingBufferSize + 2
62      *            images are guaranteed to have to be allocated, as opposed to
63      *            imageReader.getMaxImages().
64      */
ZslSharedImageReaderFactory(Lifetime lifetime, ImageReaderProxy imageReader, HandlerFactory handlerFactory, int maxRingBufferSize)65     public ZslSharedImageReaderFactory(Lifetime lifetime, ImageReaderProxy imageReader,
66             HandlerFactory handlerFactory, int maxRingBufferSize) {
67         ImageDistributorFactory imageDistributorFactory = new ImageDistributorFactory(lifetime,
68                 imageReader, handlerFactory);
69         ImageDistributor imageDistributor = imageDistributorFactory.provideImageDistributor();
70         Updatable<Long> globalTimestampQueue = imageDistributorFactory
71                 .provideGlobalTimestampCallback();
72 
73         // TODO Try using 1 instead.
74         // Leave 2 ImageReader Images available to allow ImageDistributor and
75         // the camera system to have some slack to work with.
76         TicketPool rootTicketPool = new FiniteTicketPool(imageReader.getMaxImages() - 2);
77 
78         DynamicRingBufferFactory ringBufferFactory = new DynamicRingBufferFactory(
79                 new Lifetime(lifetime), rootTicketPool, Observables.of(maxRingBufferSize));
80 
81         MetadataPoolFactory metadataPoolFactory = new MetadataPoolFactory(
82                 ringBufferFactory.provideRingBufferInput());
83 
84         mZslCaptureStream = new ImageStreamImpl(
85                 ringBufferFactory.provideRingBufferOutput(),
86                 metadataPoolFactory.provideImageQueue(),
87                 imageDistributor, imageReader.getSurface());
88 
89         mMetadataPool = metadataPoolFactory.provideMetadataPool();
90 
91         mSharedImageReader = new ManagedImageReader(
92                 new Lifetime(lifetime), ringBufferFactory.provideTicketPool(),
93                 imageReader.getSurface(), imageDistributor);
94 
95         mAvailableImageCount = ringBufferFactory.provideTicketPool().getAvailableTicketCount();
96 
97         // Create a ResponseListener which updates the global timestamp queue
98         // and the metadata callback.
99         mResponseListener = ResponseListeners.forListeners(
100                 forTimestamps(globalTimestampQueue),
101                 forFinalMetadata(metadataPoolFactory.provideMetadataCallback()));
102     }
103 
provideSharedImageReader()104     public ManagedImageReader provideSharedImageReader() {
105         return mSharedImageReader;
106     }
107 
provideGlobalResponseListener()108     public ResponseListener provideGlobalResponseListener() {
109         return mResponseListener;
110     }
111 
provideZSLStream()112     public ImageStream provideZSLStream() {
113         return mZslCaptureStream;
114     }
115 
provideMetadataPool()116     public MetadataPool provideMetadataPool() {
117         return mMetadataPool;
118     }
119 
provideAvailableImageCount()120     public Observable<Integer> provideAvailableImageCount() {
121         return mAvailableImageCount;
122     }
123 }
124