am 7ed7668b: Merge "Calculate audio media drift time from AudioSource" into gingerbread

Merge commit '7ed7668b30e70ca8e3f0f183364433326ed29f39' into gingerbread-plus-aosp

* commit '7ed7668b30e70ca8e3f0f183364433326ed29f39':
  Calculate audio media drift time from AudioSource
This commit is contained in:
James Dong
2010-09-02 18:41:49 -07:00
committed by Android Git Automerger
8 changed files with 63 additions and 32 deletions

View File

@@ -72,6 +72,7 @@ private:
int64_t mPrevSampleTimeUs; int64_t mPrevSampleTimeUs;
int64_t mTotalLostFrames; int64_t mTotalLostFrames;
int64_t mPrevLostBytes; int64_t mPrevLostBytes;
int64_t mInitialReadTimeUs;
MediaBufferGroup *mGroup; MediaBufferGroup *mGroup;

View File

@@ -132,7 +132,7 @@ private:
// Adjust other track media clock (presumably wall clock) // Adjust other track media clock (presumably wall clock)
// based on audio track media clock with the drift time. // based on audio track media clock with the drift time.
int64_t mDriftTimeUs; int64_t mDriftTimeUs;
void addDriftTimeUs(int64_t driftTimeUs); void setDriftTimeUs(int64_t driftTimeUs);
int64_t getDriftTimeUs(); int64_t getDriftTimeUs();
void lock(); void lock();

View File

