From 08c7473ce9b601e170fd79c530f106bf74277a0f Mon Sep 17 00:00:00 2001 From: James Dong Date: Thu, 10 Jun 2010 12:28:15 -0700 Subject: Initial checkin for pause and resume control Change-Id: Ibdcf7bea5fb66baa81878704ba4091dfcfe382ee --- .../libmediaplayerservice/StagefrightRecorder.cpp | 8 ++ media/libmediaplayerservice/StagefrightRecorder.h | 1 + media/libstagefright/AMRWriter.cpp | 46 ++++++++++- media/libstagefright/AudioSource.cpp | 10 ++- media/libstagefright/MPEG4Writer.cpp | 93 +++++++++++++++++++--- media/libstagefright/codecs/aacenc/AACEncoder.cpp | 11 ++- 6 files changed, 146 insertions(+), 23 deletions(-) (limited to 'media') diff --git a/media/libmediaplayerservice/StagefrightRecorder.cpp b/media/libmediaplayerservice/StagefrightRecorder.cpp index 2f3b075..a7ccce4 100644 --- a/media/libmediaplayerservice/StagefrightRecorder.cpp +++ b/media/libmediaplayerservice/StagefrightRecorder.cpp @@ -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; diff --git a/media/libmediaplayerservice/StagefrightRecorder.h b/media/libmediaplayerservice/StagefrightRecorder.h index b491e9f..baf33cf 100644 --- a/media/libmediaplayerservice/StagefrightRecorder.h +++ b/media/libmediaplayerservice/StagefrightRecorder.h @@ -47,6 +47,7 @@ struct StagefrightRecorder : public MediaRecorderBase { virtual status_t setListener(const sp& 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(); diff --git a/media/libstagefright/AMRWriter.cpp b/media/libstagefright/AMRWriter.cpp index aec7394..8951f5b 100644 --- a/media/libstagefright/AMRWriter.cpp +++ b/media/libstagefright/AMRWriter.cpp @@ -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; diff --git a/media/libstagefright/AudioSource.cpp b/media/libstagefright/AudioSource.cpp index 326e8dc..9717aa6 100644 --- a/media/libstagefright/AudioSource.cpp +++ b/media/libstagefright/AudioSource.cpp @@ -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) { diff --git a/media/libstagefright/MPEG4Writer.cpp b/media/libstagefright/MPEG4Writer.cpp index db60078..af11032 100644 --- a/media/libstagefright/MPEG4Writer.cpp +++ b/media/libstagefright/MPEG4Writer.cpp @@ -43,6 +43,7 @@ public: status_t start(); void stop(); + void pause(); bool reachedEOS(); int64_t getDurationUs() const; @@ -54,6 +55,8 @@ private: sp mMeta; sp 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 &source) { return OK; } +status_t MPEG4Writer::startTracks() { + for (List::iterator it = mTracks.begin(); + it != mTracks.end(); ++it) { + status_t err = (*it)->start(); + + if (err != OK) { + for (List::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,23 +218,26 @@ status_t MPEG4Writer::start() { mOffset = mMdatOffset; fseeko(mFile, mMdatOffset, SEEK_SET); write("\x00\x00\x00\x01mdat????????", 16); - for (List::iterator it = mTracks.begin(); - it != mTracks.end(); ++it) { - status_t err = (*it)->start(); - - if (err != OK) { - for (List::iterator it2 = mTracks.begin(); - it2 != it; ++it2) { - (*it2)->stop(); - } - return err; - } + status_t err = startTracks(); + if (err != OK) { + return err; } - + mStarted = true; return OK; } +void MPEG4Writer::pause() { + if (mFile == NULL) { + return; + } + mPaused = true; + for (List::iterator it = mTracks.begin(); + it != mTracks.end(); ++it) { + (*it)->pause(); + } +} + void MPEG4Writer::stop() { if (mFile == NULL) { return; @@ -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 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; } diff --git a/media/libstagefright/codecs/aacenc/AACEncoder.cpp b/media/libstagefright/codecs/aacenc/AACEncoder.cpp index d222cd9..282a10b 100644 --- a/media/libstagefright/codecs/aacenc/AACEncoder.cpp +++ b/media/libstagefright/codecs/aacenc/AACEncoder.cpp @@ -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; -- cgit v1.1