diff options
-rw-r--r-- | include/media/MediaProfiles.h | 3 | ||||
-rw-r--r-- | include/media/stagefright/MediaErrors.h | 32 | ||||
-rw-r--r-- | media/libmedia/MediaProfiles.cpp | 1 | ||||
-rw-r--r-- | media/libmediaplayerservice/nuplayer/NuPlayerDecoderPassThrough.cpp | 13 | ||||
-rw-r--r-- | media/libstagefright/MediaCodec.cpp | 15 | ||||
-rw-r--r-- | media/libstagefright/codecs/aacdec/SoftAAC2.cpp | 317 | ||||
-rw-r--r-- | media/libstagefright/codecs/aacdec/SoftAAC2.h | 5 | ||||
-rw-r--r-- | services/audioflinger/PatchPanel.cpp | 6 | ||||
-rw-r--r-- | services/camera/libcameraservice/Android.mk | 1 | ||||
-rw-r--r-- | services/camera/libcameraservice/api1/Camera2Client.cpp | 3 | ||||
-rw-r--r-- | services/camera/libcameraservice/api1/client2/ZslProcessor.cpp | 15 | ||||
-rw-r--r-- | services/camera/libcameraservice/api1/client2/ZslProcessor.h | 3 | ||||
-rw-r--r-- | services/camera/libcameraservice/api1/client2/ZslProcessorInterface.cpp | 28 | ||||
-rw-r--r-- | services/camera/libcameraservice/api1/client2/ZslProcessorInterface.h | 5 |
14 files changed, 225 insertions, 222 deletions
diff --git a/include/media/MediaProfiles.h b/include/media/MediaProfiles.h index 253c557..f061d22 100644 --- a/include/media/MediaProfiles.h +++ b/include/media/MediaProfiles.h @@ -54,7 +54,8 @@ enum camcorder_quality { CAMCORDER_QUALITY_HIGH_SPEED_480P = 2002, CAMCORDER_QUALITY_HIGH_SPEED_720P = 2003, CAMCORDER_QUALITY_HIGH_SPEED_1080P = 2004, - CAMCORDER_QUALITY_HIGH_SPEED_LIST_END = 2004, + CAMCORDER_QUALITY_HIGH_SPEED_2160P = 2005, + CAMCORDER_QUALITY_HIGH_SPEED_LIST_END = 2005, }; /** diff --git a/include/media/stagefright/MediaErrors.h b/include/media/stagefright/MediaErrors.h index 7540e07..2e663ec 100644 --- a/include/media/stagefright/MediaErrors.h +++ b/include/media/stagefright/MediaErrors.h @@ -58,20 +58,22 @@ enum { // drm/drm_framework_common.h DRM_ERROR_BASE = -2000, - ERROR_DRM_UNKNOWN = DRM_ERROR_BASE, - ERROR_DRM_NO_LICENSE = DRM_ERROR_BASE - 1, - ERROR_DRM_LICENSE_EXPIRED = DRM_ERROR_BASE - 2, - ERROR_DRM_SESSION_NOT_OPENED = DRM_ERROR_BASE - 3, - ERROR_DRM_DECRYPT_UNIT_NOT_INITIALIZED = DRM_ERROR_BASE - 4, - ERROR_DRM_DECRYPT = DRM_ERROR_BASE - 5, - ERROR_DRM_CANNOT_HANDLE = DRM_ERROR_BASE - 6, - ERROR_DRM_TAMPER_DETECTED = DRM_ERROR_BASE - 7, - ERROR_DRM_NOT_PROVISIONED = DRM_ERROR_BASE - 8, - ERROR_DRM_DEVICE_REVOKED = DRM_ERROR_BASE - 9, - ERROR_DRM_RESOURCE_BUSY = DRM_ERROR_BASE - 10, - - ERROR_DRM_VENDOR_MAX = DRM_ERROR_BASE - 500, - ERROR_DRM_VENDOR_MIN = DRM_ERROR_BASE - 999, + ERROR_DRM_UNKNOWN = DRM_ERROR_BASE, + ERROR_DRM_NO_LICENSE = DRM_ERROR_BASE - 1, + ERROR_DRM_LICENSE_EXPIRED = DRM_ERROR_BASE - 2, + ERROR_DRM_SESSION_NOT_OPENED = DRM_ERROR_BASE - 3, + ERROR_DRM_DECRYPT_UNIT_NOT_INITIALIZED = DRM_ERROR_BASE - 4, + ERROR_DRM_DECRYPT = DRM_ERROR_BASE - 5, + ERROR_DRM_CANNOT_HANDLE = DRM_ERROR_BASE - 6, + ERROR_DRM_TAMPER_DETECTED = DRM_ERROR_BASE - 7, + ERROR_DRM_NOT_PROVISIONED = DRM_ERROR_BASE - 8, + ERROR_DRM_DEVICE_REVOKED = DRM_ERROR_BASE - 9, + ERROR_DRM_RESOURCE_BUSY = DRM_ERROR_BASE - 10, + ERROR_DRM_INSUFFICIENT_OUTPUT_PROTECTION = DRM_ERROR_BASE - 11, + ERROR_DRM_LAST_USED_ERRORCODE = DRM_ERROR_BASE - 11, + + ERROR_DRM_VENDOR_MAX = DRM_ERROR_BASE - 500, + ERROR_DRM_VENDOR_MIN = DRM_ERROR_BASE - 999, // Heartbeat Error Codes HEARTBEAT_ERROR_BASE = -3000, @@ -100,7 +102,7 @@ enum ActionCode { // returns true if err is a recognized DRM error code static inline bool isCryptoError(status_t err) { - return (ERROR_DRM_RESOURCE_BUSY <= err && err <= ERROR_DRM_UNKNOWN) + return (ERROR_DRM_LAST_USED_ERRORCODE <= err && err <= ERROR_DRM_UNKNOWN) || (ERROR_DRM_VENDOR_MIN <= err && err <= ERROR_DRM_VENDOR_MAX); } diff --git a/media/libmedia/MediaProfiles.cpp b/media/libmedia/MediaProfiles.cpp index d2e181b..e2e6042 100644 --- a/media/libmedia/MediaProfiles.cpp +++ b/media/libmedia/MediaProfiles.cpp @@ -87,6 +87,7 @@ const MediaProfiles::NameToTagMap MediaProfiles::sCamcorderQualityNameMap[] = { {"highspeed480p", CAMCORDER_QUALITY_HIGH_SPEED_480P}, {"highspeed720p", CAMCORDER_QUALITY_HIGH_SPEED_720P}, {"highspeed1080p", CAMCORDER_QUALITY_HIGH_SPEED_1080P}, + {"highspeed2160p", CAMCORDER_QUALITY_HIGH_SPEED_2160P}, }; #if LOG_NDEBUG diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDecoderPassThrough.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerDecoderPassThrough.cpp index c9be0dd..ab7906a 100644 --- a/media/libmediaplayerservice/nuplayer/NuPlayerDecoderPassThrough.cpp +++ b/media/libmediaplayerservice/nuplayer/NuPlayerDecoderPassThrough.cpp @@ -115,9 +115,12 @@ void NuPlayer::DecoderPassThrough::requestABuffer() { notify->post(); mPendingBuffers++; - sp<AMessage> message = new AMessage(kWhatRequestABuffer, id()); - message->setInt32("generation", mBufferGeneration); - message->post(); + // pending buffers will already result in requestABuffer + if (mPendingBuffers < kMaxPendingBuffers) { + sp<AMessage> message = new AMessage(kWhatRequestABuffer, id()); + message->setInt32("generation", mBufferGeneration); + message->post(); + } return; } @@ -155,9 +158,7 @@ void android::NuPlayer::DecoderPassThrough::onInputBufferFilled( void NuPlayer::DecoderPassThrough::onBufferConsumed(int32_t size) { mPendingBuffers--; mCachedBytes -= size; - sp<AMessage> message = new AMessage(kWhatRequestABuffer, id()); - message->setInt32("generation", mBufferGeneration); - message->post(); + requestABuffer(); } void NuPlayer::DecoderPassThrough::onFlush() { diff --git a/media/libstagefright/MediaCodec.cpp b/media/libstagefright/MediaCodec.cpp index fc2dd30..0bfc6e4 100644 --- a/media/libstagefright/MediaCodec.cpp +++ b/media/libstagefright/MediaCodec.cpp @@ -270,7 +270,20 @@ status_t MediaCodec::configure( } sp<AMessage> response; - return PostAndAwaitResponse(msg, &response); + status_t err = PostAndAwaitResponse(msg, &response); + + if (err != OK && err != INVALID_OPERATION) { + // MediaCodec now set state to UNINITIALIZED upon any fatal error. + // To maintain backward-compatibility, do a reset() to put codec + // back into INITIALIZED state. + // But don't reset if the err is INVALID_OPERATION, which means + // the configure failure is due to wrong state. + + ALOGE("configure failed with err 0x%08x, resetting...", err); + reset(); + } + + return err; } status_t MediaCodec::createInputSurface( diff --git a/media/libstagefright/codecs/aacdec/SoftAAC2.cpp b/media/libstagefright/codecs/aacdec/SoftAAC2.cpp index 6dd9b92..8b4dd6f 100644 --- a/media/libstagefright/codecs/aacdec/SoftAAC2.cpp +++ b/media/libstagefright/codecs/aacdec/SoftAAC2.cpp @@ -14,8 +14,8 @@ * limitations under the License. */ -//#define LOG_NDEBUG 0 #define LOG_TAG "SoftAAC2" +//#define LOG_NDEBUG 0 #include <utils/Log.h> #include "SoftAAC2.h" @@ -68,6 +68,7 @@ SoftAAC2::SoftAAC2( mOutputBufferCount(0), mSignalledError(false), mLastInHeader(NULL), + mCurrentInputTime(0), mOutputPortSettingsChange(NONE) { initPorts(); CHECK_EQ(initDecoder(), (status_t)OK); @@ -609,24 +610,9 @@ void SoftAAC2::onQueueFilled(OMX_U32 /* portIndex */) { notify(OMX_EventError, OMX_ErrorStreamCorrupt, ERROR_MALFORMED, NULL); return; } - - // insert buffer size and time stamp - mBufferSizes.add(inBufferLength[0]); - if (mLastInHeader != inHeader) { - mBufferTimestamps.add(inHeader->nTimeStamp); - mLastInHeader = inHeader; - } else { - int64_t currentTime = mBufferTimestamps.top(); - currentTime += mStreamInfo->aacSamplesPerFrame * - 1000000ll / mStreamInfo->sampleRate; - mBufferTimestamps.add(currentTime); - } } else { inBuffer[0] = inHeader->pBuffer + inHeader->nOffset; inBufferLength[0] = inHeader->nFilledLen; - mLastInHeader = inHeader; - mBufferTimestamps.add(inHeader->nTimeStamp); - mBufferSizes.add(inHeader->nFilledLen); } // Fill and decode @@ -635,130 +621,136 @@ void SoftAAC2::onQueueFilled(OMX_U32 /* portIndex */) { INT prevSampleRate = mStreamInfo->sampleRate; INT prevNumChannels = mStreamInfo->numChannels; + if (inHeader != mLastInHeader) { + mLastInHeader = inHeader; + mCurrentInputTime = inHeader->nTimeStamp; + } else { + if (mStreamInfo->sampleRate) { + mCurrentInputTime += mStreamInfo->aacSamplesPerFrame * + 1000000ll / mStreamInfo->sampleRate; + } else { + ALOGW("no sample rate yet"); + } + } + mAnchorTimes.add(mCurrentInputTime); aacDecoder_Fill(mAACDecoder, inBuffer, inBufferLength, bytesValid); - // run DRC check - mDrcWrap.submitStreamData(mStreamInfo); - mDrcWrap.update(); + // run DRC check + mDrcWrap.submitStreamData(mStreamInfo); + mDrcWrap.update(); - UINT inBufferUsedLength = inBufferLength[0] - bytesValid[0]; - inHeader->nFilledLen -= inBufferUsedLength; - inHeader->nOffset += inBufferUsedLength; + AAC_DECODER_ERROR decoderErr = + aacDecoder_DecodeFrame(mAACDecoder, + tmpOutBuffer, + 2048 * MAX_CHANNEL_COUNT, + 0 /* flags */); - AAC_DECODER_ERROR decoderErr; - do { - int numconsumed = mStreamInfo->numTotalBytes + mStreamInfo->numBadBytes; - decoderErr = aacDecoder_DecodeFrame(mAACDecoder, - tmpOutBuffer, - 2048 * MAX_CHANNEL_COUNT, - 0 /* flags */); + if (decoderErr != AAC_DEC_OK) { + ALOGW("aacDecoder_DecodeFrame decoderErr = 0x%4.4x", decoderErr); + } - numconsumed = (mStreamInfo->numTotalBytes + mStreamInfo->numBadBytes) - numconsumed; - if (numconsumed != 0) { - mDecodedSizes.add(numconsumed); - } + if (decoderErr == AAC_DEC_NOT_ENOUGH_BITS) { + ALOGE("AAC_DEC_NOT_ENOUGH_BITS should never happen"); + mSignalledError = true; + notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL); + return; + } - if (decoderErr == AAC_DEC_NOT_ENOUGH_BITS) { - break; - } + if (bytesValid[0] != 0) { + ALOGE("bytesValid[0] != 0 should never happen"); + mSignalledError = true; + notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL); + return; + } - if (decoderErr != AAC_DEC_OK) { - ALOGW("aacDecoder_DecodeFrame decoderErr = 0x%4.4x", decoderErr); - } + size_t numOutBytes = + mStreamInfo->frameSize * sizeof(int16_t) * mStreamInfo->numChannels; - if (bytesValid[0] != 0) { - ALOGE("bytesValid[0] != 0 should never happen"); + if (decoderErr == AAC_DEC_OK) { + if (!outputDelayRingBufferPutSamples(tmpOutBuffer, + mStreamInfo->frameSize * mStreamInfo->numChannels)) { mSignalledError = true; - notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL); + notify(OMX_EventError, OMX_ErrorUndefined, decoderErr, NULL); return; } + UINT inBufferUsedLength = inBufferLength[0] - bytesValid[0]; + inHeader->nFilledLen -= inBufferUsedLength; + inHeader->nOffset += inBufferUsedLength; + } else { + ALOGW("AAC decoder returned error 0x%4.4x, substituting silence", decoderErr); - size_t numOutBytes = - mStreamInfo->frameSize * sizeof(int16_t) * mStreamInfo->numChannels; - - if (decoderErr == AAC_DEC_OK) { - if (!outputDelayRingBufferPutSamples(tmpOutBuffer, - mStreamInfo->frameSize * mStreamInfo->numChannels)) { - mSignalledError = true; - notify(OMX_EventError, OMX_ErrorUndefined, decoderErr, NULL); - return; - } - } else { - ALOGW("AAC decoder returned error 0x%4.4x, substituting silence", decoderErr); - - memset(tmpOutBuffer, 0, numOutBytes); // TODO: check for overflow - - if (!outputDelayRingBufferPutSamples(tmpOutBuffer, - mStreamInfo->frameSize * mStreamInfo->numChannels)) { - mSignalledError = true; - notify(OMX_EventError, OMX_ErrorUndefined, decoderErr, NULL); - return; - } + memset(tmpOutBuffer, 0, numOutBytes); // TODO: check for overflow - // Discard input buffer. - inHeader->nFilledLen = 0; + if (!outputDelayRingBufferPutSamples(tmpOutBuffer, + mStreamInfo->frameSize * mStreamInfo->numChannels)) { + mSignalledError = true; + notify(OMX_EventError, OMX_ErrorUndefined, decoderErr, NULL); + return; + } - aacDecoder_SetParam(mAACDecoder, AAC_TPDEC_CLEAR_BUFFER, 1); + // Discard input buffer. + inHeader->nFilledLen = 0; + + aacDecoder_SetParam(mAACDecoder, AAC_TPDEC_CLEAR_BUFFER, 1); + + // fall through + } + + /* + * AAC+/eAAC+ streams can be signalled in two ways: either explicitly + * or implicitly, according to MPEG4 spec. AAC+/eAAC+ is a dual + * rate system and the sampling rate in the final output is actually + * doubled compared with the core AAC decoder sampling rate. + * + * Explicit signalling is done by explicitly defining SBR audio object + * type in the bitstream. Implicit signalling is done by embedding + * SBR content in AAC extension payload specific to SBR, and hence + * requires an AAC decoder to perform pre-checks on actual audio frames. + * + * Thus, we could not say for sure whether a stream is + * AAC+/eAAC+ until the first data frame is decoded. + */ + if (mInputBufferCount <= 2 || mOutputBufferCount > 1) { // TODO: <= 1 + if (mStreamInfo->sampleRate != prevSampleRate || + mStreamInfo->numChannels != prevNumChannels) { + ALOGI("Reconfiguring decoder: %d->%d Hz, %d->%d channels", + prevSampleRate, mStreamInfo->sampleRate, + prevNumChannels, mStreamInfo->numChannels); - // fall through - } + notify(OMX_EventPortSettingsChanged, 1, 0, NULL); + mOutputPortSettingsChange = AWAITING_DISABLED; - /* - * AAC+/eAAC+ streams can be signalled in two ways: either explicitly - * or implicitly, according to MPEG4 spec. AAC+/eAAC+ is a dual - * rate system and the sampling rate in the final output is actually - * doubled compared with the core AAC decoder sampling rate. - * - * Explicit signalling is done by explicitly defining SBR audio object - * type in the bitstream. Implicit signalling is done by embedding - * SBR content in AAC extension payload specific to SBR, and hence - * requires an AAC decoder to perform pre-checks on actual audio frames. - * - * Thus, we could not say for sure whether a stream is - * AAC+/eAAC+ until the first data frame is decoded. - */ - if (mInputBufferCount <= 2 || mOutputBufferCount > 1) { // TODO: <= 1 - if (mStreamInfo->sampleRate != prevSampleRate || - mStreamInfo->numChannels != prevNumChannels) { - ALOGI("Reconfiguring decoder: %d->%d Hz, %d->%d channels", - prevSampleRate, mStreamInfo->sampleRate, - prevNumChannels, mStreamInfo->numChannels); - - notify(OMX_EventPortSettingsChanged, 1, 0, NULL); - mOutputPortSettingsChange = AWAITING_DISABLED; - - if (inHeader->nFilledLen == 0) { - inInfo->mOwnedByUs = false; - mInputBufferCount++; - inQueue.erase(inQueue.begin()); - mLastInHeader = NULL; - inInfo = NULL; - notifyEmptyBufferDone(inHeader); - inHeader = NULL; - } - return; + if (inHeader->nFilledLen == 0) { + inInfo->mOwnedByUs = false; + mInputBufferCount++; + inQueue.erase(inQueue.begin()); + mLastInHeader = NULL; + inInfo = NULL; + notifyEmptyBufferDone(inHeader); + inHeader = NULL; } - } else if (!mStreamInfo->sampleRate || !mStreamInfo->numChannels) { - ALOGW("Invalid AAC stream"); - mSignalledError = true; - notify(OMX_EventError, OMX_ErrorUndefined, decoderErr, NULL); return; } - if (inHeader && inHeader->nFilledLen == 0) { - inInfo->mOwnedByUs = false; - mInputBufferCount++; - inQueue.erase(inQueue.begin()); - mLastInHeader = NULL; - inInfo = NULL; - notifyEmptyBufferDone(inHeader); - inHeader = NULL; - } else { - ALOGV("inHeader->nFilledLen = %d", inHeader ? inHeader->nFilledLen : 0); - } - } while (decoderErr == AAC_DEC_OK); + } else if (!mStreamInfo->sampleRate || !mStreamInfo->numChannels) { + ALOGW("Invalid AAC stream"); + mSignalledError = true; + notify(OMX_EventError, OMX_ErrorUndefined, decoderErr, NULL); + return; + } + if (inHeader->nFilledLen == 0) { + inInfo->mOwnedByUs = false; + mInputBufferCount++; + inQueue.erase(inQueue.begin()); + mLastInHeader = NULL; + inInfo = NULL; + notifyEmptyBufferDone(inHeader); + inHeader = NULL; + } else { + ALOGV("inHeader->nFilledLen = %d", inHeader->nFilledLen); + } } int32_t outputDelay = mStreamInfo->outputDelay * mStreamInfo->numChannels; @@ -817,9 +809,8 @@ void SoftAAC2::onQueueFilled(OMX_U32 /* portIndex */) { INT_PCM *outBuffer = reinterpret_cast<INT_PCM *>(outHeader->pBuffer + outHeader->nOffset); - int samplesize = mStreamInfo->numChannels * sizeof(int16_t); if (outHeader->nOffset - + mStreamInfo->frameSize * samplesize + + mStreamInfo->frameSize * mStreamInfo->numChannels * sizeof(int16_t) > outHeader->nAllocLen) { ALOGE("buffer overflow"); mSignalledError = true; @@ -827,67 +818,17 @@ void SoftAAC2::onQueueFilled(OMX_U32 /* portIndex */) { return; } - - int available = outputDelayRingBufferSamplesAvailable(); - int numSamples = outHeader->nAllocLen / samplesize; - if (numSamples > available) { - numSamples = available; - } - int64_t currentTime = 0; - if (available) { - - int numFrames = numSamples / (mStreamInfo->frameSize * mStreamInfo->numChannels); - numSamples = numFrames * (mStreamInfo->frameSize * mStreamInfo->numChannels); - - ALOGV("%d samples available (%d), or %d frames", - numSamples, available, numFrames); - int64_t *nextTimeStamp = &mBufferTimestamps.editItemAt(0); - currentTime = *nextTimeStamp; - int32_t *currentBufLeft = &mBufferSizes.editItemAt(0); - for (int i = 0; i < numFrames; i++) { - int32_t decodedSize = mDecodedSizes.itemAt(0); - mDecodedSizes.removeAt(0); - ALOGV("decoded %d of %d", decodedSize, *currentBufLeft); - if (*currentBufLeft > decodedSize) { - // adjust/interpolate next time stamp - *currentBufLeft -= decodedSize; - *nextTimeStamp += mStreamInfo->aacSamplesPerFrame * - 1000000ll / mStreamInfo->sampleRate; - ALOGV("adjusted nextTimeStamp/size to %lld/%d", - *nextTimeStamp, *currentBufLeft); - } else { - // move to next timestamp in list - if (mBufferTimestamps.size() > 0) { - mBufferTimestamps.removeAt(0); - nextTimeStamp = &mBufferTimestamps.editItemAt(0); - mBufferSizes.removeAt(0); - currentBufLeft = &mBufferSizes.editItemAt(0); - ALOGV("moved to next time/size: %lld/%d", - *nextTimeStamp, *currentBufLeft); - } - // try to limit output buffer size to match input buffers - // (e.g when an input buffer contained 4 "sub" frames, output - // at most 4 decoded units in the corresponding output buffer) - // This is optional. Remove the next three lines to fill the output - // buffer with as many units as available. - numFrames = i + 1; - numSamples = numFrames * mStreamInfo->frameSize * mStreamInfo->numChannels; - break; - } - } - - ALOGV("getting %d from ringbuffer", numSamples); - int32_t ns = outputDelayRingBufferGetSamples(outBuffer, numSamples); - if (ns != numSamples) { - ALOGE("not a complete frame of samples available"); - mSignalledError = true; - notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL); - return; - } + int32_t ns = outputDelayRingBufferGetSamples(outBuffer, + mStreamInfo->frameSize * mStreamInfo->numChannels); // TODO: check for overflow + if (ns != mStreamInfo->frameSize * mStreamInfo->numChannels) { + ALOGE("not a complete frame of samples available"); + mSignalledError = true; + notify(OMX_EventError, OMX_ErrorUndefined, 0, NULL); + return; } - outHeader->nFilledLen = numSamples * sizeof(int16_t); - + outHeader->nFilledLen = mStreamInfo->frameSize * mStreamInfo->numChannels + * sizeof(int16_t); if (mEndOfInput && !outQueue.empty() && outputDelayRingBufferSamplesAvailable() == 0) { outHeader->nFlags = OMX_BUFFERFLAG_EOS; mEndOfOutput = true; @@ -895,13 +836,13 @@ void SoftAAC2::onQueueFilled(OMX_U32 /* portIndex */) { outHeader->nFlags = 0; } - outHeader->nTimeStamp = currentTime; + outHeader->nTimeStamp = mAnchorTimes.isEmpty() ? 0 : mAnchorTimes.itemAt(0); + mAnchorTimes.removeAt(0); mOutputBufferCount++; outInfo->mOwnedByUs = false; outQueue.erase(outQueue.begin()); outInfo = NULL; - ALOGV("out timestamp %lld / %d", outHeader->nTimeStamp, outHeader->nFilledLen); notifyFillBufferDone(outHeader); outHeader = NULL; } @@ -936,10 +877,8 @@ void SoftAAC2::onQueueFilled(OMX_U32 /* portIndex */) { outHeader->nFilledLen = 0; outHeader->nFlags = OMX_BUFFERFLAG_EOS; - outHeader->nTimeStamp = mBufferTimestamps.itemAt(0); - mBufferTimestamps.clear(); - mBufferSizes.clear(); - mDecodedSizes.clear(); + outHeader->nTimeStamp = mAnchorTimes.itemAt(0); + mAnchorTimes.removeAt(0); mOutputBufferCount++; outInfo->mOwnedByUs = false; @@ -960,9 +899,7 @@ void SoftAAC2::onPortFlushCompleted(OMX_U32 portIndex) { // depend on fragments from the last one decoded. // drain all existing data drainDecoder(); - mBufferTimestamps.clear(); - mBufferSizes.clear(); - mDecodedSizes.clear(); + mAnchorTimes.clear(); mLastInHeader = NULL; } else { while (outputDelayRingBufferSamplesAvailable() > 0) { @@ -1018,9 +955,7 @@ void SoftAAC2::onReset() { mOutputDelayRingBufferReadPos = 0; mEndOfInput = false; mEndOfOutput = false; - mBufferTimestamps.clear(); - mBufferSizes.clear(); - mDecodedSizes.clear(); + mAnchorTimes.clear(); mLastInHeader = NULL; // To make the codec behave the same before and after a reset, we need to invalidate the diff --git a/media/libstagefright/codecs/aacdec/SoftAAC2.h b/media/libstagefright/codecs/aacdec/SoftAAC2.h index 9fcb598..865bd15 100644 --- a/media/libstagefright/codecs/aacdec/SoftAAC2.h +++ b/media/libstagefright/codecs/aacdec/SoftAAC2.h @@ -59,9 +59,8 @@ private: size_t mOutputBufferCount; bool mSignalledError; OMX_BUFFERHEADERTYPE *mLastInHeader; - Vector<int32_t> mBufferSizes; - Vector<int32_t> mDecodedSizes; - Vector<int64_t> mBufferTimestamps; + int64_t mCurrentInputTime; + Vector<int64_t> mAnchorTimes; CDrcPresModeWrapper mDrcWrap; diff --git a/services/audioflinger/PatchPanel.cpp b/services/audioflinger/PatchPanel.cpp index 2d0a25f..7544052 100644 --- a/services/audioflinger/PatchPanel.cpp +++ b/services/audioflinger/PatchPanel.cpp @@ -593,10 +593,10 @@ status_t AudioFlinger::PatchPanel::releaseAudioPatch(audio_patch_handle_t handle status = BAD_VALUE; break; } - status = thread->sendReleaseAudioPatchConfigEvent(mPatches[index]->mHalHandle); + status = thread->sendReleaseAudioPatchConfigEvent(removedPatch->mHalHandle); } else { audio_hw_device_t *hwDevice = audioHwDevice->hwDevice(); - status = hwDevice->release_audio_patch(hwDevice, mPatches[index]->mHalHandle); + status = hwDevice->release_audio_patch(hwDevice, removedPatch->mHalHandle); } } else { sp<ThreadBase> thread = audioflinger->checkRecordThread_l( @@ -632,7 +632,7 @@ status_t AudioFlinger::PatchPanel::releaseAudioPatch(audio_patch_handle_t handle } AudioHwDevice *audioHwDevice = audioflinger->mAudioHwDevs.valueAt(index); if (audioHwDevice->version() >= AUDIO_DEVICE_API_VERSION_3_0) { - status = thread->sendReleaseAudioPatchConfigEvent(mPatches[index]->mHalHandle); + status = thread->sendReleaseAudioPatchConfigEvent(removedPatch->mHalHandle); } else { AudioParameter param; param.addInt(String8(AUDIO_PARAMETER_STREAM_ROUTING), 0); diff --git a/services/camera/libcameraservice/Android.mk b/services/camera/libcameraservice/Android.mk index 9d6ab23..e184d97 100644 --- a/services/camera/libcameraservice/Android.mk +++ b/services/camera/libcameraservice/Android.mk @@ -34,6 +34,7 @@ LOCAL_SRC_FILES:= \ api1/client2/JpegProcessor.cpp \ api1/client2/CallbackProcessor.cpp \ api1/client2/ZslProcessor.cpp \ + api1/client2/ZslProcessorInterface.cpp \ api1/client2/BurstCapture.cpp \ api1/client2/JpegCompressor.cpp \ api1/client2/CaptureSequencer.cpp \ diff --git a/services/camera/libcameraservice/api1/Camera2Client.cpp b/services/camera/libcameraservice/api1/Camera2Client.cpp index d59ee51..36a93b2 100644 --- a/services/camera/libcameraservice/api1/Camera2Client.cpp +++ b/services/camera/libcameraservice/api1/Camera2Client.cpp @@ -434,6 +434,9 @@ void Camera2Client::disconnect() { mCallbackProcessor->deleteStream(); mZslProcessor->deleteStream(); + // Remove all ZSL stream state before disconnect; needed to work around b/15408128. + mZslProcessor->disconnect(); + ALOGV("Camera %d: Disconnecting device", mCameraId); mDevice->disconnect(); diff --git a/services/camera/libcameraservice/api1/client2/ZslProcessor.cpp b/services/camera/libcameraservice/api1/client2/ZslProcessor.cpp index 8fb876e..bb72206 100644 --- a/services/camera/libcameraservice/api1/client2/ZslProcessor.cpp +++ b/services/camera/libcameraservice/api1/client2/ZslProcessor.cpp @@ -48,6 +48,7 @@ ZslProcessor::ZslProcessor( mDevice(client->getCameraDevice()), mSequencer(sequencer), mId(client->getCameraId()), + mDeleted(false), mZslBufferAvailable(false), mZslStreamId(NO_STREAM), mZslReprocessStreamId(NO_STREAM), @@ -62,7 +63,7 @@ ZslProcessor::ZslProcessor( ZslProcessor::~ZslProcessor() { ALOGV("%s: Exit", __FUNCTION__); - deleteStream(); + disconnect(); } void ZslProcessor::onFrameAvailable() { @@ -153,7 +154,7 @@ status_t ZslProcessor::updateStream(const Parameters ¶ms) { mId, strerror(-res), res); return res; } - if (currentWidth != (uint32_t)params.fastInfo.arrayWidth || + if (mDeleted || currentWidth != (uint32_t)params.fastInfo.arrayWidth || currentHeight != (uint32_t)params.fastInfo.arrayHeight) { res = device->deleteReprocessStream(mZslReprocessStreamId); if (res != OK) { @@ -175,6 +176,8 @@ status_t ZslProcessor::updateStream(const Parameters ¶ms) { } } + mDeleted = false; + if (mZslStreamId == NO_STREAM) { // Create stream for HAL production // TODO: Sort out better way to select resolution for ZSL @@ -209,6 +212,14 @@ status_t ZslProcessor::updateStream(const Parameters ¶ms) { status_t ZslProcessor::deleteStream() { ATRACE_CALL(); + Mutex::Autolock l(mInputMutex); + // WAR(b/15408128): do not delete stream unless client is being disconnected. + mDeleted = true; + return OK; +} + +status_t ZslProcessor::disconnect() { + ATRACE_CALL(); status_t res; Mutex::Autolock l(mInputMutex); diff --git a/services/camera/libcameraservice/api1/client2/ZslProcessor.h b/services/camera/libcameraservice/api1/client2/ZslProcessor.h index f4cf0c8..b6533cf 100644 --- a/services/camera/libcameraservice/api1/client2/ZslProcessor.h +++ b/services/camera/libcameraservice/api1/client2/ZslProcessor.h @@ -67,6 +67,7 @@ class ZslProcessor: status_t updateStream(const Parameters ¶ms); status_t deleteStream(); + status_t disconnect(); int getStreamId() const; status_t pushToReprocess(int32_t requestId); @@ -86,6 +87,8 @@ class ZslProcessor: wp<CaptureSequencer> mSequencer; int mId; + bool mDeleted; + mutable Mutex mInputMutex; bool mZslBufferAvailable; Condition mZslBufferAvailableSignal; diff --git a/services/camera/libcameraservice/api1/client2/ZslProcessorInterface.cpp b/services/camera/libcameraservice/api1/client2/ZslProcessorInterface.cpp new file mode 100644 index 0000000..9efeaba --- /dev/null +++ b/services/camera/libcameraservice/api1/client2/ZslProcessorInterface.cpp @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ZslProcessorInterface.h" + +namespace android { +namespace camera2 { + +status_t ZslProcessorInterface::disconnect() { + return OK; +} + +}; //namespace camera2 +}; //namespace android + diff --git a/services/camera/libcameraservice/api1/client2/ZslProcessorInterface.h b/services/camera/libcameraservice/api1/client2/ZslProcessorInterface.h index 183c0c2..9e266e7 100644 --- a/services/camera/libcameraservice/api1/client2/ZslProcessorInterface.h +++ b/services/camera/libcameraservice/api1/client2/ZslProcessorInterface.h @@ -19,6 +19,8 @@ #include <utils/Errors.h> #include <utils/RefBase.h> +#include <utils/String16.h> +#include <utils/Vector.h> namespace android { namespace camera2 { @@ -37,6 +39,9 @@ public: // Delete the underlying CameraDevice streams virtual status_t deleteStream() = 0; + // Clear any additional state necessary before the CameraDevice is disconnected + virtual status_t disconnect(); + /** * Submits a ZSL capture request (id = requestId) * |