Merge "CameraNDK: remove unused error enum values" into nyc-dev
diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp
index 35f439b..cd91e72 100644
--- a/media/libmediaplayerservice/MediaPlayerService.cpp
+++ b/media/libmediaplayerservice/MediaPlayerService.cpp
@@ -2150,7 +2150,7 @@
//
// The underrun event is sent once per track underrun; the condition is reset
// when more data is sent to the AudioTrack.
- ALOGI("callbackwrapper: EVENT_UNDERRUN (discarded)");
+ ALOGD("callbackwrapper: EVENT_UNDERRUN (discarded)");
break;
default:
diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp
index 238cd35..99996ed 100644
--- a/media/libstagefright/ACodec.cpp
+++ b/media/libstagefright/ACodec.cpp
@@ -5704,7 +5704,8 @@
OMX_U32 flags = OMX_BUFFERFLAG_ENDOFFRAME;
- int32_t isCSD;
+ MetadataBufferType metaType = mCodec->mInputMetadataType;
+ int32_t isCSD = 0;
if (buffer->meta()->findInt32("csd", &isCSD) && isCSD != 0) {
if (mCodec->mIsLegacyVP9Decoder) {
ALOGV("[%s] is legacy VP9 decoder. Ignore %u codec specific data",
@@ -5713,6 +5714,7 @@
break;
}
flags |= OMX_BUFFERFLAG_CODECCONFIG;
+ metaType = kMetadataBufferTypeInvalid;
}
if (eos) {
@@ -5726,7 +5728,7 @@
buffer.get(), info->mCodecData.get());
sp<DataConverter> converter = mCodec->mConverter[kPortIndexInput];
- if (converter == NULL) {
+ if (converter == NULL || isCSD) {
converter = getCopyConverter();
}
status_t err = converter->convert(buffer, info->mCodecData);
@@ -5772,14 +5774,50 @@
}
}
info->checkReadFence("onInputBufferFilled");
- status_t err2 = mCodec->mOMX->emptyBuffer(
- mCodec->mNode,
- bufferID,
- 0,
- info->mCodecData->size(),
- flags,
- timeUs,
- info->mFenceFd);
+
+ status_t err2 = OK;
+ switch (metaType) {
+ case kMetadataBufferTypeInvalid:
+ break;
+#ifndef OMX_ANDROID_COMPILE_AS_32BIT_ON_64BIT_PLATFORMS
+ case kMetadataBufferTypeNativeHandleSource:
+ if (info->mCodecData->size() >= sizeof(VideoNativeHandleMetadata)) {
+ VideoNativeHandleMetadata *vnhmd =
+ (VideoNativeHandleMetadata*)info->mCodecData->base();
+ err2 = mCodec->mOMX->updateNativeHandleInMeta(
+ mCodec->mNode, kPortIndexInput,
+ NativeHandle::create(vnhmd->pHandle, false /* ownsHandle */),
+ bufferID);
+ }
+ break;
+ case kMetadataBufferTypeANWBuffer:
+ if (info->mCodecData->size() >= sizeof(VideoNativeMetadata)) {
+ VideoNativeMetadata *vnmd = (VideoNativeMetadata*)info->mCodecData->base();
+ err2 = mCodec->mOMX->updateGraphicBufferInMeta(
+ mCodec->mNode, kPortIndexInput,
+ new GraphicBuffer(vnmd->pBuffer, false /* keepOwnership */),
+ bufferID);
+ }
+ break;
+#endif
+ default:
+ ALOGW("Can't marshall %s data in %zu sized buffers in %zu-bit mode",
+ asString(metaType), info->mCodecData->size(),
+ sizeof(buffer_handle_t) * 8);
+ err2 = ERROR_UNSUPPORTED;
+ break;
+ }
+
+ if (err2 == OK) {
+ err2 = mCodec->mOMX->emptyBuffer(
+ mCodec->mNode,
+ bufferID,
+ 0,
+ info->mCodecData->size(),
+ flags,
+ timeUs,
+ info->mFenceFd);
+ }
info->mFenceFd = -1;
if (err2 != OK) {
mCodec->signalError(OMX_ErrorUndefined, makeNoSideEffectStatus(err2));
diff --git a/media/libstagefright/OMXClient.cpp b/media/libstagefright/OMXClient.cpp
index 4dde5f6..7279f6c 100644
--- a/media/libstagefright/OMXClient.cpp
+++ b/media/libstagefright/OMXClient.cpp
@@ -207,9 +207,13 @@
// static
MuxOMX::node_location MuxOMX::getPreferredCodecLocation(const char *name) {
if (sCodecProcessEnabled) {
- // all non-secure decoders plus OMX.google.* encoders can go in the codec process
- if ((strcasestr(name, "decoder") && !strcasestr(name, "secure")) ||
- !strncasecmp(name, "OMX.google.", 11)) {
+ // all non-secure decoders, OMX.google.* codecs and encoders can go in the codec process
+ // (non-OMX.google.* encoders can be excluded using system property.)
+ if ((strcasestr(name, "decoder")
+ && strcasestr(name, ".secure") != name + strlen(name) - 7)
+ || (strcasestr(name, "encoder")
+ && !property_get_bool("media.stagefright.legacyencoder", false))
+ || !strncasecmp(name, "OMX.google.", 11)) {
return CODECPROCESS;
}
// everything else runs in the media server
@@ -409,8 +413,16 @@
status_t MuxOMX::createPersistentInputSurface(
sp<IGraphicBufferProducer> *bufferProducer,
sp<IGraphicBufferConsumer> *bufferConsumer) {
- // TODO: local or remote? Always use remote for now
- return mMediaServerOMX->createPersistentInputSurface(
+ sp<IOMX> omx;
+ {
+ Mutex::Autolock autoLock(mLock);
+ if (property_get_bool("media.stagefright.legacyencoder", false)) {
+ omx = mMediaServerOMX;
+ } else {
+ omx = mMediaCodecOMX;
+ }
+ }
+ return omx->createPersistentInputSurface(
bufferProducer, bufferConsumer);
}
diff --git a/media/libstagefright/codecs/avcdec/SoftAVCDec.cpp b/media/libstagefright/codecs/avcdec/SoftAVCDec.cpp
index 1e64b49..973c528 100644
--- a/media/libstagefright/codecs/avcdec/SoftAVCDec.cpp
+++ b/media/libstagefright/codecs/avcdec/SoftAVCDec.cpp
@@ -638,6 +638,8 @@
mChangingResolution = false;
resetDecoder();
resetPlugin();
+ mStride = outputBufferWidth();
+ setParams(mStride);
continue;
}
diff --git a/media/libstagefright/codecs/mpeg2dec/SoftMPEG2.cpp b/media/libstagefright/codecs/mpeg2dec/SoftMPEG2.cpp
index 8283ab5..27f860e 100644
--- a/media/libstagefright/codecs/mpeg2dec/SoftMPEG2.cpp
+++ b/media/libstagefright/codecs/mpeg2dec/SoftMPEG2.cpp
@@ -74,7 +74,8 @@
mIvColorFormat(IV_YUV_420P),
mNewWidth(mWidth),
mNewHeight(mHeight),
- mChangingResolution(false) {
+ mChangingResolution(false),
+ mStride(mWidth) {
initPorts(kNumBuffers, INPUT_BUF_SIZE, kNumBuffers, CODEC_MIME_TYPE);
// If input dump is enabled, then open create an empty file
@@ -202,6 +203,8 @@
/* Set number of cores/threads to be used by the codec */
setNumCores();
+ mStride = 0;
+
return OK;
}
@@ -384,7 +387,8 @@
resetPlugin();
/* Set the run time (dynamic) parameters */
- setParams(displayStride);
+ mStride = outputBufferWidth();
+ setParams(mStride);
/* Set number of cores/threads to be used by the codec */
setNumCores();
@@ -548,6 +552,12 @@
List<BufferInfo *> &inQueue = getPortQueue(kInputPortIndex);
List<BufferInfo *> &outQueue = getPortQueue(kOutputPortIndex);
+ if (outputBufferWidth() != mStride) {
+ /* Set the run-time (dynamic) parameters */
+ mStride = outputBufferWidth();
+ setParams(mStride);
+ }
+
/* If input EOS is seen and decoder is not in flush mode,
* set the decoder in flush mode.
* There can be a case where EOS is sent along with last picture data
@@ -686,6 +696,8 @@
mChangingResolution = false;
resetDecoder();
resetPlugin();
+ mStride = outputBufferWidth();
+ setParams(mStride);
continue;
}
diff --git a/media/libstagefright/codecs/mpeg2dec/SoftMPEG2.h b/media/libstagefright/codecs/mpeg2dec/SoftMPEG2.h
index f48b70b..025e9a0 100644
--- a/media/libstagefright/codecs/mpeg2dec/SoftMPEG2.h
+++ b/media/libstagefright/codecs/mpeg2dec/SoftMPEG2.h
@@ -106,6 +106,7 @@
bool mChangingResolution;
bool mFlushNeeded;
bool mWaitForI;
+ size_t mStride;
status_t initDecoder();
status_t deInitDecoder();
diff --git a/media/libstagefright/httplive/PlaylistFetcher.cpp b/media/libstagefright/httplive/PlaylistFetcher.cpp
index 20d124c..7ad7fee 100644
--- a/media/libstagefright/httplive/PlaylistFetcher.cpp
+++ b/media/libstagefright/httplive/PlaylistFetcher.cpp
@@ -1092,6 +1092,13 @@
// fall through
} else {
if (mPlaylist != NULL) {
+ if (mSeqNumber >= firstSeqNumberInPlaylist + (int32_t)mPlaylist->size()
+ && !mPlaylist->isComplete()) {
+ // Live playlists
+ ALOGW("sequence number %d not yet available", mSeqNumber);
+ postMonitorQueue(delayUsToRefreshPlaylist());
+ return false;
+ }
ALOGE("Cannot find sequence number %d in playlist "
"(contains %d - %d)",
mSeqNumber, firstSeqNumberInPlaylist,
diff --git a/media/libstagefright/include/OMXNodeInstance.h b/media/libstagefright/include/OMXNodeInstance.h
index e98156e..060b6be 100644
--- a/media/libstagefright/include/OMXNodeInstance.h
+++ b/media/libstagefright/include/OMXNodeInstance.h
@@ -241,9 +241,14 @@
OMX_BUFFERHEADERTYPE *header,
OMX_U32 flags, OMX_TICKS timestamp, intptr_t debugAddr, int fenceFd);
+ // Updates the graphic buffer handle in the metadata buffer for |buffer| and |header| to
+ // |graphicBuffer|'s handle. If |updateCodecBuffer| is true, the update will happen in
+ // the actual codec buffer (use this if not using emptyBuffer (with no _l) later to
+ // pass the buffer to the codec, as only emptyBuffer copies the backup buffer to the codec
+ // buffer.)
status_t updateGraphicBufferInMeta_l(
OMX_U32 portIndex, const sp<GraphicBuffer> &graphicBuffer,
- OMX::buffer_id buffer, OMX_BUFFERHEADERTYPE *header);
+ OMX::buffer_id buffer, OMX_BUFFERHEADERTYPE *header, bool updateCodecBuffer);
status_t createGraphicBufferSource(
OMX_U32 portIndex, sp<IGraphicBufferConsumer> consumer /* nullable */,
diff --git a/media/libstagefright/omx/OMXNodeInstance.cpp b/media/libstagefright/omx/OMXNodeInstance.cpp
index 31bab70..5445944 100644
--- a/media/libstagefright/omx/OMXNodeInstance.cpp
+++ b/media/libstagefright/omx/OMXNodeInstance.cpp
@@ -842,7 +842,7 @@
status_t OMXNodeInstance::updateGraphicBufferInMeta_l(
OMX_U32 portIndex, const sp<GraphicBuffer>& graphicBuffer,
- OMX::buffer_id buffer, OMX_BUFFERHEADERTYPE *header) {
+ OMX::buffer_id buffer, OMX_BUFFERHEADERTYPE *header, bool updateCodecBuffer) {
// No need to check |graphicBuffer| since NULL is valid for it as below.
if (header == NULL) {
ALOGE("b/25884056");
@@ -854,20 +854,27 @@
}
BufferMeta *bufferMeta = (BufferMeta *)(header->pAppPrivate);
+ sp<ABuffer> data = bufferMeta->getBuffer(
+ header, !updateCodecBuffer /* backup */, false /* limit */);
bufferMeta->setGraphicBuffer(graphicBuffer);
- if (mMetadataType[portIndex] == kMetadataBufferTypeGrallocSource
- && header->nAllocLen >= sizeof(VideoGrallocMetadata)) {
- VideoGrallocMetadata &metadata = *(VideoGrallocMetadata *)(header->pBuffer);
+ MetadataBufferType metaType = mMetadataType[portIndex];
+ // we use gralloc source only in the codec buffers
+ if (metaType == kMetadataBufferTypeGrallocSource && !updateCodecBuffer) {
+ metaType = kMetadataBufferTypeANWBuffer;
+ }
+ if (metaType == kMetadataBufferTypeGrallocSource
+ && data->capacity() >= sizeof(VideoGrallocMetadata)) {
+ VideoGrallocMetadata &metadata = *(VideoGrallocMetadata *)(data->data());
metadata.eType = kMetadataBufferTypeGrallocSource;
metadata.pHandle = graphicBuffer == NULL ? NULL : graphicBuffer->handle;
- } else if (mMetadataType[portIndex] == kMetadataBufferTypeANWBuffer
- && header->nAllocLen >= sizeof(VideoNativeMetadata)) {
- VideoNativeMetadata &metadata = *(VideoNativeMetadata *)(header->pBuffer);
+ } else if (metaType == kMetadataBufferTypeANWBuffer
+ && data->capacity() >= sizeof(VideoNativeMetadata)) {
+ VideoNativeMetadata &metadata = *(VideoNativeMetadata *)(data->data());
metadata.eType = kMetadataBufferTypeANWBuffer;
metadata.pBuffer = graphicBuffer == NULL ? NULL : graphicBuffer->getNativeBuffer();
metadata.nFenceFd = -1;
} else {
- CLOG_BUFFER(updateGraphicBufferInMeta, "%s:%u, %#x bad type (%d) or size (%u)",
+ CLOG_ERROR(updateGraphicBufferInMeta, BAD_VALUE, "%s:%u, %#x bad type (%d) or size (%u)",
portString(portIndex), portIndex, buffer, mMetadataType[portIndex], header->nAllocLen);
return BAD_VALUE;
}
@@ -883,7 +890,10 @@
OMX::buffer_id buffer) {
Mutex::Autolock autoLock(mLock);
OMX_BUFFERHEADERTYPE *header = findBufferHeader(buffer);
- return updateGraphicBufferInMeta_l(portIndex, graphicBuffer, buffer, header);
+ // update backup buffer for input, codec buffer for output
+ return updateGraphicBufferInMeta_l(
+ portIndex, graphicBuffer, buffer, header,
+ portIndex == kPortIndexOutput /* updateCodecBuffer */);
}
status_t OMXNodeInstance::updateNativeHandleInMeta(
@@ -1388,7 +1398,9 @@
Mutex::Autolock autoLock(mLock);
OMX::buffer_id buffer = findBufferID(header);
- status_t err = updateGraphicBufferInMeta_l(kPortIndexInput, graphicBuffer, buffer, header);
+ status_t err = updateGraphicBufferInMeta_l(
+ kPortIndexInput, graphicBuffer, buffer, header,
+ true /* updateCodecBuffer */);
if (err != OK) {
CLOG_ERROR(emptyGraphicBuffer, err, FULL_BUFFER(
(intptr_t)header->pBuffer, header, fenceFd));
@@ -1396,7 +1408,13 @@
}
header->nOffset = 0;
- header->nFilledLen = graphicBuffer == NULL ? 0 : header->nAllocLen;
+ if (graphicBuffer == NULL) {
+ header->nFilledLen = 0;
+ } else if (mMetadataType[kPortIndexInput] == kMetadataBufferTypeGrallocSource) {
+ header->nFilledLen = sizeof(VideoGrallocMetadata);
+ } else {
+ header->nFilledLen = sizeof(VideoNativeMetadata);
+ }
return emptyBuffer_l(header, flags, timestamp, (intptr_t)header->pBuffer, fenceFd);
}
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index 1d575b3..2b0d4c8 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -1843,8 +1843,7 @@
PlaybackThread *thread;
if (flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) {
- thread = new OffloadThread(this, outputStream, *output, devices, mSystemReady,
- config->offload_info.bit_rate);
+ thread = new OffloadThread(this, outputStream, *output, devices, mSystemReady);
ALOGV("openOutput_l() created offload output: ID %d thread %p", *output, thread);
} else if ((flags & AUDIO_OUTPUT_FLAG_DIRECT)
|| !isValidPcmSinkFormat(config->format)
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index bee0447..d296ee3 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -110,12 +110,7 @@
// direct outputs can be a scarce resource in audio hardware and should
// be released as quickly as possible.
static const int8_t kMaxTrackRetriesDirect = 2;
-// retry count before removing active track in case of underrun on offloaded thread:
-// we need to make sure that AudioTrack client has enough time to send large buffers
-//FIXME may be more appropriate if expressed in time units. Need to revise how underrun is handled
-// for offloaded tracks
-static const int8_t kMaxTrackRetriesOffload = 10;
-static const int8_t kMaxTrackStartupRetriesOffload = 100;
+
// don't warn about blocked writes or record buffer overflows more often than this
@@ -148,10 +143,6 @@
// Direct output thread minimum sleep time in idle or active(underrun) state
static const nsecs_t kDirectMinSleepTimeUs = 10000;
-// Offloaded output bit rate in bits per second when unknown.
-// Used for sleep time calculation, so use a high default bitrate to be conservative on sleep time.
-static const uint32_t kOffloadDefaultBitRateBps = 1500000;
-
// Whether to use fast mixer
static const enum {
@@ -1567,8 +1558,7 @@
audio_io_handle_t id,
audio_devices_t device,
type_t type,
- bool systemReady,
- uint32_t bitRate)
+ bool systemReady)
: ThreadBase(audioFlinger, id, device, AUDIO_DEVICE_NONE, type, systemReady),
mNormalFrameCount(0), mSinkBuffer(NULL),
mMixerBufferEnabled(AudioFlinger::kEnableExtendedPrecision),
@@ -1631,13 +1621,6 @@
mStreamTypes[stream].volume = mAudioFlinger->streamVolume_l(stream);
mStreamTypes[stream].mute = mAudioFlinger->streamMute_l(stream);
}
-
- if (audio_has_proportional_frames(mFormat)) {
- mBufferDurationUs = (uint32_t)((mNormalFrameCount * 1000000LL) / mSampleRate);
- } else {
- bitRate = bitRate != 0 ? bitRate : kOffloadDefaultBitRateBps;
- mBufferDurationUs = (uint32_t)((mBufferSize * 8 * 1000000LL) / bitRate);
- }
}
AudioFlinger::PlaybackThread::~PlaybackThread()
@@ -2049,12 +2032,18 @@
// set retry count for buffer fill
if (track->isOffloaded()) {
- track->mRetryCount = kMaxTrackStartupRetriesOffload;
+ if (track->isStopping_1()) {
+ track->mRetryCount = kMaxTrackStopRetriesOffload;
+ } else {
+ track->mRetryCount = kMaxTrackStartupRetriesOffload;
+ }
+ track->mFillingUpStatus = mStandby ? Track::FS_FILLING : Track::FS_FILLED;
} else {
track->mRetryCount = kMaxTrackStartupRetries;
+ track->mFillingUpStatus =
+ track->sharedBuffer() != 0 ? Track::FS_FILLED : Track::FS_FILLING;
}
- track->mFillingUpStatus = track->sharedBuffer() != 0 ? Track::FS_FILLED : Track::FS_FILLING;
track->mResetDone = false;
track->mPresentationCompleteFrames = 0;
mActiveTracks.add(track);
@@ -3181,32 +3170,9 @@
} else {
ATRACE_BEGIN("sleep");
- if ((mType == OFFLOAD) && !audio_has_proportional_frames(mFormat)) {
- Mutex::Autolock _l(mLock);
- if (!mSignalPending && !exitPending()) {
- // If more than one buffer has been written to the audio HAL since exiting
- // standby or last flush, do not sleep more than one buffer duration
- // since last write and not less than kDirectMinSleepTimeUs.
- // Wake up if a command is received
- uint32_t timeoutUs = mSleepTimeUs;
- if (mBytesWritten >= (int64_t) mBufferSize) {
- nsecs_t now = systemTime();
- uint32_t deltaUs = (uint32_t)((now - mLastWriteTime) / 1000);
- if (timeoutUs + deltaUs > mBufferDurationUs) {
- if (mBufferDurationUs > deltaUs) {
- timeoutUs = mBufferDurationUs - deltaUs;
- if (timeoutUs < kDirectMinSleepTimeUs) {
- timeoutUs = kDirectMinSleepTimeUs;
- }
- } else {
- timeoutUs = kDirectMinSleepTimeUs;
- }
- }
- }
- mWaitWorkCV.waitRelative(mLock, microseconds((nsecs_t)timeoutUs));
- }
- } else {
- usleep(mSleepTimeUs);
+ Mutex::Autolock _l(mLock);
+ if (!mSignalPending && mConfigEvents.isEmpty() && !exitPending()) {
+ mWaitWorkCV.waitRelative(mLock, microseconds((nsecs_t)mSleepTimeUs));
}
ATRACE_END();
}
@@ -4592,17 +4558,16 @@
// ----------------------------------------------------------------------------
AudioFlinger::DirectOutputThread::DirectOutputThread(const sp<AudioFlinger>& audioFlinger,
- AudioStreamOut* output, audio_io_handle_t id, audio_devices_t device, bool systemReady,
- uint32_t bitRate)
- : PlaybackThread(audioFlinger, output, id, device, DIRECT, systemReady, bitRate)
+ AudioStreamOut* output, audio_io_handle_t id, audio_devices_t device, bool systemReady)
+ : PlaybackThread(audioFlinger, output, id, device, DIRECT, systemReady)
// mLeftVolFloat, mRightVolFloat
{
}
AudioFlinger::DirectOutputThread::DirectOutputThread(const sp<AudioFlinger>& audioFlinger,
AudioStreamOut* output, audio_io_handle_t id, uint32_t device,
- ThreadBase::type_t type, bool systemReady, uint32_t bitRate)
- : PlaybackThread(audioFlinger, output, id, device, type, systemReady, bitRate)
+ ThreadBase::type_t type, bool systemReady)
+ : PlaybackThread(audioFlinger, output, id, device, type, systemReady)
// mLeftVolFloat, mRightVolFloat
{
}
@@ -4908,14 +4873,7 @@
}
if (mSleepTimeUs == 0) {
if (mMixerStatus == MIXER_TRACKS_ENABLED) {
- // For compressed offload, use faster sleep time when underruning until more than an
- // entire buffer was written to the audio HAL
- if (!audio_has_proportional_frames(mFormat) &&
- (mType == OFFLOAD) && (mBytesWritten < (int64_t) mBufferSize)) {
- mSleepTimeUs = kDirectMinSleepTimeUs;
- } else {
- mSleepTimeUs = mActiveSleepTimeUs;
- }
+ mSleepTimeUs = mActiveSleepTimeUs;
} else {
mSleepTimeUs = mIdleSleepTimeUs;
}
@@ -5187,9 +5145,8 @@
// ----------------------------------------------------------------------------
AudioFlinger::OffloadThread::OffloadThread(const sp<AudioFlinger>& audioFlinger,
- AudioStreamOut* output, audio_io_handle_t id, uint32_t device, bool systemReady,
- uint32_t bitRate)
- : DirectOutputThread(audioFlinger, output, id, device, OFFLOAD, systemReady, bitRate),
+ AudioStreamOut* output, audio_io_handle_t id, uint32_t device, bool systemReady)
+ : DirectOutputThread(audioFlinger, output, id, device, OFFLOAD, systemReady),
mPausedWriteLength(0), mPausedBytesRemaining(0), mKeepWakeLock(true)
{
//FIXME: mStandby should be set to true by ThreadBase constructor
@@ -5273,7 +5230,11 @@
}
tracksToRemove->add(track);
} else if (track->isFlushPending()) {
- track->mRetryCount = kMaxTrackRetriesOffload;
+ if (track->isStopping_1()) {
+ track->mRetryCount = kMaxTrackStopRetriesOffload;
+ } else {
+ track->mRetryCount = kMaxTrackRetriesOffload;
+ }
track->flushAck();
if (last) {
mFlushPending = true;
@@ -5334,38 +5295,47 @@
}
mPreviousTrack = track;
// reset retry count
- track->mRetryCount = kMaxTrackRetriesOffload;
+ if (track->isStopping_1()) {
+ track->mRetryCount = kMaxTrackStopRetriesOffload;
+ } else {
+ track->mRetryCount = kMaxTrackRetriesOffload;
+ }
mActiveTrack = t;
mixerStatus = MIXER_TRACKS_READY;
}
} else {
ALOGVV("OffloadThread: track %d s=%08x [NOT READY]", track->name(), cblk->mServer);
if (track->isStopping_1()) {
- // Hardware buffer can hold a large amount of audio so we must
- // wait for all current track's data to drain before we say
- // that the track is stopped.
- if (mBytesRemaining == 0) {
- // Only start draining when all data in mixbuffer
- // has been written
- ALOGV("OffloadThread: underrun and STOPPING_1 -> draining, STOPPING_2");
- track->mState = TrackBase::STOPPING_2; // so presentation completes after drain
- // do not drain if no data was ever sent to HAL (mStandby == true)
- if (last && !mStandby) {
- // do not modify drain sequence if we are already draining. This happens
- // when resuming from pause after drain.
- if ((mDrainSequence & 1) == 0) {
- mSleepTimeUs = 0;
- mStandbyTimeNs = systemTime() + mStandbyDelayNs;
- mixerStatus = MIXER_DRAIN_TRACK;
- mDrainSequence += 2;
- }
- if (mHwPaused) {
- // It is possible to move from PAUSED to STOPPING_1 without
- // a resume so we must ensure hardware is running
- doHwResume = true;
- mHwPaused = false;
+ if (--(track->mRetryCount) <= 0) {
+ // Hardware buffer can hold a large amount of audio so we must
+ // wait for all current track's data to drain before we say
+ // that the track is stopped.
+ if (mBytesRemaining == 0) {
+ // Only start draining when all data in mixbuffer
+ // has been written
+ ALOGV("OffloadThread: underrun and STOPPING_1 -> draining, STOPPING_2");
+ track->mState = TrackBase::STOPPING_2; // so presentation completes after
+ // drain do not drain if no data was ever sent to HAL (mStandby == true)
+ if (last && !mStandby) {
+ // do not modify drain sequence if we are already draining. This happens
+ // when resuming from pause after drain.
+ if ((mDrainSequence & 1) == 0) {
+ mSleepTimeUs = 0;
+ mStandbyTimeNs = systemTime() + mStandbyDelayNs;
+ mixerStatus = MIXER_DRAIN_TRACK;
+ mDrainSequence += 2;
+ }
+ if (mHwPaused) {
+ // It is possible to move from PAUSED to STOPPING_1 without
+ // a resume so we must ensure hardware is running
+ doHwResume = true;
+ mHwPaused = false;
+ }
}
}
+ } else if (last) {
+ ALOGV("stopping1 underrun retries left %d", track->mRetryCount);
+ mixerStatus = MIXER_TRACKS_ENABLED;
}
} else if (track->isStopping_2()) {
// Drain has completed or we are in standby, signal presentation complete
@@ -5456,20 +5426,6 @@
}
}
-uint32_t AudioFlinger::OffloadThread::activeSleepTimeUs() const
-{
- uint32_t time;
- if (audio_has_proportional_frames(mFormat)) {
- time = PlaybackThread::activeSleepTimeUs();
- } else {
- // sleep time is half the duration of an audio HAL buffer.
- // Note: This can be problematic in case of underrun with variable bit rate and
- // current rate is much less than initial rate.
- time = (uint32_t)max(kDirectMinSleepTimeUs, mBufferDurationUs / 2);
- }
- return time;
-}
-
void AudioFlinger::OffloadThread::invalidateTracks(audio_stream_type_t streamType)
{
Mutex::Autolock _l(mLock);
diff --git a/services/audioflinger/Threads.h b/services/audioflinger/Threads.h
index 0ddd279..1cceb6d 100644
--- a/services/audioflinger/Threads.h
+++ b/services/audioflinger/Threads.h
@@ -486,9 +486,16 @@
// suspend by audio policy manager is orthogonal to mixer state
};
+ // retry count before removing active track in case of underrun on offloaded thread:
+ // we need to make sure that AudioTrack client has enough time to send large buffers
+ //FIXME may be more appropriate if expressed in time units. Need to revise how underrun is
+ // handled for offloaded tracks
+ static const int8_t kMaxTrackRetriesOffload = 20;
+ static const int8_t kMaxTrackStartupRetriesOffload = 100;
+ static const int8_t kMaxTrackStopRetriesOffload = 2;
+
PlaybackThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output,
- audio_io_handle_t id, audio_devices_t device, type_t type, bool systemReady,
- uint32_t bitRate = 0);
+ audio_io_handle_t id, audio_devices_t device, type_t type, bool systemReady);
virtual ~PlaybackThread();
void dump(int fd, const Vector<String16>& args);
@@ -843,8 +850,6 @@
bool mHwSupportsPause;
bool mHwPaused;
bool mFlushPending;
- uint32_t mBufferDurationUs; // estimated duration of an audio HAL buffer
- // based on initial bit rate (offload only)
};
class MixerThread : public PlaybackThread {
@@ -935,8 +940,7 @@
public:
DirectOutputThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output,
- audio_io_handle_t id, audio_devices_t device, bool systemReady,
- uint32_t bitRate = 0);
+ audio_io_handle_t id, audio_devices_t device, bool systemReady);
virtual ~DirectOutputThread();
// Thread virtuals
@@ -969,7 +973,7 @@
DirectOutputThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output,
audio_io_handle_t id, uint32_t device, ThreadBase::type_t type,
- bool systemReady, uint32_t bitRate = 0);
+ bool systemReady);
void processVolume_l(Track *track, bool lastTrack);
// prepareTracks_l() tells threadLoop_mix() the name of the single active track
@@ -985,8 +989,7 @@
public:
OffloadThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output,
- audio_io_handle_t id, uint32_t device,
- bool systemReady, uint32_t bitRate);
+ audio_io_handle_t id, uint32_t device, bool systemReady);
virtual ~OffloadThread() {};
virtual void flushHw_l();
@@ -995,8 +998,6 @@
virtual mixer_state prepareTracks_l(Vector< sp<Track> > *tracksToRemove);
virtual void threadLoop_exit();
- virtual uint32_t activeSleepTimeUs() const;
-
virtual bool waitingAsyncCallback();
virtual bool waitingAsyncCallback_l();
virtual void invalidateTracks(audio_stream_type_t streamType);
diff --git a/services/audioflinger/Tracks.cpp b/services/audioflinger/Tracks.cpp
index 41cb030..364e339 100644
--- a/services/audioflinger/Tracks.cpp
+++ b/services/audioflinger/Tracks.cpp
@@ -373,7 +373,7 @@
// client == 0 implies sharedBuffer == 0
ALOG_ASSERT(!(client == 0 && sharedBuffer != 0));
- ALOGV_IF(sharedBuffer != 0, "sharedBuffer: %p, size: %d", sharedBuffer->pointer(),
+ ALOGV_IF(sharedBuffer != 0, "sharedBuffer: %p, size: %zu", sharedBuffer->pointer(),
sharedBuffer->size());
if (mCblk == NULL) {
@@ -728,6 +728,9 @@
// For an offloaded track this starts a drain and state will
// move to STOPPING_2 when drain completes and then STOPPED
mState = STOPPING_1;
+ if (isOffloaded()) {
+ mRetryCount = PlaybackThread::kMaxTrackStopRetriesOffload;
+ }
}
playbackThread->broadcast_l();
ALOGV("not stopping/stopped => stopping/stopped (%d) on thread %p", mName,
diff --git a/services/camera/libcameraservice/api1/client2/StreamingProcessor.cpp b/services/camera/libcameraservice/api1/client2/StreamingProcessor.cpp
index 211bdae..a2c9712 100644
--- a/services/camera/libcameraservice/api1/client2/StreamingProcessor.cpp
+++ b/services/camera/libcameraservice/api1/client2/StreamingProcessor.cpp
@@ -334,6 +334,7 @@
currentFormat != (uint32_t)params.videoFormat ||
currentDataSpace != params.videoDataSpace) {
*needsUpdate = true;
+ return res;
}
*needsUpdate = false;
return res;