PiperOrigin-RevId: 702960045
This commit is contained in:
Googler 2024-12-04 20:33:19 -08:00 committed by Copybara-Service
parent f60d2b4146
commit 5ab9a7856f
5 changed files with 53 additions and 67 deletions

View file

@ -36,8 +36,6 @@
([#1904](https://github.com/androidx/media/issues/1904)). ([#1904](https://github.com/androidx/media/issues/1904)).
* DataSource: * DataSource:
* Audio: * Audio:
* Do not bypass `SonicAudioProcessor` when `SpeedChangingAudioProcessor`
is configured with default parameters.
* Video: * Video:
* Rollback of using `MediaCodecAdapter` supplied pixel aspect ratio values * Rollback of using `MediaCodecAdapter` supplied pixel aspect ratio values
when provided while processing `onOutputFormatChanged` when provided while processing `onOutputFormatChanged`

View file

@ -15,11 +15,8 @@
*/ */
package androidx.media3.common.audio; package androidx.media3.common.audio;
import static androidx.media3.common.util.Assertions.checkArgument;
import static androidx.media3.common.util.Assertions.checkNotNull; import static androidx.media3.common.util.Assertions.checkNotNull;
import static java.lang.Math.abs;
import androidx.annotation.FloatRange;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.media3.common.C; import androidx.media3.common.C;
import androidx.media3.common.Format; import androidx.media3.common.Format;
@ -47,8 +44,6 @@ public class SonicAudioProcessor implements AudioProcessor {
*/ */
private static final int MIN_BYTES_FOR_DURATION_SCALING_CALCULATION = 1024; private static final int MIN_BYTES_FOR_DURATION_SCALING_CALCULATION = 1024;
private final boolean shouldBeActiveWithDefaultParameters;
private int pendingOutputSampleRate; private int pendingOutputSampleRate;
private float speed; private float speed;
private float pitch; private float pitch;
@ -69,17 +64,6 @@ public class SonicAudioProcessor implements AudioProcessor {
/** Creates a new Sonic audio processor. */ /** Creates a new Sonic audio processor. */
public SonicAudioProcessor() { public SonicAudioProcessor() {
this(/* keepActiveWithDefaultParameters= */ false);
}
/**
* Creates a new instance of {@link SonicAudioProcessor}.
*
* <p>If {@code keepActiveWithDefaultParameters} is set to {@code true}, then {@link #isActive()}
* returns {@code true} when parameters have been configured to default values that result in
* no-op processing.
*/
/* package */ SonicAudioProcessor(boolean keepActiveWithDefaultParameters) {
speed = 1f; speed = 1f;
pitch = 1f; pitch = 1f;
pendingInputAudioFormat = AudioFormat.NOT_SET; pendingInputAudioFormat = AudioFormat.NOT_SET;
@ -90,7 +74,6 @@ public class SonicAudioProcessor implements AudioProcessor {
shortBuffer = buffer.asShortBuffer(); shortBuffer = buffer.asShortBuffer();
outputBuffer = EMPTY_BUFFER; outputBuffer = EMPTY_BUFFER;
pendingOutputSampleRate = SAMPLE_RATE_NO_CHANGE; pendingOutputSampleRate = SAMPLE_RATE_NO_CHANGE;
shouldBeActiveWithDefaultParameters = keepActiveWithDefaultParameters;
} }
/** /**
@ -100,8 +83,7 @@ public class SonicAudioProcessor implements AudioProcessor {
* *
* @param speed The target factor by which playback should be sped up. * @param speed The target factor by which playback should be sped up.
*/ */
public final void setSpeed(@FloatRange(from = 0f, fromInclusive = false) float speed) { public final void setSpeed(float speed) {
checkArgument(speed > 0f);
if (this.speed != speed) { if (this.speed != speed) {
this.speed = speed; this.speed = speed;
pendingSonicRecreation = true; pendingSonicRecreation = true;
@ -115,8 +97,7 @@ public class SonicAudioProcessor implements AudioProcessor {
* *
* @param pitch The target pitch. * @param pitch The target pitch.
*/ */
public final void setPitch(@FloatRange(from = 0f, fromInclusive = false) float pitch) { public final void setPitch(float pitch) {
checkArgument(pitch > 0f);
if (this.pitch != pitch) { if (this.pitch != pitch) {
this.pitch = pitch; this.pitch = pitch;
pendingSonicRecreation = true; pendingSonicRecreation = true;
@ -132,7 +113,6 @@ public class SonicAudioProcessor implements AudioProcessor {
* @see #configure(AudioFormat) * @see #configure(AudioFormat)
*/ */
public final void setOutputSampleRateHz(int sampleRateHz) { public final void setOutputSampleRateHz(int sampleRateHz) {
checkArgument(sampleRateHz == SAMPLE_RATE_NO_CHANGE || sampleRateHz > 0);
pendingOutputSampleRate = sampleRateHz; pendingOutputSampleRate = sampleRateHz;
} }
@ -216,13 +196,9 @@ public class SonicAudioProcessor implements AudioProcessor {
@Override @Override
public final boolean isActive() { public final boolean isActive() {
return pendingOutputAudioFormat.sampleRate != Format.NO_VALUE return pendingOutputAudioFormat.sampleRate != Format.NO_VALUE
&& (shouldBeActiveWithDefaultParameters || !areParametersSetToDefaultValues()); && (Math.abs(speed - 1f) >= CLOSE_THRESHOLD
} || Math.abs(pitch - 1f) >= CLOSE_THRESHOLD
|| pendingOutputAudioFormat.sampleRate != pendingInputAudioFormat.sampleRate);
private boolean areParametersSetToDefaultValues() {
return abs(speed - 1f) < CLOSE_THRESHOLD
&& abs(pitch - 1f) < CLOSE_THRESHOLD
&& pendingOutputAudioFormat.sampleRate == pendingInputAudioFormat.sampleRate;
} }
@Override @Override

View file

@ -24,7 +24,6 @@ import static androidx.media3.common.util.Util.sampleCountToDurationUs;
import static java.lang.Math.min; import static java.lang.Math.min;
import static java.lang.Math.round; import static java.lang.Math.round;
import android.annotation.SuppressLint;
import androidx.annotation.GuardedBy; import androidx.annotation.GuardedBy;
import androidx.annotation.IntRange; import androidx.annotation.IntRange;
import androidx.media3.common.C; import androidx.media3.common.C;
@ -100,8 +99,7 @@ public final class SpeedChangingAudioProcessor extends BaseAudioProcessor {
public SpeedChangingAudioProcessor(SpeedProvider speedProvider) { public SpeedChangingAudioProcessor(SpeedProvider speedProvider) {
this.speedProvider = speedProvider; this.speedProvider = speedProvider;
lock = new Object(); lock = new Object();
sonicAudioProcessor = sonicAudioProcessor = new SynchronizedSonicAudioProcessor(lock);
new SynchronizedSonicAudioProcessor(lock, /* keepActiveWithDefaultParameters= */ true);
pendingCallbackInputTimesUs = new LongArrayQueue(); pendingCallbackInputTimesUs = new LongArrayQueue();
pendingCallbacks = new ArrayDeque<>(); pendingCallbacks = new ArrayDeque<>();
speedAdjustedTimeAsyncInputTimeUs = C.TIME_UNSET; speedAdjustedTimeAsyncInputTimeUs = C.TIME_UNSET;
@ -176,11 +174,19 @@ public final class SpeedChangingAudioProcessor extends BaseAudioProcessor {
} }
long startPosition = inputBuffer.position(); long startPosition = inputBuffer.position();
sonicAudioProcessor.queueInput(inputBuffer); if (isUsingSonic()) {
if (bytesToNextSpeedChange != C.LENGTH_UNSET sonicAudioProcessor.queueInput(inputBuffer);
&& (inputBuffer.position() - startPosition) == bytesToNextSpeedChange) { if (bytesToNextSpeedChange != C.LENGTH_UNSET
sonicAudioProcessor.queueEndOfStream(); && (inputBuffer.position() - startPosition) == bytesToNextSpeedChange) {
endOfStreamQueuedToSonic = true; sonicAudioProcessor.queueEndOfStream();
endOfStreamQueuedToSonic = true;
}
} else {
ByteBuffer buffer = replaceOutputBuffer(/* size= */ inputBuffer.remaining());
if (inputBuffer.hasRemaining()) {
buffer.put(inputBuffer);
}
buffer.flip();
} }
long bytesRead = inputBuffer.position() - startPosition; long bytesRead = inputBuffer.position() - startPosition;
checkState( checkState(
@ -198,11 +204,9 @@ public final class SpeedChangingAudioProcessor extends BaseAudioProcessor {
} }
} }
// Not using BaseAudioProcessor's buffers.
@SuppressLint("MissingSuperCall")
@Override @Override
public ByteBuffer getOutput() { public ByteBuffer getOutput() {
ByteBuffer output = sonicAudioProcessor.getOutput(); ByteBuffer output = isUsingSonic() ? sonicAudioProcessor.getOutput() : super.getOutput();
processPendingCallbacks(); processPendingCallbacks();
return output; return output;
} }
@ -347,8 +351,10 @@ public final class SpeedChangingAudioProcessor extends BaseAudioProcessor {
if (newSpeed != currentSpeed) { if (newSpeed != currentSpeed) {
updateSpeedChangeArrays(timeUs); updateSpeedChangeArrays(timeUs);
currentSpeed = newSpeed; currentSpeed = newSpeed;
sonicAudioProcessor.setSpeed(newSpeed); if (isUsingSonic()) {
sonicAudioProcessor.setPitch(newSpeed); sonicAudioProcessor.setSpeed(newSpeed);
sonicAudioProcessor.setPitch(newSpeed);
}
// Invalidate any previously created buffers in SonicAudioProcessor and the base class. // Invalidate any previously created buffers in SonicAudioProcessor and the base class.
sonicAudioProcessor.flush(); sonicAudioProcessor.flush();
endOfStreamQueuedToSonic = false; endOfStreamQueuedToSonic = false;
@ -372,25 +378,39 @@ public final class SpeedChangingAudioProcessor extends BaseAudioProcessor {
} }
private long getPlayoutDurationUsAtCurrentSpeed(long mediaDurationUs) { private long getPlayoutDurationUsAtCurrentSpeed(long mediaDurationUs) {
return sonicAudioProcessor.getPlayoutDuration(mediaDurationUs); return isUsingSonic()
? sonicAudioProcessor.getPlayoutDuration(mediaDurationUs)
: mediaDurationUs;
} }
private long getMediaDurationUsAtCurrentSpeed(long playoutDurationUs) { private long getMediaDurationUsAtCurrentSpeed(long playoutDurationUs) {
return sonicAudioProcessor.getMediaDuration(playoutDurationUs); return isUsingSonic()
? sonicAudioProcessor.getMediaDuration(playoutDurationUs)
: playoutDurationUs;
} }
private void updateLastProcessedInputTime() { private void updateLastProcessedInputTime() {
synchronized (lock) { synchronized (lock) {
// TODO - b/320242819: Investigate whether bytesRead can be used here rather than if (isUsingSonic()) {
// sonicAudioProcessor.getProcessedInputBytes(). // TODO - b/320242819: Investigate whether bytesRead can be used here rather than
long currentProcessedInputDurationUs = // sonicAudioProcessor.getProcessedInputBytes().
Util.scaleLargeTimestamp( long currentProcessedInputDurationUs =
/* timestamp= */ sonicAudioProcessor.getProcessedInputBytes(), Util.scaleLargeTimestamp(
/* multiplier= */ C.MICROS_PER_SECOND, /* timestamp= */ sonicAudioProcessor.getProcessedInputBytes(),
/* divisor= */ (long) inputAudioFormat.sampleRate * inputAudioFormat.bytesPerFrame); /* multiplier= */ C.MICROS_PER_SECOND,
lastProcessedInputTimeUs = /* divisor= */ (long) inputAudioFormat.sampleRate * inputAudioFormat.bytesPerFrame);
inputSegmentStartTimesUs.get(inputSegmentStartTimesUs.size() - 1) lastProcessedInputTimeUs =
+ currentProcessedInputDurationUs; inputSegmentStartTimesUs.get(inputSegmentStartTimesUs.size() - 1)
+ currentProcessedInputDurationUs;
} else {
lastProcessedInputTimeUs = sampleCountToDurationUs(framesRead, inputAudioFormat.sampleRate);
}
}
}
private boolean isUsingSonic() {
synchronized (lock) {
return currentSpeed != 1f;
} }
} }

View file

@ -26,9 +26,9 @@ import java.nio.ByteBuffer;
private final Object lock; private final Object lock;
private final SonicAudioProcessor sonicAudioProcessor; private final SonicAudioProcessor sonicAudioProcessor;
public SynchronizedSonicAudioProcessor(Object lock, boolean keepActiveWithDefaultParameters) { public SynchronizedSonicAudioProcessor(Object lock) {
this.lock = lock; this.lock = lock;
sonicAudioProcessor = new SonicAudioProcessor(keepActiveWithDefaultParameters); sonicAudioProcessor = new SonicAudioProcessor();
} }
public final void setSpeed(float speed) { public final void setSpeed(float speed) {

View file

@ -86,19 +86,11 @@ public final class SonicAudioProcessorTest {
} }
@Test @Test
public void isActive_withDefaultParameters_returnsFalse() throws Exception { public void isNotActiveWithNoChange() throws Exception {
sonicAudioProcessor.configure(AUDIO_FORMAT_44100_HZ); sonicAudioProcessor.configure(AUDIO_FORMAT_44100_HZ);
assertThat(sonicAudioProcessor.isActive()).isFalse(); assertThat(sonicAudioProcessor.isActive()).isFalse();
} }
@Test
public void isActive_keepActiveWithDefaultParameters_returnsTrue() throws Exception {
SonicAudioProcessor processor =
new SonicAudioProcessor(/* keepActiveWithDefaultParameters= */ true);
processor.configure(AUDIO_FORMAT_44100_HZ);
assertThat(processor.isActive()).isTrue();
}
@Test @Test
public void doesNotSupportNon16BitInput() throws Exception { public void doesNotSupportNon16BitInput() throws Exception {
try { try {