Skip to content

Commit 9101536

Browse files
committed
try fix hevc transcoding
1 parent 0ae71fd commit 9101536

File tree

7 files changed

+121
-5
lines changed

7 files changed

+121
-5
lines changed

crates/mp4/src/boxes/mod.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ use crate::boxes::types::ftyp::Ftyp;
3333
use crate::boxes::types::hdlr::Hdlr;
3434
use crate::boxes::types::hev1::Hev1;
3535
use crate::boxes::types::hmhd::Hmhd;
36+
use crate::boxes::types::hvc1::Hvc1;
3637
use crate::boxes::types::hvcc::HvcC;
3738
use crate::boxes::types::mdat::Mdat;
3839
use crate::boxes::types::mdhd::Mdhd;
@@ -84,5 +85,5 @@ impl_box!(
8485
Url, Avc1, Clap, Pasp, AvcC, Btrt,
8586
Mp4a, Esds, Moof, Mfhd, Traf, Tfhd,
8687
Tfdt, Trun, Mdat, Av01, Av1C, Colr,
87-
Hev1, HvcC, Opus,
88+
Hev1, Hvc1, HvcC, Opus,
8889
);

crates/mp4/src/boxes/types/ftyp.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ pub enum FourCC {
7777
Avc1,
7878
Av01,
7979
Hev1,
80+
Hvc1,
8081
Unknown([u8; 4]),
8182
}
8283

@@ -89,6 +90,7 @@ impl FourCC {
8990
Self::Avc1 => *b"avc1",
9091
Self::Av01 => *b"av01",
9192
Self::Hev1 => *b"hev1",
93+
Self::Hvc1 => *b"hvc1",
9294
Self::Unknown(bytes) => *bytes,
9395
}
9496
}

crates/mp4/src/boxes/types/hvc1.rs

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
use std::io;
2+
3+
use bytes::{Buf, Bytes};
4+
5+
use super::btrt::Btrt;
6+
use super::hvcc::HvcC;
7+
use super::stsd::{SampleEntry, VisualSampleEntry};
8+
use crate::boxes::DynBox;
9+
use crate::boxes::header::BoxHeader;
10+
use crate::boxes::traits::BoxType;
11+
use crate::codec::VideoCodec;
12+
13+
#[derive(Debug, Clone, PartialEq)]
14+
/// HEVC (H.265) Codec Box
15+
/// ISO/IEC 14496-15:2022 - 8.4
16+
pub struct Hvc1 {
17+
pub header: BoxHeader,
18+
pub visual_sample_entry: SampleEntry<VisualSampleEntry>,
19+
pub hvcc: HvcC,
20+
pub btrt: Option<Btrt>,
21+
pub unknown: Vec<DynBox>,
22+
}
23+
24+
impl Hvc1 {
25+
pub fn new(visual_sample_entry: SampleEntry<VisualSampleEntry>, hvcc: HvcC, btrt: Option<Btrt>) -> Self {
26+
Self {
27+
header: BoxHeader::new(Self::NAME),
28+
visual_sample_entry,
29+
hvcc,
30+
btrt,
31+
unknown: Vec::new(),
32+
}
33+
}
34+
35+
pub fn codec(&self) -> io::Result<VideoCodec> {
36+
Ok(VideoCodec::Hevc {
37+
constraint_indicator: self.hvcc.hevc_config.general_constraint_indicator_flags,
38+
level: self.hvcc.hevc_config.general_level_idc,
39+
profile: self.hvcc.hevc_config.general_profile_idc,
40+
profile_compatibility: self.hvcc.hevc_config.general_profile_compatibility_flags,
41+
tier: self.hvcc.hevc_config.general_tier_flag,
42+
general_profile_space: self.hvcc.hevc_config.general_profile_space,
43+
})
44+
}
45+
}
46+
47+
impl BoxType for Hvc1 {
48+
const NAME: [u8; 4] = *b"hvc1";
49+
50+
fn demux(header: BoxHeader, data: Bytes) -> io::Result<Self> {
51+
let mut reader = io::Cursor::new(data);
52+
53+
let mut visual_sample_entry = SampleEntry::<VisualSampleEntry>::demux(&mut reader)?;
54+
55+
let mut hvcc = None;
56+
let mut btrt = None;
57+
let mut unknown = Vec::new();
58+
59+
while reader.has_remaining() {
60+
let dyn_box = DynBox::demux(&mut reader)?;
61+
match dyn_box {
62+
DynBox::HvcC(b) => {
63+
hvcc = Some(*b);
64+
}
65+
DynBox::Btrt(b) => {
66+
btrt = Some(*b);
67+
}
68+
DynBox::Clap(b) => {
69+
visual_sample_entry.extension.clap = Some(*b);
70+
}
71+
DynBox::Pasp(b) => {
72+
visual_sample_entry.extension.pasp = Some(*b);
73+
}
74+
DynBox::Colr(b) => {
75+
visual_sample_entry.extension.colr = Some(*b);
76+
}
77+
_ => {
78+
unknown.push(dyn_box);
79+
}
80+
}
81+
}
82+
83+
let hvcc = hvcc.ok_or_else(|| io::Error::new(io::ErrorKind::InvalidData, "trak box is missing tkhd box"))?;
84+
85+
Ok(Self {
86+
header,
87+
visual_sample_entry,
88+
hvcc,
89+
btrt,
90+
unknown,
91+
})
92+
}
93+
94+
fn primitive_size(&self) -> u64 {
95+
self.visual_sample_entry.size()
96+
+ self.hvcc.size()
97+
+ self.btrt.as_ref().map(|b| b.size()).unwrap_or(0)
98+
+ self.unknown.iter().map(|b| b.size()).sum::<u64>()
99+
}
100+
101+
fn primitive_mux<T: io::Write>(&self, writer: &mut T) -> io::Result<()> {
102+
self.visual_sample_entry.mux(writer)?;
103+
self.hvcc.mux(writer)?;
104+
if let Some(btrt) = &self.btrt {
105+
btrt.mux(writer)?;
106+
}
107+
for unknown in &self.unknown {
108+
unknown.mux(writer)?;
109+
}
110+
Ok(())
111+
}
112+
}

