diff options
-rw-r--r-- | include/media/stagefright/AMRWriter.h | 4 | ||||
-rw-r--r-- | include/media/stagefright/MPEG4Writer.h | 2 | ||||
-rw-r--r-- | include/media/stagefright/MediaWriter.h | 16 | ||||
-rw-r--r-- | media/libmediaplayerservice/StagefrightRecorder.cpp | 15 | ||||
-rw-r--r-- | media/libstagefright/AMRWriter.cpp | 36 | ||||
-rw-r--r-- | media/libstagefright/MPEG4Writer.cpp | 52 |
6 files changed, 124 insertions, 1 deletions
diff --git a/include/media/stagefright/AMRWriter.h b/include/media/stagefright/AMRWriter.h index 34f3c4a..dd11809 100644 --- a/include/media/stagefright/AMRWriter.h +++ b/include/media/stagefright/AMRWriter.h @@ -49,9 +49,13 @@ private: volatile bool mDone; volatile bool mReachedEOS; pthread_t mThread; + int64_t mEstimatedSizeBytes; + int64_t mEstimatedDurationUs; static void *ThreadWrapper(void *); void threadFunc(); + bool exceedsFileSizeLimit(); + bool exceedsFileDurationLimit(); AMRWriter(const AMRWriter &); AMRWriter &operator=(const AMRWriter &); diff --git a/include/media/stagefright/MPEG4Writer.h b/include/media/stagefright/MPEG4Writer.h index 6064fc4..60f30f5 100644 --- a/include/media/stagefright/MPEG4Writer.h +++ b/include/media/stagefright/MPEG4Writer.h @@ -82,6 +82,8 @@ private: off_t addLengthPrefixedSample_l(MediaBuffer *buffer); inline size_t write(const void *ptr, size_t size, size_t nmemb, FILE* stream); + bool exceedsFileSizeLimit(); + bool exceedsFileDurationLimit(); MPEG4Writer(const MPEG4Writer &); MPEG4Writer &operator=(const MPEG4Writer &); diff --git a/include/media/stagefright/MediaWriter.h b/include/media/stagefright/MediaWriter.h index b8232c6..b15f69c 100644 --- a/include/media/stagefright/MediaWriter.h +++ b/include/media/stagefright/MediaWriter.h @@ -19,6 +19,7 @@ #define MEDIA_WRITER_H_ #include <utils/RefBase.h> +#include <media/IMediaPlayerClient.h> namespace android { @@ -31,10 +32,23 @@ struct MediaWriter : public RefBase { virtual bool reachedEOS() = 0; virtual status_t start() = 0; virtual void stop() = 0; + virtual void setMaxFileSize(int64_t bytes) { mMaxFileSizeLimitBytes = bytes; } + virtual void setMaxFileDuration(int64_t durationUs) { mMaxFileDurationLimitUs = durationUs; } + virtual void setListener(const sp<IMediaPlayerClient>& listener) { + mListener = listener; + } protected: virtual ~MediaWriter() {} - + int64_t mMaxFileSizeLimitBytes; + int64_t mMaxFileDurationLimitUs; + sp<IMediaPlayerClient> mListener; + + void notify(int msg, int ext1, int ext2) { + if (mListener != NULL) { + mListener->notify(msg, ext1, ext2); + } + } private: MediaWriter(const MediaWriter &); MediaWriter &operator=(const MediaWriter &); diff --git a/media/libmediaplayerservice/StagefrightRecorder.cpp b/media/libmediaplayerservice/StagefrightRecorder.cpp index e41a716..cb08100 100644 --- a/media/libmediaplayerservice/StagefrightRecorder.cpp +++ b/media/libmediaplayerservice/StagefrightRecorder.cpp @@ -523,6 +523,14 @@ status_t StagefrightRecorder::startAMRRecording() { CHECK(mOutputFd >= 0); mWriter = new AMRWriter(dup(mOutputFd)); mWriter->addSource(audioEncoder); + + if (mMaxFileDurationUs != 0) { + mWriter->setMaxFileDuration(mMaxFileDurationUs); + } + if (mMaxFileSizeBytes != 0) { + mWriter->setMaxFileSize(mMaxFileSizeBytes); + } + mWriter->setListener(mListener); mWriter->start(); return OK; @@ -641,6 +649,13 @@ status_t StagefrightRecorder::startMPEG4Recording() { writer->setInterleaveDuration(mInterleaveDurationUs); } + if (mMaxFileDurationUs != 0) { + mWriter->setMaxFileDuration(mMaxFileDurationUs); + } + if (mMaxFileSizeBytes != 0) { + mWriter->setMaxFileSize(mMaxFileSizeBytes); + } + mWriter->setListener(mListener); mWriter->start(); return OK; } diff --git a/media/libstagefright/AMRWriter.cpp b/media/libstagefright/AMRWriter.cpp index 73ea56d..0d54235 100644 --- a/media/libstagefright/AMRWriter.cpp +++ b/media/libstagefright/AMRWriter.cpp @@ -22,6 +22,7 @@ #include <media/stagefright/MediaErrors.h> #include <media/stagefright/MediaSource.h> #include <media/stagefright/MetaData.h> +#include <media/mediarecorder.h> namespace android { @@ -137,6 +138,20 @@ void AMRWriter::stop() { mStarted = false; } +bool AMRWriter::exceedsFileSizeLimit() { + if (mMaxFileSizeLimitBytes == 0) { + return false; + } + return mEstimatedSizeBytes >= mMaxFileSizeLimitBytes; +} + +bool AMRWriter::exceedsFileDurationLimit() { + if (mMaxFileDurationLimitUs == 0) { + return false; + } + return mEstimatedDurationUs >= mMaxFileDurationLimitUs; +} + // static void *AMRWriter::ThreadWrapper(void *me) { static_cast<AMRWriter *>(me)->threadFunc(); @@ -145,6 +160,8 @@ void *AMRWriter::ThreadWrapper(void *me) { } void AMRWriter::threadFunc() { + mEstimatedDurationUs = 0; + mEstimatedSizeBytes = 0; while (!mDone) { MediaBuffer *buffer; status_t err = mSource->read(&buffer); @@ -153,6 +170,25 @@ void AMRWriter::threadFunc() { break; } + mEstimatedSizeBytes += buffer->range_length(); + if (exceedsFileSizeLimit()) { + buffer->release(); + buffer = NULL; + notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED, 0); + break; + } + + int64_t timestampUs; + CHECK(buffer->meta_data()->findInt64(kKeyTime, ×tampUs)); + if (timestampUs > mEstimatedDurationUs) { + mEstimatedDurationUs = timestampUs; + } + if (exceedsFileDurationLimit()) { + buffer->release(); + buffer = NULL; + notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_DURATION_REACHED, 0); + break; + } ssize_t n = fwrite( (const uint8_t *)buffer->data() + buffer->range_offset(), 1, diff --git a/media/libstagefright/MPEG4Writer.cpp b/media/libstagefright/MPEG4Writer.cpp index 19cccf7..044460c 100644 --- a/media/libstagefright/MPEG4Writer.cpp +++ b/media/libstagefright/MPEG4Writer.cpp @@ -31,6 +31,7 @@ #include <media/stagefright/MediaErrors.h> #include <media/stagefright/MediaSource.h> #include <media/stagefright/Utils.h> +#include <media/mediarecorder.h> namespace android { @@ -44,6 +45,7 @@ public: bool reachedEOS(); int64_t getDurationUs() const; + int64_t getEstimatedTrackSizeBytes() const; void writeTrackHeader(int32_t trackID); private: @@ -52,6 +54,7 @@ private: sp<MediaSource> mSource; volatile bool mDone; int64_t mMaxTimeStampUs; + int64_t mEstimatedTrackSizeBytes; pthread_t mThread; @@ -455,6 +458,35 @@ void MPEG4Writer::write(const void *data, size_t size) { write(data, 1, size, mFile); } +bool MPEG4Writer::exceedsFileSizeLimit() { + // No limit + if (mMaxFileSizeLimitBytes == 0) { + return false; + } + + int64_t nTotalBytesEstimate = mEstimatedMoovBoxSize; + for (List<Track *>::iterator it = mTracks.begin(); + it != mTracks.end(); ++it) { + nTotalBytesEstimate += (*it)->getEstimatedTrackSizeBytes(); + } + return (nTotalBytesEstimate >= mMaxFileSizeLimitBytes); +} + +bool MPEG4Writer::exceedsFileDurationLimit() { + // No limit + if (mMaxFileDurationLimitUs == 0) { + return false; + } + + for (List<Track *>::iterator it = mTracks.begin(); + it != mTracks.end(); ++it) { + if ((*it)->getDurationUs() >= mMaxFileDurationLimitUs) { + return true; + } + } + return false; +} + bool MPEG4Writer::reachedEOS() { bool allDone = true; for (List<Track *>::iterator it = mTracks.begin(); @@ -656,6 +688,7 @@ void MPEG4Writer::Track::threadEntry() { int32_t sampleCount = 1; // Sample count in the current stts table entry uint32_t previousSampleSize = 0; // Size of the previous sample + mEstimatedTrackSizeBytes = 0; MediaBuffer *buffer; while (!mDone && mSource->read(&buffer) == OK) { if (buffer->range_length() == 0) { @@ -784,6 +817,21 @@ void MPEG4Writer::Track::threadEntry() { #endif : buffer->range_length(); + // Max file size or duration handling + mEstimatedTrackSizeBytes += info.size; + if (mOwner->exceedsFileSizeLimit()) { + buffer->release(); + buffer = NULL; + mOwner->notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED, 0); + break; + } + if (mOwner->exceedsFileDurationLimit()) { + buffer->release(); + buffer = NULL; + mOwner->notify(MEDIA_RECORDER_EVENT_INFO, MEDIA_RECORDER_INFO_MAX_DURATION_REACHED, 0); + break; + } + bool is_audio = !strncasecmp(mime, "audio/", 6); int64_t timestampUs; @@ -904,6 +952,10 @@ int64_t MPEG4Writer::Track::getDurationUs() const { return mMaxTimeStampUs; } +int64_t MPEG4Writer::Track::getEstimatedTrackSizeBytes() const { + return mEstimatedTrackSizeBytes; +} + void MPEG4Writer::Track::writeTrackHeader(int32_t trackID) { const char *mime; bool success = mMeta->findCString(kKeyMIMEType, &mime); |