RequestQueue.java revision e663cb77281c4c76241b820f6126543f1c2d859f
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.LongParcelable; 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 43 public RequestQueue() {} 44 45 /** 46 * Return and remove the next burst on the queue. 47 * 48 * <p>If a repeating burst is returned, it will not be removed.</p> 49 * 50 * @return a pair containing the next burst and the current frame number, or null if none exist. 51 */ 52 public synchronized Pair<BurstHolder, Long> getNext() { 53 BurstHolder next = mRequestQueue.poll(); 54 if (next == null && mRepeatingRequest != null) { 55 next = mRepeatingRequest; 56 mCurrentRepeatingFrameNumber = mCurrentFrameNumber + 57 next.getNumberOfRequests(); 58 } 59 60 if (next == null) { 61 return null; 62 } 63 64 Pair<BurstHolder, Long> ret = new Pair<BurstHolder, Long>(next, mCurrentFrameNumber); 65 mCurrentFrameNumber += next.getNumberOfRequests(); 66 return ret; 67 } 68 69 /** 70 * Cancel a repeating request. 71 * 72 * @param requestId the id of the repeating request to cancel. 73 * @return the last frame to be returned from the HAL for the given repeating request, or 74 * {@code INVALID_FRAME} if none exists. 75 */ 76 public synchronized long stopRepeating(int requestId) { 77 long ret = INVALID_FRAME; 78 if (mRepeatingRequest != null && mRepeatingRequest.getRequestId() == requestId) { 79 mRepeatingRequest = null; 80 ret = (mCurrentRepeatingFrameNumber == INVALID_FRAME) ? INVALID_FRAME : 81 mCurrentRepeatingFrameNumber - 1; 82 mCurrentRepeatingFrameNumber = INVALID_FRAME; 83 Log.i(TAG, "Repeating capture request cancelled."); 84 } else { 85 Log.e(TAG, "cancel failed: no repeating request exists for request id: " + requestId); 86 } 87 return ret; 88 } 89 90 /** 91 * Cancel a repeating request. 92 * 93 * @return the last frame to be returned from the HAL for the given repeating request, or 94 * {@code INVALID_FRAME} if none exists. 95 */ 96 public synchronized long stopRepeating() { 97 if (mRepeatingRequest == null) { 98 Log.e(TAG, "cancel failed: no repeating request exists."); 99 return INVALID_FRAME; 100 } 101 return stopRepeating(mRepeatingRequest.getRequestId()); 102 } 103 104 /** 105 * Add a the given burst to the queue. 106 * 107 * <p>If the burst is repeating, replace the current repeating burst.</p> 108 * 109 * @param requests the burst of requests to add to the queue. 110 * @param repeating true if the burst is repeating. 111 * @param frameNumber an output argument that contains either the frame number of the last frame 112 * that will be returned for this request, or the frame number of the last 113 * frame that will be returned for the current repeating request if this 114 * burst is set to be repeating. 115 * @return the request id. 116 */ 117 public synchronized int submit(List<CaptureRequest> requests, boolean repeating, 118 /*out*/LongParcelable frameNumber) { 119 int requestId = mCurrentRequestId++; 120 BurstHolder burst = new BurstHolder(requestId, repeating, requests); 121 long ret = INVALID_FRAME; 122 if (burst.isRepeating()) { 123 Log.i(TAG, "Repeating capture request set."); 124 if (mRepeatingRequest != null) { 125 ret = (mCurrentRepeatingFrameNumber == INVALID_FRAME) ? INVALID_FRAME : 126 mCurrentRepeatingFrameNumber - 1; 127 } 128 mCurrentRepeatingFrameNumber = INVALID_FRAME; 129 mRepeatingRequest = burst; 130 } else { 131 mRequestQueue.offer(burst); 132 ret = calculateLastFrame(burst.getRequestId()); 133 } 134 frameNumber.setNumber(ret); 135 return requestId; 136 } 137 138 private long calculateLastFrame(int requestId) { 139 long total = mCurrentFrameNumber; 140 for (BurstHolder b : mRequestQueue) { 141 total += b.getNumberOfRequests(); 142 if (b.getRequestId() == requestId) { 143 return total - 1; 144 } 145 } 146 throw new IllegalStateException( 147 "At least one request must be in the queue to calculate frame number"); 148 } 149 150} 151