Commit fe1ffdb9 by hschlueter Committed by tonihei

Throw when inferred sample MIME type is not supported by the muxer.

This is better than silently dropping tracks as done previously. Later,
we will implement fallback to transcoding to a supported MIME type.

PiperOrigin-RevId: 418006258
parent 036a28b2
containerMimeType = video/mp4
format 0:
sampleMimeType = audio/mp4a-latm
channelCount = 1
sampleRate = 44100
pcmEncoding = 2
format 1:
id = 1
sampleMimeType = video/avc
codecs = avc1.640034
......@@ -11,181 +16,355 @@ format 0:
data = length 30, hash F6F3D010
data = length 10, hash 7A0D0F2B
sample:
trackIndex = 0
trackIndex = 1
dataHashCode = -252482306
size = 36477
isKeyFrame = true
presentationTimeUs = 0
sample:
trackIndex = 0
trackIndex = 1
dataHashCode = 67864034
size = 5341
isKeyFrame = false
presentationTimeUs = 67000
sample:
trackIndex = 0
trackIndex = 1
dataHashCode = 897273234
size = 596
isKeyFrame = false
presentationTimeUs = 33000
sample:
trackIndex = 0
trackIndex = 1
dataHashCode = -1549870586
size = 7704
isKeyFrame = false
presentationTimeUs = 200000
sample:
trackIndex = 0
trackIndex = 1
dataHashCode = 672384813
size = 989
isKeyFrame = false
presentationTimeUs = 133000
sample:
trackIndex = 0
trackIndex = 1
dataHashCode = -988996493
size = 721
isKeyFrame = false
presentationTimeUs = 100000
sample:
trackIndex = 0
trackIndex = 1
dataHashCode = 1711151377
size = 519
isKeyFrame = false
presentationTimeUs = 167000
sample:
trackIndex = 0
trackIndex = 1
dataHashCode = -506806036
size = 6160
isKeyFrame = false
presentationTimeUs = 333000
sample:
trackIndex = 0
trackIndex = 1
dataHashCode = 1902167649
size = 953
isKeyFrame = false
presentationTimeUs = 267000
sample:
trackIndex = 0
trackIndex = 1
dataHashCode = 2054873212
size = 620
isKeyFrame = false
presentationTimeUs = 233000
sample:
trackIndex = 0
trackIndex = 1
dataHashCode = 1556608231
size = 405
isKeyFrame = false
presentationTimeUs = 300000
sample:
trackIndex = 0
trackIndex = 1
dataHashCode = -1648978019
size = 4852
isKeyFrame = false
presentationTimeUs = 433000
sample:
trackIndex = 0
trackIndex = 1
dataHashCode = -484808327
size = 547
isKeyFrame = false
presentationTimeUs = 400000
sample:
trackIndex = 0
trackIndex = 1
dataHashCode = -20706048
size = 570
isKeyFrame = false
presentationTimeUs = 367000
sample:
trackIndex = 0
trackIndex = 1
dataHashCode = 2085064574
size = 5525
isKeyFrame = false
presentationTimeUs = 567000
sample:
trackIndex = 0
dataHashCode = 555688582
size = 416
isKeyFrame = true
presentationTimeUs = 0
sample:
trackIndex = 0
dataHashCode = 2000837254
size = 418
isKeyFrame = true
presentationTimeUs = 4717
sample:
trackIndex = 0
dataHashCode = -1593942879
size = 418
isKeyFrame = true
presentationTimeUs = 9456
sample:
trackIndex = 0
dataHashCode = 587837542
size = 418
isKeyFrame = true
presentationTimeUs = 14196
sample:
trackIndex = 0
dataHashCode = -1836423877
size = 418
isKeyFrame = true
presentationTimeUs = 18935
sample:
trackIndex = 0
dataHashCode = 874705099
size = 418
isKeyFrame = true
presentationTimeUs = 23674
sample:
trackIndex = 0
dataHashCode = -269206181
size = 418
isKeyFrame = true
presentationTimeUs = 28413
sample:
trackIndex = 0
dataHashCode = -58682425
size = 418
isKeyFrame = true
presentationTimeUs = 33152
sample:
trackIndex = 0
dataHashCode = -859796970
size = 418
isKeyFrame = true
presentationTimeUs = 37892
sample:
trackIndex = 0
dataHashCode = 711911523
size = 418
isKeyFrame = true
presentationTimeUs = 42631
sample:
trackIndex = 0
dataHashCode = -694513071
size = 418
isKeyFrame = true
presentationTimeUs = 47370
sample:
trackIndex = 0
dataHashCode = -1124371059
size = 418
isKeyFrame = true
presentationTimeUs = 52109
sample:
trackIndex = 0
dataHashCode = 297166745
size = 418
isKeyFrame = true
presentationTimeUs = 56849
sample:
trackIndex = 0
dataHashCode = -937110638
size = 418
isKeyFrame = true
presentationTimeUs = 61588
sample:
trackIndex = 0
dataHashCode = -1050158990
size = 418
isKeyFrame = true
presentationTimeUs = 66327
sample:
trackIndex = 0
dataHashCode = 1109510229
size = 418
isKeyFrame = true
presentationTimeUs = 71066
sample:
trackIndex = 0
dataHashCode = 1297086772
size = 418
isKeyFrame = true
presentationTimeUs = 75805
sample:
trackIndex = 0
dataHashCode = -1739939803
size = 418
isKeyFrame = true
presentationTimeUs = 80545
sample:
trackIndex = 0
dataHashCode = -1149727930
size = 418
isKeyFrame = true
presentationTimeUs = 85284
sample:
trackIndex = 0
dataHashCode = -1627652713
size = 418
isKeyFrame = true
presentationTimeUs = 90023
sample:
trackIndex = 0
dataHashCode = -551926260
size = 418
isKeyFrame = true
presentationTimeUs = 94762
sample:
trackIndex = 0
dataHashCode = 45987178
size = 418
isKeyFrame = true
presentationTimeUs = 99502
sample:
trackIndex = 0
dataHashCode = -903675808
size = 418
isKeyFrame = true
presentationTimeUs = 104241
sample:
trackIndex = 0
dataHashCode = -755916991
size = 418
isKeyFrame = true
presentationTimeUs = 108980
sample:
trackIndex = 0
dataHashCode = -1355207303
size = 418
isKeyFrame = true
presentationTimeUs = 113719
sample:
trackIndex = 0
dataHashCode = -975703389
size = 418
isKeyFrame = true
presentationTimeUs = 118459
sample:
trackIndex = 0
dataHashCode = 1933194670
size = 418
isKeyFrame = true
presentationTimeUs = 123198
sample:
trackIndex = 0
dataHashCode = -565778989
size = 418
isKeyFrame = true
presentationTimeUs = 127937
sample:
trackIndex = 0
dataHashCode = 1454083383
size = 418
isKeyFrame = true
presentationTimeUs = 132676
sample:
trackIndex = 1
dataHashCode = -637074022
size = 1082
isKeyFrame = false
presentationTimeUs = 500000
sample:
trackIndex = 0
trackIndex = 1
dataHashCode = -1824027029
size = 807
isKeyFrame = false
presentationTimeUs = 467000
sample:
trackIndex = 0
trackIndex = 1
dataHashCode = -1701945306
size = 744
isKeyFrame = false
presentationTimeUs = 533000
sample:
trackIndex = 0
trackIndex = 1
dataHashCode = -952425536
size = 4732
isKeyFrame = false
presentationTimeUs = 700000
sample:
trackIndex = 0
trackIndex = 1
dataHashCode = -1978031576
size = 1004
isKeyFrame = false
presentationTimeUs = 633000
sample:
trackIndex = 0
trackIndex = 1
dataHashCode = -2128215508
size = 794
isKeyFrame = false
presentationTimeUs = 600000
sample:
trackIndex = 0
trackIndex = 1
dataHashCode = -259850011
size = 645
isKeyFrame = false
presentationTimeUs = 667000
sample:
trackIndex = 0
trackIndex = 1
dataHashCode = 1920983928
size = 2684
isKeyFrame = false
presentationTimeUs = 833000
sample:
trackIndex = 0
trackIndex = 1
dataHashCode = 1100642337
size = 787
isKeyFrame = false
presentationTimeUs = 767000
sample:
trackIndex = 0
trackIndex = 1
dataHashCode = 1544917830
size = 649
isKeyFrame = false
presentationTimeUs = 733000
sample:
trackIndex = 0
trackIndex = 1
dataHashCode = -116205995
size = 509
isKeyFrame = false
presentationTimeUs = 800000
sample:
trackIndex = 0
trackIndex = 1
dataHashCode = 696343585
size = 1226
isKeyFrame = false
presentationTimeUs = 967000
sample:
trackIndex = 0
trackIndex = 1
dataHashCode = -644371190
size = 898
isKeyFrame = false
presentationTimeUs = 900000
sample:
trackIndex = 0
trackIndex = 1
dataHashCode = -1606273467
size = 476
isKeyFrame = false
presentationTimeUs = 867000
sample:
trackIndex = 0
trackIndex = 1
dataHashCode = -571265861
size = 486
isKeyFrame = false
......
containerMimeType = video/mp4
format 0:
id = 1
sampleMimeType = video/avc
codecs = avc1.64001F
maxInputSize = 36722
width = 1080
height = 720
frameRate = 29.970028
colorInfo:
colorSpace = 1
colorRange = 2
colorTransfer = 3
hdrStaticInfo = length 0, hash 0
initializationData:
data = length 29, hash 4746B5D9
data = length 10, hash 7A0D0F2B
sample:
trackIndex = 0
dataHashCode = -770308242
size = 36692
isKeyFrame = true
presentationTimeUs = 0
sample:
trackIndex = 0
dataHashCode = -732087136
size = 5312
isKeyFrame = false
presentationTimeUs = 66733
sample:
trackIndex = 0
dataHashCode = 468156717
size = 599
isKeyFrame = false
presentationTimeUs = 33366
sample:
trackIndex = 0
dataHashCode = 1150349584
size = 7735
isKeyFrame = false
presentationTimeUs = 200200
sample:
trackIndex = 0
dataHashCode = 1443582006
size = 987
isKeyFrame = false
presentationTimeUs = 133466
sample:
trackIndex = 0
dataHashCode = -310585145
size = 673
isKeyFrame = false
presentationTimeUs = 100100
sample:
trackIndex = 0
dataHashCode = 807460688
size = 523
isKeyFrame = false
presentationTimeUs = 166833
sample:
trackIndex = 0
dataHashCode = 1936487090
size = 6061
isKeyFrame = false
presentationTimeUs = 333666
sample:
trackIndex = 0
dataHashCode = -32297181
size = 992
isKeyFrame = false
presentationTimeUs = 266933
sample:
trackIndex = 0
dataHashCode = 1529616406
size = 623
isKeyFrame = false
presentationTimeUs = 233566
sample:
trackIndex = 0
dataHashCode = 1949198785
size = 421
isKeyFrame = false
presentationTimeUs = 300300
sample:
trackIndex = 0
dataHashCode = -147880287
size = 4899
isKeyFrame = false
presentationTimeUs = 433766
sample:
trackIndex = 0
dataHashCode = 1369083472
size = 568
isKeyFrame = false
presentationTimeUs = 400400
sample:
trackIndex = 0
dataHashCode = 965782073
size = 620
isKeyFrame = false
presentationTimeUs = 367033
sample:
trackIndex = 0
dataHashCode = -261176150
size = 5450
isKeyFrame = false
presentationTimeUs = 567233
sample:
trackIndex = 0
dataHashCode = -1830836678
size = 1051
isKeyFrame = false
presentationTimeUs = 500500
sample:
trackIndex = 0
dataHashCode = 1767407540
size = 874
isKeyFrame = false
presentationTimeUs = 467133
sample:
trackIndex = 0
dataHashCode = 918440283
size = 781
isKeyFrame = false
presentationTimeUs = 533866
sample:
trackIndex = 0
dataHashCode = -1408463661
size = 4725
isKeyFrame = false
presentationTimeUs = 700700
sample:
trackIndex = 0
dataHashCode = 1569455924
size = 1022
isKeyFrame = false
presentationTimeUs = 633966
sample:
trackIndex = 0
dataHashCode = -1723778407
size = 790
isKeyFrame = false
presentationTimeUs = 600600
sample:
trackIndex = 0
dataHashCode = 1578275472
size = 610
isKeyFrame = false
presentationTimeUs = 667333
sample:
trackIndex = 0
dataHashCode = 1989768395
size = 2751
isKeyFrame = false
presentationTimeUs = 834166
sample:
trackIndex = 0
dataHashCode = -1215674502
size = 745
isKeyFrame = false
presentationTimeUs = 767433
sample:
trackIndex = 0
dataHashCode = -814473606
size = 621
isKeyFrame = false
presentationTimeUs = 734066
sample:
trackIndex = 0
dataHashCode = 498370894
size = 505
isKeyFrame = false
presentationTimeUs = 800800
sample:
trackIndex = 0
dataHashCode = -1051506468
size = 1268
isKeyFrame = false
presentationTimeUs = 967633
sample:
trackIndex = 0
dataHashCode = -1025604144
size = 880
isKeyFrame = false
presentationTimeUs = 900900
sample:
trackIndex = 0
dataHashCode = -913586520
size = 530
isKeyFrame = false
presentationTimeUs = 867533
sample:
trackIndex = 0
dataHashCode = 1340459242
size = 568
isKeyFrame = false
presentationTimeUs = 934266
released = true
......@@ -161,6 +161,16 @@ public final class TransformationException extends Exception {
/** Caused by an audio processor initialization failure. */
public static final int ERROR_CODE_AUDIO_PROCESSOR_INIT_FAILED = 6001;
// Muxing errors (7xxx).
/**
* Caused by an output sample MIME type inferred from the input not being supported by the muxer.
*
* <p>Use {@link TransformationRequest.Builder#setAudioMimeType(String)} or {@link
* TransformationRequest.Builder#setVideoMimeType(String)} to transcode to a supported MIME type.
*/
public static final int ERROR_CODE_MUXER_SAMPLE_MIME_TYPE_UNSUPPORTED = 7001;
private static final ImmutableBiMap<String, @ErrorCode Integer> NAME_TO_ERROR_CODE =
new ImmutableBiMap.Builder<String, @ErrorCode Integer>()
.put("ERROR_CODE_FAILED_RUNTIME_CHECK", ERROR_CODE_FAILED_RUNTIME_CHECK)
......@@ -182,6 +192,9 @@ public final class TransformationException extends Exception {
.put("ERROR_CODE_GL_INIT_FAILED", ERROR_CODE_GL_INIT_FAILED)
.put("ERROR_CODE_GL_PROCESSING_FAILED", ERROR_CODE_GL_PROCESSING_FAILED)
.put("ERROR_CODE_AUDIO_PROCESSOR_INIT_FAILED", ERROR_CODE_AUDIO_PROCESSOR_INIT_FAILED)
.put(
"ERROR_CODE_MUXER_SAMPLE_MIME_TYPE_UNSUPPORTED",
ERROR_CODE_MUXER_SAMPLE_MIME_TYPE_UNSUPPORTED)
.buildOrThrow();
/** Returns the {@code errorCode} for a given name. */
......@@ -233,6 +246,17 @@ public final class TransformationException extends Exception {
}
/**
* Creates an instance for a muxer related exception.
*
* @param cause The cause of the failure.
* @param errorCode See {@link #errorCode}.
* @return The created instance.
*/
/* package */ static TransformationException createForMuxer(Throwable cause, int errorCode) {
return new TransformationException("Muxer error", cause, errorCode);
}
/**
* Creates an instance for an unexpected exception.
*
* <p>If the exception is a runtime exception, error code {@link #ERROR_CODE_FAILED_RUNTIME_CHECK}
......
......@@ -808,13 +808,9 @@ public final class Transformer {
@Override
public void onTracksInfoChanged(TracksInfo tracksInfo) {
if (muxerWrapper.getTrackCount() == 0) {
// TODO(b/209469847): Do not silently drop unsupported tracks and throw a more specific
// exception earlier.
handleTransformationEnded(
TransformationException.createForUnexpected(
new IllegalStateException(
"The output does not contain any tracks. Check that at least one of the input"
+ " sample formats is supported.")));
new IllegalStateException("The output does not contain any tracks.")));
}
}
......
......@@ -16,6 +16,7 @@
package androidx.media3.transformer;
import static androidx.media3.common.util.Assertions.checkState;
import static androidx.media3.common.util.Assertions.checkStateNotNull;
import androidx.annotation.Nullable;
......@@ -57,26 +58,46 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
this.transformationRequest = transformationRequest;
}
/**
* Returns whether the renderer supports the track type of the given input format.
*
* @param inputFormat The input format.
* @return The {@link Capabilities} for this format.
* @throws ExoPlaybackException If the muxer does not support the output sample MIME type derived
* from the input {@code format} and {@link TransformationRequest}.
*/
@Override
@C.FormatSupport
public final int supportsFormat(Format format) {
@Nullable String sampleMimeType = format.sampleMimeType;
if (MimeTypes.getTrackType(sampleMimeType) != getTrackType()) {
@Capabilities
public final int supportsFormat(Format inputFormat) throws ExoPlaybackException {
@Nullable String inputSampleMimeType = inputFormat.sampleMimeType;
if (inputSampleMimeType == null
|| MimeTypes.getTrackType(inputSampleMimeType) != getTrackType()) {
return RendererCapabilities.create(C.FORMAT_UNSUPPORTED_TYPE);
} else if ((MimeTypes.isAudio(sampleMimeType)
&& muxerWrapper.supportsSampleMimeType(
transformationRequest.audioMimeType == null
? sampleMimeType
: transformationRequest.audioMimeType))
|| (MimeTypes.isVideo(sampleMimeType)
&& muxerWrapper.supportsSampleMimeType(
transformationRequest.videoMimeType == null
? sampleMimeType
: transformationRequest.videoMimeType))) {
}
// If the output sample MIME type is given in the transformationRequest it has already been
// validated by the builder.
if (MimeTypes.isAudio(inputSampleMimeType) && transformationRequest.audioMimeType != null) {
checkState(muxerWrapper.supportsSampleMimeType(transformationRequest.audioMimeType));
return RendererCapabilities.create(C.FORMAT_HANDLED);
}
if (MimeTypes.isVideo(inputSampleMimeType) && transformationRequest.videoMimeType != null) {
checkState(muxerWrapper.supportsSampleMimeType(transformationRequest.videoMimeType));
return RendererCapabilities.create(C.FORMAT_HANDLED);
} else {
return RendererCapabilities.create(C.FORMAT_UNSUPPORTED_SUBTYPE);
}
// When the output sample MIME type is not given in the transformationRequest, it is inferred
// from the input.
if (muxerWrapper.supportsSampleMimeType(inputSampleMimeType)) {
return RendererCapabilities.create(C.FORMAT_HANDLED);
}
throw wrapTransformationException(
TransformationException.createForMuxer(
new IllegalArgumentException(
"The sample MIME inferred from the input is not supported by the muxer. "
+ "Input sample MIME type: "
+ inputSampleMimeType),
TransformationException.ERROR_CODE_MUXER_SAMPLE_MIME_TYPE_UNSUPPORTED));
}
@Override
......@@ -103,16 +124,7 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
while (feedMuxerFromPipeline() || samplePipeline.processData() || feedPipelineFromInput()) {}
} catch (TransformationException e) {
// Transformer extracts the TransformationException from this ExoPlaybackException again. This
// temporary wrapping is needed due to the dependence on ExoPlayer's BaseRenderer.
throw ExoPlaybackException.createForRenderer(
e,
"Transformer",
getIndex(),
/* rendererFormat= */ null,
C.FORMAT_HANDLED,
/* isRecoverable= */ false,
PlaybackException.ERROR_CODE_UNSPECIFIED);
throw wrapTransformationException(e);
}
}
......@@ -226,4 +238,23 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
return false;
}
}
/**
* Returns an {@link ExoPlaybackException} wrapping the {@link TransformationException}.
*
* <p>This temporary wrapping is needed due to the dependence on ExoPlayer's BaseRenderer. {@link
* Transformer} extracts the {@link TransformationException} from this {@link
* ExoPlaybackException} again.
*/
private ExoPlaybackException wrapTransformationException(
TransformationException transformationException) {
return ExoPlaybackException.createForRenderer(
transformationException,
"Transformer",
getIndex(),
/* rendererFormat= */ null,
C.FORMAT_HANDLED,
/* isRecoverable= */ false,
PlaybackException.ERROR_CODE_UNSPECIFIED);
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment