am 1824486e: Handle recording file size and/or duration limit

This commit is contained in:
James Dong
2010-05-14 10:51:35 -07:00
committed by Android Git Automerger
6 changed files with 123 additions and 0 deletions

View File

@@ -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 &);

View File

@@ -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 &);

View File

@@ -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 &);

View File

@@ -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;
}

View File

@@ -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, &timestampUs));
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,

View File

@@ -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);