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 Original line Diff line number Diff line
@@ -12,11 +12,16 @@ LOCAL_C_INCLUDES := \
        frameworks/av/media/libstagefright/include \
        frameworks/av/media/libstagefright/include \
        frameworks/native/include/media/openmax \
        frameworks/native/include/media/openmax \


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

LOCAL_STATIC_LIBRARIES := \
LOCAL_STATIC_LIBRARIES := \
        libvpx
        libvpx


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


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


#include <utils/Log.h>
#include <utils/Log.h>


#include <media/hardware/HardwareAPI.h>
#include <media/hardware/MetadataBufferType.h>
#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/MediaDefs.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,
SoftVPXEncoder::SoftVPXEncoder(const char *name,
                               const OMX_CALLBACKTYPE *callbacks,
                               const OMX_CALLBACKTYPE *callbacks,
@@ -99,8 +147,9 @@ SoftVPXEncoder::SoftVPXEncoder(const char *name,
      mErrorResilience(OMX_FALSE),
      mErrorResilience(OMX_FALSE),
      mColorFormat(OMX_COLOR_FormatYUV420Planar),
      mColorFormat(OMX_COLOR_FormatYUV420Planar),
      mLevel(OMX_VIDEO_VP8Level_Version0),
      mLevel(OMX_VIDEO_VP8Level_Version0),
      mConversionBuffer(NULL) {
      mConversionBuffer(NULL),

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


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


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


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


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

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

        case OMX_IndexParamVideoPortFormat:
        case OMX_IndexParamVideoPortFormat:
            return internalSetFormatParams(
            return internalSetFormatParams(
                (const OMX_VIDEO_PARAM_PORTFORMATTYPE *)param);
                (const OMX_VIDEO_PARAM_PORTFORMATTYPE *)param);
@@ -442,6 +499,21 @@ OMX_ERRORTYPE SoftVPXEncoder::internalSetParameter(OMX_INDEXTYPE index,
            return internalSetProfileLevel(
            return internalSetProfileLevel(
                (const OMX_VIDEO_PARAM_PROFILELEVELTYPE *)param);
                (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:
        default:
            return SimpleSoftOMXComponent::internalSetParameter(index, param);
            return SimpleSoftOMXComponent::internalSetParameter(index, param);
    }
    }
@@ -507,6 +579,10 @@ OMX_ERRORTYPE SoftVPXEncoder::internalSetFormatParams(
            format->eColorFormat == OMX_COLOR_FormatYUV420SemiPlanar ||
            format->eColorFormat == OMX_COLOR_FormatYUV420SemiPlanar ||
            format->eColorFormat == OMX_COLOR_FormatAndroidOpaque) {
            format->eColorFormat == OMX_COLOR_FormatAndroidOpaque) {
            mColorFormat = format->eColorFormat;
            mColorFormat = format->eColorFormat;

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

            return OMX_ErrorNone;
            return OMX_ErrorNone;
        } else {
        } else {
            ALOGE("Unsupported color format %i", format->eColorFormat);
            ALOGE("Unsupported color format %i", format->eColorFormat);
@@ -557,6 +633,12 @@ OMX_ERRORTYPE SoftVPXEncoder::internalSetPortParams(
            return OMX_ErrorUnsupportedSetting;
            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;
        return OMX_ErrorNone;
    } else if (port->nPortIndex == kOutputPortIndex) {
    } else if (port->nPortIndex == kOutputPortIndex) {
        mBitrate = port->format.video.nBitrate;
        mBitrate = port->format.video.nBitrate;
@@ -625,19 +707,51 @@ void SoftVPXEncoder::onQueueFilled(OMX_U32 portIndex) {
            return;
            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;
            source = mConversionBuffer;
        }
        }
        vpx_image_t raw_frame;
        vpx_image_t raw_frame;
        vpx_img_wrap(&raw_frame, VPX_IMG_FMT_I420, mWidth, mHeight,
        vpx_img_wrap(&raw_frame, VPX_IMG_FMT_I420, mWidth, mHeight,
                     kInputBufferAlignment, source);
                     kInputBufferAlignment, source);
        codec_return = vpx_codec_encode(mCodecContext,
        codec_return = vpx_codec_encode(
                mCodecContext,
                &raw_frame,
                &raw_frame,
                inputBufferHeader->nTimeStamp,  // in timebase units
                inputBufferHeader->nTimeStamp,  // in timebase units
                mFrameDurationUs,  // frame duration in timebase units
                mFrameDurationUs,  // frame duration in timebase units
@@ -676,6 +790,17 @@ void SoftVPXEncoder::onQueueFilled(OMX_U32 portIndex) {
        notifyEmptyBufferDone(inputBufferHeader);
        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
}  // namespace android




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


#include <hardware/gralloc.h>

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


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


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

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


    bool mInputDataIsMeta;
    const hw_module_t *mGrallocModule;

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