Merge "Rotation support"

This commit is contained in:
James Dong
2010-11-09 11:58:36 -08:00
committed by Android (Google) Code Review
4 changed files with 85 additions and 19 deletions

View File

@@ -154,6 +154,7 @@ private:
bool exceedsFileDurationLimit();
bool isFileStreamable() const;
void trackProgressStatus(const Track* track, int64_t timeUs, status_t err = OK);
void writeCompositionMatrix(int32_t degrees);
MPEG4Writer(const MPEG4Writer &);
MPEG4Writer &operator=(const MPEG4Writer &);

View File

@@ -345,6 +345,17 @@ status_t StagefrightRecorder::setParamVideoEncodingBitRate(int32_t bitRate) {
return OK;
}
// Always rotate clockwise, and only support 0, 90, 180 and 270 for now.
status_t StagefrightRecorder::setParamVideoRotation(int32_t degrees) {
LOGV("setParamVideoRotation: %d", degrees);
if (degrees < 0 || degrees % 90 != 0) {
LOGE("Unsupported video rotation angle: %d", degrees);
return BAD_VALUE;
}
mRotationDegrees = degrees % 360;
return OK;
}
status_t StagefrightRecorder::setParamMaxFileDurationUs(int64_t timeUs) {
LOGV("setParamMaxFileDurationUs: %lld us", timeUs);
if (timeUs <= 0) {
@@ -599,6 +610,11 @@ status_t StagefrightRecorder::setParameter(
if (safe_strtoi32(value.string(), &video_bitrate)) {
return setParamVideoEncodingBitRate(video_bitrate);
}
} else if (key == "video-param-rotation-angle-degrees") {
int32_t degrees;
if (safe_strtoi32(value.string(), &degrees)) {
return setParamVideoRotation(degrees);
}
} else if (key == "video-param-i-frames-interval") {
int32_t seconds;
if (safe_strtoi32(value.string(), &seconds)) {
@@ -1255,6 +1271,9 @@ void StagefrightRecorder::setupMPEG4MetaData(int64_t startTimeUs, int32_t totalB
if (mTrackEveryTimeDurationUs > 0) {
(*meta)->setInt64(kKeyTrackTimeStatus, mTrackEveryTimeDurationUs);
}
if (mRotationDegrees != 0) {
(*meta)->setInt32(kKeyRotation, mRotationDegrees);
}
}
status_t StagefrightRecorder::startMPEG4Recording() {

View File

@@ -93,6 +93,7 @@ private:
int64_t mMaxFileSizeBytes;
int64_t mMaxFileDurationUs;
int64_t mTrackEveryTimeDurationUs;
int32_t mRotationDegrees; // Clockwise
bool mCaptureTimeLapse;
int64_t mTimeBetweenTimeLapseFrameCaptureUs;
@@ -146,6 +147,7 @@ private:
status_t setParamVideoEncoderLevel(int32_t level);
status_t setParamVideoCameraId(int32_t cameraId);
status_t setParamVideoTimeScale(int32_t timeScale);
status_t setParamVideoRotation(int32_t degrees);
status_t setParamTrackTimeStatus(int64_t timeDurationUs);
status_t setParamInterleaveDuration(int32_t durationUs);
status_t setParam64BitFileOffset(bool use64BitFileOffset);

View File

@@ -202,6 +202,7 @@ private:
// Simple validation on the codec specific data
status_t checkCodecSpecificData() const;
int32_t mRotation;
void updateTrackSizeEstimate();
void addOneStscTableEntry(size_t chunkId, size_t sampleId);
@@ -520,6 +521,59 @@ void MPEG4Writer::stopWriterThread() {
LOGD("Writer thread stopped");
}
/*
* MP4 file standard defines a composition matrix:
* | a b u |
* | c d v |
* | x y w |
*
* the element in the matrix is stored in the following
* order: {a, b, u, c, d, v, x, y, w},
* where a, b, c, d, x, and y is in 16.16 format, while
* u, v and w is in 2.30 format.
*/
void MPEG4Writer::writeCompositionMatrix(int degrees) {
LOGV("writeCompositionMatrix");
uint32_t a = 0x00010000;
uint32_t b = 0;
uint32_t c = 0;
uint32_t d = 0x00010000;
switch (degrees) {
case 0:
break;
case 90:
a = 0;
b = 0x00010000;
c = 0xFFFF0000;
d = 0;
break;
case 180:
a = 0xFFFF0000;
d = 0xFFFF0000;
break;
case 270:
a = 0;
b = 0xFFFF0000;
c = 0x00010000;
d = 0;
break;
default:
CHECK(!"Should never reach this unknown rotation");
break;
}
writeInt32(a); // a
writeInt32(b); // b
writeInt32(0); // u
writeInt32(c); // c
writeInt32(d); // d
writeInt32(0); // v
writeInt32(0); // x
writeInt32(0); // y
writeInt32(0x40000000); // w
}
status_t MPEG4Writer::stop() {
if (mFile == NULL) {
return OK;
@@ -585,15 +639,7 @@ status_t MPEG4Writer::stop() {
writeInt16(0); // reserved
writeInt32(0); // reserved
writeInt32(0); // reserved
writeInt32(0x10000); // matrix
writeInt32(0);
writeInt32(0);
writeInt32(0);
writeInt32(0x10000);
writeInt32(0);
writeInt32(0);
writeInt32(0);
writeInt32(0x40000000);
writeCompositionMatrix(0); // matrix
writeInt32(0); // predefined
writeInt32(0); // predefined
writeInt32(0); // predefined
@@ -886,7 +932,8 @@ MPEG4Writer::Track::Track(
mCodecSpecificData(NULL),
mCodecSpecificDataSize(0),
mGotAllCodecSpecificData(false),
mReachedEOS(false) {
mReachedEOS(false),
mRotation(0) {
getCodecSpecificDataFromInputFormatIfPossible();
const char *mime;
@@ -1179,6 +1226,11 @@ status_t MPEG4Writer::Track::start(MetaData *params) {
startTimeUs = 0;
}
int32_t rotationDegrees;
if (!mIsAudio && params && params->findInt32(kKeyRotation, &rotationDegrees)) {
mRotation = rotationDegrees;
}
mIsRealTimeRecording = true;
{
int32_t isNotRealTime;
@@ -2075,15 +2127,7 @@ void MPEG4Writer::Track::writeTrackHeader(
mOwner->writeInt16(mIsAudio ? 0x100 : 0); // volume
mOwner->writeInt16(0); // reserved
mOwner->writeInt32(0x10000); // matrix
mOwner->writeInt32(0);
mOwner->writeInt32(0);
mOwner->writeInt32(0);
mOwner->writeInt32(0x10000);
mOwner->writeInt32(0);
mOwner->writeInt32(0);
mOwner->writeInt32(0);
mOwner->writeInt32(0x40000000);
mOwner->writeCompositionMatrix(mRotation); // matrix
if (mIsAudio) {
mOwner->writeInt32(0);