am 53d4e0d5: Allows the authoring engine to skip frame.

Merge commit '53d4e0d58e2d5c18f6e026c705af833b9bdd7aba' into gingerbread-plus-aosp

* commit '53d4e0d58e2d5c18f6e026c705af833b9bdd7aba':
  Allows the authoring engine to skip frame.
This commit is contained in:
James Dong
2010-07-22 16:25:17 -07:00
committed by Android Git Automerger
7 changed files with 142 additions and 58 deletions

View File

@@ -78,18 +78,31 @@ struct MediaSource : public RefBase {
void clearSeekTo(); void clearSeekTo();
bool getSeekTo(int64_t *time_us, SeekMode *mode) const; bool getSeekTo(int64_t *time_us, SeekMode *mode) const;
// Option allows encoder to skip some frames until the specified
// time stamp.
// To prevent from being abused, when the skipFrame timestamp is
// found to be more than 1 second later than the current timestamp,
// an error will be returned from read().
void clearSkipFrame();
bool getSkipFrame(int64_t *timeUs) const;
void setSkipFrame(int64_t timeUs);
void setLateBy(int64_t lateness_us); void setLateBy(int64_t lateness_us);
int64_t getLateBy() const; int64_t getLateBy() const;
private: private:
enum Options { enum Options {
// Bit map
kSeekTo_Option = 1, kSeekTo_Option = 1,
kSkipFrame_Option = 2,
}; };
uint32_t mOptions; uint32_t mOptions;
int64_t mSeekTimeUs; int64_t mSeekTimeUs;
SeekMode mSeekMode; SeekMode mSeekMode;
int64_t mLatenessUs; int64_t mLatenessUs;
int64_t mSkipFrameUntilTimeUs;
}; };
// Causes this source to suspend pulling data from its upstream source // Causes this source to suspend pulling data from its upstream source

View File

@@ -143,6 +143,7 @@ private:
int64_t mSeekTimeUs; int64_t mSeekTimeUs;
ReadOptions::SeekMode mSeekMode; ReadOptions::SeekMode mSeekMode;
int64_t mTargetTimeUs; int64_t mTargetTimeUs;
int64_t mSkipTimeUs;
MediaBuffer *mLeftOverBuffer; MediaBuffer *mLeftOverBuffer;

View File

