Merge "Pipe throttle based on requested frame count" into jb-dev
diff --git a/libvideoeditor/vss/src/M4VSS3GPP_Clip.c b/libvideoeditor/vss/src/M4VSS3GPP_Clip.c
index a79128d..40612f3 100755
--- a/libvideoeditor/vss/src/M4VSS3GPP_Clip.c
+++ b/libvideoeditor/vss/src/M4VSS3GPP_Clip.c
@@ -167,6 +167,47 @@
return M4NO_ERROR;
}
+// This method maps the frequency value to a string.
+static const char* freqToString(int freq) {
+ switch (freq) {
+ case 8000:
+ return "_8000";
+ case 11025:
+ return "_11025";
+ case 12000:
+ return "_12000";
+ case 16000:
+ return "_16000";
+ case 22050:
+ return "_22050";
+ case 24000:
+ return "_24000";
+ case 32000:
+ return "_32000";
+ case 44100:
+ return "_44100";
+ case 48000:
+ return "_48000";
+ default:
+ M4OSA_TRACE1_1("Unsupported sampling rate: %d Hz", freq);
+ return NULL;
+ }
+}
+
+// This method maps the number of channel value to
+// a string that will be part of a file name extension
+static const char* channelToStringAndFileExt(int channels) {
+ switch (channels) {
+ case 1:
+ return "_1.pcm";
+ case 2:
+ return "_2.pcm";
+ default:
+ M4OSA_TRACE1_1("Unsupported %d channels", channels);
+ return NULL;
+ }
+}
+
/* Note: if the clip is opened in fast mode, it can only be used for analysis and nothing else. */
M4OSA_ERR M4VSS3GPP_intClipOpen( M4VSS3GPP_ClipContext *pClipCtxt,
M4VSS3GPP_ClipSettings *pClipSettings, M4OSA_Bool bSkipAudioTrack,
@@ -185,7 +226,6 @@
#endif /* M4VSS_ENABLE_EXTERNAL_DECODERS */
M4DECODER_OutputFilter FilterOption;
- M4OSA_Char pTempFile[100];
/**
* Check input parameters */
@@ -303,73 +343,45 @@
}
}
}
- if(pClipCtxt->pSettings->FileType == M4VIDEOEDITING_kFileType_PCM)
- {
+ if (pClipCtxt->pSettings->FileType == M4VIDEOEDITING_kFileType_PCM) {
+ // Compose the temp filename with sample rate and channel information.
+ const char* freqStr = freqToString(
+ pClipCtxt->pSettings->ClipProperties.uiSamplingFrequency);
-
-
-
- M4OSA_chrNCopy(pTempFile,pClipSettings->pFile,strlen(pClipSettings->pFile));
-
-
- switch (pClipCtxt->pSettings->ClipProperties.uiSamplingFrequency)
- {
- case 8000:
- strncat((char *)pTempFile,(const char *)"_8000",6);
- break;
- case 11025:
- strncat((char *)pTempFile,(const char *)"_11025",6);
- break;
- case 12000:
- strncat((char *)pTempFile,(const char *)"_12000",6);
- break;
- case 16000:
- strncat((char *)pTempFile,(const char *)"_16000",6);
- break;
- case 22050:
- strncat((char *)pTempFile,(const char *)"_22050",6);
- break;
- case 24000:
- strncat((char *)pTempFile,(const char *)"_24000",6);
- break;
- case 32000:
- strncat((char *)pTempFile,(const char *)"_32000",6);
- break;
- case 44100:
- strncat((char *)pTempFile,(const char *)"_44100",6);
- break;
- case 48000:
- strncat((char *)pTempFile,(const char *)"_48000",6);
- break;
- default:
- M4OSA_TRACE1_1("M4VSS3GPP_intClipOpen: invalid input for BG tracksampling \
- frequency (%d Hz), returning M4VSS3GPP_WAR_INCOMPATIBLE_AUDIO_SAMPLING_FREQUENCY"\
- ,pClipCtxt->pSettings->ClipProperties.uiSamplingFrequency );
+ if (freqStr == NULL) {
return M4VSS3GPP_WAR_INCOMPATIBLE_AUDIO_SAMPLING_FREQUENCY;
- }
-
-
-
- //M4OSA_chrNCat(pTempFile,
- // itoa(pClipCtxt->pSettings->ClipProperties.uiSamplingFrequency),5);
- switch(pClipCtxt->pSettings->ClipProperties.uiNbChannels)
- {
- case 1:
- strncat((char *)pTempFile,(const char *)"_1.pcm",6);
- break;
- case 2:
- strncat((char *)pTempFile,(const char *)"_2.pcm",6);
- break;
- default:
- M4OSA_TRACE1_1("M4VSS3GPP_intClipOpen: invalid input for BG track no.\
- of channels (%d ), returning M4VSS3GPP_WAR_INCOMPATIBLE_AUDIO_NB_OF_CHANNELS",\
- pClipCtxt->pSettings->ClipProperties.uiNbChannels);
- return M4VSS3GPP_WAR_INCOMPATIBLE_AUDIO_NB_OF_CHANNELS;
}
- //M4OSA_chrNCat(pTempFile,itoa(pClipCtxt->pSettings->ClipProperties.uiNbChannels),1);
+
+ const char* chanStr = channelToStringAndFileExt(
+ pClipCtxt->pSettings->ClipProperties.uiNbChannels);
+
+ if (chanStr == NULL) {
+ return M4VSS3GPP_WAR_INCOMPATIBLE_AUDIO_NB_OF_CHANNELS;
+ }
+
+ // Allocate one byte more to hold the null terminator
+ M4OSA_UInt32 length =
+ strlen(pClipSettings->pFile) + strlen(freqStr) + strlen(chanStr) + 1;
+
+ char* pTempFile = (char *) malloc(length);
+ if (pTempFile == NULL) {
+ M4OSA_TRACE1_1("M4VSS3GPP_intClipOpen(): malloc %d bytes fail",length);
+ return M4ERR_ALLOC;
+ }
+ memset(pTempFile, 0, length);
+ memcpy(pTempFile, pClipSettings->pFile, strlen(pClipSettings->pFile));
+ strncat(pTempFile, freqStr, strlen(freqStr));
+ strncat(pTempFile, chanStr, strlen(chanStr));
err = pClipCtxt->ShellAPI.m_pReader->m_pFctOpen( pClipCtxt->pReaderContext, pTempFile);
-
+ if (pTempFile != NULL) {
+ free(pTempFile);
+ pTempFile = NULL;
+ }
+ if ( M4NO_ERROR != err ) {
+ M4OSA_TRACE1_1("M4VSS3GPP_intClipOpen(): open pcm file returns error : 0x%x", err);
+ return err;
+ }
}
else
{
diff --git a/libvideoeditor/vss/stagefrightshells/src/VideoEditor3gpReader.cpp b/libvideoeditor/vss/stagefrightshells/src/VideoEditor3gpReader.cpp
index c4c4d84..5026073 100755
--- a/libvideoeditor/vss/stagefrightshells/src/VideoEditor3gpReader.cpp
+++ b/libvideoeditor/vss/stagefrightshells/src/VideoEditor3gpReader.cpp
@@ -1867,6 +1867,28 @@
}
err = VideoEditor3gpReader_getNextAu(pC, (*pStreamHandler),
(M4_AccessUnit*)pUserData->m_pFirstAU);
+
+ /*
+ * 1. "M4WAR_NO_MORE_AU == err" indicates that there is no more
+ * access unit from the current track. In other words, there
+ * is only a single access unit from the current track, and
+ * the parsing of this track has reached EOS. The reason why
+ * the first access unit needs to be parsed here is because for
+ * some audio codec (like AAC), the very first access unit
+ * must be decoded before its configuration/encoding parameters
+ * (such as # of channels and sample rate) can be correctly
+ * determined.
+ *
+ * 2. "trackCount > pC->mCurrTrack" indicates that there are other
+ * tracks to be parsed, in addition to the current track.
+ *
+ * When both conditions 1 & 2 hold, other tracks should be
+ * parsed. Thus, we should not bail out.
+ */
+ if (M4WAR_NO_MORE_AU == err && trackCount > pC->mCurrTrack) {
+ err = M4NO_ERROR;
+ }
+
if (M4NO_ERROR != err) {
goto Error;
}
diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp
index 5e6cd51..e234532 100644
--- a/media/libmedia/AudioTrack.cpp
+++ b/media/libmedia/AudioTrack.cpp
@@ -1019,13 +1019,6 @@
cblk->lock.unlock();
}
- // restart track if it was disabled by audioflinger due to previous underrun
- if (mActive && (cblk->flags & CBLK_DISABLED_MSK)) {
- android_atomic_and(~CBLK_DISABLED_ON, &cblk->flags);
- ALOGW("obtainBuffer() track %p disabled, restarting", this);
- mAudioTrack->start();
- }
-
cblk->waitTimeMs = 0;
if (framesReq > framesAvail) {
@@ -1057,6 +1050,14 @@
{
AutoMutex lock(mLock);
mCblk->stepUser(audioBuffer->frameCount);
+ if (audioBuffer->frameCount > 0) {
+ // restart track if it was disabled by audioflinger due to previous underrun
+ if (mActive && (mCblk->flags & CBLK_DISABLED_MSK)) {
+ android_atomic_and(~CBLK_DISABLED_ON, &mCblk->flags);
+ ALOGW("releaseBuffer() track %p disabled, restarting", this);
+ mAudioTrack->start();
+ }
+ }
}
// -------------------------------------------------------------------------
@@ -1077,6 +1078,10 @@
ALOGV("write %p: %d bytes, mActive=%d", this, userSize, mActive);
+ if (userSize == 0) {
+ return 0;
+ }
+
// acquire a strong reference on the IMemory and IAudioTrack so that they cannot be destroyed
// while we are accessing the cblk
mLock.lock();
@@ -1157,14 +1162,18 @@
status_t TimedAudioTrack::queueTimedBuffer(const sp<IMemory>& buffer,
int64_t pts)
{
- // restart track if it was disabled by audioflinger due to previous underrun
- if (mActive && (mCblk->flags & CBLK_DISABLED_MSK)) {
- android_atomic_and(~CBLK_DISABLED_ON, &mCblk->flags);
- ALOGW("queueTimedBuffer() track %p disabled, restarting", this);
- mAudioTrack->start();
+ status_t status = mAudioTrack->queueTimedBuffer(buffer, pts);
+ {
+ AutoMutex lock(mLock);
+ // restart track if it was disabled by audioflinger due to previous underrun
+ if (buffer->size() != 0 && status == NO_ERROR &&
+ mActive && (mCblk->flags & CBLK_DISABLED_MSK)) {
+ android_atomic_and(~CBLK_DISABLED_ON, &mCblk->flags);
+ ALOGW("queueTimedBuffer() track %p disabled, restarting", this);
+ mAudioTrack->start();
+ }
}
-
- return mAudioTrack->queueTimedBuffer(buffer, pts);
+ return status;
}
status_t TimedAudioTrack::setMediaTimeTransform(const LinearTransform& xform,
@@ -1276,6 +1285,7 @@
usleep(WAIT_PERIOD_MS*1000);
break;
}
+
if (writtenSize > reqSize) writtenSize = reqSize;
if (mFormat == AUDIO_FORMAT_PCM_8_BIT && !(mFlags & AUDIO_OUTPUT_FLAG_DIRECT)) {
diff --git a/media/libstagefright/AwesomePlayer.cpp b/media/libstagefright/AwesomePlayer.cpp
index 892da92..0749254 100644
--- a/media/libstagefright/AwesomePlayer.cpp
+++ b/media/libstagefright/AwesomePlayer.cpp
@@ -753,19 +753,23 @@
if ((mFlags & PLAYING) && !eos
&& (cachedDurationUs < kLowWaterMarkUs)) {
- ALOGI("cache is running low (%.2f secs) , pausing.",
- cachedDurationUs / 1E6);
modifyFlags(CACHE_UNDERRUN, SET);
- pause_l();
- ensureCacheIsFetching_l();
- sendCacheStats();
+ if (mWVMExtractor == NULL) {
+ ALOGI("cache is running low (%.2f secs) , pausing.",
+ cachedDurationUs / 1E6);
+ pause_l();
+ ensureCacheIsFetching_l();
+ sendCacheStats();
+ }
notifyListener_l(MEDIA_INFO, MEDIA_INFO_BUFFERING_START);
} else if (eos || cachedDurationUs > kHighWaterMarkUs) {
if (mFlags & CACHE_UNDERRUN) {
- ALOGI("cache has filled up (%.2f secs), resuming.",
- cachedDurationUs / 1E6);
modifyFlags(CACHE_UNDERRUN, CLEAR);
- play_l();
+ if (mWVMExtractor == NULL) {
+ ALOGI("cache has filled up (%.2f secs), resuming.",
+ cachedDurationUs / 1E6);
+ play_l();
+ }
notifyListener_l(MEDIA_INFO, MEDIA_INFO_BUFFERING_END);
} else if (mFlags & PREPARING) {
ALOGV("cache has filled up (%.2f secs), prepare is done",
diff --git a/media/libstagefright/codecs/aacdec/SoftAAC2.cpp b/media/libstagefright/codecs/aacdec/SoftAAC2.cpp
index 8dbff9e..ff95f9f 100644
--- a/media/libstagefright/codecs/aacdec/SoftAAC2.cpp
+++ b/media/libstagefright/codecs/aacdec/SoftAAC2.cpp
@@ -293,12 +293,18 @@
info->mOwnedByUs = false;
notifyEmptyBufferDone(header);
- maybeConfigureDownmix();
- ALOGI("Initially configuring decoder: %d Hz, %d channels",
- mStreamInfo->sampleRate,
- mStreamInfo->numChannels);
- notify(OMX_EventPortSettingsChanged, 1, 0, NULL);
- mOutputPortSettingsChange = AWAITING_DISABLED;
+ // Only send out port settings changed event if both sample rate
+ // and numChannels are valid.
+ if (mStreamInfo->sampleRate && mStreamInfo->numChannels) {
+ maybeConfigureDownmix();
+ ALOGI("Initially configuring decoder: %d Hz, %d channels",
+ mStreamInfo->sampleRate,
+ mStreamInfo->numChannels);
+
+ notify(OMX_EventPortSettingsChanged, 1, 0, NULL);
+ mOutputPortSettingsChange = AWAITING_DISABLED;
+ }
+
return;
}
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index 57d7089..eea3cd2 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -3147,6 +3147,13 @@
mixerStatus = MIXER_TRACKS_READY;
}
} else {
+ // clear effect chain input buffer if an active track underruns to avoid sending
+ // previous audio buffer again to effects
+ chain = getEffectChain_l(track->sessionId());
+ if (chain != 0) {
+ chain->clearInputBuffer();
+ }
+
//ALOGV("track %d u=%08x, s=%08x [NOT READY] on thread %p", name, cblk->user, cblk->server, this);
if ((track->sharedBuffer() != 0) || track->isTerminated() ||
track->isStopped() || track->isPaused()) {
@@ -3661,6 +3668,12 @@
mActiveTrack = t;
mixerStatus = MIXER_TRACKS_READY;
} else {
+ // clear effect chain input buffer if an active track underruns to avoid sending
+ // previous audio buffer again to effects
+ if (!mEffectChains.isEmpty()) {
+ mEffectChains[0]->clearInputBuffer();
+ }
+
//ALOGV("track %d u=%08x, s=%08x [NOT READY]", track->name(), cblk->user, cblk->server);
if (track->isTerminated() || track->isStopped() || track->isPaused()) {
// We have consumed all the buffers of this track.
@@ -8978,6 +8991,25 @@
return 0;
}
+void AudioFlinger::EffectChain::clearInputBuffer()
+{
+ Mutex::Autolock _l(mLock);
+ sp<ThreadBase> thread = mThread.promote();
+ if (thread == 0) {
+ ALOGW("clearInputBuffer(): cannot promote mixer thread");
+ return;
+ }
+ clearInputBuffer_l(thread);
+}
+
+// Must be called with EffectChain::mLock locked
+void AudioFlinger::EffectChain::clearInputBuffer_l(sp<ThreadBase> thread)
+{
+ size_t numSamples = thread->frameCount() * thread->channelCount();
+ memset(mInBuffer, 0, numSamples * sizeof(int16_t));
+
+}
+
// Must be called with EffectChain::mLock locked
void AudioFlinger::EffectChain::process_l()
{
@@ -9002,8 +9034,7 @@
// if no track is active and the effect tail has not been rendered,
// the input buffer must be cleared here as the mixer process will not do it
if (tracksOnSession || mTailBufferCount > 0) {
- size_t numSamples = thread->frameCount() * thread->channelCount();
- memset(mInBuffer, 0, numSamples * sizeof(int16_t));
+ clearInputBuffer_l(thread);
if (mTailBufferCount > 0) {
mTailBufferCount--;
}
diff --git a/services/audioflinger/AudioFlinger.h b/services/audioflinger/AudioFlinger.h
index 51cbae7..19390b1 100644
--- a/services/audioflinger/AudioFlinger.h
+++ b/services/audioflinger/AudioFlinger.h
@@ -1717,6 +1717,8 @@
void checkSuspendOnEffectEnabled(const sp<EffectModule>& effect,
bool enabled);
+ void clearInputBuffer();
+
status_t dump(int fd, const Vector<String16>& args);
protected:
@@ -1744,6 +1746,8 @@
// types or implementations from the suspend/restore mechanism.
bool isEffectEligibleForSuspend(const effect_descriptor_t& desc);
+ void clearInputBuffer_l(sp<ThreadBase> thread);
+
wp<ThreadBase> mThread; // parent mixer thread
Mutex mLock; // mutex protecting effect list
Vector< sp<EffectModule> > mEffects; // list of effect modules