# Advanced Encoder Frame-QP Control

Table of Contents

- [Advanced Encoder Frame-QP Control](https://docs.qualcomm.com/doc/80-56386-10/topic/advance_qp_control.html#advanced-encoder-frame-qp-control)

    - [Advanced Encoder Frame-QP Extensions](https://docs.qualcomm.com/doc/80-56386-10/topic/advance_qp_control.html#advanced-encoder-frame-qp-extensions)
    - [Query capabilities](https://docs.qualcomm.com/doc/80-56386-10/topic/advance_qp_control.html#query-capabilities)
    - [Using the advanced frame-QP extension](https://docs.qualcomm.com/doc/80-56386-10/topic/advance_qp_control.html#using-the-advanced-frame-qp-extension)

The Snapdragon Advanced Encoder-QP Control feature allows applications to implement a fine-grained encoder by completely taking over the QP decision per frame.
This is an extension to the [Encoder Initial Quantization Parameter (QP)](https://docs.qualcomm.com/doc/80-56386-10/topic/encoder_qp.html#init-qp-main-label) feature, where the application can override the QP of the initial frame and each subsequent frame.
When using this extension, the application takes complete ownership of analyzing frame complexity and making quality versus bitrate tradeoffs to arrive at the QP values per frame.
The encoder operates in *Rate-Control Off* mode and expects the application to program the QP per frame.

Note

It is recommended to use MediaCodec.QueueRequest() to bundle the frames and configuration and submit them atomically (unless using ByteBuffer mode).
When buffers are submitted to the encoder using an input surface, setting parameters dynamically with MediaCodec.setParameters() does not guarantee frame synchronization.

## [Advanced Encoder Frame-QP Extensions](https://docs.qualcomm.com/doc/80-56386-10/topic/advance_qp_control.html#id2)[](https://docs.qualcomm.com/doc/80-56386-10/topic/advance_qp_control.html#advanced-encoder-frame-qp-extensions)

| API KEY | Value Type | Details |
| --- | --- | --- |
| [`KEY_ADV_BITRATE_MODE`](https://docs.qualcomm.com/doc/80-56386-10/topic/classqti_1_1video_1_1QMediaExtensions.html#_CPPv4N3qti5video16QMediaExtensionsE) | Integer | Set value to [`ADV_BITRATE_MODE`](https://docs.qualcomm.com/doc/80-56386-10/topic/classqti_1_1video_1_1QMediaExtensions.html#_CPPv4N3qti5video16QMediaExtensionsE) to disable Hardware Encoder’s QP generation and allow application to provide QP values. |
| [`KEY_ADV_QP_FRAME_QP_VALUE`](https://docs.qualcomm.com/doc/80-56386-10/topic/classqti_1_1video_1_1QMediaExtensions.html#_CPPv4N3qti5video16QMediaExtensionsE) | Integer | QP value supplied by application to be used by the encoder to compress the next frame. |

## [Query capabilities](https://docs.qualcomm.com/doc/80-56386-10/topic/advance_qp_control.html#id3)[](https://docs.qualcomm.com/doc/80-56386-10/topic/advance_qp_control.html#query-capabilities)

MediaCodec codec = MediaCodec.createByCodecName("c2.qti.hevc.encoder");
    // codec.getSupportedVendorParameters() should contain KEY_ADV_QP_BITRATE_MODE and KEY_ADV_QP_FRAME_QP_VALUE
    List<String> vendorParams = codec.getSupportedVendorParameters();
    
    /*
     * vendorParams should contain KEY_ADV_BITRATE_MODE and KEY_ADV_QP_FRAME_QP_VALUE
     */
    if (supportedExtensions.indexOf(KEY_ADV_BITRATE_MODE) != -1
            && supportedExtensions.indexOf(KEY_ADV_QP_FRAME_QP_VALUE) != -1) {
        // Advanced frame QP extension is supported
    }
    
    /*
     * Query if the rate-control disable mode (ADV_BITRATE_MODE_DISABLED) is supported
     */
    QMediaCodecCapabilities qCodecCaps = QMediaCodecCapabilities.CreateForCodec("c2.qti.hevc.encoder", "video/hevc");
    // qCodecCaps.getParameterDescriptor(KEY_ADV_BITRATE_MODE).getType() -> MediaFormat.TYPE_INTEGER
    SupportedValues<Integer> bitrateModeValues = qCodecCaps.getParameterRangeInteger(KEY_ADV_QP_BITRATE_MODE);
    // bitrateModeValues.getType() -> SupportedValues.TYPE_RANGE or SupportedValues.TYPE_VALUES
    
    /*
     * Query the valid range of frame-QP values that can be programmed to the encoder
     */
    // qCodecCaps.getParameterDescriptor(KEY_ADV_QP_FRAME_QP_VALUE).getType() -> MediaFormat.TYPE_INTEGER
    SupportedValues<Integer> frameQpValues = qCodecCaps.getParameterRangeInteger(KEY_ADV_QP_FRAME_QP_VALUE);
    // frameQpValues.getType() -> SupportedValues.TYPE_RANGE
    Copy to clipboard

## [Using the advanced frame-QP extension](https://docs.qualcomm.com/doc/80-56386-10/topic/advance_qp_control.html#id4)[](https://docs.qualcomm.com/doc/80-56386-10/topic/advance_qp_control.html#using-the-advanced-frame-qp-extension)

MediaCodec codec = MediaCodec.createEncoderByType("video/hevc");
    
    // Disable encoder's rate-control to be able to override frame-QP
    MediaFormat format = MediaFormat.createVideoFormat("video/hevc", 1280, 720);
    format.setInteger(KEY_ADV_QP_BITRATE_MODE, ADV_BITRATE_MODE_DISABLED);
    ...
    codec.configure(format, ...);
    
    ...
    
    /*
     * Inside the input buffer queueing loop
     */
    {
        // analyze frame-complexity and determine frame-QP
        // int qp = computeFrameQP(inputBuffer);
    
        // set the frame-QP
        Bundle frameQPInfo = new Bundle();
        frameQPInfo.setInteger(KEY_ADV_QP_FRAME_QP_VALUE, qp);
    
        codec.setParameters(frameQPInfo);
    
        // queue the input buffer
    }
    Copy to clipboard

Last Published: Jun 13, 2023

[Previous Topic
Encoder Initial QP Override](https://docs.qualcomm.com/bundle/publicresource/80-56386-10/topics/encoder_qp.md) [Next Topic
Error Resilience - Slices and Resync-Markers](https://docs.qualcomm.com/bundle/publicresource/80-56386-10/topics/er_slice_resync_markers.md)