feat: Add support for ALAC codec (#1299)
Co-authored-by: Cosmin Stejerean <cstejerean@meta.com>
This commit is contained in:
parent
35c2f46428
commit
b68ec87f6a
|
@ -1477,6 +1477,15 @@ class PackagerFunctionalTest(PackagerAppTest):
|
||||||
self.assertPackageSuccess(streams, flags)
|
self.assertPackageSuccess(streams, flags)
|
||||||
self._CheckTestResults('flac-with-encryption', verify_decryption=True)
|
self._CheckTestResults('flac-with-encryption', verify_decryption=True)
|
||||||
|
|
||||||
|
def testAlac(self):
|
||||||
|
streams = [
|
||||||
|
self._GetStream('audio', test_file='bear-alac.mp4'),
|
||||||
|
]
|
||||||
|
flags = self._GetFlags(output_dash=True)
|
||||||
|
|
||||||
|
self.assertPackageSuccess(streams, flags)
|
||||||
|
self._CheckTestResults('audio-alac')
|
||||||
|
|
||||||
def testAv1Mp4WithEncryption(self):
|
def testAv1Mp4WithEncryption(self):
|
||||||
self.assertPackageSuccess(
|
self.assertPackageSuccess(
|
||||||
self._GetStreams(['video'], test_files=['bear-av1.mp4']),
|
self._GetStreams(['video'], test_files=['bear-av1.mp4']),
|
||||||
|
|
Binary file not shown.
|
@ -0,0 +1,15 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!--Generated with https://github.com/shaka-project/shaka-packager version <tag>-<hash>-<test>-->
|
||||||
|
<MPD xmlns="urn:mpeg:dash:schema:mpd:2011" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:mpeg:dash:schema:mpd:2011 DASH-MPD.xsd" profiles="urn:mpeg:dash:profile:isoff-on-demand:2011" minBufferTime="PT2S" type="static" mediaPresentationDuration="PT2.739955S">
|
||||||
|
<Period id="0">
|
||||||
|
<AdaptationSet id="0" contentType="audio" subsegmentAlignment="true">
|
||||||
|
<Representation id="0" bandwidth="1046256" codecs="alac" mimeType="audio/mp4" audioSamplingRate="44100">
|
||||||
|
<AudioChannelConfiguration schemeIdUri="urn:mpeg:dash:23003:3:audio_channel_configuration:2011" value="2"/>
|
||||||
|
<BaseURL>bear-alac-audio.mp4</BaseURL>
|
||||||
|
<SegmentBase indexRange="762-829" timescale="44100">
|
||||||
|
<Initialization range="0-761"/>
|
||||||
|
</SegmentBase>
|
||||||
|
</Representation>
|
||||||
|
</AdaptationSet>
|
||||||
|
</Period>
|
||||||
|
</MPD>
|
|
@ -25,6 +25,8 @@ std::string AudioCodecToString(Codec codec) {
|
||||||
return "AAC";
|
return "AAC";
|
||||||
case kCodecAC3:
|
case kCodecAC3:
|
||||||
return "AC3";
|
return "AC3";
|
||||||
|
case kCodecALAC:
|
||||||
|
return "ALAC";
|
||||||
case kCodecDTSC:
|
case kCodecDTSC:
|
||||||
return "DTSC";
|
return "DTSC";
|
||||||
case kCodecDTSE:
|
case kCodecDTSE:
|
||||||
|
@ -138,6 +140,8 @@ std::string AudioStreamInfo::GetCodecString(Codec codec,
|
||||||
return "mp4a.40." + absl::StrFormat("%hhu", audio_object_type);
|
return "mp4a.40." + absl::StrFormat("%hhu", audio_object_type);
|
||||||
case kCodecAC3:
|
case kCodecAC3:
|
||||||
return "ac-3";
|
return "ac-3";
|
||||||
|
case kCodecALAC:
|
||||||
|
return "alac";
|
||||||
case kCodecDTSC:
|
case kCodecDTSC:
|
||||||
return "dtsc";
|
return "dtsc";
|
||||||
case kCodecDTSE:
|
case kCodecDTSE:
|
||||||
|
|
|
@ -23,6 +23,7 @@ enum FourCC : uint32_t {
|
||||||
FOURCC_ac_3 = 0x61632d33, // "ac-3"
|
FOURCC_ac_3 = 0x61632d33, // "ac-3"
|
||||||
FOURCC_ac_4 = 0x61632d34, // "ac-4"
|
FOURCC_ac_4 = 0x61632d34, // "ac-4"
|
||||||
FOURCC_ac3d = 0x61633364,
|
FOURCC_ac3d = 0x61633364,
|
||||||
|
FOURCC_alac = 0x616c6163,
|
||||||
FOURCC_apad = 0x61706164,
|
FOURCC_apad = 0x61706164,
|
||||||
FOURCC_av01 = 0x61763031,
|
FOURCC_av01 = 0x61763031,
|
||||||
FOURCC_av1C = 0x61763143,
|
FOURCC_av1C = 0x61763143,
|
||||||
|
|
|
@ -41,6 +41,7 @@ enum Codec {
|
||||||
kCodecAAC = kCodecAudio,
|
kCodecAAC = kCodecAudio,
|
||||||
kCodecAC3,
|
kCodecAC3,
|
||||||
kCodecAC4,
|
kCodecAC4,
|
||||||
|
kCodecALAC,
|
||||||
// TODO(kqyang): Use kCodecDTS and a kDtsStreamFormat for the various DTS
|
// TODO(kqyang): Use kCodecDTS and a kDtsStreamFormat for the various DTS
|
||||||
// streams.
|
// streams.
|
||||||
kCodecDTSC,
|
kCodecDTSC,
|
||||||
|
|
|
@ -1969,6 +1969,27 @@ size_t FlacSpecific::ComputeSizeInternal() {
|
||||||
return HeaderSize() + data.size();
|
return HeaderSize() + data.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ALACSpecific::ALACSpecific() = default;
|
||||||
|
ALACSpecific::~ALACSpecific() = default;
|
||||||
|
|
||||||
|
FourCC ALACSpecific::BoxType() const {
|
||||||
|
return FOURCC_alac;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ALACSpecific::ReadWriteInternal(BoxBuffer* buffer) {
|
||||||
|
RCHECK(ReadWriteHeaderInternal(buffer));
|
||||||
|
size_t size = buffer->Reading() ? buffer->BytesLeft() : data.size();
|
||||||
|
RCHECK(buffer->ReadWriteVector(&data, size));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t ALACSpecific::ComputeSizeInternal() {
|
||||||
|
// This box is optional. Skip it if not initialized.
|
||||||
|
if (data.empty())
|
||||||
|
return 0;
|
||||||
|
return HeaderSize() + data.size();
|
||||||
|
}
|
||||||
|
|
||||||
AudioSampleEntry::AudioSampleEntry() = default;
|
AudioSampleEntry::AudioSampleEntry() = default;
|
||||||
AudioSampleEntry::~AudioSampleEntry() = default;
|
AudioSampleEntry::~AudioSampleEntry() = default;
|
||||||
|
|
||||||
|
@ -2011,6 +2032,7 @@ bool AudioSampleEntry::ReadWriteInternal(BoxBuffer* buffer) {
|
||||||
RCHECK(buffer->TryReadWriteChild(&dops));
|
RCHECK(buffer->TryReadWriteChild(&dops));
|
||||||
RCHECK(buffer->TryReadWriteChild(&dfla));
|
RCHECK(buffer->TryReadWriteChild(&dfla));
|
||||||
RCHECK(buffer->TryReadWriteChild(&mhac));
|
RCHECK(buffer->TryReadWriteChild(&mhac));
|
||||||
|
RCHECK(buffer->TryReadWriteChild(&alac));
|
||||||
|
|
||||||
// Somehow Edge does not support having sinf box before codec_configuration,
|
// Somehow Edge does not support having sinf box before codec_configuration,
|
||||||
// box, so just do it in the end of AudioSampleEntry. See
|
// box, so just do it in the end of AudioSampleEntry. See
|
||||||
|
@ -2036,6 +2058,7 @@ size_t AudioSampleEntry::ComputeSizeInternal() {
|
||||||
sizeof(samplesize) + sizeof(samplerate) + sinf.ComputeSize() +
|
sizeof(samplesize) + sizeof(samplerate) + sinf.ComputeSize() +
|
||||||
esds.ComputeSize() + ddts.ComputeSize() + dac3.ComputeSize() +
|
esds.ComputeSize() + ddts.ComputeSize() + dac3.ComputeSize() +
|
||||||
dec3.ComputeSize() + dops.ComputeSize() + dfla.ComputeSize() +
|
dec3.ComputeSize() + dops.ComputeSize() + dfla.ComputeSize() +
|
||||||
|
dac4.ComputeSize() + mhac.ComputeSize() + alac.ComputeSize() +
|
||||||
dac4.ComputeSize() + mhac.ComputeSize() + udts.ComputeSize() +
|
dac4.ComputeSize() + mhac.ComputeSize() + udts.ComputeSize() +
|
||||||
// Reserved and predefined bytes.
|
// Reserved and predefined bytes.
|
||||||
6 + 8 + // 6 + 8 bytes reserved.
|
6 + 8 + // 6 + 8 bytes reserved.
|
||||||
|
|
|
@ -382,6 +382,15 @@ struct FlacSpecific : FullBox {
|
||||||
std::vector<uint8_t> data;
|
std::vector<uint8_t> data;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// ALAC specific decoder configuration box:
|
||||||
|
// https://wiki.multimedia.cx/index.php/Apple_Lossless_Audio_Coding
|
||||||
|
// We do not care about the actual data inside, which is simply copied over.
|
||||||
|
struct ALACSpecific : FullBox {
|
||||||
|
DECLARE_BOX_METHODS(ALACSpecific);
|
||||||
|
|
||||||
|
std::vector<uint8_t> data;
|
||||||
|
};
|
||||||
|
|
||||||
struct AudioSampleEntry : Box {
|
struct AudioSampleEntry : Box {
|
||||||
DECLARE_BOX_METHODS(AudioSampleEntry);
|
DECLARE_BOX_METHODS(AudioSampleEntry);
|
||||||
|
|
||||||
|
@ -409,6 +418,7 @@ struct AudioSampleEntry : Box {
|
||||||
OpusSpecific dops;
|
OpusSpecific dops;
|
||||||
FlacSpecific dfla;
|
FlacSpecific dfla;
|
||||||
MHAConfiguration mhac;
|
MHAConfiguration mhac;
|
||||||
|
ALACSpecific alac;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct WebVTTConfigurationBox : Box {
|
struct WebVTTConfigurationBox : Box {
|
||||||
|
|
|
@ -102,6 +102,8 @@ Codec FourCCToCodec(FourCC fourcc) {
|
||||||
return kCodecEAC3;
|
return kCodecEAC3;
|
||||||
case FOURCC_ac_4:
|
case FOURCC_ac_4:
|
||||||
return kCodecAC4;
|
return kCodecAC4;
|
||||||
|
case FOURCC_alac:
|
||||||
|
return kCodecALAC;
|
||||||
case FOURCC_fLaC:
|
case FOURCC_fLaC:
|
||||||
return kCodecFlac;
|
return kCodecFlac;
|
||||||
case FOURCC_mha1:
|
case FOURCC_mha1:
|
||||||
|
@ -514,6 +516,9 @@ bool MP4MediaParser::ParseMoov(BoxReader* reader) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case FOURCC_alac:
|
||||||
|
codec_config = entry.alac.data;
|
||||||
|
break;
|
||||||
case FOURCC_fLaC:
|
case FOURCC_fLaC:
|
||||||
codec_config = entry.dfla.data;
|
codec_config = entry.dfla.data;
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -76,6 +76,8 @@ FourCC CodecToFourCC(Codec codec, H26xStreamFormat h26x_stream_format) {
|
||||||
return FOURCC_mp4a;
|
return FOURCC_mp4a;
|
||||||
case kCodecAC3:
|
case kCodecAC3:
|
||||||
return FOURCC_ac_3;
|
return FOURCC_ac_3;
|
||||||
|
case kCodecALAC:
|
||||||
|
return FOURCC_alac;
|
||||||
case kCodecDTSC:
|
case kCodecDTSC:
|
||||||
return FOURCC_dtsc;
|
return FOURCC_dtsc;
|
||||||
case kCodecDTSH:
|
case kCodecDTSH:
|
||||||
|
@ -512,6 +514,9 @@ bool MP4Muxer::GenerateAudioTrak(const AudioStreamInfo* audio_info,
|
||||||
case kCodecAC4:
|
case kCodecAC4:
|
||||||
audio.dac4.data = audio_info->codec_config();
|
audio.dac4.data = audio_info->codec_config();
|
||||||
break;
|
break;
|
||||||
|
case kCodecALAC:
|
||||||
|
audio.alac.data = audio_info->codec_config();
|
||||||
|
break;
|
||||||
case kCodecFlac:
|
case kCodecFlac:
|
||||||
audio.dfla.data = audio_info->codec_config();
|
audio.dfla.data = audio_info->codec_config();
|
||||||
break;
|
break;
|
||||||
|
|
Binary file not shown.
Loading…
Reference in New Issue