Allow output audio MIME type to be set in TranscodingTransformer.

This introduces a new option `setAudioMimeType` in `TranscodingTransformer.Builder` and a corresponding check whether the selected type is supported. This check is done using `supportsSampleMimeType` which is now part of the `Muxer.Factory` and `MuxerWrapper` rather than `Muxer`.
A new field `audioMimeType` is added to `Transformation` and the `TransformerAudioRenderer` uses this instead of the input MIME type if requested.

PiperOrigin-RevId: 405367817
This commit is contained in:
olly 2021-10-25 12:28:46 +01:00 committed by Oliver Woodman
parent 17d2f5a0b1
commit a42d9f36b1
10 changed files with 144 additions and 71 deletions

View File

@ -42,7 +42,7 @@ import java.nio.ByteBuffer;
@Override @Override
public FrameworkMuxer create(String path, String outputMimeType) throws IOException { public FrameworkMuxer create(String path, String outputMimeType) throws IOException {
MediaMuxer mediaMuxer = new MediaMuxer(path, mimeTypeToMuxerOutputFormat(outputMimeType)); MediaMuxer mediaMuxer = new MediaMuxer(path, mimeTypeToMuxerOutputFormat(outputMimeType));
return new FrameworkMuxer(mediaMuxer, outputMimeType); return new FrameworkMuxer(mediaMuxer);
} }
@RequiresApi(26) @RequiresApi(26)
@ -53,7 +53,7 @@ import java.nio.ByteBuffer;
new MediaMuxer( new MediaMuxer(
parcelFileDescriptor.getFileDescriptor(), parcelFileDescriptor.getFileDescriptor(),
mimeTypeToMuxerOutputFormat(outputMimeType)); mimeTypeToMuxerOutputFormat(outputMimeType));
return new FrameworkMuxer(mediaMuxer, outputMimeType); return new FrameworkMuxer(mediaMuxer);
} }
@Override @Override
@ -65,47 +65,46 @@ import java.nio.ByteBuffer;
} }
return true; return true;
} }
@Override
public boolean supportsSampleMimeType(
@Nullable String sampleMimeType, String containerMimeType) {
// MediaMuxer supported sample formats are documented in MediaMuxer.addTrack(MediaFormat).
boolean isAudio = MimeTypes.isAudio(sampleMimeType);
boolean isVideo = MimeTypes.isVideo(sampleMimeType);
if (containerMimeType.equals(MimeTypes.VIDEO_MP4)) {
if (isVideo) {
return MimeTypes.VIDEO_H263.equals(sampleMimeType)
|| MimeTypes.VIDEO_H264.equals(sampleMimeType)
|| MimeTypes.VIDEO_MP4V.equals(sampleMimeType)
|| (Util.SDK_INT >= 24 && MimeTypes.VIDEO_H265.equals(sampleMimeType));
} else if (isAudio) {
return MimeTypes.AUDIO_AAC.equals(sampleMimeType)
|| MimeTypes.AUDIO_AMR_NB.equals(sampleMimeType)
|| MimeTypes.AUDIO_AMR_WB.equals(sampleMimeType);
}
} else if (containerMimeType.equals(MimeTypes.VIDEO_WEBM) && SDK_INT >= 21) {
if (isVideo) {
return MimeTypes.VIDEO_VP8.equals(sampleMimeType)
|| (Util.SDK_INT >= 24 && MimeTypes.VIDEO_VP9.equals(sampleMimeType));
} else if (isAudio) {
return MimeTypes.AUDIO_VORBIS.equals(sampleMimeType);
}
}
return false;
}
} }
private final MediaMuxer mediaMuxer; private final MediaMuxer mediaMuxer;
private final String outputMimeType;
private final MediaCodec.BufferInfo bufferInfo; private final MediaCodec.BufferInfo bufferInfo;
private boolean isStarted; private boolean isStarted;
private FrameworkMuxer(MediaMuxer mediaMuxer, String outputMimeType) { private FrameworkMuxer(MediaMuxer mediaMuxer) {
this.mediaMuxer = mediaMuxer; this.mediaMuxer = mediaMuxer;
this.outputMimeType = outputMimeType;
bufferInfo = new MediaCodec.BufferInfo(); bufferInfo = new MediaCodec.BufferInfo();
} }
@Override
public boolean supportsSampleMimeType(@Nullable String mimeType) {
// MediaMuxer supported sample formats are documented in MediaMuxer.addTrack(MediaFormat).
boolean isAudio = MimeTypes.isAudio(mimeType);
boolean isVideo = MimeTypes.isVideo(mimeType);
if (outputMimeType.equals(MimeTypes.VIDEO_MP4)) {
if (isVideo) {
return MimeTypes.VIDEO_H263.equals(mimeType)
|| MimeTypes.VIDEO_H264.equals(mimeType)
|| MimeTypes.VIDEO_MP4V.equals(mimeType)
|| (Util.SDK_INT >= 24 && MimeTypes.VIDEO_H265.equals(mimeType));
} else if (isAudio) {
return MimeTypes.AUDIO_AAC.equals(mimeType)
|| MimeTypes.AUDIO_AMR_NB.equals(mimeType)
|| MimeTypes.AUDIO_AMR_WB.equals(mimeType);
}
} else if (outputMimeType.equals(MimeTypes.VIDEO_WEBM) && SDK_INT >= 21) {
if (isVideo) {
return MimeTypes.VIDEO_VP8.equals(mimeType)
|| (Util.SDK_INT >= 24 && MimeTypes.VIDEO_VP9.equals(mimeType));
} else if (isAudio) {
return MimeTypes.AUDIO_VORBIS.equals(mimeType);
}
}
return false;
}
@Override @Override
public int addTrack(Format format) { public int addTrack(Format format) {
String sampleMimeType = checkNotNull(format.sampleMimeType); String sampleMimeType = checkNotNull(format.sampleMimeType);

View File

@ -25,11 +25,12 @@ import java.nio.ByteBuffer;
/** /**
* Abstracts media muxing operations. * Abstracts media muxing operations.
* *
* <p>Query whether {@link #supportsSampleMimeType(String) sample MIME types are supported} and * <p>Query whether {@link Factory#supportsOutputMimeType(String) container MIME type} and {@link
* {@link #addTrack(Format) add all tracks}, then {@link #writeSampleData(int, ByteBuffer, boolean, * Factory#supportsSampleMimeType(String, String) sample MIME types} are supported and {@link
* long) write sample data} to mux samples. Once any sample data has been written, it is not * #addTrack(Format) add all tracks}, then {@link #writeSampleData(int, ByteBuffer, boolean, long)
* possible to add tracks. After writing all sample data, {@link #release(boolean) release} the * write sample data} to mux samples. Once any sample data has been written, it is not possible to
* instance to finish writing to the output and return any resources to the system. * add tracks. After writing all sample data, {@link #release(boolean) release} the instance to
* finish writing to the output and return any resources to the system.
*/ */
/* package */ interface Muxer { /* package */ interface Muxer {
@ -62,10 +63,13 @@ import java.nio.ByteBuffer;
/** Returns whether the {@link MimeTypes MIME type} provided is a supported output format. */ /** Returns whether the {@link MimeTypes MIME type} provided is a supported output format. */
boolean supportsOutputMimeType(String mimeType); boolean supportsOutputMimeType(String mimeType);
}
/** Returns whether the sample {@link MimeTypes MIME type} is supported. */ /**
boolean supportsSampleMimeType(@Nullable String mimeType); * Returns whether the sample {@link MimeTypes MIME type} is supported with the given container
* {@link MimeTypes MIME type}.
*/
boolean supportsSampleMimeType(@Nullable String sampleMimeType, String containerMimeType);
}
/** /**
* Adds a track with the specified format, and returns its index (to be passed in subsequent calls * Adds a track with the specified format, and returns its index (to be passed in subsequent calls

View File

@ -45,8 +45,10 @@ import java.nio.ByteBuffer;
private static final long MAX_TRACK_WRITE_AHEAD_US = C.msToUs(500); private static final long MAX_TRACK_WRITE_AHEAD_US = C.msToUs(500);
private final Muxer muxer; private final Muxer muxer;
private final Muxer.Factory muxerFactory;
private final SparseIntArray trackTypeToIndex; private final SparseIntArray trackTypeToIndex;
private final SparseLongArray trackTypeToTimeUs; private final SparseLongArray trackTypeToTimeUs;
private final String containerMimeType;
private int trackCount; private int trackCount;
private int trackFormatCount; private int trackFormatCount;
@ -54,8 +56,10 @@ import java.nio.ByteBuffer;
private @C.TrackType int previousTrackType; private @C.TrackType int previousTrackType;
private long minTrackTimeUs; private long minTrackTimeUs;
public MuxerWrapper(Muxer muxer) { public MuxerWrapper(Muxer muxer, Muxer.Factory muxerFactory, String containerMimeType) {
this.muxer = muxer; this.muxer = muxer;
this.muxerFactory = muxerFactory;
this.containerMimeType = containerMimeType;
trackTypeToIndex = new SparseIntArray(); trackTypeToIndex = new SparseIntArray();
trackTypeToTimeUs = new SparseLongArray(); trackTypeToTimeUs = new SparseLongArray();
previousTrackType = C.TRACK_TYPE_NONE; previousTrackType = C.TRACK_TYPE_NONE;
@ -78,7 +82,7 @@ import java.nio.ByteBuffer;
/** Returns whether the sample {@link MimeTypes MIME type} is supported. */ /** Returns whether the sample {@link MimeTypes MIME type} is supported. */
public boolean supportsSampleMimeType(@Nullable String mimeType) { public boolean supportsSampleMimeType(@Nullable String mimeType) {
return muxer.supportsSampleMimeType(mimeType); return muxerFactory.supportsSampleMimeType(mimeType, containerMimeType);
} }
/** /**

View File

@ -100,6 +100,7 @@ public final class TranscodingTransformer {
private boolean removeVideo; private boolean removeVideo;
private boolean flattenForSlowMotion; private boolean flattenForSlowMotion;
private String outputMimeType; private String outputMimeType;
@Nullable private String audioMimeType;
private TranscodingTransformer.Listener listener; private TranscodingTransformer.Listener listener;
private Looper looper; private Looper looper;
private Clock clock; private Clock clock;
@ -122,6 +123,7 @@ public final class TranscodingTransformer {
this.removeVideo = transcodingTransformer.transformation.removeVideo; this.removeVideo = transcodingTransformer.transformation.removeVideo;
this.flattenForSlowMotion = transcodingTransformer.transformation.flattenForSlowMotion; this.flattenForSlowMotion = transcodingTransformer.transformation.flattenForSlowMotion;
this.outputMimeType = transcodingTransformer.transformation.outputMimeType; this.outputMimeType = transcodingTransformer.transformation.outputMimeType;
this.audioMimeType = transcodingTransformer.transformation.audioMimeType;
this.listener = transcodingTransformer.listener; this.listener = transcodingTransformer.listener;
this.looper = transcodingTransformer.looper; this.looper = transcodingTransformer.looper;
this.clock = transcodingTransformer.clock; this.clock = transcodingTransformer.clock;
@ -212,10 +214,8 @@ public final class TranscodingTransformer {
} }
/** /**
* Sets the MIME type of the output. The default value is {@link MimeTypes#VIDEO_MP4}. The * Sets the MIME type of the output. The default value is {@link MimeTypes#VIDEO_MP4}. Supported
* output MIME type should be supported by the {@link * values are:
* Muxer.Factory#supportsOutputMimeType(String) muxer}. Values supported by the default {@link
* FrameworkMuxer} are:
* *
* <ul> * <ul>
* <li>{@link MimeTypes#VIDEO_MP4} * <li>{@link MimeTypes#VIDEO_MP4}
@ -230,6 +230,31 @@ public final class TranscodingTransformer {
return this; return this;
} }
/**
* Sets the audio MIME type of the output. The default value is to use the same MIME type as the
* input. Supported values are:
*
* <ul>
* <li>when the container MIME type is {@link MimeTypes#VIDEO_MP4}:
* <ul>
* <li>{@link MimeTypes#AUDIO_AAC}
* <li>{@link MimeTypes#AUDIO_AMR_NB}
* <li>{@link MimeTypes#AUDIO_AMR_WB}
* </ul>
* <li>when the container MIME type is {@link MimeTypes#VIDEO_WEBM}:
* <ul>
* <li>{@link MimeTypes#AUDIO_VORBIS}
* </ul>
* </ul>
*
* @param audioMimeType The MIME type of the audio samples in the output.
* @return This builder.
*/
public Builder setAudioMimeType(String audioMimeType) {
this.audioMimeType = audioMimeType;
return this;
}
/** /**
* Sets the {@link TranscodingTransformer.Listener} to listen to the transformation events. * Sets the {@link TranscodingTransformer.Listener} to listen to the transformation events.
* *
@ -290,6 +315,7 @@ public final class TranscodingTransformer {
* @throws IllegalStateException If both audio and video have been removed (otherwise the output * @throws IllegalStateException If both audio and video have been removed (otherwise the output
* would not contain any samples). * would not contain any samples).
* @throws IllegalStateException If the muxer doesn't support the requested output MIME type. * @throws IllegalStateException If the muxer doesn't support the requested output MIME type.
* @throws IllegalStateException If the muxer doesn't support the requested audio MIME type.
*/ */
public TranscodingTransformer build() { public TranscodingTransformer build() {
checkStateNotNull(context); checkStateNotNull(context);
@ -303,8 +329,17 @@ public final class TranscodingTransformer {
checkState( checkState(
muxerFactory.supportsOutputMimeType(outputMimeType), muxerFactory.supportsOutputMimeType(outputMimeType),
"Unsupported output MIME type: " + outputMimeType); "Unsupported output MIME type: " + outputMimeType);
if (audioMimeType != null) {
checkState(
muxerFactory.supportsSampleMimeType(audioMimeType, outputMimeType),
"Unsupported sample MIME type "
+ audioMimeType
+ " for container MIME type "
+ outputMimeType);
}
Transformation transformation = Transformation transformation =
new Transformation(removeAudio, removeVideo, flattenForSlowMotion, outputMimeType); new Transformation(
removeAudio, removeVideo, flattenForSlowMotion, outputMimeType, audioMimeType);
return new TranscodingTransformer( return new TranscodingTransformer(
context, mediaSourceFactory, muxerFactory, transformation, listener, looper, clock); context, mediaSourceFactory, muxerFactory, transformation, listener, looper, clock);
} }
@ -469,7 +504,8 @@ public final class TranscodingTransformer {
throw new IllegalStateException("There is already a transformation in progress."); throw new IllegalStateException("There is already a transformation in progress.");
} }
MuxerWrapper muxerWrapper = new MuxerWrapper(muxer); MuxerWrapper muxerWrapper =
new MuxerWrapper(muxer, muxerFactory, transformation.outputMimeType);
this.muxerWrapper = muxerWrapper; this.muxerWrapper = muxerWrapper;
DefaultTrackSelector trackSelector = new DefaultTrackSelector(context); DefaultTrackSelector trackSelector = new DefaultTrackSelector(context);
trackSelector.setParameters( trackSelector.setParameters(

View File

@ -16,6 +16,8 @@
package com.google.android.exoplayer2.transformer; package com.google.android.exoplayer2.transformer;
import androidx.annotation.Nullable;
/** A media transformation configuration. */ /** A media transformation configuration. */
/* package */ final class Transformation { /* package */ final class Transformation {
@ -23,15 +25,18 @@ package com.google.android.exoplayer2.transformer;
public final boolean removeVideo; public final boolean removeVideo;
public final boolean flattenForSlowMotion; public final boolean flattenForSlowMotion;
public final String outputMimeType; public final String outputMimeType;
@Nullable public final String audioMimeType;
public Transformation( public Transformation(
boolean removeAudio, boolean removeAudio,
boolean removeVideo, boolean removeVideo,
boolean flattenForSlowMotion, boolean flattenForSlowMotion,
String outputMimeType) { String outputMimeType,
@Nullable String audioMimeType) {
this.removeAudio = removeAudio; this.removeAudio = removeAudio;
this.removeVideo = removeVideo; this.removeVideo = removeVideo;
this.flattenForSlowMotion = flattenForSlowMotion; this.flattenForSlowMotion = flattenForSlowMotion;
this.outputMimeType = outputMimeType; this.outputMimeType = outputMimeType;
this.audioMimeType = audioMimeType;
} }
} }

View File

@ -209,10 +209,8 @@ public final class Transformer {
} }
/** /**
* Sets the MIME type of the output. The default value is {@link MimeTypes#VIDEO_MP4}. The * Sets the MIME type of the output. The default value is {@link MimeTypes#VIDEO_MP4}. Supported
* output MIME type should be supported by the {@link * values are:
* Muxer.Factory#supportsOutputMimeType(String) muxer}. Values supported by the default {@link
* FrameworkMuxer} are:
* *
* <ul> * <ul>
* <li>{@link MimeTypes#VIDEO_MP4} * <li>{@link MimeTypes#VIDEO_MP4}
@ -301,7 +299,12 @@ public final class Transformer {
muxerFactory.supportsOutputMimeType(outputMimeType), muxerFactory.supportsOutputMimeType(outputMimeType),
"Unsupported output MIME type: " + outputMimeType); "Unsupported output MIME type: " + outputMimeType);
Transformation transformation = Transformation transformation =
new Transformation(removeAudio, removeVideo, flattenForSlowMotion, outputMimeType); new Transformation(
removeAudio,
removeVideo,
flattenForSlowMotion,
outputMimeType,
/* audioMimeType= */ null);
return new Transformer( return new Transformer(
context, mediaSourceFactory, muxerFactory, transformation, listener, looper, clock); context, mediaSourceFactory, muxerFactory, transformation, listener, looper, clock);
} }
@ -464,7 +467,8 @@ public final class Transformer {
throw new IllegalStateException("There is already a transformation in progress."); throw new IllegalStateException("There is already a transformation in progress.");
} }
MuxerWrapper muxerWrapper = new MuxerWrapper(muxer); MuxerWrapper muxerWrapper =
new MuxerWrapper(muxer, muxerFactory, transformation.outputMimeType);
this.muxerWrapper = muxerWrapper; this.muxerWrapper = muxerWrapper;
DefaultTrackSelector trackSelector = new DefaultTrackSelector(context); DefaultTrackSelector trackSelector = new DefaultTrackSelector(context);
trackSelector.setParameters( trackSelector.setParameters(

View File

@ -350,11 +350,15 @@ import java.nio.ByteBuffer;
throw createRendererException(e, PlaybackException.ERROR_CODE_UNSPECIFIED); throw createRendererException(e, PlaybackException.ERROR_CODE_UNSPECIFIED);
} }
} }
String audioMimeType =
transformation.audioMimeType == null
? checkNotNull(inputFormat).sampleMimeType
: transformation.audioMimeType;
try { try {
encoder = encoder =
MediaCodecAdapterWrapper.createForAudioEncoding( MediaCodecAdapterWrapper.createForAudioEncoding(
new Format.Builder() new Format.Builder()
.setSampleMimeType(checkNotNull(inputFormat).sampleMimeType) .setSampleMimeType(audioMimeType)
.setSampleRate(outputAudioFormat.sampleRate) .setSampleRate(outputAudioFormat.sampleRate)
.setChannelCount(outputAudioFormat.channelCount) .setChannelCount(outputAudioFormat.channelCount)
.setAverageBitrate(DEFAULT_ENCODER_BITRATE) .setAverageBitrate(DEFAULT_ENCODER_BITRATE)

View File

@ -52,7 +52,13 @@ import com.google.android.exoplayer2.util.MimeTypes;
@Nullable String sampleMimeType = format.sampleMimeType; @Nullable String sampleMimeType = format.sampleMimeType;
if (MimeTypes.getTrackType(sampleMimeType) != getTrackType()) { if (MimeTypes.getTrackType(sampleMimeType) != getTrackType()) {
return RendererCapabilities.create(C.FORMAT_UNSUPPORTED_TYPE); return RendererCapabilities.create(C.FORMAT_UNSUPPORTED_TYPE);
} else if (muxerWrapper.supportsSampleMimeType(sampleMimeType)) { } else if ((MimeTypes.isAudio(sampleMimeType)
&& muxerWrapper.supportsSampleMimeType(
transformation.audioMimeType == null
? sampleMimeType
: transformation.audioMimeType))
|| (MimeTypes.isVideo(sampleMimeType)
&& muxerWrapper.supportsSampleMimeType(sampleMimeType))) {
return RendererCapabilities.create(C.FORMAT_HANDLED); return RendererCapabilities.create(C.FORMAT_HANDLED);
} else { } else {
return RendererCapabilities.create(C.FORMAT_UNSUPPORTED_SUBTYPE); return RendererCapabilities.create(C.FORMAT_UNSUPPORTED_SUBTYPE);

View File

@ -26,30 +26,27 @@ import java.util.List;
/** /**
* An implementation of {@link Muxer} that supports dumping information about all interactions (for * An implementation of {@link Muxer} that supports dumping information about all interactions (for
* testing purposes) and delegates the actual muxing operations to a {@link FrameworkMuxer}. * testing purposes) and delegates the actual muxing operations to another {@link Muxer} created
* using the factory provided.
*/ */
public final class TestMuxer implements Muxer, Dumper.Dumpable { public final class TestMuxer implements Muxer, Dumper.Dumpable {
private final Muxer frameworkMuxer; private final Muxer muxer;
private final List<Dumper.Dumpable> dumpables; private final List<Dumper.Dumpable> dumpables;
/** Creates a new test muxer. */ /** Creates a new test muxer. */
public TestMuxer(String path, String outputMimeType) throws IOException { public TestMuxer(String path, String outputMimeType, Muxer.Factory muxerFactory)
frameworkMuxer = new FrameworkMuxer.Factory().create(path, outputMimeType); throws IOException {
muxer = muxerFactory.create(path, outputMimeType);
dumpables = new ArrayList<>(); dumpables = new ArrayList<>();
dumpables.add(dumper -> dumper.add("containerMimeType", outputMimeType)); dumpables.add(dumper -> dumper.add("containerMimeType", outputMimeType));
} }
// Muxer implementation. // Muxer implementation.
@Override
public boolean supportsSampleMimeType(String mimeType) {
return frameworkMuxer.supportsSampleMimeType(mimeType);
}
@Override @Override
public int addTrack(Format format) { public int addTrack(Format format) {
int trackIndex = frameworkMuxer.addTrack(format); int trackIndex = muxer.addTrack(format);
dumpables.add(new DumpableFormat(format, trackIndex)); dumpables.add(new DumpableFormat(format, trackIndex));
return trackIndex; return trackIndex;
} }
@ -58,13 +55,13 @@ public final class TestMuxer implements Muxer, Dumper.Dumpable {
public void writeSampleData( public void writeSampleData(
int trackIndex, ByteBuffer data, boolean isKeyFrame, long presentationTimeUs) { int trackIndex, ByteBuffer data, boolean isKeyFrame, long presentationTimeUs) {
dumpables.add(new DumpableSample(trackIndex, data, isKeyFrame, presentationTimeUs)); dumpables.add(new DumpableSample(trackIndex, data, isKeyFrame, presentationTimeUs));
frameworkMuxer.writeSampleData(trackIndex, data, isKeyFrame, presentationTimeUs); muxer.writeSampleData(trackIndex, data, isKeyFrame, presentationTimeUs);
} }
@Override @Override
public void release(boolean forCancellation) { public void release(boolean forCancellation) {
dumpables.add(dumper -> dumper.add("released", true)); dumpables.add(dumper -> dumper.add("released", true));
frameworkMuxer.release(forCancellation); muxer.release(forCancellation);
} }
// Dumper.Dumpable implementation. // Dumper.Dumpable implementation.

View File

@ -562,16 +562,25 @@ public final class TransformerTest {
} }
private final class TestMuxerFactory implements Muxer.Factory { private final class TestMuxerFactory implements Muxer.Factory {
private final Muxer.Factory frameworkMuxerFactory;
public TestMuxerFactory() {
frameworkMuxerFactory = new FrameworkMuxer.Factory();
}
@Override @Override
public Muxer create(String path, String outputMimeType) throws IOException { public Muxer create(String path, String outputMimeType) throws IOException {
testMuxer = new TestMuxer(path, outputMimeType); testMuxer = new TestMuxer(path, outputMimeType, frameworkMuxerFactory);
return testMuxer; return testMuxer;
} }
@Override @Override
public Muxer create(ParcelFileDescriptor parcelFileDescriptor, String outputMimeType) public Muxer create(ParcelFileDescriptor parcelFileDescriptor, String outputMimeType)
throws IOException { throws IOException {
testMuxer = new TestMuxer("FD:" + parcelFileDescriptor.getFd(), outputMimeType); testMuxer =
new TestMuxer(
"FD:" + parcelFileDescriptor.getFd(), outputMimeType, frameworkMuxerFactory);
return testMuxer; return testMuxer;
} }
@ -579,5 +588,10 @@ public final class TransformerTest {
public boolean supportsOutputMimeType(String mimeType) { public boolean supportsOutputMimeType(String mimeType) {
return true; return true;
} }
@Override
public boolean supportsSampleMimeType(String sampleMimeType, String outputMimeType) {
return frameworkMuxerFactory.supportsSampleMimeType(sampleMimeType, outputMimeType);
}
} }
} }