Do not allow null for DefaultAudioSink capabilities

Null was equivalent to DEFAULT_AUDIO_CAPABILITIES.
In favor of null safety, remove the null state.

PiperOrigin-RevId: 415037404
This commit is contained in:
krocard 2021-12-08 18:22:36 +00:00 committed by Oliver Woodman
parent 9676d548c3
commit 2ad9a2e6a5
5 changed files with 42 additions and 43 deletions

View File

@ -28,6 +28,8 @@
* Audio: * Audio:
* Add a `Builder` to `DefaultAudioSink` and deprecate the existing * Add a `Builder` to `DefaultAudioSink` and deprecate the existing
constructors. constructors.
* Change `AudioCapabilities` APIs to require passing explicitly
`AudioCapabilities.DEFAULT_AUDIO_CAPABILITIES` instead of `null`.
* Extractors: * Extractors:
* Fix inconsistency with spec in H.265 SPS nal units parsing * Fix inconsistency with spec in H.265 SPS nal units parsing
((#9719)[https://github.com/google/ExoPlayer/issues/9719]). ((#9719)[https://github.com/google/ExoPlayer/issues/9719]).

View File

@ -19,6 +19,7 @@ import static com.google.android.exoplayer2.decoder.DecoderReuseEvaluation.DISCA
import static com.google.android.exoplayer2.decoder.DecoderReuseEvaluation.DISCARD_REASON_REUSE_NOT_IMPLEMENTED; import static com.google.android.exoplayer2.decoder.DecoderReuseEvaluation.DISCARD_REASON_REUSE_NOT_IMPLEMENTED;
import static com.google.android.exoplayer2.decoder.DecoderReuseEvaluation.REUSE_RESULT_NO; import static com.google.android.exoplayer2.decoder.DecoderReuseEvaluation.REUSE_RESULT_NO;
import static com.google.android.exoplayer2.source.SampleStream.FLAG_REQUIRE_FORMAT; import static com.google.android.exoplayer2.source.SampleStream.FLAG_REQUIRE_FORMAT;
import static com.google.common.base.MoreObjects.firstNonNull;
import static java.lang.Math.max; import static java.lang.Math.max;
import android.os.Handler; import android.os.Handler;
@ -54,7 +55,6 @@ import com.google.android.exoplayer2.util.MediaClock;
import com.google.android.exoplayer2.util.MimeTypes; import com.google.android.exoplayer2.util.MimeTypes;
import com.google.android.exoplayer2.util.TraceUtil; import com.google.android.exoplayer2.util.TraceUtil;
import com.google.android.exoplayer2.util.Util; import com.google.android.exoplayer2.util.Util;
import com.google.common.base.MoreObjects;
import java.lang.annotation.Documented; import java.lang.annotation.Documented;
import java.lang.annotation.Retention; import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy; import java.lang.annotation.RetentionPolicy;
@ -163,22 +163,22 @@ public abstract class DecoderAudioRenderer<
* @param eventHandler A handler to use when delivering events to {@code eventListener}. May be * @param eventHandler A handler to use when delivering events to {@code eventListener}. May be
* null if delivery of events is not required. * null if delivery of events is not required.
* @param eventListener A listener of events. May be null if delivery of events is not required. * @param eventListener A listener of events. May be null if delivery of events is not required.
* @param audioCapabilities The audio capabilities for playback on this device. May be null if the * @param audioCapabilities The audio capabilities for playback on this device. Use {@link
* default capabilities (no encoded audio passthrough support) should be assumed. * AudioCapabilities#DEFAULT_AUDIO_CAPABILITIES} if default capabilities (no encoded audio
* passthrough support) should be assumed.
* @param audioProcessors Optional {@link AudioProcessor}s that will process audio before output. * @param audioProcessors Optional {@link AudioProcessor}s that will process audio before output.
*/ */
public DecoderAudioRenderer( public DecoderAudioRenderer(
@Nullable Handler eventHandler, @Nullable Handler eventHandler,
@Nullable AudioRendererEventListener eventListener, @Nullable AudioRendererEventListener eventListener,
@Nullable AudioCapabilities audioCapabilities, AudioCapabilities audioCapabilities,
AudioProcessor... audioProcessors) { AudioProcessor... audioProcessors) {
this( this(
eventHandler, eventHandler,
eventListener, eventListener,
new DefaultAudioSink.Builder() new DefaultAudioSink.Builder()
.setAudioCapabilities( .setAudioCapabilities( // For backward compatibility, null == default.
MoreObjects.firstNonNull( firstNonNull(audioCapabilities, AudioCapabilities.DEFAULT_AUDIO_CAPABILITIES))
audioCapabilities, AudioCapabilities.DEFAULT_AUDIO_CAPABILITIES))
.setAudioProcessors(audioProcessors) .setAudioProcessors(audioProcessors)
.build()); .build());
} }

View File

@ -15,7 +15,9 @@
*/ */
package com.google.android.exoplayer2.audio; package com.google.android.exoplayer2.audio;
import static com.google.android.exoplayer2.audio.AudioCapabilities.DEFAULT_AUDIO_CAPABILITIES;
import static com.google.android.exoplayer2.util.Assertions.checkNotNull; import static com.google.android.exoplayer2.util.Assertions.checkNotNull;
import static com.google.common.base.MoreObjects.firstNonNull;
import static java.lang.Math.max; import static java.lang.Math.max;
import static java.lang.Math.min; import static java.lang.Math.min;
@ -210,7 +212,7 @@ public final class DefaultAudioSink implements AudioSink {
/** A builder to create {@link DefaultAudioSink} instances. */ /** A builder to create {@link DefaultAudioSink} instances. */
public static final class Builder { public static final class Builder {
@Nullable private AudioCapabilities audioCapabilities; private AudioCapabilities audioCapabilities;
@Nullable private AudioProcessorChain audioProcessorChain; @Nullable private AudioProcessorChain audioProcessorChain;
private boolean enableFloatOutput; private boolean enableFloatOutput;
private boolean enableAudioTrackPlaybackParams; private boolean enableAudioTrackPlaybackParams;
@ -218,6 +220,7 @@ public final class DefaultAudioSink implements AudioSink {
/** Creates a new builder. */ /** Creates a new builder. */
public Builder() { public Builder() {
audioCapabilities = DEFAULT_AUDIO_CAPABILITIES;
offloadMode = OFFLOAD_MODE_DISABLED; offloadMode = OFFLOAD_MODE_DISABLED;
} }
@ -225,9 +228,10 @@ public final class DefaultAudioSink implements AudioSink {
* Sets audio capabilities for playback on this device. May be {@code null} if the default * Sets audio capabilities for playback on this device. May be {@code null} if the default
* capabilities (no encoded audio passthrough support) should be assumed. * capabilities (no encoded audio passthrough support) should be assumed.
* *
* <p>The default value is {@code null}. * <p>Default is {@link AudioCapabilities#DEFAULT_AUDIO_CAPABILITIES}.
*/ */
public Builder setAudioCapabilities(@Nullable AudioCapabilities audioCapabilities) { public Builder setAudioCapabilities(AudioCapabilities audioCapabilities) {
checkNotNull(audioCapabilities);
this.audioCapabilities = audioCapabilities; this.audioCapabilities = audioCapabilities;
return this; return this;
} }
@ -413,7 +417,7 @@ public final class DefaultAudioSink implements AudioSink {
*/ */
public static boolean failOnSpuriousAudioTimestamp = false; public static boolean failOnSpuriousAudioTimestamp = false;
@Nullable private final AudioCapabilities audioCapabilities; private final AudioCapabilities audioCapabilities;
private final AudioProcessorChain audioProcessorChain; private final AudioProcessorChain audioProcessorChain;
private final boolean enableFloatOutput; private final boolean enableFloatOutput;
private final ChannelMappingAudioProcessor channelMappingAudioProcessor; private final ChannelMappingAudioProcessor channelMappingAudioProcessor;
@ -486,7 +490,10 @@ public final class DefaultAudioSink implements AudioSink {
imports = "com.google.android.exoplayer2.audio.DefaultAudioSink") imports = "com.google.android.exoplayer2.audio.DefaultAudioSink")
public DefaultAudioSink( public DefaultAudioSink(
@Nullable AudioCapabilities audioCapabilities, AudioProcessor[] audioProcessors) { @Nullable AudioCapabilities audioCapabilities, AudioProcessor[] audioProcessors) {
this(new Builder().setAudioCapabilities(audioCapabilities).setAudioProcessors(audioProcessors)); this(
new Builder()
.setAudioCapabilities(firstNonNull(audioCapabilities, DEFAULT_AUDIO_CAPABILITIES))
.setAudioProcessors(audioProcessors));
} }
/** @deprecated Use {@link Builder}. */ /** @deprecated Use {@link Builder}. */
@ -506,7 +513,7 @@ public final class DefaultAudioSink implements AudioSink {
boolean enableFloatOutput) { boolean enableFloatOutput) {
this( this(
new Builder() new Builder()
.setAudioCapabilities(audioCapabilities) .setAudioCapabilities(firstNonNull(audioCapabilities, DEFAULT_AUDIO_CAPABILITIES))
.setAudioProcessors(audioProcessors) .setAudioProcessors(audioProcessors)
.setEnableFloatOutput(enableFloatOutput)); .setEnableFloatOutput(enableFloatOutput));
} }
@ -532,7 +539,7 @@ public final class DefaultAudioSink implements AudioSink {
@OffloadMode int offloadMode) { @OffloadMode int offloadMode) {
this( this(
new Builder() new Builder()
.setAudioCapabilities(audioCapabilities) .setAudioCapabilities(firstNonNull(audioCapabilities, DEFAULT_AUDIO_CAPABILITIES))
.setAudioProcessorChain(audioProcessorChain) .setAudioProcessorChain(audioProcessorChain)
.setEnableFloatOutput(enableFloatOutput) .setEnableFloatOutput(enableFloatOutput)
.setEnableAudioTrackPlaybackParams(enableAudioTrackPlaybackParams) .setEnableAudioTrackPlaybackParams(enableAudioTrackPlaybackParams)
@ -1592,7 +1599,7 @@ public final class DefaultAudioSink implements AudioSink {
} }
private static boolean isPassthroughPlaybackSupported( private static boolean isPassthroughPlaybackSupported(
Format format, @Nullable AudioCapabilities audioCapabilities) { Format format, AudioCapabilities audioCapabilities) {
return getEncodingAndChannelConfigForPassthrough(format, audioCapabilities) != null; return getEncodingAndChannelConfigForPassthrough(format, audioCapabilities) != null;
} }
@ -1608,11 +1615,7 @@ public final class DefaultAudioSink implements AudioSink {
*/ */
@Nullable @Nullable
private static Pair<Integer, Integer> getEncodingAndChannelConfigForPassthrough( private static Pair<Integer, Integer> getEncodingAndChannelConfigForPassthrough(
Format format, @Nullable AudioCapabilities audioCapabilities) { Format format, AudioCapabilities audioCapabilities) {
if (audioCapabilities == null) {
return null;
}
@C.Encoding @C.Encoding
int encoding = MimeTypes.getEncoding(checkNotNull(format.sampleMimeType), format.codecs); int encoding = MimeTypes.getEncoding(checkNotNull(format.sampleMimeType), format.codecs);
// Check for encodings that are known to work for passthrough with the implementation in this // Check for encodings that are known to work for passthrough with the implementation in this

View File

@ -18,6 +18,7 @@ package com.google.android.exoplayer2.audio;
import static com.google.android.exoplayer2.decoder.DecoderReuseEvaluation.DISCARD_REASON_MAX_INPUT_SIZE_EXCEEDED; import static com.google.android.exoplayer2.decoder.DecoderReuseEvaluation.DISCARD_REASON_MAX_INPUT_SIZE_EXCEEDED;
import static com.google.android.exoplayer2.decoder.DecoderReuseEvaluation.REUSE_RESULT_NO; import static com.google.android.exoplayer2.decoder.DecoderReuseEvaluation.REUSE_RESULT_NO;
import static com.google.android.exoplayer2.util.Assertions.checkNotNull; import static com.google.android.exoplayer2.util.Assertions.checkNotNull;
import static com.google.common.base.MoreObjects.firstNonNull;
import static java.lang.Math.max; import static java.lang.Math.max;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
@ -129,7 +130,12 @@ public class MediaCodecAudioRenderer extends MediaCodecRenderer implements Media
MediaCodecSelector mediaCodecSelector, MediaCodecSelector mediaCodecSelector,
@Nullable Handler eventHandler, @Nullable Handler eventHandler,
@Nullable AudioRendererEventListener eventListener) { @Nullable AudioRendererEventListener eventListener) {
this(context, mediaCodecSelector, eventHandler, eventListener, (AudioCapabilities) null); this(
context,
mediaCodecSelector,
eventHandler,
eventListener,
AudioCapabilities.DEFAULT_AUDIO_CAPABILITIES);
} }
/** /**
@ -138,8 +144,9 @@ public class MediaCodecAudioRenderer extends MediaCodecRenderer implements Media
* @param eventHandler A handler to use when delivering events to {@code eventListener}. May be * @param eventHandler A handler to use when delivering events to {@code eventListener}. May be
* null if delivery of events is not required. * null if delivery of events is not required.
* @param eventListener A listener of events. May be null if delivery of events is not required. * @param eventListener A listener of events. May be null if delivery of events is not required.
* @param audioCapabilities The audio capabilities for playback on this device. May be null if the * @param audioCapabilities The audio capabilities for playback on this device. Use {@link
* default capabilities (no encoded audio passthrough support) should be assumed. * AudioCapabilities#DEFAULT_AUDIO_CAPABILITIES} if default capabilities (no encoded audio
* passthrough support) should be assumed.
* @param audioProcessors Optional {@link AudioProcessor}s that will process PCM audio before * @param audioProcessors Optional {@link AudioProcessor}s that will process PCM audio before
* output. * output.
*/ */
@ -148,7 +155,7 @@ public class MediaCodecAudioRenderer extends MediaCodecRenderer implements Media
MediaCodecSelector mediaCodecSelector, MediaCodecSelector mediaCodecSelector,
@Nullable Handler eventHandler, @Nullable Handler eventHandler,
@Nullable AudioRendererEventListener eventListener, @Nullable AudioRendererEventListener eventListener,
@Nullable AudioCapabilities audioCapabilities, AudioCapabilities audioCapabilities,
AudioProcessor... audioProcessors) { AudioProcessor... audioProcessors) {
this( this(
context, context,
@ -156,7 +163,8 @@ public class MediaCodecAudioRenderer extends MediaCodecRenderer implements Media
eventHandler, eventHandler,
eventListener, eventListener,
new DefaultAudioSink.Builder() new DefaultAudioSink.Builder()
.setAudioCapabilities(audioCapabilities) .setAudioCapabilities( // For backward compatibility, null == default.
firstNonNull(audioCapabilities, AudioCapabilities.DEFAULT_AUDIO_CAPABILITIES))
.setAudioProcessors(audioProcessors) .setAudioProcessors(audioProcessors)
.build()); .build());
} }

View File

@ -15,7 +15,6 @@
*/ */
package com.google.android.exoplayer2.audio; package com.google.android.exoplayer2.audio;
import static com.google.android.exoplayer2.audio.AudioCapabilities.DEFAULT_AUDIO_CAPABILITIES;
import static com.google.android.exoplayer2.audio.AudioSink.CURRENT_POSITION_NOT_SET; import static com.google.android.exoplayer2.audio.AudioSink.CURRENT_POSITION_NOT_SET;
import static com.google.android.exoplayer2.audio.AudioSink.SINK_FORMAT_SUPPORTED_DIRECTLY; import static com.google.android.exoplayer2.audio.AudioSink.SINK_FORMAT_SUPPORTED_DIRECTLY;
import static com.google.android.exoplayer2.audio.AudioSink.SINK_FORMAT_SUPPORTED_WITH_TRANSCODING; import static com.google.android.exoplayer2.audio.AudioSink.SINK_FORMAT_SUPPORTED_WITH_TRANSCODING;
@ -61,7 +60,6 @@ public final class DefaultAudioSinkTest {
TeeAudioProcessor teeAudioProcessor = new TeeAudioProcessor(arrayAudioBufferSink); TeeAudioProcessor teeAudioProcessor = new TeeAudioProcessor(arrayAudioBufferSink);
defaultAudioSink = defaultAudioSink =
new DefaultAudioSink.Builder() new DefaultAudioSink.Builder()
.setAudioCapabilities(DEFAULT_AUDIO_CAPABILITIES)
.setAudioProcessorChain(new DefaultAudioProcessorChain(teeAudioProcessor)) .setAudioProcessorChain(new DefaultAudioProcessorChain(teeAudioProcessor))
.setOffloadMode(DefaultAudioSink.OFFLOAD_MODE_DISABLED) .setOffloadMode(DefaultAudioSink.OFFLOAD_MODE_DISABLED)
.build(); .build();
@ -70,10 +68,7 @@ public final class DefaultAudioSinkTest {
@Test @Test
public void handlesSpecializedAudioProcessorArray() { public void handlesSpecializedAudioProcessorArray() {
defaultAudioSink = defaultAudioSink =
new DefaultAudioSink.Builder() new DefaultAudioSink.Builder().setAudioProcessors(new TeeAudioProcessor[0]).build();
.setAudioCapabilities(DEFAULT_AUDIO_CAPABILITIES)
.setAudioProcessors(new TeeAudioProcessor[0])
.build();
} }
@Test @Test
@ -204,8 +199,7 @@ public final class DefaultAudioSinkTest {
@Test @Test
public void floatPcmNeedsTranscodingIfFloatOutputDisabled() { public void floatPcmNeedsTranscodingIfFloatOutputDisabled() {
defaultAudioSink = defaultAudioSink = new DefaultAudioSink.Builder().build();
new DefaultAudioSink.Builder().setAudioCapabilities(DEFAULT_AUDIO_CAPABILITIES).build();
Format floatFormat = Format floatFormat =
STEREO_44_1_FORMAT STEREO_44_1_FORMAT
.buildUpon() .buildUpon()
@ -219,11 +213,7 @@ public final class DefaultAudioSinkTest {
@Config(maxSdk = 20) @Config(maxSdk = 20)
@Test @Test
public void floatPcmNeedsTranscodingIfFloatOutputEnabledBeforeApi21() { public void floatPcmNeedsTranscodingIfFloatOutputEnabledBeforeApi21() {
defaultAudioSink = defaultAudioSink = new DefaultAudioSink.Builder().setEnableFloatOutput(true).build();
new DefaultAudioSink.Builder()
.setAudioCapabilities(DEFAULT_AUDIO_CAPABILITIES)
.setEnableFloatOutput(true)
.build();
Format floatFormat = Format floatFormat =
STEREO_44_1_FORMAT STEREO_44_1_FORMAT
.buildUpon() .buildUpon()
@ -237,11 +227,7 @@ public final class DefaultAudioSinkTest {
@Config(minSdk = 21) @Config(minSdk = 21)
@Test @Test
public void floatOutputSupportedIfFloatOutputEnabledFromApi21() { public void floatOutputSupportedIfFloatOutputEnabledFromApi21() {
defaultAudioSink = defaultAudioSink = new DefaultAudioSink.Builder().setEnableFloatOutput(true).build();
new DefaultAudioSink.Builder()
.setAudioCapabilities(DEFAULT_AUDIO_CAPABILITIES)
.setEnableFloatOutput(true)
.build();
Format floatFormat = Format floatFormat =
STEREO_44_1_FORMAT STEREO_44_1_FORMAT
.buildUpon() .buildUpon()