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 */ Builder(int requestId, int subsequenceId, CaptureRequest request, boolean repeating, Collection<Long> jpegSurfaceIds)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 */ jpegType(Surface s)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 */ previewType(Surface s)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 */ numJpegTargets(CaptureRequest request)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 */ numPreviewTargets(CaptureRequest request)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 */ build(long frameNumber)154 public RequestHolder build(long frameNumber) { 155 return new RequestHolder(mRequestId, mSubsequenceId, mRequest, mRepeating, frameNumber, 156 mNumJpegTargets, mNumPreviewTargets, mJpegSurfaceIds); 157 } 158 } 159 RequestHolder(int requestId, int subsequenceId, CaptureRequest request, boolean repeating, long frameNumber, int numJpegTargets, int numPreviewTargets, Collection<Long> jpegSurfaceIds)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 */ getRequestId()176 public int getRequestId() { 177 return mRequestId; 178 } 179 180 /** 181 * Returns true if the contained request is repeating. 182 */ isRepeating()183 public boolean isRepeating() { 184 return mRepeating; 185 } 186 187 /** 188 * Return the subsequence id for this request. 189 */ getSubsequeceId()190 public int getSubsequeceId() { 191 return mSubsequeceId; 192 } 193 194 /** 195 * Returns the frame number for this request. 196 */ getFrameNumber()197 public long getFrameNumber() { 198 return mFrameNumber; 199 } 200 201 /** 202 * Returns the contained request. 203 */ getRequest()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 */ getHolderTargets()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 */ hasJpegTargets()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 */ hasPreviewTargets()226 public boolean hasPreviewTargets(){ 227 return mNumPreviewTargets > 0; 228 } 229 230 /** 231 * Return the number of jpeg-type surfaces targeted by this request. 232 */ numJpegTargets()233 public int numJpegTargets() { 234 return mNumJpegTargets; 235 } 236 237 /** 238 * Return the number of non-jpeg-type surfaces targeted by this request. 239 */ numPreviewTargets()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 */ jpegType(Surface s)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 */ failRequest()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 */ requestFailed()266 public boolean requestFailed() { 267 return mFailed; 268 } 269 270 /** 271 * Mark at least one of this request's output surfaces is abandoned. 272 */ setOutputAbandoned()273 public void setOutputAbandoned() { 274 mOutputAbandoned = true; 275 } 276 277 /** 278 * Return if any of this request's output surface is abandoned. 279 */ isOutputAbandoned()280 public boolean isOutputAbandoned() { 281 return mOutputAbandoned; 282 } 283 } 284