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

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

Merge "Experimental support for enabling the use of "surface input" mode"

parents 3a24dfc5 a0a63e13
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -12,11 +12,16 @@ LOCAL_C_INCLUDES := \
        frameworks/av/media/libstagefright/include \
        frameworks/native/include/media/openmax \

ifeq ($(TARGET_DEVICE), manta)
    LOCAL_CFLAGS += -DSURFACE_IS_BGR32
endif

LOCAL_STATIC_LIBRARIES := \
        libvpx

LOCAL_SHARED_LIBRARIES := \
        libstagefright libstagefright_omx libstagefright_foundation libutils liblog \
        libhardware \

LOCAL_MODULE := libstagefright_soft_vpxenc
LOCAL_MODULE_TAGS := optional
+142 −17
Original line number Diff line number Diff line
@@ -20,6 +20,8 @@

#include <utils/Log.h>

#include <media/hardware/HardwareAPI.h>
#include <media/hardware/MetadataBufferType.h>
#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/MediaDefs.h>

@@ -81,6 +83,52 @@ inline static void ConvertSemiPlanarToPlanar(uint8_t *inyuv,
    }
}

static void ConvertRGB32ToPlanar(
        const uint8_t *src, uint8_t *dstY, int32_t width, int32_t height) {
    CHECK((width & 1) == 0);
    CHECK((height & 1) == 0);

    uint8_t *dstU = dstY + width * height;
    uint8_t *dstV = dstU + (width / 2) * (height / 2);

    for (int32_t y = 0; y < height; ++y) {
        for (int32_t x = 0; x < width; ++x) {
#ifdef SURFACE_IS_BGR32
            unsigned blue = src[4 * x];
            unsigned green = src[4 * x + 1];
            unsigned red= src[4 * x + 2];
#else
            unsigned red= src[4 * x];
            unsigned green = src[4 * x + 1];
            unsigned blue = src[4 * x + 2];
#endif

            unsigned luma =
                ((red * 66 + green * 129 + blue * 25) >> 8) + 16;

            dstY[x] = luma;

            if ((x & 1) == 0 && (y & 1) == 0) {
                unsigned U =
                    ((-red * 38 - green * 74 + blue * 112) >> 8) + 128;

                unsigned V =
                    ((red * 112 - green * 94 - blue * 18) >> 8) + 128;

                dstU[x / 2] = U;
                dstV[x / 2] = V;
            }
        }

        if ((y & 1) == 0) {
            dstU += width / 2;
            dstV += width / 2;
        }

        src += 4 * width;
        dstY += width;
    }
}

