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

Commit 456dec2b authored by Chong Zhang's avatar Chong Zhang
Browse files

stagefright: handle constant quality mode

Handle constant quality mode from MediaCodec, and pass the
quality to encoder.

bug: 63633199
Change-Id: I4183e44bb5c11b7bd93ce7ade1859e6f774b97fd
parent cf11d8f7
Loading
Loading
Loading
Loading
+78 −45
Original line number Diff line number Diff line
@@ -125,6 +125,32 @@ static inline status_t makeNoSideEffectStatus(status_t err) {
    }
}

static OMX_VIDEO_CONTROLRATETYPE getVideoBitrateMode(const sp<AMessage> &msg) {
    int32_t tmp;
    if (msg->findInt32("bitrate-mode", &tmp)) {
        // explicitly translate from MediaCodecInfo.EncoderCapabilities.
        // BITRATE_MODE_* into OMX bitrate mode.
        switch (tmp) {
            //BITRATE_MODE_CQ
            case 0: return OMX_Video_ControlRateConstantQuality;
            //BITRATE_MODE_VBR
            case 1: return OMX_Video_ControlRateVariable;
            //BITRATE_MODE_CBR
            case 2: return OMX_Video_ControlRateConstant;
            default: break;
        }
    }
    return OMX_Video_ControlRateVariable;
}

static bool findVideoBitrateControlInfo(const sp<AMessage> &msg,
        OMX_VIDEO_CONTROLRATETYPE *mode, int32_t *bitrate, int32_t *quality) {
    *mode = getVideoBitrateMode(msg);
    bool isCQ = (*mode == OMX_Video_ControlRateConstantQuality);
    return (!isCQ && msg->findInt32("bitrate", bitrate))
         || (isCQ && msg->findInt32("quality", quality));
}

struct MessageList : public RefBase {
    MessageList() {
    }
@@ -1683,6 +1709,7 @@ status_t ACodec::configureCodec(
    mConfigFormat = msg;

    mIsEncoder = encoder;
    mIsVideo = !strncasecmp(mime, "video/", 6);

    mPortMode[kPortIndexInput] = IOMX::kPortModePresetByteBuffer;
    mPortMode[kPortIndexOutput] = IOMX::kPortModePresetByteBuffer;
@@ -1693,19 +1720,26 @@ status_t ACodec::configureCodec(
        return err;
    }

    int32_t bitRate = 0;
    // FLAC encoder doesn't need a bitrate, other encoders do
    if (encoder && strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_FLAC)
            && !msg->findInt32("bitrate", &bitRate)) {
    OMX_VIDEO_CONTROLRATETYPE bitrateMode;
    int32_t bitrate = 0, quality;
    // FLAC encoder or video encoder in constant quality mode doesn't need a
    // bitrate, other encoders do.
    if (encoder) {
        if (mIsVideo && !findVideoBitrateControlInfo(
                msg, &bitrateMode, &bitrate, &quality)) {
            return INVALID_OPERATION;
        } else if (!mIsVideo && strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_FLAC)
            && !msg->findInt32("bitrate", &bitrate)) {
            return INVALID_OPERATION;
        }
    }

