summaryrefslogtreecommitdiffstats
path: root/media
diff options
context:
space:
mode:
authorJames Dong <jdong@google.com>2010-08-13 14:16:26 -0700
committerJames Dong <jdong@google.com>2010-08-16 10:38:35 -0700
commitc059860c73678a202bfa33062723e8f82fb779d9 (patch)
tree94b5887059eabda7d8fabe686eba50f5c7963f94 /media
parente259531ce59ab1f31de5a23124b22536f6a5a767 (diff)
downloadframeworks_av-c059860c73678a202bfa33062723e8f82fb779d9.zip
frameworks_av-c059860c73678a202bfa33062723e8f82fb779d9.tar.gz
frameworks_av-c059860c73678a202bfa33062723e8f82fb779d9.tar.bz2
Change the default time scale for audio/video track during recording
and reduce rounding errors in calculating the sample duration - Default time scale for tracks other than audio is set to 90000. - Audio track by default uses the audio sampling rate as the time scale. - Default movie time scale remains to be 1000. - The default time scale values will be overwritten by a user-supplied value if exits. Change-Id: I81b40ed0626ea45e9fd24a89e21a2c5a4a2c3415
Diffstat (limited to 'media')
-rw-r--r--media/libmediaplayerservice/StagefrightRecorder.cpp18
-rw-r--r--media/libstagefright/MPEG4Writer.cpp59
2 files changed, 63 insertions, 14 deletions
diff --git a/media/libmediaplayerservice/StagefrightRecorder.cpp b/media/libmediaplayerservice/StagefrightRecorder.cpp
index 8481d49..94448c1 100644
--- a/media/libmediaplayerservice/StagefrightRecorder.cpp
+++ b/media/libmediaplayerservice/StagefrightRecorder.cpp
@@ -675,7 +675,9 @@ sp<MediaSource> StagefrightRecorder::createAudioSource() {
encMeta->setInt32(kKeyChannelCount, mAudioChannels);
encMeta->setInt32(kKeySampleRate, mSampleRate);
encMeta->setInt32(kKeyBitRate, mAudioBitRate);
- encMeta->setInt32(kKeyTimeScale, mAudioTimeScale);
+ if (mAudioTimeScale > 0) {
+ encMeta->setInt32(kKeyTimeScale, mAudioTimeScale);
+ }
OMXClient client;
CHECK_EQ(client.connect(), OK);
@@ -961,7 +963,9 @@ status_t StagefrightRecorder::setupVideoEncoder(sp<MediaSource> *source) {
enc_meta->setInt32(kKeyStride, stride);
enc_meta->setInt32(kKeySliceHeight, sliceHeight);
enc_meta->setInt32(kKeyColorFormat, colorFormat);
- enc_meta->setInt32(kKeyTimeScale, mVideoTimeScale);
+ if (mVideoTimeScale > 0) {
+ enc_meta->setInt32(kKeyTimeScale, mVideoTimeScale);
+ }
if (mVideoEncoderProfile != -1) {
enc_meta->setInt32(kKeyVideoProfile, mVideoEncoderProfile);
}
@@ -1041,7 +1045,9 @@ status_t StagefrightRecorder::startMPEG4Recording() {
meta->setInt32(kKeyFileType, mOutputFormat);
meta->setInt32(kKeyBitRate, totalBitRate);
meta->setInt32(kKey64BitFileOffset, mUse64BitFileOffset);
- meta->setInt32(kKeyTimeScale, mMovieTimeScale);
+ if (mMovieTimeScale > 0) {
+ meta->setInt32(kKeyTimeScale, mMovieTimeScale);
+ }
if (mTrackEveryTimeDurationUs > 0) {
meta->setInt64(kKeyTrackTimeStatus, mTrackEveryTimeDurationUs);
}
@@ -1117,9 +1123,9 @@ status_t StagefrightRecorder::reset() {
mIFramesIntervalSec = 1;
mAudioSourceNode = 0;
mUse64BitFileOffset = false;
- mMovieTimeScale = 1000;
- mAudioTimeScale = 1000;
- mVideoTimeScale = 1000;
+ mMovieTimeScale = -1;
+ mAudioTimeScale = -1;
+ mVideoTimeScale = -1;
mCameraId = 0;
mVideoEncoderProfile = -1;
mVideoEncoderLevel = -1;
diff --git a/media/libstagefright/MPEG4Writer.cpp b/media/libstagefright/MPEG4Writer.cpp
index 9fe3864..f52ec1a 100644
--- a/media/libstagefright/MPEG4Writer.cpp
+++ b/media/libstagefright/MPEG4Writer.cpp
@@ -168,6 +168,12 @@ private:
void getCodecSpecificDataFromInputFormatIfPossible();
+ // Determine the track time scale
+ // If it is an audio track, try to use the sampling rate as
+ // the time scale; however, if user chooses the overwrite
+ // value, the user-supplied time scale will be used.
+ void setTimeScale();
+
Track(const Track &);
Track &operator=(const Track &);
};
@@ -434,7 +440,7 @@ void MPEG4Writer::stop() {
mMoovBoxBuffer = (uint8_t *) malloc(mEstimatedMoovBoxSize);
mMoovBoxBufferOffset = 0;
CHECK(mMoovBoxBuffer != NULL);
- int32_t duration = (maxDurationUs * mTimeScale) / 1E6;
+ int32_t duration = (maxDurationUs * mTimeScale + 5E5) / 1E6;
beginBox("moov");
@@ -749,10 +755,6 @@ MPEG4Writer::Track::Track(
mReachedEOS(false) {
getCodecSpecificDataFromInputFormatIfPossible();
- if (!mMeta->findInt32(kKeyTimeScale, &mTimeScale)) {
- mTimeScale = 1000;
- }
-
const char *mime;
mMeta->findCString(kKeyMIMEType, &mime);
mIsAvc = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC);
@@ -760,6 +762,28 @@ MPEG4Writer::Track::Track(
mIsMPEG4 = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_MPEG4) ||
!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC);
+ setTimeScale();
+}
+
+void MPEG4Writer::Track::setTimeScale() {
+ LOGV("setTimeScale");
+ // Default time scale
+ mTimeScale = 90000;
+
+ if (mIsAudio) {
+ // Use the sampling rate as the default time scale for audio track.
+ int32_t sampleRate;
+ bool success = mMeta->findInt32(kKeySampleRate, &sampleRate);
+ CHECK(success);
+ mTimeScale = sampleRate;
+ }
+
+ // If someone would like to overwrite the timescale, use user-supplied value.
+ int32_t timeScale;
+ if (mMeta->findInt32(kKeyTimeScale, &timeScale)) {
+ mTimeScale = timeScale;
+ }
+
CHECK(mTimeScale > 0);
}
@@ -1336,6 +1360,8 @@ void MPEG4Writer::Track::threadEntry() {
int32_t nZeroLengthFrames = 0;
int64_t lastTimestampUs = 0; // Previous sample time stamp in ms
int64_t lastDurationUs = 0; // Between the previous two samples in ms
+ int64_t currDurationTicks = 0; // Timescale based ticks
+ int64_t lastDurationTicks = 0; // Timescale based ticks
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;
@@ -1483,7 +1509,16 @@ void MPEG4Writer::Track::threadEntry() {
mSampleSizes.push_back(sampleSize);
++mNumSamples;
if (mNumSamples > 2) {
- if (lastDurationUs != timestampUs - lastTimestampUs) {
+ // We need to use the time scale based ticks, rather than the
+ // timestamp itself to determine whether we have to use a new
+ // stts entry, since we may have rounding errors.
+ // The calculation is intended to reduce the accumulated
+ // rounding errors.
+ currDurationTicks =
+ ((timestampUs * mTimeScale + 500000LL) / 1000000LL -
+ (lastTimestampUs * mTimeScale + 500000LL) / 1000000LL);
+
+ if (currDurationTicks != lastDurationTicks) {
SttsTableEntry sttsEntry(sampleCount, lastDurationUs);
mSttsTableEntries.push_back(sttsEntry);
sampleCount = 1;
@@ -1498,6 +1533,7 @@ void MPEG4Writer::Track::threadEntry() {
previousSampleSize = sampleSize;
}
lastDurationUs = timestampUs - lastTimestampUs;
+ lastDurationTicks = currDurationTicks;
lastTimestampUs = timestampUs;
if (mIsRealTimeRecording && mIsAudio) {
wallClockTimeUs = systemTime() / 1000;
@@ -1774,7 +1810,6 @@ void MPEG4Writer::Track::writeTrackHeader(
LOGV("%s track time scale: %d",
mIsAudio? "Audio": "Video", mTimeScale);
-
time_t now = time(NULL);
int32_t mvhdTimeScale = mOwner->getTimeScale();
int64_t trakDurationUs = getDurationUs();
@@ -2089,10 +2124,18 @@ void MPEG4Writer::Track::writeTrackHeader(
mOwner->beginBox("stts");
mOwner->writeInt32(0); // version=0, flags=0
mOwner->writeInt32(mSttsTableEntries.size());
+ int64_t prevTimestampUs = 0;
for (List<SttsTableEntry>::iterator it = mSttsTableEntries.begin();
it != mSttsTableEntries.end(); ++it) {
mOwner->writeInt32(it->sampleCount);
- int32_t dur = (it->sampleDurationUs * mTimeScale + 5E5) / 1E6;
+
+ // Make sure that we are calculating the sample duration the exactly
+ // same way as we made decision on how to create stts entries.
+ int64_t currTimestampUs = prevTimestampUs + it->sampleDurationUs;
+ int32_t dur = ((currTimestampUs * mTimeScale + 500000LL) / 1000000LL -
+ (prevTimestampUs * mTimeScale + 500000LL) / 1000000LL);
+ prevTimestampUs += (it->sampleCount * it->sampleDurationUs);
+
mOwner->writeInt32(dur);
}
mOwner->endBox(); // stts