mirror of
https://github.com/samsonjs/media.git
synced 2026-04-11 12:15:47 +00:00
Standardize ALAC initialization data
Android considers ALAC initialization data to consider of the magic cookie only, where-as FFmpeg requires a full atom. Standardize around the Android definition, since it makes more sense (the magic cookie being contained within an atom is container specific, where-as the decoder shouldn't care what container the media stream is carried in) Issue: #5938 PiperOrigin-RevId: 261124155
This commit is contained in:
parent
95ed5ce65d
commit
cb8983afd1
2 changed files with 35 additions and 18 deletions
|
|
@ -172,28 +172,49 @@ import java.util.List;
|
|||
private static @Nullable byte[] getExtraData(String mimeType, List<byte[]> initializationData) {
|
||||
switch (mimeType) {
|
||||
case MimeTypes.AUDIO_AAC:
|
||||
case MimeTypes.AUDIO_ALAC:
|
||||
case MimeTypes.AUDIO_OPUS:
|
||||
return initializationData.get(0);
|
||||
case MimeTypes.AUDIO_ALAC:
|
||||
return getAlacExtraData(initializationData);
|
||||
case MimeTypes.AUDIO_VORBIS:
|
||||
byte[] header0 = initializationData.get(0);
|
||||
byte[] header1 = initializationData.get(1);
|
||||
byte[] extraData = new byte[header0.length + header1.length + 6];
|
||||
extraData[0] = (byte) (header0.length >> 8);
|
||||
extraData[1] = (byte) (header0.length & 0xFF);
|
||||
System.arraycopy(header0, 0, extraData, 2, header0.length);
|
||||
extraData[header0.length + 2] = 0;
|
||||
extraData[header0.length + 3] = 0;
|
||||
extraData[header0.length + 4] = (byte) (header1.length >> 8);
|
||||
extraData[header0.length + 5] = (byte) (header1.length & 0xFF);
|
||||
System.arraycopy(header1, 0, extraData, header0.length + 6, header1.length);
|
||||
return extraData;
|
||||
return getVorbisExtraData(initializationData);
|
||||
default:
|
||||
// Other codecs do not require extra data.
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static byte[] getAlacExtraData(List<byte[]> initializationData) {
|
||||
// FFmpeg's ALAC decoder expects an ALAC atom, which contains the ALAC "magic cookie", as extra
|
||||
// data. initializationData[0] contains only the magic cookie, and so we need to package it into
|
||||
// an ALAC atom. See:
|
||||
// https://ffmpeg.org/doxygen/0.6/alac_8c.html
|
||||
// https://github.com/macosforge/alac/blob/master/ALACMagicCookieDescription.txt
|
||||
byte[] magicCookie = initializationData.get(0);
|
||||
int alacAtomLength = 12 + magicCookie.length;
|
||||
ByteBuffer alacAtom = ByteBuffer.allocate(alacAtomLength);
|
||||
alacAtom.putInt(alacAtomLength);
|
||||
alacAtom.putInt(0x616c6163); // type=alac
|
||||
alacAtom.putInt(0); // version=0, flags=0
|
||||
alacAtom.put(magicCookie, /* offset= */ 0, magicCookie.length);
|
||||
return alacAtom.array();
|
||||
}
|
||||
|
||||
private static byte[] getVorbisExtraData(List<byte[]> initializationData) {
|
||||
byte[] header0 = initializationData.get(0);
|
||||
byte[] header1 = initializationData.get(1);
|
||||
byte[] extraData = new byte[header0.length + header1.length + 6];
|
||||
extraData[0] = (byte) (header0.length >> 8);
|
||||
extraData[1] = (byte) (header0.length & 0xFF);
|
||||
System.arraycopy(header0, 0, extraData, 2, header0.length);
|
||||
extraData[header0.length + 2] = 0;
|
||||
extraData[header0.length + 3] = 0;
|
||||
extraData[header0.length + 4] = (byte) (header1.length >> 8);
|
||||
extraData[header0.length + 5] = (byte) (header1.length & 0xFF);
|
||||
System.arraycopy(header1, 0, extraData, header0.length + 6, header1.length);
|
||||
return extraData;
|
||||
}
|
||||
|
||||
private native long ffmpegInitialize(
|
||||
String codecName,
|
||||
@Nullable byte[] extraData,
|
||||
|
|
|
|||
|
|
@ -1154,10 +1154,6 @@ import java.util.List;
|
|||
out.format = Format.createAudioSampleFormat(Integer.toString(trackId), mimeType, null,
|
||||
Format.NO_VALUE, Format.NO_VALUE, channelCount, sampleRate, null, drmInitData, 0,
|
||||
language);
|
||||
} else if (childAtomType == Atom.TYPE_alac) {
|
||||
initializationData = new byte[childAtomSize];
|
||||
parent.setPosition(childPosition);
|
||||
parent.readBytes(initializationData, /* offset= */ 0, childAtomSize);
|
||||
} else if (childAtomType == Atom.TYPE_dOps) {
|
||||
// Build an Opus Identification Header (defined in RFC-7845) by concatenating the Opus Magic
|
||||
// Signature and the body of the dOps atom.
|
||||
|
|
@ -1166,7 +1162,7 @@ import java.util.List;
|
|||
System.arraycopy(opusMagic, 0, initializationData, 0, opusMagic.length);
|
||||
parent.setPosition(childPosition + Atom.HEADER_SIZE);
|
||||
parent.readBytes(initializationData, opusMagic.length, childAtomBodySize);
|
||||
} else if (childAtomSize == Atom.TYPE_dfLa) {
|
||||
} else if (childAtomSize == Atom.TYPE_dfLa || childAtomType == Atom.TYPE_alac) {
|
||||
int childAtomBodySize = childAtomSize - Atom.FULL_HEADER_SIZE;
|
||||
initializationData = new byte[childAtomBodySize];
|
||||
parent.setPosition(childPosition + Atom.FULL_HEADER_SIZE);
|
||||
|
|
|
|||
Loading…
Reference in a new issue