@@ -137,11 +137,13 @@ status_t AudioSource::read(
MediaBuffer *buffer; MediaBuffer *buffer;
CHECK_EQ(mGroup->acquire_buffer(&buffer), OK); CHECK_EQ(mGroup->acquire_buffer(&buffer), OK);
while (mStarted) {
uint32_t numFramesRecorded; uint32_t numFramesRecorded;
mRecord->getPosition(&numFramesRecorded); mRecord->getPosition(&numFramesRecorded);
int64_t latency = mRecord->latency() * 1000; int64_t latency = mRecord->latency() * 1000;
int64_t readTime = systemTime() / 1000; int64_t readTime = systemTime() / 1000;
if (numFramesRecorded == 0) { if (numFramesRecorded == 0) {
// Initial delay // Initial delay
if (mStartTimeUs > 0) { if (mStartTimeUs > 0) {
@@ -170,12 +172,31 @@ status_t AudioSource::read(
return (status_t)n; return (status_t)n;
} }
uint32_t sampleRate = mRecord->getSampleRate();
int64_t timestampUs = (1000000LL * numFramesRecorded) / sampleRate +
mStartTimeUs;
int64_t skipFrameUs;
if (!options || !options->getSkipFrame(&skipFrameUs)) {
skipFrameUs = timestampUs; // Don't skip frame
}
if (skipFrameUs > timestampUs) {
// Safe guard against the abuse of the kSkipFrame_Option.
if (skipFrameUs - timestampUs >= 1E6) {
LOGE("Frame skipping requested is way too long: %lld us",
skipFrameUs - timestampUs);
buffer->release();
return UNKNOWN_ERROR;
}
LOGV("skipFrame: %lld us > timestamp: %lld us, samples %d",
skipFrameUs, timestampUs, numFramesRecorded);
continue;
}
if (mTrackMaxAmplitude) { if (mTrackMaxAmplitude) {
trackMaxAmplitude((int16_t *) buffer->data(), n >> 1); trackMaxAmplitude((int16_t *) buffer->data(), n >> 1);
} }
uint32_t sampleRate = mRecord->getSampleRate();
int64_t timestampUs = (1000000LL * numFramesRecorded) / sampleRate + mStartTimeUs;
buffer->meta_data()->setInt64(kKeyTime, timestampUs); buffer->meta_data()->setInt64(kKeyTime, timestampUs);
LOGV("initial delay: %lld, sample rate: %d, timestamp: %lld", LOGV("initial delay: %lld, sample rate: %d, timestamp: %lld",
mStartTimeUs, sampleRate, timestampUs); mStartTimeUs, sampleRate, timestampUs);
@@ -183,6 +204,8 @@ status_t AudioSource::read(
buffer->set_range(0, n); buffer->set_range(0, n);
*out = buffer; *out = buffer;
return OK;
}
return OK; return OK;
} }

View File

@@ -277,23 +277,44 @@ status_t CameraSource::read(
{ {
Mutex::Autolock autoLock(mLock); Mutex::Autolock autoLock(mLock);
while (mStarted && mFramesReceived.empty()) { while (mStarted) {
while(mFramesReceived.empty()) {
mFrameAvailableCondition.wait(mLock); mFrameAvailableCondition.wait(mLock);
} }
if (!mStarted) { if (!mStarted) {
return OK; return OK;
} }
frame = *mFramesReceived.begin(); frame = *mFramesReceived.begin();
mFramesReceived.erase(mFramesReceived.begin()); mFramesReceived.erase(mFramesReceived.begin());
frameTime = *mFrameTimes.begin(); frameTime = *mFrameTimes.begin();
mFrameTimes.erase(mFrameTimes.begin()); mFrameTimes.erase(mFrameTimes.begin());
int64_t skipTimeUs;
if (!options || !options->getSkipFrame(&skipTimeUs)) {
skipTimeUs = frameTime;
}
if (skipTimeUs > frameTime) {
LOGV("skipTimeUs: %lld us > frameTime: %lld us",
skipTimeUs, frameTime);
releaseOneRecordingFrame(frame);
++mNumFramesDropped;
// Safeguard against the abuse of the kSkipFrame_Option.
if (skipTimeUs - frameTime >= 1E6) {
LOGE("Frame skipping requested is way too long: %lld us",
skipTimeUs - frameTime);
return UNKNOWN_ERROR;
}
} else {
mFramesBeingEncoded.push_back(frame); mFramesBeingEncoded.push_back(frame);
*buffer = new MediaBuffer(frame->pointer(), frame->size()); *buffer = new MediaBuffer(frame->pointer(), frame->size());
(*buffer)->setObserver(this); (*buffer)->setObserver(this);
(*buffer)->add_ref(); (*buffer)->add_ref();
(*buffer)->meta_data()->setInt64(kKeyTime, frameTime); (*buffer)->meta_data()->setInt64(kKeyTime, frameTime);
return OK;
}
}
} }
return OK; return OK;
} }

View File

@@ -32,6 +32,7 @@ void MediaSource::ReadOptions::reset() {
mOptions = 0; mOptions = 0;
mSeekTimeUs = 0; mSeekTimeUs = 0;
mLatenessUs = 0; mLatenessUs = 0;
mSkipFrameUntilTimeUs = 0;
} }
void MediaSource::ReadOptions::setSeekTo(int64_t time_us, SeekMode mode) { void MediaSource::ReadOptions::setSeekTo(int64_t time_us, SeekMode mode) {
@@ -53,6 +54,21 @@ bool MediaSource::ReadOptions::getSeekTo(
return (mOptions & kSeekTo_Option) != 0; return (mOptions & kSeekTo_Option) != 0;
} }
void MediaSource::ReadOptions::clearSkipFrame() {
mOptions &= ~kSkipFrame_Option;
mSkipFrameUntilTimeUs = 0;
}
void MediaSource::ReadOptions::setSkipFrame(int64_t timeUs) {
mOptions |= kSkipFrame_Option;
mSkipFrameUntilTimeUs = timeUs;
}
bool MediaSource::ReadOptions::getSkipFrame(int64_t *timeUs) const {
*timeUs = mSkipFrameUntilTimeUs;
return (mOptions & kSkipFrame_Option) != 0;
}
void MediaSource::ReadOptions::setLateBy(int64_t lateness_us) { void MediaSource::ReadOptions::setLateBy(int64_t lateness_us) {
mLatenessUs = lateness_us; mLatenessUs = lateness_us;
} }

View File

@@ -1274,6 +1274,7 @@ OMXCodec::OMXCodec(
mSeekTimeUs(-1), mSeekTimeUs(-1),
mSeekMode(ReadOptions::SEEK_CLOSEST_SYNC), mSeekMode(ReadOptions::SEEK_CLOSEST_SYNC),
mTargetTimeUs(-1), mTargetTimeUs(-1),
mSkipTimeUs(-1),
mLeftOverBuffer(NULL), mLeftOverBuffer(NULL),
mPaused(false) { mPaused(false) {
mPortStatus[kPortIndexInput] = ENABLED; mPortStatus[kPortIndexInput] = ENABLED;
@@ -2200,13 +2201,15 @@ void OMXCodec::drainInputBuffer(BufferInfo *info) {
int32_t n = 0; int32_t n = 0;
for (;;) { for (;;) {
MediaBuffer *srcBuffer; MediaBuffer *srcBuffer;
MediaSource::ReadOptions options;
if (mSkipTimeUs >= 0) {
options.setSkipFrame(mSkipTimeUs);
}
if (mSeekTimeUs >= 0) { if (mSeekTimeUs >= 0) {
if (mLeftOverBuffer) { if (mLeftOverBuffer) {
mLeftOverBuffer->release(); mLeftOverBuffer->release();
mLeftOverBuffer = NULL; mLeftOverBuffer = NULL;
} }
MediaSource::ReadOptions options;
options.setSeekTo(mSeekTimeUs, mSeekMode); options.setSeekTo(mSeekTimeUs, mSeekMode);
mSeekTimeUs = -1; mSeekTimeUs = -1;
@@ -2231,7 +2234,7 @@ void OMXCodec::drainInputBuffer(BufferInfo *info) {
err = OK; err = OK;
} else { } else {
err = mSource->read(&srcBuffer); err = mSource->read(&srcBuffer, &options);
} }
if (err != OK) { if (err != OK) {
@@ -2830,6 +2833,12 @@ status_t OMXCodec::read(
if (options && options->getSeekTo(&seekTimeUs, &seekMode)) { if (options && options->getSeekTo(&seekTimeUs, &seekMode)) {
seeking = true; seeking = true;
} }
int64_t skipTimeUs;
if (options && options->getSkipFrame(&skipTimeUs)) {
mSkipTimeUs = skipTimeUs;
} else {
mSkipTimeUs = -1;
}
if (mInitialBufferSubmit) { if (mInitialBufferSubmit) {
mInitialBufferSubmit = false; mInitialBufferSubmit = false;

View File

@@ -224,6 +224,7 @@ status_t AACEncoder::read(
if (mInputBuffer == NULL) { if (mInputBuffer == NULL) {
if (mSource->read(&mInputBuffer, options) != OK) { if (mSource->read(&mInputBuffer, options) != OK) {
if (mNumInputSamples == 0) { if (mNumInputSamples == 0) {
buffer->release();
return ERROR_END_OF_STREAM; return ERROR_END_OF_STREAM;
} }
memset(&mInputFrame[mNumInputSamples], memset(&mInputFrame[mNumInputSamples],