am f1aea7f9: Merge "camera2: Add jpeg metadata for LEGACY shim." into lmp-dev

* commit 'f1aea7f92498e3f107350c6d1a41e211d1c764a3':
  camera2: Add jpeg metadata for LEGACY shim.
This commit is contained in:
Ruben Brunk
2014-08-16 00:15:23 +00:00
committed by Android Git Automerger
7 changed files with 147 additions and 7 deletions

View File

@@ -510,4 +510,6 @@ public class LegacyCameraDevice implements AutoCloseable {
/*out*/int[/*2*/] dimens);
private static native int nativeSetNextTimestamp(Surface surface, long timestamp);
static native int nativeGetJpegFooterSize();
}

View File

@@ -33,6 +33,7 @@ import android.hardware.camera2.params.StreamConfigurationDuration;
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;
@@ -40,6 +41,8 @@ import android.util.SizeF;
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.*;
@@ -187,8 +190,10 @@ public class LegacyMetadataMapper {
* flash.*
*/
mapFlash(m, p);
// TODO: map other fields
/*
* jpeg.*
*/
mapJpeg(m, p);
/*
* scaler.*
@@ -595,6 +600,16 @@ public class LegacyMetadataMapper {
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

View File

@@ -24,6 +24,7 @@ import android.hardware.camera2.CaptureRequest;
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;
@@ -44,6 +45,8 @@ public class LegacyRequestMapper {
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}.
*
@@ -350,6 +353,70 @@ public class LegacyRequestMapper {
+ 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) {

View File

@@ -28,6 +28,7 @@ import android.hardware.camera2.legacy.ParameterUtils.ZoomData;
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;
@@ -250,6 +251,29 @@ public class LegacyResultMapper {
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;
}

View File

@@ -252,6 +252,33 @@ public class ParameterUtils {
return sizes;
}
/**
* 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.
*/

View File

@@ -190,7 +190,8 @@ public class RequestThreadManager {
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);
@@ -665,10 +666,6 @@ public class RequestThreadManager {
}
mReceivedJpeg.close();
doJpegCapturePrepare(holder);
if (!mReceivedJpeg.block(JPEG_FRAME_TIMEOUT)) {
// TODO: report error to CameraDevice
Log.e(TAG, "Hit timeout for jpeg callback!");
}
}
/*

View File

@@ -633,6 +633,11 @@ static jint LegacyCameraDevice_nativeSetNextTimestamp(JNIEnv* env, jobject thiz,
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[] = {
@@ -666,6 +671,9 @@ 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