summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/media/stagefright/MPEG4Writer.h1
-rw-r--r--media/libmediaplayerservice/StagefrightRecorder.cpp19
-rw-r--r--media/libmediaplayerservice/StagefrightRecorder.h2
-rw-r--r--media/libstagefright/MPEG4Writer.cpp82
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(), &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() {
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);