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

Commit 66404133 authored by Hangyu Kuang's avatar Hangyu Kuang Committed by Android (Google) Code Review
Browse files

Merge "stagefright: Support intra refresh in SoftAVC video encoder."

parents c71563f7 870aff9b
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -369,6 +369,8 @@ private:

    status_t setPriority(int32_t priority);
    status_t setOperatingRate(float rateFloat, bool isVideo);
    status_t getIntraRefreshPeriod(uint32_t *intraRefreshPeriod);
    status_t setIntraRefreshPeriod(uint32_t intraRefreshPeriod, bool inConfigure);

    status_t setMinBufferSize(OMX_U32 portIndex, size_t size);

+123 −0
Original line number Diff line number Diff line
@@ -2231,6 +2231,102 @@ status_t ACodec::setOperatingRate(float rateFloat, bool isVideo) {
    return OK;
}

status_t ACodec::getIntraRefreshPeriod(uint32_t *intraRefreshPeriod) {
    OMX_VIDEO_CONFIG_ANDROID_INTRAREFRESHTYPE params;
    InitOMXParams(&params);
    params.nPortIndex = kPortIndexOutput;
    status_t err = mOMX->getConfig(
            mNode, (OMX_INDEXTYPE)OMX_IndexConfigAndroidIntraRefresh, &params, sizeof(params));
    if (err == OK) {
        *intraRefreshPeriod = params.nRefreshPeriod;
        return OK;
    }

    // Fallback to query through standard OMX index.
    OMX_VIDEO_PARAM_INTRAREFRESHTYPE refreshParams;
    InitOMXParams(&refreshParams);
    refreshParams.nPortIndex = kPortIndexOutput;
    refreshParams.eRefreshMode = OMX_VIDEO_IntraRefreshCyclic;
    err = mOMX->getParameter(
            mNode, OMX_IndexParamVideoIntraRefresh, &refreshParams, sizeof(refreshParams));
    if (err != OK || refreshParams.nCirMBs == 0) {
        *intraRefreshPeriod = 0;
        return OK;
    }

    // Calculate period based on width and height
    uint32_t width, height;
    OMX_PARAM_PORTDEFINITIONTYPE def;
    InitOMXParams(&def);
    OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video;
    def.nPortIndex = kPortIndexOutput;
    err = mOMX->getParameter(
            mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
    if (err != OK) {
        *intraRefreshPeriod = 0;
        return err;
    }
    width = video_def->nFrameWidth;
    height = video_def->nFrameHeight;
    // Use H.264/AVC MacroBlock size 16x16
    *intraRefreshPeriod = divUp((divUp(width, 16u) * divUp(height, 16u)), refreshParams.nCirMBs);

    return OK;
}

status_t ACodec::setIntraRefreshPeriod(uint32_t intraRefreshPeriod, bool inConfigure) {
    OMX_VIDEO_CONFIG_ANDROID_INTRAREFRESHTYPE params;
    InitOMXParams(&params);
    params.nPortIndex = kPortIndexOutput;
    params.nRefreshPeriod = intraRefreshPeriod;
    status_t err = mOMX->setConfig(
            mNode, (OMX_INDEXTYPE)OMX_IndexConfigAndroidIntraRefresh, &params, sizeof(params));
    if (err == OK) {
        return OK;
    }

    // Only in configure state, a component could invoke setParameter.
    if (!inConfigure) {
        return INVALID_OPERATION;
    } else {
        ALOGI("[%s] try falling back to Cyclic", mComponentName.c_str());
    }

    OMX_VIDEO_PARAM_INTRAREFRESHTYPE refreshParams;
    InitOMXParams(&refreshParams);
    refreshParams.nPortIndex = kPortIndexOutput;
    refreshParams.eRefreshMode = OMX_VIDEO_IntraRefreshCyclic;

    if (intraRefreshPeriod == 0) {
        // 0 means disable intra refresh.
        refreshParams.nCirMBs = 0;
    } else {
        // Calculate macroblocks that need to be intra coded base on width and height
        uint32_t width, height;
        OMX_PARAM_PORTDEFINITIONTYPE def;
        InitOMXParams(&def);
        OMX_VIDEO_PORTDEFINITIONTYPE *video_def = &def.format.video;
        def.nPortIndex = kPortIndexOutput;
        err = mOMX->getParameter(
                mNode, OMX_IndexParamPortDefinition, &def, sizeof(def));
        if (err != OK) {
            return err;
        }
        width = video_def->nFrameWidth;
        height = video_def->nFrameHeight;
        // Use H.264/AVC MacroBlock size 16x16
        refreshParams.nCirMBs = divUp((divUp(width, 16u) * divUp(height, 16u)), intraRefreshPeriod);
    }

    err = mOMX->setParameter(mNode, OMX_IndexParamVideoIntraRefresh,
                             &refreshParams, sizeof(refreshParams));
    if (err != OK) {
        return err;
    }

    return OK;
}

status_t ACodec::setMinBufferSize(OMX_U32 portIndex, size_t size) {
    OMX_PARAM_PORTDEFINITIONTYPE def;
    InitOMXParams(&def);
@@ -3082,6 +3178,17 @@ status_t ACodec::setupVideoEncoder(const char *mime, const sp<AMessage> &msg) {
        return err;
    }

    int32_t intraRefreshPeriod = 0;
    if (msg->findInt32("intra-refresh-period", &intraRefreshPeriod)
            && intraRefreshPeriod >= 0) {
        err = setIntraRefreshPeriod((uint32_t)intraRefreshPeriod, true);
        if (err != OK) {
            ALOGI("[%s] failed setIntraRefreshPeriod. Failure is fine since this key is optional",
                    mComponentName.c_str());
            err = OK;
        }
    }

    switch (compressionFormat) {
        case OMX_VIDEO_CodingMPEG4:
            err = setupMPEG4EncoderParameters(msg);
@@ -4159,6 +4266,11 @@ status_t ACodec::getPortFormat(OMX_U32 portIndex, sp<AMessage> &notify) {
                    } else {
                        notify->setString("mime", mime.c_str());
                    }
                    uint32_t intraRefreshPeriod = 0;
                    if (mIsEncoder && getIntraRefreshPeriod(&intraRefreshPeriod) == OK
                            && intraRefreshPeriod > 0) {
                        notify->setInt32("intra-refresh-period", intraRefreshPeriod);
                    }
                    break;
                }
            }
@@ -6362,6 +6474,17 @@ status_t ACodec::setParameters(const sp<AMessage> &params) {
        }
    }

    int32_t intraRefreshPeriod = 0;
    if (params->findInt32("intra-refresh-period", &intraRefreshPeriod)
            && intraRefreshPeriod > 0) {
        status_t err = setIntraRefreshPeriod(intraRefreshPeriod, false);
        if (err != OK) {
            ALOGI("[%s] failed setIntraRefreshPeriod. Failure is fine since this key is optional",
                    mComponentName.c_str());
            err = OK;
        }
    }

    return OK;
}

