Merge changes I20310606,Ic23b7fb2 into pi-dev

* changes:
  Camera: more external camera CTS fix
  Camera: various external camera CTS fixes
This commit is contained in:
TreeHugger Robot
2018-03-19 20:06:27 +00:00
committed by Android (Google) Code Review
4 changed files with 79 additions and 50 deletions

View File

@@ -983,15 +983,15 @@ bool ExifUtilsImpl::setFromMetadata(const CameraMetadata& metadata,
camera_metadata_ro_entry entry = metadata.find(ANDROID_LENS_FOCAL_LENGTH);
if (entry.count) {
focal_length = entry.data.f[0];
if (!setFocalLength(
static_cast<uint32_t>(focal_length * kRationalPrecision),
kRationalPrecision)) {
ALOGE("%s: setting focal length failed.", __FUNCTION__);
return false;
}
} else {
ALOGE("%s: Cannot find focal length in metadata.", __FUNCTION__);
return false;
}
if (!setFocalLength(
static_cast<uint32_t>(focal_length * kRationalPrecision),
kRationalPrecision)) {
ALOGE("%s: setting focal length failed.", __FUNCTION__);
return false;
ALOGV("%s: Cannot find focal length in metadata.", __FUNCTION__);
}
if (metadata.exists(ANDROID_JPEG_GPS_COORDINATES)) {

View File

@@ -284,13 +284,6 @@ status_t ExternalCameraDevice::initDefaultCharsKeys(
const int32_t jpegMaxSize = mCfg.maxJpegBufSize;
UPDATE(ANDROID_JPEG_MAX_SIZE, &jpegMaxSize, 1);
const uint8_t jpegQuality = 90;
UPDATE(ANDROID_JPEG_QUALITY, &jpegQuality, 1);
UPDATE(ANDROID_JPEG_THUMBNAIL_QUALITY, &jpegQuality, 1);
const int32_t jpegOrientation = 0;
UPDATE(ANDROID_JPEG_ORIENTATION, &jpegOrientation, 1);
// android.lens
const uint8_t focusDistanceCalibration =
ANDROID_LENS_INFO_FOCUS_DISTANCE_CALIBRATION_UNCALIBRATED;
@@ -322,7 +315,6 @@ status_t ExternalCameraDevice::initDefaultCharsKeys(
// This means pipeline latency of X frame intervals. The maximum number is 4.
const uint8_t requestPipelineMaxDepth = 4;
UPDATE(ANDROID_REQUEST_PIPELINE_MAX_DEPTH, &requestPipelineMaxDepth, 1);
UPDATE(ANDROID_REQUEST_PIPELINE_DEPTH, &requestPipelineMaxDepth, 1);
// Three numbers represent the maximum numbers of different types of output
// streams simultaneously. The types are raw sensor, processed (but not
@@ -355,7 +347,6 @@ status_t ExternalCameraDevice::initDefaultCharsKeys(
ANDROID_SENSOR_TEST_PATTERN_MODE_OFF};
UPDATE(ANDROID_SENSOR_AVAILABLE_TEST_PATTERN_MODES, testPatternModes,
ARRAY_SIZE(testPatternModes));
UPDATE(ANDROID_SENSOR_TEST_PATTERN_MODE, &testPatternModes[0], 1);
const uint8_t timestampSource = ANDROID_SENSOR_INFO_TIMESTAMP_SOURCE_UNKNOWN;
UPDATE(ANDROID_SENSOR_INFO_TIMESTAMP_SOURCE, &timestampSource, 1);
@@ -576,7 +567,6 @@ status_t ExternalCameraDevice::initOutputCharsKeys(int fd,
std::vector<int32_t> streamConfigurations;
std::vector<int64_t> minFrameDurations;
std::vector<int64_t> stallDurations;
int64_t maxFrameDuration = 0;
int32_t maxFps = std::numeric_limits<int32_t>::min();
int32_t minFps = std::numeric_limits<int32_t>::max();
std::set<int32_t> framerates;
@@ -604,9 +594,6 @@ status_t ExternalCameraDevice::initOutputCharsKeys(int fd,
if (frameDuration < minFrameDuration) {
minFrameDuration = frameDuration;
}
if (frameDuration > maxFrameDuration) {
maxFrameDuration = frameDuration;
}
int32_t frameRateInt = static_cast<int32_t>(fr.getDouble());
if (minFps > frameRateInt) {
minFps = frameRateInt;
@@ -639,14 +626,15 @@ status_t ExternalCameraDevice::initOutputCharsKeys(int fd,
}
std::vector<int32_t> fpsRanges;
// Variable range
fpsRanges.push_back(minFps);
fpsRanges.push_back(maxFps);
// Fixed ranges
// FPS ranges
for (const auto& framerate : framerates) {
fpsRanges.push_back(framerate);
// Empirical: webcams often have close to 2x fps error and cannot support fixed fps range
fpsRanges.push_back(framerate / 2);
fpsRanges.push_back(framerate);
}
minFps /= 2;
int64_t maxFrameDuration = 1000000000LL / minFps;
UPDATE(ANDROID_CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES, fpsRanges.data(),
fpsRanges.size());

View File

@@ -47,6 +47,9 @@ static constexpr size_t kMetadataMsgQueueSize = 1 << 18 /* 256kB */;
const int kBadFramesAfterStreamOn = 1; // drop x frames after streamOn to get rid of some initial
// bad frames. TODO: develop a better bad frame detection
// method
constexpr int MAX_RETRY = 15; // Allow retry some ioctl failures a few times to account for some
// webcam showing temporarily ioctl failures.
constexpr int IOCTL_RETRY_SLEEP_US = 33000; // 33ms * MAX_RETRY = 5 seconds
bool tryLock(Mutex& mutex)
{
@@ -1480,6 +1483,7 @@ int ExternalCameraDeviceSession::OutputThread::createJpegLocked(
int jpegQuality, thumbQuality;
Size thumbSize;
bool outputThumbnail = true;
if (req->setting.exists(ANDROID_JPEG_QUALITY)) {
camera_metadata_entry entry =
@@ -1505,6 +1509,9 @@ int ExternalCameraDeviceSession::OutputThread::createJpegLocked(
thumbSize = Size { static_cast<uint32_t>(entry.data.i32[0]),
static_cast<uint32_t>(entry.data.i32[1])
};
if (thumbSize.width == 0 && thumbSize.height == 0) {
outputThumbnail = false;
}
} else {
return lfail(
"%s: ANDROID_JPEG_THUMBNAIL_SIZE not set", __FUNCTION__);
@@ -1532,14 +1539,16 @@ int ExternalCameraDeviceSession::OutputThread::createJpegLocked(
/* Hold actual thumbnail and main image code sizes */
size_t thumbCodeSize = 0, jpegCodeSize = 0;
/* Temporary thumbnail code buffer */
std::vector<uint8_t> thumbCode(maxThumbCodeSize);
std::vector<uint8_t> thumbCode(outputThumbnail ? maxThumbCodeSize : 0);
YCbCrLayout yu12Thumb;
ret = cropAndScaleThumbLocked(mYu12Frame, thumbSize, &yu12Thumb);
if (outputThumbnail) {
ret = cropAndScaleThumbLocked(mYu12Frame, thumbSize, &yu12Thumb);
if (ret != 0) {
return lfail(
"%s: crop and scale thumbnail failed!", __FUNCTION__);
if (ret != 0) {
return lfail(
"%s: crop and scale thumbnail failed!", __FUNCTION__);
}
}
/* Scale and crop main jpeg */
@@ -1550,12 +1559,14 @@ int ExternalCameraDeviceSession::OutputThread::createJpegLocked(
}
/* Encode the thumbnail image */
ret = encodeJpegYU12(thumbSize, yu12Thumb,
thumbQuality, 0, 0,
&thumbCode[0], maxThumbCodeSize, thumbCodeSize);
if (outputThumbnail) {
ret = encodeJpegYU12(thumbSize, yu12Thumb,
thumbQuality, 0, 0,
&thumbCode[0], maxThumbCodeSize, thumbCodeSize);
if (ret != 0) {
return lfail("%s: encodeJpegYU12 failed with %d",__FUNCTION__, ret);
if (ret != 0) {
return lfail("%s: thumbnail encodeJpegYU12 failed with %d",__FUNCTION__, ret);
}
}
/* Combine camera characteristics with request settings to form EXIF
@@ -1570,11 +1581,7 @@ int ExternalCameraDeviceSession::OutputThread::createJpegLocked(
utils->setFromMetadata(meta, jpegSize.width, jpegSize.height);
/* Check if we made a non-zero-sized thumbnail. Currently not possible
* that we got this far and the code is size 0, but if this code moves
* around it might become relevant again */
ret = utils->generateApp1(thumbCodeSize ? &thumbCode[0] : 0, thumbCodeSize);
ret = utils->generateApp1(outputThumbnail ? &thumbCode[0] : 0, thumbCodeSize);
if (!ret) {
return lfail("%s: generating APP1 failed", __FUNCTION__);
@@ -2109,8 +2116,20 @@ int ExternalCameraDeviceSession::configureV4l2StreamLocked(
fmt.fmt.pix.pixelformat = v4l2Fmt.fourcc;
ret = TEMP_FAILURE_RETRY(ioctl(mV4l2Fd.get(), VIDIOC_S_FMT, &fmt));
if (ret < 0) {
ALOGE("%s: S_FMT ioctl failed: %s", __FUNCTION__, strerror(errno));
return -errno;
int numAttempt = 0;
while (ret < 0) {
ALOGW("%s: VIDIOC_S_FMT failed, wait 33ms and try again", __FUNCTION__);
usleep(IOCTL_RETRY_SLEEP_US); // sleep 100 ms and try again
ret = TEMP_FAILURE_RETRY(ioctl(mV4l2Fd.get(), VIDIOC_S_FMT, &fmt));
if (numAttempt == MAX_RETRY) {
break;
}
numAttempt++;
}
if (ret < 0) {
ALOGE("%s: S_FMT ioctl failed: %s", __FUNCTION__, strerror(errno));
return -errno;
}
}
if (v4l2Fmt.width != fmt.fmt.pix.width || v4l2Fmt.height != fmt.fmt.pix.height ||
@@ -2199,9 +2218,22 @@ int ExternalCameraDeviceSession::configureV4l2StreamLocked(
// VIDIOC_STREAMON: start streaming
v4l2_buf_type capture_type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
if (TEMP_FAILURE_RETRY(ioctl(mV4l2Fd.get(), VIDIOC_STREAMON, &capture_type)) < 0) {
ALOGE("%s: VIDIOC_STREAMON failed: %s", __FUNCTION__, strerror(errno));
return -errno;
ret = TEMP_FAILURE_RETRY(ioctl(mV4l2Fd.get(), VIDIOC_STREAMON, &capture_type));
if (ret < 0) {
int numAttempt = 0;
while (ret < 0) {
ALOGW("%s: VIDIOC_STREAMON failed, wait 33ms and try again", __FUNCTION__);
usleep(IOCTL_RETRY_SLEEP_US); // sleep 100 ms and try again
ret = TEMP_FAILURE_RETRY(ioctl(mV4l2Fd.get(), VIDIOC_STREAMON, &capture_type));
if (numAttempt == MAX_RETRY) {
break;
}
numAttempt++;
}
if (ret < 0) {
ALOGE("%s: VIDIOC_STREAMON ioctl failed: %s", __FUNCTION__, strerror(errno));
return -errno;
}
}
// Swallow first few frames after streamOn to account for bad frames from some devices
@@ -2220,6 +2252,8 @@ int ExternalCameraDeviceSession::configureV4l2StreamLocked(
}
}
ALOGI("%s: start V4L2 streaming %dx%d@%ffps",
__FUNCTION__, v4l2Fmt.width, v4l2Fmt.height, fps);
mV4l2StreamingFmt = v4l2Fmt;
mV4l2Streaming = true;
return OK;
@@ -2388,6 +2422,7 @@ Status ExternalCameraDeviceSession::configureStreams(
uint32_t maxDim = 0;
for (const auto& stream : config.streams) {
float aspectRatio = ASPECT_RATIO(stream);
ALOGI("%s: request stream %dx%d", __FUNCTION__, stream.width, stream.height);
if ((mCroppingType == VERTICAL && aspectRatio < desiredAr) ||
(mCroppingType == HORIZONTAL && aspectRatio > desiredAr)) {
desiredAr = aspectRatio;
@@ -2572,6 +2607,9 @@ status_t ExternalCameraDeviceSession::initDefaultRequests() {
const uint8_t nrMode = ANDROID_NOISE_REDUCTION_MODE_OFF;
UPDATE(md, ANDROID_NOISE_REDUCTION_MODE, &nrMode, 1);
const int32_t testPatternModes = ANDROID_SENSOR_TEST_PATTERN_MODE_OFF;
UPDATE(md, ANDROID_SENSOR_TEST_PATTERN_MODE, &testPatternModes, 1);
const uint8_t fdMode = ANDROID_STATISTICS_FACE_DETECT_MODE_OFF;
UPDATE(md, ANDROID_STATISTICS_FACE_DETECT_MODE, &fdMode, 1);
@@ -2596,7 +2634,7 @@ status_t ExternalCameraDeviceSession::initDefaultRequests() {
}
}
int32_t defaultFramerate = support30Fps ? 30 : maxFps;
int32_t defaultFpsRange[] = {defaultFramerate, defaultFramerate};
int32_t defaultFpsRange[] = {defaultFramerate / 2, defaultFramerate};
UPDATE(md, ANDROID_CONTROL_AE_TARGET_FPS_RANGE, defaultFpsRange, ARRAY_SIZE(defaultFpsRange));
uint8_t antibandingMode = ANDROID_CONTROL_AE_ANTIBANDING_MODE_AUTO;
@@ -2691,6 +2729,10 @@ status_t ExternalCameraDeviceSession::fillCaptureResult(
const uint8_t flashState = ANDROID_FLASH_STATE_UNAVAILABLE;
UPDATE(md, ANDROID_FLASH_STATE, &flashState, 1);
// This means pipeline latency of X frame intervals. The maximum number is 4.
const uint8_t requestPipelineMaxDepth = 4;
UPDATE(md, ANDROID_REQUEST_PIPELINE_DEPTH, &requestPipelineMaxDepth, 1);
// android.scaler
const int32_t crop_region[] = {
active_array_size.data.i32[0], active_array_size.data.i32[1],

View File

@@ -283,9 +283,8 @@ ExternalCameraConfig::ExternalCameraConfig() :
numVideoBuffers(kDefaultNumVideoBuffer),
numStillBuffers(kDefaultNumStillBuffer) {
fpsLimits.push_back({/*Size*/{ 640, 480}, /*FPS upper bound*/30.0});
fpsLimits.push_back({/*Size*/{1280, 720}, /*FPS upper bound*/15.0});
fpsLimits.push_back({/*Size*/{1920, 1080}, /*FPS upper bound*/10.0});
fpsLimits.push_back({/*Size*/{4096, 3072}, /*FPS upper bound*/5.0});
fpsLimits.push_back({/*Size*/{1280, 720}, /*FPS upper bound*/7.5});
fpsLimits.push_back({/*Size*/{1920, 1080}, /*FPS upper bound*/5.0});
}