/src/symphonia/symphonia-format-isomp4/src/atoms/alac.rs
Line | Count | Source |
1 | | // Symphonia |
2 | | // Copyright (c) 2019-2026 The Project Symphonia Developers. |
3 | | // |
4 | | // This Source Code Form is subject to the terms of the Mozilla Public |
5 | | // License, v. 2.0. If a copy of the MPL was not distributed with this |
6 | | // file, You can obtain one at https://mozilla.org/MPL/2.0/. |
7 | | |
8 | | use symphonia_core::codecs::audio::well_known::CODEC_ID_ALAC; |
9 | | |
10 | | use symphonia_common::apple::audio::alac::MagicCookie; |
11 | | |
12 | | use crate::atoms::stsd::AudioSampleEntry; |
13 | | use crate::atoms::{ |
14 | | Atom, AtomHeader, AtomIterator, ReadAtom, Result, decode_error, unsupported_error, |
15 | | }; |
16 | | |
17 | | #[allow(dead_code)] |
18 | | #[derive(Debug)] |
19 | | pub struct AlacAtom { |
20 | | /// ALAC extra data (magic cookie). |
21 | | extra_data: Box<[u8]>, |
22 | | } |
23 | | |
24 | | impl Atom for AlacAtom { |
25 | 3.05k | fn read<B: ReadAtom>(it: &mut AtomIterator<B>, _header: &AtomHeader) -> Result<Self> { |
26 | 3.05k | let (version, flags) = it.read_extended_header()?; |
27 | | |
28 | 3.04k | if version != 0 { |
29 | 3 | return unsupported_error("isomp4 (alac): unsupported alac version"); |
30 | 3.04k | } |
31 | | |
32 | 3.04k | if flags != 0 { |
33 | 24 | return decode_error("isomp4 (alac): flags not zero"); |
34 | 3.02k | } |
35 | | |
36 | | // The ALAC magic cookie (aka extra data) is either 24 or 48 bytes long. |
37 | 3.02k | let magic_len = match it.data_left()? { |
38 | 2.94k | Some(len @ 24) | Some(len @ 48) => len as usize, |
39 | | Some(_) => { |
40 | 74 | return decode_error("isomp4 (alac): invalid magic cookie length"); |
41 | | } |
42 | 1 | None => return decode_error("isomp4 (alac): unknown magic cookie length"), |
43 | | }; |
44 | | |
45 | | // Read the magic cookie. |
46 | 2.94k | let extra_data = it.read_boxed_slice_exact(magic_len)?; |
47 | | |
48 | 2.93k | Ok(AlacAtom { extra_data }) |
49 | 3.05k | } |
50 | | } |
51 | | |
52 | | impl AlacAtom { |
53 | 2.93k | pub fn fill_audio_sample_entry(self, entry: &mut AudioSampleEntry) { |
54 | 2.93k | entry.codec_id = CODEC_ID_ALAC; |
55 | | |
56 | | // Try to parse the magic cookie. |
57 | 2.93k | if let Ok(cookie) = MagicCookie::read(&self.extra_data) { |
58 | 231 | entry.channels = Some(cookie.channels); |
59 | 231 | entry.sample_rate = f64::from(cookie.sample_rate); |
60 | 2.69k | } |
61 | | |
62 | 2.93k | entry.extra_data = Some(self.extra_data); |
63 | 2.93k | } |
64 | | } |