/*out*/int[/*2*/] dimens);
private static native int nativeSetNextTimestamp(Surface surface, long timestamp);
+
+ static native int nativeGetJpegFooterSize();
}
import android.hardware.camera2.utils.ArrayUtils;
import android.hardware.camera2.utils.ListUtils;
import android.hardware.camera2.utils.ParamsUtils;
+import android.hardware.camera2.utils.SizeAreaComparator;
import android.util.Log;
import android.util.Range;
import android.util.Size;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collections;
+import java.util.Comparator;
import java.util.List;
import static com.android.internal.util.Preconditions.*;
* flash.*
*/
mapFlash(m, p);
-
- // TODO: map other fields
+ /*
+ * jpeg.*
+ */
+ mapJpeg(m, p);
/*
* scaler.*
m.set(FLASH_INFO_AVAILABLE, flashAvailable);
}
+ private static void mapJpeg(CameraMetadataNative m, Camera.Parameters p) {
+ List<Camera.Size> thumbnailSizes = p.getSupportedJpegThumbnailSizes();
+
+ if (thumbnailSizes != null) {
+ Size[] sizes = convertSizeListToArray(thumbnailSizes);
+ Arrays.sort(sizes, new SizeAreaComparator());
+ m.set(JPEG_AVAILABLE_THUMBNAIL_SIZES, sizes);
+ }
+ }
+
private static void mapRequest(CameraMetadataNative m, Parameters p) {
/*
* request.availableCapabilities
import android.hardware.camera2.params.MeteringRectangle;
import android.hardware.camera2.utils.ListUtils;
import android.hardware.camera2.utils.ParamsUtils;
+import android.location.Location;
import android.util.Log;
import android.util.Range;
import android.util.Size;
private static final String TAG = "LegacyRequestMapper";
private static final boolean VERBOSE = Log.isLoggable(TAG, Log.VERBOSE);
+ private static final byte DEFAULT_JPEG_QUALITY = 85;
+
/**
* Set the legacy parameters using the {@link LegacyRequest legacy request}.
*
+ testPatternMode + "; only OFF is supported");
}
}
+
+ /*
+ * jpeg.*
+ */
+
+ // jpeg.gpsLocation
+ {
+ Location location = request.get(JPEG_GPS_LOCATION);
+ if (location != null) {
+ if (checkForCompleteGpsData(location)) {
+ params.setGpsAltitude(location.getAltitude());
+ params.setGpsLatitude(location.getLatitude());
+ params.setGpsLongitude(location.getLongitude());
+ params.setGpsProcessingMethod(location.getProvider().toUpperCase());
+ params.setGpsTimestamp(location.getTime());
+ } else {
+ Log.w(TAG, "Incomplete GPS parameters provided in location " + location);
+ }
+ } else {
+ params.removeGpsData();
+ }
+ }
+
+ // jpeg.orientation
+ {
+ int orientation = characteristics.get(CameraCharacteristics.SENSOR_ORIENTATION);
+ params.setRotation(ParamsUtils.getOrDefault(request, JPEG_ORIENTATION, orientation));
+ }
+
+ // jpeg.quality
+ {
+ params.setJpegQuality(0xFF & ParamsUtils.getOrDefault(request, JPEG_QUALITY,
+ DEFAULT_JPEG_QUALITY));
+ }
+
+ // jpeg.thumbnailQuality
+ {
+ params.setJpegQuality(0xFF & ParamsUtils.getOrDefault(request, JPEG_THUMBNAIL_QUALITY,
+ DEFAULT_JPEG_QUALITY));
+ }
+
+ // jpeg.thumbnailSize
+ {
+ List<Camera.Size> sizes = params.getSupportedJpegThumbnailSizes();
+
+ if (sizes != null && sizes.size() > 0) {
+ Size s = request.get(JPEG_THUMBNAIL_SIZE);
+ boolean invalidSize = (s == null) ? false : !ParameterUtils.containsSize(sizes,
+ s.getWidth(), s.getHeight());
+ if (invalidSize) {
+ Log.w(TAG, "Invalid JPEG thumbnail size set " + s + ", skipping thumbnail...");
+ }
+ if (s == null || invalidSize) {
+ // (0,0) = "no thumbnail" in Camera API 1
+ params.setJpegThumbnailSize(/*width*/0, /*height*/0);
+ } else {
+ params.setJpegThumbnailSize(s.getWidth(), s.getHeight());
+ }
+ }
+ }
+ }
+
+ private static boolean checkForCompleteGpsData(Location location) {
+ return location != null && location.getProvider() != null && location.getTime() != 0;
}
static int filterSupportedCaptureIntent(int captureIntent) {
import android.hardware.camera2.params.MeteringRectangle;
import android.hardware.camera2.utils.ListUtils;
import android.hardware.camera2.utils.ParamsUtils;
+import android.location.Location;
import android.util.Log;
import android.util.Size;
result.set(SENSOR_TEST_PATTERN_MODE, SENSOR_TEST_PATTERN_MODE_OFF);
}
+ /*
+ * jpeg
+ */
+ // jpeg.gpsLocation
+ result.set(JPEG_GPS_LOCATION, request.get(CaptureRequest.JPEG_GPS_LOCATION));
+
+ // jpeg.orientation
+ result.set(JPEG_ORIENTATION, request.get(CaptureRequest.JPEG_ORIENTATION));
+
+ // jpeg.quality
+ result.set(JPEG_QUALITY, (byte) params.getJpegQuality());
+
+ // jpeg.thumbnailQuality
+ result.set(JPEG_THUMBNAIL_QUALITY, (byte) params.getJpegThumbnailQuality());
+
+ // jpeg.thumbnailSize
+ Camera.Size s = params.getJpegThumbnailSize();
+ if (s != null) {
+ result.set(JPEG_THUMBNAIL_SIZE, ParameterUtils.convertSize(s));
+ } else {
+ Log.w(TAG, "Null thumbnail size received from parameters.");
+ }
+
// TODO: Remaining result metadata tags conversions.
return result;
}
}
/**
+ * Convert a camera API1 list of sizes into an array of sizes
+ */
+ public static Size[] convertSizeListToArray(List<Camera.Size> sizeList) {
+ checkNotNull(sizeList, "sizeList must not be null");
+
+ Size[] array = new Size[sizeList.size()];
+ int ctr = 0;
+ for (Camera.Size s : sizeList) {
+ array[ctr++] = new Size(s.width, s.height);
+ }
+ return array;
+ }
+
+ /**
+ * Check if the camera API1 list of sizes contains a size with the given dimens.
+ */
+ public static boolean containsSize(List<Camera.Size> sizeList, int width, int height) {
+ checkNotNull(sizeList, "sizeList must not be null");
+ for (Camera.Size s : sizeList) {
+ if (s.height == height && s.width == width) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
* Returns the largest supported picture size, as compared by its area.
*/
public static Size getLargestSupportedJpegSizeByArea(Camera.Parameters params) {
try {
if (RequestHolder.jpegType(s)) {
Log.i(TAG, "Producing jpeg buffer...");
- LegacyCameraDevice.setSurfaceDimens(s, data.length, /*height*/1);
+ LegacyCameraDevice.setSurfaceDimens(s, data.length +
+ LegacyCameraDevice.nativeGetJpegFooterSize(), /*height*/1);
LegacyCameraDevice.setNextTimestamp(s, timestamp);
LegacyCameraDevice.produceFrame(s, data, data.length, /*height*/1,
CameraMetadataNative.NATIVE_JPEG_FORMAT);
}
mReceivedJpeg.close();
doJpegCapturePrepare(holder);
- if (!mReceivedJpeg.block(JPEG_FRAME_TIMEOUT)) {
- // TODO: report error to CameraDevice
- Log.e(TAG, "Hit timeout for jpeg callback!");
- }
}
/*
return NO_ERROR;
}
+static jint LegacyCameraDevice_nativeGetJpegFooterSize(JNIEnv* env, jobject thiz) {
+ ALOGV("nativeGetJpegFooterSize");
+ return static_cast<jint>(sizeof(struct camera3_jpeg_blob));
+}
+
} // extern "C"
static JNINativeMethod gCameraDeviceMethods[] = {
{ "nativeSetNextTimestamp",
"(Landroid/view/Surface;J)I",
(void *)LegacyCameraDevice_nativeSetNextTimestamp },
+ { "nativeGetJpegFooterSize",
+ "()I",
+ (void *)LegacyCameraDevice_nativeGetJpegFooterSize },
};
// Get all the required offsets in java class and register native functions