|
43 | 43 | import com.google.android.exoplayer2.Format;
|
44 | 44 | import com.google.android.exoplayer2.MediaItem;
|
45 | 45 | import com.google.android.exoplayer2.audio.AudioProcessor;
|
| 46 | +import com.google.android.exoplayer2.audio.AudioProcessor.AudioFormat; |
| 47 | +import com.google.android.exoplayer2.audio.ChannelMixingAudioProcessor; |
| 48 | +import com.google.android.exoplayer2.audio.ChannelMixingMatrix; |
46 | 49 | import com.google.android.exoplayer2.audio.SonicAudioProcessor;
|
| 50 | +import com.google.android.exoplayer2.audio.TeeAudioProcessor; |
47 | 51 | import com.google.android.exoplayer2.effect.Contrast;
|
48 | 52 | import com.google.android.exoplayer2.effect.DefaultGlObjectsProvider;
|
49 | 53 | import com.google.android.exoplayer2.effect.DefaultVideoFrameProcessor;
|
|
57 | 61 | import com.google.android.exoplayer2.util.OnInputFrameProcessedListener;
|
58 | 62 | import com.google.android.exoplayer2.util.VideoFrameProcessingException;
|
59 | 63 | import com.google.common.collect.ImmutableList;
|
| 64 | +import com.google.common.collect.ImmutableSet; |
| 65 | +import java.nio.ByteBuffer; |
60 | 66 | import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
61 | 67 | import org.junit.Test;
|
62 | 68 | import org.junit.runner.RunWith;
|
@@ -627,6 +633,60 @@ public void loopingImage_producesExpectedResult() throws Exception {
|
627 | 633 | assertThat(result.exportResult.durationMs).isEqualTo(3100);
|
628 | 634 | }
|
629 | 635 |
|
| 636 | + @Test |
| 637 | + public void audioTranscode_processesInInt16Pcm() throws Exception { |
| 638 | + String testId = "audioTranscode_processesInInt16Pcm"; |
| 639 | + FormatTrackingAudioBufferSink audioFormatTracker = new FormatTrackingAudioBufferSink(); |
| 640 | + |
| 641 | + Transformer transformer = new Transformer.Builder(context).build(); |
| 642 | + EditedMediaItem editedMediaItem = |
| 643 | + new EditedMediaItem.Builder(MediaItem.fromUri(Uri.parse(MP4_ASSET_URI_STRING))) |
| 644 | + .setEffects( |
| 645 | + new Effects( |
| 646 | + ImmutableList.of(audioFormatTracker.createTeeAudioProcessor()), |
| 647 | + /* videoEffects= */ ImmutableList.of())) |
| 648 | + .setRemoveVideo(true) |
| 649 | + .build(); |
| 650 | + |
| 651 | + new TransformerAndroidTestRunner.Builder(context, transformer) |
| 652 | + .build() |
| 653 | + .run(testId, editedMediaItem); |
| 654 | + |
| 655 | + ImmutableList<AudioFormat> audioFormats = audioFormatTracker.getFlushedAudioFormats(); |
| 656 | + assertThat(audioFormats).hasSize(1); |
| 657 | + assertThat(audioFormats.get(0).encoding).isEqualTo(C.ENCODING_PCM_16BIT); |
| 658 | + } |
| 659 | + |
| 660 | + @Test |
| 661 | + public void audioEditing_monoToStereo_outputsStereo() throws Exception { |
| 662 | + String testId = "audioEditing_monoToStereo_outputsStereo"; |
| 663 | + |
| 664 | + ChannelMixingAudioProcessor channelMixingAudioProcessor = new ChannelMixingAudioProcessor(); |
| 665 | + channelMixingAudioProcessor.putChannelMixingMatrix( |
| 666 | + ChannelMixingMatrix.create(/* inputChannelCount= */ 1, /* outputChannelCount= */ 2)); |
| 667 | + EditedMediaItem editedMediaItem = |
| 668 | + new EditedMediaItem.Builder(MediaItem.fromUri(Uri.parse(MP4_ASSET_URI_STRING))) |
| 669 | + .setRemoveVideo(true) |
| 670 | + .setEffects( |
| 671 | + new Effects( |
| 672 | + ImmutableList.of(channelMixingAudioProcessor), |
| 673 | + /* videoEffects= */ ImmutableList.of())) |
| 674 | + .build(); |
| 675 | + |
| 676 | + ExportTestResult result = |
| 677 | + new TransformerAndroidTestRunner.Builder(context, new Transformer.Builder(context).build()) |
| 678 | + .build() |
| 679 | + .run(testId, editedMediaItem); |
| 680 | + |
| 681 | + assertThat(result.exportResult.channelCount).isEqualTo(2); |
| 682 | + } |
| 683 | + |
| 684 | + private static AudioProcessor createSonic(float pitch) { |
| 685 | + SonicAudioProcessor sonic = new SonicAudioProcessor(); |
| 686 | + sonic.setPitch(pitch); |
| 687 | + return sonic; |
| 688 | + } |
| 689 | + |
630 | 690 | private final class TestTextureAssetLoaderFactory implements AssetLoader.Factory {
|
631 | 691 |
|
632 | 692 | private final int width;
|
@@ -690,9 +750,30 @@ public boolean videoNeedsEncoding() {
|
690 | 750 | }
|
691 | 751 | }
|
692 | 752 |
|
693 |
| - private static AudioProcessor createSonic(float pitch) { |
694 |
| - SonicAudioProcessor sonic = new SonicAudioProcessor(); |
695 |
| - sonic.setPitch(pitch); |
696 |
| - return sonic; |
| 753 | + private static final class FormatTrackingAudioBufferSink |
| 754 | + implements TeeAudioProcessor.AudioBufferSink { |
| 755 | + private final ImmutableSet.Builder<AudioFormat> flushedAudioFormats; |
| 756 | + |
| 757 | + public FormatTrackingAudioBufferSink() { |
| 758 | + this.flushedAudioFormats = new ImmutableSet.Builder<>(); |
| 759 | + } |
| 760 | + |
| 761 | + public TeeAudioProcessor createTeeAudioProcessor() { |
| 762 | + return new TeeAudioProcessor(this); |
| 763 | + } |
| 764 | + |
| 765 | + @Override |
| 766 | + public void flush(int sampleRateHz, int channelCount, @C.PcmEncoding int encoding) { |
| 767 | + flushedAudioFormats.add(new AudioFormat(sampleRateHz, channelCount, encoding)); |
| 768 | + } |
| 769 | + |
| 770 | + @Override |
| 771 | + public void handleBuffer(ByteBuffer buffer) { |
| 772 | + // Do nothing. |
| 773 | + } |
| 774 | + |
| 775 | + public ImmutableList<AudioFormat> getFlushedAudioFormats() { |
| 776 | + return flushedAudioFormats.build().asList(); |
| 777 | + } |
697 | 778 | }
|
698 | 779 | }
|
0 commit comments