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

Commit 66b8994e authored by Andreas Huber's avatar Andreas Huber Committed by Android (Google) Code Review
Browse files

Merge "Support post-decode video rotation."

parents 3ee66f7b 940c866c
Loading
Loading
Loading
Loading
+54 −10
Original line number Diff line number Diff line
@@ -84,11 +84,13 @@ struct AwesomeLocalRenderer : public AwesomeRenderer {
            OMX_COLOR_FORMATTYPE colorFormat,
            const sp<Surface> &surface,
            size_t displayWidth, size_t displayHeight,
            size_t decodedWidth, size_t decodedHeight)
            size_t decodedWidth, size_t decodedHeight,
            int32_t rotationDegrees)
        : mTarget(NULL) {
            init(colorFormat, surface,
                 displayWidth, displayHeight,
                 decodedWidth, decodedHeight);
                 decodedWidth, decodedHeight,
                 rotationDegrees);
    }

    virtual void render(MediaBuffer *buffer) {
@@ -113,7 +115,8 @@ private:
            OMX_COLOR_FORMATTYPE colorFormat,
            const sp<Surface> &surface,
            size_t displayWidth, size_t displayHeight,
            size_t decodedWidth, size_t decodedHeight);
            size_t decodedWidth, size_t decodedHeight,
            int32_t rotationDegrees);

    AwesomeLocalRenderer(const AwesomeLocalRenderer &);
    AwesomeLocalRenderer &operator=(const AwesomeLocalRenderer &);;
@@ -123,15 +126,19 @@ void AwesomeLocalRenderer::init(
        OMX_COLOR_FORMATTYPE colorFormat,
        const sp<Surface> &surface,
        size_t displayWidth, size_t displayHeight,
        size_t decodedWidth, size_t decodedHeight) {
        size_t decodedWidth, size_t decodedHeight,
        int32_t rotationDegrees) {
    mTarget = new SoftwareRenderer(
            colorFormat, surface, displayWidth, displayHeight,
            decodedWidth, decodedHeight);
            decodedWidth, decodedHeight, rotationDegrees);
}

struct AwesomeNativeWindowRenderer : public AwesomeRenderer {
    AwesomeNativeWindowRenderer(const sp<ANativeWindow> &nativeWindow)
    AwesomeNativeWindowRenderer(
            const sp<ANativeWindow> &nativeWindow,
            int32_t rotationDegrees)
        : mNativeWindow(nativeWindow) {
        applyRotation(rotationDegrees);
    }