    // propagate bitrate to the output so that the muxer has it
    if (encoder && msg->findInt32("bitrate", &bitRate)) {
    if (encoder && msg->findInt32("bitrate", &bitrate)) {
        // Technically ISO spec says that 'bitrate' should be 0 for VBR even though it is the
        // average bitrate. We've been setting both bitrate and max-bitrate to this same value.
        outputFormat->setInt32("bitrate", bitRate);
        outputFormat->setInt32("max-bitrate", bitRate);
        outputFormat->setInt32("bitrate", bitrate);
        outputFormat->setInt32("max-bitrate", bitrate);
    }

    int32_t storeMeta;
@@ -1762,9 +1796,7 @@ status_t ACodec::configureCodec(
    // Only enable metadata mode on encoder output if encoder can prepend
    // sps/pps to idr frames, since in metadata mode the bitstream is in an
    // opaque handle, to which we don't have access.
    int32_t video = !strncasecmp(mime, "video/", 6);
    mIsVideo = video;
    if (encoder && video) {
    if (encoder && mIsVideo) {
        OMX_BOOL enable = (OMX_BOOL) (prependSPSPPS
            && msg->findInt32("android._store-metadata-in-buffers-output", &storeMeta)
            && storeMeta != 0);
@@ -1810,9 +1842,9 @@ status_t ACodec::configureCodec(
    // NOTE: we only use native window for video decoders
    sp<RefBase> obj;
    bool haveNativeWindow = msg->findObject("native-window", &obj)
            && obj != NULL && video && !encoder;
            && obj != NULL && mIsVideo && !encoder;
    mUsingNativeWindow = haveNativeWindow;
    if (video && !encoder) {
    if (mIsVideo && !encoder) {
        inputFormat->setInt32("adaptive-playback", false);

        int32_t usageProtected;
@@ -1975,7 +2007,7 @@ status_t ACodec::configureCodec(
    (void)msg->findInt32("pcm-encoding", (int32_t*)&pcmEncoding);
    // invalid encodings will default to PCM-16bit in setupRawAudioFormat.

    if (video) {
    if (mIsVideo) {
        // determine need for software renderer
        bool usingSwRenderer = false;
        if (haveNativeWindow && mComponentName.startsWith("OMX.google.")) {
@@ -2109,14 +2141,14 @@ status_t ACodec::configureCodec(
            }

            err = setupAACCodec(
                    encoder, numChannels, sampleRate, bitRate, aacProfile,
                    encoder, numChannels, sampleRate, bitrate, aacProfile,
                    isADTS != 0, sbrMode, maxOutputChannelCount, drc,
                    pcmLimiterEnable);
        }
    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AMR_NB)) {
        err = setupAMRCodec(encoder, false /* isWAMR */, bitRate);
        err = setupAMRCodec(encoder, false /* isWAMR */, bitrate);
    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AMR_WB)) {
        err = setupAMRCodec(encoder, true /* isWAMR */, bitRate);
        err = setupAMRCodec(encoder, true /* isWAMR */, bitrate);
    } else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_G711_ALAW)
            || !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_G711_MLAW)) {
        // These are PCM-like formats with a fixed sample rate but
@@ -2230,7 +2262,7 @@ status_t ACodec::configureCodec(
        rateFloat = (float)rateInt;  // 16MHz (FLINTMAX) is OK for upper bound.
    }
    if (rateFloat > 0) {
        err = setOperatingRate(rateFloat, video);
        err = setOperatingRate(rateFloat, mIsVideo);
        err = OK; // ignore errors
    }

@@ -2255,7 +2287,7 @@ status_t ACodec::configureCodec(
    }

    // create data converters if needed
    if (!video && err == OK) {
    if (!mIsVideo && err == OK) {
        AudioEncoding codecPcmEncoding = kAudioEncodingPcm16bit;
        if (encoder) {
            (void)mInputFormat->findInt32("pcm-encoding", (int32_t*)&codecPcmEncoding);
@@ -3706,10 +3738,12 @@ status_t ACodec::setupVideoEncoder(
        return err;
    }

    int32_t width, height, bitrate;
    OMX_VIDEO_CONTROLRATETYPE bitrateMode;
    int32_t width, height, bitrate = 0, quality;
    if (!msg->findInt32("width", &width)
            || !msg->findInt32("height", &height)
            || !msg->findInt32("bitrate", &bitrate)) {
            || !findVideoBitrateControlInfo(
                    msg, &bitrateMode, &bitrate, &quality)) {
        return INVALID_OPERATION;
    }

@@ -3962,15 +3996,6 @@ static OMX_U32 setPFramesSpacing(
    return ret > 0 ? ret - 1 : 0;
}

static OMX_VIDEO_CONTROLRATETYPE getBitrateMode(const sp<AMessage> &msg) {
    int32_t tmp;
    if (!msg->findInt32("bitrate-mode", &tmp)) {
        return OMX_Video_ControlRateVariable;
    }

    return static_cast<OMX_VIDEO_CONTROLRATETYPE>(tmp);
}

status_t ACodec::setupMPEG4EncoderParameters(const sp<AMessage> &msg) {
    int32_t bitrate;
    float iFrameInterval;
@@ -3979,7 +4004,7 @@ status_t ACodec::setupMPEG4EncoderParameters(const sp<AMessage> &msg) {
        return INVALID_OPERATION;
    }

    OMX_VIDEO_CONTROLRATETYPE bitrateMode = getBitrateMode(msg);
    OMX_VIDEO_CONTROLRATETYPE bitrateMode = getVideoBitrateMode(msg);

    float frameRate;
    if (!msg->findFloat("frame-rate", &frameRate)) {
@@ -4044,7 +4069,7 @@ status_t ACodec::setupMPEG4EncoderParameters(const sp<AMessage> &msg) {
        return err;
    }

    err = configureBitrate(bitrate, bitrateMode);
    err = configureBitrate(bitrateMode, bitrate);

    if (err != OK) {
        return err;
@@ -4061,7 +4086,7 @@ status_t ACodec::setupH263EncoderParameters(const sp<AMessage> &msg) {
        return INVALID_OPERATION;
    }

    OMX_VIDEO_CONTROLRATETYPE bitrateMode = getBitrateMode(msg);
    OMX_VIDEO_CONTROLRATETYPE bitrateMode = getVideoBitrateMode(msg);

    float frameRate;
    if (!msg->findFloat("frame-rate", &frameRate)) {
@@ -4121,7 +4146,7 @@ status_t ACodec::setupH263EncoderParameters(const sp<AMessage> &msg) {
        return err;
    }

    err = configureBitrate(bitrate, bitrateMode);
    err = configureBitrate(bitrateMode, bitrate);

    if (err != OK) {
        return err;
@@ -4191,7 +4216,7 @@ status_t ACodec::setupAVCEncoderParameters(const sp<AMessage> &msg) {
        return INVALID_OPERATION;
    }

    OMX_VIDEO_CONTROLRATETYPE bitrateMode = getBitrateMode(msg);
    OMX_VIDEO_CONTROLRATETYPE bitrateMode = getVideoBitrateMode(msg);

    float frameRate;
    if (!msg->findFloat("frame-rate", &frameRate)) {
@@ -4347,18 +4372,20 @@ status_t ACodec::setupAVCEncoderParameters(const sp<AMessage> &msg) {
        }
    }

    return configureBitrate(bitrate, bitrateMode);
    return configureBitrate(bitrateMode, bitrate);
}

status_t ACodec::setupHEVCEncoderParameters(const sp<AMessage> &msg) {
    int32_t bitrate;
    float iFrameInterval;
    if (!msg->findInt32("bitrate", &bitrate)
            || !msg->findAsFloat("i-frame-interval", &iFrameInterval)) {
    if (!msg->findAsFloat("i-frame-interval", &iFrameInterval)) {
        return INVALID_OPERATION;
    }

    OMX_VIDEO_CONTROLRATETYPE bitrateMode = getBitrateMode(msg);
    OMX_VIDEO_CONTROLRATETYPE bitrateMode;
    int32_t bitrate, quality;
    if (!findVideoBitrateControlInfo(msg, &bitrateMode, &bitrate, &quality)) {
        return INVALID_OPERATION;
    }

    float frameRate;
    if (!msg->findFloat("frame-rate", &frameRate)) {
@@ -4404,7 +4431,7 @@ status_t ACodec::setupHEVCEncoderParameters(const sp<AMessage> &msg) {
        return err;
    }

    return configureBitrate(bitrate, bitrateMode);
    return configureBitrate(bitrateMode, bitrate, quality);
}

status_t ACodec::setupVPXEncoderParameters(const sp<AMessage> &msg, sp<AMessage> &outputFormat) {
@@ -4425,7 +4452,7 @@ status_t ACodec::setupVPXEncoderParameters(const sp<AMessage> &msg, sp<AMessage>
    }
    msg->findAsFloat("i-frame-interval", &iFrameInterval);

    OMX_VIDEO_CONTROLRATETYPE bitrateMode = getBitrateMode(msg);
    OMX_VIDEO_CONTROLRATETYPE bitrateMode = getVideoBitrateMode(msg);

    float frameRate;
    if (!msg->findFloat("frame-rate", &frameRate)) {
@@ -4502,7 +4529,7 @@ status_t ACodec::setupVPXEncoderParameters(const sp<AMessage> &msg, sp<AMessage>
        }
    }

    return configureBitrate(bitrate, bitrateMode);
    return configureBitrate(bitrateMode, bitrate);
}

status_t ACodec::verifySupportForProfileAndLevel(
@@ -4538,7 +4565,7 @@ status_t ACodec::verifySupportForProfileAndLevel(
}

status_t ACodec::configureBitrate(
        int32_t bitrate, OMX_VIDEO_CONTROLRATETYPE bitrateMode) {
        OMX_VIDEO_CONTROLRATETYPE bitrateMode, int32_t bitrate, int32_t quality) {
    OMX_VIDEO_PARAM_BITRATETYPE bitrateType;
    InitOMXParams(&bitrateType);
    bitrateType.nPortIndex = kPortIndexOutput;
@@ -4551,7 +4578,13 @@ status_t ACodec::configureBitrate(
    }

    bitrateType.eControlRate = bitrateMode;

    // write it out explicitly even if it's a union
    if (bitrateMode == OMX_Video_ControlRateConstantQuality) {
        bitrateType.nQualityFactor = quality;
    } else {
        bitrateType.nTargetBitrate = bitrate;
    }

    return mOMXNode->setParameter(
            OMX_IndexParamVideoBitrate, &bitrateType, sizeof(bitrateType));
+1 −1
Original line number Diff line number Diff line
@@ -494,7 +494,7 @@ private:
    status_t verifySupportForProfileAndLevel(int32_t profile, int32_t level);

    status_t configureBitrate(
            int32_t bitrate, OMX_VIDEO_CONTROLRATETYPE bitrateMode);
            OMX_VIDEO_CONTROLRATETYPE bitrateMode, int32_t bitrate, int32_t quality = 0);
    void configureEncoderLatency(const sp<AMessage> &msg);

    status_t setupErrorCorrectionParameters();