SoftVPXEncoder::SoftVPXEncoder(const char *name,
                               const OMX_CALLBACKTYPE *callbacks,
@@ -99,8 +147,9 @@ SoftVPXEncoder::SoftVPXEncoder(const char *name,
      mErrorResilience(OMX_FALSE),
      mColorFormat(OMX_COLOR_FormatYUV420Planar),
      mLevel(OMX_VIDEO_VP8Level_Version0),
      mConversionBuffer(NULL) {

      mConversionBuffer(NULL),
      mInputDataIsMeta(false),
      mGrallocModule(NULL) {
    initPorts();
}

@@ -247,7 +296,7 @@ status_t SoftVPXEncoder::initEncoder() {
        return UNKNOWN_ERROR;
    }

    if (mColorFormat == OMX_COLOR_FormatYUV420SemiPlanar) {
    if (mColorFormat == OMX_COLOR_FormatYUV420SemiPlanar || mInputDataIsMeta) {
        if (mConversionBuffer == NULL) {
            mConversionBuffer = (uint8_t *)malloc(mWidth * mHeight * 3 / 2);
            if (mConversionBuffer == NULL) {
@@ -427,9 +476,17 @@ OMX_ERRORTYPE SoftVPXEncoder::internalSetParameter(OMX_INDEXTYPE index,
                (const OMX_VIDEO_PARAM_BITRATETYPE *)param);

        case OMX_IndexParamPortDefinition:
            return internalSetPortParams(
        {
            OMX_ERRORTYPE err = internalSetPortParams(
                (const OMX_PARAM_PORTDEFINITIONTYPE *)param);

            if (err != OMX_ErrorNone) {
                return err;
            }

            return SimpleSoftOMXComponent::internalSetParameter(index, param);
        }

        case OMX_IndexParamVideoPortFormat:
            return internalSetFormatParams(
                (const OMX_VIDEO_PARAM_PORTFORMATTYPE *)param);
@@ -442,6 +499,21 @@ OMX_ERRORTYPE SoftVPXEncoder::internalSetParameter(OMX_INDEXTYPE index,
            return internalSetProfileLevel(
                (const OMX_VIDEO_PARAM_PROFILELEVELTYPE *)param);

        case OMX_IndexVendorStartUnused:
        {
            // storeMetaDataInBuffers
            const StoreMetaDataInBuffersParams *storeParam =
                (const StoreMetaDataInBuffersParams *)param;

            if (storeParam->nPortIndex != kInputPortIndex) {
                return OMX_ErrorBadPortIndex;
            }

            mInputDataIsMeta = (storeParam->bStoreMetaData == OMX_TRUE);

            return OMX_ErrorNone;
        }

        default:
            return SimpleSoftOMXComponent::internalSetParameter(index, param);
    }
@@ -507,6 +579,10 @@ OMX_ERRORTYPE SoftVPXEncoder::internalSetFormatParams(
            format->eColorFormat == OMX_COLOR_FormatYUV420SemiPlanar ||
            format->eColorFormat == OMX_COLOR_FormatAndroidOpaque) {
            mColorFormat = format->eColorFormat;

            OMX_PARAM_PORTDEFINITIONTYPE *def = &editPortInfo(kInputPortIndex)->mDef;
            def->format.video.eColorFormat = mColorFormat;

            return OMX_ErrorNone;
        } else {
            ALOGE("Unsupported color format %i", format->eColorFormat);
@@ -557,6 +633,12 @@ OMX_ERRORTYPE SoftVPXEncoder::internalSetPortParams(
            return OMX_ErrorUnsupportedSetting;
        }

        OMX_PARAM_PORTDEFINITIONTYPE *def = &editPortInfo(kInputPortIndex)->mDef;
        def->format.video.nFrameWidth = mWidth;
        def->format.video.nFrameHeight = mHeight;
        def->format.video.xFramerate = port->format.video.xFramerate;
        def->format.video.eColorFormat = mColorFormat;

        return OMX_ErrorNone;
    } else if (port->nPortIndex == kOutputPortIndex) {
        mBitrate = port->format.video.nBitrate;
@@ -625,19 +707,51 @@ void SoftVPXEncoder::onQueueFilled(OMX_U32 portIndex) {
            return;
        }

        uint8_t* source = inputBufferHeader->pBuffer + inputBufferHeader->nOffset;
        uint8_t *source =
            inputBufferHeader->pBuffer + inputBufferHeader->nOffset;

        if (mInputDataIsMeta) {
            CHECK_GE(inputBufferHeader->nFilledLen,
                     4 + sizeof(buffer_handle_t));

            uint32_t bufferType = *(uint32_t *)source;
            CHECK_EQ(bufferType, kMetadataBufferTypeGrallocSource);

            if (mGrallocModule == NULL) {
                CHECK_EQ(0, hw_get_module(
                            GRALLOC_HARDWARE_MODULE_ID, &mGrallocModule));
            }

            const gralloc_module_t *grmodule =
                (const gralloc_module_t *)mGrallocModule;

            buffer_handle_t handle = *(buffer_handle_t *)(source + 4);

            void *bits;
            CHECK_EQ(0,
                     grmodule->lock(
                         grmodule, handle,
                         GRALLOC_USAGE_SW_READ_OFTEN
                            | GRALLOC_USAGE_SW_WRITE_NEVER,
                         0, 0, mWidth, mHeight, &bits));

            ConvertRGB32ToPlanar(
                    (const uint8_t *)bits, mConversionBuffer, mWidth, mHeight);

            source = mConversionBuffer;

            CHECK_EQ(0, grmodule->unlock(grmodule, handle));
        } else if (mColorFormat == OMX_COLOR_FormatYUV420SemiPlanar) {
            ConvertSemiPlanarToPlanar(
                    source, mConversionBuffer, mWidth, mHeight);

        // NOTE: As much as nothing is known about color format
        // when it is denoted as AndroidOpaque, it is at least
        // assumed to be planar.
        if (mColorFormat == OMX_COLOR_FormatYUV420SemiPlanar) {
            ConvertSemiPlanarToPlanar(source, mConversionBuffer, mWidth, mHeight);
            source = mConversionBuffer;
        }
        vpx_image_t raw_frame;
        vpx_img_wrap(&raw_frame, VPX_IMG_FMT_I420, mWidth, mHeight,
                     kInputBufferAlignment, source);
        codec_return = vpx_codec_encode(mCodecContext,
        codec_return = vpx_codec_encode(
                mCodecContext,
                &raw_frame,
                inputBufferHeader->nTimeStamp,  // in timebase units
                mFrameDurationUs,  // frame duration in timebase units
@@ -676,6 +790,17 @@ void SoftVPXEncoder::onQueueFilled(OMX_U32 portIndex) {
        notifyEmptyBufferDone(inputBufferHeader);
    }
}

OMX_ERRORTYPE SoftVPXEncoder::getExtensionIndex(
        const char *name, OMX_INDEXTYPE *index) {
    if (!strcmp(name, "OMX.google.android.index.storeMetaDataInBuffers")) {
        *index = OMX_IndexVendorStartUnused;
        return OMX_ErrorNone;
    }

    return SimpleSoftOMXComponent::getExtensionIndex(name, index);
}

}  // namespace android


+11 −4
Original line number Diff line number Diff line
@@ -23,6 +23,8 @@
#include <OMX_VideoExt.h>
#include <OMX_IndexExt.h>

#include <hardware/gralloc.h>

#include "vpx/vpx_encoder.h"
#include "vpx/vpx_codec.h"
#include "vpx/vp8cx.h"
@@ -57,8 +59,7 @@ namespace android {
//    - OMX timestamps are in microseconds, therefore
// encoder timebase is fixed to 1/1000000

class SoftVPXEncoder : public SimpleSoftOMXComponent {
 public:
struct SoftVPXEncoder : public SimpleSoftOMXComponent {
    SoftVPXEncoder(const char *name,
                   const OMX_CALLBACKTYPE *callbacks,
                   OMX_PTR appData,
@@ -83,6 +84,9 @@ class SoftVPXEncoder : public SimpleSoftOMXComponent {
    // encoding of the frame
    virtual void onQueueFilled(OMX_U32 portIndex);

    virtual OMX_ERRORTYPE getExtensionIndex(
            const char *name, OMX_INDEXTYPE *index);

private:
    // number of buffers allocated per port
    static const uint32_t kNumBuffers = 4;
@@ -156,6 +160,9 @@ class SoftVPXEncoder : public SimpleSoftOMXComponent {
    // indeed YUV420SemiPlanar.
    uint8_t* mConversionBuffer;

    bool mInputDataIsMeta;
    const hw_module_t *mGrallocModule;

    // Initializes input and output OMX ports with sensible
    // default values.
    void initPorts();