    virtual void render(MediaBuffer *buffer) {
@@ -153,6 +160,22 @@ protected:
private:
    sp<ANativeWindow> mNativeWindow;

    void applyRotation(int32_t rotationDegrees) {
        uint32_t transform;
        switch (rotationDegrees) {
            case 0: transform = 0; break;
            case 90: transform = HAL_TRANSFORM_ROT_90; break;
            case 180: transform = HAL_TRANSFORM_ROT_180; break;
            case 270: transform = HAL_TRANSFORM_ROT_270; break;
            default: transform = 0; break;
        }

        if (transform) {
            CHECK_EQ(0, native_window_set_buffers_transform(
                        mNativeWindow.get(), transform));
        }
    }

    AwesomeNativeWindowRenderer(const AwesomeNativeWindowRenderer &);
    AwesomeNativeWindowRenderer &operator=(
            const AwesomeNativeWindowRenderer &);
@@ -796,7 +819,19 @@ void AwesomePlayer::notifyVideoSize_l() {
    CHECK(meta->findInt32(kKeyWidth, &decodedWidth));
    CHECK(meta->findInt32(kKeyHeight, &decodedHeight));

    notifyListener_l(MEDIA_SET_VIDEO_SIZE, decodedWidth, decodedHeight);
    int32_t rotationDegrees;
    if (!mVideoTrack->getFormat()->findInt32(
                kKeyRotation, &rotationDegrees)) {
        rotationDegrees = 0;
    }

    if (rotationDegrees == 90 || rotationDegrees == 270) {
        notifyListener_l(
                MEDIA_SET_VIDEO_SIZE, decodedHeight, decodedWidth);
    } else {
        notifyListener_l(
                MEDIA_SET_VIDEO_SIZE, decodedWidth, decodedHeight);
    }
}

void AwesomePlayer::initRenderer_l() {
@@ -814,6 +849,12 @@ void AwesomePlayer::initRenderer_l() {
    CHECK(meta->findInt32(kKeyWidth, &decodedWidth));
    CHECK(meta->findInt32(kKeyHeight, &decodedHeight));

    int32_t rotationDegrees;
    if (!mVideoTrack->getFormat()->findInt32(
                kKeyRotation, &rotationDegrees)) {
        rotationDegrees = 0;
    }

    mVideoRenderer.clear();

    // Must ensure that mVideoRenderer's destructor is actually executed
@@ -824,7 +865,8 @@ void AwesomePlayer::initRenderer_l() {
        // Hardware decoders avoid the CPU color conversion by decoding
        // directly to ANativeBuffers, so we must use a renderer that
        // just pushes those buffers to the ANativeWindow.
        mVideoRenderer = new AwesomeNativeWindowRenderer(mSurface);
        mVideoRenderer =
            new AwesomeNativeWindowRenderer(mSurface, rotationDegrees);
    } else {
        // Other decoders are instantiated locally and as a consequence
        // allocate their buffers in local address space.  This renderer
@@ -834,7 +876,8 @@ void AwesomePlayer::initRenderer_l() {
            (OMX_COLOR_FORMATTYPE)format,
            mSurface,
            mVideoWidth, mVideoHeight,
            decodedWidth, decodedHeight);
            decodedWidth, decodedHeight,
            rotationDegrees);
    }
}

@@ -1819,7 +1862,8 @@ status_t AwesomePlayer::resume() {
                    state->mVideoWidth,
                    state->mVideoHeight,
                    state->mDecodedWidth,
                    state->mDecodedHeight);
                    state->mDecodedHeight,
                    0);

