Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1653e261 authored by James Dong's avatar James Dong Committed by Android (Google) Code Review
Browse files

Merge "Rotation support" into gingerbread

parents 0467b0ab 65a73f4e
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -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 &);
+1 −0
Original line number Diff line number Diff line
@@ -90,6 +90,7 @@ enum {
    // Track authoring progress status
    // kKeyTrackTimeStatus is used to track progress in elapsed time
    kKeyTrackTimeStatus   = 'tktm',  // int64_t
    kKeyRotationDegree    = 'rdge',  // int32_t (clockwise, in degree)

    kKeyNotRealTime       = 'ntrt',  // bool (int32_t)

+20 −0
Original line number Diff line number Diff line
@@ -340,6 +340,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) {
@@ -532,6 +543,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)) {
@@ -1105,6 +1121,9 @@ status_t StagefrightRecorder::startMPEG4Recording() {
    if (mTrackEveryTimeDurationUs > 0) {
        meta->setInt64(kKeyTrackTimeStatus, mTrackEveryTimeDurationUs);
    }
    if (mRotationDegrees != 0) {
        meta->setInt32(kKeyRotationDegree, mRotationDegrees);
    }
    writer->setListener(mListener);
    mWriter = writer;
    return mWriter->start(meta.get());
@@ -1187,6 +1206,7 @@ status_t StagefrightRecorder::reset() {
    mMaxFileDurationUs = 0;
    mMaxFileSizeBytes = 0;
    mTrackEveryTimeDurationUs = 0;
    mRotationDegrees = 0;
    mEncoderProfiles = MediaProfiles::getInstance();

    mOutputFd = -1;
+2 −0
Original line number Diff line number Diff line
@@ -91,6 +91,7 @@ private:
    int64_t mMaxFileSizeBytes;
    int64_t mMaxFileDurationUs;
    int64_t mTrackEveryTimeDurationUs;
    int32_t mRotationDegrees;  // Clockwise

    String8 mParams;
    int mOutputFd;
@@ -120,6 +121,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);
+62 −19
Original line number Diff line number Diff line
@@ -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);
@@ -519,6 +520,58 @@ void MPEG4Writer::stopWriterThread() {
    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() {
    if (mFile == NULL) {
        return OK;
@@ -584,15 +637,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);
        writeInt32(0);             // predefined
        writeInt32(0);             // predefined
        writeInt32(0);             // predefined
@@ -885,7 +930,8 @@ MPEG4Writer::Track::Track(
      mCodecSpecificData(NULL),
      mCodecSpecificDataSize(0),
      mGotAllCodecSpecificData(false),
      mReachedEOS(false) {
      mReachedEOS(false),
      mRotation(0) {
    getCodecSpecificDataFromInputFormatIfPossible();

    const char *mime;
@@ -1178,6 +1224,11 @@ status_t MPEG4Writer::Track::start(MetaData *params) {
        startTimeUs = 0;
    }

    int32_t rotationDegrees;
    if (!mIsAudio && params && params->findInt32(kKeyRotationDegree, &rotationDegrees)) {
        mRotation = rotationDegrees;
    }

    mIsRealTimeRecording = true;
    {
        int32_t isNotRealTime;
@@ -2071,15 +2122,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);

        if (mIsAudio) {
            mOwner->writeInt32(0);