am cbd038fe: Merge "Make MediaWriter stop and pause return errors if necessary" into gingerbread

Merge commit 'cbd038fe207f183bc7e0a610973473f7c2e9d118' into gingerbread-plus-aosp

* commit 'cbd038fe207f183bc7e0a610973473f7c2e9d118':
  Make MediaWriter stop and pause return errors if necessary
This commit is contained in:
James Dong
2010-08-19 14:02:25 -07:00
committed by Android Git Automerger
8 changed files with 90 additions and 43 deletions

View File

@ -37,8 +37,8 @@ struct AMRWriter : public MediaWriter {
virtual status_t addSource(const sp<MediaSource> &source); virtual status_t addSource(const sp<MediaSource> &source);
virtual bool reachedEOS(); virtual bool reachedEOS();
virtual status_t start(MetaData *params = NULL); virtual status_t start(MetaData *params = NULL);
virtual void stop(); virtual status_t stop();
virtual void pause(); virtual status_t pause();
protected: protected:
virtual ~AMRWriter(); virtual ~AMRWriter();
@ -57,7 +57,7 @@ private:
int64_t mEstimatedDurationUs; int64_t mEstimatedDurationUs;
static void *ThreadWrapper(void *); static void *ThreadWrapper(void *);
void threadFunc(); status_t threadFunc();
bool exceedsFileSizeLimit(); bool exceedsFileSizeLimit();
bool exceedsFileDurationLimit(); bool exceedsFileDurationLimit();

View File

@ -37,9 +37,9 @@ public:
virtual status_t addSource(const sp<MediaSource> &source); virtual status_t addSource(const sp<MediaSource> &source);
virtual status_t start(MetaData *param = NULL); virtual status_t start(MetaData *param = NULL);
virtual status_t stop();
virtual status_t pause();
virtual bool reachedEOS(); virtual bool reachedEOS();
virtual void stop();
virtual void pause();
void beginBox(const char *fourcc); void beginBox(const char *fourcc);
void writeInt8(int8_t x); void writeInt8(int8_t x);

View File

@ -35,8 +35,9 @@ struct MediaWriter : public RefBase {
virtual status_t addSource(const sp<MediaSource> &source) = 0; virtual status_t addSource(const sp<MediaSource> &source) = 0;
virtual bool reachedEOS() = 0; virtual bool reachedEOS() = 0;
virtual status_t start(MetaData *params = NULL) = 0; virtual status_t start(MetaData *params = NULL) = 0;
virtual void stop() = 0; virtual status_t stop() = 0;
virtual void pause() = 0; virtual status_t pause() = 0;
virtual void setMaxFileSize(int64_t bytes) { mMaxFileSizeLimitBytes = bytes; } virtual void setMaxFileSize(int64_t bytes) { mMaxFileSizeLimitBytes = bytes; }
virtual void setMaxFileDuration(int64_t durationUs) { mMaxFileDurationLimitUs = durationUs; } virtual void setMaxFileDuration(int64_t durationUs) { mMaxFileDurationLimitUs = durationUs; }
virtual void setListener(const sp<IMediaRecorderClient>& listener) { virtual void setListener(const sp<IMediaRecorderClient>& listener) {

View File

@ -1067,8 +1067,9 @@ status_t StagefrightRecorder::pause() {
status_t StagefrightRecorder::stop() { status_t StagefrightRecorder::stop() {
LOGV("stop"); LOGV("stop");
status_t err = OK;
if (mWriter != NULL) { if (mWriter != NULL) {
mWriter->stop(); err = mWriter->stop();
mWriter.clear(); mWriter.clear();
} }
@ -1090,7 +1091,7 @@ status_t StagefrightRecorder::stop() {
mOutputFd = -1; mOutputFd = -1;
} }
return OK; return err;
} }
status_t StagefrightRecorder::close() { status_t StagefrightRecorder::close() {

View File

@ -136,16 +136,17 @@ status_t AMRWriter::start(MetaData *params) {
return OK; return OK;
} }
void AMRWriter::pause() { status_t AMRWriter::pause() {
if (!mStarted) { if (!mStarted) {
return; return OK;
} }
mPaused = true; mPaused = true;
return OK;
} }
void AMRWriter::stop() { status_t AMRWriter::stop() {
if (!mStarted) { if (!mStarted) {
return; return OK;
} }
mDone = true; mDone = true;
@ -153,9 +154,17 @@ void AMRWriter::stop() {
void *dummy; void *dummy;
pthread_join(mThread, &dummy); pthread_join(mThread, &dummy);
mSource->stop(); status_t err = (status_t) dummy;
{
status_t status = mSource->stop();
if (err == OK &&
(status != OK && status != ERROR_END_OF_STREAM)) {
err = status;
}
}
mStarted = false; mStarted = false;
return err;
} }
bool AMRWriter::exceedsFileSizeLimit() { bool AMRWriter::exceedsFileSizeLimit() {
@ -174,21 +183,20 @@ bool AMRWriter::exceedsFileDurationLimit() {
// static // static
void *AMRWriter::ThreadWrapper(void *me) { void *AMRWriter::ThreadWrapper(void *me) {
static_cast<AMRWriter *>(me)->threadFunc(); return (void *) static_cast<AMRWriter *>(me)->threadFunc();
return NULL;
} }
void AMRWriter::threadFunc() { status_t AMRWriter::threadFunc() {
mEstimatedDurationUs = 0; mEstimatedDurationUs = 0;
mEstimatedSizeBytes = 0; mEstimatedSizeBytes = 0;
bool stoppedPrematurely = true; bool stoppedPrematurely = true;
int64_t previousPausedDurationUs = 0; int64_t previousPausedDurationUs = 0;
int64_t maxTimestampUs = 0; int64_t maxTimestampUs = 0;
status_t err = OK;
while (!mDone) { while (!mDone) {
MediaBuffer *buffer; MediaBuffer *buffer;
status_t err = mSource->read(&buffer); err = mSource->read(&buffer);
if (err != OK) { if (err != OK) {
break; break;
@ -260,6 +268,10 @@ void AMRWriter::threadFunc() {
fclose(mFile); fclose(mFile);
mFile = NULL; mFile = NULL;
mReachedEOS = true; mReachedEOS = true;
if (err == ERROR_END_OF_STREAM) {
return OK;
}
return err;
} }
bool AMRWriter::reachedEOS() { bool AMRWriter::reachedEOS() {

View File

@ -48,8 +48,8 @@ public:
~Track(); ~Track();
status_t start(MetaData *params); status_t start(MetaData *params);
void stop(); status_t stop();
void pause(); status_t pause();
bool reachedEOS(); bool reachedEOS();
int64_t getDurationUs() const; int64_t getDurationUs() const;
@ -144,7 +144,7 @@ private:
int64_t mTrackEveryTimeDurationUs; int64_t mTrackEveryTimeDurationUs;
static void *ThreadWrapper(void *me); static void *ThreadWrapper(void *me);
void threadEntry(); status_t threadEntry();
const uint8_t *parseParamSet( const uint8_t *parseParamSet(
const uint8_t *data, size_t length, int type, size_t *paramSetLen); const uint8_t *data, size_t length, int type, size_t *paramSetLen);
@ -378,16 +378,21 @@ status_t MPEG4Writer::start(MetaData *param) {
return OK; return OK;
} }
void MPEG4Writer::pause() { status_t MPEG4Writer::pause() {
if (mFile == NULL) { if (mFile == NULL) {
return; return OK;
} }
mPaused = true; mPaused = true;
status_t err = OK;
for (List<Track *>::iterator it = mTracks.begin(); for (List<Track *>::iterator it = mTracks.begin();
it != mTracks.end(); ++it) { it != mTracks.end(); ++it) {
(*it)->pause(); status_t status = (*it)->pause();
if (status != OK) {
err = status;
} }
} }
return err;
}
void MPEG4Writer::stopWriterThread() { void MPEG4Writer::stopWriterThread() {
LOGV("stopWriterThread"); LOGV("stopWriterThread");
@ -403,15 +408,19 @@ void MPEG4Writer::stopWriterThread() {
pthread_join(mThread, &dummy); pthread_join(mThread, &dummy);
} }
void MPEG4Writer::stop() { status_t MPEG4Writer::stop() {
if (mFile == NULL) { if (mFile == NULL) {
return; return OK;
} }
status_t err = OK;
int64_t maxDurationUs = 0; int64_t maxDurationUs = 0;
for (List<Track *>::iterator it = mTracks.begin(); for (List<Track *>::iterator it = mTracks.begin();
it != mTracks.end(); ++it) { it != mTracks.end(); ++it) {
(*it)->stop(); status_t status = (*it)->stop();
if (err == OK && status != OK) {
err = status;
}
int64_t durationUs = (*it)->getDurationUs(); int64_t durationUs = (*it)->getDurationUs();
if (durationUs > maxDurationUs) { if (durationUs > maxDurationUs) {
@ -421,6 +430,15 @@ void MPEG4Writer::stop() {
stopWriterThread(); stopWriterThread();
// Do not write out movie header on error.
if (err != OK) {
fflush(mFile);
fclose(mFile);
mFile = NULL;
mStarted = false;
return err;
}
// Fix up the size of the 'mdat' chunk. // Fix up the size of the 'mdat' chunk.
if (mUse32BitOffset) { if (mUse32BitOffset) {
fseeko(mFile, mMdatOffset, SEEK_SET); fseeko(mFile, mMdatOffset, SEEK_SET);
@ -508,6 +526,7 @@ void MPEG4Writer::stop() {
fclose(mFile); fclose(mFile);
mFile = NULL; mFile = NULL;
mStarted = false; mStarted = false;
return err;
} }
status_t MPEG4Writer::setInterleaveDuration(uint32_t durationUs) { status_t MPEG4Writer::setInterleaveDuration(uint32_t durationUs) {
@ -1030,13 +1049,14 @@ status_t MPEG4Writer::Track::start(MetaData *params) {
return OK; return OK;
} }
void MPEG4Writer::Track::pause() { status_t MPEG4Writer::Track::pause() {
mPaused = true; mPaused = true;
return OK;
} }
void MPEG4Writer::Track::stop() { status_t MPEG4Writer::Track::stop() {
if (mDone) { if (mDone) {
return; return OK;
} }
mDone = true; mDone = true;
@ -1044,7 +1064,16 @@ void MPEG4Writer::Track::stop() {
void *dummy; void *dummy;
pthread_join(mThread, &dummy); pthread_join(mThread, &dummy);
mSource->stop(); status_t err = (status_t) dummy;
{
status_t status = mSource->stop();
if (err == OK && status != OK && status != ERROR_END_OF_STREAM) {
err = status;
}
}
return err;
} }
bool MPEG4Writer::Track::reachedEOS() { bool MPEG4Writer::Track::reachedEOS() {
@ -1055,9 +1084,8 @@ bool MPEG4Writer::Track::reachedEOS() {
void *MPEG4Writer::Track::ThreadWrapper(void *me) { void *MPEG4Writer::Track::ThreadWrapper(void *me) {
Track *track = static_cast<Track *>(me); Track *track = static_cast<Track *>(me);
track->threadEntry(); status_t err = track->threadEntry();
return (void *) err;
return NULL;
} }
#include <ctype.h> #include <ctype.h>
@ -1352,7 +1380,7 @@ static bool collectStatisticalData() {
return false; return false;
} }
void MPEG4Writer::Track::threadEntry() { status_t MPEG4Writer::Track::threadEntry() {
int32_t count = 0; int32_t count = 0;
const int64_t interleaveDurationUs = mOwner->interleaveDuration(); const int64_t interleaveDurationUs = mOwner->interleaveDuration();
int64_t chunkTimestampUs = 0; int64_t chunkTimestampUs = 0;
@ -1595,7 +1623,7 @@ void MPEG4Writer::Track::threadEntry() {
} }
if (mSampleSizes.empty()) { if (mSampleSizes.empty()) {
err = UNKNOWN_ERROR; err = ERROR_MALFORMED;
} }
mOwner->trackProgressStatus(this, -1, err); mOwner->trackProgressStatus(this, -1, err);
@ -1626,6 +1654,10 @@ void MPEG4Writer::Track::threadEntry() {
count, nZeroLengthFrames, mNumSamples, mMaxWriteTimeUs, mIsAudio? "audio": "video"); count, nZeroLengthFrames, mNumSamples, mMaxWriteTimeUs, mIsAudio? "audio": "video");
logStatisticalData(mIsAudio); logStatisticalData(mIsAudio);
if (err == ERROR_END_OF_STREAM) {
return OK;
}
return err;
} }
void MPEG4Writer::Track::trackProgressStatus(int64_t timeUs, status_t err) { void MPEG4Writer::Track::trackProgressStatus(int64_t timeUs, status_t err) {
@ -1973,7 +2005,6 @@ void MPEG4Writer::Track::writeTrackHeader(
int32_t samplerate; int32_t samplerate;
bool success = mMeta->findInt32(kKeySampleRate, &samplerate); bool success = mMeta->findInt32(kKeySampleRate, &samplerate);
CHECK(success); CHECK(success);
mOwner->writeInt32(samplerate << 16); mOwner->writeInt32(samplerate << 16);
if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime)) { if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AAC, mime)) {
mOwner->beginBox("esds"); mOwner->beginBox("esds");

View File

@ -134,10 +134,10 @@ status_t ARTPWriter::start(MetaData *params) {
return OK; return OK;
} }
void ARTPWriter::stop() { status_t ARTPWriter::stop() {
Mutex::Autolock autoLock(mLock); Mutex::Autolock autoLock(mLock);
if (!(mFlags & kFlagStarted)) { if (!(mFlags & kFlagStarted)) {
return; return OK;
} }
(new AMessage(kWhatStop, mReflector->id()))->post(); (new AMessage(kWhatStop, mReflector->id()))->post();
@ -145,9 +145,11 @@ void ARTPWriter::stop() {
while (mFlags & kFlagStarted) { while (mFlags & kFlagStarted) {
mCondition.wait(mLock); mCondition.wait(mLock);
} }
return OK;
} }
void ARTPWriter::pause() { status_t ARTPWriter::pause() {
return OK;
} }
static void StripStartcode(MediaBuffer *buffer) { static void StripStartcode(MediaBuffer *buffer) {

View File

@ -40,8 +40,8 @@ struct ARTPWriter : public MediaWriter {
virtual status_t addSource(const sp<MediaSource> &source); virtual status_t addSource(const sp<MediaSource> &source);
virtual bool reachedEOS(); virtual bool reachedEOS();
virtual status_t start(MetaData *params); virtual status_t start(MetaData *params);
virtual void stop(); virtual status_t stop();
virtual void pause(); virtual status_t pause();
virtual void onMessageReceived(const sp<AMessage> &msg); virtual void onMessageReceived(const sp<AMessage> &msg);