Propagate PCM encoding passed to AudioSamplePipeline.

PiperOrigin-RevId: 511810757
This commit is contained in:
samrobinson 2023-02-23 17:40:54 +00:00 committed by tonihei
parent cc1ca860b1
commit a6932f9bdd
2 changed files with 25 additions and 13 deletions

View File

@ -20,6 +20,7 @@ import static androidx.media3.common.util.Assertions.checkNotNull;
import static androidx.media3.common.util.Assertions.checkState; import static androidx.media3.common.util.Assertions.checkState;
import static androidx.media3.decoder.DecoderInputBuffer.BUFFER_REPLACEMENT_MODE_DIRECT; import static androidx.media3.decoder.DecoderInputBuffer.BUFFER_REPLACEMENT_MODE_DIRECT;
import static androidx.media3.decoder.DecoderInputBuffer.BUFFER_REPLACEMENT_MODE_DISABLED; import static androidx.media3.decoder.DecoderInputBuffer.BUFFER_REPLACEMENT_MODE_DISABLED;
import static androidx.media3.transformer.DefaultCodec.DEFAULT_PCM_ENCODING;
import static java.lang.Math.min; import static java.lang.Math.min;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
@ -92,13 +93,14 @@ import org.checkerframework.dataflow.qual.Pure;
} }
audioProcessingPipeline = new AudioProcessingPipeline(audioProcessors); audioProcessingPipeline = new AudioProcessingPipeline(audioProcessors);
// TODO(b/267301878): Once decoder format propagated, remove setting default PCM encoding.
AudioFormat pipelineInputAudioFormat = AudioFormat pipelineInputAudioFormat =
new AudioFormat( new AudioFormat(
firstInputFormat.sampleRate, firstInputFormat.sampleRate,
firstInputFormat.channelCount, firstInputFormat.channelCount,
// The decoder uses ENCODING_PCM_16BIT by default. firstInputFormat.pcmEncoding != Format.NO_VALUE
// https://developer.android.com/reference/android/media/MediaCodec#raw-audio-buffers ? firstInputFormat.pcmEncoding
C.ENCODING_PCM_16BIT); : DEFAULT_PCM_ENCODING);
try { try {
encoderInputAudioFormat = audioProcessingPipeline.configure(pipelineInputAudioFormat); encoderInputAudioFormat = audioProcessingPipeline.configure(pipelineInputAudioFormat);
@ -117,6 +119,7 @@ import org.checkerframework.dataflow.qual.Pure;
: checkNotNull(firstInputFormat.sampleMimeType)) : checkNotNull(firstInputFormat.sampleMimeType))
.setSampleRate(encoderInputAudioFormat.sampleRate) .setSampleRate(encoderInputAudioFormat.sampleRate)
.setChannelCount(encoderInputAudioFormat.channelCount) .setChannelCount(encoderInputAudioFormat.channelCount)
.setPcmEncoding(encoderInputAudioFormat.encoding)
.setAverageBitrate(DEFAULT_ENCODER_BITRATE) .setAverageBitrate(DEFAULT_ENCODER_BITRATE)
.build(); .build();

View File

