RequestQueue.java revision 0fd198ad89ec9c600bb1761b10d938146c28bb98
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 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 * @param frameNumber an output argument that contains either the frame number of the last frame 115 * that will be returned for this request, or the frame number of the last 116 * frame that will be returned for the current repeating request if this 117 * burst is set to be repeating. 118 * @return the request id. 119 */ 120 public synchronized int submit(List<CaptureRequest> requests, boolean repeating, 121 /*out*/LongParcelable frameNumber) { 122 int requestId = mCurrentRequestId++; 123 BurstHolder burst = new BurstHolder(requestId, repeating, requests, mJpegSurfaceIds); 124 long ret = INVALID_FRAME; 125 if (burst.isRepeating()) { 126 Log.i(TAG, "Repeating capture request set."); 127 if (mRepeatingRequest != null) { 128 ret = (mCurrentRepeatingFrameNumber == INVALID_FRAME) ? INVALID_FRAME : 129 mCurrentRepeatingFrameNumber - 1; 130 } 131 mCurrentRepeatingFrameNumber = INVALID_FRAME; 132 mRepeatingRequest = burst; 133 } else { 134 mRequestQueue.offer(burst); 135 ret = calculateLastFrame(burst.getRequestId()); 136 } 137 frameNumber.setNumber(ret); 138 return requestId; 139 } 140 141 private long calculateLastFrame(int requestId) { 142 long total = mCurrentFrameNumber; 143 for (BurstHolder b : mRequestQueue) { 144 total += b.getNumberOfRequests(); 145 if (b.getRequestId() == requestId) { 146 return total - 1; 147 } 148 } 149 throw new IllegalStateException( 150 "At least one request must be in the queue to calculate frame number"); 151 } 152 153} 154