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:
@@ -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;
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user