mAudioRenderingStartGeneration(0),
mAudioOffloadPauseTimeoutGeneration(0),
mAudioOffloadTornDown(false),
- mCurrentOffloadInfo(AUDIO_INFO_INITIALIZER) {
+ mCurrentOffloadInfo(AUDIO_INFO_INITIALIZER),
+ mTotalBuffersQueued(0),
+ mLastAudioBufferDrained(0) {
readProperties();
}
break;
}
+ case kWhatPostDrainVideoQueue:
+ {
+ int32_t generation;
+ CHECK(msg->findInt32("generation", &generation));
+ if (generation != mVideoQueueGeneration) {
+ break;
+ }
+
+ mDrainVideoQueuePending = false;
+ postDrainVideoQueue();
+ break;
+ }
+
case kWhatQueueBuffer:
{
onQueueBuffer(msg);
while (numBytesAvailableToWrite > 0 && !mAudioQueue.empty()) {
QueueEntry *entry = &*mAudioQueue.begin();
+ mLastAudioBufferDrained = entry->mBufferOrdinal;
+
if (entry->mBuffer == NULL) {
// EOS
int64_t postEOSDelayUs = 0;
} else {
realTimeUs = getRealTimeUs(mediaTimeUs, nowUs);
}
+
+ // Heuristics to handle situation when media time changed without a
+ // discontinuity. If we have not drained an audio buffer that was
+ // received after this buffer, repost in 10 msec. Otherwise repost
+ // in 500 msec.
+ delayUs = realTimeUs - nowUs;
+ if (delayUs > 500000) {
+ int64_t postDelayUs = 500000;
+ if (mHasAudio && (mLastAudioBufferDrained - entry.mBufferOrdinal) <= 0) {
+ postDelayUs = 10000;
+ }
+ msg->setWhat(kWhatPostDrainVideoQueue);
+ msg->post(postDelayUs);
+ mVideoScheduler->restart();
+ ALOGI("possible video time jump of %dms, retrying in %dms",
+ (int)(delayUs / 1000), (int)(postDelayUs / 1000));
+ mDrainVideoQueuePending = true;
+ return;
+ }
}
realTimeUs = mVideoScheduler->schedule(realTimeUs * 1000) / 1000;
entry.mNotifyConsumed = notifyConsumed;
entry.mOffset = 0;
entry.mFinalResult = OK;
+ entry.mBufferOrdinal = ++mTotalBuffersQueued;
if (audio) {
Mutex::Autolock autoLock(mLock);
enum {
kWhatDrainAudioQueue = 'draA',
kWhatDrainVideoQueue = 'draV',
+ kWhatPostDrainVideoQueue = 'pDVQ',
kWhatQueueBuffer = 'queB',
kWhatQueueEOS = 'qEOS',
kWhatFlush = 'flus',
sp<AMessage> mNotifyConsumed;
size_t mOffset;
status_t mFinalResult;
+ int32_t mBufferOrdinal;
};
static const int64_t kMinPositionUpdateDelayUs;
bool mAudioOffloadTornDown;
audio_offload_info_t mCurrentOffloadInfo;
+ int32_t mTotalBuffersQueued;
+ int32_t mLastAudioBufferDrained;
+
size_t fillAudioBuffer(void *buffer, size_t size);
bool onDrainAudioQueue();