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 
     17 package android.hardware.camera2.legacy;
     18 
     19 import android.hardware.camera2.CaptureRequest;
     20 import android.hardware.camera2.impl.CameraMetadataNative;
     21 import android.util.Log;
     22 import android.view.Surface;
     23 
     24 import java.util.Collection;
     25 
     26 import static com.android.internal.util.Preconditions.*;
     27 
     28 /**
     29  * Semi-immutable container for a single capture request and associated information,
     30  * the only mutable characteristic of this container is whether or not is has been
     31  * marked as "failed" using {@code #failRequest}.
     32  */
     33 public class RequestHolder {
     34     private static final String TAG = "RequestHolder";
     35 
     36     private final boolean mRepeating;
     37     private final CaptureRequest mRequest;
     38     private final int mRequestId;
     39     private final int mSubsequeceId;
     40     private final long mFrameNumber;
     41     private final int mNumJpegTargets;
     42     private final int mNumPreviewTargets;
     43     private volatile boolean mFailed = false;
     44 
     45     /**
     46      * A builder class for {@link RequestHolder} objects.
     47      *
     48      * <p>
     49      * This allows per-request queries to be cached for repeating {@link CaptureRequest} objects.
     50      * </p>
     51      */
     52     public final static class Builder {
     53         private final int mRequestId;
     54         private final int mSubsequenceId;
     55         private final CaptureRequest mRequest;
     56         private final boolean mRepeating;
     57         private final int mNumJpegTargets;
     58         private final int mNumPreviewTargets;
     59         private final Collection<Long> mJpegSurfaceIds;
     60 
     61         /**
     62          * Construct a new {@link Builder} to generate {@link RequestHolder} objects.
     63          *
     64          * @param requestId the ID to set in {@link RequestHolder} objects.
     65          * @param subsequenceId the sequence ID to set in {@link RequestHolder} objects.
     66          * @param request the original {@link CaptureRequest} to set in {@link RequestHolder}
     67          *                objects.
     68          * @param repeating {@code true} if the request is repeating.
     69          */
     70         public Builder(int requestId, int subsequenceId, CaptureRequest request,
     71                        boolean repeating, Collection<Long> jpegSurfaceIds) {
     72             checkNotNull(request, "request must not be null");
     73             mRequestId = requestId;
     74             mSubsequenceId = subsequenceId;
     75             mRequest = request;
     76             mRepeating = repeating;
     77             mJpegSurfaceIds = jpegSurfaceIds;
     78             mNumJpegTargets = numJpegTargets(mRequest);
     79             mNumPreviewTargets = numPreviewTargets(mRequest);
     80         }
     81 
     82         /**
     83          * Returns true if the given surface requires jpeg buffers.
     84          *
     85          * @param s a {@link android.view.Surface} to check.
     86          * @return true if the surface requires a jpeg buffer.
     87          */
     88         private boolean jpegType(Surface s)
     89                 throws LegacyExceptionUtils.BufferQueueAbandonedException {
     90             return LegacyCameraDevice.containsSurfaceId(s, mJpegSurfaceIds);
     91         }
     92 
     93         /**
     94          * Returns true if the given surface requires non-jpeg buffer types.
     95          *
     96          * <p>
     97          * "Jpeg buffer" refers to the buffers returned in the jpeg
     98          * {@link android.hardware.Camera.PictureCallback}.  Non-jpeg buffers are created using a tee
     99          * of the preview stream drawn to the surface
    100          * set via {@link android.hardware.Camera#setPreviewDisplay(android.view.SurfaceHolder)} or
    101          * equivalent methods.
    102          * </p>
    103          * @param s a {@link android.view.Surface} to check.
    104          * @return true if the surface requires a non-jpeg buffer type.
    105          */
    106         private boolean previewType(Surface s)
    107                 throws LegacyExceptionUtils.BufferQueueAbandonedException {
    108             return !jpegType(s);
    109         }
    110 
    111         /**
    112          * Returns the number of surfaces targeted by the request that require jpeg buffers.
    113          */
    114         private int numJpegTargets(CaptureRequest request) {
    115             int count = 0;
    116             for (Surface s : request.getTargets()) {
    117                 try {
    118                     if (jpegType(s)) {
    119                         ++count;
    120                     }
    121                 } catch (LegacyExceptionUtils.BufferQueueAbandonedException e) {
    122                     Log.d(TAG, "Surface abandoned, skipping...", e);
    123                 }
    124             }
    125             return count;
    126         }
    127 
    128         /**
    129          * Returns the number of surfaces targeted by the request that require non-jpeg buffers.
    130          */
    131         private int numPreviewTargets(CaptureRequest request) {
    132             int count = 0;
    133             for (Surface s : request.getTargets()) {
    134                 try {
    135                     if (previewType(s)) {
    136                         ++count;
    137                     }
    138                 } catch (LegacyExceptionUtils.BufferQueueAbandonedException e) {
    139                     Log.d(TAG, "Surface abandoned, skipping...", e);
    140                 }
    141             }
    142             return count;
    143         }
    144 
    145         /**
    146          * Build a new {@link RequestHolder} using with parameters generated from this
    147          *      {@link Builder}.
    148          *
    149          * @param frameNumber the {@code framenumber} to generate in the {@link RequestHolder}.
    150          * @return a {@link RequestHolder} constructed with the {@link Builder}'s parameters.
    151          */
    152         public RequestHolder build(long frameNumber) {
    153             return new RequestHolder(mRequestId, mSubsequenceId, mRequest, mRepeating, frameNumber,
    154                     mNumJpegTargets, mNumPreviewTargets);
    155         }
    156     }
    157 
    158     private RequestHolder(int requestId, int subsequenceId, CaptureRequest request,
    159                           boolean repeating, long frameNumber, int numJpegTargets,
    160                           int numPreviewTargets) {
    161         mRepeating = repeating;
    162         mRequest = request;
    163         mRequestId = requestId;
    164         mSubsequeceId = subsequenceId;
    165         mFrameNumber = frameNumber;
    166         mNumJpegTargets = numJpegTargets;
    167         mNumPreviewTargets = numPreviewTargets;
    168     }
    169 
    170     /**
    171      * Return the request id for the contained {@link CaptureRequest}.
    172      */
    173     public int getRequestId() {
    174         return mRequestId;
    175     }
    176 
    177     /**
    178      * Returns true if the contained request is repeating.
    179      */
    180     public boolean isRepeating() {
    181         return mRepeating;
    182     }
    183 
    184     /**
    185      * Return the subsequence id for this request.
    186      */
    187     public int getSubsequeceId() {
    188         return mSubsequeceId;
    189     }
    190 
    191     /**
    192      * Returns the frame number for this request.
    193      */
    194     public long getFrameNumber() {
    195         return mFrameNumber;
    196     }
    197 
    198     /**
    199      * Returns the contained request.
    200      */
    201     public CaptureRequest getRequest() {
    202         return mRequest;
    203     }
    204 
    205     /**
    206      * Returns a read-only collection of the surfaces targeted by the contained request.
    207      */
    208     public Collection<Surface> getHolderTargets() {
    209         return getRequest().getTargets();
    210     }
    211 
    212     /**
    213      * Returns true if any of the surfaces targeted by the contained request require jpeg buffers.
    214      */
    215     public boolean hasJpegTargets() {
    216         return mNumJpegTargets > 0;
    217     }
    218 
    219     /**
    220      * Returns true if any of the surfaces targeted by the contained request require a
    221      * non-jpeg buffer type.
    222      */
    223     public boolean hasPreviewTargets(){
    224         return mNumPreviewTargets > 0;
    225     }
    226 
    227     /**
    228      * Return the number of jpeg-type surfaces targeted by this request.
    229      */
    230     public int numJpegTargets() {
    231         return mNumJpegTargets;
    232     }
    233 
    234     /**
    235      * Return the number of non-jpeg-type surfaces targeted by this request.
    236      */
    237     public int numPreviewTargets() {
    238         return mNumPreviewTargets;
    239     }
    240 
    241     /**
    242      * Mark this request as failed.
    243      */
    244     public void failRequest() {
    245         Log.w(TAG, "Capture failed for request: " + getRequestId());
    246         mFailed = true;
    247     }
    248 
    249     /**
    250      * Return {@code true} if this request failed.
    251      */
    252     public boolean requestFailed() {
    253         return mFailed;
    254     }
    255 
    256 }
    257