1feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk/*
2feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * Copyright (C) 2014 The Android Open Source Project
3feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk *
4feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * Licensed under the Apache License, Version 2.0 (the "License");
5feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * you may not use this file except in compliance with the License.
6feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * You may obtain a copy of the License at
7feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk *
8feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk *      http://www.apache.org/licenses/LICENSE-2.0
9feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk *
10feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * Unless required by applicable law or agreed to in writing, software
11feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * distributed under the License is distributed on an "AS IS" BASIS,
12feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * See the License for the specific language governing permissions and
14feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * limitations under the License.
15feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk */
16feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkpackage android.hardware.camera2.legacy;
17feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
18feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkimport android.hardware.camera2.CaptureRequest;
19feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkimport android.hardware.camera2.utils.LongParcelable;
20feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkimport android.util.Log;
21feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkimport android.util.Pair;
22feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
23feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkimport java.util.ArrayDeque;
24feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkimport java.util.List;
25feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
26feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk/**
27feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * A queue of bursts of requests.
28feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk *
29feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk * <p>This queue maintains the count of frames that have been produced, and is thread safe.</p>
30feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk */
31feb50af361e4305a25758966b6b5df2738c00259Ruben Brunkpublic class RequestQueue {
32feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    private static final String TAG = "RequestQueue";
33feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
34feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    private static final long INVALID_FRAME = -1;
35feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
36feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    private BurstHolder mRepeatingRequest = null;
37feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    private final ArrayDeque<BurstHolder> mRequestQueue = new ArrayDeque<BurstHolder>();
38feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
39feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    private long mCurrentFrameNumber = 0;
40feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    private long mCurrentRepeatingFrameNumber = INVALID_FRAME;
41feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    private int mCurrentRequestId = 0;
420fd198ad89ec9c600bb1761b10d938146c28bb98Ruben Brunk    private final List<Long> mJpegSurfaceIds;
43feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
440fd198ad89ec9c600bb1761b10d938146c28bb98Ruben Brunk    public RequestQueue(List<Long> jpegSurfaceIds) {
450fd198ad89ec9c600bb1761b10d938146c28bb98Ruben Brunk        mJpegSurfaceIds = jpegSurfaceIds;
460fd198ad89ec9c600bb1761b10d938146c28bb98Ruben Brunk    }
47feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
48feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    /**
49feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk     * Return and remove the next burst on the queue.
50feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk     *
51feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk     * <p>If a repeating burst is returned, it will not be removed.</p>
52feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk     *
53feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk     * @return a pair containing the next burst and the current frame number, or null if none exist.
54feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk     */
55feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    public synchronized Pair<BurstHolder, Long> getNext() {
56feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        BurstHolder next = mRequestQueue.poll();
57feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        if (next == null && mRepeatingRequest != null) {
58feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            next = mRepeatingRequest;
59feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            mCurrentRepeatingFrameNumber = mCurrentFrameNumber +
60feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                    next.getNumberOfRequests();
61feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        }
62feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
63feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        if (next == null) {
64feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            return null;
65feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        }
66feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
67feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        Pair<BurstHolder, Long> ret =  new Pair<BurstHolder, Long>(next, mCurrentFrameNumber);
68feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        mCurrentFrameNumber += next.getNumberOfRequests();
69feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        return ret;
70feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
71feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
72feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    /**
73feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk     * Cancel a repeating request.
74feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk     *
75feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk     * @param requestId the id of the repeating request to cancel.
76feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk     * @return the last frame to be returned from the HAL for the given repeating request, or
77feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk     *          {@code INVALID_FRAME} if none exists.
78feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk     */
79feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    public synchronized long stopRepeating(int requestId) {
80feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        long ret = INVALID_FRAME;
81feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        if (mRepeatingRequest != null && mRepeatingRequest.getRequestId() == requestId) {
82feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            mRepeatingRequest = null;
8353284d5816f065b2de20dcb019fa1096b148eee4Ruben Brunk            ret = (mCurrentRepeatingFrameNumber == INVALID_FRAME) ? INVALID_FRAME :
8453284d5816f065b2de20dcb019fa1096b148eee4Ruben Brunk                    mCurrentRepeatingFrameNumber - 1;
85feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            mCurrentRepeatingFrameNumber = INVALID_FRAME;
86e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk            Log.i(TAG, "Repeating capture request cancelled.");
87feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        } else {
88feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            Log.e(TAG, "cancel failed: no repeating request exists for request id: " + requestId);
89feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        }
90feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        return ret;
91feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
92feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
93feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    /**
94e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk     * Cancel a repeating request.
95e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk     *
96e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk     * @return the last frame to be returned from the HAL for the given repeating request, or
97e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk     *          {@code INVALID_FRAME} if none exists.
98e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk     */
99e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk    public synchronized long stopRepeating() {
100e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk        if (mRepeatingRequest == null) {
101e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk            Log.e(TAG, "cancel failed: no repeating request exists.");
102e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk            return INVALID_FRAME;
103e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk        }
104e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk        return stopRepeating(mRepeatingRequest.getRequestId());
105e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk    }
106e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk
107e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk    /**
108feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk     * Add a the given burst to the queue.
109feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk     *
110feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk     * <p>If the burst is repeating, replace the current repeating burst.</p>
111feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk     *
112feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk     * @param requests the burst of requests to add to the queue.
113feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk     * @param repeating true if the burst is repeating.
114feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk     * @param frameNumber an output argument that contains either the frame number of the last frame
115feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk     *                    that will be returned for this request, or the frame number of the last
116feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk     *                    frame that will be returned for the current repeating request if this
117feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk     *                    burst is set to be repeating.
118feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk     * @return the request id.
119feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk     */
120feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    public synchronized int submit(List<CaptureRequest> requests, boolean repeating,
121feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            /*out*/LongParcelable frameNumber) {
122feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        int requestId = mCurrentRequestId++;
1230fd198ad89ec9c600bb1761b10d938146c28bb98Ruben Brunk        BurstHolder burst = new BurstHolder(requestId, repeating, requests, mJpegSurfaceIds);
124feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        long ret = INVALID_FRAME;
125feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        if (burst.isRepeating()) {
126e663cb77281c4c76241b820f6126543f1c2d859fRuben Brunk            Log.i(TAG, "Repeating capture request set.");
127feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            if (mRepeatingRequest != null) {
12853284d5816f065b2de20dcb019fa1096b148eee4Ruben Brunk                ret = (mCurrentRepeatingFrameNumber == INVALID_FRAME) ? INVALID_FRAME :
12953284d5816f065b2de20dcb019fa1096b148eee4Ruben Brunk                        mCurrentRepeatingFrameNumber - 1;
130feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            }
131feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            mCurrentRepeatingFrameNumber = INVALID_FRAME;
132feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            mRepeatingRequest = burst;
133feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        } else {
134feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            mRequestQueue.offer(burst);
135feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            ret = calculateLastFrame(burst.getRequestId());
136feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        }
137feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        frameNumber.setNumber(ret);
138feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        return requestId;
139feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
140feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
141feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    private long calculateLastFrame(int requestId) {
142feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        long total = mCurrentFrameNumber;
143feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        for (BurstHolder b : mRequestQueue) {
144feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            total += b.getNumberOfRequests();
145feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            if (b.getRequestId() == requestId) {
14691b9aabc9fa0c058ecc4a8b3f486540c28fe1cc0Ruben Brunk                return total - 1;
147feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk            }
148feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        }
149feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk        throw new IllegalStateException(
150feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk                "At least one request must be in the queue to calculate frame number");
151feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk    }
152feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk
153feb50af361e4305a25758966b6b5df2738c00259Ruben Brunk}
154