Require 16x16 alignment when using HardwareVideoEncoder for encoding.
It seems the Android CTS tests only verify that 16x16 aligned resolutions are supported. This change checks the validity of input frame's size when initialing or encoding processes are about to start using H/W MediaCodec. This change has additional APIs to retrieve |requested_resolution_alignment| and |apply_alignment_to_all_simulcast_layers| from JAVA VideoEncoder class and its inherited classes. HardwareVideoEncoder using MediaCodec has values of 16 and true for above variables. Bug: webrtc:13089 Change-Id: I0c4ebf94eb36da29c2e384a3edf85b82e779b7f9 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/229460 Reviewed-by: Sergey Silkin <ssilkin@webrtc.org> Reviewed-by: Åsa Persson <asapersson@webrtc.org> Commit-Queue: Sergey Silkin <ssilkin@webrtc.org> Cr-Commit-Position: refs/heads/main@{#35169}
This commit is contained in:
committed by
WebRTC LUCI CQ
parent
3179fb2931
commit
5a79d28eba
@ -54,6 +54,9 @@ class HardwareVideoEncoder implements VideoEncoder {
|
||||
private static final int MEDIA_CODEC_RELEASE_TIMEOUT_MS = 5000;
|
||||
private static final int DEQUEUE_OUTPUT_BUFFER_TIMEOUT_US = 100000;
|
||||
|
||||
// Size of the input frames should be multiple of 16 for the H/W encoder.
|
||||
private static final int REQUIRED_RESOLUTION_ALIGNMENT = 16;
|
||||
|
||||
/**
|
||||
* Keeps track of the number of output buffers that have been passed down the pipeline and not yet
|
||||
* released. We need to wait for this to go down to zero before operations invalidating the output
|
||||
@ -207,6 +210,12 @@ class HardwareVideoEncoder implements VideoEncoder {
|
||||
|
||||
this.callback = callback;
|
||||
automaticResizeOn = settings.automaticResizeOn;
|
||||
|
||||
if (settings.width % REQUIRED_RESOLUTION_ALIGNMENT != 0
|
||||
|| settings.height % REQUIRED_RESOLUTION_ALIGNMENT != 0) {
|
||||
Logging.e(TAG, "MediaCodec is only tested with resolutions that are 16x16 aligned.");
|
||||
return VideoCodecStatus.ERR_SIZE;
|
||||
}
|
||||
this.width = settings.width;
|
||||
this.height = settings.height;
|
||||
useSurfaceMode = canUseSurface();
|
||||
@ -498,12 +507,28 @@ class HardwareVideoEncoder implements VideoEncoder {
|
||||
return "HWEncoder";
|
||||
}
|
||||
|
||||
@Override
|
||||
public EncoderInfo getEncoderInfo() {
|
||||
// Since our MediaCodec is guaranteed to encode 16-pixel-aligned frames only, we set alignment
|
||||
// value to be 16. Additionally, this encoder produces a single stream. So it should not require
|
||||
// alignment for all layers.
|
||||
return new EncoderInfo(
|
||||
/* requestedResolutionAlignment= */ REQUIRED_RESOLUTION_ALIGNMENT,
|
||||
/* applyAlignmentToAllSimulcastLayers= */ false);
|
||||
}
|
||||
|
||||
private VideoCodecStatus resetCodec(int newWidth, int newHeight, boolean newUseSurfaceMode) {
|
||||
encodeThreadChecker.checkIsOnValidThread();
|
||||
VideoCodecStatus status = release();
|
||||
if (status != VideoCodecStatus.OK) {
|
||||
return status;
|
||||
}
|
||||
|
||||
if (newWidth % REQUIRED_RESOLUTION_ALIGNMENT != 0
|
||||
|| newHeight % REQUIRED_RESOLUTION_ALIGNMENT != 0) {
|
||||
Logging.e(TAG, "MediaCodec is only tested with resolutions that are 16x16 aligned.");
|
||||
return VideoCodecStatus.ERR_SIZE;
|
||||
}
|
||||
width = newWidth;
|
||||
height = newHeight;
|
||||
useSurfaceMode = newUseSurfaceMode;
|
||||
|
||||
@ -113,6 +113,12 @@ void VideoEncoderWrapper::UpdateEncoderInfo(JNIEnv* jni) {
|
||||
|
||||
encoder_info_.resolution_bitrate_limits = JavaToNativeResolutionBitrateLimits(
|
||||
jni, Java_VideoEncoder_getResolutionBitrateLimits(jni, encoder_));
|
||||
|
||||
EncoderInfo info = GetEncoderInfoInternal(jni);
|
||||
encoder_info_.requested_resolution_alignment =
|
||||
info.requested_resolution_alignment;
|
||||
encoder_info_.apply_alignment_to_all_simulcast_layers =
|
||||
info.apply_alignment_to_all_simulcast_layers;
|
||||
}
|
||||
|
||||
int32_t VideoEncoderWrapper::RegisterEncodeCompleteCallback(
|
||||
@ -230,6 +236,26 @@ VideoEncoderWrapper::GetScalingSettingsInternal(JNIEnv* jni) const {
|
||||
}
|
||||
}
|
||||
|
||||
VideoEncoder::EncoderInfo VideoEncoderWrapper::GetEncoderInfoInternal(
|
||||
JNIEnv* jni) const {
|
||||
ScopedJavaLocalRef<jobject> j_encoder_info =
|
||||
Java_VideoEncoder_getEncoderInfo(jni, encoder_);
|
||||
|
||||
jint requested_resolution_alignment =
|
||||
Java_EncoderInfo_getRequestedResolutionAlignment(jni, j_encoder_info);
|
||||
|
||||
jboolean apply_alignment_to_all_simulcast_layers =
|
||||
Java_EncoderInfo_getApplyAlignmentToAllSimulcastLayers(jni,
|
||||
j_encoder_info);
|
||||
|
||||
VideoEncoder::EncoderInfo info;
|
||||
info.requested_resolution_alignment = requested_resolution_alignment;
|
||||
info.apply_alignment_to_all_simulcast_layers =
|
||||
apply_alignment_to_all_simulcast_layers;
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
void VideoEncoderWrapper::OnEncodedFrame(
|
||||
JNIEnv* jni,
|
||||
const JavaRef<jobject>& j_encoded_image) {
|
||||
|
||||
@ -87,6 +87,8 @@ class VideoEncoderWrapper : public VideoEncoder {
|
||||
std::vector<ResolutionBitrateLimits> GetResolutionBitrateLimits(
|
||||
JNIEnv* jni) const;
|
||||
|
||||
VideoEncoder::EncoderInfo GetEncoderInfoInternal(JNIEnv* jni) const;
|
||||
|
||||
const ScopedJavaGlobalRef<jobject> encoder_;
|
||||
const ScopedJavaGlobalRef<jclass> int_array_class_;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user