Commit 7d847a95 by kimvde Committed by Ian Baker

Handle sample size mismatch in MP4 extractors

#minor-release

PiperOrigin-RevId: 351756333
parent 9b062053
...@@ -106,6 +106,8 @@ ...@@ -106,6 +106,8 @@
* Populate codecs string for H.265/HEVC in MP4, Matroska and MPEG-TS * Populate codecs string for H.265/HEVC in MP4, Matroska and MPEG-TS
streams to allow decoder capability checks based on codec profile/level streams to allow decoder capability checks based on codec profile/level
([#8393](https://github.com/google/ExoPlayer/issues/8393)). ([#8393](https://github.com/google/ExoPlayer/issues/8393)).
* Handle sample size mismatches between raw audio PCM encoding and `stsz`
sample size in MP4 extractors.
* Track selection: * Track selection:
* Allow parallel adaptation for video and audio * Allow parallel adaptation for video and audio
([#5111](https://github.com/google/ExoPlayer/issues/5111)). ([#5111](https://github.com/google/ExoPlayer/issues/5111)).
......
...@@ -1674,24 +1674,23 @@ public final class Util { ...@@ -1674,24 +1674,23 @@ public final class Util {
} }
/** /**
* Returns the frame size for audio with {@code channelCount} channels in the specified encoding. * Returns the sample size for audio in the specified encoding.
* *
* @param pcmEncoding The encoding of the audio data. * @param pcmEncoding The encoding of the audio data.
* @param channelCount The channel count. * @return The size of one audio sample in bytes.
* @return The size of one audio frame in bytes.
*/ */
public static int getPcmFrameSize(@C.PcmEncoding int pcmEncoding, int channelCount) { public static int getPcmSampleSize(@C.PcmEncoding int pcmEncoding) {
switch (pcmEncoding) { switch (pcmEncoding) {
case C.ENCODING_PCM_8BIT: case C.ENCODING_PCM_8BIT:
return channelCount; return 1;
case C.ENCODING_PCM_16BIT: case C.ENCODING_PCM_16BIT:
case C.ENCODING_PCM_16BIT_BIG_ENDIAN: case C.ENCODING_PCM_16BIT_BIG_ENDIAN:
return channelCount * 2; return 2;
case C.ENCODING_PCM_24BIT: case C.ENCODING_PCM_24BIT:
return channelCount * 3; return 3;
case C.ENCODING_PCM_32BIT: case C.ENCODING_PCM_32BIT:
case C.ENCODING_PCM_FLOAT: case C.ENCODING_PCM_FLOAT:
return channelCount * 4; return 4;
case C.ENCODING_INVALID: case C.ENCODING_INVALID:
case Format.NO_VALUE: case Format.NO_VALUE:
default: default:
...@@ -1700,6 +1699,17 @@ public final class Util { ...@@ -1700,6 +1699,17 @@ public final class Util {
} }
/** /**
* Returns the frame size for audio with {@code channelCount} channels in the specified encoding.
*
* @param pcmEncoding The encoding of the audio data.
* @param channelCount The channel count.
* @return The size of one audio frame in bytes.
*/
public static int getPcmFrameSize(@C.PcmEncoding int pcmEncoding, int channelCount) {
return getPcmSampleSize(pcmEncoding) * channelCount;
}
/**
* Returns the {@link C.AudioUsage} corresponding to the specified {@link C.StreamType}. * Returns the {@link C.AudioUsage} corresponding to the specified {@link C.StreamType}.
*/ */
@C.AudioUsage @C.AudioUsage
......
...@@ -315,7 +315,7 @@ import org.checkerframework.checker.nullness.compatqual.NullableType; ...@@ -315,7 +315,7 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
SampleSizeBox sampleSizeBox; SampleSizeBox sampleSizeBox;
@Nullable Atom.LeafAtom stszAtom = stblAtom.getLeafAtomOfType(Atom.TYPE_stsz); @Nullable Atom.LeafAtom stszAtom = stblAtom.getLeafAtomOfType(Atom.TYPE_stsz);
if (stszAtom != null) { if (stszAtom != null) {
sampleSizeBox = new StszSampleSizeBox(stszAtom); sampleSizeBox = new StszSampleSizeBox(stszAtom, track.format);
} else { } else {
@Nullable Atom.LeafAtom stz2Atom = stblAtom.getLeafAtomOfType(Atom.TYPE_stz2); @Nullable Atom.LeafAtom stz2Atom = stblAtom.getLeafAtomOfType(Atom.TYPE_stz2);
if (stz2Atom == null) { if (stz2Atom == null) {
...@@ -1720,10 +1720,25 @@ import org.checkerframework.checker.nullness.compatqual.NullableType; ...@@ -1720,10 +1720,25 @@ import org.checkerframework.checker.nullness.compatqual.NullableType;
private final int sampleCount; private final int sampleCount;
private final ParsableByteArray data; private final ParsableByteArray data;
public StszSampleSizeBox(Atom.LeafAtom stszAtom) { public StszSampleSizeBox(Atom.LeafAtom stszAtom, Format trackFormat) {
data = stszAtom.data; data = stszAtom.data;
data.setPosition(Atom.FULL_HEADER_SIZE); data.setPosition(Atom.FULL_HEADER_SIZE);
int fixedSampleSize = data.readUnsignedIntToInt(); int fixedSampleSize = data.readUnsignedIntToInt();
if (MimeTypes.AUDIO_RAW.equals(trackFormat.sampleMimeType)) {
@C.PcmEncoding int pcmEncoding = trackFormat.pcmEncoding;
int pcmSampleSize = Util.getPcmSampleSize(pcmEncoding);
if (pcmSampleSize != fixedSampleSize) {
// The sample size from the stsz box is inconsistent with the PCM encoding derived from
// the stsd box. Choose the PCM encoding as source of truth [Internal ref: b/171627904].
Log.w(
TAG,
"Audio sample size mismatch. PCM encoding: "
+ pcmEncoding
+ ", stsz sample size = "
+ fixedSampleSize);
fixedSampleSize = pcmSampleSize;
}
}
this.fixedSampleSize = fixedSampleSize == 0 ? C.LENGTH_UNSET : fixedSampleSize; this.fixedSampleSize = fixedSampleSize == 0 ? C.LENGTH_UNSET : fixedSampleSize;
sampleCount = data.readUnsignedIntToInt(); sampleCount = data.readUnsignedIntToInt();
} }
......
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