From e6527ec1dd9a780bc9a6d0bbfbed97f0aa173726 Mon Sep 17 00:00:00 2001 From: kimvde Date: Wed, 4 Jan 2023 14:26:45 +0000 Subject: [PATCH] Merge BaseSamplePipeline and SamplePipeline PiperOrigin-RevId: 499469006 --- .../AudioTranscodingSamplePipeline.java | 2 +- .../transformer/BaseSamplePipeline.java | 123 ------------------ .../PassthroughSamplePipeline.java | 7 +- .../transformer/SamplePipeline.java | 109 +++++++++++++++- .../VideoTranscodingSamplePipeline.java | 7 +- 5 files changed, 108 insertions(+), 140 deletions(-) delete mode 100644 library/transformer/src/main/java/com/google/android/exoplayer2/transformer/BaseSamplePipeline.java diff --git a/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/AudioTranscodingSamplePipeline.java b/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/AudioTranscodingSamplePipeline.java index a98639f338..55105ea30c 100644 --- a/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/AudioTranscodingSamplePipeline.java +++ b/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/AudioTranscodingSamplePipeline.java @@ -36,7 +36,7 @@ import org.checkerframework.checker.nullness.qual.EnsuresNonNullIf; import org.checkerframework.dataflow.qual.Pure; /** Pipeline to process, re-encode and mux raw audio samples. */ -/* package */ final class AudioTranscodingSamplePipeline extends BaseSamplePipeline { +/* package */ final class AudioTranscodingSamplePipeline extends SamplePipeline { private static final int DEFAULT_ENCODER_BITRATE = 128 * 1024; diff --git a/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/BaseSamplePipeline.java b/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/BaseSamplePipeline.java deleted file mode 100644 index a2ff9e7f63..0000000000 --- a/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/BaseSamplePipeline.java +++ /dev/null @@ -1,123 +0,0 @@ -/* - * Copyright 2022 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.android.exoplayer2.transformer; - -import static com.google.android.exoplayer2.util.Assertions.checkStateNotNull; - -import androidx.annotation.Nullable; -import com.google.android.exoplayer2.C; -import com.google.android.exoplayer2.Format; -import com.google.android.exoplayer2.decoder.DecoderInputBuffer; -import com.google.android.exoplayer2.util.MimeTypes; - -/* package */ abstract class BaseSamplePipeline implements SamplePipeline { - - private final long streamStartPositionUs; - private final MuxerWrapper muxerWrapper; - private final @C.TrackType int trackType; - - private boolean muxerWrapperTrackAdded; - - public BaseSamplePipeline( - Format inputFormat, long streamStartPositionUs, MuxerWrapper muxerWrapper) { - this.streamStartPositionUs = streamStartPositionUs; - this.muxerWrapper = muxerWrapper; - trackType = MimeTypes.getTrackType(inputFormat.sampleMimeType); - } - - protected static TransformationException createNoSupportedMimeTypeException( - Format requestedEncoderFormat) { - return TransformationException.createForCodec( - new IllegalArgumentException("No MIME type is supported by both encoder and muxer."), - MimeTypes.isVideo(requestedEncoderFormat.sampleMimeType), - /* isDecoder= */ false, - requestedEncoderFormat, - /* mediaCodecName= */ null, - TransformationException.ERROR_CODE_ENCODING_FORMAT_UNSUPPORTED); - } - - @Override - public boolean expectsDecodedData() { - return true; - } - - @Override - public boolean processData() throws TransformationException { - return feedMuxer() || processDataUpToMuxer(); - } - - protected abstract boolean processDataUpToMuxer() throws TransformationException; - - @Nullable - protected abstract Format getMuxerInputFormat() throws TransformationException; - - @Nullable - protected abstract DecoderInputBuffer getMuxerInputBuffer() throws TransformationException; - - protected abstract void releaseMuxerInputBuffer() throws TransformationException; - - protected abstract boolean isMuxerInputEnded(); - - /** - * Attempts to pass encoded data to the muxer, and returns whether it may be possible to pass more - * data immediately by calling this method again. - */ - private boolean feedMuxer() throws TransformationException { - if (!muxerWrapperTrackAdded) { - @Nullable Format inputFormat = getMuxerInputFormat(); - if (inputFormat == null) { - return false; - } - try { - muxerWrapper.addTrackFormat(inputFormat); - } catch (Muxer.MuxerException e) { - throw TransformationException.createForMuxer( - e, TransformationException.ERROR_CODE_MUXING_FAILED); - } - muxerWrapperTrackAdded = true; - } - - if (isMuxerInputEnded()) { - muxerWrapper.endTrack(trackType); - return false; - } - - @Nullable DecoderInputBuffer muxerInputBuffer = getMuxerInputBuffer(); - if (muxerInputBuffer == null) { - return false; - } - - long samplePresentationTimeUs = muxerInputBuffer.timeUs - streamStartPositionUs; - // TODO(b/204892224): Consider subtracting the first sample timestamp from the sample pipeline - // buffer from all samples so that they are guaranteed to start from zero in the output file. - try { - if (!muxerWrapper.writeSample( - trackType, - checkStateNotNull(muxerInputBuffer.data), - muxerInputBuffer.isKeyFrame(), - samplePresentationTimeUs)) { - return false; - } - } catch (Muxer.MuxerException e) { - throw TransformationException.createForMuxer( - e, TransformationException.ERROR_CODE_MUXING_FAILED); - } - - releaseMuxerInputBuffer(); - return true; - } -} diff --git a/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/PassthroughSamplePipeline.java b/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/PassthroughSamplePipeline.java index 67672774cf..2fd497e7bf 100644 --- a/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/PassthroughSamplePipeline.java +++ b/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/PassthroughSamplePipeline.java @@ -21,7 +21,7 @@ import com.google.android.exoplayer2.Format; import com.google.android.exoplayer2.decoder.DecoderInputBuffer; /** Pipeline that muxes encoded samples without any transcoding or transformation. */ -/* package */ final class PassthroughSamplePipeline extends BaseSamplePipeline { +/* package */ final class PassthroughSamplePipeline extends SamplePipeline { private final DecoderInputBuffer buffer; private final Format format; @@ -61,11 +61,6 @@ import com.google.android.exoplayer2.decoder.DecoderInputBuffer; @Override public void release() {} - @Override - protected boolean processDataUpToMuxer() { - return false; - } - @Override protected Format getMuxerInputFormat() { return format; diff --git a/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/SamplePipeline.java b/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/SamplePipeline.java index 422a2b930c..9eccc3d94e 100644 --- a/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/SamplePipeline.java +++ b/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/SamplePipeline.java @@ -1,5 +1,5 @@ /* - * Copyright 2021 The Android Open Source Project + * Copyright 2022 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,19 +16,120 @@ package com.google.android.exoplayer2.transformer; +import static com.google.android.exoplayer2.util.Assertions.checkStateNotNull; + +import androidx.annotation.Nullable; +import com.google.android.exoplayer2.C; +import com.google.android.exoplayer2.Format; +import com.google.android.exoplayer2.decoder.DecoderInputBuffer; +import com.google.android.exoplayer2.util.MimeTypes; + /** * Pipeline for processing media data. * *

This pipeline can be used to implement transformations of audio or video samples. */ -/* package */ interface SamplePipeline extends SampleConsumer { +/* package */ abstract class SamplePipeline implements SampleConsumer { + + private final long streamStartPositionUs; + private final MuxerWrapper muxerWrapper; + private final @C.TrackType int trackType; + + private boolean muxerWrapperTrackAdded; + + public SamplePipeline(Format inputFormat, long streamStartPositionUs, MuxerWrapper muxerWrapper) { + this.streamStartPositionUs = streamStartPositionUs; + this.muxerWrapper = muxerWrapper; + trackType = MimeTypes.getTrackType(inputFormat.sampleMimeType); + } + + protected static TransformationException createNoSupportedMimeTypeException( + Format requestedEncoderFormat) { + return TransformationException.createForCodec( + new IllegalArgumentException("No MIME type is supported by both encoder and muxer."), + MimeTypes.isVideo(requestedEncoderFormat.sampleMimeType), + /* isDecoder= */ false, + requestedEncoderFormat, + /* mediaCodecName= */ null, + TransformationException.ERROR_CODE_ENCODING_FORMAT_UNSUPPORTED); + } + + @Override + public boolean expectsDecodedData() { + return true; + } /** * Processes the input data and returns whether it may be possible to process more data by calling * this method again. */ - boolean processData() throws TransformationException; + public final boolean processData() throws TransformationException { + return feedMuxer() || processDataUpToMuxer(); + } /** Releases all resources held by the pipeline. */ - void release(); + public abstract void release(); + + protected boolean processDataUpToMuxer() throws TransformationException { + return false; + } + + @Nullable + protected abstract Format getMuxerInputFormat() throws TransformationException; + + @Nullable + protected abstract DecoderInputBuffer getMuxerInputBuffer() throws TransformationException; + + protected abstract void releaseMuxerInputBuffer() throws TransformationException; + + protected abstract boolean isMuxerInputEnded(); + + /** + * Attempts to pass encoded data to the muxer, and returns whether it may be possible to pass more + * data immediately by calling this method again. + */ + private boolean feedMuxer() throws TransformationException { + if (!muxerWrapperTrackAdded) { + @Nullable Format inputFormat = getMuxerInputFormat(); + if (inputFormat == null) { + return false; + } + try { + muxerWrapper.addTrackFormat(inputFormat); + } catch (Muxer.MuxerException e) { + throw TransformationException.createForMuxer( + e, TransformationException.ERROR_CODE_MUXING_FAILED); + } + muxerWrapperTrackAdded = true; + } + + if (isMuxerInputEnded()) { + muxerWrapper.endTrack(trackType); + return false; + } + + @Nullable DecoderInputBuffer muxerInputBuffer = getMuxerInputBuffer(); + if (muxerInputBuffer == null) { + return false; + } + + long samplePresentationTimeUs = muxerInputBuffer.timeUs - streamStartPositionUs; + // TODO(b/204892224): Consider subtracting the first sample timestamp from the sample pipeline + // buffer from all samples so that they are guaranteed to start from zero in the output file. + try { + if (!muxerWrapper.writeSample( + trackType, + checkStateNotNull(muxerInputBuffer.data), + muxerInputBuffer.isKeyFrame(), + samplePresentationTimeUs)) { + return false; + } + } catch (Muxer.MuxerException e) { + throw TransformationException.createForMuxer( + e, TransformationException.ERROR_CODE_MUXING_FAILED); + } + + releaseMuxerInputBuffer(); + return true; + } } diff --git a/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/VideoTranscodingSamplePipeline.java b/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/VideoTranscodingSamplePipeline.java index 6614cc3c64..0a2f3f9bdd 100644 --- a/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/VideoTranscodingSamplePipeline.java +++ b/library/transformer/src/main/java/com/google/android/exoplayer2/transformer/VideoTranscodingSamplePipeline.java @@ -54,7 +54,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull; import org.checkerframework.dataflow.qual.Pure; /** Pipeline to process, re-encode and mux raw video frames. */ -/* package */ final class VideoTranscodingSamplePipeline extends BaseSamplePipeline { +/* package */ final class VideoTranscodingSamplePipeline extends SamplePipeline { private final FrameProcessor frameProcessor; private final ColorInfo frameProcessorInputColor; @@ -257,11 +257,6 @@ import org.checkerframework.dataflow.qual.Pure; encoderWrapper.release(); } - @Override - protected boolean processDataUpToMuxer() { - return false; - } - @Override @Nullable protected Format getMuxerInputFormat() throws TransformationException {