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