• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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  */
16 package android.hardware.camera2.legacy;
17 
18 import android.hardware.camera2.CaptureRequest;
19 import android.hardware.camera2.utils.LongParcelable;
20 import android.util.Log;
21 import android.util.Pair;
22 
23 import java.util.ArrayDeque;
24 import 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  */
31 public 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 
RequestQueue(List<Long> jpegSurfaceIds)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      */
getNext()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      */
stopRepeating(int requestId)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      */
stopRepeating()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      */
submit(List<CaptureRequest> requests, boolean repeating, LongParcelable frameNumber)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 
calculateLastFrame(int requestId)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