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 * 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