Merge "camera3: Don't eagerly finish configuring bidi streams more than once" into jb-mr2-dev
diff --git a/include/media/AudioTrack.h b/include/media/AudioTrack.h
index db5a7ab..64f82bb 100644
--- a/include/media/AudioTrack.h
+++ b/include/media/AudioTrack.h
@@ -599,6 +599,7 @@
int mPreviousPriority; // before start()
SchedPolicy mPreviousSchedulingGroup;
AudioTrackClientProxy* mProxy;
+ bool mAwaitBoost; // thread should wait for priority boost before running
};
class TimedAudioTrack : public AudioTrack
diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp
index 1bd839f..7eeb4f8 100644
--- a/media/libmedia/AudioTrack.cpp
+++ b/media/libmedia/AudioTrack.cpp
@@ -893,9 +893,11 @@
ALOGW("Requested frameCount %u but received frameCount %u", frameCount, temp);
}
frameCount = temp;
+ mAwaitBoost = false;
if (flags & AUDIO_OUTPUT_FLAG_FAST) {
if (trackFlags & IAudioFlinger::TRACK_FAST) {
ALOGV("AUDIO_OUTPUT_FLAG_FAST successful; frameCount %u", frameCount);
+ mAwaitBoost = true;
} else {
ALOGV("AUDIO_OUTPUT_FLAG_FAST denied by server; frameCount %u", frameCount);
// once denied, do not request again if IAudioTrack is re-created
@@ -1219,6 +1221,25 @@
size_t writtenSize;
mLock.lock();
+ if (mAwaitBoost) {
+ mAwaitBoost = false;
+ mLock.unlock();
+ static const int32_t kMaxTries = 5;
+ int32_t tryCounter = kMaxTries;
+ uint32_t pollUs = 10000;
+ do {
+ int policy = sched_getscheduler(0);
+ if (policy == SCHED_FIFO || policy == SCHED_RR) {
+ break;
+ }
+ usleep(pollUs);
+ pollUs <<= 1;
+ } while (tryCounter-- > 0);
+ if (tryCounter < 0) {
+ ALOGE("did not receive expected priority boost on time");
+ }
+ return true;
+ }
// acquire a strong reference on the IMemory and IAudioTrack so that they cannot be destroyed
// while we are accessing the cblk
sp<IAudioTrack> audioTrack = mAudioTrack;
diff --git a/media/libstagefright/codecs/flac/enc/SoftFlacEncoder.cpp b/media/libstagefright/codecs/flac/enc/SoftFlacEncoder.cpp
index 233aed3..e64fe72 100644
--- a/media/libstagefright/codecs/flac/enc/SoftFlacEncoder.cpp
+++ b/media/libstagefright/codecs/flac/enc/SoftFlacEncoder.cpp
@@ -109,7 +109,7 @@
def.eDir = OMX_DirInput;
def.nBufferCountMin = kNumBuffers;// TODO verify that 1 is enough
def.nBufferCountActual = def.nBufferCountMin;
- def.nBufferSize = kMaxNumSamplesPerFrame * sizeof(int16_t) * 2;
+ def.nBufferSize = kMaxInputBufferSize;
def.bEnabled = OMX_TRUE;
def.bPopulated = OMX_FALSE;
def.eDomain = OMX_PortDomainAudio;
@@ -234,6 +234,22 @@
return OMX_ErrorNone;
}
+ case OMX_IndexParamPortDefinition:
+ {
+ OMX_PARAM_PORTDEFINITIONTYPE *defParams =
+ (OMX_PARAM_PORTDEFINITIONTYPE *)params;
+
+ if (defParams->nPortIndex == 0) {
+ if (defParams->nBufferSize > kMaxInputBufferSize) {
+ ALOGE("Input buffer size must be at most %zu bytes",
+ kMaxInputBufferSize);
+ return OMX_ErrorUnsupportedSetting;
+ }
+ }
+
+ // fall through
+ }
+
default:
ALOGV("SoftFlacEncoder::internalSetParameter(default)");
return SimpleSoftOMXComponent::internalSetParameter(index, params);
@@ -273,7 +289,7 @@
return;
}
- if (inHeader->nFilledLen > kMaxNumSamplesPerFrame * sizeof(FLAC__int32) * 2) {
+ if (inHeader->nFilledLen > kMaxInputBufferSize) {
ALOGE("input buffer too large (%ld).", inHeader->nFilledLen);
mSignalledError = true;
notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL);
@@ -290,6 +306,7 @@
const unsigned nbInputSamples = inHeader->nFilledLen / 2;
const OMX_S16 * const pcm16 = reinterpret_cast<OMX_S16 *>(inHeader->pBuffer);
+ CHECK_LE(nbInputSamples, 2 * kMaxNumSamplesPerFrame);
for (unsigned i=0 ; i < nbInputSamples ; i++) {
mInputBufferPcm32[i] = (FLAC__int32) pcm16[i];
}
diff --git a/media/libstagefright/codecs/flac/enc/SoftFlacEncoder.h b/media/libstagefright/codecs/flac/enc/SoftFlacEncoder.h
index 1e0148a..97361fa 100644
--- a/media/libstagefright/codecs/flac/enc/SoftFlacEncoder.h
+++ b/media/libstagefright/codecs/flac/enc/SoftFlacEncoder.h
@@ -52,6 +52,7 @@
enum {
kNumBuffers = 2,
kMaxNumSamplesPerFrame = 1152,
+ kMaxInputBufferSize = kMaxNumSamplesPerFrame * sizeof(int16_t) * 2,
kMaxOutputBufferSize = 65536, //TODO check if this can be reduced
};
diff --git a/media/libstagefright/mpeg2ts/ATSParser.cpp b/media/libstagefright/mpeg2ts/ATSParser.cpp
index c12572f..9850a46 100644
--- a/media/libstagefright/mpeg2ts/ATSParser.cpp
+++ b/media/libstagefright/mpeg2ts/ATSParser.cpp
@@ -1059,7 +1059,7 @@
ssize_t sectionIndex = mPSISections.indexOfKey(PID);
if (sectionIndex >= 0) {
- const sp<PSISection> §ion = mPSISections.valueAt(sectionIndex);
+ sp<PSISection> section = mPSISections.valueAt(sectionIndex);
if (payload_unit_start_indicator) {
CHECK(section->isEmpty());
@@ -1068,7 +1068,6 @@
br->skipBits(skip * 8);
}
-
CHECK((br->numBitsLeft() % 8) == 0);
status_t err = section->append(br->data(), br->numBitsLeft() / 8);
@@ -1103,10 +1102,13 @@
if (!handled) {
mPSISections.removeItem(PID);
+ section.clear();
}
}
- section->clear();
+ if (section != NULL) {
+ section->clear();
+ }
return OK;
}
diff --git a/media/libstagefright/wifi-display/VideoFormats.cpp b/media/libstagefright/wifi-display/VideoFormats.cpp
index d171c6f..da557f7 100644
--- a/media/libstagefright/wifi-display/VideoFormats.cpp
+++ b/media/libstagefright/wifi-display/VideoFormats.cpp
@@ -249,11 +249,20 @@
mNativeIndex = native >> 3;
mNativeType = (ResolutionType)(native & 7);
+ bool success;
if (mNativeType >= kNumResolutionTypes) {
- return false;
+ success = false;
+ } else {
+ success = GetConfiguration(
+ mNativeType, mNativeIndex, NULL, NULL, NULL, NULL);
}
- return GetConfiguration(mNativeType, mNativeIndex, NULL, NULL, NULL, NULL);
+ if (!success) {
+ ALOGW("sink advertised an illegal native resolution, fortunately "
+ "this value is ignored for the time being...");
+ }
+
+ return true;
}
AString VideoFormats::getFormatSpec(bool forM4Message) const {
diff --git a/media/libstagefright/wifi-display/source/Converter.cpp b/media/libstagefright/wifi-display/source/Converter.cpp
index 0a8462c..5344623 100644
--- a/media/libstagefright/wifi-display/source/Converter.cpp
+++ b/media/libstagefright/wifi-display/source/Converter.cpp
@@ -649,6 +649,13 @@
&bufferIndex, &offset, &size, &timeUs, &flags);
if (err != OK) {
+ if (err == INFO_FORMAT_CHANGED) {
+ continue;
+ } else if (err == INFO_OUTPUT_BUFFERS_CHANGED) {
+ mEncoder->getOutputBuffers(&mEncoderOutputBuffers);
+ continue;
+ }
+
if (err == -EAGAIN) {
err = OK;
}
diff --git a/services/audioflinger/FastMixer.cpp b/services/audioflinger/FastMixer.cpp
index 24a6dfe..21df1d7 100644
--- a/services/audioflinger/FastMixer.cpp
+++ b/services/audioflinger/FastMixer.cpp
@@ -170,6 +170,10 @@
if (old <= 0) {
__futex_syscall4(coldFutexAddr, FUTEX_WAIT_PRIVATE, old - 1, NULL);
}
+ int policy = sched_getscheduler(0);
+ if (!(policy == SCHED_FIFO || policy == SCHED_RR)) {
+ ALOGE("did not receive expected priority boost");
+ }
// This may be overly conservative; there could be times that the normal mixer
// requests such a brief cold idle that it doesn't require resetting this flag.
isWarm = false;
diff --git a/services/audioflinger/ISchedulingPolicyService.cpp b/services/audioflinger/ISchedulingPolicyService.cpp
index 218aa6b..0079968 100644
--- a/services/audioflinger/ISchedulingPolicyService.cpp
+++ b/services/audioflinger/ISchedulingPolicyService.cpp
@@ -37,14 +37,15 @@
{
}
- virtual int requestPriority(int32_t pid, int32_t tid, int32_t prio)
+ virtual int requestPriority(int32_t pid, int32_t tid, int32_t prio, bool asynchronous)
{
Parcel data, reply;
data.writeInterfaceToken(ISchedulingPolicyService::getInterfaceDescriptor());
data.writeInt32(pid);
data.writeInt32(tid);
data.writeInt32(prio);
- remote()->transact(REQUEST_PRIORITY_TRANSACTION, data, &reply, IBinder::FLAG_ONEWAY);
+ uint32_t flags = asynchronous ? IBinder::FLAG_ONEWAY : 0;
+ remote()->transact(REQUEST_PRIORITY_TRANSACTION, data, &reply, flags);
// fail on exception
if (reply.readExceptionCode() != 0) return -1;
return reply.readInt32();
diff --git a/services/audioflinger/ISchedulingPolicyService.h b/services/audioflinger/ISchedulingPolicyService.h
index a38e67e..b94b191 100644
--- a/services/audioflinger/ISchedulingPolicyService.h
+++ b/services/audioflinger/ISchedulingPolicyService.h
@@ -27,7 +27,7 @@
DECLARE_META_INTERFACE(SchedulingPolicyService);
virtual int requestPriority(/*pid_t*/int32_t pid, /*pid_t*/int32_t tid,
- int32_t prio) = 0;
+ int32_t prio, bool asynchronous) = 0;
};
diff --git a/services/audioflinger/SchedulingPolicyService.cpp b/services/audioflinger/SchedulingPolicyService.cpp
index 59cc99a..36e62e9 100644
--- a/services/audioflinger/SchedulingPolicyService.cpp
+++ b/services/audioflinger/SchedulingPolicyService.cpp
@@ -25,7 +25,7 @@
static const String16 _scheduling_policy("scheduling_policy");
static Mutex sMutex;
-int requestPriority(pid_t pid, pid_t tid, int32_t prio)
+int requestPriority(pid_t pid, pid_t tid, int32_t prio, bool asynchronous)
{
// FIXME merge duplicated code related to service lookup, caching, and error recovery
sp<ISchedulingPolicyService> sps;
@@ -46,7 +46,7 @@
}
sleep(1);
}
- return sps->requestPriority(pid, tid, prio);
+ return sps->requestPriority(pid, tid, prio, asynchronous);
}
} // namespace android
diff --git a/services/audioflinger/SchedulingPolicyService.h b/services/audioflinger/SchedulingPolicyService.h
index 7ac8454..a9870d4 100644
--- a/services/audioflinger/SchedulingPolicyService.h
+++ b/services/audioflinger/SchedulingPolicyService.h
@@ -21,7 +21,10 @@
// Request elevated priority for thread tid, whose thread group leader must be pid.
// The priority parameter is currently restricted to either 1 or 2.
-int requestPriority(pid_t pid, pid_t tid, int32_t prio);
+// The asynchronous parameter should be 'true' to return immediately,
+// after the request is enqueued but not necessarily executed.
+// The default value 'false' means to return after request has been enqueued and executed.
+int requestPriority(pid_t pid, pid_t tid, int32_t prio, bool asynchronous = false);
} // namespace android
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index 47ca100..539bb4f 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -373,7 +373,9 @@
switch(event->type()) {
case CFG_EVENT_PRIO: {
PrioConfigEvent *prioEvent = static_cast<PrioConfigEvent *>(event);
- int err = requestPriority(prioEvent->pid(), prioEvent->tid(), prioEvent->prio());
+ // FIXME Need to understand why this has be done asynchronously
+ int err = requestPriority(prioEvent->pid(), prioEvent->tid(), prioEvent->prio(),
+ true /*asynchronous*/);
if (err != 0) {
ALOGW("Policy SCHED_FIFO priority %d is unavailable for pid %d tid %d; "
"error %d",
diff --git a/services/camera/libcameraservice/camera2/Parameters.cpp b/services/camera/libcameraservice/camera2/Parameters.cpp
index d02f17e..b26cd09 100644
--- a/services/camera/libcameraservice/camera2/Parameters.cpp
+++ b/services/camera/libcameraservice/camera2/Parameters.cpp
@@ -659,15 +659,13 @@
float minFocalLength = availableFocalLengths.data.f[0];
params.setFloat(CameraParameters::KEY_FOCAL_LENGTH, minFocalLength);
- camera_metadata_ro_entry_t sensorSize =
- staticInfo(ANDROID_SENSOR_INFO_PHYSICAL_SIZE, 2, 2);
- if (!sensorSize.count) return NO_INIT;
+ float horizFov, vertFov;
+ res = calculatePictureFovs(&horizFov, &vertFov);
+ if (res != OK) {
+ ALOGE("%s: Can't calculate field of views!", __FUNCTION__);
+ return res;
+ }
- // The fields of view here assume infinity focus, maximum wide angle
- float horizFov = 180 / M_PI *
- 2 * atanf(sensorSize.data.f[0] / (2 * minFocalLength));
- float vertFov = 180 / M_PI *
- 2 * atanf(sensorSize.data.f[1] / (2 * minFocalLength));
params.setFloat(CameraParameters::KEY_HORIZONTAL_VIEW_ANGLE, horizFov);
params.setFloat(CameraParameters::KEY_VERTICAL_VIEW_ANGLE, vertFov);
@@ -861,6 +859,10 @@
staticInfo(ANDROID_LENS_INFO_MINIMUM_FOCUS_DISTANCE);
bool fixedLens = (minFocusDistance.data.f[0] == 0);
+ camera_metadata_ro_entry_t availableFocalLengths =
+ staticInfo(ANDROID_LENS_INFO_AVAILABLE_FOCAL_LENGTHS);
+ if (!availableFocalLengths.count) return NO_INIT;
+
if (sceneModeOverrides.count > 0) {
// sceneModeOverrides is defined to have 3 entries for each scene mode,
// which are AE, AWB, and AF override modes the HAL wants for that scene
@@ -928,6 +930,16 @@
fastInfo.arrayHeight = arrayHeight;
fastInfo.bestFaceDetectMode = bestFaceDetectMode;
fastInfo.maxFaces = maxFaces;
+
+ // Find smallest (widest-angle) focal length to use as basis of still
+ // picture FOV reporting.
+ fastInfo.minFocalLength = availableFocalLengths.data.f[0];
+ for (size_t i = 1; i < availableFocalLengths.count; i++) {
+ if (fastInfo.minFocalLength > availableFocalLengths.data.f[i]) {
+ fastInfo.minFocalLength = availableFocalLengths.data.f[i];
+ }
+ }
+
return OK;
}
@@ -1577,6 +1589,21 @@
*this = validatedParams;
+ /** Update external parameters calculated from the internal ones */
+
+ // HORIZONTAL/VERTICAL FIELD OF VIEW
+ float horizFov, vertFov;
+ res = calculatePictureFovs(&horizFov, &vertFov);
+ if (res != OK) {
+ ALOGE("%s: Can't calculate FOVs", __FUNCTION__);
+ // continue so parameters are at least consistent
+ }
+ newParams.setFloat(CameraParameters::KEY_HORIZONTAL_VIEW_ANGLE,
+ horizFov);
+ newParams.setFloat(CameraParameters::KEY_VERTICAL_VIEW_ANGLE,
+ vertFov);
+ ALOGV("Current still picture FOV: %f x %f deg", horizFov, vertFov);
+
// Need to flatten again in case of overrides
paramsFlattened = newParams.flatten();
params = newParams;
@@ -2246,7 +2273,7 @@
CropRegion previewCrop = calculateCropRegion(CropRegion::OUTPUT_PREVIEW);
ALOG_ASSERT(x < previewCrop.width, "Crop-relative X coordinate = '%d' "
- "is out of bounds (upper = %d)", x, previewCrop.width);
+ "is out of bounds (upper = %f)", x, previewCrop.width);
int ret = x + previewCrop.left;
@@ -2262,7 +2289,7 @@
CropRegion previewCrop = calculateCropRegion(CropRegion::OUTPUT_PREVIEW);
ALOG_ASSERT(y < previewCrop.height, "Crop-relative Y coordinate = '%d' is "
- "out of bounds (upper = %d)", y, previewCrop.height);
+ "out of bounds (upper = %f)", y, previewCrop.height);
int ret = y + previewCrop.top;
@@ -2468,6 +2495,90 @@
return crop;
}
+status_t Parameters::calculatePictureFovs(float *horizFov, float *vertFov)
+ const {
+ camera_metadata_ro_entry_t sensorSize =
+ staticInfo(ANDROID_SENSOR_INFO_PHYSICAL_SIZE, 2, 2);
+ if (!sensorSize.count) return NO_INIT;
+
+ camera_metadata_ro_entry_t availableFocalLengths =
+ staticInfo(ANDROID_LENS_INFO_AVAILABLE_FOCAL_LENGTHS);
+ if (!availableFocalLengths.count) return NO_INIT;
+
+ float arrayAspect = static_cast<float>(fastInfo.arrayWidth) /
+ fastInfo.arrayHeight;
+ float stillAspect = static_cast<float>(pictureWidth) / pictureHeight;
+ ALOGV("Array aspect: %f, still aspect: %f", arrayAspect, stillAspect);
+
+ // The crop factors from the full sensor array to the still picture crop
+ // region
+ float horizCropFactor = 1.f;
+ float vertCropFactor = 1.f;
+
+ /**
+ * Need to calculate the still image field of view based on the total pixel
+ * array field of view, and the relative aspect ratios of the pixel array
+ * and output streams.
+ *
+ * Special treatment for quirky definition of crop region and relative
+ * stream cropping.
+ */
+ if (quirks.meteringCropRegion) {
+ /**
+ * All streams are the same in height, so narrower aspect ratios will
+ * get cropped on the sides. First find the largest (widest) aspect
+ * ratio, then calculate the crop of the still FOV based on that.
+ */
+ float cropAspect = arrayAspect;
+ float aspects[] = {
+ stillAspect,
+ static_cast<float>(previewWidth) / previewHeight,
+ static_cast<float>(videoWidth) / videoHeight
+ };
+ for (size_t i = 0; i < sizeof(aspects)/sizeof(aspects[0]); i++) {
+ if (cropAspect < aspects[i]) cropAspect = aspects[i];
+ }
+ ALOGV("Widest crop aspect: %f", cropAspect);
+ // Horizontal crop of still is done based on fitting in the widest
+ // aspect ratio
+ horizCropFactor = stillAspect / cropAspect;
+ // Vertical crop is a function of the array aspect ratio and the
+ // widest aspect ratio.
+ vertCropFactor = arrayAspect / cropAspect;
+ } else {
+ /**
+ * Crop are just a function of just the still/array relative aspect
+ * ratios. Since each stream will maximize its area within the crop
+ * region, and for FOV we assume a full-sensor crop region, we only ever
+ * crop the FOV either vertically or horizontally, never both.
+ */
+ horizCropFactor = (arrayAspect > stillAspect) ?
+ (stillAspect / arrayAspect) : 1.f;
+ vertCropFactor = (arrayAspect < stillAspect) ?
+ (arrayAspect / stillAspect) : 1.f;
+ }
+ ALOGV("Horiz crop factor: %f, vert crop fact: %f",
+ horizCropFactor, vertCropFactor);
+ /**
+ * Basic field of view formula is:
+ * angle of view = 2 * arctangent ( d / 2f )
+ * where d is the physical sensor dimension of interest, and f is
+ * the focal length. This only applies to rectilinear sensors, for focusing
+ * at distances >> f, etc.
+ */
+ if (horizFov != NULL) {
+ *horizFov = 180 / M_PI * 2 *
+ atanf(horizCropFactor * sensorSize.data.f[0] /
+ (2 * fastInfo.minFocalLength));
+ }
+ if (vertFov != NULL) {
+ *vertFov = 180 / M_PI * 2 *
+ atanf(vertCropFactor * sensorSize.data.f[1] /
+ (2 * fastInfo.minFocalLength));
+ }
+ return OK;
+}
+
int32_t Parameters::fpsFromRange(int32_t /*min*/, int32_t max) const {
return max;
}
diff --git a/services/camera/libcameraservice/camera2/Parameters.h b/services/camera/libcameraservice/camera2/Parameters.h
index 696ee2f..6d85037 100644
--- a/services/camera/libcameraservice/camera2/Parameters.h
+++ b/services/camera/libcameraservice/camera2/Parameters.h
@@ -183,6 +183,7 @@
}
};
DefaultKeyedVector<uint8_t, OverrideModes> sceneModeOverrides;
+ float minFocalLength;
} fastInfo;
// Quirks information; these are short-lived flags to enable workarounds for
@@ -243,6 +244,9 @@
};
CropRegion calculateCropRegion(CropRegion::Outputs outputs) const;
+ // Calculate the field of view of the high-resolution JPEG capture
+ status_t calculatePictureFovs(float *horizFov, float *vertFov) const;
+
// Static methods for debugging and converting between camera1 and camera2
// parameters