feat: Add support for ALAC codec (#1299)

Co-authored-by: Cosmin Stejerean <cstejerean@meta.com>
This commit is contained in:
wjywbs 2024-02-26 16:39:30 -05:00 committed by GitHub
parent 35c2f46428
commit b68ec87f6a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
11 changed files with 73 additions and 0 deletions

View File

@ -1477,6 +1477,15 @@ class PackagerFunctionalTest(PackagerAppTest):
self.assertPackageSuccess(streams, flags)
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):
self.assertPackageSuccess(
self._GetStreams(['video'], test_files=['bear-av1.mp4']),

Binary file not shown.

View File

@ -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>

View File

@ -25,6 +25,8 @@ std::string AudioCodecToString(Codec codec) {
return "AAC";
case kCodecAC3:
return "AC3";
case kCodecALAC:
return "ALAC";
case kCodecDTSC:
return "DTSC";
case kCodecDTSE:
@ -138,6 +140,8 @@ std::string AudioStreamInfo::GetCodecString(Codec codec,
return "mp4a.40." + absl::StrFormat("%hhu", audio_object_type);
case kCodecAC3:
return "ac-3";
case kCodecALAC:
return "alac";
case kCodecDTSC:
return "dtsc";
case kCodecDTSE:

View File

@ -23,6 +23,7 @@ enum FourCC : uint32_t {
FOURCC_ac_3 = 0x61632d33, // "ac-3"
FOURCC_ac_4 = 0x61632d34, // "ac-4"
FOURCC_ac3d = 0x61633364,
FOURCC_alac = 0x616c6163,
FOURCC_apad = 0x61706164,
FOURCC_av01 = 0x61763031,
FOURCC_av1C = 0x61763143,

View File

@ -41,6 +41,7 @@ enum Codec {
kCodecAAC = kCodecAudio,
kCodecAC3,
kCodecAC4,
kCodecALAC,
// TODO(kqyang): Use kCodecDTS and a kDtsStreamFormat for the various DTS
// streams.
kCodecDTSC,

View File

@ -1969,6 +1969,27 @@ size_t FlacSpecific::ComputeSizeInternal() {
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;
@ -2011,6 +2032,7 @@ bool AudioSampleEntry::ReadWriteInternal(BoxBuffer* buffer) {
RCHECK(buffer->TryReadWriteChild(&dops));
RCHECK(buffer->TryReadWriteChild(&dfla));
RCHECK(buffer->TryReadWriteChild(&mhac));
RCHECK(buffer->TryReadWriteChild(&alac));
// Somehow Edge does not support having sinf box before codec_configuration,
// 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() +
esds.ComputeSize() + ddts.ComputeSize() + dac3.ComputeSize() +
dec3.ComputeSize() + dops.ComputeSize() + dfla.ComputeSize() +
dac4.ComputeSize() + mhac.ComputeSize() + alac.ComputeSize() +
dac4.ComputeSize() + mhac.ComputeSize() + udts.ComputeSize() +
// Reserved and predefined bytes.
6 + 8 + // 6 + 8 bytes reserved.

View File

@ -382,6 +382,15 @@ struct FlacSpecific : FullBox {
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 {
DECLARE_BOX_METHODS(AudioSampleEntry);
@ -409,6 +418,7 @@ struct AudioSampleEntry : Box {
OpusSpecific dops;
FlacSpecific dfla;
MHAConfiguration mhac;
ALACSpecific alac;
};
struct WebVTTConfigurationBox : Box {

View File

@ -102,6 +102,8 @@ Codec FourCCToCodec(FourCC fourcc) {
return kCodecEAC3;
case FOURCC_ac_4:
return kCodecAC4;
case FOURCC_alac:
return kCodecALAC;
case FOURCC_fLaC:
return kCodecFlac;
case FOURCC_mha1:
@ -514,6 +516,9 @@ bool MP4MediaParser::ParseMoov(BoxReader* reader) {
return false;
}
break;
case FOURCC_alac:
codec_config = entry.alac.data;
break;
case FOURCC_fLaC:
codec_config = entry.dfla.data;
break;

View File

@ -76,6 +76,8 @@ FourCC CodecToFourCC(Codec codec, H26xStreamFormat h26x_stream_format) {
return FOURCC_mp4a;
case kCodecAC3:
return FOURCC_ac_3;
case kCodecALAC:
return FOURCC_alac;
case kCodecDTSC:
return FOURCC_dtsc;
case kCodecDTSH:
@ -512,6 +514,9 @@ bool MP4Muxer::GenerateAudioTrak(const AudioStreamInfo* audio_info,
case kCodecAC4:
audio.dac4.data = audio_info->codec_config();
break;
case kCodecALAC:
audio.alac.data = audio_info->codec_config();
break;
case kCodecFlac:
audio.dfla.data = audio_info->codec_config();
break;

Binary file not shown.