summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/media/stagefright/AMRWriter.h3
-rw-r--r--include/media/stagefright/MPEG4Writer.h4
-rw-r--r--include/media/stagefright/MediaWriter.h1
-rw-r--r--media/libmediaplayerservice/StagefrightRecorder.cpp8
-rw-r--r--media/libmediaplayerservice/StagefrightRecorder.h1
-rw-r--r--media/libstagefright/AMRWriter.cpp46
-rw-r--r--media/libstagefright/AudioSource.cpp10
-rw-r--r--media/libstagefright/MPEG4Writer.cpp93
-rw-r--r--media/libstagefright/codecs/aacenc/AACEncoder.cpp11
9 files changed, 154 insertions, 23 deletions
diff --git a/include/media/stagefright/AMRWriter.h b/include/media/stagefright/AMRWriter.h
index dd11809..b0eaba4 100644
--- a/include/media/stagefright/AMRWriter.h
+++ b/include/media/stagefright/AMRWriter.h
@@ -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;
diff --git a/include/media/stagefright/MPEG4Writer.h b/include/media/stagefright/MPEG4Writer.h
index 3c85eca..3d90434 100644
--- a/include/media/stagefright/MPEG4Writer.h
+++ b/include/media/stagefright/MPEG4Writer.h
@@ -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();
diff --git a/include/media/stagefright/MediaWriter.h b/include/media/stagefright/MediaWriter.h
index b15f69c..8528203 100644
--- a/include/media/stagefright/MediaWriter.h
+++ b/include/media/stagefright/MediaWriter.h
@@ -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) {
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<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();
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<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,23 +218,26 @@ status_t MPEG4Writer::start() {
mOffset = mMdatOffset;
fseeko(mFile, mMdatOffset, SEEK_SET);
write("\x00\x00\x00\x01mdat????????", 16);
- 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;
- }
+ 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) {
+ (*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<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;
}
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;