summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--media/libmediaplayerservice/nuplayer/NuPlayer.cpp4
-rw-r--r--media/libmediaplayerservice/nuplayer/RTSPSource.cpp4
-rw-r--r--media/libstagefright/ACodec.cpp13
-rw-r--r--media/libstagefright/OMXCodec.cpp11
-rw-r--r--media/libstagefright/codecs/aacdec/SoftAAC2.cpp12
-rw-r--r--media/libstagefright/codecs/mp3dec/SoftMP3.cpp15
-rw-r--r--media/libstagefright/codecs/vorbis/dec/SoftVorbis.cpp13
-rw-r--r--media/libstagefright/httplive/M3UParser.cpp3
-rw-r--r--services/camera/libcameraservice/Camera3Device.cpp235
-rw-r--r--services/camera/libcameraservice/Camera3Device.h44
10 files changed, 301 insertions, 53 deletions
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
index 46d0a5a..607ec6a 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
@@ -1158,7 +1158,7 @@ void NuPlayer::performSeek(int64_t seekTimeUs) {
void NuPlayer::performDecoderFlush() {
ALOGV("performDecoderFlush");
- if (mAudioDecoder != NULL && mVideoDecoder == NULL) {
+ if (mAudioDecoder == NULL && mVideoDecoder == NULL) {
return;
}
@@ -1176,7 +1176,7 @@ void NuPlayer::performDecoderFlush() {
void NuPlayer::performDecoderShutdown() {
ALOGV("performDecoderShutdown");
- if (mAudioDecoder != NULL && mVideoDecoder == NULL) {
+ if (mAudioDecoder == NULL && mVideoDecoder == NULL) {
return;
}
diff --git a/media/libmediaplayerservice/nuplayer/RTSPSource.cpp b/media/libmediaplayerservice/nuplayer/RTSPSource.cpp
index a5ff0ca..50ebf9c 100644
--- a/media/libmediaplayerservice/nuplayer/RTSPSource.cpp
+++ b/media/libmediaplayerservice/nuplayer/RTSPSource.cpp
@@ -66,7 +66,9 @@ NuPlayer::RTSPSource::RTSPSource(
}
NuPlayer::RTSPSource::~RTSPSource() {
- mLooper->stop();
+ if (mLooper != NULL) {
+ mLooper->stop();
+ }
}
void NuPlayer::RTSPSource::prepareAsync() {
diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp
index ee49033..b3bc6d8 100644
--- a/media/libstagefright/ACodec.cpp
+++ b/media/libstagefright/ACodec.cpp
@@ -960,6 +960,19 @@ status_t ACodec::configureCodec(
err = setupVideoDecoder(mime, width, height);
}
}
+ } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_MPEG)) {
+ int32_t numChannels, sampleRate;
+ if (!msg->findInt32("channel-count", &numChannels)
+ || !msg->findInt32("sample-rate", &sampleRate)) {
+ // Since we did not always check for these, leave them optional
+ // and have the decoder figure it all out.
+ err = OK;
+ } else {
+ err = setupRawAudioFormat(
+ encoder ? kPortIndexInput : kPortIndexOutput,
+ sampleRate,
+ numChannels);
+ }
} else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) {
int32_t numChannels, sampleRate;
if (!msg->findInt32("channel-count", &numChannels)
diff --git a/media/libstagefright/OMXCodec.cpp b/media/libstagefright/OMXCodec.cpp
index 6c0779d..9d349a1 100644
--- a/media/libstagefright/OMXCodec.cpp
+++ b/media/libstagefright/OMXCodec.cpp
@@ -522,6 +522,17 @@ status_t OMXCodec::configureCodec(const sp<MetaData> &meta) {
CODEC_LOGE("setAACFormat() failed (err = %d)", err);
return err;
}
+ } else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_MPEG, mMIME)) {
+ int32_t numChannels, sampleRate;
+ if (meta->findInt32(kKeyChannelCount, &numChannels)
+ && meta->findInt32(kKeySampleRate, &sampleRate)) {
+ // Since we did not always check for these, leave them optional
+ // and have the decoder figure it all out.
+ setRawAudioFormat(
+ mIsEncoder ? kPortIndexInput : kPortIndexOutput,
+ sampleRate,
+ numChannels);
+ }
} else if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_G711_ALAW, mMIME)
|| !strcasecmp(MEDIA_MIMETYPE_AUDIO_G711_MLAW, mMIME)) {
// These are PCM-like formats with a fixed sample rate but
diff --git a/media/libstagefright/codecs/aacdec/SoftAAC2.cpp b/media/libstagefright/codecs/aacdec/SoftAAC2.cpp
index 536cfde..cf50dc9 100644
--- a/media/libstagefright/codecs/aacdec/SoftAAC2.cpp
+++ b/media/libstagefright/codecs/aacdec/SoftAAC2.cpp
@@ -29,6 +29,7 @@
#define DRC_DEFAULT_MOBILE_REF_LEVEL 64 /* 64*-0.25dB = -16 dB below full scale for mobile conf */
#define DRC_DEFAULT_MOBILE_DRC_CUT 127 /* maximum compression of dynamic range for mobile conf */
+#define DRC_DEFAULT_MOBILE_DRC_BOOST 127 /* maximum compression of dynamic range for mobile conf */
#define MAX_CHANNEL_COUNT 6 /* maximum number of audio channels that can be decoded */
// names of properties that can be used to override the default DRC settings
#define PROP_DRC_OVERRIDE_REF_LEVEL "aac_drc_reference_level"
@@ -146,6 +147,8 @@ status_t SoftAAC2::initDecoder() {
unsigned boost = atoi(value);
ALOGV("AAC decoder using AAC_DRC_BOOST_FACTOR of %d", boost);
aacDecoder_SetParam(mAACDecoder, AAC_DRC_BOOST_FACTOR, boost);
+ } else {
+ aacDecoder_SetParam(mAACDecoder, AAC_DRC_BOOST_FACTOR, DRC_DEFAULT_MOBILE_DRC_BOOST);
}
return status;
@@ -583,9 +586,12 @@ void SoftAAC2::onPortFlushCompleted(OMX_U32 portIndex) {
}
void SoftAAC2::drainDecoder() {
- short buf [2048];
- aacDecoder_DecodeFrame(mAACDecoder, buf, 4096, AACDEC_FLUSH | AACDEC_CLRHIST | AACDEC_INTR);
- aacDecoder_DecodeFrame(mAACDecoder, buf, 4096, AACDEC_FLUSH | AACDEC_CLRHIST | AACDEC_INTR);
+ // a buffer big enough for 6 channels of decoded HE-AAC
+ short buf [2048*6];
+ aacDecoder_DecodeFrame(mAACDecoder,
+ buf, sizeof(buf), AACDEC_FLUSH | AACDEC_CLRHIST | AACDEC_INTR);
+ aacDecoder_DecodeFrame(mAACDecoder,
+ buf, sizeof(buf), AACDEC_FLUSH | AACDEC_CLRHIST | AACDEC_INTR);
aacDecoder_SetParam(mAACDecoder, AAC_TPDEC_CLEAR_BUFFER, 1);
mDecoderHasData = false;
}
diff --git a/media/libstagefright/codecs/mp3dec/SoftMP3.cpp b/media/libstagefright/codecs/mp3dec/SoftMP3.cpp
index 849be87..9f25536 100644
--- a/media/libstagefright/codecs/mp3dec/SoftMP3.cpp
+++ b/media/libstagefright/codecs/mp3dec/SoftMP3.cpp
@@ -166,6 +166,21 @@ OMX_ERRORTYPE SoftMP3::internalSetParameter(
return OMX_ErrorNone;
}
+ case OMX_IndexParamAudioPcm:
+ {
+ const OMX_AUDIO_PARAM_PCMMODETYPE *pcmParams =
+ (const OMX_AUDIO_PARAM_PCMMODETYPE *)params;
+
+ if (pcmParams->nPortIndex != 1) {
+ return OMX_ErrorUndefined;
+ }
+
+ mNumChannels = pcmParams->nChannels;
+ mSamplingRate = pcmParams->nSamplingRate;
+
+ return OMX_ErrorNone;
+ }
+
default:
return SimpleSoftOMXComponent::internalSetParameter(index, params);
}
diff --git a/media/libstagefright/codecs/vorbis/dec/SoftVorbis.cpp b/media/libstagefright/codecs/vorbis/dec/SoftVorbis.cpp
index 922ac61..4115324 100644
--- a/media/libstagefright/codecs/vorbis/dec/SoftVorbis.cpp
+++ b/media/libstagefright/codecs/vorbis/dec/SoftVorbis.cpp
@@ -411,8 +411,19 @@ void SoftVorbis::onPortFlushCompleted(OMX_U32 portIndex) {
}
void SoftVorbis::onReset() {
+ mInputBufferCount = 0;
mNumFramesOutput = 0;
- vorbis_dsp_restart(mState);
+ if (mState != NULL) {
+ vorbis_dsp_clear(mState);
+ delete mState;
+ mState = NULL;
+ }
+
+ if (mVi != NULL) {
+ vorbis_info_clear(mVi);
+ delete mVi;
+ mVi = NULL;
+ }
}
void SoftVorbis::onPortEnableCompleted(OMX_U32 portIndex, bool enabled) {
diff --git a/media/libstagefright/httplive/M3UParser.cpp b/media/libstagefright/httplive/M3UParser.cpp
index 44e03dc..68bbca2 100644
--- a/media/libstagefright/httplive/M3UParser.cpp
+++ b/media/libstagefright/httplive/M3UParser.cpp
@@ -163,9 +163,6 @@ status_t M3UParser::parse(const void *_data, size_t size) {
while (offsetLF < size && data[offsetLF] != '\n') {
++offsetLF;
}
- if (offsetLF >= size) {
- break;
- }
AString line;
if (offsetLF > offset && data[offsetLF - 1] == '\r') {
diff --git a/services/camera/libcameraservice/Camera3Device.cpp b/services/camera/libcameraservice/Camera3Device.cpp
index 08aef83..d67b535 100644
--- a/services/camera/libcameraservice/Camera3Device.cpp
+++ b/services/camera/libcameraservice/Camera3Device.cpp
@@ -51,6 +51,8 @@ Camera3Device::Camera3Device(int id):
mId(id),
mHal3Device(NULL),
mStatus(STATUS_UNINITIALIZED),
+ mNextResultFrameNumber(0),
+ mNextShutterFrameNumber(0),
mListener(NULL)
{
ATRACE_CALL();
@@ -246,8 +248,22 @@ status_t Camera3Device::dump(int fd, const Vector<String16> &args) {
mOutputStreams[i]->dump(fd,args);
}
+ lines = String8(" In-flight requests:\n");
+ if (mInFlightMap.size() == 0) {
+ lines.append(" None\n");
+ } else {
+ for (size_t i = 0; i < mInFlightMap.size(); i++) {
+ InFlightRequest r = mInFlightMap.valueAt(i);
+ lines.appendFormat(" Frame %d | Timestamp: %lld, metadata"
+ " arrived: %s, buffers left: %d\n", mInFlightMap.keyAt(i),
+ r.captureTimestamp, r.haveResultMetadata ? "true" : "false",
+ r.numBuffersLeft);
+ }
+ }
+ write(fd, lines.string(), lines.size());
+
if (mHal3Device != NULL) {
- lines = String8(" HAL device dump:\n");
+ lines = String8(" HAL device dump:\n");
write(fd, lines.string(), lines.size());
mHal3Device->ops->dump(mHal3Device, fd);
}
@@ -927,15 +943,36 @@ void Camera3Device::setErrorStateLocked(const char *fmt, ...) {
}
void Camera3Device::setErrorStateLockedV(const char *fmt, va_list args) {
- // Only accept the first failure cause
+ // Print out all error messages to log
+ String8 errorCause = String8::formatV(fmt, args);
+ ALOGE("Camera %d: %s", mId, errorCause.string());
+
+ // But only do error state transition steps for the first error
if (mStatus == STATUS_ERROR) return;
- mErrorCause = String8::formatV(fmt, args);
- ALOGE("Camera %d: %s", mId, mErrorCause.string());
+ mErrorCause = errorCause;
+
+ mRequestThread->setPaused(true);
mStatus = STATUS_ERROR;
}
/**
+ * In-flight request management
+ */
+
+status_t Camera3Device::registerInFlight(int32_t frameNumber,
+ int32_t numBuffers) {
+ ATRACE_CALL();
+ Mutex::Autolock l(mInFlightLock);
+
+ ssize_t res;
+ res = mInFlightMap.add(frameNumber, InFlightRequest(numBuffers));
+ if (res < 0) return res;
+
+ return OK;
+}
+
+/**
* Camera HAL device callback methods
*/
@@ -944,47 +981,107 @@ void Camera3Device::processCaptureResult(const camera3_capture_result *result) {
status_t res;
- if (result->result == NULL) {
- SET_ERR("No metadata provided by HAL for frame %d",
- result->frame_number);
+ uint32_t frameNumber = result->frame_number;
+ if (result->result == NULL && result->num_output_buffers == 0) {
+ SET_ERR("No result data provided by HAL for frame %d",
+ frameNumber);
return;
}
+ // Get capture timestamp from list of in-flight requests, where it was added
+ // by the shutter notification for this frame. Then update the in-flight
+ // status and remove the in-flight entry if all result data has been
+ // received.
nsecs_t timestamp = 0;
+ {
+ Mutex::Autolock l(mInFlightLock);
+ ssize_t idx = mInFlightMap.indexOfKey(frameNumber);
+ if (idx == NAME_NOT_FOUND) {
+ SET_ERR("Unknown frame number for capture result: %d",
+ frameNumber);
+ return;
+ }
+ InFlightRequest &request = mInFlightMap.editValueAt(idx);
+ timestamp = request.captureTimestamp;
+ if (timestamp == 0) {
+ SET_ERR("Called before shutter notify for frame %d",
+ frameNumber);
+ return;
+ }
+
+ if (result->result != NULL) {
+ if (request.haveResultMetadata) {
+ SET_ERR("Called multiple times with metadata for frame %d",
+ frameNumber);
+ return;
+ }
+ request.haveResultMetadata = true;
+ }
+
+ request.numBuffersLeft -= result->num_output_buffers;
+
+ if (request.numBuffersLeft < 0) {
+ SET_ERR("Too many buffers returned for frame %d",
+ frameNumber);
+ return;
+ }
+
+ if (request.haveResultMetadata && request.numBuffersLeft == 0) {
+ mInFlightMap.removeItemsAt(idx, 1);
+ }
+
+ // Sanity check - if we have too many in-flight frames, something has
+ // likely gone wrong
+ if (mInFlightMap.size() > kInFlightWarnLimit) {
+ CLOGE("In-flight list too large: %d", mInFlightMap.size());
+ }
+
+ }
+
AlgState cur3aState;
AlgState new3aState;
int32_t aeTriggerId = 0;
int32_t afTriggerId = 0;
- NotificationListener *listener;
+ NotificationListener *listener = NULL;
- {
+ // Process the result metadata, if provided
+ if (result->result != NULL) {
Mutex::Autolock l(mOutputLock);
- // Push result metadata into queue
- mResultQueue.push_back(CameraMetadata());
- // Lets avoid copies! Too bad there's not a #back method
- CameraMetadata &captureResult = *(--mResultQueue.end());
+ if (frameNumber != mNextResultFrameNumber) {
+ SET_ERR("Out-of-order capture result metadata submitted! "
+ "(got frame number %d, expecting %d)",
+ frameNumber, mNextResultFrameNumber);
+ return;
+ }
+ mNextResultFrameNumber++;
+
+ CameraMetadata &captureResult =
+ *mResultQueue.insert(mResultQueue.end(), CameraMetadata());
captureResult = result->result;
if (captureResult.update(ANDROID_REQUEST_FRAME_COUNT,
- (int32_t*)&result->frame_number, 1) != OK) {
+ (int32_t*)&frameNumber, 1) != OK) {
SET_ERR("Failed to set frame# in metadata (%d)",
- result->frame_number);
+ frameNumber);
} else {
ALOGVV("%s: Camera %d: Set frame# in metadata (%d)",
- __FUNCTION__, mId, result->frame_number);
+ __FUNCTION__, mId, frameNumber);
}
- // Get timestamp from result metadata
+ // Check that there's a timestamp in the result metadata
camera_metadata_entry entry =
captureResult.find(ANDROID_SENSOR_TIMESTAMP);
if (entry.count == 0) {
SET_ERR("No timestamp provided by HAL for frame %d!",
- result->frame_number);
- } else {
- timestamp = entry.data.i64[0];
+ frameNumber);
+ }
+ if (timestamp != entry.data.i64[0]) {
+ SET_ERR("Timestamp mismatch between shutter notify and result"
+ " metadata for frame %d (%lld vs %lld respectively)",
+ frameNumber, timestamp, entry.data.i64[0]);
}
// Get 3A states from result metadata
@@ -992,7 +1089,7 @@ void Camera3Device::processCaptureResult(const camera3_capture_result *result) {
entry = captureResult.find(ANDROID_CONTROL_AE_STATE);
if (entry.count == 0) {
CLOGE("No AE state provided by HAL for frame %d!",
- result->frame_number);
+ frameNumber);
} else {
new3aState.aeState =
static_cast<camera_metadata_enum_android_control_ae_state>(
@@ -1002,7 +1099,7 @@ void Camera3Device::processCaptureResult(const camera3_capture_result *result) {
entry = captureResult.find(ANDROID_CONTROL_AF_STATE);
if (entry.count == 0) {
CLOGE("No AF state provided by HAL for frame %d!",
- result->frame_number);
+ frameNumber);
} else {
new3aState.afState =
static_cast<camera_metadata_enum_android_control_af_state>(
@@ -1012,7 +1109,7 @@ void Camera3Device::processCaptureResult(const camera3_capture_result *result) {
entry = captureResult.find(ANDROID_CONTROL_AWB_STATE);
if (entry.count == 0) {
CLOGE("No AWB state provided by HAL for frame %d!",
- result->frame_number);
+ frameNumber);
} else {
new3aState.awbState =
static_cast<camera_metadata_enum_android_control_awb_state>(
@@ -1022,7 +1119,7 @@ void Camera3Device::processCaptureResult(const camera3_capture_result *result) {
entry = captureResult.find(ANDROID_CONTROL_AF_TRIGGER_ID);
if (entry.count == 0) {
CLOGE("No AF trigger ID provided by HAL for frame %d!",
- result->frame_number);
+ frameNumber);
} else {
afTriggerId = entry.data.i32[0];
}
@@ -1030,7 +1127,7 @@ void Camera3Device::processCaptureResult(const camera3_capture_result *result) {
entry = captureResult.find(ANDROID_CONTROL_AE_PRECAPTURE_ID);
if (entry.count == 0) {
CLOGE("No AE precapture trigger ID provided by HAL"
- " for frame %d!", result->frame_number);
+ " for frame %d!", frameNumber);
} else {
aeTriggerId = entry.data.i32[0];
}
@@ -1041,7 +1138,8 @@ void Camera3Device::processCaptureResult(const camera3_capture_result *result) {
m3AState = new3aState;
} // scope for mOutputLock
- // Return completed buffers to their streams
+ // Return completed buffers to their streams with the timestamp
+
for (size_t i = 0; i < result->num_output_buffers; i++) {
Camera3Stream *stream =
Camera3Stream::cast(result->output_buffers[i].stream);
@@ -1050,20 +1148,21 @@ void Camera3Device::processCaptureResult(const camera3_capture_result *result) {
// last reference to it.
if (res != OK) {
SET_ERR("Can't return buffer %d for frame %d to its stream: "
- " %s (%d)", i, result->frame_number, strerror(-res), res);
+ " %s (%d)", i, frameNumber, strerror(-res), res);
}
}
- // Dispatch any 3A change events to listeners
- if (listener != NULL) {
+ // Finally, dispatch any 3A change events to listeners if we got metadata
+
+ if (result->result != NULL && listener != NULL) {
if (new3aState.aeState != cur3aState.aeState) {
ALOGVV("%s: AE state changed from 0x%x to 0x%x",
- __FUNCTION__, cur3aState.aeState, new3aState.aeState);
+ __FUNCTION__, cur3aState.aeState, new3aState.aeState);
listener->notifyAutoExposure(new3aState.aeState, aeTriggerId);
}
if (new3aState.afState != cur3aState.afState) {
ALOGVV("%s: AF state changed from 0x%x to 0x%x",
- __FUNCTION__, cur3aState.afState, new3aState.afState);
+ __FUNCTION__, cur3aState.afState, new3aState.afState);
listener->notifyAutoFocus(new3aState.afState, afTriggerId);
}
if (new3aState.awbState != cur3aState.awbState) {
@@ -1077,12 +1176,11 @@ void Camera3Device::notify(const camera3_notify_msg *msg) {
NotificationListener *listener;
{
Mutex::Autolock l(mOutputLock);
- if (mListener == NULL) return;
listener = mListener;
}
if (msg == NULL) {
- SET_ERR_L("HAL sent NULL notify message!");
+ SET_ERR("HAL sent NULL notify message!");
return;
}
@@ -1095,17 +1193,50 @@ void Camera3Device::notify(const camera3_notify_msg *msg) {
msg->message.error.error_stream);
streamId = stream->getId();
}
- listener->notifyError(msg->message.error.error_code,
- msg->message.error.frame_number, streamId);
+ if (listener != NULL) {
+ listener->notifyError(msg->message.error.error_code,
+ msg->message.error.frame_number, streamId);
+ }
break;
}
case CAMERA3_MSG_SHUTTER: {
- listener->notifyShutter(msg->message.shutter.frame_number,
- msg->message.shutter.timestamp);
+ ssize_t idx;
+ uint32_t frameNumber = msg->message.shutter.frame_number;
+ nsecs_t timestamp = msg->message.shutter.timestamp;
+ // Verify ordering of shutter notifications
+ {
+ Mutex::Autolock l(mOutputLock);
+ if (frameNumber != mNextShutterFrameNumber) {
+ SET_ERR("Shutter notification out-of-order. Expected "
+ "notification for frame %d, got frame %d",
+ mNextShutterFrameNumber, frameNumber);
+ break;
+ }
+ mNextShutterFrameNumber++;
+ }
+
+ // Set timestamp for the request in the in-flight tracking
+ {
+ Mutex::Autolock l(mInFlightLock);
+ idx = mInFlightMap.indexOfKey(frameNumber);
+ if (idx >= 0) {
+ mInFlightMap.editValueAt(idx).captureTimestamp = timestamp;
+ }
+ }
+ if (idx < 0) {
+ SET_ERR("Shutter notification for non-existent frame number %d",
+ frameNumber);
+ break;
+ }
+
+ // Call listener, if any
+ if (listener != NULL) {
+ listener->notifyShutter(frameNumber, timestamp);
+ }
break;
}
default:
- SET_ERR_L("Unknown notify message from HAL: %d",
+ SET_ERR("Unknown notify message from HAL: %d",
msg->type);
}
}
@@ -1119,6 +1250,7 @@ Camera3Device::RequestThread::RequestThread(wp<Camera3Device> parent,
Thread(false),
mParent(parent),
mHal3Device(hal3Device),
+ mId(getId(parent)),
mReconfigured(false),
mDoPause(false),
mPaused(true),
@@ -1158,6 +1290,12 @@ status_t Camera3Device::RequestThread::queueTrigger(
return OK;
}
+int Camera3Device::RequestThread::getId(const wp<Camera3Device> &device) {
+ sp<Camera3Device> d = device.promote();
+ if (d != NULL) return d->mId;
+ return 0;
+}
+
status_t Camera3Device::RequestThread::queueTriggerLocked(
RequestTrigger trigger) {
@@ -1170,9 +1308,8 @@ status_t Camera3Device::RequestThread::queueTriggerLocked(
case TYPE_INT32:
break;
default:
- ALOGE("%s: Type not supported: 0x%x",
- __FUNCTION__,
- trigger.getTagType());
+ ALOGE("%s: Type not supported: 0x%x", __FUNCTION__,
+ trigger.getTagType());
return INVALID_OPERATION;
}
@@ -1340,6 +1477,22 @@ bool Camera3Device::RequestThread::threadLoop() {
request.frame_number = mFrameNumber++;
+ // Log request in the in-flight queue
+ sp<Camera3Device> parent = mParent.promote();
+ if (parent == NULL) {
+ CLOGE("RequestThread: Parent is gone");
+ cleanUpFailedRequest(request, nextRequest, outputBuffers);
+ return false;
+ }
+
+ res = parent->registerInFlight(request.frame_number,
+ request.num_output_buffers);
+ if (res != OK) {
+ SET_ERR("RequestThread: Unable to register new in-flight request:"
+ " %s (%d)", strerror(-res), res);
+ cleanUpFailedRequest(request, nextRequest, outputBuffers);
+ return false;
+ }
// Submit request and block until ready for next one
diff --git a/services/camera/libcameraservice/Camera3Device.h b/services/camera/libcameraservice/Camera3Device.h
index 2e4a303..6cad08e 100644
--- a/services/camera/libcameraservice/Camera3Device.h
+++ b/services/camera/libcameraservice/Camera3Device.h
@@ -108,7 +108,8 @@ class Camera3Device :
buffer_handle_t *buffer, wp<BufferReleasedListener> listener);
private:
- static const nsecs_t kShutdownTimeout = 5000000000; // 5 sec
+ static const size_t kInFlightWarnLimit = 20;
+ static const nsecs_t kShutdownTimeout = 5000000000; // 5 sec
struct RequestTrigger;
Mutex mLock;
@@ -262,6 +263,8 @@ class Camera3Device :
virtual bool threadLoop();
private:
+ static int getId(const wp<Camera3Device> &device);
+
status_t queueTriggerLocked(RequestTrigger trigger);
// Mix-in queued triggers into this request
int32_t insertTriggers(const sp<CaptureRequest> &request);
@@ -291,6 +294,8 @@ class Camera3Device :
wp<Camera3Device> mParent;
camera3_device_t *mHal3Device;
+ const int mId;
+
Mutex mRequestLock;
Condition mRequestSignal;
RequestList mRequestQueue;
@@ -308,7 +313,7 @@ class Camera3Device :
sp<CaptureRequest> mPrevRequest;
int32_t mPrevTriggers;
- int32_t mFrameNumber;
+ uint32_t mFrameNumber;
Mutex mLatestRequestMutex;
Condition mLatestRequestSignal;
@@ -324,6 +329,39 @@ class Camera3Device :
sp<RequestThread> mRequestThread;
/**
+ * In-flight queue for tracking completion of capture requests.
+ */
+
+ struct InFlightRequest {
+ // Set by notify() SHUTTER call.
+ nsecs_t captureTimestamp;
+ // Set by process_capture_result call with valid metadata
+ bool haveResultMetadata;
+ // Decremented by calls to process_capture_result with valid output
+ // buffers
+ int numBuffersLeft;
+
+ InFlightRequest() :
+ captureTimestamp(0),
+ haveResultMetadata(false),
+ numBuffersLeft(0) {
+ }
+
+ explicit InFlightRequest(int numBuffers) :
+ captureTimestamp(0),
+ haveResultMetadata(false),
+ numBuffersLeft(numBuffers) {
+ }
+ };
+ // Map from frame number to the in-flight request state
+ typedef KeyedVector<uint32_t, InFlightRequest> InFlightMap;
+
+ Mutex mInFlightLock; // Protects mInFlightMap
+ InFlightMap mInFlightMap;
+
+ status_t registerInFlight(int32_t frameNumber, int32_t numBuffers);
+
+ /**
* Output result queue and current HAL device 3A state
*/
@@ -332,6 +370,8 @@ class Camera3Device :
/**** Scope for mOutputLock ****/
+ uint32_t mNextResultFrameNumber;
+ uint32_t mNextShutterFrameNumber;
List<CameraMetadata> mResultQueue;
Condition mResultSignal;
NotificationListener *mListener;