Merge "Fixed the software AAC encoder" into gingerbread

This commit is contained in:
James Dong
2010-06-24 09:46:48 -07:00
committed by Android (Google) Code Review
3 changed files with 64 additions and 31 deletions

View File

@@ -185,7 +185,7 @@ status_t MPEG4Writer::start() {
return UNKNOWN_ERROR; return UNKNOWN_ERROR;
} }
mStartTimestampUs = 0; mStartTimestampUs = -1;
if (mStarted) { if (mStarted) {
if (mPaused) { if (mPaused) {
mPaused = false; mPaused = false;
@@ -561,8 +561,7 @@ void MPEG4Writer::setStartTimestampUs(int64_t timeUs) {
LOGI("setStartTimestampUs: %lld", timeUs); LOGI("setStartTimestampUs: %lld", timeUs);
CHECK(timeUs >= 0); CHECK(timeUs >= 0);
Mutex::Autolock autoLock(mLock); Mutex::Autolock autoLock(mLock);
if (mStartTimestampUs == 0 || if (mStartTimestampUs < 0 || mStartTimestampUs > timeUs) {
(mStartTimestampUs > 0 && mStartTimestampUs > timeUs)) {
mStartTimestampUs = timeUs; mStartTimestampUs = timeUs;
LOGI("Earliest track starting time: %lld", mStartTimestampUs); LOGI("Earliest track starting time: %lld", mStartTimestampUs);
} }

View File

@@ -139,6 +139,8 @@ status_t AACEncoder::start(MetaData *params) {
CHECK_EQ(OK, initCheck()); CHECK_EQ(OK, initCheck());
mNumInputSamples = 0;
mAnchorTimeUs = 0;
mFrameCount = 0; mFrameCount = 0;
mSource->start(params); mSource->start(params);
@@ -205,33 +207,65 @@ status_t AACEncoder::read(
buffer->set_range(0, 2); buffer->set_range(0, 2);
buffer->meta_data()->setInt32(kKeyIsCodecConfig, true); buffer->meta_data()->setInt32(kKeyIsCodecConfig, true);
*out = buffer; *out = buffer;
mInputBuffer = NULL;
++mFrameCount; ++mFrameCount;
return OK; return OK;
} else if (mFrameCount == 1) { } else if (mFrameCount == 1) {
buffer->meta_data()->setInt32(kKeyIsCodecConfig, false); buffer->meta_data()->setInt32(kKeyIsCodecConfig, false);
} }
// XXX: We assume that the input buffer contains at least while (mNumInputSamples < kNumSamplesPerFrame) {
// (actually, exactly) 1024 PCM samples. This needs to be fixed. if (mInputBuffer == NULL) {
if (mInputBuffer == NULL) { if (mSource->read(&mInputBuffer, options) != OK) {
if (mSource->read(&mInputBuffer, options) != OK) { if (mNumInputSamples == 0) {
LOGE("failed to read from input audio source"); return ERROR_END_OF_STREAM;
return UNKNOWN_ERROR; }
memset(&mInputFrame[mNumInputSamples],
0,
sizeof(int16_t) * (kNumSamplesPerFrame - mNumInputSamples));
mNumInputSamples = 0;
break;
}
size_t align = mInputBuffer->range_length() % sizeof(int16_t);
CHECK_EQ(align, 0);
int64_t timeUs;
if (mInputBuffer->meta_data()->findInt64(kKeyTime, &timeUs)) {
mAnchorTimeUs = timeUs;
}
} }
size_t copy =
(kNumSamplesPerFrame - mNumInputSamples) * sizeof(int16_t);
if (copy > mInputBuffer->range_length()) {
copy = mInputBuffer->range_length();
}
memcpy(&mInputFrame[mNumInputSamples],
(const uint8_t *) mInputBuffer->data()
+ mInputBuffer->range_offset(),
copy);
mInputBuffer->set_range(
mInputBuffer->range_offset() + copy,
mInputBuffer->range_length() - copy);
if (mInputBuffer->range_length() == 0) { if (mInputBuffer->range_length() == 0) {
mInputBuffer->release(); mInputBuffer->release();
mInputBuffer = NULL; mInputBuffer = NULL;
return ERROR_END_OF_STREAM;
} }
VO_CODECBUFFER inputData; mNumInputSamples += copy / sizeof(int16_t);
memset(&inputData, 0, sizeof(inputData)); if (mNumInputSamples >= kNumSamplesPerFrame) {
inputData.Buffer = (unsigned char*) mInputBuffer->data(); mNumInputSamples %= kNumSamplesPerFrame;
inputData.Length = mInputBuffer->range_length(); break;
CHECK(VO_ERR_NONE == mApiHandle->SetInputData(mEncoderHandle,&inputData)); }
} }
CHECK(mInputBuffer != NULL); VO_CODECBUFFER inputData;
memset(&inputData, 0, sizeof(inputData));
inputData.Buffer = (unsigned char*) mInputFrame;
inputData.Length = kNumSamplesPerFrame * sizeof(int16_t);
CHECK(VO_ERR_NONE == mApiHandle->SetInputData(mEncoderHandle,&inputData));
VO_CODECBUFFER outputData; VO_CODECBUFFER outputData;
memset(&outputData, 0, sizeof(outputData)); memset(&outputData, 0, sizeof(outputData));
@@ -239,24 +273,14 @@ status_t AACEncoder::read(
memset(&outputInfo, 0, sizeof(outputInfo)); memset(&outputInfo, 0, sizeof(outputInfo));
VO_U32 ret = VO_ERR_NONE; VO_U32 ret = VO_ERR_NONE;
int32_t outputLength = 0;
outputData.Buffer = outPtr; outputData.Buffer = outPtr;
outputData.Length = buffer->size(); outputData.Length = buffer->size();
ret = mApiHandle->GetOutputData(mEncoderHandle, &outputData, &outputInfo); ret = mApiHandle->GetOutputData(mEncoderHandle, &outputData, &outputInfo);
if (ret == VO_ERR_NONE || ret == VO_ERR_INPUT_BUFFER_SMALL) { CHECK(ret == VO_ERR_NONE || ret == VO_ERR_INPUT_BUFFER_SMALL);
outputLength += outputData.Length; CHECK(outputData.Length != 0);
if (ret == VO_ERR_INPUT_BUFFER_SMALL) { // All done buffer->set_range(0, outputData.Length);
mInputBuffer->release();
mInputBuffer = NULL;
}
} else {
LOGE("failed to encode the input data 0x%lx", ret);
}
buffer->set_range(0, outputLength); int64_t timestampUs = ((mFrameCount - 1) * 1000000LL * kNumSamplesPerFrame) / mSampleRate;
// Each output frame compresses 1024 input PCM samples.
int64_t timestampUs = ((mFrameCount - 1) * 1000000LL * 1024) / mSampleRate;
++mFrameCount; ++mFrameCount;
buffer->meta_data()->setInt64(kKeyTime, timestampUs); buffer->meta_data()->setInt64(kKeyTime, timestampUs);

View File

@@ -52,6 +52,16 @@ class AACEncoder: public MediaSource {
int32_t mChannels; int32_t mChannels;
int32_t mBitRate; int32_t mBitRate;
int32_t mFrameCount; int32_t mFrameCount;
int64_t mAnchorTimeUs;
int64_t mNumInputSamples;
enum {
kNumSamplesPerFrame = 1024,
};
int16_t mInputFrame[kNumSamplesPerFrame];
uint8_t mAudioSpecificConfigData[2]; // auido specific data uint8_t mAudioSpecificConfigData[2]; // auido specific data
void *mEncoderHandle; void *mEncoderHandle;
VO_AUDIO_CODECAPI *mApiHandle; VO_AUDIO_CODECAPI *mApiHandle;