diff options
-rw-r--r-- | include/media/stagefright/MPEG4Writer.h | 1 | ||||
-rw-r--r-- | media/libmediaplayerservice/StagefrightRecorder.cpp | 19 | ||||
-rw-r--r-- | media/libmediaplayerservice/StagefrightRecorder.h | 2 | ||||
-rw-r--r-- | media/libstagefright/MPEG4Writer.cpp | 82 |
4 files changed, 85 insertions, 19 deletions
diff --git a/include/media/stagefright/MPEG4Writer.h b/include/media/stagefright/MPEG4Writer.h index bb469e5..7bf07eb 100644 --- a/include/media/stagefright/MPEG4Writer.h +++ b/include/media/stagefright/MPEG4Writer.h @@ -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 &); diff --git a/media/libmediaplayerservice/StagefrightRecorder.cpp b/media/libmediaplayerservice/StagefrightRecorder.cpp index 6a25dc5..9da5f01 100644 --- a/media/libmediaplayerservice/StagefrightRecorder.cpp +++ b/media/libmediaplayerservice/StagefrightRecorder.cpp @@ -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(), °rees)) { + 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() { diff --git a/media/libmediaplayerservice/StagefrightRecorder.h b/media/libmediaplayerservice/StagefrightRecorder.h index d11d7e0..36a15a8 100644 --- a/media/libmediaplayerservice/StagefrightRecorder.h +++ b/media/libmediaplayerservice/StagefrightRecorder.h @@ -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); diff --git a/media/libstagefright/MPEG4Writer.cpp b/media/libstagefright/MPEG4Writer.cpp index b3ed845..17a40b0 100644 --- a/media/libstagefright/MPEG4Writer.cpp +++ b/media/libstagefright/MPEG4Writer.cpp @@ -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); |