@@ -48,6 +48,7 @@ enum {
kKeyTime = 'time', // int64_t (usecs) kKeyTime = 'time', // int64_t (usecs)
kKeyNTPTime = 'ntpT', // uint64_t (ntp-timestamp) kKeyNTPTime = 'ntpT', // uint64_t (ntp-timestamp)
kKeyTargetTime = 'tarT', // int64_t (usecs) kKeyTargetTime = 'tarT', // int64_t (usecs)
kKeyDriftTime = 'dftT', // int64_t (usecs)
kKeyDuration = 'dura', // int64_t (usecs) kKeyDuration = 'dura', // int64_t (usecs)
kKeyColorFormat = 'colf', kKeyColorFormat = 'colf',
kKeyPlatformPrivate = 'priv', // pointer kKeyPlatformPrivate = 'priv', // pointer

View File

@@ -84,6 +84,7 @@ status_t AudioSource::start(MetaData *params) {
mTrackMaxAmplitude = false; mTrackMaxAmplitude = false;
mMaxAmplitude = 0; mMaxAmplitude = 0;
mInitialReadTimeUs = 0;
mStartTimeUs = 0; mStartTimeUs = 0;
int64_t startTimeUs; int64_t startTimeUs;
if (params && params->findInt64(kKeyTime, &startTimeUs)) { if (params && params->findInt64(kKeyTime, &startTimeUs)) {
@@ -210,6 +211,7 @@ status_t AudioSource::read(
return NO_INIT; return NO_INIT;
} }
int64_t readTimeUs = systemTime() / 1000;
*out = NULL; *out = NULL;
MediaBuffer *buffer; MediaBuffer *buffer;
@@ -223,9 +225,10 @@ status_t AudioSource::read(
if (numFramesRecorded == 0 && mPrevSampleTimeUs == 0) { if (numFramesRecorded == 0 && mPrevSampleTimeUs == 0) {
mInitialReadTimeUs = readTimeUs;
// Initial delay // Initial delay
if (mStartTimeUs > 0) { if (mStartTimeUs > 0) {
mStartTimeUs = systemTime() / 1000 - mStartTimeUs; mStartTimeUs = readTimeUs - mStartTimeUs;
} else { } else {
// Assume latency is constant. // Assume latency is constant.
mStartTimeUs += mRecord->latency() * 1000; mStartTimeUs += mRecord->latency() * 1000;
@@ -271,7 +274,10 @@ status_t AudioSource::read(
} }
memset(buffer->data(), 0, numLostBytes); memset(buffer->data(), 0, numLostBytes);
buffer->set_range(0, numLostBytes); buffer->set_range(0, numLostBytes);
buffer->meta_data()->setInt64(kKeyTime, mPrevSampleTimeUs); if (numFramesRecorded == 0) {
buffer->meta_data()->setInt64(kKeyTime, mStartTimeUs);
}
buffer->meta_data()->setInt64(kKeyDriftTime, readTimeUs - mInitialReadTimeUs);
mPrevSampleTimeUs = timestampUs; mPrevSampleTimeUs = timestampUs;
*out = buffer; *out = buffer;
return OK; return OK;
@@ -309,7 +315,10 @@ status_t AudioSource::read(
trackMaxAmplitude((int16_t *) buffer->data(), n >> 1); trackMaxAmplitude((int16_t *) buffer->data(), n >> 1);
} }
buffer->meta_data()->setInt64(kKeyTime, mPrevSampleTimeUs); if (numFramesRecorded == 0) {
buffer->meta_data()->setInt64(kKeyTime, mStartTimeUs);
}
buffer->meta_data()->setInt64(kKeyDriftTime, readTimeUs - mInitialReadTimeUs);
CHECK(timestampUs > mPrevSampleTimeUs); CHECK(timestampUs > mPrevSampleTimeUs);
mPrevSampleTimeUs = timestampUs; mPrevSampleTimeUs = timestampUs;
LOGV("initial delay: %lld, sample rate: %d, timestamp: %lld", LOGV("initial delay: %lld, sample rate: %d, timestamp: %lld",

View File

@@ -1430,9 +1430,6 @@ status_t MPEG4Writer::Track::threadEntry() {
int64_t previousPausedDurationUs = 0; int64_t previousPausedDurationUs = 0;
int64_t timestampUs; int64_t timestampUs;
int64_t wallClockTimeUs = 0;
int64_t lastWallClockTimeUs = 0;
sp<MetaData> meta_data; sp<MetaData> meta_data;
bool collectStats = collectStatisticalData(); bool collectStats = collectStatisticalData();
@@ -1542,14 +1539,15 @@ status_t MPEG4Writer::Track::threadEntry() {
// of neighboring samples. This in turn helps reduce the track header size, // of neighboring samples. This in turn helps reduce the track header size,
// especially, the number of entries in the "stts" box. // especially, the number of entries in the "stts" box.
if (mNumSamples > 1) { if (mNumSamples > 1) {
int64_t durationUs = timestampUs + mOwner->getDriftTimeUs() - lastTimestampUs; int64_t currDriftTimeUs = mOwner->getDriftTimeUs();
int64_t durationUs = timestampUs + currDriftTimeUs - lastTimestampUs;
int64_t diffUs = (durationUs > lastDurationUs) int64_t diffUs = (durationUs > lastDurationUs)
? durationUs - lastDurationUs ? durationUs - lastDurationUs
: lastDurationUs - durationUs; : lastDurationUs - durationUs;
if (diffUs <= 5000) { // XXX: Magic number 5ms if (diffUs <= 5000) { // XXX: Magic number 5ms
timestampUs = lastTimestampUs + lastDurationUs; timestampUs = lastTimestampUs + lastDurationUs;
} else { } else {
timestampUs += mOwner->getDriftTimeUs(); timestampUs += currDriftTimeUs;
} }
} }
} }
@@ -1557,12 +1555,6 @@ status_t MPEG4Writer::Track::threadEntry() {
if (mNumSamples > 1) { if (mNumSamples > 1) {
if (timestampUs <= lastTimestampUs) { if (timestampUs <= lastTimestampUs) {
LOGW("Frame arrives too late!"); LOGW("Frame arrives too late!");
#if 0
// Drop the late frame.
copy->release();
copy = NULL;
continue;
#else
// Don't drop the late frame, since dropping a frame may cause // Don't drop the late frame, since dropping a frame may cause
// problems later during playback // problems later during playback
@@ -1573,7 +1565,6 @@ status_t MPEG4Writer::Track::threadEntry() {
} else { } else {
timestampUs = lastTimestampUs + (1000000LL + (mTimeScale >> 1)) / mTimeScale; timestampUs = lastTimestampUs + (1000000LL + (mTimeScale >> 1)) / mTimeScale;
} }
#endif
} }
} }
@@ -1613,12 +1604,10 @@ status_t MPEG4Writer::Track::threadEntry() {
lastDurationTicks = currDurationTicks; lastDurationTicks = currDurationTicks;
lastTimestampUs = timestampUs; lastTimestampUs = timestampUs;
if (mIsRealTimeRecording && mIsAudio) { if (mIsRealTimeRecording && mIsAudio) {
wallClockTimeUs = systemTime() / 1000; int64_t driftTimeUs = 0;
int64_t wallClockDurationUs = wallClockTimeUs - lastWallClockTimeUs; if (meta_data->findInt64(kKeyDriftTime, &driftTimeUs)) {
if (mNumSamples > 2) { mOwner->setDriftTimeUs(driftTimeUs);
mOwner->addDriftTimeUs(lastDurationUs - wallClockDurationUs);
} }
lastWallClockTimeUs = wallClockTimeUs;
} }
if (isSync != 0) { if (isSync != 0) {
@@ -1851,10 +1840,10 @@ void MPEG4Writer::Track::logStatisticalData(bool isAudio) {
} }
} }
void MPEG4Writer::addDriftTimeUs(int64_t driftTimeUs) { void MPEG4Writer::setDriftTimeUs(int64_t driftTimeUs) {
LOGV("addDriftTimeUs: %lld us", driftTimeUs); LOGV("setDriftTimeUs: %lld us", driftTimeUs);
Mutex::Autolock autolock(mLock); Mutex::Autolock autolock(mLock);
mDriftTimeUs += driftTimeUs; mDriftTimeUs = driftTimeUs;
} }
int64_t MPEG4Writer::getDriftTimeUs() { int64_t MPEG4Writer::getDriftTimeUs() {

View File

@@ -208,6 +208,8 @@ status_t AACEncoder::read(
MediaBuffer *buffer; MediaBuffer *buffer;
CHECK_EQ(mBufferGroup->acquire_buffer(&buffer), OK); CHECK_EQ(mBufferGroup->acquire_buffer(&buffer), OK);
uint8_t *outPtr = (uint8_t *)buffer->data(); uint8_t *outPtr = (uint8_t *)buffer->data();
bool readFromSource = false;
int64_t wallClockTimeUs = 0;
if (mFrameCount == 0) { if (mFrameCount == 0) {
memcpy(outPtr, mAudioSpecificConfigData, 2); memcpy(outPtr, mAudioSpecificConfigData, 2);
@@ -238,9 +240,14 @@ status_t AACEncoder::read(
CHECK_EQ(align, 0); CHECK_EQ(align, 0);
int64_t timeUs; int64_t timeUs;
CHECK(mInputBuffer->meta_data()->findInt64(kKeyDriftTime, &timeUs));
wallClockTimeUs = timeUs;
if (mInputBuffer->meta_data()->findInt64(kKeyTime, &timeUs)) { if (mInputBuffer->meta_data()->findInt64(kKeyTime, &timeUs)) {
mAnchorTimeUs = timeUs; mAnchorTimeUs = timeUs;
} }
readFromSource = true;
} else {
readFromSource = false;
} }
size_t copy = size_t copy =
(kNumSamplesPerFrame - mNumInputSamples) * sizeof(int16_t); (kNumSamplesPerFrame - mNumInputSamples) * sizeof(int16_t);
@@ -288,9 +295,13 @@ status_t AACEncoder::read(
CHECK(outputData.Length != 0); CHECK(outputData.Length != 0);
buffer->set_range(0, outputData.Length); buffer->set_range(0, outputData.Length);
int64_t timestampUs = ((mFrameCount - 1) * 1000000LL * kNumSamplesPerFrame) / mSampleRate; int64_t mediaTimeUs =
((mFrameCount - 1) * 1000000LL * kNumSamplesPerFrame) / mSampleRate;
buffer->meta_data()->setInt64(kKeyTime, mAnchorTimeUs + mediaTimeUs);
if (readFromSource) {
buffer->meta_data()->setInt64(kKeyDriftTime, mediaTimeUs - wallClockTimeUs);
}
++mFrameCount; ++mFrameCount;
buffer->meta_data()->setInt64(kKeyTime, timestampUs);
*out = buffer; *out = buffer;
return OK; return OK;

View File

@@ -147,6 +147,8 @@ status_t AMRNBEncoder::read(
int64_t seekTimeUs; int64_t seekTimeUs;
ReadOptions::SeekMode mode; ReadOptions::SeekMode mode;
CHECK(options == NULL || !options->getSeekTo(&seekTimeUs, &mode)); CHECK(options == NULL || !options->getSeekTo(&seekTimeUs, &mode));
bool readFromSource = false;
int64_t wallClockTimeUs = 0;
while (mNumInputSamples < kNumSamplesPerFrame) { while (mNumInputSamples < kNumSamplesPerFrame) {
if (mInputBuffer == NULL) { if (mInputBuffer == NULL) {
@@ -166,12 +168,16 @@ status_t AMRNBEncoder::read(
size_t align = mInputBuffer->range_length() % sizeof(int16_t); size_t align = mInputBuffer->range_length() % sizeof(int16_t);
CHECK_EQ(align, 0); CHECK_EQ(align, 0);
readFromSource = true;
int64_t timeUs; int64_t timeUs;
CHECK(mInputBuffer->meta_data()->findInt64(kKeyDriftTime, &timeUs));
wallClockTimeUs = timeUs;
if (mInputBuffer->meta_data()->findInt64(kKeyTime, &timeUs)) { if (mInputBuffer->meta_data()->findInt64(kKeyTime, &timeUs)) {
mAnchorTimeUs = timeUs; mAnchorTimeUs = timeUs;
mNumFramesOutput = 0;
} }
} else {
readFromSource = false;
} }
size_t copy = size_t copy =
@@ -217,8 +223,14 @@ status_t AMRNBEncoder::read(
buffer->set_range(0, res); buffer->set_range(0, res);
// Each frame of 160 samples is 20ms long. // Each frame of 160 samples is 20ms long.
int64_t mediaTimeUs = mNumFramesOutput * 20000LL;
buffer->meta_data()->setInt64( buffer->meta_data()->setInt64(
kKeyTime, mAnchorTimeUs + mNumFramesOutput * 20000); kKeyTime, mAnchorTimeUs + mediaTimeUs);
if (readFromSource) {
buffer->meta_data()->setInt64(kKeyDriftTime,
mediaTimeUs - wallClockTimeUs);
}
++mNumFramesOutput; ++mNumFramesOutput;

View File

@@ -198,6 +198,8 @@ status_t AMRWBEncoder::read(
int64_t seekTimeUs; int64_t seekTimeUs;
ReadOptions::SeekMode mode; ReadOptions::SeekMode mode;
CHECK(options == NULL || !options->getSeekTo(&seekTimeUs, &mode)); CHECK(options == NULL || !options->getSeekTo(&seekTimeUs, &mode));
bool readFromSource = false;
int64_t wallClockTimeUs = 0;
while (mNumInputSamples < kNumSamplesPerFrame) { while (mNumInputSamples < kNumSamplesPerFrame) {
if (mInputBuffer == NULL) { if (mInputBuffer == NULL) {
@@ -219,9 +221,14 @@ status_t AMRWBEncoder::read(
CHECK_EQ(align, 0); CHECK_EQ(align, 0);
int64_t timeUs; int64_t timeUs;
CHECK(mInputBuffer->meta_data()->findInt64(kKeyDriftTime, &timeUs));
wallClockTimeUs = timeUs;
if (mInputBuffer->meta_data()->findInt64(kKeyTime, &timeUs)) { if (mInputBuffer->meta_data()->findInt64(kKeyTime, &timeUs)) {
mAnchorTimeUs = timeUs; mAnchorTimeUs = timeUs;
} }
readFromSource = true;
} else {
readFromSource = false;
} }
size_t copy = size_t copy =
@@ -276,10 +283,11 @@ status_t AMRWBEncoder::read(
buffer->set_range(0, outputData.Length); buffer->set_range(0, outputData.Length);
++mNumFramesOutput; ++mNumFramesOutput;
// XXX: fix timestamp calculation int64_t mediaTimeUs = mNumFramesOutput * 20000LL;
int64_t timestampUs = mNumFramesOutput * 20000LL; buffer->meta_data()->setInt64(kKeyTime, mAnchorTimeUs + mediaTimeUs);
if (readFromSource) {
buffer->meta_data()->setInt64(kKeyTime, timestampUs); buffer->meta_data()->setInt64(kKeyDriftTime, mediaTimeUs - wallClockTimeUs);
}
*out = buffer; *out = buffer;
return OK; return OK;