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:
@@ -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
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|
||||||
|
|||||||
@@ -137,53 +137,76 @@ status_t AudioSource::read(
|
|||||||
MediaBuffer *buffer;
|
MediaBuffer *buffer;
|
||||||
CHECK_EQ(mGroup->acquire_buffer(&buffer), OK);
|
CHECK_EQ(mGroup->acquire_buffer(&buffer), OK);
|
||||||
|
|
||||||
uint32_t numFramesRecorded;
|
while (mStarted) {
|
||||||
mRecord->getPosition(&numFramesRecorded);
|
uint32_t numFramesRecorded;
|
||||||
int64_t latency = mRecord->latency() * 1000;
|
mRecord->getPosition(&numFramesRecorded);
|
||||||
|
int64_t latency = mRecord->latency() * 1000;
|
||||||
|
|
||||||
int64_t readTime = systemTime() / 1000;
|
int64_t readTime = systemTime() / 1000;
|
||||||
if (numFramesRecorded == 0) {
|
|
||||||
// Initial delay
|
if (numFramesRecorded == 0) {
|
||||||
if (mStartTimeUs > 0) {
|
// Initial delay
|
||||||
mStartTimeUs = readTime - mStartTimeUs;
|
if (mStartTimeUs > 0) {
|
||||||
|
mStartTimeUs = readTime - mStartTimeUs;
|
||||||
|
} else {
|
||||||
|
mStartTimeUs += latency;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ssize_t n = 0;
|
||||||
|
if (mCollectStats) {
|
||||||
|
n = mRecord->read(buffer->data(), buffer->size());
|
||||||
|
int64_t endTime = systemTime() / 1000;
|
||||||
|
mTotalReadTimeUs += (endTime - readTime);
|
||||||
|
if (n >= 0) {
|
||||||
|
mTotalReadBytes += n;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
mStartTimeUs += latency;
|
n = mRecord->read(buffer->data(), buffer->size());
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
ssize_t n = 0;
|
if (n < 0) {
|
||||||
if (mCollectStats) {
|
buffer->release();
|
||||||
n = mRecord->read(buffer->data(), buffer->size());
|
buffer = NULL;
|
||||||
int64_t endTime = systemTime() / 1000;
|
|
||||||
mTotalReadTimeUs += (endTime - readTime);
|
return (status_t)n;
|
||||||
if (n >= 0) {
|
|
||||||
mTotalReadBytes += n;
|
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
n = mRecord->read(buffer->data(), buffer->size());
|
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) {
|
||||||
|
trackMaxAmplitude((int16_t *) buffer->data(), n >> 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer->meta_data()->setInt64(kKeyTime, timestampUs);
|
||||||
|
LOGV("initial delay: %lld, sample rate: %d, timestamp: %lld",
|
||||||
|
mStartTimeUs, sampleRate, timestampUs);
|
||||||
|
|
||||||
|
buffer->set_range(0, n);
|
||||||
|
|
||||||
|
*out = buffer;
|
||||||
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (n < 0) {
|
|
||||||
buffer->release();
|
|
||||||
buffer = NULL;
|
|
||||||
|
|
||||||
return (status_t)n;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mTrackMaxAmplitude) {
|
|
||||||
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);
|
|
||||||
LOGV("initial delay: %lld, sample rate: %d, timestamp: %lld",
|
|
||||||
mStartTimeUs, sampleRate, timestampUs);
|
|
||||||
|
|
||||||
buffer->set_range(0, n);
|
|
||||||
|
|
||||||
*out = buffer;
|
|
||||||
|
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -277,23 +277,44 @@ status_t CameraSource::read(
|
|||||||
|
|
||||||
{
|
{
|
||||||
Mutex::Autolock autoLock(mLock);
|
Mutex::Autolock autoLock(mLock);
|
||||||
while (mStarted && mFramesReceived.empty()) {
|
while (mStarted) {
|
||||||
mFrameAvailableCondition.wait(mLock);
|
while(mFramesReceived.empty()) {
|
||||||
}
|
mFrameAvailableCondition.wait(mLock);
|
||||||
if (!mStarted) {
|
}
|
||||||
return OK;
|
|
||||||
}
|
|
||||||
frame = *mFramesReceived.begin();
|
|
||||||
mFramesReceived.erase(mFramesReceived.begin());
|
|
||||||
|
|
||||||
frameTime = *mFrameTimes.begin();
|
if (!mStarted) {
|
||||||
mFrameTimes.erase(mFrameTimes.begin());
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
mFramesBeingEncoded.push_back(frame);
|
frame = *mFramesReceived.begin();
|
||||||
*buffer = new MediaBuffer(frame->pointer(), frame->size());
|
mFramesReceived.erase(mFramesReceived.begin());
|
||||||
(*buffer)->setObserver(this);
|
|
||||||
(*buffer)->add_ref();
|
frameTime = *mFrameTimes.begin();
|
||||||
(*buffer)->meta_data()->setInt64(kKeyTime, frameTime);
|
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);
|
||||||
|
*buffer = new MediaBuffer(frame->pointer(), frame->size());
|
||||||
|
(*buffer)->setObserver(this);
|
||||||
|
(*buffer)->add_ref();
|
||||||
|
(*buffer)->meta_data()->setInt64(kKeyTime, frameTime);
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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],
|
||||||
|
|||||||
Reference in New Issue
Block a user