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 */ 16package android.hardware.camera2.legacy; 17 18import android.hardware.camera2.CaptureRequest; 19import android.hardware.camera2.utils.SubmitInfo; 20import android.util.Log; 21import android.util.Pair; 22 23import java.util.ArrayDeque; 24import java.util.List; 25 26/** 27 * A queue of bursts of requests. 28 * 29 * <p>This queue maintains the count of frames that have been produced, and is thread safe.</p> 30 */ 31public class RequestQueue { 32 private static final String TAG = "RequestQueue"; 33 34 private static final long INVALID_FRAME = -1; 35 36 private BurstHolder mRepeatingRequest = null; 37 private final ArrayDeque<BurstHolder> mRequestQueue = new ArrayDeque<BurstHolder>(); 38 39 private long mCurrentFrameNumber = 0; 40 private long mCurrentRepeatingFrameNumber = INVALID_FRAME; 41 private int mCurrentRequestId = 0; 42 private final List<Long> mJpegSurfaceIds; 43 44 public RequestQueue(List<Long> jpegSurfaceIds) { 45 mJpegSurfaceIds = jpegSurfaceIds; 46 } 47 48 /** 49 * Return and remove the next burst on the queue. 50 * 51 * <p>If a repeating burst is returned, it will not be removed.</p> 52 * 53 * @return a pair containing the next burst and the current frame number, or null if none exist. 54 */ 55 public synchronized Pair<BurstHolder, Long> getNext() { 56 BurstHolder next = mRequestQueue.poll(); 57 if (next == null && mRepeatingRequest != null) { 58 next = mRepeatingRequest; 59 mCurrentRepeatingFrameNumber = mCurrentFrameNumber + 60 next.getNumberOfRequests(); 61 } 62 63 if (next == null) { 64 return null; 65 } 66 67 Pair<BurstHolder, Long> ret = new Pair<BurstHolder, Long>(next, mCurrentFrameNumber); 68 mCurrentFrameNumber += next.getNumberOfRequests(); 69 return ret; 70 } 71 72 /** 73 * Cancel a repeating request. 74 * 75 * @param requestId the id of the repeating request to cancel. 76 * @return the last frame to be returned from the HAL for the given repeating request, or 77 * {@code INVALID_FRAME} if none exists. 78 */ 79 public synchronized long stopRepeating(int requestId) { 80 long ret = INVALID_FRAME; 81 if (mRepeatingRequest != null && mRepeatingRequest.getRequestId() == requestId) { 82 mRepeatingRequest = null; 83 ret = (mCurrentRepeatingFrameNumber == INVALID_FRAME) ? INVALID_FRAME : 84 mCurrentRepeatingFrameNumber - 1; 85 mCurrentRepeatingFrameNumber = INVALID_FRAME; 86 Log.i(TAG, "Repeating capture request cancelled."); 87 } else { 88 Log.e(TAG, "cancel failed: no repeating request exists for request id: " + requestId); 89 } 90 return ret; 91 } 92 93 /** 94 * Cancel a repeating request. 95 * 96 * @return the last frame to be returned from the HAL for the given repeating request, or 97 * {@code INVALID_FRAME} if none exists. 98 */ 99 public synchronized long stopRepeating() { 100 if (mRepeatingRequest == null) { 101 Log.e(TAG, "cancel failed: no repeating request exists."); 102 return INVALID_FRAME; 103 } 104 return stopRepeating(mRepeatingRequest.getRequestId()); 105 } 106 107 /** 108 * Add a the given burst to the queue. 109 * 110 * <p>If the burst is repeating, replace the current repeating burst.</p> 111 * 112 * @param requests the burst of requests to add to the queue. 113 * @param repeating true if the burst is repeating. 114 * @return the submission info, including the new request id, and the last frame number, which 115 * contains either the frame number of the last frame that will be returned for this request, 116 * or the frame number of the last frame that will be returned for the current repeating 117 * request if this burst is set to be repeating. 118 */ 119 public synchronized SubmitInfo submit(CaptureRequest[] requests, boolean repeating) { 120 int requestId = mCurrentRequestId++; 121 BurstHolder burst = new BurstHolder(requestId, repeating, requests, mJpegSurfaceIds); 122 long lastFrame = INVALID_FRAME; 123 if (burst.isRepeating()) { 124 Log.i(TAG, "Repeating capture request set."); 125 if (mRepeatingRequest != null) { 126 lastFrame = (mCurrentRepeatingFrameNumber == INVALID_FRAME) ? INVALID_FRAME : 127 mCurrentRepeatingFrameNumber - 1; 128 } 129 mCurrentRepeatingFrameNumber = INVALID_FRAME; 130 mRepeatingRequest = burst; 131 } else { 132 mRequestQueue.offer(burst); 133 lastFrame = calculateLastFrame(burst.getRequestId()); 134 } 135 SubmitInfo info = new SubmitInfo(requestId, lastFrame); 136 return info; 137 } 138 139 private long calculateLastFrame(int requestId) { 140 long total = mCurrentFrameNumber; 141 for (BurstHolder b : mRequestQueue) { 142 total += b.getNumberOfRequests(); 143 if (b.getRequestId() == requestId) { 144 return total - 1; 145 } 146 } 147 throw new IllegalStateException( 148 "At least one request must be in the queue to calculate frame number"); 149 } 150 151} 152