1b4b27f2c7738cd5e3f31a281d66a33f4698810b3Shashi Shekhar/* 2b4b27f2c7738cd5e3f31a281d66a33f4698810b3Shashi Shekhar * Copyright (C) 2015 The Android Open Source Project 3b4b27f2c7738cd5e3f31a281d66a33f4698810b3Shashi Shekhar * 4b4b27f2c7738cd5e3f31a281d66a33f4698810b3Shashi Shekhar * Licensed under the Apache License, Version 2.0 (the "License"); 5b4b27f2c7738cd5e3f31a281d66a33f4698810b3Shashi Shekhar * you may not use this file except in compliance with the License. 6b4b27f2c7738cd5e3f31a281d66a33f4698810b3Shashi Shekhar * You may obtain a copy of the License at 7b4b27f2c7738cd5e3f31a281d66a33f4698810b3Shashi Shekhar * 8b4b27f2c7738cd5e3f31a281d66a33f4698810b3Shashi Shekhar * http://www.apache.org/licenses/LICENSE-2.0 9b4b27f2c7738cd5e3f31a281d66a33f4698810b3Shashi Shekhar * 10b4b27f2c7738cd5e3f31a281d66a33f4698810b3Shashi Shekhar * Unless required by applicable law or agreed to in writing, software 11b4b27f2c7738cd5e3f31a281d66a33f4698810b3Shashi Shekhar * distributed under the License is distributed on an "AS IS" BASIS, 12b4b27f2c7738cd5e3f31a281d66a33f4698810b3Shashi Shekhar * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13b4b27f2c7738cd5e3f31a281d66a33f4698810b3Shashi Shekhar * See the License for the specific language governing permissions and 14b4b27f2c7738cd5e3f31a281d66a33f4698810b3Shashi Shekhar * limitations under the License. 15b4b27f2c7738cd5e3f31a281d66a33f4698810b3Shashi Shekhar */ 16b4b27f2c7738cd5e3f31a281d66a33f4698810b3Shashi Shekhar 17b4b27f2c7738cd5e3f31a281d66a33f4698810b3Shashi Shekharpackage com.android.camera.burst; 18b4b27f2c7738cd5e3f31a281d66a33f4698810b3Shashi Shekhar 19b4b27f2c7738cd5e3f31a281d66a33f4698810b3Shashi Shekharimport android.support.v4.util.LongSparseArray; 20b4b27f2c7738cd5e3f31a281d66a33f4698810b3Shashi Shekhar 21b4b27f2c7738cd5e3f31a281d66a33f4698810b3Shashi Shekharimport com.android.camera.async.SafeCloseable; 22b4b27f2c7738cd5e3f31a281d66a33f4698810b3Shashi Shekharimport com.android.camera.one.v2.camera2proxy.ImageProxy; 23b4b27f2c7738cd5e3f31a281d66a33f4698810b3Shashi Shekhar 24b4b27f2c7738cd5e3f31a281d66a33f4698810b3Shashi Shekharimport java.util.ArrayList; 25b4b27f2c7738cd5e3f31a281d66a33f4698810b3Shashi Shekharimport java.util.List; 26b4b27f2c7738cd5e3f31a281d66a33f4698810b3Shashi Shekhar 27b4b27f2c7738cd5e3f31a281d66a33f4698810b3Shashi Shekhar/** 28b4b27f2c7738cd5e3f31a281d66a33f4698810b3Shashi Shekhar * A RingBuffer that is used during burst capture. It takes a 29b4b27f2c7738cd5e3f31a281d66a33f4698810b3Shashi Shekhar * {@link EvictionHandler} instance and uses it to evict frames when the ring 30b4b27f2c7738cd5e3f31a281d66a33f4698810b3Shashi Shekhar * buffer runs out of capacity. 31b4b27f2c7738cd5e3f31a281d66a33f4698810b3Shashi Shekhar */ 32f6031c016d916db9789026dc0a6c559d8163a088Spike Spragueclass RingBuffer<T extends ImageProxy> implements SafeCloseable { 33b4b27f2c7738cd5e3f31a281d66a33f4698810b3Shashi Shekhar private final int mMaxCapacity; 34b4b27f2c7738cd5e3f31a281d66a33f4698810b3Shashi Shekhar private final EvictionHandler mEvictionHandler; 35f6031c016d916db9789026dc0a6c559d8163a088Spike Sprague private final LongSparseArray<T> mImages = new LongSparseArray<>(); 36b4b27f2c7738cd5e3f31a281d66a33f4698810b3Shashi Shekhar 37b4b27f2c7738cd5e3f31a281d66a33f4698810b3Shashi Shekhar /** 38b4b27f2c7738cd5e3f31a281d66a33f4698810b3Shashi Shekhar * Create a new ring buffer instance. 39b4b27f2c7738cd5e3f31a281d66a33f4698810b3Shashi Shekhar * 40b4b27f2c7738cd5e3f31a281d66a33f4698810b3Shashi Shekhar * @param maxCapacity the maximum number of images in the ring buffer. 41b4b27f2c7738cd5e3f31a281d66a33f4698810b3Shashi Shekhar * @param evictionHandler 42b4b27f2c7738cd5e3f31a281d66a33f4698810b3Shashi Shekhar */ 43b4b27f2c7738cd5e3f31a281d66a33f4698810b3Shashi Shekhar public RingBuffer(int maxCapacity, EvictionHandler evictionHandler) { 44b4b27f2c7738cd5e3f31a281d66a33f4698810b3Shashi Shekhar mMaxCapacity = maxCapacity; 45b4b27f2c7738cd5e3f31a281d66a33f4698810b3Shashi Shekhar mEvictionHandler = evictionHandler; 46b4b27f2c7738cd5e3f31a281d66a33f4698810b3Shashi Shekhar } 47b4b27f2c7738cd5e3f31a281d66a33f4698810b3Shashi Shekhar 48b4b27f2c7738cd5e3f31a281d66a33f4698810b3Shashi Shekhar /** 49b4b27f2c7738cd5e3f31a281d66a33f4698810b3Shashi Shekhar * Insert an image in the ring buffer, evicting any frames if necessary. 50b4b27f2c7738cd5e3f31a281d66a33f4698810b3Shashi Shekhar * 51b4b27f2c7738cd5e3f31a281d66a33f4698810b3Shashi Shekhar * @param image the image to be inserted. 52b4b27f2c7738cd5e3f31a281d66a33f4698810b3Shashi Shekhar */ 53f6031c016d916db9789026dc0a6c559d8163a088Spike Sprague public synchronized void insertImage(T image) { 54b4b27f2c7738cd5e3f31a281d66a33f4698810b3Shashi Shekhar long timestamp = image.getTimestamp(); 55b4b27f2c7738cd5e3f31a281d66a33f4698810b3Shashi Shekhar if (mImages.get(timestamp) != null) { 56b4b27f2c7738cd5e3f31a281d66a33f4698810b3Shashi Shekhar image.close(); 57b4b27f2c7738cd5e3f31a281d66a33f4698810b3Shashi Shekhar return; 58b4b27f2c7738cd5e3f31a281d66a33f4698810b3Shashi Shekhar } 59b4b27f2c7738cd5e3f31a281d66a33f4698810b3Shashi Shekhar // Add image to ring buffer so it can be closed in case eviction 60b4b27f2c7738cd5e3f31a281d66a33f4698810b3Shashi Shekhar // handler throws. 61b4b27f2c7738cd5e3f31a281d66a33f4698810b3Shashi Shekhar addImage(image); 62b4b27f2c7738cd5e3f31a281d66a33f4698810b3Shashi Shekhar mEvictionHandler.onFrameInserted(timestamp); 63b4b27f2c7738cd5e3f31a281d66a33f4698810b3Shashi Shekhar if (mImages.size() > mMaxCapacity) { 64b4b27f2c7738cd5e3f31a281d66a33f4698810b3Shashi Shekhar long selectFrameToDrop = mEvictionHandler.selectFrameToDrop(); 65b4b27f2c7738cd5e3f31a281d66a33f4698810b3Shashi Shekhar removeAndCloseImage(selectFrameToDrop); 66b4b27f2c7738cd5e3f31a281d66a33f4698810b3Shashi Shekhar mEvictionHandler.onFrameDropped(selectFrameToDrop); 67b4b27f2c7738cd5e3f31a281d66a33f4698810b3Shashi Shekhar } 68b4b27f2c7738cd5e3f31a281d66a33f4698810b3Shashi Shekhar } 69b4b27f2c7738cd5e3f31a281d66a33f4698810b3Shashi Shekhar 70b4b27f2c7738cd5e3f31a281d66a33f4698810b3Shashi Shekhar /** 71b4b27f2c7738cd5e3f31a281d66a33f4698810b3Shashi Shekhar * Returns all images present in the ring buffer. 72b4b27f2c7738cd5e3f31a281d66a33f4698810b3Shashi Shekhar */ 73f6031c016d916db9789026dc0a6c559d8163a088Spike Sprague public synchronized List<T> getAndRemoveAllImages() { 74f6031c016d916db9789026dc0a6c559d8163a088Spike Sprague List<T> allImages = new ArrayList<>(mImages.size()); 75b4b27f2c7738cd5e3f31a281d66a33f4698810b3Shashi Shekhar for (int i = 0; i < mImages.size(); i++) { 76b4b27f2c7738cd5e3f31a281d66a33f4698810b3Shashi Shekhar allImages.add(mImages.valueAt(i)); 77b4b27f2c7738cd5e3f31a281d66a33f4698810b3Shashi Shekhar } 78b4b27f2c7738cd5e3f31a281d66a33f4698810b3Shashi Shekhar mImages.clear(); 79b4b27f2c7738cd5e3f31a281d66a33f4698810b3Shashi Shekhar return allImages; 80b4b27f2c7738cd5e3f31a281d66a33f4698810b3Shashi Shekhar } 81b4b27f2c7738cd5e3f31a281d66a33f4698810b3Shashi Shekhar 82b4b27f2c7738cd5e3f31a281d66a33f4698810b3Shashi Shekhar /** 83b4b27f2c7738cd5e3f31a281d66a33f4698810b3Shashi Shekhar * Closes the ring buffer and any images in the ring buffer. 84b4b27f2c7738cd5e3f31a281d66a33f4698810b3Shashi Shekhar */ 85b4b27f2c7738cd5e3f31a281d66a33f4698810b3Shashi Shekhar @Override 86b4b27f2c7738cd5e3f31a281d66a33f4698810b3Shashi Shekhar public synchronized void close() { 87b4b27f2c7738cd5e3f31a281d66a33f4698810b3Shashi Shekhar for (int i = 0; i < mImages.size(); i++) { 88b4b27f2c7738cd5e3f31a281d66a33f4698810b3Shashi Shekhar mImages.valueAt(i).close(); 89b4b27f2c7738cd5e3f31a281d66a33f4698810b3Shashi Shekhar } 90b4b27f2c7738cd5e3f31a281d66a33f4698810b3Shashi Shekhar mImages.clear(); 91b4b27f2c7738cd5e3f31a281d66a33f4698810b3Shashi Shekhar } 92b4b27f2c7738cd5e3f31a281d66a33f4698810b3Shashi Shekhar 93b4b27f2c7738cd5e3f31a281d66a33f4698810b3Shashi Shekhar private synchronized void removeAndCloseImage(long timestampNs) { 94f6031c016d916db9789026dc0a6c559d8163a088Spike Sprague mImages.get(timestampNs).close(); 95b4b27f2c7738cd5e3f31a281d66a33f4698810b3Shashi Shekhar mImages.remove(timestampNs); 96b4b27f2c7738cd5e3f31a281d66a33f4698810b3Shashi Shekhar } 97b4b27f2c7738cd5e3f31a281d66a33f4698810b3Shashi Shekhar 98f6031c016d916db9789026dc0a6c559d8163a088Spike Sprague private synchronized void addImage(T image) { 99b4b27f2c7738cd5e3f31a281d66a33f4698810b3Shashi Shekhar mImages.put(image.getTimestamp(), image); 100b4b27f2c7738cd5e3f31a281d66a33f4698810b3Shashi Shekhar } 101b4b27f2c7738cd5e3f31a281d66a33f4698810b3Shashi Shekhar} 102