am eff30e3d: Change the default time scale for audio/video track during recording and reduce rounding errors in calculating the sample duration
Merge commit 'eff30e3d1b005fd0696390d1dd47ec4ff0c52784' into gingerbread-plus-aosp * commit 'eff30e3d1b005fd0696390d1dd47ec4ff0c52784': Change the default time scale for audio/video track during recording
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user