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