Fix wav format pcm encoding detection error
(cherry picked from commit 8a9aec9c40df6eccf8dce88ccb7089147ae9ffef)
This commit is contained in:
parent
7e023f915b
commit
921b7a58c8
@ -25,6 +25,7 @@ import java.nio.ByteBuffer;
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Arrays;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Wraps a byte array, providing a set of methods for parsing data from it. Numerical values are
|
||||
@ -661,6 +662,26 @@ public final class ParsableByteArray {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads microsoft GUID as java UUID
|
||||
*
|
||||
* @throws IllegalStateException if there is not enough data decoding
|
||||
* @return Decoded UUID
|
||||
* */
|
||||
public UUID readMSGUID() {
|
||||
if (bytesLeft() < 16) {
|
||||
throw new IllegalStateException("Not enough data");
|
||||
}
|
||||
// flip little ending to big ending
|
||||
// https://learn.microsoft.com/en-us/windows/win32/api/guiddef/ns-guiddef-guid
|
||||
long d1 = readLittleEndianUnsignedInt();
|
||||
long d2 = readLittleEndianUnsignedShort();
|
||||
long d3 = readLittleEndianUnsignedShort();
|
||||
long mostSigBits = d1 << 32 | d2 << 16 | d3;
|
||||
long leastSigBits = readLong();
|
||||
return new UUID(mostSigBits, leastSigBits);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the index of the next occurrence of '\n' or '\r', or {@link #limit} if none is found.
|
||||
*/
|
||||
|
@ -20,6 +20,8 @@ import androidx.media3.common.Format;
|
||||
import androidx.media3.common.util.UnstableApi;
|
||||
import androidx.media3.common.util.Util;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/** Utilities for handling WAVE files. */
|
||||
@UnstableApi
|
||||
public final class WavUtil {
|
||||
@ -60,6 +62,14 @@ public final class WavUtil {
|
||||
/** WAVE type value for extended WAVE format. */
|
||||
public static final int TYPE_WAVE_FORMAT_EXTENSIBLE = 0xFFFE;
|
||||
|
||||
public static final UUID KSDATAFORMAT_SUBTYPE_PCM = UUID.fromString("00000001-0000-0010-8000-00aa00389b71");
|
||||
|
||||
public static final UUID KSDATAFORMAT_SUBTYPE_IEEE_FLOAT = UUID.fromString("00000003-0000-0010-8000-00aa00389b71");
|
||||
|
||||
public static final UUID KSDATAFORMAT_SUBTYPE_ALAW = UUID.fromString("00000006-0000-0010-8000-00aa00389b71");
|
||||
|
||||
public static final UUID KSDATAFORMAT_SUBTYPE_MULAW = UUID.fromString("00000007-0000-0010-8000-00aa00389b71");
|
||||
|
||||
/**
|
||||
* Returns the WAVE format type value for the given {@link C.PcmEncoding}.
|
||||
*
|
||||
|
@ -175,9 +175,19 @@ public final class WavExtractor implements Extractor {
|
||||
@RequiresNonNull({"extractorOutput", "trackOutput"})
|
||||
private void readFormat(ExtractorInput input) throws IOException {
|
||||
WavFormat wavFormat = WavHeaderReader.readFormat(input);
|
||||
// WAVE_FORMAT_EXTENSIBLE Determined by SubFormat
|
||||
// available SubFormats (GUID , Decoder)
|
||||
// ("00000001-0000-0010-8000-00aa00389b71", KSDATAFORMAT_SUBTYPE_PCM)
|
||||
// ("00000003-0000-0010-8000-00aa00389b71", KSDATAFORMAT_SUBTYPE_IEEE_FLOAT)
|
||||
// ("00000006-0000-0010-8000-00aa00389b71", KSDATAFORMAT_SUBTYPE_ALAW)
|
||||
// ("00000007-0000-0010-8000-00aa00389b71", KSDATAFORMAT_SUBTYPE_MULAW)
|
||||
// full subformat GUIDs for compressed audio formats
|
||||
// https://learn.microsoft.com/en-us/windows-hardware/drivers/audio/subformat-guids-for-compressed-audio-formats
|
||||
if (wavFormat.formatType == WavUtil.TYPE_IMA_ADPCM) {
|
||||
outputWriter = new ImaAdPcmOutputWriter(extractorOutput, trackOutput, wavFormat);
|
||||
} else if (wavFormat.formatType == WavUtil.TYPE_ALAW) {
|
||||
} else if (wavFormat.formatType == WavUtil.TYPE_ALAW ||
|
||||
wavFormat.formatType == WavUtil.TYPE_WAVE_FORMAT_EXTENSIBLE &&
|
||||
WavUtil.KSDATAFORMAT_SUBTYPE_ALAW.equals(wavFormat.uuid)) {
|
||||
outputWriter =
|
||||
new PassthroughOutputWriter(
|
||||
extractorOutput,
|
||||
@ -185,7 +195,9 @@ public final class WavExtractor implements Extractor {
|
||||
wavFormat,
|
||||
MimeTypes.AUDIO_ALAW,
|
||||
/* pcmEncoding= */ Format.NO_VALUE);
|
||||
} else if (wavFormat.formatType == WavUtil.TYPE_MLAW) {
|
||||
} else if (wavFormat.formatType == WavUtil.TYPE_MLAW ||
|
||||
wavFormat.formatType == WavUtil.TYPE_WAVE_FORMAT_EXTENSIBLE &&
|
||||
WavUtil.KSDATAFORMAT_SUBTYPE_MULAW.equals(wavFormat.uuid)) {
|
||||
outputWriter =
|
||||
new PassthroughOutputWriter(
|
||||
extractorOutput,
|
||||
@ -197,6 +209,10 @@ public final class WavExtractor implements Extractor {
|
||||
@C.PcmEncoding
|
||||
int pcmEncoding =
|
||||
WavUtil.getPcmEncodingForType(wavFormat.formatType, wavFormat.bitsPerSample);
|
||||
if (wavFormat.formatType == WavUtil.TYPE_WAVE_FORMAT_EXTENSIBLE &&
|
||||
WavUtil.KSDATAFORMAT_SUBTYPE_IEEE_FLOAT.equals(wavFormat.uuid)) {
|
||||
pcmEncoding = C.ENCODING_PCM_FLOAT;
|
||||
}
|
||||
if (pcmEncoding == C.ENCODING_INVALID) {
|
||||
throw ParserException.createForUnsupportedContainerFeature(
|
||||
"Unsupported WAV format type: " + wavFormat.formatType);
|
||||
|
@ -15,6 +15,9 @@
|
||||
*/
|
||||
package androidx.media3.extractor.wav;
|
||||
|
||||
import java.util.UUID;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/** Format information for a WAV file. */
|
||||
/* package */ final class WavFormat {
|
||||
|
||||
@ -42,6 +45,16 @@ package androidx.media3.extractor.wav;
|
||||
/** Extra data appended to the format chunk. */
|
||||
public final byte[] extraData;
|
||||
|
||||
/** Number of valid bits */
|
||||
public final int validBitsPerSample;
|
||||
|
||||
/** Speaker position mask */
|
||||
public final int channelMask;
|
||||
|
||||
/** GUID, including the data format code */
|
||||
@Nullable
|
||||
public final UUID uuid;
|
||||
|
||||
public WavFormat(
|
||||
int formatType,
|
||||
int numChannels,
|
||||
@ -57,5 +70,32 @@ package androidx.media3.extractor.wav;
|
||||
this.blockSize = blockSize;
|
||||
this.bitsPerSample = bitsPerSample;
|
||||
this.extraData = extraData;
|
||||
this.validBitsPerSample = 0;
|
||||
this.channelMask = 0;
|
||||
this.uuid = null;
|
||||
}
|
||||
|
||||
public WavFormat(
|
||||
int formatType,
|
||||
int numChannels,
|
||||
int frameRateHz,
|
||||
int averageBytesPerSecond,
|
||||
int blockSize,
|
||||
int bitsPerSample,
|
||||
byte[] extraData,
|
||||
int validBitsPerSample,
|
||||
int channelMask,
|
||||
@Nullable UUID uuid) {
|
||||
this.formatType = formatType;
|
||||
this.numChannels = numChannels;
|
||||
this.frameRateHz = frameRateHz;
|
||||
this.averageBytesPerSecond = averageBytesPerSecond;
|
||||
this.blockSize = blockSize;
|
||||
this.bitsPerSample = bitsPerSample;
|
||||
this.extraData = extraData;
|
||||
this.validBitsPerSample = validBitsPerSample;
|
||||
this.channelMask = channelMask;
|
||||
this.uuid = uuid;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -25,6 +25,7 @@ import androidx.media3.common.util.Util;
|
||||
import androidx.media3.extractor.ExtractorInput;
|
||||
import androidx.media3.extractor.WavUtil;
|
||||
import java.io.IOException;
|
||||
import java.util.UUID;
|
||||
|
||||
/** Reads a WAV header from an input stream; supports resuming from input failures. */
|
||||
/* package */ final class WavHeaderReader {
|
||||
@ -109,9 +110,21 @@ import java.io.IOException;
|
||||
|
||||
int bytesLeft = (int) chunkHeader.size - 16;
|
||||
byte[] extraData;
|
||||
int validBitsPerSample = 0;
|
||||
int channelMask = 0;
|
||||
UUID uuid = null;
|
||||
|
||||
if (bytesLeft > 0) {
|
||||
extraData = new byte[bytesLeft];
|
||||
input.peekFully(extraData, 0, bytesLeft);
|
||||
if (bytesLeft == 24) {
|
||||
ParsableByteArray extra = new ParsableByteArray(extraData);
|
||||
// ignore useless extra data length ( 0 or 22 )
|
||||
int cbSize = extra.readLittleEndianUnsignedShort();
|
||||
validBitsPerSample = extra.readLittleEndianUnsignedShort();
|
||||
channelMask = extra.readLittleEndianUnsignedIntToInt();
|
||||
uuid = extra.readMSGUID();
|
||||
}
|
||||
} else {
|
||||
extraData = Util.EMPTY_BYTE_ARRAY;
|
||||
}
|
||||
@ -124,7 +137,10 @@ import java.io.IOException;
|
||||
averageBytesPerSecond,
|
||||
blockSize,
|
||||
bitsPerSample,
|
||||
extraData);
|
||||
extraData,
|
||||
validBitsPerSample,
|
||||
channelMask,
|
||||
uuid);
|
||||
}
|
||||
|
||||
/**
|
||||
|
Loading…
x
Reference in New Issue
Block a user