summaryrefslogtreecommitdiffstats
path: root/media/libstagefright/MPEG4Writer.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'media/libstagefright/MPEG4Writer.cpp')
-rw-r--r--media/libstagefright/MPEG4Writer.cpp92
1 files changed, 69 insertions, 23 deletions
diff --git a/media/libstagefright/MPEG4Writer.cpp b/media/libstagefright/MPEG4Writer.cpp
index 58a4487..24e53b3 100644
--- a/media/libstagefright/MPEG4Writer.cpp
+++ b/media/libstagefright/MPEG4Writer.cpp
@@ -41,6 +41,12 @@
#include "include/ESDS.h"
+#define WARN_UNLESS(condition, message, ...) \
+( (CONDITION(condition)) ? false : ({ \
+ ALOGW("Condition %s failed " message, #condition, ##__VA_ARGS__); \
+ true; \
+}))
+
namespace android {
static const int64_t kMinStreamableFileSizeInBytes = 5 * 1024 * 1024;
@@ -975,13 +981,16 @@ void MPEG4Writer::writeFtypBox(MetaData *param) {
if (param && param->findInt32(kKeyFileType, &fileType) &&
fileType != OUTPUT_FORMAT_MPEG_4) {
writeFourcc("3gp4");
+ writeInt32(0);
+ writeFourcc("isom");
+ writeFourcc("3gp4");
} else {
+ writeFourcc("mp42");
+ writeInt32(0);
writeFourcc("isom");
+ writeFourcc("mp42");
}
- writeInt32(0);
- writeFourcc("isom");
- writeFourcc("3gp4");
endBox();
}
@@ -1763,7 +1772,7 @@ status_t MPEG4Writer::Track::pause() {
}
status_t MPEG4Writer::Track::stop() {
- ALOGD("Stopping %s track", mIsAudio? "Audio": "Video");
+ ALOGD("%s track stopping", mIsAudio? "Audio": "Video");
if (!mStarted) {
ALOGE("Stop() called but track is not started");
return ERROR_END_OF_STREAM;
@@ -1774,19 +1783,14 @@ status_t MPEG4Writer::Track::stop() {
}
mDone = true;
+ ALOGD("%s track source stopping", mIsAudio? "Audio": "Video");
+ mSource->stop();
+ ALOGD("%s track source stopped", mIsAudio? "Audio": "Video");
+
void *dummy;
pthread_join(mThread, &dummy);
-
status_t err = static_cast<status_t>(reinterpret_cast<uintptr_t>(dummy));
- ALOGD("Stopping %s track source", mIsAudio? "Audio": "Video");
- {
- status_t status = mSource->stop();
- if (err == OK && status != OK && status != ERROR_END_OF_STREAM) {
- err = status;
- }
- }
-
ALOGD("%s track stopped", mIsAudio? "Audio": "Video");
return err;
}
@@ -2100,6 +2104,7 @@ status_t MPEG4Writer::Track::threadEntry() {
status_t err = OK;
MediaBuffer *buffer;
+ const char *trackName = mIsAudio ? "Audio" : "Video";
while (!mDone && (err = mSource->read(&buffer)) == OK) {
if (buffer->range_length() == 0) {
buffer->release();
@@ -2195,15 +2200,27 @@ status_t MPEG4Writer::Track::threadEntry() {
if (mResumed) {
int64_t durExcludingEarlierPausesUs = timestampUs - previousPausedDurationUs;
- CHECK_GE(durExcludingEarlierPausesUs, 0ll);
+ if (WARN_UNLESS(durExcludingEarlierPausesUs >= 0ll, "for %s track", trackName)) {
+ copy->release();
+ return ERROR_MALFORMED;
+ }
+
int64_t pausedDurationUs = durExcludingEarlierPausesUs - mTrackDurationUs;
- CHECK_GE(pausedDurationUs, lastDurationUs);
+ if (WARN_UNLESS(pausedDurationUs >= lastDurationUs, "for %s track", trackName)) {
+ copy->release();
+ return ERROR_MALFORMED;
+ }
+
previousPausedDurationUs += pausedDurationUs - lastDurationUs;
mResumed = false;
}
timestampUs -= previousPausedDurationUs;
- CHECK_GE(timestampUs, 0ll);
+ if (WARN_UNLESS(timestampUs >= 0ll, "for %s track", trackName)) {
+ copy->release();
+ return ERROR_MALFORMED;
+ }
+
if (!mIsAudio) {
/*
* Composition time: timestampUs
@@ -2215,7 +2232,11 @@ status_t MPEG4Writer::Track::threadEntry() {
decodingTimeUs -= previousPausedDurationUs;
cttsOffsetTimeUs =
timestampUs + kMaxCttsOffsetTimeUs - decodingTimeUs;
- CHECK_GE(cttsOffsetTimeUs, 0ll);
+ if (WARN_UNLESS(cttsOffsetTimeUs >= 0ll, "for %s track", trackName)) {
+ copy->release();
+ return ERROR_MALFORMED;
+ }
+
timestampUs = decodingTimeUs;
ALOGV("decoding time: %lld and ctts offset time: %lld",
timestampUs, cttsOffsetTimeUs);
@@ -2223,7 +2244,11 @@ status_t MPEG4Writer::Track::threadEntry() {
// Update ctts box table if necessary
currCttsOffsetTimeTicks =
(cttsOffsetTimeUs * mTimeScale + 500000LL) / 1000000LL;
- CHECK_LE(currCttsOffsetTimeTicks, 0x0FFFFFFFFLL);
+ if (WARN_UNLESS(currCttsOffsetTimeTicks <= 0x0FFFFFFFFLL, "for %s track", trackName)) {
+ copy->release();
+ return ERROR_MALFORMED;
+ }
+
if (mStszTableEntries->count() == 0) {
// Force the first ctts table entry to have one single entry
// so that we can do adjustment for the initial track start
@@ -2261,9 +2286,13 @@ status_t MPEG4Writer::Track::threadEntry() {
}
}
- CHECK_GE(timestampUs, 0ll);
+ if (WARN_UNLESS(timestampUs >= 0ll, "for %s track", trackName)) {
+ copy->release();
+ return ERROR_MALFORMED;
+ }
+
ALOGV("%s media time stamp: %lld and previous paused duration %lld",
- mIsAudio? "Audio": "Video", timestampUs, previousPausedDurationUs);
+ trackName, timestampUs, previousPausedDurationUs);
if (timestampUs > mTrackDurationUs) {
mTrackDurationUs = timestampUs;
}
@@ -2278,10 +2307,27 @@ status_t MPEG4Writer::Track::threadEntry() {
(lastTimestampUs * mTimeScale + 500000LL) / 1000000LL);
if (currDurationTicks < 0ll) {
ALOGE("timestampUs %lld < lastTimestampUs %lld for %s track",
- timestampUs, lastTimestampUs, mIsAudio? "Audio": "Video");
+ timestampUs, lastTimestampUs, trackName);
+ copy->release();
return UNKNOWN_ERROR;
}
+ // if the duration is different for this sample, see if it is close enough to the previous
+ // duration that we can fudge it and use the same value, to avoid filling the stts table
+ // with lots of near-identical entries.
+ // "close enough" here means that the current duration needs to be adjusted by less
+ // than 0.1 milliseconds
+ if (lastDurationTicks && (currDurationTicks != lastDurationTicks)) {
+ int64_t deltaUs = ((lastDurationTicks - currDurationTicks) * 1000000LL
+ + (mTimeScale / 2)) / mTimeScale;
+ if (deltaUs > -100 && deltaUs < 100) {
+ // use previous ticks, and adjust timestamp as if it was actually that number
+ // of ticks
+ currDurationTicks = lastDurationTicks;
+ timestampUs += deltaUs;
+ }
+ }
+
mStszTableEntries->add(htonl(sampleSize));
if (mStszTableEntries->count() > 2) {
@@ -2302,7 +2348,7 @@ status_t MPEG4Writer::Track::threadEntry() {
previousSampleSize = sampleSize;
}
ALOGV("%s timestampUs/lastTimestampUs: %lld/%lld",
- mIsAudio? "Audio": "Video", timestampUs, lastTimestampUs);
+ trackName, timestampUs, lastTimestampUs);
lastDurationUs = timestampUs - lastTimestampUs;
lastDurationTicks = currDurationTicks;
lastTimestampUs = timestampUs;
@@ -2407,7 +2453,7 @@ status_t MPEG4Writer::Track::threadEntry() {
sendTrackSummary(hasMultipleTracks);
ALOGI("Received total/0-length (%d/%d) buffers and encoded %d frames. - %s",
- count, nZeroLengthFrames, mStszTableEntries->count(), mIsAudio? "audio": "video");
+ count, nZeroLengthFrames, mStszTableEntries->count(), trackName);
if (mIsAudio) {
ALOGI("Audio track drift time: %lld us", mOwner->getDriftTimeUs());
}