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