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