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