am 1824486e: Handle recording file size and/or duration limit
This commit is contained in:
@@ -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 &);
|
||||
|
||||
@@ -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 &);
|
||||
|
||||
@@ -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 &);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user