From 406c51c77e0d084e218b9949bfa1ec7f3222b5a2 Mon Sep 17 00:00:00 2001 From: Christian Bernier Date: Tue, 28 Apr 2020 22:24:32 -0400 Subject: [PATCH 1/2] - Add a video strategy to change the way that the videos are scaled to be the same resolution - Add a method in VideoDecoderOutput to scale the canvas instead of the frame --- .../transcoder/demo/TranscoderActivity.java | 3 ++- .../transcoder/TranscoderOptions.java | 13 +++++++------ .../transcoder/engine/Engine.java | 1 + .../strategy/DefaultVideoStrategy.java | 8 +++++++- .../transcoder/strategy/TrackStrategy.java | 5 ++--- .../strategy/VideoTrackStrategy.java | 18 ++++++++++++++++++ .../transcode/VideoTrackTranscoder.java | 11 +++++++---- .../transcode/internal/VideoDecoderOutput.java | 15 +++++++++++++++ 8 files changed, 59 insertions(+), 15 deletions(-) create mode 100644 lib/src/main/java/com/otaliastudios/transcoder/strategy/VideoTrackStrategy.java diff --git a/demo/src/main/java/com/otaliastudios/transcoder/demo/TranscoderActivity.java b/demo/src/main/java/com/otaliastudios/transcoder/demo/TranscoderActivity.java index f5e70b86..292f41bc 100644 --- a/demo/src/main/java/com/otaliastudios/transcoder/demo/TranscoderActivity.java +++ b/demo/src/main/java/com/otaliastudios/transcoder/demo/TranscoderActivity.java @@ -29,6 +29,7 @@ import com.otaliastudios.transcoder.strategy.DefaultVideoStrategy; import com.otaliastudios.transcoder.strategy.RemoveTrackStrategy; import com.otaliastudios.transcoder.strategy.TrackStrategy; +import com.otaliastudios.transcoder.strategy.VideoTrackStrategy; import com.otaliastudios.transcoder.strategy.size.AspectRatioResizer; import com.otaliastudios.transcoder.strategy.size.FractionResizer; import com.otaliastudios.transcoder.strategy.size.PassThroughResizer; @@ -78,7 +79,7 @@ public class TranscoderActivity extends AppCompatActivity implements private Uri mAudioReplacementUri; private File mTranscodeOutputFile; private long mTranscodeStartTime; - private TrackStrategy mTranscodeVideoStrategy; + private VideoTrackStrategy mTranscodeVideoStrategy; private TrackStrategy mTranscodeAudioStrategy; private long mTrimStartUs = 0; private long mTrimEndUs = 0; diff --git a/lib/src/main/java/com/otaliastudios/transcoder/TranscoderOptions.java b/lib/src/main/java/com/otaliastudios/transcoder/TranscoderOptions.java index 81c12a4d..91836704 100644 --- a/lib/src/main/java/com/otaliastudios/transcoder/TranscoderOptions.java +++ b/lib/src/main/java/com/otaliastudios/transcoder/TranscoderOptions.java @@ -18,6 +18,7 @@ import com.otaliastudios.transcoder.strategy.DefaultAudioStrategy; import com.otaliastudios.transcoder.strategy.DefaultVideoStrategies; import com.otaliastudios.transcoder.strategy.TrackStrategy; +import com.otaliastudios.transcoder.strategy.VideoTrackStrategy; import com.otaliastudios.transcoder.stretch.AudioStretcher; import com.otaliastudios.transcoder.stretch.DefaultAudioStretcher; import com.otaliastudios.transcoder.time.DefaultTimeInterpolator; @@ -45,7 +46,7 @@ private TranscoderOptions() {} private List videoDataSources; private List audioDataSources; private TrackStrategy audioTrackStrategy; - private TrackStrategy videoTrackStrategy; + private VideoTrackStrategy videoTrackStrategy; private Validator validator; private int rotation; private TimeInterpolator timeInterpolator; @@ -76,7 +77,7 @@ public TrackStrategy getAudioTrackStrategy() { } @NonNull - public TrackStrategy getVideoTrackStrategy() { + public VideoTrackStrategy getVideoTrackStrategy() { return videoTrackStrategy; } @@ -111,7 +112,7 @@ public static class Builder { private TranscoderListener listener; private Handler listenerHandler; private TrackStrategy audioTrackStrategy; - private TrackStrategy videoTrackStrategy; + private VideoTrackStrategy videoTrackStrategy; private Validator validator; private int rotation; private TimeInterpolator timeInterpolator; @@ -199,13 +200,13 @@ public Builder setAudioTrackStrategy(@Nullable TrackStrategy trackStrategy) { * Sets the video output strategy. If absent, this defaults to the 16:9 * strategy returned by {@link DefaultVideoStrategies#for720x1280()}. * - * @param trackStrategy the desired strategy + * @param videoTrackStrategy the desired strategy * @return this for chaining */ @NonNull @SuppressWarnings("unused") - public Builder setVideoTrackStrategy(@Nullable TrackStrategy trackStrategy) { - this.videoTrackStrategy = trackStrategy; + public Builder setVideoTrackStrategy(@Nullable VideoTrackStrategy videoTrackStrategy) { + this.videoTrackStrategy = videoTrackStrategy; return this; } diff --git a/lib/src/main/java/com/otaliastudios/transcoder/engine/Engine.java b/lib/src/main/java/com/otaliastudios/transcoder/engine/Engine.java index 742fd1cf..17f5cc4b 100644 --- a/lib/src/main/java/com/otaliastudios/transcoder/engine/Engine.java +++ b/lib/src/main/java/com/otaliastudios/transcoder/engine/Engine.java @@ -171,6 +171,7 @@ private void openCurrentStep(@NonNull TrackType type, @NonNull TranscoderOptions case VIDEO: transcoder = new VideoTrackTranscoder(dataSource, mDataSink, interpolator, + options.getVideoTrackStrategy(), options.getVideoRotation()); break; case AUDIO: diff --git a/lib/src/main/java/com/otaliastudios/transcoder/strategy/DefaultVideoStrategy.java b/lib/src/main/java/com/otaliastudios/transcoder/strategy/DefaultVideoStrategy.java index bbab7255..82f9639f 100644 --- a/lib/src/main/java/com/otaliastudios/transcoder/strategy/DefaultVideoStrategy.java +++ b/lib/src/main/java/com/otaliastudios/transcoder/strategy/DefaultVideoStrategy.java @@ -16,6 +16,7 @@ import com.otaliastudios.transcoder.strategy.size.Resizer; import com.otaliastudios.transcoder.internal.Logger; import com.otaliastudios.transcoder.internal.MediaFormatConstants; +import com.otaliastudios.transcoder.transcode.internal.VideoDecoderOutput; import androidx.annotation.NonNull; @@ -25,7 +26,7 @@ * An {@link TrackStrategy} for video that converts it AVC with the given size. * The input and output aspect ratio must match. */ -public class DefaultVideoStrategy implements TrackStrategy { +public class DefaultVideoStrategy implements VideoTrackStrategy { private final static String TAG = DefaultVideoStrategy.class.getSimpleName(); private final static Logger LOG = new Logger(TAG); @@ -290,6 +291,11 @@ public TrackStatus createOutputFormat(@NonNull List inputFormats, return TrackStatus.COMPRESSING; } + @Override + public void scaleOutput(@NonNull VideoDecoderOutput videoDecoderOutput, float scaleX, float scaleY) { + videoDecoderOutput.setScale(scaleX, scaleY); + } + private boolean checkMimeType(@NonNull List formats) { for (MediaFormat format : formats) { if (!format.getString(MediaFormat.KEY_MIME).equalsIgnoreCase(options.targetMimeType)) { diff --git a/lib/src/main/java/com/otaliastudios/transcoder/strategy/TrackStrategy.java b/lib/src/main/java/com/otaliastudios/transcoder/strategy/TrackStrategy.java index fa2df2a4..a2210e51 100644 --- a/lib/src/main/java/com/otaliastudios/transcoder/strategy/TrackStrategy.java +++ b/lib/src/main/java/com/otaliastudios/transcoder/strategy/TrackStrategy.java @@ -2,12 +2,11 @@ import android.media.MediaFormat; +import androidx.annotation.NonNull; + import com.otaliastudios.transcoder.engine.TrackStatus; import com.otaliastudios.transcoder.strategy.size.Resizer; -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; - import java.util.List; /** diff --git a/lib/src/main/java/com/otaliastudios/transcoder/strategy/VideoTrackStrategy.java b/lib/src/main/java/com/otaliastudios/transcoder/strategy/VideoTrackStrategy.java new file mode 100644 index 00000000..d52e72da --- /dev/null +++ b/lib/src/main/java/com/otaliastudios/transcoder/strategy/VideoTrackStrategy.java @@ -0,0 +1,18 @@ +package com.otaliastudios.transcoder.strategy; + +import androidx.annotation.NonNull; +import com.otaliastudios.transcoder.transcode.internal.VideoDecoderOutput; + +public interface VideoTrackStrategy extends TrackStrategy { + + /** + * Apply the scaling to the video decoder output + * + * It can be done using VideoDecoderOutput.setScale or VideoDecoderOutput.setDrawableScale + * + * @param videoDecoderOutput the video decoder output + * @param scaleX the expected x scaling + * @param scaleY the expected y scaling + */ + void scaleOutput(@NonNull VideoDecoderOutput videoDecoderOutput, float scaleX, float scaleY); +} diff --git a/lib/src/main/java/com/otaliastudios/transcoder/transcode/VideoTrackTranscoder.java b/lib/src/main/java/com/otaliastudios/transcoder/transcode/VideoTrackTranscoder.java index 1f782566..ea1dea5d 100644 --- a/lib/src/main/java/com/otaliastudios/transcoder/transcode/VideoTrackTranscoder.java +++ b/lib/src/main/java/com/otaliastudios/transcoder/transcode/VideoTrackTranscoder.java @@ -16,20 +16,20 @@ package com.otaliastudios.transcoder.transcode; import android.media.MediaCodec; -import android.media.MediaExtractor; import android.media.MediaFormat; import androidx.annotation.NonNull; import com.otaliastudios.transcoder.engine.TrackType; +import com.otaliastudios.transcoder.internal.Logger; import com.otaliastudios.transcoder.internal.MediaCodecBuffers; +import com.otaliastudios.transcoder.internal.MediaFormatConstants; import com.otaliastudios.transcoder.sink.DataSink; import com.otaliastudios.transcoder.source.DataSource; +import com.otaliastudios.transcoder.strategy.VideoTrackStrategy; import com.otaliastudios.transcoder.time.TimeInterpolator; import com.otaliastudios.transcoder.transcode.internal.VideoDecoderOutput; import com.otaliastudios.transcoder.transcode.internal.VideoEncoderInput; -import com.otaliastudios.transcoder.internal.Logger; -import com.otaliastudios.transcoder.internal.MediaFormatConstants; import com.otaliastudios.transcoder.transcode.internal.VideoFrameDropper; import java.nio.ByteBuffer; @@ -46,6 +46,7 @@ public class VideoTrackTranscoder extends BaseTrackTranscoder { private MediaCodec mEncoder; // Keep this since we want to signal EOS on it. private VideoFrameDropper mFrameDropper; private final TimeInterpolator mTimeInterpolator; + private final VideoTrackStrategy mStrategy; private final int mSourceRotation; private final int mExtraRotation; @@ -53,9 +54,11 @@ public VideoTrackTranscoder( @NonNull DataSource dataSource, @NonNull DataSink dataSink, @NonNull TimeInterpolator timeInterpolator, + @NonNull VideoTrackStrategy strategy, int rotation) { super(dataSource, dataSink, TrackType.VIDEO); mTimeInterpolator = timeInterpolator; + mStrategy = strategy; mSourceRotation = dataSource.getOrientation(); mExtraRotation = rotation; } @@ -130,7 +133,7 @@ protected void onCodecsStarted(@NonNull MediaFormat inputFormat, @NonNull MediaF } else if (inputRatio < outputRatio) { // Input taller. We have a scaleY. scaleY = outputRatio / inputRatio; } - mDecoderOutputSurface.setScale(scaleX, scaleY); + mStrategy.scaleOutput(mDecoderOutputSurface, scaleX, scaleY); } @Override diff --git a/lib/src/main/java/com/otaliastudios/transcoder/transcode/internal/VideoDecoderOutput.java b/lib/src/main/java/com/otaliastudios/transcoder/transcode/internal/VideoDecoderOutput.java index 7f052561..efa20220 100644 --- a/lib/src/main/java/com/otaliastudios/transcoder/transcode/internal/VideoDecoderOutput.java +++ b/lib/src/main/java/com/otaliastudios/transcoder/transcode/internal/VideoDecoderOutput.java @@ -87,6 +87,21 @@ public void setScale(float scaleX, float scaleY) { mScaleY = scaleY; } + /** + * Scale the canvas along the two axes. + * @param scaleX x scale + * @param scaleY y scale + */ + @SuppressWarnings("unused") + public void setDrawableScale(float scaleX, float scaleY) { + mDrawable.setRect( + -1.0F * scaleX, + -1.0F * scaleY, + 1.0F * scaleX, + 1.0F * scaleY + ); + } + /** * Sets the desired frame rotation with respect * to its natural orientation. From a772879875028293887b8452e641b187ad581370 Mon Sep 17 00:00:00 2001 From: Christian Bernier Date: Thu, 30 Apr 2020 21:10:30 -0400 Subject: [PATCH 2/2] - Replace the scaleOutput video strategy by a VideoScaler TranscoderOption - Add the VideoScaler TranscoderOptions to the demo app --- .../transcoder/demo/TranscoderActivity.java | 19 ++++++++-- .../main/res/layout/activity_transcoder.xml | 36 +++++++++++++++++++ .../transcoder/TranscoderOptions.java | 34 +++++++++++++++--- .../transcoder/engine/Engine.java | 2 +- .../transcoder/scale/DownVideoScaler.java | 20 +++++++++++ .../transcoder/scale/StretchVideoScaler.java | 16 +++++++++ .../transcoder/scale/UpVideoScaler.java | 16 +++++++++ .../VideoScaler.java} | 16 +++++---- .../strategy/DefaultVideoStrategy.java | 7 +--- .../transcode/VideoTrackTranscoder.java | 10 +++--- 10 files changed, 150 insertions(+), 26 deletions(-) create mode 100644 lib/src/main/java/com/otaliastudios/transcoder/scale/DownVideoScaler.java create mode 100644 lib/src/main/java/com/otaliastudios/transcoder/scale/StretchVideoScaler.java create mode 100644 lib/src/main/java/com/otaliastudios/transcoder/scale/UpVideoScaler.java rename lib/src/main/java/com/otaliastudios/transcoder/{strategy/VideoTrackStrategy.java => scale/VideoScaler.java} (53%) diff --git a/demo/src/main/java/com/otaliastudios/transcoder/demo/TranscoderActivity.java b/demo/src/main/java/com/otaliastudios/transcoder/demo/TranscoderActivity.java index 292f41bc..6702624c 100644 --- a/demo/src/main/java/com/otaliastudios/transcoder/demo/TranscoderActivity.java +++ b/demo/src/main/java/com/otaliastudios/transcoder/demo/TranscoderActivity.java @@ -20,6 +20,10 @@ import com.otaliastudios.transcoder.engine.TrackStatus; import com.otaliastudios.transcoder.engine.TrackType; import com.otaliastudios.transcoder.internal.Logger; +import com.otaliastudios.transcoder.scale.DownVideoScaler; +import com.otaliastudios.transcoder.scale.StretchVideoScaler; +import com.otaliastudios.transcoder.scale.UpVideoScaler; +import com.otaliastudios.transcoder.scale.VideoScaler; import com.otaliastudios.transcoder.sink.DataSink; import com.otaliastudios.transcoder.sink.DefaultDataSink; import com.otaliastudios.transcoder.source.DataSource; @@ -29,7 +33,6 @@ import com.otaliastudios.transcoder.strategy.DefaultVideoStrategy; import com.otaliastudios.transcoder.strategy.RemoveTrackStrategy; import com.otaliastudios.transcoder.strategy.TrackStrategy; -import com.otaliastudios.transcoder.strategy.VideoTrackStrategy; import com.otaliastudios.transcoder.strategy.size.AspectRatioResizer; import com.otaliastudios.transcoder.strategy.size.FractionResizer; import com.otaliastudios.transcoder.strategy.size.PassThroughResizer; @@ -60,6 +63,7 @@ public class TranscoderActivity extends AppCompatActivity implements private RadioGroup mVideoFramesGroup; private RadioGroup mVideoResolutionGroup; private RadioGroup mVideoAspectGroup; + private RadioGroup mVideoScalingGroup; private RadioGroup mVideoRotationGroup; private RadioGroup mSpeedGroup; private RadioGroup mAudioReplaceGroup; @@ -79,7 +83,7 @@ public class TranscoderActivity extends AppCompatActivity implements private Uri mAudioReplacementUri; private File mTranscodeOutputFile; private long mTranscodeStartTime; - private VideoTrackStrategy mTranscodeVideoStrategy; + private TrackStrategy mTranscodeVideoStrategy; private TrackStrategy mTranscodeAudioStrategy; private long mTrimStartUs = 0; private long mTrimEndUs = 0; @@ -135,6 +139,7 @@ protected void onCreate(Bundle savedInstanceState) { mVideoFramesGroup = findViewById(R.id.frames); mVideoResolutionGroup = findViewById(R.id.resolution); mVideoAspectGroup = findViewById(R.id.aspect); + mVideoScalingGroup = findViewById(R.id.scale); mVideoRotationGroup = findViewById(R.id.rotation); mSpeedGroup = findViewById(R.id.speed); mAudioSampleRateGroup = findViewById(R.id.sampleRate); @@ -144,6 +149,7 @@ protected void onCreate(Bundle savedInstanceState) { mVideoFramesGroup.setOnCheckedChangeListener(mRadioGroupListener); mVideoResolutionGroup.setOnCheckedChangeListener(mRadioGroupListener); mVideoAspectGroup.setOnCheckedChangeListener(mRadioGroupListener); + mVideoScalingGroup.setOnCheckedChangeListener(mRadioGroupListener); mAudioSampleRateGroup.setOnCheckedChangeListener(mRadioGroupListener); mTrimStartView.addTextChangedListener(mTextListener); mTrimEndView.addTextChangedListener(mTextListener); @@ -297,11 +303,18 @@ private void transcode() { default: speed = 1F; } + VideoScaler videoScaler; + switch (mVideoScalingGroup.getCheckedRadioButtonId()) { + case R.id.scale_down: videoScaler = new DownVideoScaler(); break; + case R.id.scale_stretch: videoScaler = new StretchVideoScaler(); break; + default: videoScaler = new UpVideoScaler(); break; + } + // Launch the transcoding operation. mTranscodeStartTime = SystemClock.uptimeMillis(); setIsTranscoding(true); DataSink sink = new DefaultDataSink(mTranscodeOutputFile.getAbsolutePath()); - TranscoderOptions.Builder builder = Transcoder.into(sink); + TranscoderOptions.Builder builder = Transcoder.into(sink).setVideoScaler(videoScaler); if (mAudioReplacementUri == null) { if (mTranscodeInputUri1 != null) { DataSource source = new UriDataSource(this, mTranscodeInputUri1); diff --git a/demo/src/main/res/layout/activity_transcoder.xml b/demo/src/main/res/layout/activity_transcoder.xml index 8034a75c..87ccda03 100644 --- a/demo/src/main/res/layout/activity_transcoder.xml +++ b/demo/src/main/res/layout/activity_transcoder.xml @@ -205,6 +205,42 @@ android:layout_height="wrap_content" /> + + + + + + + + videoDataSources; private List audioDataSources; private TrackStrategy audioTrackStrategy; - private VideoTrackStrategy videoTrackStrategy; + private TrackStrategy videoTrackStrategy; private Validator validator; private int rotation; private TimeInterpolator timeInterpolator; private AudioStretcher audioStretcher; private AudioResampler audioResampler; + private VideoScaler videoScaler; TranscoderListener listener; Handler listenerHandler; @@ -77,7 +79,7 @@ public TrackStrategy getAudioTrackStrategy() { } @NonNull - public VideoTrackStrategy getVideoTrackStrategy() { + public TrackStrategy getVideoTrackStrategy() { return videoTrackStrategy; } @@ -105,6 +107,11 @@ public AudioResampler getAudioResampler() { return audioResampler; } + @NonNull + public VideoScaler getVideoScaler() { + return videoScaler; + } + public static class Builder { private DataSink dataSink; private final List audioDataSources = new ArrayList<>(); @@ -112,12 +119,13 @@ public static class Builder { private TranscoderListener listener; private Handler listenerHandler; private TrackStrategy audioTrackStrategy; - private VideoTrackStrategy videoTrackStrategy; + private TrackStrategy videoTrackStrategy; private Validator validator; private int rotation; private TimeInterpolator timeInterpolator; private AudioStretcher audioStretcher; private AudioResampler audioResampler; + private VideoScaler videoScaler; Builder(@NonNull String outPath) { this.dataSink = new DefaultDataSink(outPath); @@ -205,7 +213,7 @@ public Builder setAudioTrackStrategy(@Nullable TrackStrategy trackStrategy) { */ @NonNull @SuppressWarnings("unused") - public Builder setVideoTrackStrategy(@Nullable VideoTrackStrategy videoTrackStrategy) { + public Builder setVideoTrackStrategy(@Nullable TrackStrategy videoTrackStrategy) { this.videoTrackStrategy = videoTrackStrategy; return this; } @@ -319,6 +327,18 @@ public Builder setAudioResampler(@NonNull AudioResampler audioResampler) { return this; } + /** + * Set an {@link VideoScaler} to change the resolution of the video frames + * so that they fit the new resolution + * + */ + @NonNull + @SuppressWarnings("unused") + public Builder setVideoScaler(@NonNull VideoScaler videoScaler) { + this.videoScaler = videoScaler; + return this; + } + /** * Generates muted audio data sources if needed * @return The list of audio data sources including the muted sources @@ -390,6 +410,9 @@ public TranscoderOptions build() { if (audioResampler == null) { audioResampler = new DefaultAudioResampler(); } + if (videoScaler == null) { + videoScaler = new UpVideoScaler(); + } TranscoderOptions options = new TranscoderOptions(); options.listener = listener; options.audioDataSources = buildAudioDataSources(); @@ -403,6 +426,7 @@ public TranscoderOptions build() { options.timeInterpolator = timeInterpolator; options.audioStretcher = audioStretcher; options.audioResampler = audioResampler; + options.videoScaler = videoScaler; return options; } diff --git a/lib/src/main/java/com/otaliastudios/transcoder/engine/Engine.java b/lib/src/main/java/com/otaliastudios/transcoder/engine/Engine.java index 17f5cc4b..18e2e683 100644 --- a/lib/src/main/java/com/otaliastudios/transcoder/engine/Engine.java +++ b/lib/src/main/java/com/otaliastudios/transcoder/engine/Engine.java @@ -171,7 +171,7 @@ private void openCurrentStep(@NonNull TrackType type, @NonNull TranscoderOptions case VIDEO: transcoder = new VideoTrackTranscoder(dataSource, mDataSink, interpolator, - options.getVideoTrackStrategy(), + options.getVideoScaler(), options.getVideoRotation()); break; case AUDIO: diff --git a/lib/src/main/java/com/otaliastudios/transcoder/scale/DownVideoScaler.java b/lib/src/main/java/com/otaliastudios/transcoder/scale/DownVideoScaler.java new file mode 100644 index 00000000..b239dc23 --- /dev/null +++ b/lib/src/main/java/com/otaliastudios/transcoder/scale/DownVideoScaler.java @@ -0,0 +1,20 @@ +package com.otaliastudios.transcoder.scale; + +import androidx.annotation.NonNull; + +import com.otaliastudios.transcoder.transcode.internal.VideoDecoderOutput; + +/** + * An {@link VideoScaler} that scale the video down so that no side exceed the new resolution + * Sides that are too small will have black borders + */ +public class DownVideoScaler implements VideoScaler { + @Override + public void scaleOutput(@NonNull VideoDecoderOutput videoDecoderOutput, float scaleX, float scaleY, boolean flipped) { + if (flipped) { // The drawable is not affected by the flip so we need to reverse it + videoDecoderOutput.setDrawableScale(1.0F / scaleX, 1.0F / scaleY); + } else { + videoDecoderOutput.setDrawableScale(1.0F / scaleY, 1.0F / scaleX); + } + } +} \ No newline at end of file diff --git a/lib/src/main/java/com/otaliastudios/transcoder/scale/StretchVideoScaler.java b/lib/src/main/java/com/otaliastudios/transcoder/scale/StretchVideoScaler.java new file mode 100644 index 00000000..8862f229 --- /dev/null +++ b/lib/src/main/java/com/otaliastudios/transcoder/scale/StretchVideoScaler.java @@ -0,0 +1,16 @@ +package com.otaliastudios.transcoder.scale; + +import androidx.annotation.NonNull; + +import com.otaliastudios.transcoder.transcode.internal.VideoDecoderOutput; + +/** + * An {@link VideoScaler} that strech the video so that they match the video resolution + * at the cost of deforming the images + */ +public class StretchVideoScaler implements VideoScaler { + @Override + public void scaleOutput(@NonNull VideoDecoderOutput videoDecoderOutput, float scaleX, float scaleY, boolean flipped) { + //No scaling will automatically stretch the frames to fill all the drawable space + } +} \ No newline at end of file diff --git a/lib/src/main/java/com/otaliastudios/transcoder/scale/UpVideoScaler.java b/lib/src/main/java/com/otaliastudios/transcoder/scale/UpVideoScaler.java new file mode 100644 index 00000000..444eab65 --- /dev/null +++ b/lib/src/main/java/com/otaliastudios/transcoder/scale/UpVideoScaler.java @@ -0,0 +1,16 @@ +package com.otaliastudios.transcoder.scale; + +import androidx.annotation.NonNull; + +import com.otaliastudios.transcoder.transcode.internal.VideoDecoderOutput; + +/** + * An {@link VideoScaler} that scale the video up so that it touches all sides + * of the new resolution and exceeding parts will be truncated + */ +public class UpVideoScaler implements VideoScaler { + @Override + public void scaleOutput(@NonNull VideoDecoderOutput videoDecoderOutput, float scaleX, float scaleY, boolean flipped) { + videoDecoderOutput.setScale(scaleX, scaleY); + } +} diff --git a/lib/src/main/java/com/otaliastudios/transcoder/strategy/VideoTrackStrategy.java b/lib/src/main/java/com/otaliastudios/transcoder/scale/VideoScaler.java similarity index 53% rename from lib/src/main/java/com/otaliastudios/transcoder/strategy/VideoTrackStrategy.java rename to lib/src/main/java/com/otaliastudios/transcoder/scale/VideoScaler.java index d52e72da..b012361f 100644 --- a/lib/src/main/java/com/otaliastudios/transcoder/strategy/VideoTrackStrategy.java +++ b/lib/src/main/java/com/otaliastudios/transcoder/scale/VideoScaler.java @@ -1,18 +1,22 @@ -package com.otaliastudios.transcoder.strategy; +package com.otaliastudios.transcoder.scale; import androidx.annotation.NonNull; -import com.otaliastudios.transcoder.transcode.internal.VideoDecoderOutput; -public interface VideoTrackStrategy extends TrackStrategy { +import com.otaliastudios.transcoder.transcode.internal.VideoDecoderOutput; +/** + * Scale the frames when they are not of the expected resolution + */ +public interface VideoScaler { /** * Apply the scaling to the video decoder output * * It can be done using VideoDecoderOutput.setScale or VideoDecoderOutput.setDrawableScale * * @param videoDecoderOutput the video decoder output - * @param scaleX the expected x scaling - * @param scaleY the expected y scaling + * @param scaleX the input width/height + * @param scaleY the output width/height + * @param flipped whether or not the frame was rotated by 90 degrees */ - void scaleOutput(@NonNull VideoDecoderOutput videoDecoderOutput, float scaleX, float scaleY); + void scaleOutput(@NonNull VideoDecoderOutput videoDecoderOutput, float scaleX, float scaleY, boolean flipped); } diff --git a/lib/src/main/java/com/otaliastudios/transcoder/strategy/DefaultVideoStrategy.java b/lib/src/main/java/com/otaliastudios/transcoder/strategy/DefaultVideoStrategy.java index 82f9639f..5335b3ed 100644 --- a/lib/src/main/java/com/otaliastudios/transcoder/strategy/DefaultVideoStrategy.java +++ b/lib/src/main/java/com/otaliastudios/transcoder/strategy/DefaultVideoStrategy.java @@ -26,7 +26,7 @@ * An {@link TrackStrategy} for video that converts it AVC with the given size. * The input and output aspect ratio must match. */ -public class DefaultVideoStrategy implements VideoTrackStrategy { +public class DefaultVideoStrategy implements TrackStrategy { private final static String TAG = DefaultVideoStrategy.class.getSimpleName(); private final static Logger LOG = new Logger(TAG); @@ -291,11 +291,6 @@ public TrackStatus createOutputFormat(@NonNull List inputFormats, return TrackStatus.COMPRESSING; } - @Override - public void scaleOutput(@NonNull VideoDecoderOutput videoDecoderOutput, float scaleX, float scaleY) { - videoDecoderOutput.setScale(scaleX, scaleY); - } - private boolean checkMimeType(@NonNull List formats) { for (MediaFormat format : formats) { if (!format.getString(MediaFormat.KEY_MIME).equalsIgnoreCase(options.targetMimeType)) { diff --git a/lib/src/main/java/com/otaliastudios/transcoder/transcode/VideoTrackTranscoder.java b/lib/src/main/java/com/otaliastudios/transcoder/transcode/VideoTrackTranscoder.java index ea1dea5d..c4e1e573 100644 --- a/lib/src/main/java/com/otaliastudios/transcoder/transcode/VideoTrackTranscoder.java +++ b/lib/src/main/java/com/otaliastudios/transcoder/transcode/VideoTrackTranscoder.java @@ -24,9 +24,9 @@ import com.otaliastudios.transcoder.internal.Logger; import com.otaliastudios.transcoder.internal.MediaCodecBuffers; import com.otaliastudios.transcoder.internal.MediaFormatConstants; +import com.otaliastudios.transcoder.scale.VideoScaler; import com.otaliastudios.transcoder.sink.DataSink; import com.otaliastudios.transcoder.source.DataSource; -import com.otaliastudios.transcoder.strategy.VideoTrackStrategy; import com.otaliastudios.transcoder.time.TimeInterpolator; import com.otaliastudios.transcoder.transcode.internal.VideoDecoderOutput; import com.otaliastudios.transcoder.transcode.internal.VideoEncoderInput; @@ -46,7 +46,7 @@ public class VideoTrackTranscoder extends BaseTrackTranscoder { private MediaCodec mEncoder; // Keep this since we want to signal EOS on it. private VideoFrameDropper mFrameDropper; private final TimeInterpolator mTimeInterpolator; - private final VideoTrackStrategy mStrategy; + private final VideoScaler mVideoScaler; private final int mSourceRotation; private final int mExtraRotation; @@ -54,11 +54,11 @@ public VideoTrackTranscoder( @NonNull DataSource dataSource, @NonNull DataSink dataSink, @NonNull TimeInterpolator timeInterpolator, - @NonNull VideoTrackStrategy strategy, + @NonNull VideoScaler videoScaler, int rotation) { super(dataSource, dataSink, TrackType.VIDEO); mTimeInterpolator = timeInterpolator; - mStrategy = strategy; + mVideoScaler = videoScaler; mSourceRotation = dataSource.getOrientation(); mExtraRotation = rotation; } @@ -133,7 +133,7 @@ protected void onCodecsStarted(@NonNull MediaFormat inputFormat, @NonNull MediaF } else if (inputRatio < outputRatio) { // Input taller. We have a scaleY. scaleY = outputRatio / inputRatio; } - mStrategy.scaleOutput(mDecoderOutputSurface, scaleX, scaleY); + mVideoScaler.scaleOutput(mDecoderOutputSurface, scaleX, scaleY, flip); } @Override pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy