Add support for codec importance
Set an importance value when configuring the codec in `Codec.Factory`, PiperOrigin-RevId: 623902251
This commit is contained in:
parent
a154c98faa
commit
b1127ed735
@ -27,6 +27,7 @@ import android.media.MediaFormat;
|
|||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.util.Pair;
|
import android.util.Pair;
|
||||||
import android.view.Surface;
|
import android.view.Surface;
|
||||||
|
import androidx.annotation.IntRange;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import androidx.media3.common.C;
|
import androidx.media3.common.C;
|
||||||
import androidx.media3.common.ColorInfo;
|
import androidx.media3.common.ColorInfo;
|
||||||
@ -40,6 +41,7 @@ import androidx.media3.exoplayer.mediacodec.MediaCodecInfo;
|
|||||||
import androidx.media3.exoplayer.mediacodec.MediaCodecSelector;
|
import androidx.media3.exoplayer.mediacodec.MediaCodecSelector;
|
||||||
import androidx.media3.exoplayer.mediacodec.MediaCodecUtil;
|
import androidx.media3.exoplayer.mediacodec.MediaCodecUtil;
|
||||||
import com.google.common.collect.ImmutableList;
|
import com.google.common.collect.ImmutableList;
|
||||||
|
import com.google.errorprone.annotations.CanIgnoreReturnValue;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@ -51,9 +53,8 @@ public final class DefaultDecoderFactory implements Codec.DecoderFactory {
|
|||||||
|
|
||||||
private static final String TAG = "DefaultDecoderFactory";
|
private static final String TAG = "DefaultDecoderFactory";
|
||||||
|
|
||||||
private final Context context;
|
/** The platform's default value of {@code MediaFormat#KEY_IMPORTANCE}. */
|
||||||
private final boolean enableDecoderFallback;
|
private static final int DEFAULT_CODEC_IMPORTANCE = 0;
|
||||||
private final Listener listener;
|
|
||||||
|
|
||||||
/** Listener for decoder factory events. */
|
/** Listener for decoder factory events. */
|
||||||
public interface Listener {
|
public interface Listener {
|
||||||
@ -70,12 +71,78 @@ public final class DefaultDecoderFactory implements Codec.DecoderFactory {
|
|||||||
void onCodecInitialized(String codecName, List<ExportException> codecInitializationExceptions);
|
void onCodecInitialized(String codecName, List<ExportException> codecInitializationExceptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Creates a new factory that selects the most preferred decoder for the format. */
|
/** A builder for {@link DefaultDecoderFactory} instances. */
|
||||||
|
public static final class Builder {
|
||||||
|
private final Context context;
|
||||||
|
private Listener listener;
|
||||||
|
private boolean enableDecoderFallback;
|
||||||
|
private int codecImportance;
|
||||||
|
|
||||||
|
/** Creates a new {@link Builder}. */
|
||||||
|
public Builder(Context context) {
|
||||||
|
this.context = context.getApplicationContext();
|
||||||
|
listener = (codecName, codecInitializationExceptions) -> {};
|
||||||
|
codecImportance = DEFAULT_CODEC_IMPORTANCE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Sets the {@link Listener}. */
|
||||||
|
@CanIgnoreReturnValue
|
||||||
|
public Builder setListener(Listener listener) {
|
||||||
|
this.listener = listener;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets whether the decoder can fallback.
|
||||||
|
*
|
||||||
|
* <p>This decides whether to enable fallback to lower-priority decoders if decoder
|
||||||
|
* initialization fails. This may result in using a decoder that is less efficient or slower
|
||||||
|
* than the primary decoder.
|
||||||
|
*
|
||||||
|
* <p>The default value is {@code false}.
|
||||||
|
*/
|
||||||
|
@CanIgnoreReturnValue
|
||||||
|
public Builder setEnableDecoderFallback(boolean enableDecoderFallback) {
|
||||||
|
this.enableDecoderFallback = enableDecoderFallback;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the codec importance value.
|
||||||
|
*
|
||||||
|
* <p>Specifying codec importance allows the resource manager in the platform to reclaim less
|
||||||
|
* important codecs (higher importance values) before more important codecs. For example, codecs
|
||||||
|
* used for background operations should have higher importance values so they are reclaimed if
|
||||||
|
* required for foreground operations.
|
||||||
|
*
|
||||||
|
* <p>This method is a no-op on API versions before 35.
|
||||||
|
*
|
||||||
|
* <p>The default value is {@code 0}.
|
||||||
|
*/
|
||||||
|
// TODO: b/333552477 - Link documentation after API35 is released.
|
||||||
|
@CanIgnoreReturnValue
|
||||||
|
public Builder setCodecImportance(@IntRange(from = 0) int codecImportance) {
|
||||||
|
this.codecImportance = codecImportance;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Creates an instance of {@link DefaultDecoderFactory}, using defaults if values are unset. */
|
||||||
|
public DefaultDecoderFactory build() {
|
||||||
|
return new DefaultDecoderFactory(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private final Context context;
|
||||||
|
private final boolean enableDecoderFallback;
|
||||||
|
private final Listener listener;
|
||||||
|
private final int codecImportance;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated Use {@link Builder} instead.
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
public DefaultDecoderFactory(Context context) {
|
public DefaultDecoderFactory(Context context) {
|
||||||
this(
|
this(new Builder(context));
|
||||||
context,
|
|
||||||
/* enableDecoderFallback= */ false,
|
|
||||||
(codecName, codecInitializationExceptions) -> {});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -87,11 +154,19 @@ public final class DefaultDecoderFactory implements Codec.DecoderFactory {
|
|||||||
* initialization fails. This may result in using a decoder that is less efficient or slower
|
* initialization fails. This may result in using a decoder that is less efficient or slower
|
||||||
* than the primary decoder.
|
* than the primary decoder.
|
||||||
* @param listener Listener for codec initialization errors.
|
* @param listener Listener for codec initialization errors.
|
||||||
|
* @deprecated Use {@link Builder} instead.
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public DefaultDecoderFactory(Context context, boolean enableDecoderFallback, Listener listener) {
|
public DefaultDecoderFactory(Context context, boolean enableDecoderFallback, Listener listener) {
|
||||||
this.context = context.getApplicationContext();
|
this(
|
||||||
this.enableDecoderFallback = enableDecoderFallback;
|
new Builder(context).setEnableDecoderFallback(enableDecoderFallback).setListener(listener));
|
||||||
this.listener = listener;
|
}
|
||||||
|
|
||||||
|
private DefaultDecoderFactory(Builder builder) {
|
||||||
|
this.context = builder.context;
|
||||||
|
this.enableDecoderFallback = builder.enableDecoderFallback;
|
||||||
|
this.listener = builder.listener;
|
||||||
|
this.codecImportance = builder.codecImportance;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -146,6 +221,12 @@ public final class DefaultDecoderFactory implements Codec.DecoderFactory {
|
|||||||
mediaFormat, MediaFormat.KEY_LEVEL, codecProfileAndLevel.second);
|
mediaFormat, MediaFormat.KEY_LEVEL, codecProfileAndLevel.second);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (SDK_INT >= 35) {
|
||||||
|
// TODO: b/333552477 - Redefinition of MediaFormat.KEY_IMPORTANCE, remove after API35 is
|
||||||
|
// released.
|
||||||
|
mediaFormat.setInteger("importance", codecImportance);
|
||||||
|
}
|
||||||
|
|
||||||
return createCodecForMediaFormat(mediaFormat, format, outputSurface);
|
return createCodecForMediaFormat(mediaFormat, format, outputSurface);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -32,6 +32,7 @@ import android.media.MediaFormat;
|
|||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.util.Pair;
|
import android.util.Pair;
|
||||||
import android.util.Size;
|
import android.util.Size;
|
||||||
|
import androidx.annotation.IntRange;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import androidx.media3.common.ColorInfo;
|
import androidx.media3.common.ColorInfo;
|
||||||
import androidx.media3.common.Format;
|
import androidx.media3.common.Format;
|
||||||
@ -54,18 +55,25 @@ public final class DefaultEncoderFactory implements Codec.EncoderFactory {
|
|||||||
/** Best effort, or as-fast-as-possible priority setting for {@link MediaFormat#KEY_PRIORITY}. */
|
/** Best effort, or as-fast-as-possible priority setting for {@link MediaFormat#KEY_PRIORITY}. */
|
||||||
private static final int PRIORITY_BEST_EFFORT = 1;
|
private static final int PRIORITY_BEST_EFFORT = 1;
|
||||||
|
|
||||||
|
/** The platform's default value of {@code MediaFormat#KEY_IMPORTANCE}. */
|
||||||
|
private static final int DEFAULT_CODEC_IMPORTANCE = 0;
|
||||||
|
|
||||||
/** A builder for {@link DefaultEncoderFactory} instances. */
|
/** A builder for {@link DefaultEncoderFactory} instances. */
|
||||||
public static final class Builder {
|
public static final class Builder {
|
||||||
private final Context context;
|
private final Context context;
|
||||||
|
|
||||||
@Nullable private EncoderSelector videoEncoderSelector;
|
private EncoderSelector videoEncoderSelector;
|
||||||
@Nullable private VideoEncoderSettings requestedVideoEncoderSettings;
|
private VideoEncoderSettings requestedVideoEncoderSettings;
|
||||||
private boolean enableFallback;
|
private boolean enableFallback;
|
||||||
|
private int codecImportance;
|
||||||
|
|
||||||
/** Creates a new {@link Builder}. */
|
/** Creates a new {@link Builder}. */
|
||||||
public Builder(Context context) {
|
public Builder(Context context) {
|
||||||
this.context = context;
|
this.context = context.getApplicationContext();
|
||||||
this.enableFallback = true;
|
videoEncoderSelector = EncoderSelector.DEFAULT;
|
||||||
|
requestedVideoEncoderSettings = VideoEncoderSettings.DEFAULT;
|
||||||
|
enableFallback = true;
|
||||||
|
codecImportance = DEFAULT_CODEC_IMPORTANCE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -120,17 +128,28 @@ public final class DefaultEncoderFactory implements Codec.EncoderFactory {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the codec importance value.
|
||||||
|
*
|
||||||
|
* <p>Specifying codec importance allows the resource manager in the platform to reclaim less
|
||||||
|
* important codecs (higher importance values) before more important codecs. For example, codecs
|
||||||
|
* used for background operations should have higher importance values so they are reclaimed if
|
||||||
|
* required for foreground operations.
|
||||||
|
*
|
||||||
|
* <p>This method is a no-op on API versions before 35.
|
||||||
|
*
|
||||||
|
* <p>The default value is {@code 0}.
|
||||||
|
*/
|
||||||
|
// TODO: b/333552477 - Link documentation after API35 is released.
|
||||||
|
@CanIgnoreReturnValue
|
||||||
|
public Builder setCodecImportance(@IntRange(from = 0) int codecImportance) {
|
||||||
|
this.codecImportance = codecImportance;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
/** Creates an instance of {@link DefaultEncoderFactory}, using defaults if values are unset. */
|
/** Creates an instance of {@link DefaultEncoderFactory}, using defaults if values are unset. */
|
||||||
@SuppressWarnings("deprecation")
|
|
||||||
public DefaultEncoderFactory build() {
|
public DefaultEncoderFactory build() {
|
||||||
if (videoEncoderSelector == null) {
|
return new DefaultEncoderFactory(this);
|
||||||
videoEncoderSelector = EncoderSelector.DEFAULT;
|
|
||||||
}
|
|
||||||
if (requestedVideoEncoderSettings == null) {
|
|
||||||
requestedVideoEncoderSettings = VideoEncoderSettings.DEFAULT;
|
|
||||||
}
|
|
||||||
return new DefaultEncoderFactory(
|
|
||||||
context, videoEncoderSelector, requestedVideoEncoderSettings, enableFallback);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -138,6 +157,7 @@ public final class DefaultEncoderFactory implements Codec.EncoderFactory {
|
|||||||
private final EncoderSelector videoEncoderSelector;
|
private final EncoderSelector videoEncoderSelector;
|
||||||
private final VideoEncoderSettings requestedVideoEncoderSettings;
|
private final VideoEncoderSettings requestedVideoEncoderSettings;
|
||||||
private final boolean enableFallback;
|
private final boolean enableFallback;
|
||||||
|
private final int codecImportance;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @deprecated Use {@link Builder} instead.
|
* @deprecated Use {@link Builder} instead.
|
||||||
@ -171,6 +191,15 @@ public final class DefaultEncoderFactory implements Codec.EncoderFactory {
|
|||||||
this.videoEncoderSelector = videoEncoderSelector;
|
this.videoEncoderSelector = videoEncoderSelector;
|
||||||
this.requestedVideoEncoderSettings = requestedVideoEncoderSettings;
|
this.requestedVideoEncoderSettings = requestedVideoEncoderSettings;
|
||||||
this.enableFallback = enableFallback;
|
this.enableFallback = enableFallback;
|
||||||
|
this.codecImportance = DEFAULT_CODEC_IMPORTANCE;
|
||||||
|
}
|
||||||
|
|
||||||
|
private DefaultEncoderFactory(Builder builder) {
|
||||||
|
this.context = builder.context;
|
||||||
|
this.videoEncoderSelector = builder.videoEncoderSelector;
|
||||||
|
this.requestedVideoEncoderSettings = builder.requestedVideoEncoderSettings;
|
||||||
|
this.enableFallback = builder.enableFallback;
|
||||||
|
this.codecImportance = builder.codecImportance;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -326,6 +355,12 @@ public final class DefaultEncoderFactory implements Codec.EncoderFactory {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (Util.SDK_INT >= 35) {
|
||||||
|
// TODO: b/333552477 - Redefinition of MediaFormat.KEY_IMPORTANCE, remove after API35 is
|
||||||
|
// released.
|
||||||
|
mediaFormat.setInteger("importance", codecImportance);
|
||||||
|
}
|
||||||
|
|
||||||
return new DefaultCodec(
|
return new DefaultCodec(
|
||||||
context,
|
context,
|
||||||
encoderSupportedFormat,
|
encoderSupportedFormat,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user