@ -52,13 +52,12 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
/** A default {@link Codec} implementation that uses {@link MediaCodec}. */ /** A default {@link Codec} implementation that uses {@link MediaCodec}. */
@UnstableApi @UnstableApi
public final class DefaultCodec implements Codec { public final class DefaultCodec implements Codec {
// MediaCodec decoders output 16 bit PCM, unless configured to output PCM float.
// https://developer.android.com/reference/android/media/MediaCodec#raw-audio-buffers.
public static final int DEFAULT_PCM_ENCODING = C.ENCODING_PCM_16BIT;
private static final String TAG = "DefaultCodec"; private static final String TAG = "DefaultCodec";
// MediaCodec decoders always output 16 bit PCM, unless configured to output PCM float.
// https://developer.android.com/reference/android/media/MediaCodec#raw-audio-buffers.
private static final int MEDIA_CODEC_PCM_ENCODING = C.ENCODING_PCM_16BIT;
private final BufferInfo outputBufferInfo; private final BufferInfo outputBufferInfo;
/** The {@link MediaFormat} used to configure the underlying {@link MediaCodec}. */ /** The {@link MediaFormat} used to configure the underlying {@link MediaCodec}. */
private final MediaFormat configurationMediaFormat; private final MediaFormat configurationMediaFormat;
@ -325,7 +324,7 @@ public final class DefaultCodec implements Codec {
} }
if (outputBufferIndex < 0) { if (outputBufferIndex < 0) {
if (outputBufferIndex == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) { if (outputBufferIndex == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
outputFormat = convertToFormat(mediaCodec.getOutputFormat()); outputFormat = convertToFormat(mediaCodec.getOutputFormat(), isDecoder);
ColorInfo expectedColorInfo = ColorInfo expectedColorInfo =
isSdrToneMappingEnabled(configurationMediaFormat) isSdrToneMappingEnabled(configurationMediaFormat)
? ColorInfo.SDR_BT709_LIMITED ? ColorInfo.SDR_BT709_LIMITED
@ -402,7 +401,7 @@ public final class DefaultCodec implements Codec {
return transfer1 == transfer2; return transfer1 == transfer2;
} }
private static Format convertToFormat(MediaFormat mediaFormat) { private static Format convertToFormat(MediaFormat mediaFormat, boolean isDecoder) {
ImmutableList.Builder<byte[]> csdBuffers = new ImmutableList.Builder<>(); ImmutableList.Builder<byte[]> csdBuffers = new ImmutableList.Builder<>();
int csdIndex = 0; int csdIndex = 0;
while (true) { while (true) {
@ -424,12 +423,22 @@ public final class DefaultCodec implements Codec {
.setHeight(mediaFormat.getInteger(MediaFormat.KEY_HEIGHT)) .setHeight(mediaFormat.getInteger(MediaFormat.KEY_HEIGHT))
.setColorInfo(MediaFormatUtil.getColorInfo(mediaFormat)); .setColorInfo(MediaFormatUtil.getColorInfo(mediaFormat));
} else if (MimeTypes.isAudio(mimeType)) { } else if (MimeTypes.isAudio(mimeType)) {
// TODO(b/178685617): Only set the PCM encoding for audio/raw, once we have a way to
// simulate more realistic codec input/output formats in tests.
formatBuilder formatBuilder
.setChannelCount(mediaFormat.getInteger(MediaFormat.KEY_CHANNEL_COUNT)) .setChannelCount(mediaFormat.getInteger(MediaFormat.KEY_CHANNEL_COUNT))
.setSampleRate(mediaFormat.getInteger(MediaFormat.KEY_SAMPLE_RATE)) .setSampleRate(mediaFormat.getInteger(MediaFormat.KEY_SAMPLE_RATE));
.setPcmEncoding(MEDIA_CODEC_PCM_ENCODING);
if (SDK_INT >= 24 && mediaFormat.containsKey(MediaFormat.KEY_PCM_ENCODING)) {
formatBuilder.setPcmEncoding(mediaFormat.getInteger(MediaFormat.KEY_PCM_ENCODING));
} else if (isDecoder) {
// TODO(b/178685617): Restrict this to only set the PCM encoding for audio/raw once we have
// a way to simulate more realistic codec input/output formats in tests.
// With Robolectric, codecs do not actually encode/decode. The format of buffers is passed
// through. However downstream components need to know the PCM encoding of the data being
// output, so if a decoder is not outputting raw audio, we need to set the PCM
// encoding to the default.
formatBuilder.setPcmEncoding(DEFAULT_PCM_ENCODING);
}
} }
return formatBuilder.build(); return formatBuilder.build();
} }