Merge "Rotation support" into gingerbread

This commit is contained in:
James Dong
2010-11-05 16:58:51 -07:00
committed by Android (Google) Code Review
5 changed files with 86 additions and 19 deletions

View File

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

View File

@ -90,6 +90,7 @@ enum {
// Track authoring progress status // Track authoring progress status
// kKeyTrackTimeStatus is used to track progress in elapsed time // kKeyTrackTimeStatus is used to track progress in elapsed time
kKeyTrackTimeStatus = 'tktm', // int64_t kKeyTrackTimeStatus = 'tktm', // int64_t
kKeyRotationDegree = 'rdge', // int32_t (clockwise, in degree)
kKeyNotRealTime = 'ntrt', // bool (int32_t) kKeyNotRealTime = 'ntrt', // bool (int32_t)

View File

@ -340,6 +340,17 @@ status_t StagefrightRecorder::setParamVideoEncodingBitRate(int32_t bitRate) {
return OK; 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) { status_t StagefrightRecorder::setParamMaxFileDurationUs(int64_t timeUs) {
LOGV("setParamMaxFileDurationUs: %lld us", timeUs); LOGV("setParamMaxFileDurationUs: %lld us", timeUs);
if (timeUs <= 0) { if (timeUs <= 0) {
@ -532,6 +543,11 @@ status_t StagefrightRecorder::setParameter(
if (safe_strtoi32(value.string(), &video_bitrate)) { if (safe_strtoi32(value.string(), &video_bitrate)) {
return setParamVideoEncodingBitRate(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") { } else if (key == "video-param-i-frames-interval") {
int32_t seconds; int32_t seconds;
if (safe_strtoi32(value.string(), &seconds)) { if (safe_strtoi32(value.string(), &seconds)) {
@ -1105,6 +1121,9 @@ status_t StagefrightRecorder::startMPEG4Recording() {
if (mTrackEveryTimeDurationUs > 0) { if (mTrackEveryTimeDurationUs > 0) {
meta->setInt64(kKeyTrackTimeStatus, mTrackEveryTimeDurationUs); meta->setInt64(kKeyTrackTimeStatus, mTrackEveryTimeDurationUs);
} }
if (mRotationDegrees != 0) {
meta->setInt32(kKeyRotationDegree, mRotationDegrees);
}
writer->setListener(mListener); writer->setListener(mListener);
mWriter = writer; mWriter = writer;
return mWriter->start(meta.get()); return mWriter->start(meta.get());
@ -1187,6 +1206,7 @@ status_t StagefrightRecorder::reset() {
mMaxFileDurationUs = 0; mMaxFileDurationUs = 0;
mMaxFileSizeBytes = 0; mMaxFileSizeBytes = 0;
mTrackEveryTimeDurationUs = 0; mTrackEveryTimeDurationUs = 0;
mRotationDegrees = 0;
mEncoderProfiles = MediaProfiles::getInstance(); mEncoderProfiles = MediaProfiles::getInstance();
mOutputFd = -1; mOutputFd = -1;

View File

@ -91,6 +91,7 @@ private:
int64_t mMaxFileSizeBytes; int64_t mMaxFileSizeBytes;
int64_t mMaxFileDurationUs; int64_t mMaxFileDurationUs;
int64_t mTrackEveryTimeDurationUs; int64_t mTrackEveryTimeDurationUs;
int32_t mRotationDegrees; // Clockwise
String8 mParams; String8 mParams;
int mOutputFd; int mOutputFd;
@ -120,6 +121,7 @@ private:
status_t setParamVideoEncoderLevel(int32_t level); status_t setParamVideoEncoderLevel(int32_t level);
status_t setParamVideoCameraId(int32_t cameraId); status_t setParamVideoCameraId(int32_t cameraId);
status_t setParamVideoTimeScale(int32_t timeScale); status_t setParamVideoTimeScale(int32_t timeScale);
status_t setParamVideoRotation(int32_t degrees);
status_t setParamTrackTimeStatus(int64_t timeDurationUs); status_t setParamTrackTimeStatus(int64_t timeDurationUs);
status_t setParamInterleaveDuration(int32_t durationUs); status_t setParamInterleaveDuration(int32_t durationUs);
status_t setParam64BitFileOffset(bool use64BitFileOffset); status_t setParam64BitFileOffset(bool use64BitFileOffset);

View File

@ -202,6 +202,7 @@ private:
// Simple validation on the codec specific data // Simple validation on the codec specific data
status_t checkCodecSpecificData() const; status_t checkCodecSpecificData() const;
int32_t mRotation;
void updateTrackSizeEstimate(); void updateTrackSizeEstimate();
void addOneStscTableEntry(size_t chunkId, size_t sampleId); void addOneStscTableEntry(size_t chunkId, size_t sampleId);
@ -519,6 +520,58 @@ void MPEG4Writer::stopWriterThread() {
pthread_join(mThread, &dummy); pthread_join(mThread, &dummy);
} }
/*
* 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() { status_t MPEG4Writer::stop() {
if (mFile == NULL) { if (mFile == NULL) {
return OK; return OK;
@ -584,15 +637,7 @@ status_t MPEG4Writer::stop() {
writeInt16(0); // reserved writeInt16(0); // reserved
writeInt32(0); // reserved writeInt32(0); // reserved
writeInt32(0); // reserved writeInt32(0); // reserved
writeInt32(0x10000); // matrix writeCompositionMatrix(0);
writeInt32(0);
writeInt32(0);
writeInt32(0);
writeInt32(0x10000);
writeInt32(0);
writeInt32(0);
writeInt32(0);
writeInt32(0x40000000);
writeInt32(0); // predefined writeInt32(0); // predefined
writeInt32(0); // predefined writeInt32(0); // predefined
writeInt32(0); // predefined writeInt32(0); // predefined
@ -885,7 +930,8 @@ MPEG4Writer::Track::Track(
mCodecSpecificData(NULL), mCodecSpecificData(NULL),
mCodecSpecificDataSize(0), mCodecSpecificDataSize(0),
mGotAllCodecSpecificData(false), mGotAllCodecSpecificData(false),
mReachedEOS(false) { mReachedEOS(false),
mRotation(0) {
getCodecSpecificDataFromInputFormatIfPossible(); getCodecSpecificDataFromInputFormatIfPossible();
const char *mime; const char *mime;
@ -1178,6 +1224,11 @@ status_t MPEG4Writer::Track::start(MetaData *params) {
startTimeUs = 0; startTimeUs = 0;
} }
int32_t rotationDegrees;
if (!mIsAudio && params && params->findInt32(kKeyRotationDegree, &rotationDegrees)) {
mRotation = rotationDegrees;
}
mIsRealTimeRecording = true; mIsRealTimeRecording = true;
{ {
int32_t isNotRealTime; int32_t isNotRealTime;
@ -2071,15 +2122,7 @@ void MPEG4Writer::Track::writeTrackHeader(
mOwner->writeInt16(mIsAudio ? 0x100 : 0); // volume mOwner->writeInt16(mIsAudio ? 0x100 : 0); // volume
mOwner->writeInt16(0); // reserved mOwner->writeInt16(0); // reserved
mOwner->writeInt32(0x10000); // matrix mOwner->writeCompositionMatrix(mRotation);
mOwner->writeInt32(0);
mOwner->writeInt32(0);
mOwner->writeInt32(0);
mOwner->writeInt32(0x10000);
mOwner->writeInt32(0);
mOwner->writeInt32(0);
mOwner->writeInt32(0);
mOwner->writeInt32(0x40000000);
if (mIsAudio) { if (mIsAudio) {
mOwner->writeInt32(0); mOwner->writeInt32(0);