RequestHolder.java revision e663cb77281c4c76241b820f6126543f1c2d859f
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
17package android.hardware.camera2.legacy;
18
19import android.hardware.camera2.CaptureRequest;
20import android.hardware.camera2.impl.CameraMetadataNative;
21import android.util.Log;
22import android.view.Surface;
23
24import java.util.Collection;
25
26import 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 */
33public 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     * Returns true if the given surface requires jpeg buffers.
47     *
48     * @param s a {@link android.view.Surface} to check.
49     * @return true if the surface requires a jpeg buffer.
50     */
51    public static boolean jpegType(Surface s)
52            throws LegacyExceptionUtils.BufferQueueAbandonedException {
53        return LegacyCameraDevice.detectSurfaceType(s) ==
54                CameraMetadataNative.NATIVE_JPEG_FORMAT;
55    }
56
57    /**
58     * Returns true if the given surface requires non-jpeg buffer types.
59     *
60     * <p>
61     * "Jpeg buffer" refers to the buffers returned in the jpeg
62     * {@link android.hardware.Camera.PictureCallback}.  Non-jpeg buffers are created using a tee
63     * of the preview stream drawn to the surface
64     * set via {@link android.hardware.Camera#setPreviewDisplay(android.view.SurfaceHolder)} or
65     * equivalent methods.
66     * </p>
67     * @param s a {@link android.view.Surface} to check.
68     * @return true if the surface requires a non-jpeg buffer type.
69     */
70    public static boolean previewType(Surface s)
71            throws LegacyExceptionUtils.BufferQueueAbandonedException {
72        return LegacyCameraDevice.detectSurfaceType(s) !=
73                CameraMetadataNative.NATIVE_JPEG_FORMAT;
74    }
75
76    /**
77     * Returns the number of surfaces targeted by the request that require jpeg buffers.
78     */
79    private static int numJpegTargets(CaptureRequest request) {
80        int count = 0;
81        for (Surface s : request.getTargets()) {
82            try {
83                if (jpegType(s)) {
84                    ++count;
85                }
86            } catch (LegacyExceptionUtils.BufferQueueAbandonedException e) {
87                Log.w(TAG, "Surface abandoned, skipping...", e);
88            }
89        }
90        return count;
91    }
92
93    /**
94     * Returns the number of surfaces targeted by the request that require non-jpeg buffers.
95     */
96    private static int numPreviewTargets(CaptureRequest request) {
97        int count = 0;
98        for (Surface s : request.getTargets()) {
99            try {
100                if (previewType(s)) {
101                    ++count;
102                }
103            } catch (LegacyExceptionUtils.BufferQueueAbandonedException e) {
104                Log.w(TAG, "Surface abandoned, skipping...", e);
105            }
106        }
107        return count;
108    }
109
110    /**
111     * A builder class for {@link RequestHolder} objects.
112     *
113     * <p>
114     * This allows per-request queries to be cached for repeating {@link CaptureRequest} objects.
115     * </p>
116     */
117    public final static class Builder {
118        private final int mRequestId;
119        private final int mSubsequenceId;
120        private final CaptureRequest mRequest;
121        private final boolean mRepeating;
122        private final int mNumJpegTargets;
123        private final int mNumPreviewTargets;
124
125        /**
126         * Construct a new {@link Builder} to generate {@link RequestHolder} objects.
127         *
128         * @param requestId the ID to set in {@link RequestHolder} objects.
129         * @param subsequenceId the sequence ID to set in {@link RequestHolder} objects.
130         * @param request the original {@link CaptureRequest} to set in {@link RequestHolder}
131         *                objects.
132         * @param repeating {@code true} if the request is repeating.
133         */
134        public Builder(int requestId, int subsequenceId, CaptureRequest request,
135                       boolean repeating) {
136            checkNotNull(request, "request must not be null");
137            mRequestId = requestId;
138            mSubsequenceId = subsequenceId;
139            mRequest = request;
140            mRepeating = repeating;
141            mNumJpegTargets = numJpegTargets(mRequest);
142            mNumPreviewTargets = numPreviewTargets(mRequest);
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