blob: 407e5e63e6ac599d3fb8bf65a6854946f82b8e59 [file] [log] [blame]
Ruben Brunkfeb50af2014-05-09 19:58:49 -07001/*
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;
Eino-Ville Talvala5d2d7782015-12-17 16:50:50 -080019import android.hardware.camera2.utils.SubmitInfo;
Ruben Brunkfeb50af2014-05-09 19:58:49 -070020import android.util.Log;
Ruben Brunkfeb50af2014-05-09 19:58:49 -070021
22import java.util.ArrayDeque;
23import java.util.List;
24
25/**
26 * A queue of bursts of requests.
27 *
28 * <p>This queue maintains the count of frames that have been produced, and is thread safe.</p>
29 */
30public class RequestQueue {
31 private static final String TAG = "RequestQueue";
32
33 private static final long INVALID_FRAME = -1;
34
35 private BurstHolder mRepeatingRequest = null;
36 private final ArrayDeque<BurstHolder> mRequestQueue = new ArrayDeque<BurstHolder>();
37
38 private long mCurrentFrameNumber = 0;
39 private long mCurrentRepeatingFrameNumber = INVALID_FRAME;
40 private int mCurrentRequestId = 0;
Ruben Brunk0fd198a2014-09-23 23:35:43 -070041 private final List<Long> mJpegSurfaceIds;
Ruben Brunkfeb50af2014-05-09 19:58:49 -070042
Shuzhen Wang234ba3e2017-08-11 09:11:23 -070043 public final class RequestQueueEntry {
44 private final BurstHolder mBurstHolder;
45 private final Long mFrameNumber;
46 private final boolean mQueueEmpty;
47
48 public BurstHolder getBurstHolder() {
49 return mBurstHolder;
50 }
51 public Long getFrameNumber() {
52 return mFrameNumber;
53 }
54 public boolean isQueueEmpty() {
55 return mQueueEmpty;
56 }
57
58 public RequestQueueEntry(BurstHolder burstHolder, Long frameNumber, boolean queueEmpty) {
59 mBurstHolder = burstHolder;
60 mFrameNumber = frameNumber;
61 mQueueEmpty = queueEmpty;
62 }
63 }
64
Ruben Brunk0fd198a2014-09-23 23:35:43 -070065 public RequestQueue(List<Long> jpegSurfaceIds) {
66 mJpegSurfaceIds = jpegSurfaceIds;
67 }
Ruben Brunkfeb50af2014-05-09 19:58:49 -070068
69 /**
70 * Return and remove the next burst on the queue.
71 *
72 * <p>If a repeating burst is returned, it will not be removed.</p>
73 *
Shuzhen Wang234ba3e2017-08-11 09:11:23 -070074 * @return an entry containing the next burst, the current frame number, and flag about whether
75 * request queue becomes empty. Null if no burst exists.
Ruben Brunkfeb50af2014-05-09 19:58:49 -070076 */
Shuzhen Wang234ba3e2017-08-11 09:11:23 -070077 public synchronized RequestQueueEntry getNext() {
Ruben Brunkfeb50af2014-05-09 19:58:49 -070078 BurstHolder next = mRequestQueue.poll();
Shuzhen Wang234ba3e2017-08-11 09:11:23 -070079 boolean queueEmptied = (next != null && mRequestQueue.size() == 0);
Ruben Brunkfeb50af2014-05-09 19:58:49 -070080 if (next == null && mRepeatingRequest != null) {
81 next = mRepeatingRequest;
82 mCurrentRepeatingFrameNumber = mCurrentFrameNumber +
83 next.getNumberOfRequests();
84 }
85
86 if (next == null) {
87 return null;
88 }
89
Shuzhen Wang234ba3e2017-08-11 09:11:23 -070090 RequestQueueEntry ret = new RequestQueueEntry(next, mCurrentFrameNumber, queueEmptied);
Ruben Brunkfeb50af2014-05-09 19:58:49 -070091 mCurrentFrameNumber += next.getNumberOfRequests();
92 return ret;
93 }
94
95 /**
96 * Cancel a repeating request.
97 *
98 * @param requestId the id of the repeating request to cancel.
99 * @return the last frame to be returned from the HAL for the given repeating request, or
100 * {@code INVALID_FRAME} if none exists.
101 */
102 public synchronized long stopRepeating(int requestId) {
103 long ret = INVALID_FRAME;
104 if (mRepeatingRequest != null && mRepeatingRequest.getRequestId() == requestId) {
105 mRepeatingRequest = null;
Ruben Brunk53284d52014-06-23 11:36:10 -0700106 ret = (mCurrentRepeatingFrameNumber == INVALID_FRAME) ? INVALID_FRAME :
107 mCurrentRepeatingFrameNumber - 1;
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700108 mCurrentRepeatingFrameNumber = INVALID_FRAME;
Ruben Brunke663cb772014-09-16 13:18:31 -0700109 Log.i(TAG, "Repeating capture request cancelled.");
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700110 } else {
111 Log.e(TAG, "cancel failed: no repeating request exists for request id: " + requestId);
112 }
113 return ret;
114 }
115
116 /**
Ruben Brunke663cb772014-09-16 13:18:31 -0700117 * Cancel a repeating request.
118 *
119 * @return the last frame to be returned from the HAL for the given repeating request, or
120 * {@code INVALID_FRAME} if none exists.
121 */
122 public synchronized long stopRepeating() {
123 if (mRepeatingRequest == null) {
124 Log.e(TAG, "cancel failed: no repeating request exists.");
125 return INVALID_FRAME;
126 }
127 return stopRepeating(mRepeatingRequest.getRequestId());
128 }
129
130 /**
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700131 * Add a the given burst to the queue.
132 *
133 * <p>If the burst is repeating, replace the current repeating burst.</p>
134 *
135 * @param requests the burst of requests to add to the queue.
136 * @param repeating true if the burst is repeating.
Eino-Ville Talvala5d2d7782015-12-17 16:50:50 -0800137 * @return the submission info, including the new request id, and the last frame number, which
138 * contains either the frame number of the last frame that will be returned for this request,
139 * or the frame number of the last frame that will be returned for the current repeating
140 * request if this burst is set to be repeating.
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700141 */
Eino-Ville Talvala5d2d7782015-12-17 16:50:50 -0800142 public synchronized SubmitInfo submit(CaptureRequest[] requests, boolean repeating) {
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700143 int requestId = mCurrentRequestId++;
Ruben Brunk0fd198a2014-09-23 23:35:43 -0700144 BurstHolder burst = new BurstHolder(requestId, repeating, requests, mJpegSurfaceIds);
Eino-Ville Talvala5d2d7782015-12-17 16:50:50 -0800145 long lastFrame = INVALID_FRAME;
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700146 if (burst.isRepeating()) {
Ruben Brunke663cb772014-09-16 13:18:31 -0700147 Log.i(TAG, "Repeating capture request set.");
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700148 if (mRepeatingRequest != null) {
Eino-Ville Talvala5d2d7782015-12-17 16:50:50 -0800149 lastFrame = (mCurrentRepeatingFrameNumber == INVALID_FRAME) ? INVALID_FRAME :
Ruben Brunk53284d52014-06-23 11:36:10 -0700150 mCurrentRepeatingFrameNumber - 1;
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700151 }
152 mCurrentRepeatingFrameNumber = INVALID_FRAME;
153 mRepeatingRequest = burst;
154 } else {
155 mRequestQueue.offer(burst);
Eino-Ville Talvala5d2d7782015-12-17 16:50:50 -0800156 lastFrame = calculateLastFrame(burst.getRequestId());
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700157 }
Eino-Ville Talvala5d2d7782015-12-17 16:50:50 -0800158 SubmitInfo info = new SubmitInfo(requestId, lastFrame);
159 return info;
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700160 }
161
162 private long calculateLastFrame(int requestId) {
163 long total = mCurrentFrameNumber;
164 for (BurstHolder b : mRequestQueue) {
165 total += b.getNumberOfRequests();
166 if (b.getRequestId() == requestId) {
Ruben Brunk91b9aab2014-06-20 00:24:56 -0700167 return total - 1;
Ruben Brunkfeb50af2014-05-09 19:58:49 -0700168 }
169 }
170 throw new IllegalStateException(
171 "At least one request must be in the queue to calculate frame number");
172 }
173
174}