media: Add MediaCodec constants for RoI encoding
Bug: 299191092
Test: Build
API-Coverage-Bug: 324928731
Change-Id: Ibfd0586e091f781e09798b1c34ae63e09e42f76c
diff --git a/core/api/current.txt b/core/api/current.txt
index a150535..f0315d1 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -22611,6 +22611,8 @@
field public static final String PARAMETER_KEY_HDR10_PLUS_INFO = "hdr10-plus-info";
field public static final String PARAMETER_KEY_LOW_LATENCY = "low-latency";
field public static final String PARAMETER_KEY_OFFSET_TIME = "time-offset-us";
+ field @FlaggedApi("android.media.codec.region_of_interest") public static final String PARAMETER_KEY_QP_OFFSET_MAP = "qp-offset-map";
+ field @FlaggedApi("android.media.codec.region_of_interest") public static final String PARAMETER_KEY_QP_OFFSET_RECTS = "qp-offset-rects";
field public static final String PARAMETER_KEY_REQUEST_SYNC_FRAME = "request-sync";
field public static final String PARAMETER_KEY_SUSPEND = "drop-input-frames";
field public static final String PARAMETER_KEY_SUSPEND_TIME = "drop-start-time-us";
@@ -22853,6 +22855,7 @@
field public static final String FEATURE_MultipleFrames = "multiple-frames";
field public static final String FEATURE_PartialFrame = "partial-frame";
field public static final String FEATURE_QpBounds = "qp-bounds";
+ field @FlaggedApi("android.media.codec.region_of_interest") public static final String FEATURE_Roi = "region-of-interest";
field public static final String FEATURE_SecurePlayback = "secure-playback";
field public static final String FEATURE_TunneledPlayback = "tunneled-playback";
field public int[] colorFormats;
diff --git a/media/java/android/media/MediaCodec.java b/media/java/android/media/MediaCodec.java
index 862ae8d..1d5092b 100644
--- a/media/java/android/media/MediaCodec.java
+++ b/media/java/android/media/MediaCodec.java
@@ -16,6 +16,10 @@
package android.media;
+import static android.media.codec.Flags.FLAG_REGION_OF_INTEREST;
+
+import static com.android.media.codec.flags.Flags.FLAG_LARGE_AUDIO_FRAME;
+
import android.Manifest;
import android.annotation.FlaggedApi;
import android.annotation.IntDef;
@@ -51,7 +55,6 @@
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
-import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
@@ -62,7 +65,6 @@
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
-import static com.android.media.codec.flags.Flags.FLAG_LARGE_AUDIO_FRAME;
/**
MediaCodec class can be used to access low-level media codecs, i.e. encoder/decoder components.
It is part of the Android low-level multimedia support infrastructure (normally used together
@@ -4936,6 +4938,68 @@
public static final String PARAMETER_KEY_TUNNEL_PEEK = "tunnel-peek";
/**
+ * Set the region of interest as QpOffset-Map on the next queued input frame.
+ * <p>
+ * The associated value is a byte array containing quantization parameter (QP) offsets in
+ * raster scan order for the entire frame at 16x16 granularity. The size of the byte array
+ * shall be ((frame_width + 15) / 16) * ((frame_height + 15) / 16), where frame_width and
+ * frame_height correspond to width and height configured using {@link MediaFormat#KEY_WIDTH}
+ * and {@link MediaFormat#KEY_HEIGHT} keys respectively. During encoding, if the coding unit
+ * size is larger than 16x16, then the qpOffset information of all 16x16 blocks that
+ * encompass the coding unit is combined and used. The QP of target block will be calculated
+ * as 'frameQP + offsetQP'. If the result exceeds minQP or maxQP configured then the value
+ * may be clamped. Negative offset results in blocks encoded at lower QP than frame QP and
+ * positive offsets will result in encoding blocks at higher QP than frame QP. If the areas
+ * of negative QP and positive QP are chosen wisely, the overall viewing experience can be
+ * improved.
+ * <p>
+ * If byte array size is too small than the expected size, components may ignore the
+ * configuration silently. If the byte array exceeds the expected size, components shall use
+ * the initial portion and ignore the rest.
+ * <p>
+ * The scope of this key is throughout the encoding session until it is reconfigured during
+ * running state.
+ * <p>
+ * @see #setParameters(Bundle)
+ */
+ @FlaggedApi(FLAG_REGION_OF_INTEREST)
+ public static final String PARAMETER_KEY_QP_OFFSET_MAP = "qp-offset-map";
+
+ /**
+ * Set the region of interest as QpOffset-Rects on the next queued input frame.
+ * <p>
+ * The associated value is a String in the format "Top1,Left1-Bottom1,Right1=Offset1;Top2,
+ * Left2-Bottom2,Right2=Offset2;...". Co-ordinates (Top, Left), (Top, Right), (Bottom, Left)
+ * and (Bottom, Right) form the vertices of bounding box of region of interest in pixels.
+ * Pixel (0, 0) points to the top-left corner of the frame. Offset is the suggested
+ * quantization parameter (QP) offset of the blocks in the bounding box. The bounding box
+ * will get stretched outwards to align to LCU boundaries during encoding. The Qp Offset is
+ * integral and shall be in the range [-128, 127]. The QP of target block will be calculated
+ * as frameQP + offsetQP. If the result exceeds minQP or maxQP configured then the value may
+ * be clamped. Negative offset results in blocks encoded at lower QP than frame QP and
+ * positive offsets will result in blocks encoded at higher QP than frame QP. If the areas of
+ * negative QP and positive QP are chosen wisely, the overall viewing experience can be
+ * improved.
+ * <p>
+ * If Roi rect is not valid that is bounding box width is < 0 or bounding box height is < 0,
+ * components may ignore the configuration silently. If Roi rect extends outside frame
+ * boundaries, then rect shall be clamped to the frame boundaries.
+ * <p>
+ * The scope of this key is throughout the encoding session until it is reconfigured during
+ * running state.
+ * <p>
+ * The maximum number of contours (rectangles) that can be specified for a given input frame
+ * is device specific. Implementations will drop/ignore the rectangles that are beyond their
+ * supported limit. Hence it is preferable to place the rects in descending order of
+ * importance. Transitively, if the bounding boxes overlap, then the most preferred
+ * rectangle's qp offset (earlier rectangle qp offset) will be used to quantize the block.
+ * <p>
+ * @see #setParameters(Bundle)
+ */
+ @FlaggedApi(FLAG_REGION_OF_INTEREST)
+ public static final String PARAMETER_KEY_QP_OFFSET_RECTS = "qp-offset-rects";
+
+ /**
* Communicate additional parameter changes to the component instance.
* <b>Note:</b> Some of these parameter changes may silently fail to apply.
*
diff --git a/media/java/android/media/MediaCodecInfo.java b/media/java/android/media/MediaCodecInfo.java
index b0daea8..86f89ab 100644
--- a/media/java/android/media/MediaCodecInfo.java
+++ b/media/java/android/media/MediaCodecInfo.java
@@ -20,6 +20,7 @@
import static android.media.Utils.sortDistinctRanges;
import static android.media.codec.Flags.FLAG_DYNAMIC_COLOR_ASPECTS;
import static android.media.codec.Flags.FLAG_HLG_EDITING;
+import static android.media.codec.Flags.FLAG_REGION_OF_INTEREST;
import android.annotation.FlaggedApi;
import android.annotation.IntRange;
@@ -741,6 +742,42 @@
public static final String FEATURE_DynamicColorAspects = "dynamic-color-aspects";
/**
+ * <b>video encoder only</b>: codec supports region of interest encoding.
+ * <p>
+ * RoI encoding support means the codec accepts information that specifies the relative
+ * importance of different portions of each video frame. This allows the encoder to
+ * separate a video frame into critical and non-critical regions, and use more bits
+ * (better quality) to represent the critical regions and de-prioritize non-critical
+ * regions. In other words, the encoder chooses a negative qp bias for the critical
+ * portions and a zero or positive qp bias for the non-critical portions.
+ * <p>
+ * At a basic level, if the encoder decides to encode each frame with a uniform
+ * quantization value 'qpFrame' and a 'qpBias' is chosen/suggested for an LCU of the
+ * frame, then the actual qp of the LCU will be 'qpFrame + qpBias', although this value
+ * can be clamped basing on the min-max configured qp bounds for the current encoding
+ * session.
+ * <p>
+ * In a shot, if a group of LCUs pan out quickly they can be marked as non-critical
+ * thereby enabling the encoder to reserve fewer bits during their encoding. Contrarily,
+ * LCUs that remain in shot for a prolonged duration can be encoded at better quality in
+ * one frame thereby setting-up an excellent long-term reference for all future frames.
+ * <p>
+ * Note that by offsetting the quantization of each LCU, the overall bit allocation will
+ * differ from the originally estimated bit allocation, and the encoder will adjust the
+ * frame quantization for subsequent frames to meet the bitrate target. An effective
+ * selection of critical regions can set-up a golden reference and this can compensate
+ * for the bit burden that was introduced due to encoding RoI's at better quality.
+ * On the other hand, an ineffective choice of critical regions might increase the
+ * quality of certain parts of the image but this can hamper quality in subsequent frames.
+ * <p>
+ * @see MediaCodec#PARAMETER_KEY_QP_OFFSET_MAP
+ * @see MediaCodec#PARAMETER_KEY_QP_OFFSET_RECTS
+ */
+ @SuppressLint("AllUpper")
+ @FlaggedApi(FLAG_REGION_OF_INTEREST)
+ public static final String FEATURE_Roi = "region-of-interest";
+
+ /**
* Query codec feature capabilities.
* <p>
* These features are supported to be used by the codec. These
@@ -798,6 +835,9 @@
if (android.media.codec.Flags.hlgEditing()) {
features.add(new Feature(FEATURE_HlgEditing, (1 << 6), true));
}
+ if (android.media.codec.Flags.regionOfInterest()) {
+ features.add(new Feature(FEATURE_Roi, (1 << 7), true));
+ }
// feature to exclude codec from REGULAR codec list
features.add(new Feature(FEATURE_SpecialCodec, (1 << 30), false, true));