1use serde::Serialize;
2use std::borrow::Cow;
3use std::convert::TryFrom;
4use std::fmt;
5
6use crate::mp4box::*;
7use crate::*;
8
9pub use bytes::Bytes;
10pub use num_rational::Ratio;
11
12#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
13pub struct FixedPointU8(Ratio<u16>);
14
15impl FixedPointU8 {
16 pub fn new(val: u8) -> Self {
17 Self(Ratio::new_raw(val as u16 * 0x100, 0x100))
18 }
19
20 pub fn new_raw(val: u16) -> Self {
21 Self(Ratio::new_raw(val, 0x100))
22 }
23
24 pub fn value(&self) -> u8 {
25 self.0.to_integer() as u8
26 }
27
28 pub fn raw_value(&self) -> u16 {
29 *self.0.numer()
30 }
31}
32
33#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
34pub struct FixedPointI8(Ratio<i16>);
35
36impl FixedPointI8 {
37 pub fn new(val: i8) -> Self {
38 Self(Ratio::new_raw(val as i16 * 0x100, 0x100))
39 }
40
41 pub fn new_raw(val: i16) -> Self {
42 Self(Ratio::new_raw(val, 0x100))
43 }
44
45 pub fn value(&self) -> i8 {
46 self.0.to_integer() as i8
47 }
48
49 pub fn raw_value(&self) -> i16 {
50 *self.0.numer()
51 }
52}
53
54#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
55pub struct FixedPointU16(Ratio<u32>);
56
57impl FixedPointU16 {
58 pub fn new(val: u16) -> Self {
59 Self(Ratio::new_raw(val as u32 * 0x10000, 0x10000))
60 }
61
62 pub fn new_raw(val: u32) -> Self {
63 Self(Ratio::new_raw(val, 0x10000))
64 }
65
66 pub fn value(&self) -> u16 {
67 self.0.to_integer() as u16
68 }
69
70 pub fn raw_value(&self) -> u32 {
71 *self.0.numer()
72 }
73}
74
75impl fmt::Debug for BoxType {
76 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
77 let fourcc: FourCC = From::from(*self);
78 write!(f, "{fourcc}")
79 }
80}
81
82impl fmt::Display for BoxType {
83 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
84 let fourcc: FourCC = From::from(*self);
85 write!(f, "{fourcc}")
86 }
87}
88
89#[derive(Default, PartialEq, Eq, Clone, Copy, Serialize)]
90pub struct FourCC {
91 pub value: [u8; 4],
92}
93
94impl std::str::FromStr for FourCC {
95 type Err = Error;
96
97 fn from_str(s: &str) -> Result<Self, Error> {
98 if let [a, b, c, d] = s.as_bytes() {
99 Ok(Self {
100 value: [*a, *b, *c, *d],
101 })
102 } else {
103 Err(Error::InvalidData("expected exactly four bytes in string"))
104 }
105 }
106}
107
108impl From<u32> for FourCC {
109 fn from(number: u32) -> Self {
110 FourCC {
111 value: number.to_be_bytes(),
112 }
113 }
114}
115
116impl From<FourCC> for u32 {
117 fn from(fourcc: FourCC) -> u32 {
118 (&fourcc).into()
119 }
120}
121
122impl From<&FourCC> for u32 {
123 fn from(fourcc: &FourCC) -> u32 {
124 u32::from_be_bytes(fourcc.value)
125 }
126}
127
128impl From<[u8; 4]> for FourCC {
129 fn from(value: [u8; 4]) -> FourCC {
130 FourCC { value }
131 }
132}
133
134impl From<BoxType> for FourCC {
135 fn from(t: BoxType) -> FourCC {
136 let box_num: u32 = Into::into(t);
137 From::from(box_num)
138 }
139}
140
141impl fmt::Debug for FourCC {
142 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
143 let code: u32 = self.into();
144 let string = String::from_utf8_lossy(&self.value[..]);
145 write!(f, "{string} / {code:#010X}")
146 }
147}
148
149impl fmt::Display for FourCC {
150 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
151 write!(f, "{}", String::from_utf8_lossy(&self.value[..]))
152 }
153}
154
155const DISPLAY_TYPE_VIDEO: &str = "Video";
156const DISPLAY_TYPE_AUDIO: &str = "Audio";
157const DISPLAY_TYPE_SUBTITLE: &str = "Subtitle";
158
159const HANDLER_TYPE_VIDEO: &str = "vide";
160const HANDLER_TYPE_VIDEO_FOURCC: [u8; 4] = [b'v', b'i', b'd', b'e'];
161
162const HANDLER_TYPE_AUDIO: &str = "soun";
163const HANDLER_TYPE_AUDIO_FOURCC: [u8; 4] = [b's', b'o', b'u', b'n'];
164
165const HANDLER_TYPE_SUBTITLE: &str = "sbtl";
166const HANDLER_TYPE_SUBTITLE_FOURCC: [u8; 4] = [b's', b'b', b't', b'l'];
167
168#[derive(Debug, Clone, Copy, PartialEq, Eq)]
169pub enum TrackType {
170 Video,
171 Audio,
172 Subtitle,
173 Other(FourCC),
174}
175
176impl fmt::Display for TrackType {
177 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
178 match self {
179 TrackType::Video => write!(f, "{DISPLAY_TYPE_VIDEO}"),
180 TrackType::Audio => write!(f, "{DISPLAY_TYPE_AUDIO}"),
181 TrackType::Subtitle => write!(f, "{DISPLAY_TYPE_SUBTITLE}"),
182 TrackType::Other(other) => write!(f, "Other({})", other),
183 }
184 }
185}
186
187impl TryFrom<&str> for TrackType {
188 type Error = Error;
189 fn try_from(handler: &str) -> Result<TrackType, Error> {
190 match handler {
191 HANDLER_TYPE_VIDEO => Ok(TrackType::Video),
192 HANDLER_TYPE_AUDIO => Ok(TrackType::Audio),
193 HANDLER_TYPE_SUBTITLE => Ok(TrackType::Subtitle),
194 _ => Err(Error::InvalidData("unsupported handler type")),
195 }
196 }
197}
198
199impl From<&FourCC> for TrackType {
200 fn from(fourcc: &FourCC) -> TrackType {
201 match fourcc.value {
202 HANDLER_TYPE_VIDEO_FOURCC => TrackType::Video,
203 HANDLER_TYPE_AUDIO_FOURCC => TrackType::Audio,
204 HANDLER_TYPE_SUBTITLE_FOURCC => TrackType::Subtitle,
205 other => TrackType::Other(other.into()),
206 }
207 }
208}
209
210impl From<TrackType> for FourCC {
211 fn from(t: TrackType) -> FourCC {
212 match t {
213 TrackType::Video => HANDLER_TYPE_VIDEO_FOURCC.into(),
214 TrackType::Audio => HANDLER_TYPE_AUDIO_FOURCC.into(),
215 TrackType::Subtitle => HANDLER_TYPE_SUBTITLE_FOURCC.into(),
216 TrackType::Other(inner) => inner,
217 }
218 }
219}
220
221const MEDIA_TYPE_H264: &str = "h264";
222const MEDIA_TYPE_H265: &str = "h265";
223const MEDIA_TYPE_VP9: &str = "vp9";
224const MEDIA_TYPE_AAC: &str = "aac";
225const MEDIA_TYPE_TTXT: &str = "ttxt";
226
227#[derive(Debug, Clone, Copy, PartialEq, Eq)]
228pub enum MediaType {
229 H264,
230 H265,
231 VP9,
232 AAC,
233 TTXT,
234}
235
236impl fmt::Display for MediaType {
237 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
238 let s: &str = self.into();
239 write!(f, "{s}")
240 }
241}
242
243impl TryFrom<&str> for MediaType {
244 type Error = Error;
245 fn try_from(media: &str) -> Result<MediaType, Error> {
246 match media {
247 MEDIA_TYPE_H264 => Ok(MediaType::H264),
248 MEDIA_TYPE_H265 => Ok(MediaType::H265),
249 MEDIA_TYPE_VP9 => Ok(MediaType::VP9),
250 MEDIA_TYPE_AAC => Ok(MediaType::AAC),
251 MEDIA_TYPE_TTXT => Ok(MediaType::TTXT),
252 _ => Err(Error::InvalidData("unsupported media type")),
253 }
254 }
255}
256
257impl From<MediaType> for &str {
258 fn from(t: MediaType) -> &'static str {
259 match t {
260 MediaType::H264 => MEDIA_TYPE_H264,
261 MediaType::H265 => MEDIA_TYPE_H265,
262 MediaType::VP9 => MEDIA_TYPE_VP9,
263 MediaType::AAC => MEDIA_TYPE_AAC,
264 MediaType::TTXT => MEDIA_TYPE_TTXT,
265 }
266 }
267}
268
269impl From<&MediaType> for &str {
270 fn from(t: &MediaType) -> &'static str {
271 match t {
272 MediaType::H264 => MEDIA_TYPE_H264,
273 MediaType::H265 => MEDIA_TYPE_H265,
274 MediaType::VP9 => MEDIA_TYPE_VP9,
275 MediaType::AAC => MEDIA_TYPE_AAC,
276 MediaType::TTXT => MEDIA_TYPE_TTXT,
277 }
278 }
279}
280
281#[derive(Debug, PartialEq, Eq, Clone, Copy)]
282pub enum AvcProfile {
283 AvcConstrainedBaseline, AvcBaseline, AvcMain, AvcExtended, AvcHigh, }
290
291impl TryFrom<(u8, u8)> for AvcProfile {
292 type Error = Error;
293 fn try_from(value: (u8, u8)) -> Result<AvcProfile, Error> {
294 let profile = value.0;
295 let constraint_set1_flag = (value.1 & 0x40) >> 7;
296 match (profile, constraint_set1_flag) {
297 (66, 1) => Ok(AvcProfile::AvcConstrainedBaseline),
298 (66, 0) => Ok(AvcProfile::AvcBaseline),
299 (77, _) => Ok(AvcProfile::AvcMain),
300 (88, _) => Ok(AvcProfile::AvcExtended),
301 (100, _) => Ok(AvcProfile::AvcHigh),
302 _ => Err(Error::InvalidData("unsupported avc profile")),
303 }
304 }
305}
306
307impl fmt::Display for AvcProfile {
308 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
309 let profile = match self {
310 AvcProfile::AvcConstrainedBaseline => "Constrained Baseline",
311 AvcProfile::AvcBaseline => "Baseline",
312 AvcProfile::AvcMain => "Main",
313 AvcProfile::AvcExtended => "Extended",
314 AvcProfile::AvcHigh => "High",
315 };
316 write!(f, "{profile}")
317 }
318}
319
320#[derive(Debug, PartialEq, Eq, Clone, Copy)]
321pub enum AudioObjectType {
322 AacMain = 1, AacLowComplexity = 2, AacScalableSampleRate = 3, AacLongTermPrediction = 4, SpectralBandReplication = 5, AACScalable = 6, TwinVQ = 7, CodeExcitedLinearPrediction = 8, HarmonicVectorExcitationCoding = 9, TextToSpeechtInterface = 12, MainSynthetic = 13, WavetableSynthesis = 14, GeneralMIDI = 15, AlgorithmicSynthesis = 16, ErrorResilientAacLowComplexity = 17, ErrorResilientAacLongTermPrediction = 19, ErrorResilientAacScalable = 20, ErrorResilientAacTwinVQ = 21, ErrorResilientAacBitSlicedArithmeticCoding = 22, ErrorResilientAacLowDelay = 23, ErrorResilientCodeExcitedLinearPrediction = 24, ErrorResilientHarmonicVectorExcitationCoding = 25, ErrorResilientHarmonicIndividualLinesNoise = 26, ErrorResilientParametric = 27, SinuSoidalCoding = 28, ParametricStereo = 29, MpegSurround = 30, MpegLayer1 = 32, MpegLayer2 = 33, MpegLayer3 = 34, DirectStreamTransfer = 35, AudioLosslessCoding = 36, ScalableLosslessCoding = 37, ScalableLosslessCodingNoneCore = 38, ErrorResilientAacEnhancedLowDelay = 39, SymbolicMusicRepresentationSimple = 40, SymbolicMusicRepresentationMain = 41, UnifiedSpeechAudioCoding = 42, SpatialAudioObjectCoding = 43, LowDelayMpegSurround = 44, SpatialAudioObjectCodingDialogueEnhancement = 45, AudioSync = 46, }
365
366impl TryFrom<u8> for AudioObjectType {
367 type Error = Error;
368 fn try_from(value: u8) -> Result<AudioObjectType, Error> {
369 match value {
370 1 => Ok(AudioObjectType::AacMain),
371 2 => Ok(AudioObjectType::AacLowComplexity),
372 3 => Ok(AudioObjectType::AacScalableSampleRate),
373 4 => Ok(AudioObjectType::AacLongTermPrediction),
374 5 => Ok(AudioObjectType::SpectralBandReplication),
375 6 => Ok(AudioObjectType::AACScalable),
376 7 => Ok(AudioObjectType::TwinVQ),
377 8 => Ok(AudioObjectType::CodeExcitedLinearPrediction),
378 9 => Ok(AudioObjectType::HarmonicVectorExcitationCoding),
379 12 => Ok(AudioObjectType::TextToSpeechtInterface),
380 13 => Ok(AudioObjectType::MainSynthetic),
381 14 => Ok(AudioObjectType::WavetableSynthesis),
382 15 => Ok(AudioObjectType::GeneralMIDI),
383 16 => Ok(AudioObjectType::AlgorithmicSynthesis),
384 17 => Ok(AudioObjectType::ErrorResilientAacLowComplexity),
385 19 => Ok(AudioObjectType::ErrorResilientAacLongTermPrediction),
386 20 => Ok(AudioObjectType::ErrorResilientAacScalable),
387 21 => Ok(AudioObjectType::ErrorResilientAacTwinVQ),
388 22 => Ok(AudioObjectType::ErrorResilientAacBitSlicedArithmeticCoding),
389 23 => Ok(AudioObjectType::ErrorResilientAacLowDelay),
390 24 => Ok(AudioObjectType::ErrorResilientCodeExcitedLinearPrediction),
391 25 => Ok(AudioObjectType::ErrorResilientHarmonicVectorExcitationCoding),
392 26 => Ok(AudioObjectType::ErrorResilientHarmonicIndividualLinesNoise),
393 27 => Ok(AudioObjectType::ErrorResilientParametric),
394 28 => Ok(AudioObjectType::SinuSoidalCoding),
395 29 => Ok(AudioObjectType::ParametricStereo),
396 30 => Ok(AudioObjectType::MpegSurround),
397 32 => Ok(AudioObjectType::MpegLayer1),
398 33 => Ok(AudioObjectType::MpegLayer2),
399 34 => Ok(AudioObjectType::MpegLayer3),
400 35 => Ok(AudioObjectType::DirectStreamTransfer),
401 36 => Ok(AudioObjectType::AudioLosslessCoding),
402 37 => Ok(AudioObjectType::ScalableLosslessCoding),
403 38 => Ok(AudioObjectType::ScalableLosslessCodingNoneCore),
404 39 => Ok(AudioObjectType::ErrorResilientAacEnhancedLowDelay),
405 40 => Ok(AudioObjectType::SymbolicMusicRepresentationSimple),
406 41 => Ok(AudioObjectType::SymbolicMusicRepresentationMain),
407 42 => Ok(AudioObjectType::UnifiedSpeechAudioCoding),
408 43 => Ok(AudioObjectType::SpatialAudioObjectCoding),
409 44 => Ok(AudioObjectType::LowDelayMpegSurround),
410 45 => Ok(AudioObjectType::SpatialAudioObjectCodingDialogueEnhancement),
411 46 => Ok(AudioObjectType::AudioSync),
412 _ => Err(Error::InvalidData("invalid audio object type")),
413 }
414 }
415}
416
417impl fmt::Display for AudioObjectType {
418 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
419 let type_str = match self {
420 AudioObjectType::AacMain => "AAC Main",
421 AudioObjectType::AacLowComplexity => "LC",
422 AudioObjectType::AacScalableSampleRate => "SSR",
423 AudioObjectType::AacLongTermPrediction => "LTP",
424 AudioObjectType::SpectralBandReplication => "SBR",
425 AudioObjectType::AACScalable => "Scalable",
426 AudioObjectType::TwinVQ => "TwinVQ",
427 AudioObjectType::CodeExcitedLinearPrediction => "CELP",
428 AudioObjectType::HarmonicVectorExcitationCoding => "HVXC",
429 AudioObjectType::TextToSpeechtInterface => "TTSI",
430 AudioObjectType::MainSynthetic => "Main Synthetic",
431 AudioObjectType::WavetableSynthesis => "Wavetable Synthesis",
432 AudioObjectType::GeneralMIDI => "General MIDI",
433 AudioObjectType::AlgorithmicSynthesis => "Algorithmic Synthesis",
434 AudioObjectType::ErrorResilientAacLowComplexity => "ER AAC LC",
435 AudioObjectType::ErrorResilientAacLongTermPrediction => "ER AAC LTP",
436 AudioObjectType::ErrorResilientAacScalable => "ER AAC scalable",
437 AudioObjectType::ErrorResilientAacTwinVQ => "ER AAC TwinVQ",
438 AudioObjectType::ErrorResilientAacBitSlicedArithmeticCoding => "ER AAC BSAC",
439 AudioObjectType::ErrorResilientAacLowDelay => "ER AAC LD",
440 AudioObjectType::ErrorResilientCodeExcitedLinearPrediction => "ER CELP",
441 AudioObjectType::ErrorResilientHarmonicVectorExcitationCoding => "ER HVXC",
442 AudioObjectType::ErrorResilientHarmonicIndividualLinesNoise => "ER HILN",
443 AudioObjectType::ErrorResilientParametric => "ER Parametric",
444 AudioObjectType::SinuSoidalCoding => "SSC",
445 AudioObjectType::ParametricStereo => "Parametric Stereo",
446 AudioObjectType::MpegSurround => "MPEG surround",
447 AudioObjectType::MpegLayer1 => "MPEG Layer 1",
448 AudioObjectType::MpegLayer2 => "MPEG Layer 2",
449 AudioObjectType::MpegLayer3 => "MPEG Layer 3",
450 AudioObjectType::DirectStreamTransfer => "DST",
451 AudioObjectType::AudioLosslessCoding => "ALS",
452 AudioObjectType::ScalableLosslessCoding => "SLS",
453 AudioObjectType::ScalableLosslessCodingNoneCore => "SLS Non-core",
454 AudioObjectType::ErrorResilientAacEnhancedLowDelay => "ER AAC ELD",
455 AudioObjectType::SymbolicMusicRepresentationSimple => "SMR Simple",
456 AudioObjectType::SymbolicMusicRepresentationMain => "SMR Main",
457 AudioObjectType::UnifiedSpeechAudioCoding => "USAC",
458 AudioObjectType::SpatialAudioObjectCoding => "SAOC",
459 AudioObjectType::LowDelayMpegSurround => "LD MPEG Surround",
460 AudioObjectType::SpatialAudioObjectCodingDialogueEnhancement => "SAOC-DE",
461 AudioObjectType::AudioSync => "Audio Sync",
462 };
463 write!(f, "{type_str}")
464 }
465}
466
467#[derive(Debug, PartialEq, Eq, Clone, Copy)]
468pub enum SampleFreqIndex {
469 Freq96000 = 0x0,
470 Freq88200 = 0x1,
471 Freq64000 = 0x2,
472 Freq48000 = 0x3,
473 Freq44100 = 0x4,
474 Freq32000 = 0x5,
475 Freq24000 = 0x6,
476 Freq22050 = 0x7,
477 Freq16000 = 0x8,
478 Freq12000 = 0x9,
479 Freq11025 = 0xa,
480 Freq8000 = 0xb,
481 Freq7350 = 0xc,
482}
483
484impl TryFrom<u8> for SampleFreqIndex {
485 type Error = Error;
486 fn try_from(value: u8) -> Result<SampleFreqIndex, Error> {
487 match value {
488 0x0 => Ok(SampleFreqIndex::Freq96000),
489 0x1 => Ok(SampleFreqIndex::Freq88200),
490 0x2 => Ok(SampleFreqIndex::Freq64000),
491 0x3 => Ok(SampleFreqIndex::Freq48000),
492 0x4 => Ok(SampleFreqIndex::Freq44100),
493 0x5 => Ok(SampleFreqIndex::Freq32000),
494 0x6 => Ok(SampleFreqIndex::Freq24000),
495 0x7 => Ok(SampleFreqIndex::Freq22050),
496 0x8 => Ok(SampleFreqIndex::Freq16000),
497 0x9 => Ok(SampleFreqIndex::Freq12000),
498 0xa => Ok(SampleFreqIndex::Freq11025),
499 0xb => Ok(SampleFreqIndex::Freq8000),
500 0xc => Ok(SampleFreqIndex::Freq7350),
501 _ => Err(Error::InvalidData("invalid sampling frequency index")),
502 }
503 }
504}
505
506impl SampleFreqIndex {
507 pub fn freq(&self) -> u32 {
508 match *self {
509 SampleFreqIndex::Freq96000 => 96000,
510 SampleFreqIndex::Freq88200 => 88200,
511 SampleFreqIndex::Freq64000 => 64000,
512 SampleFreqIndex::Freq48000 => 48000,
513 SampleFreqIndex::Freq44100 => 44100,
514 SampleFreqIndex::Freq32000 => 32000,
515 SampleFreqIndex::Freq24000 => 24000,
516 SampleFreqIndex::Freq22050 => 22050,
517 SampleFreqIndex::Freq16000 => 16000,
518 SampleFreqIndex::Freq12000 => 12000,
519 SampleFreqIndex::Freq11025 => 11025,
520 SampleFreqIndex::Freq8000 => 8000,
521 SampleFreqIndex::Freq7350 => 7350,
522 }
523 }
524}
525
526#[derive(Debug, PartialEq, Eq, Clone, Copy)]
527pub enum ChannelConfig {
528 Mono = 0x1,
529 Stereo = 0x2,
530 Three = 0x3,
531 Four = 0x4,
532 Five = 0x5,
533 FiveOne = 0x6,
534 SevenOne = 0x7,
535}
536
537impl TryFrom<u8> for ChannelConfig {
538 type Error = Error;
539 fn try_from(value: u8) -> Result<ChannelConfig, Error> {
540 match value {
541 0x1 => Ok(ChannelConfig::Mono),
542 0x2 => Ok(ChannelConfig::Stereo),
543 0x3 => Ok(ChannelConfig::Three),
544 0x4 => Ok(ChannelConfig::Four),
545 0x5 => Ok(ChannelConfig::Five),
546 0x6 => Ok(ChannelConfig::FiveOne),
547 0x7 => Ok(ChannelConfig::SevenOne),
548 _ => Err(Error::InvalidData("invalid channel configuration")),
549 }
550 }
551}
552
553impl fmt::Display for ChannelConfig {
554 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
555 let s = match self {
556 ChannelConfig::Mono => "mono",
557 ChannelConfig::Stereo => "stereo",
558 ChannelConfig::Three => "three",
559 ChannelConfig::Four => "four",
560 ChannelConfig::Five => "five",
561 ChannelConfig::FiveOne => "five.one",
562 ChannelConfig::SevenOne => "seven.one",
563 };
564 write!(f, "{s}")
565 }
566}
567
568#[derive(Debug, PartialEq, Eq, Clone, Default)]
569pub struct AvcConfig {
570 pub width: u16,
571 pub height: u16,
572 pub seq_param_set: Vec<u8>,
573 pub pic_param_set: Vec<u8>,
574}
575
576#[derive(Debug, PartialEq, Eq, Clone, Default)]
577pub struct HevcConfig {
578 pub width: u16,
579 pub height: u16,
580}
581
582#[derive(Debug, PartialEq, Eq, Clone, Default)]
583pub struct Vp9Config {
584 pub width: u16,
585 pub height: u16,
586}
587
588#[derive(Debug, PartialEq, Eq, Clone)]
589pub struct AacConfig {
590 pub bitrate: u32,
591 pub profile: AudioObjectType,
592 pub freq_index: SampleFreqIndex,
593 pub chan_conf: ChannelConfig,
594}
595
596impl Default for AacConfig {
597 fn default() -> Self {
598 Self {
599 bitrate: 0,
600 profile: AudioObjectType::AacLowComplexity,
601 freq_index: SampleFreqIndex::Freq48000,
602 chan_conf: ChannelConfig::Stereo,
603 }
604 }
605}
606
607#[derive(Debug, PartialEq, Eq, Clone, Default)]
608pub struct TtxtConfig {}
609
610#[derive(Debug, PartialEq, Eq, Clone)]
611pub enum MediaConfig {
612 AvcConfig(AvcConfig),
613 HevcConfig(HevcConfig),
614 Vp9Config(Vp9Config),
615 AacConfig(AacConfig),
616 TtxtConfig(TtxtConfig),
617}
618
619#[derive(Debug)]
620pub struct Mp4Sample {
621 pub start_time: u64,
622 pub duration: u32,
623 pub rendering_offset: i32,
624 pub is_sync: bool,
625 pub bytes: Bytes,
626}
627
628impl PartialEq for Mp4Sample {
629 fn eq(&self, other: &Self) -> bool {
630 self.start_time == other.start_time
631 && self.duration == other.duration
632 && self.rendering_offset == other.rendering_offset
633 && self.is_sync == other.is_sync
634 && self.bytes.len() == other.bytes.len() }
636}
637
638impl fmt::Display for Mp4Sample {
639 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
640 write!(
641 f,
642 "start_time {}, duration {}, rendering_offset {}, is_sync {}, length {}",
643 self.start_time,
644 self.duration,
645 self.rendering_offset,
646 self.is_sync,
647 self.bytes.len()
648 )
649 }
650}
651
652pub fn creation_time(creation_time: u64) -> u64 {
653 if creation_time >= 2082844800 {
655 creation_time - 2082844800
656 } else {
657 creation_time
658 }
659}
660
661#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
662pub enum DataType {
663 Binary = 0x000000,
664 Text = 0x000001,
665 Image = 0x00000D,
666 TempoCpil = 0x000015,
667}
668
669#[allow(clippy::derivable_impls)]
670impl std::default::Default for DataType {
671 fn default() -> Self {
672 DataType::Binary
673 }
674}
675
676impl TryFrom<u32> for DataType {
677 type Error = Error;
678 fn try_from(value: u32) -> Result<DataType, Self::Error> {
679 match value {
680 0x000000 => Ok(DataType::Binary),
681 0x000001 => Ok(DataType::Text),
682 0x00000D => Ok(DataType::Image),
683 0x000015 => Ok(DataType::TempoCpil),
684 _ => Err(Error::InvalidData("invalid data type")),
685 }
686 }
687}
688
689#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize)]
690pub enum MetadataKey {
691 Title,
692 Year,
693 Poster,
694 Summary,
695}
696
697pub trait Metadata<'a> {
698 fn title(&self) -> Option<Cow<'_, str>>;
700 fn year(&self) -> Option<u32>;
702 fn poster(&self) -> Option<&[u8]>;
704 fn summary(&self) -> Option<Cow<'_, str>>;
706}
707
708impl<'a, T: Metadata<'a>> Metadata<'a> for &'a T {
709 fn title(&self) -> Option<Cow<'_, str>> {
710 (**self).title()
711 }
712
713 fn year(&self) -> Option<u32> {
714 (**self).year()
715 }
716
717 fn poster(&self) -> Option<&[u8]> {
718 (**self).poster()
719 }
720
721 fn summary(&self) -> Option<Cow<'_, str>> {
722 (**self).summary()
723 }
724}
725
726impl<'a, T: Metadata<'a>> Metadata<'a> for Option<T> {
727 fn title(&self) -> Option<Cow<'_, str>> {
728 self.as_ref().and_then(|t| t.title())
729 }
730
731 fn year(&self) -> Option<u32> {
732 self.as_ref().and_then(|t| t.year())
733 }
734
735 fn poster(&self) -> Option<&[u8]> {
736 self.as_ref().and_then(|t| t.poster())
737 }
738
739 fn summary(&self) -> Option<Cow<'_, str>> {
740 self.as_ref().and_then(|t| t.summary())
741 }
742}