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 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 */ Builder(int requestId, int subsequenceId, CaptureRequest request, boolean repeating, Collection<Long> jpegSurfaceIds)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 */ jpegType(Surface s)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 */ previewType(Surface s)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 */ numJpegTargets(CaptureRequest request)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 */ numPreviewTargets(CaptureRequest request)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 */ build(long frameNumber)151 public RequestHolder build(long frameNumber) { 152 return new RequestHolder(mRequestId, mSubsequenceId, mRequest, mRepeating, frameNumber, 153 mNumJpegTargets, mNumPreviewTargets); 154 } 155 } 156 RequestHolder(int requestId, int subsequenceId, CaptureRequest request, boolean repeating, long frameNumber, int numJpegTargets, int numPreviewTargets)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 */ getRequestId()172 public int getRequestId() { 173 return mRequestId; 174 } 175 176 /** 177 * Returns true if the contained request is repeating. 178 */ isRepeating()179 public boolean isRepeating() { 180 return mRepeating; 181 } 182 183 /** 184 * Return the subsequence id for this request. 185 */ getSubsequeceId()186 public int getSubsequeceId() { 187 return mSubsequeceId; 188 } 189 190 /** 191 * Returns the frame number for this request. 192 */ getFrameNumber()193 public long getFrameNumber() { 194 return mFrameNumber; 195 } 196 197 /** 198 * Returns the contained request. 199 */ getRequest()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 */ getHolderTargets()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 */ hasJpegTargets()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 */ hasPreviewTargets()222 public boolean hasPreviewTargets(){ 223 return mNumPreviewTargets > 0; 224 } 225 226 /** 227 * Return the number of jpeg-type surfaces targeted by this request. 228 */ numJpegTargets()229 public int numJpegTargets() { 230 return mNumJpegTargets; 231 } 232 233 /** 234 * Return the number of non-jpeg-type surfaces targeted by this request. 235 */ numPreviewTargets()236 public int numPreviewTargets() { 237 return mNumPreviewTargets; 238 } 239 240 /** 241 * Mark this request as failed. 242 */ failRequest()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 */ requestFailed()251 public boolean requestFailed() { 252 return mFailed; 253 } 254 255 } 256