am f62c57d6: Merge "Initial checkin for pause and resume control" into kraken

Merge commit 'f62c57d684b83df7d2817db976c0afdb500ae92a' into gingerbread-plus-aosp

* commit 'f62c57d684b83df7d2817db976c0afdb500ae92a':
  Initial checkin for pause and resume control
This commit is contained in:
James Dong
2010-06-11 14:31:49 -07:00
committed by Android Git Automerger
9 changed files with 154 additions and 23 deletions

View File

@@ -37,6 +37,7 @@ struct AMRWriter : public MediaWriter {
virtual bool reachedEOS();
virtual status_t start();
virtual void stop();
virtual void pause();
protected:
virtual ~AMRWriter();
@@ -46,6 +47,8 @@ private:
status_t mInitCheck;
sp<MediaSource> mSource;
bool mStarted;
volatile bool mPaused;
volatile bool mResumed;
volatile bool mDone;
volatile bool mReachedEOS;
pthread_t mThread;

View File

@@ -39,6 +39,7 @@ public:
virtual status_t start();
virtual bool reachedEOS();
virtual void stop();
virtual void pause();
void beginBox(const char *fourcc);
void writeInt8(int8_t x);
@@ -59,6 +60,8 @@ private:
class Track;
FILE *mFile;
bool mPaused;
bool mStarted;
off_t mOffset;
off_t mMdatOffset;
uint8_t *mMoovBoxBuffer;
@@ -77,6 +80,7 @@ private:
void setStartTimestamp(int64_t timeUs);
int64_t getStartTimestamp(); // Not const
status_t startTracks();
void lock();
void unlock();

View File

@@ -32,6 +32,7 @@ struct MediaWriter : public RefBase {
virtual bool reachedEOS() = 0;
virtual status_t start() = 0;
virtual void stop() = 0;
virtual void pause() = 0;
virtual void setMaxFileSize(int64_t bytes) { mMaxFileSizeLimitBytes = bytes; }
virtual void setMaxFileDuration(int64_t durationUs) { mMaxFileDurationLimitUs = durationUs; }
virtual void setListener(const sp<IMediaPlayerClient>& listener) {

View File

@@ -692,6 +692,14 @@ status_t StagefrightRecorder::startMPEG4Recording() {
return OK;
}
status_t StagefrightRecorder::pause() {
if (mWriter == NULL) {
return UNKNOWN_ERROR;
}
mWriter->pause();
return OK;
}
status_t StagefrightRecorder::stop() {
if (mWriter == NULL) {
return UNKNOWN_ERROR;

View File

@@ -47,6 +47,7 @@ struct StagefrightRecorder : public MediaRecorderBase {
virtual status_t setListener(const sp<IMediaPlayerClient>& listener);
virtual status_t prepare();
virtual status_t start();
virtual status_t pause();
virtual status_t stop();
virtual status_t close();
virtual status_t reset();

View File

@@ -29,13 +29,17 @@ namespace android {
AMRWriter::AMRWriter(const char *filename)
: mFile(fopen(filename, "wb")),
mInitCheck(mFile != NULL ? OK : NO_INIT),
mStarted(false) {
mStarted(false),
mPaused(false),
mResumed(false) {
}
AMRWriter::AMRWriter(int fd)
: mFile(fdopen(fd, "wb")),
mInitCheck(mFile != NULL ? OK : NO_INIT),
mStarted(false) {
mStarted(false),
mPaused(false),
mResumed(false) {
}
AMRWriter::~AMRWriter() {
@@ -98,10 +102,19 @@ status_t AMRWriter::start() {
return mInitCheck;
}
if (mStarted || mSource == NULL) {
if (mSource == NULL) {
return UNKNOWN_ERROR;
}
if (mStarted && mPaused) {
mPaused = false;
mResumed = true;
return OK;
} else if (mStarted) {
// Already started, does nothing
return OK;
}
status_t err = mSource->start();
if (err != OK) {
@@ -123,6 +136,13 @@ status_t AMRWriter::start() {
return OK;
}
void AMRWriter::pause() {
if (!mStarted) {
return;
}
mPaused = true;
}
void AMRWriter::stop() {
if (!mStarted) {
return;
@@ -163,6 +183,9 @@ void AMRWriter::threadFunc() {
mEstimatedDurationUs = 0;
mEstimatedSizeBytes = 0;
bool stoppedPrematurely = true;
int64_t previousPausedDurationUs = 0;
int64_t maxTimestampUs = 0;
while (!mDone) {
MediaBuffer *buffer;
status_t err = mSource->read(&buffer);
@@ -171,6 +194,12 @@ void AMRWriter::threadFunc() {
break;
}
if (mPaused) {
buffer->release();
buffer = NULL;
continue;
}
mEstimatedSizeBytes += buffer->range_length();
if (exceedsFileSizeLimit()) {
buffer->release();
@@ -184,6 +213,17 @@ void AMRWriter::threadFunc() {
if (timestampUs > mEstimatedDurationUs) {
mEstimatedDurationUs = timestampUs;
}
if (mResumed) {
previousPausedDurationUs += (timestampUs - maxTimestampUs - 20000);
mResumed = false;
}
timestampUs -= previousPausedDurationUs;
LOGV("time stamp: %lld, previous paused duration: %lld",
timestampUs, previousPausedDurationUs);
if (timestampUs > maxTimestampUs) {
maxTimestampUs = timestampUs;
}
if (exceedsFileDurationLimit()) {
buffer->release();
buffer = NULL;

View File

@@ -121,11 +121,13 @@ status_t AudioSource::read(
uint32_t numFramesRecorded;
mRecord->getPosition(&numFramesRecorded);
int64_t latency = mRecord->latency() * 1000;
uint32_t sampleRate = mRecord->getSampleRate();
int64_t timestampUs = (1000000LL * numFramesRecorded) / sampleRate - latency;
LOGV("latency: %lld, sample rate: %d, timestamp: %lld",
latency, sampleRate, timestampUs);
buffer->meta_data()->setInt64(
kKeyTime,
(1000000ll * numFramesRecorded) / mRecord->getSampleRate()
- mRecord->latency() * 1000);
buffer->meta_data()->setInt64(kKeyTime, timestampUs);
ssize_t n = 0;
if (mCollectStats) {

View File

@@ -43,6 +43,7 @@ public:
status_t start();
void stop();
void pause();
bool reachedEOS();
int64_t getDurationUs() const;
@@ -54,6 +55,8 @@ private:
sp<MetaData> mMeta;
sp<MediaSource> mSource;
volatile bool mDone;
volatile bool mPaused;
volatile bool mResumed;
int64_t mMaxTimeStampUs;
int64_t mEstimatedTrackSizeBytes;
@@ -120,6 +123,8 @@ private:
MPEG4Writer::MPEG4Writer(const char *filename)
: mFile(fopen(filename, "wb")),
mPaused(false),
mStarted(false),
mOffset(0),
mMdatOffset(0),
mEstimatedMoovBoxSize(0),
@@ -129,6 +134,8 @@ MPEG4Writer::MPEG4Writer(const char *filename)
MPEG4Writer::MPEG4Writer(int fd)
: mFile(fdopen(fd, "wb")),
mPaused(false),
mStarted(false),
mOffset(0),
mMdatOffset(0),
mEstimatedMoovBoxSize(0),
@@ -153,11 +160,36 @@ status_t MPEG4Writer::addSource(const sp<MediaSource> &source) {
return OK;
}
status_t MPEG4Writer::startTracks() {
for (List<Track *>::iterator it = mTracks.begin();
it != mTracks.end(); ++it) {
status_t err = (*it)->start();
if (err != OK) {
for (List<Track *>::iterator it2 = mTracks.begin();
it2 != it; ++it2) {
(*it2)->stop();
}
return err;
}
}
return OK;
}
status_t MPEG4Writer::start() {
if (mFile == NULL) {
return UNKNOWN_ERROR;
}
if (mStarted) {
if (mPaused) {
mPaused = false;
return startTracks();
}
return OK;
}
mStartTimestampUs = 0;
mStreamableFile = true;
mWriteMoovBoxToMemory = false;
@@ -186,21 +218,24 @@ status_t MPEG4Writer::start() {
mOffset = mMdatOffset;
fseeko(mFile, mMdatOffset, SEEK_SET);
write("\x00\x00\x00\x01mdat????????", 16);
status_t err = startTracks();
if (err != OK) {
return err;
}
mStarted = true;
return OK;
}
void MPEG4Writer::pause() {
if (mFile == NULL) {
return;
}
mPaused = true;
for (List<Track *>::iterator it = mTracks.begin();
it != mTracks.end(); ++it) {
status_t err = (*it)->start();
if (err != OK) {
for (List<Track *>::iterator it2 = mTracks.begin();
it2 != it; ++it2) {
(*it2)->stop();
}
return err;
}
(*it)->pause();
}
return OK;
}
void MPEG4Writer::stop() {
@@ -298,6 +333,7 @@ void MPEG4Writer::stop() {
fflush(mFile);
fclose(mFile);
mFile = NULL;
mStarted = false;
}
status_t MPEG4Writer::setInterleaveDuration(uint32_t durationUs) {
@@ -528,6 +564,8 @@ MPEG4Writer::Track::Track(
mMeta(source->getFormat()),
mSource(source),
mDone(false),
mPaused(false),
mResumed(false),
mMaxTimeStampUs(0),
mEstimatedTrackSizeBytes(0),
mSamplesHaveSameSize(true),
@@ -547,6 +585,11 @@ MPEG4Writer::Track::~Track() {
}
status_t MPEG4Writer::Track::start() {
if (!mDone && mPaused) {
mPaused = false;
mResumed = true;
return OK;
}
status_t err = mSource->start();
if (err != OK) {
@@ -569,6 +612,10 @@ status_t MPEG4Writer::Track::start() {
return OK;
}
void MPEG4Writer::Track::pause() {
mPaused = true;
}
void MPEG4Writer::Track::stop() {
if (mDone) {
return;
@@ -710,6 +757,7 @@ void MPEG4Writer::Track::threadEntry() {
int64_t lastDuration = 0; // Time spacing between the previous two samples
int32_t sampleCount = 1; // Sample count in the current stts table entry
uint32_t previousSampleSize = 0; // Size of the previous sample
int64_t previousPausedDurationUs = 0;
sp<MetaData> meta_data;
MediaBuffer *buffer;
@@ -721,6 +769,15 @@ void MPEG4Writer::Track::threadEntry() {
continue;
}
// If the codec specific data has not been received yet, delay pause.
// After the codec specific data is received, discard what we received
// when the track is to be paused.
if (mPaused && !mResumed) {
buffer->release();
buffer = NULL;
continue;
}
++count;
int32_t isCodecConfig;
@@ -831,6 +888,10 @@ void MPEG4Writer::Track::threadEntry() {
continue;
}
if (!mGotAllCodecSpecificData) {
mGotAllCodecSpecificData = true;
}
// Make a deep copy of the MediaBuffer and Metadata and release
// the original as soon as we can
MediaBuffer *copy = new MediaBuffer(buffer->range_length());
@@ -876,6 +937,14 @@ void MPEG4Writer::Track::threadEntry() {
mStartTimestampUs = (timestampUs - mOwner->getStartTimestamp());
}
if (mResumed) {
previousPausedDurationUs += (timestampUs - mMaxTimeStampUs - 1000 * lastDuration);
mResumed = false;
}
timestampUs -= previousPausedDurationUs;
LOGV("time stamp: %lld and previous paused duration %lld",
timestampUs, previousPausedDurationUs);
if (timestampUs > mMaxTimeStampUs) {
mMaxTimeStampUs = timestampUs;
}

View File

@@ -205,13 +205,15 @@ status_t AACEncoder::read(
buffer->set_range(0, 2);
buffer->meta_data()->setInt32(kKeyIsCodecConfig, true);
*out = buffer;
++mFrameCount;
mInputBuffer = NULL;
++mFrameCount;
return OK;
} else {
} else if (mFrameCount == 1) {
buffer->meta_data()->setInt32(kKeyIsCodecConfig, false);
}
// XXX: We assume that the input buffer contains at least
// (actually, exactly) 1024 PCM samples. This needs to be fixed.
if (mInputBuffer == NULL) {
if (mSource->read(&mInputBuffer, options) != OK) {
LOGE("failed to read from input audio source");
@@ -252,9 +254,10 @@ status_t AACEncoder::read(
}
buffer->set_range(0, outputLength);
++mFrameCount;
int64_t timestampUs = (mFrameCount * 1000000LL * 1024) / mSampleRate;
// Each output frame compresses 1024 input PCM samples.
int64_t timestampUs = ((mFrameCount - 1) * 1000000LL * 1024) / mSampleRate;
++mFrameCount;
buffer->meta_data()->setInt64(kKeyTime, timestampUs);
*out = buffer;