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