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