diff options
-rw-r--r-- | media/libmediaplayerservice/nuplayer/NuPlayer.cpp | 4 | ||||
-rw-r--r-- | media/libmediaplayerservice/nuplayer/RTSPSource.cpp | 4 | ||||
-rw-r--r-- | media/libstagefright/ACodec.cpp | 13 | ||||
-rw-r--r-- | media/libstagefright/OMXCodec.cpp | 11 | ||||
-rw-r--r-- | media/libstagefright/codecs/aacdec/SoftAAC2.cpp | 12 | ||||
-rw-r--r-- | media/libstagefright/codecs/mp3dec/SoftMP3.cpp | 15 | ||||
-rw-r--r-- | media/libstagefright/codecs/vorbis/dec/SoftVorbis.cpp | 13 | ||||
-rw-r--r-- | media/libstagefright/httplive/M3UParser.cpp | 3 | ||||
-rw-r--r-- | services/camera/libcameraservice/Camera3Device.cpp | 235 | ||||
-rw-r--r-- | services/camera/libcameraservice/Camera3Device.h | 44 |
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; |