1use crate::media::{Error, Result};
2use crate::mp4::boxes::{BoxBuf, Cur, FourCc, boxes};
3
4#[derive(Clone, Debug, PartialEq)]
5pub struct SampleEntry {
6 pub format: FourCc,
7 pub codec: CodecConfig,
8 pub video: Option<VideoParams>,
9 pub audio: Option<AudioParams>,
10 pub bitrate: Option<BitRate>,
11 pub raw: Vec<u8>,
12}
13
14#[derive(Clone, Copy, Debug, PartialEq, Eq, Default)]
15pub struct VideoParams {
16 pub width: u16,
17 pub height: u16,
18 pub pixel_aspect: Option<(u32, u32)>,
19}
20
21#[derive(Clone, Copy, Debug, PartialEq, Eq)]
22pub struct BitRate {
23 pub buffer_size: u32,
24 pub max_bitrate: u32,
25 pub avg_bitrate: u32,
26}
27
28#[derive(Clone, Debug, PartialEq, Default)]
29pub struct AudioParams {
30 pub qt_version: u16,
31 pub channels: u32,
32 pub sample_size: u16,
33 pub sample_rate: f64,
34 pub samples_per_packet: u32,
35 pub bytes_per_frame: u32,
36 pub const_bits_per_channel: u32,
37 pub lpcm_flags: u32,
38 pub little_endian: Option<bool>,
39}
40
41#[derive(Clone, Debug, PartialEq)]
42pub enum CodecConfig {
43 Avc(AvcConfig),
44 Hevc(HevcConfig),
45 Vp9(VpcConfig),
46 Aac(AacConfig),
47 Mp3,
48 Pcm(PcmConfig),
49 Other(FourCc),
50}
51
52impl CodecConfig {
53 pub fn name(&self) -> String {
54 match self {
55 CodecConfig::Avc(_) => "h264".into(),
56 CodecConfig::Hevc(_) => "hevc".into(),
57 CodecConfig::Vp9(_) => "vp9".into(),
58 CodecConfig::Aac(_) => "aac".into(),
59 CodecConfig::Mp3 => "mp3".into(),
60 CodecConfig::Pcm(_) => "pcm".into(),
61 CodecConfig::Other(f) if &f.0 == b"ac-3" => "ac3".into(),
62 CodecConfig::Other(f) if &f.0 == b"ec-3" => "eac3".into(),
63 CodecConfig::Other(f) => f.to_string_lossy().trim().to_string(),
64 }
65 }
66
67 pub fn extradata(&self) -> Option<Vec<u8>> {
68 match self {
69 CodecConfig::Avc(c) => Some(c.to_bytes()),
70 CodecConfig::Hevc(c) => Some(c.to_bytes()),
71 CodecConfig::Vp9(c) => Some(c.to_bytes()),
72 CodecConfig::Aac(c) => Some(c.asc.clone()),
73 _ => None,
74 }
75 }
76}
77
78#[derive(Clone, Debug, PartialEq, Eq, Default)]
79pub struct AvcConfig {
80 pub profile: u8,
81 pub compatibility: u8,
82 pub level: u8,
83 pub length_size: u8,
84 pub sps: Vec<Vec<u8>>,
85 pub pps: Vec<Vec<u8>>,
86 pub ext: Vec<u8>,
87}
88
89impl AvcConfig {
90 pub fn new(sps: Vec<Vec<u8>>, pps: Vec<Vec<u8>>) -> Self {
91 let (profile, compatibility, level) = sps
92 .first()
93 .filter(|s| s.len() >= 4)
94 .map(|s| (s[1], s[2], s[3]))
95 .unwrap_or((0, 0, 0));
96 let ext = if matches!(profile, 100 | 110 | 122 | 144) {
97 vec![0xFD, 0xF8, 0xF8, 0]
98 } else {
99 Vec::new()
100 };
101 AvcConfig {
102 profile,
103 compatibility,
104 level,
105 length_size: 4,
106 sps,
107 pps,
108 ext,
109 }
110 }
111
112 pub fn parameter_sets_annexb(&self) -> Vec<u8> {
113 let mut out = Vec::new();
114 for nal in self.sps.iter().chain(&self.pps) {
115 out.extend_from_slice(&[0, 0, 0, 1]);
116 out.extend_from_slice(nal);
117 }
118 out
119 }
120
121 pub fn parse(data: &[u8]) -> Result<Self> {
122 let mut c = Cur::new(data, "avcC");
123 let _version = c.u8()?;
124 let profile = c.u8()?;
125 let compatibility = c.u8()?;
126 let level = c.u8()?;
127 let length_size = (c.u8()? & 3) + 1;
128 let nsps = (c.u8()? & 0x1F) as usize;
129 let mut sps = Vec::with_capacity(nsps);
130 for _ in 0..nsps {
131 let n = c.u16()? as usize;
132 sps.push(c.bytes(n)?.to_vec());
133 }
134 let npps = c.u8()? as usize;
135 let mut pps = Vec::with_capacity(npps);
136 for _ in 0..npps {
137 let n = c.u16()? as usize;
138 pps.push(c.bytes(n)?.to_vec());
139 }
140 Ok(AvcConfig {
141 profile,
142 compatibility,
143 level,
144 length_size,
145 sps,
146 pps,
147 ext: c.rest().to_vec(),
148 })
149 }
150
151 pub fn to_bytes(&self) -> Vec<u8> {
152 let mut b = BoxBuf::new();
153 b.u8(1);
154 b.u8(self.profile);
155 b.u8(self.compatibility);
156 b.u8(self.level);
157 b.u8(0xFC | (self.length_size.clamp(1, 4) - 1));
158 b.u8(0xE0 | (self.sps.len().min(31) as u8));
159 for s in self.sps.iter().take(31) {
160 b.u16(s.len() as u16);
161 b.bytes(s);
162 }
163 b.u8(self.pps.len().min(255) as u8);
164 for p in self.pps.iter().take(255) {
165 b.u16(p.len() as u16);
166 b.bytes(p);
167 }
168 b.bytes(&self.ext);
169 b.buf
170 }
171}
172
173#[derive(Clone, Debug, PartialEq, Eq, Default)]
174pub struct NalArray {
175 pub completeness: bool,
176 pub nal_type: u8,
177 pub nalus: Vec<Vec<u8>>,
178}
179
180#[derive(Clone, Debug, PartialEq, Eq, Default)]
181pub struct HevcConfig {
182 pub profile_space: u8,
183 pub tier: bool,
184 pub profile: u8,
185 pub compatibility: u32,
186 pub constraints: u64,
187 pub level: u8,
188 pub min_spatial_segmentation: u16,
189 pub parallelism: u8,
190 pub chroma_format: u8,
191 pub bit_depth_luma: u8,
192 pub bit_depth_chroma: u8,
193 pub avg_frame_rate: u16,
194 pub constant_frame_rate: u8,
195 pub temporal_layers: u8,
196 pub temporal_id_nested: bool,
197 pub length_size: u8,
198 pub arrays: Vec<NalArray>,
199}
200
201impl HevcConfig {
202 pub fn parse(data: &[u8]) -> Result<Self> {
203 let mut c = Cur::new(data, "hvcC");
204 let _version = c.u8()?;
205 let b = c.u8()?;
206 let compatibility = c.u32()?;
207 let hi = c.u16()? as u64;
208 let lo = c.u32()? as u64;
209 let level = c.u8()?;
210 let min_seg = c.u16()? & 0x0FFF;
211 let par = c.u8()? & 3;
212 let chroma = c.u8()? & 3;
213 let bdl = (c.u8()? & 7) + 8;
214 let bdc = (c.u8()? & 7) + 8;
215 let afr = c.u16()?;
216 let x = c.u8()?;
217 let narrays = c.u8()? as usize;
218 let mut arrays = Vec::new();
219 for _ in 0..narrays {
220 let t = c.u8()?;
221 let n = c.u16()? as usize;
222 c.check_count(n, 2)?;
223 let mut nalus = Vec::with_capacity(n);
224 for _ in 0..n {
225 let len = c.u16()? as usize;
226 nalus.push(c.bytes(len)?.to_vec());
227 }
228 arrays.push(NalArray {
229 completeness: t & 0x80 != 0,
230 nal_type: t & 0x3F,
231 nalus,
232 });
233 }
234 Ok(HevcConfig {
235 profile_space: b >> 6,
236 tier: b & 0x20 != 0,
237 profile: b & 0x1F,
238 compatibility,
239 constraints: (hi << 32) | lo,
240 level,
241 min_spatial_segmentation: min_seg,
242 parallelism: par,
243 chroma_format: chroma,
244 bit_depth_luma: bdl,
245 bit_depth_chroma: bdc,
246 avg_frame_rate: afr,
247 constant_frame_rate: x >> 6,
248 temporal_layers: (x >> 3) & 7,
249 temporal_id_nested: x & 4 != 0,
250 length_size: (x & 3) + 1,
251 arrays,
252 })
253 }
254
255 pub fn to_bytes(&self) -> Vec<u8> {
256 let mut b = BoxBuf::new();
257 b.u8(1);
258 b.u8((self.profile_space << 6) | ((self.tier as u8) << 5) | (self.profile & 0x1F));
259 b.u32(self.compatibility);
260 b.u16((self.constraints >> 32) as u16);
261 b.u32(self.constraints as u32);
262 b.u8(self.level);
263 b.u16(0xF000 | (self.min_spatial_segmentation & 0x0FFF));
264 b.u8(0xFC | (self.parallelism & 3));
265 b.u8(0xFC | (self.chroma_format & 3));
266 b.u8(0xF8 | (self.bit_depth_luma.saturating_sub(8) & 7));
267 b.u8(0xF8 | (self.bit_depth_chroma.saturating_sub(8) & 7));
268 b.u16(self.avg_frame_rate);
269 b.u8((self.constant_frame_rate << 6)
270 | ((self.temporal_layers & 7) << 3)
271 | ((self.temporal_id_nested as u8) << 2)
272 | (self.length_size.clamp(1, 4) - 1));
273 b.u8(self.arrays.len() as u8);
274 for a in &self.arrays {
275 b.u8(((a.completeness as u8) << 7) | (a.nal_type & 0x3F));
276 b.u16(a.nalus.len() as u16);
277 for n in &a.nalus {
278 b.u16(n.len() as u16);
279 b.bytes(n);
280 }
281 }
282 b.buf
283 }
284
285 fn nalus(&self, t: u8) -> Vec<&[u8]> {
286 self.arrays
287 .iter()
288 .filter(|a| a.nal_type == t)
289 .flat_map(|a| a.nalus.iter().map(Vec::as_slice))
290 .collect()
291 }
292
293 pub fn vps(&self) -> Vec<&[u8]> {
294 self.nalus(32)
295 }
296
297 pub fn sps(&self) -> Vec<&[u8]> {
298 self.nalus(33)
299 }
300
301 pub fn pps(&self) -> Vec<&[u8]> {
302 self.nalus(34)
303 }
304}
305
306#[derive(Clone, Copy, Debug, PartialEq, Eq, Default)]
307pub struct VpcConfig {
308 pub profile: u8,
309 pub level: u8,
310 pub bit_depth: u8,
311 pub chroma_subsampling: u8,
312 pub full_range: bool,
313 pub colour_primaries: u8,
314 pub transfer_characteristics: u8,
315 pub matrix_coefficients: u8,
316}
317
318const VP9_LEVELS: [(u8, u64, u64, u32); 14] = [
319 (10, 829_440, 36_864, 512),
320 (11, 2_764_800, 73_728, 768),
321 (20, 4_608_000, 122_880, 1_536),
322 (21, 9_216_000, 245_760, 2_816),
323 (30, 20_736_000, 552_960, 6_656),
324 (31, 36_864_000, 983_040, 10_496),
325 (40, 83_558_400, 2_228_224, 16_384),
326 (41, 160_432_128, 2_228_224, 16_384),
327 (50, 311_951_360, 8_912_896, 32_768),
328 (51, 588_251_136, 8_912_896, 32_768),
329 (52, 1_176_502_272, 8_912_896, 32_768),
330 (60, 1_176_502_272, 35_651_584, 65_536),
331 (61, 2_353_004_544, 35_651_584, 65_536),
332 (62, 4_706_009_088, 35_651_584, 65_536),
333];
334
335impl VpcConfig {
336 pub fn new(
337 (profile, bit_depth, chroma_subsampling): (u8, u8, u8),
338 (color_space, full_range): (u8, bool),
339 (width, height): (u32, u32),
340 fps: (u32, u32),
341 ) -> Self {
342 let (colour_primaries, transfer_characteristics, matrix_coefficients) = match color_space {
343 1 => (5, 6, 5),
344 2 => (1, 1, 1),
345 3 => (6, 6, 6),
346 4 => (7, 7, 7),
347 5 => (9, 2, 9),
348 7 => (1, 13, 0),
349 _ => (2, 2, 2),
350 };
351 VpcConfig {
352 profile,
353 level: vp9_level((width, height), fps),
354 bit_depth,
355 chroma_subsampling,
356 full_range,
357 colour_primaries,
358 transfer_characteristics,
359 matrix_coefficients,
360 }
361 }
362
363 pub fn parse(data: &[u8]) -> Result<Self> {
364 let mut c = Cur::new(data, "vpcC");
365 let (version, _) = c.full_header()?;
366 if version != 1 {
367 return Err(Error::Unsupported(format!("vpcC version {version}")));
368 }
369 let profile = c.u8()?;
370 let level = c.u8()?;
371 let packed = c.u8()?;
372 Ok(VpcConfig {
373 profile,
374 level,
375 bit_depth: packed >> 4,
376 chroma_subsampling: (packed >> 1) & 7,
377 full_range: packed & 1 == 1,
378 colour_primaries: c.u8()?,
379 transfer_characteristics: c.u8()?,
380 matrix_coefficients: c.u8()?,
381 })
382 }
383
384 pub fn to_bytes(&self) -> Vec<u8> {
385 vec![
386 1,
387 0,
388 0,
389 0,
390 self.profile,
391 self.level,
392 (self.bit_depth << 4) | ((self.chroma_subsampling & 7) << 1) | self.full_range as u8,
393 self.colour_primaries,
394 self.transfer_characteristics,
395 self.matrix_coefficients,
396 0,
397 0,
398 ]
399 }
400}
401
402fn vp9_level((width, height): (u32, u32), (num, den): (u32, u32)) -> u8 {
403 let picture = width as u64 * height as u64;
404 let rate = picture * num as u64 / den.max(1) as u64;
405 let breadth = width.max(height);
406 VP9_LEVELS
407 .iter()
408 .find(|l| rate <= l.1 && picture <= l.2 && breadth <= l.3)
409 .map_or(62, |l| l.0)
410}
411
412#[derive(Clone, Debug, PartialEq, Eq, Default)]
413pub struct AacConfig {
414 pub asc: Vec<u8>,
415 pub object_type: u8,
416 pub sample_rate: u32,
417 pub channel_config: u8,
418 pub max_bitrate: u32,
419 pub avg_bitrate: u32,
420 pub buffer_size: u32,
421}
422
423const AAC_RATES: [u32; 13] = [
424 96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050, 16000, 12000, 11025, 8000, 7350,
425];
426
427impl AacConfig {
428 pub fn from_asc(asc: Vec<u8>) -> Self {
429 let (object_type, sample_rate, channel_config) = parse_asc(&asc).unwrap_or((0, 0, 0));
430 AacConfig {
431 asc,
432 object_type,
433 sample_rate,
434 channel_config,
435 ..Default::default()
436 }
437 }
438
439 pub fn channels(&self) -> u32 {
440 match self.channel_config {
441 1..=6 => self.channel_config as u32,
442 7 => 8,
443 _ => 0,
444 }
445 }
446}
447
448fn parse_asc(asc: &[u8]) -> Option<(u8, u32, u8)> {
449 let bit = |i: usize| asc.get(i / 8).map(|b| (b >> (7 - i % 8)) & 1);
450 let bits = |at: &mut usize, n: usize| -> Option<u32> {
451 let mut v = 0u32;
452 for _ in 0..n {
453 v = (v << 1) | bit(*at)? as u32;
454 *at += 1;
455 }
456 Some(v)
457 };
458 let mut at = 0;
459 let mut t = bits(&mut at, 5)? as u8;
460 if t == 31 {
461 t = 32 + bits(&mut at, 6)? as u8;
462 }
463 let i = bits(&mut at, 4)? as usize;
464 let sr = if i == 15 {
465 bits(&mut at, 24)?
466 } else {
467 *AAC_RATES.get(i)?
468 };
469 let ch = bits(&mut at, 4)? as u8;
470 Some((t, sr, ch))
471}
472
473#[derive(Clone, Copy, Debug, PartialEq, Default)]
474pub struct PcmConfig {
475 pub bits: u16,
476 pub float: bool,
477 pub big_endian: bool,
478 pub signed: bool,
479 pub channels: u32,
480 pub sample_rate: f64,
481}
482
483impl PcmConfig {
484 pub fn bytes_per_frame(&self) -> u32 {
485 (self.bits as u32)
486 .div_ceil(8)
487 .saturating_mul(self.channels.max(1))
488 }
489}
490
491fn is_video_fourcc(f: &[u8; 4]) -> bool {
492 matches!(
493 f,
494 b"avc1"
495 | b"avc3"
496 | b"hvc1"
497 | b"hev1"
498 | b"av01"
499 | b"vp09"
500 | b"vp08"
501 | b"apch"
502 | b"apcn"
503 | b"apcs"
504 | b"apco"
505 | b"ap4h"
506 | b"ap4x"
507 | b"jpeg"
508 | b"mjpa"
509 | b"mjpb"
510 | b"AVdn"
511 | b"AVdh"
512 | b"mp4v"
513 | b"encv"
514 | b"2vuy"
515 | b"v210"
516 )
517}
518
519fn is_audio_fourcc(f: &[u8; 4]) -> bool {
520 matches!(
521 f,
522 b"mp4a"
523 | b"lpcm"
524 | b"sowt"
525 | b"twos"
526 | b"in24"
527 | b"in32"
528 | b"fl32"
529 | b"fl64"
530 | b"ipcm"
531 | b"fpcm"
532 | b"alac"
533 | b"Opus"
534 | b"fLaC"
535 | b"ac-3"
536 | b"ec-3"
537 | b".mp3"
538 | b".mp2"
539 | b"enca"
540 | b"ulaw"
541 | b"alaw"
542 | b"NONE"
543 )
544}
545
546pub(crate) fn parse_sample_entry(
547 format: FourCc,
548 payload: &[u8],
549 handler: FourCc,
550 is_qt: bool,
551) -> Result<SampleEntry> {
552 let mut c = Cur::new(payload, "sample entry");
553 c.skip(8)?;
554 let f = &format.0;
555 let mut entry = SampleEntry {
556 format,
557 codec: CodecConfig::Other(format),
558 video: None,
559 audio: None,
560 bitrate: None,
561 raw: payload.to_vec(),
562 };
563 let video_like = is_video_fourcc(f) || (handler == b"vide" && !is_audio_fourcc(f));
564 let audio_like = is_audio_fourcc(f) || (handler == b"soun" && !video_like);
565 if handler == b"tmcd" || f == b"tmcd" {
566 return Ok(entry);
567 }
568 if video_like {
569 let mut v = VideoParams::default();
570 c.skip(16)?;
571 v.width = c.u16()?;
572 v.height = c.u16()?;
573 c.skip(50)?;
574 for b in boxes(c.rest()).map_while(|b| b.ok()) {
575 let p = b.payload;
576 match &b.kind.0 {
577 b"avcC" if matches!(f, b"avc1" | b"avc3") => {
578 entry.codec = CodecConfig::Avc(AvcConfig::parse(p)?)
579 }
580 b"hvcC" if matches!(f, b"hvc1" | b"hev1") => {
581 entry.codec = CodecConfig::Hevc(HevcConfig::parse(p)?)
582 }
583 b"vpcC" if f == b"vp09" => entry.codec = CodecConfig::Vp9(VpcConfig::parse(p)?),
584 b"pasp" => {
585 let mut c = Cur::new(p, "pasp");
586 v.pixel_aspect = Some((c.u32()?, c.u32()?));
587 }
588 b"btrt" => entry.bitrate = Some(parse_btrt(p)?),
589 _ => {}
590 }
591 }
592 entry.video = Some(v);
593 return Ok(entry);
594 }
595 if !audio_like {
596 return Ok(entry);
597 }
598 let mut a = AudioParams {
599 qt_version: c.u16()?,
600 ..Default::default()
601 };
602 c.skip(6)?;
603 a.channels = c.u16()? as u32;
604 a.sample_size = c.u16()?;
605 c.skip(4)?;
606 a.sample_rate = c.u32()? as f64 / 65536.0;
607 if is_qt && a.qt_version == 1 {
608 a.samples_per_packet = c.u32()?;
609 c.skip(4)?;
610 a.bytes_per_frame = c.u32()?;
611 c.skip(4)?;
612 } else if is_qt && a.qt_version == 2 {
613 c.skip(4)?;
614 a.sample_rate = c.f64()?;
615 a.channels = c.u32()?;
616 c.skip(4)?;
617 a.const_bits_per_channel = c.u32()?;
618 a.lpcm_flags = c.u32()?;
619 c.skip(8)?;
620 }
621 let mut ext: Vec<(FourCc, &[u8])> = Vec::new();
622 for b in boxes(c.rest()).map_while(|b| b.ok()) {
623 if b.kind == b"wave" {
624 for w in boxes(b.payload).map_while(|b| b.ok()) {
625 ext.push((w.kind, w.payload));
626 }
627 } else {
628 ext.push((b.kind, b.payload));
629 }
630 }
631 let get = |k: &[u8; 4]| ext.iter().find(|(kk, _)| kk == k).map(|(_, p)| *p);
632 if let Some(p) = get(b"enda") {
633 let v = if p.len() >= 2 {
634 u16::from_be_bytes([p[0], p[1]])
635 } else {
636 p.first().copied().unwrap_or(0) as u16
637 };
638 a.little_endian = Some(v != 0);
639 }
640 entry.bitrate = get(b"btrt").and_then(|p| parse_btrt(p).ok());
641 entry.codec = match f {
642 b"mp4a" => match get(b"esds") {
643 Some(p) => parse_esds(p)?,
644 None => CodecConfig::Other(format),
645 },
646 b".mp3" | b".mp2" => CodecConfig::Mp3,
647 b"lpcm" | b"sowt" | b"twos" | b"in24" | b"in32" | b"fl32" | b"fl64" | b"raw " | b"NONE" => {
648 CodecConfig::Pcm(qt_pcm(f, &a))
649 }
650 b"ipcm" | b"fpcm" => {
651 let mut pcm = PcmConfig {
652 bits: a.sample_size,
653 float: f == b"fpcm",
654 big_endian: true,
655 signed: true,
656 channels: a.channels,
657 sample_rate: a.sample_rate,
658 };
659 if let Some(p) = get(b"pcmC") {
660 let mut c = Cur::new(p, "pcmC");
661 c.full_header()?;
662 pcm.big_endian = c.u8()? & 1 == 0;
663 pcm.bits = c.u8()? as u16;
664 }
665 CodecConfig::Pcm(pcm)
666 }
667 _ => CodecConfig::Other(format),
668 };
669 entry.audio = Some(a);
670 Ok(entry)
671}
672
673fn qt_pcm(f: &[u8; 4], a: &AudioParams) -> PcmConfig {
674 let mut p = PcmConfig {
675 channels: a.channels,
676 sample_rate: a.sample_rate,
677 signed: true,
678 ..Default::default()
679 };
680 match f {
681 b"lpcm" => {
682 p.bits = a.const_bits_per_channel as u16;
683 p.float = a.lpcm_flags & 1 != 0;
684 p.big_endian = a.lpcm_flags & 2 != 0;
685 p.signed = a.lpcm_flags & 4 != 0 || p.float;
686 if p.bits == 0 {
687 p.bits = a.sample_size;
688 }
689 }
690 b"sowt" => {
691 p.bits = if a.sample_size == 0 {
692 16
693 } else {
694 a.sample_size
695 }
696 }
697 b"twos" => {
698 p.bits = if a.sample_size == 0 {
699 16
700 } else {
701 a.sample_size
702 };
703 p.big_endian = true;
704 }
705 b"raw " | b"NONE" => {
706 p.bits = if a.sample_size == 0 { 8 } else { a.sample_size };
707 p.signed = p.bits != 8;
708 p.big_endian = true;
709 }
710 _ => {
711 p.bits = match f {
712 b"in24" => 24,
713 b"in32" | b"fl32" => 32,
714 _ => 64,
715 };
716 p.float = f[0] == b'f';
717 p.big_endian = !a.little_endian.unwrap_or(false);
718 }
719 }
720 p
721}
722
723fn parse_btrt(p: &[u8]) -> Result<BitRate> {
724 let mut c = Cur::new(p, "btrt");
725 Ok(BitRate {
726 buffer_size: c.u32()?,
727 max_bitrate: c.u32()?,
728 avg_bitrate: c.u32()?,
729 })
730}
731
732fn descriptor(c: &mut Cur) -> Result<(u8, usize)> {
733 let tag = c.u8()?;
734 let mut len = 0usize;
735 for _ in 0..4 {
736 let b = c.u8()?;
737 len = (len << 7) | (b & 0x7F) as usize;
738 if b & 0x80 == 0 {
739 break;
740 }
741 }
742 Ok((tag, len))
743}
744
745fn parse_esds(p: &[u8]) -> Result<CodecConfig> {
746 let mut c = Cur::new(p, "esds");
747 c.full_header()?;
748 let (tag, len) = descriptor(&mut c)?;
749 if tag != 3 {
750 return Err(Error::Invalid(format!(
751 "esds: expected ES_Descriptor, got tag {tag}"
752 )));
753 }
754 let es = c.bytes(len.min(c.remaining()))?;
755 let mut c = Cur::new(es, "ES_Descriptor");
756 c.u16()?;
757 let fl = c.u8()?;
758 if fl & 0x80 != 0 {
759 c.u16()?;
760 }
761 if fl & 0x40 != 0 {
762 let n = c.u8()? as usize;
763 c.skip(n)?;
764 }
765 if fl & 0x20 != 0 {
766 c.u16()?;
767 }
768 while c.remaining() > 0 {
769 let (tag, len) = descriptor(&mut c)?;
770 let body = c.bytes(len.min(c.remaining()))?;
771 if tag != 4 {
772 continue;
773 }
774 let mut d = Cur::new(body, "DecoderConfigDescriptor");
775 let oti = d.u8()?;
776 let _stream_type = d.u8()?;
777 let buffer_size = d.u24()?;
778 let max_bitrate = d.u32()?;
779 let avg_bitrate = d.u32()?;
780 let mut asc = Vec::new();
781 while d.remaining() > 0 {
782 let (t, l) = descriptor(&mut d)?;
783 let b = d.bytes(l.min(d.remaining()))?;
784 if t == 5 {
785 asc = b.to_vec();
786 break;
787 }
788 }
789 return Ok(match oti {
790 0x69 | 0x6B => CodecConfig::Mp3,
791 _ => {
792 let mut a = AacConfig::from_asc(asc);
793 a.max_bitrate = max_bitrate;
794 a.avg_bitrate = avg_bitrate;
795 a.buffer_size = buffer_size;
796 CodecConfig::Aac(a)
797 }
798 });
799 }
800 Err(Error::Invalid(
801 "esds without DecoderConfigDescriptor".into(),
802 ))
803}
804
805fn put_descriptor(b: &mut BoxBuf, tag: u8, body: &[u8]) {
806 b.u8(tag);
807 let n = body.len() as u32;
808 b.u8(0x80 | ((n >> 21) & 0x7F) as u8);
809 b.u8(0x80 | ((n >> 14) & 0x7F) as u8);
810 b.u8(0x80 | ((n >> 7) & 0x7F) as u8);
811 b.u8((n & 0x7F) as u8);
812 b.bytes(body);
813}
814
815fn esds_payload(asc: &[u8], max_bitrate: u32, avg_bitrate: u32, buffer_size: u32) -> Vec<u8> {
816 let mut dcd = BoxBuf::new();
817 dcd.u8(0x40);
818 dcd.u8(0x15);
819 dcd.u8((buffer_size >> 16) as u8);
820 dcd.u16(buffer_size as u16);
821 dcd.u32(max_bitrate);
822 dcd.u32(avg_bitrate);
823 if !asc.is_empty() {
824 put_descriptor(&mut dcd, 5, asc);
825 }
826 let mut es = BoxBuf::new();
827 es.u16(1);
828 es.u8(0);
829 put_descriptor(&mut es, 4, &dcd.buf);
830 put_descriptor(&mut es, 6, &[2]);
831 let mut b = BoxBuf::new();
832 b.u32(0);
833 put_descriptor(&mut b, 3, &es.buf);
834 b.buf
835}
836
837impl SampleEntry {
838 pub fn ac3_channels(&self) -> Option<u32> {
839 let extra = match self.audio.as_ref()?.qt_version {
840 1 => 16,
841 2 => 36,
842 _ => 0,
843 };
844 let mut rest = self.raw.get(28 + extra..)?;
845 while rest.len() >= 8 {
846 let size = u32::from_be_bytes(rest.get(..4)?.try_into().ok()?) as usize;
847 if size < 8 || size > rest.len() {
848 return None;
849 }
850 let body = rest.get(8..size)?;
851 let nfchans = |acmod: u64| [2, 1, 2, 3, 3, 4, 4, 5][acmod as usize & 7];
852 match rest.get(4..8)? {
853 b"dac3" => {
854 let b = body.get(..3)?;
855 let v = u64::from_be_bytes([0, 0, 0, 0, 0, b[0], b[1], b[2]]);
856 return Some(nfchans(v >> 11) + ((v >> 10) & 1) as u32);
857 }
858 b"dec3" => {
859 let b = body.get(..5)?;
860 let v = u64::from_be_bytes([0, 0, 0, b[0], b[1], b[2], b[3], b[4]]);
861 let deps = if (v >> 1) & 15 > 0 { 2 } else { 0 };
862 return Some(nfchans(v >> 9) + ((v >> 8) & 1) as u32 + deps);
863 }
864 _ => rest = rest.get(size..)?,
865 }
866 }
867 None
868 }
869
870 fn video(format: &[u8; 4], codec: CodecConfig, width: u16, height: u16) -> Self {
871 SampleEntry {
872 format: FourCc(*format),
873 codec,
874 video: Some(VideoParams {
875 width,
876 height,
877 pixel_aspect: None,
878 }),
879 audio: None,
880 bitrate: None,
881 raw: Vec::new(),
882 }
883 }
884
885 pub fn h264(config: AvcConfig, width: u16, height: u16) -> Self {
886 Self::video(b"avc1", CodecConfig::Avc(config), width, height)
887 }
888
889 pub fn hevc(config: HevcConfig, width: u16, height: u16) -> Self {
890 Self::video(b"hvc1", CodecConfig::Hevc(config), width, height)
891 }
892
893 pub fn vp9(config: VpcConfig, width: u16, height: u16) -> Self {
894 Self::video(b"vp09", CodecConfig::Vp9(config), width, height)
895 }
896
897 pub fn aac(asc: Vec<u8>, channels: u32, sample_rate: u32, bitrate: u32) -> Self {
898 let mut config = AacConfig::from_asc(asc);
899 config.avg_bitrate = bitrate;
900 config.max_bitrate = bitrate;
901 SampleEntry {
902 format: FourCc(*b"mp4a"),
903 codec: CodecConfig::Aac(config),
904 video: None,
905 audio: Some(AudioParams {
906 channels,
907 sample_rate: sample_rate as f64,
908 sample_size: 16,
909 ..Default::default()
910 }),
911 bitrate: None,
912 raw: Vec::new(),
913 }
914 }
915
916 pub fn is_video(&self) -> bool {
917 self.video.is_some()
918 }
919
920 pub fn is_audio(&self) -> bool {
921 self.audio.is_some()
922 }
923
924 pub(crate) fn write(&self, b: &mut BoxBuf) -> Result<()> {
925 if !self.raw.is_empty() {
926 let m = b.start(&self.format.0);
927 b.bytes(&self.raw);
928 b.end(m);
929 return Ok(());
930 }
931 if let Some(v) = &self.video {
932 let m = b.start(&self.format.0);
933 b.zeros(6);
934 b.u16(1);
935 b.zeros(16);
936 b.u16(v.width);
937 b.u16(v.height);
938 b.u32(0x0048_0000);
939 b.u32(0x0048_0000);
940 b.u32(0);
941 b.u16(1);
942 b.zeros(32);
943 b.u16(24);
944 b.i16(-1);
945 match &self.codec {
946 CodecConfig::Avc(c) => b.leaf(b"avcC", &c.to_bytes()),
947 CodecConfig::Hevc(c) => b.leaf(b"hvcC", &c.to_bytes()),
948 CodecConfig::Vp9(c) => b.leaf(b"vpcC", &c.to_bytes()),
949 _ => {
950 return Err(Error::Unsupported(format!(
951 "writing {} video",
952 self.codec.name()
953 )));
954 }
955 }
956 if let Some((h, vv)) = v.pixel_aspect {
957 let m = b.start(b"pasp");
958 b.u32(h);
959 b.u32(vv);
960 b.end(m);
961 }
962 b.end(m);
963 return Ok(());
964 }
965 let (Some(a), CodecConfig::Aac(c)) = (&self.audio, &self.codec) else {
966 return Err(Error::Unsupported(format!(
967 "writing {} audio",
968 self.codec.name()
969 )));
970 };
971 let m = b.start(&self.format.0);
972 b.zeros(6);
973 b.u16(1);
974 b.zeros(8);
975 b.u16(a.channels.min(u16::MAX as u32) as u16);
976 b.u16(16);
977 b.zeros(4);
978 b.u32(if a.sample_rate < 65536.0 {
979 (a.sample_rate * 65536.0).round() as u32
980 } else {
981 0
982 });
983 b.leaf(
984 b"esds",
985 &esds_payload(&c.asc, c.max_bitrate, c.avg_bitrate, c.buffer_size),
986 );
987 if c.avg_bitrate > 0 {
988 let m = b.start(b"btrt");
989 b.u32(c.buffer_size);
990 b.u32(c.max_bitrate);
991 b.u32(c.avg_bitrate);
992 b.end(m);
993 }
994 b.end(m);
995 Ok(())
996 }
997}