crates/mp4/src/boxes/types/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ pub mod ftyp;
1616
pub mod hdlr;
1717
pub mod hev1;
1818
pub mod hmhd;
19+
pub mod hvc1;
1920
pub mod hvcc;
2021
pub mod mdat;
2122
pub mod mdhd;

crates/transmuxer/src/codecs/hevc.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use scuffle_flv::video::header::VideoFrameType;
55
use scuffle_h265::{HEVCDecoderConfigurationRecord, SpsRbsp};
66
use scuffle_mp4::DynBox;
77
use scuffle_mp4::types::colr::{ColorType, Colr};
8-
use scuffle_mp4::types::hev1::Hev1;
8+
use scuffle_mp4::types::hvc1::Hvc1;
99
use scuffle_mp4::types::hvcc::HvcC;
1010
use scuffle_mp4::types::stsd::{SampleEntry, VisualSampleEntry};
1111
use scuffle_mp4::types::trun::{TrunSample, TrunSampleFlag};
@@ -34,7 +34,7 @@ pub(crate) fn stsd_entry(config: HEVCDecoderConfigurationRecord) -> Result<(DynB
3434
});
3535

3636
Ok((
37-
Hev1::new(
37+
Hvc1::new(
3838
SampleEntry::new(VisualSampleEntry::new(
3939
sps.cropped_width() as u16,
4040
sps.cropped_height() as u16,

crates/transmuxer/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -493,7 +493,7 @@ impl<'a> Transmuxer<'a> {
493493
entry
494494
}
495495
VideoSequenceHeader::Hevc(config) => {
496-
compatable_brands.push(FourCC::Hev1);
496+
compatable_brands.push(FourCC::Hvc1);
497497
video_codec = VideoCodec::Hevc {
498498
constraint_indicator: config.general_constraint_indicator_flags,
499499
level: config.general_level_idc,

crates/transmuxer/src/tests/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -333,7 +333,7 @@ fn test_transmuxer_hevc_aac() {
333333
assert_eq!(json["format"]["duration"], "2.026667");
334334
assert_eq!(json["format"]["tags"]["major_brand"], "iso5");
335335
assert_eq!(json["format"]["tags"]["minor_version"], "512");
336-
assert_eq!(json["format"]["tags"]["compatible_brands"], "iso5iso6hev1mp41");
336+
assert_eq!(json["format"]["tags"]["compatible_brands"], "iso5iso6hvc1mp41");
337337

338338
assert_eq!(json["streams"][0]["codec_name"], "hevc");
339339
assert_eq!(json["streams"][0]["codec_type"], "video");

0 commit comments

Comments
 (0)