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 
     22 import java.util.ArrayDeque;
     23 import 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  */
     30 public 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;
     41     private final List<Long> mJpegSurfaceIds;
     42 
     43     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 
     65     public RequestQueue(List<Long> jpegSurfaceIds) {
     66         mJpegSurfaceIds = jpegSurfaceIds;
     67     }
     68 
     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      *
     74      * @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.
     76      */
     77     public synchronized RequestQueueEntry getNext() {
     78         BurstHolder next = mRequestQueue.poll();
     79         boolean queueEmptied = (next != null && mRequestQueue.size() == 0);
     80         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 
     90         RequestQueueEntry ret =  new RequestQueueEntry(next, mCurrentFrameNumber, queueEmptied);
     91         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;
    106             ret = (mCurrentRepeatingFrameNumber == INVALID_FRAME) ? INVALID_FRAME :
    107                     mCurrentRepeatingFrameNumber - 1;
    108             mCurrentRepeatingFrameNumber = INVALID_FRAME;
    109             Log.i(TAG, "Repeating capture request cancelled.");
    110         } else {
    111             Log.e(TAG, "cancel failed: no repeating request exists for request id: " + requestId);
    112         }
    113         return ret;
    114     }
    115 
    116     /**
    117      * 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     /**
    131      * 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.
    137      * @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.
    141      */
    142     public synchronized SubmitInfo submit(CaptureRequest[] requests, boolean repeating) {
    143         int requestId = mCurrentRequestId++;
    144         BurstHolder burst = new BurstHolder(requestId, repeating, requests, mJpegSurfaceIds);
    145         long lastFrame = INVALID_FRAME;
    146         if (burst.isRepeating()) {
    147             Log.i(TAG, "Repeating capture request set.");
    148             if (mRepeatingRequest != null) {
    149                 lastFrame = (mCurrentRepeatingFrameNumber == INVALID_FRAME) ? INVALID_FRAME :
    150                         mCurrentRepeatingFrameNumber - 1;
    151             }
    152             mCurrentRepeatingFrameNumber = INVALID_FRAME;
    153             mRepeatingRequest = burst;
    154         } else {
    155             mRequestQueue.offer(burst);
    156             lastFrame = calculateLastFrame(burst.getRequestId());
    157         }
    158         SubmitInfo info = new SubmitInfo(requestId, lastFrame);
    159         return info;
    160     }
    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) {
    167                 return total - 1;
    168             }
    169         }
    170         throw new IllegalStateException(
    171                 "At least one request must be in the queue to calculate frame number");
    172     }
    173 
    174 }
    175