diff options
| -rw-r--r-- | core/api/current.txt | 3 | ||||
| -rw-r--r-- | media/java/android/media/MediaCodec.java | 68 | ||||
| -rw-r--r-- | media/java/android/media/MediaCodecInfo.java | 40 |
3 files changed, 109 insertions, 2 deletions
diff --git a/core/api/current.txt b/core/api/current.txt index 7052fd1c08e9..70babd3fb360 100644 --- a/core/api/current.txt +++ b/core/api/current.txt @@ -22552,6 +22552,8 @@ package android.media { 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"; @@ -22794,6 +22796,7 @@ package android.media { 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 bfb4b42a8346..4ee25c4bcf60 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.BitSet; 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.LinkedBlockingQueue; 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 @@ -4938,6 +4940,68 @@ final public class MediaCodec { 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 b0daea84a525..86f89ab89f63 100644 --- a/media/java/android/media/MediaCodecInfo.java +++ b/media/java/android/media/MediaCodecInfo.java @@ -20,6 +20,7 @@ import static android.media.Utils.intersectSortedDistinctRanges; 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 final class MediaCodecInfo { 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 @@ public final class MediaCodecInfo { 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)); |