        mVideoRendererIsPreview = true;

+94 −51
Original line number Diff line number Diff line
@@ -27,11 +27,11 @@
#include <stdlib.h>
#include <string.h>

#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/DataSource.h>
#include "include/ESDS.h"
#include <media/stagefright/MediaBuffer.h>
#include <media/stagefright/MediaBufferGroup.h>
#include <media/stagefright/MediaDebug.h>
#include <media/stagefright/MediaDefs.h>
#include <media/stagefright/MediaSource.h>
#include <media/stagefright/MetaData.h>
@@ -766,55 +766,11 @@ status_t MPEG4Extractor::parseChunk(off_t *offset, int depth) {

        case FOURCC('t', 'k', 'h', 'd'):
        {
            if (chunk_data_size < 4) {
                return ERROR_MALFORMED;
            }

            uint8_t version;
            if (mDataSource->readAt(data_offset, &version, 1) < 1) {
                return ERROR_IO;
            }

            uint64_t ctime, mtime, duration;
            int32_t id;
            uint32_t width, height;

            if (version == 1) {
                if (chunk_data_size != 36 + 60) {
                    return ERROR_MALFORMED;
                }

                uint8_t buffer[36 + 60];
                if (mDataSource->readAt(
                            data_offset, buffer, sizeof(buffer)) < (ssize_t)sizeof(buffer)) {
                    return ERROR_IO;
                }

                ctime = U64_AT(&buffer[4]);
                mtime = U64_AT(&buffer[12]);
                id = U32_AT(&buffer[20]);
                duration = U64_AT(&buffer[28]);
                width = U32_AT(&buffer[88]);
                height = U32_AT(&buffer[92]);
            } else if (version == 0) {
                if (chunk_data_size != 24 + 60) {
                    return ERROR_MALFORMED;
                }

                uint8_t buffer[24 + 60];
                if (mDataSource->readAt(
                            data_offset, buffer, sizeof(buffer)) < (ssize_t)sizeof(buffer)) {
                    return ERROR_IO;
                }
                ctime = U32_AT(&buffer[4]);
                mtime = U32_AT(&buffer[8]);
                id = U32_AT(&buffer[12]);
                duration = U32_AT(&buffer[20]);
                width = U32_AT(&buffer[76]);
                height = U32_AT(&buffer[80]);
            status_t err;
            if ((err = parseTrackHeader(data_offset, chunk_data_size)) != OK) {
                return err;
            }

            mLastTrack->meta->setInt32(kKeyTrackID, id);
            *offset += chunk_size;
            break;
        }
@@ -1275,6 +1231,93 @@ status_t MPEG4Extractor::parseChunk(off_t *offset, int depth) {
    return OK;
}

status_t MPEG4Extractor::parseTrackHeader(
        off_t data_offset, off_t data_size) {
    if (data_size < 4) {
        return ERROR_MALFORMED;
    }

    uint8_t version;
    if (mDataSource->readAt(data_offset, &version, 1) < 1) {
        return ERROR_IO;
    }

    size_t dynSize = (version == 1) ? 36 : 24;

    uint8_t buffer[36 + 60];

    if (data_size != (off_t)dynSize + 60) {
        return ERROR_MALFORMED;
    }

    if (mDataSource->readAt(
                data_offset, buffer, data_size) < (ssize_t)data_size) {
        return ERROR_IO;
    }

    uint64_t ctime, mtime, duration;
    int32_t id;

    if (version == 1) {
        ctime = U64_AT(&buffer[4]);
        mtime = U64_AT(&buffer[12]);
        id = U32_AT(&buffer[20]);
        duration = U64_AT(&buffer[28]);
    } else {
        CHECK_EQ((unsigned)version, 0u);

        ctime = U32_AT(&buffer[4]);
        mtime = U32_AT(&buffer[8]);
        id = U32_AT(&buffer[12]);
        duration = U32_AT(&buffer[20]);
    }

    mLastTrack->meta->setInt32(kKeyTrackID, id);

    size_t matrixOffset = dynSize + 16;
    int32_t a00 = U32_AT(&buffer[matrixOffset]);
    int32_t a01 = U32_AT(&buffer[matrixOffset + 4]);
    int32_t dx = U32_AT(&buffer[matrixOffset + 8]);
    int32_t a10 = U32_AT(&buffer[matrixOffset + 12]);
    int32_t a11 = U32_AT(&buffer[matrixOffset + 16]);
    int32_t dy = U32_AT(&buffer[matrixOffset + 20]);

#if 0
    LOGI("x' = %.2f * x + %.2f * y + %.2f",
         a00 / 65536.0f, a01 / 65536.0f, dx / 65536.0f);
    LOGI("y' = %.2f * x + %.2f * y + %.2f",
         a10 / 65536.0f, a11 / 65536.0f, dy / 65536.0f);
#endif

    uint32_t rotationDegrees;

    static const int32_t kFixedOne = 0x10000;
    if (a00 == kFixedOne && a01 == 0 && a10 == 0 && a11 == kFixedOne) {
        // Identity, no rotation
        rotationDegrees = 0;
    } else if (a00 == 0 && a01 == kFixedOne && a10 == -kFixedOne && a11 == 0) {
        rotationDegrees = 90;
    } else if (a00 == 0 && a01 == -kFixedOne && a10 == kFixedOne && a11 == 0) {
        rotationDegrees = 270;
    } else if (a00 == -kFixedOne && a01 == 0 && a10 == 0 && a11 == -kFixedOne) {
        rotationDegrees = 180;
    } else {
        LOGW("We only support 0,90,180,270 degree rotation matrices");
        rotationDegrees = 0;
    }

    if (rotationDegrees != 0) {
        mLastTrack->meta->setInt32(kKeyRotation, rotationDegrees);
    }

#if 0
    uint32_t width = U32_AT(&buffer[dynSize + 52]);
    uint32_t height = U32_AT(&buffer[dynSize + 56]);
#endif

    return OK;
}

status_t MPEG4Extractor::parseMetaData(off_t offset, size_t size) {
    if (size < 4) {
        return ERROR_MALFORMED;
@@ -1588,7 +1631,7 @@ MPEG4Source::MPEG4Source(
        const uint8_t *ptr = (const uint8_t *)data;

        CHECK(size >= 7);
        CHECK_EQ(ptr[0], 1);  // configurationVersion == 1
        CHECK_EQ((unsigned)ptr[0], 1u);  // configurationVersion == 1

        // The number of bytes used to encode the length of a NAL unit.
        mNALLengthSize = 1 + (ptr[4] & 3);
@@ -1736,7 +1779,7 @@ status_t MPEG4Source::read(
        }

        uint32_t sampleTime;
        CHECK_EQ(OK, mSampleTable->getMetaDataForSample(
        CHECK_EQ((status_t)OK, mSampleTable->getMetaDataForSample(
                    sampleIndex, NULL, NULL, &sampleTime));

        if (mode == ReadOptions::SEEK_CLOSEST) {
@@ -1783,7 +1826,7 @@ status_t MPEG4Source::read(
        err = mGroup->acquire_buffer(&mBuffer);

        if (err != OK) {
            CHECK_EQ(mBuffer, NULL);
            CHECK(mBuffer == NULL);
            return err;
        }
    }
+16 −1
Original line number Diff line number Diff line
@@ -35,7 +35,8 @@ SoftwareRenderer::SoftwareRenderer(
        OMX_COLOR_FORMATTYPE colorFormat,
        const sp<Surface> &surface,
        size_t displayWidth, size_t displayHeight,
        size_t decodedWidth, size_t decodedHeight)
        size_t decodedWidth, size_t decodedHeight,
        int32_t rotationDegrees)
    : mColorFormat(colorFormat),
      mConverter(NULL),
      mYUVMode(None),
@@ -95,6 +96,20 @@ SoftwareRenderer::SoftwareRenderer(
    CHECK_EQ(0, native_window_set_buffers_geometry(
                mSurface.get(), mDecodedWidth, mDecodedHeight,
                halFormat));

    uint32_t transform;
    switch (rotationDegrees) {
        case 0: transform = 0; break;
        case 90: transform = HAL_TRANSFORM_ROT_90; break;
        case 180: transform = HAL_TRANSFORM_ROT_180; break;
        case 270: transform = HAL_TRANSFORM_ROT_270; break;
        default: transform = 0; break;
    }

    if (transform) {
        CHECK_EQ(0, native_window_set_buffers_transform(
                    mSurface.get(), transform));
    }
}

SoftwareRenderer::~SoftwareRenderer() {
+2 −0
Original line number Diff line number Diff line
@@ -88,6 +88,8 @@ private:
    bool mIsDrm;
    status_t parseDrmSINF(off_t *offset, off_t data_offset);

    status_t parseTrackHeader(off_t data_offset, off_t data_size);

    MPEG4Extractor(const MPEG4Extractor &);
    MPEG4Extractor &operator=(const MPEG4Extractor &);
};
+2 −1
Original line number Diff line number Diff line
@@ -31,7 +31,8 @@ public:
            OMX_COLOR_FORMATTYPE colorFormat,
            const sp<Surface> &surface,
            size_t displayWidth, size_t displayHeight,
            size_t decodedWidth, size_t decodedHeight);
            size_t decodedWidth, size_t decodedHeight,
            int32_t rotationDegrees);

    ~SoftwareRenderer();