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