+41 −1
Original line number Diff line number Diff line
@@ -28,6 +28,8 @@
#include <media/stagefright/MediaErrors.h>
#include <media/stagefright/MetaData.h>
#include <media/stagefright/Utils.h>
#include <OMX_IndexExt.h>
#include <OMX_VideoExt.h>
#include <ui/Rect.h>

#include "ih264_typedefs.h"
@@ -1027,9 +1029,29 @@ OMX_ERRORTYPE SoftAVC::internalSetParameter(OMX_INDEXTYPE index, const OMX_PTR p
    }
}

OMX_ERRORTYPE SoftAVC::getConfig(
        OMX_INDEXTYPE index, OMX_PTR _params) {
    switch ((int)index) {
        case OMX_IndexConfigAndroidIntraRefresh:
        {
            OMX_VIDEO_CONFIG_ANDROID_INTRAREFRESHTYPE *intraRefreshParams =
                (OMX_VIDEO_CONFIG_ANDROID_INTRAREFRESHTYPE *)_params;
            if (intraRefreshParams->nPortIndex != kOutputPortIndex) {
                return OMX_ErrorUndefined;
            }

            intraRefreshParams->nRefreshPeriod = mAIRRefreshPeriod;
            return OMX_ErrorNone;
        }

        default:
            return SoftVideoEncoderOMXComponent::getConfig(index, _params);
    }
}

OMX_ERRORTYPE SoftAVC::setConfig(
        OMX_INDEXTYPE index, const OMX_PTR _params) {
    switch (index) {
    switch ((int)index) {
        case OMX_IndexConfigVideoIntraVOPRefresh:
        {
            OMX_CONFIG_INTRAREFRESHVOPTYPE *params =
@@ -1059,6 +1081,24 @@ OMX_ERRORTYPE SoftAVC::setConfig(
            return OMX_ErrorNone;
        }

        case OMX_IndexConfigAndroidIntraRefresh:
        {
            const OMX_VIDEO_CONFIG_ANDROID_INTRAREFRESHTYPE *intraRefreshParams =
                (const OMX_VIDEO_CONFIG_ANDROID_INTRAREFRESHTYPE *)_params;
            if (intraRefreshParams->nPortIndex != kOutputPortIndex) {
                return OMX_ErrorUndefined;
            }

            if (intraRefreshParams->nRefreshPeriod == 0) {
                mAIRMode = IVE_AIR_MODE_NONE;
                mAIRRefreshPeriod = 0;
            } else if (intraRefreshParams->nRefreshPeriod > 0) {
                mAIRMode = IVE_AIR_MODE_CYCLIC;
                mAIRRefreshPeriod = intraRefreshParams->nRefreshPeriod;
            }
            return OMX_ErrorNone;
        }

        default:
            return SimpleSoftOMXComponent::setConfig(index, _params);
    }
+3 −0
Original line number Diff line number Diff line
@@ -218,6 +218,9 @@ private:
    OMX_ERRORTYPE setConfig(
        OMX_INDEXTYPE index, const OMX_PTR _params);

    OMX_ERRORTYPE getConfig(
        OMX_INDEXTYPE index, const OMX_PTR _params);

    // Handles port definition changes.
    OMX_ERRORTYPE internalSetPortParams(
        const OMX_PARAM_PORTDEFINITIONTYPE *port);