summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/media/MediaProfiles.h3
-rw-r--r--include/media/stagefright/MediaErrors.h32
-rw-r--r--media/libmedia/MediaProfiles.cpp1
-rw-r--r--media/libmediaplayerservice/nuplayer/NuPlayerDecoderPassThrough.cpp13
-rw-r--r--media/libstagefright/MediaCodec.cpp15
-rw-r--r--media/libstagefright/codecs/aacdec/SoftAAC2.cpp317
-rw-r--r--media/libstagefright/codecs/aacdec/SoftAAC2.h5
-rw-r--r--services/audioflinger/PatchPanel.cpp6
-rw-r--r--services/camera/libcameraservice/Android.mk1
-rw-r--r--services/camera/libcameraservice/api1/Camera2Client.cpp3
-rw-r--r--services/camera/libcameraservice/api1/client2/ZslProcessor.cpp15
-rw-r--r--services/camera/libcameraservice/api1/client2/ZslProcessor.h3
-rw-r--r--services/camera/libcameraservice/api1/client2/ZslProcessorInterface.cpp28
-rw-r--r--services/camera/libcameraservice/api1/client2/ZslProcessorInterface.h5
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 &params) {
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 &params) {
}
}
+ 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 &params) {
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 &params);
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)
*