-
Notifications
You must be signed in to change notification settings - Fork 64
Parsing sinf box for enca/encv track #48
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
2 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -228,6 +228,7 @@ pub struct AudioSampleEntry { | |
pub samplesize: u16, | ||
pub samplerate: u32, | ||
pub codec_specific: AudioCodecSpecific, | ||
pub protection_info: Option<ProtectionSchemeInfoBox>, | ||
} | ||
|
||
#[derive(Debug, Clone)] | ||
|
@@ -242,6 +243,7 @@ pub struct VideoSampleEntry { | |
pub width: u16, | ||
pub height: u16, | ||
pub codec_specific: VideoCodecSpecific, | ||
pub protection_info: Option<ProtectionSchemeInfoBox>, | ||
} | ||
|
||
/// Represent a Video Partition Codec Configuration 'vpcC' box (aka vp9). | ||
|
@@ -306,6 +308,19 @@ pub struct ProtectionSystemSpecificHeaderBox { | |
pub box_content: ByteData, | ||
} | ||
|
||
#[derive(Debug, Default, Clone)] | ||
pub struct TrackEncryptionBox { | ||
pub is_encrypted: u32, | ||
pub iv_size: u8, | ||
pub kid: Vec<u8>, | ||
} | ||
|
||
#[derive(Debug, Default, Clone)] | ||
pub struct ProtectionSchemeInfoBox { | ||
pub code_name: String, | ||
pub tenc: TrackEncryptionBox, | ||
} | ||
|
||
/// Internal data structures. | ||
#[derive(Debug, Default)] | ||
pub struct MediaContext { | ||
|
@@ -1476,6 +1491,7 @@ fn read_video_sample_entry<T: Read>(src: &mut BMFFBox<T>, track: &mut Track) -> | |
|
||
// Skip clap/pasp/etc. for now. | ||
let mut codec_specific = None; | ||
let mut protection_info = None; | ||
let mut iter = src.box_iter(); | ||
while let Some(mut b) = iter.next_box()? { | ||
match b.head.name { | ||
|
@@ -1491,6 +1507,7 @@ fn read_video_sample_entry<T: Read>(src: &mut BMFFBox<T>, track: &mut Track) -> | |
return Err(Error::InvalidData("avcC box exceeds BUF_SIZE_LIMIT")); | ||
} | ||
let avcc = read_buf(&mut b.content, avcc_size as usize)?; | ||
log!("{:?} (avcc)", avcc); | ||
// TODO(kinetik): Parse avcC box? For now we just stash the data. | ||
codec_specific = Some(VideoCodecSpecific::AVCConfig(avcc)); | ||
} | ||
|
@@ -1503,6 +1520,14 @@ fn read_video_sample_entry<T: Read>(src: &mut BMFFBox<T>, track: &mut Track) -> | |
let vpcc = read_vpcc(&mut b)?; | ||
codec_specific = Some(VideoCodecSpecific::VPxConfig(vpcc)); | ||
} | ||
BoxType::ProtectionSchemeInformationBox => { | ||
if name != BoxType::ProtectedVisualSampleEntry { | ||
return Err(Error::InvalidData("malformed video sample entry")); | ||
} | ||
let sinf = read_sinf(&mut b)?; | ||
log!("{:?} (sinf)", sinf); | ||
protection_info = Some(sinf); | ||
} | ||
_ => skip_box_content(&mut b)?, | ||
} | ||
check_parser_state!(b.content); | ||
|
@@ -1514,6 +1539,7 @@ fn read_video_sample_entry<T: Read>(src: &mut BMFFBox<T>, track: &mut Track) -> | |
width: width, | ||
height: height, | ||
codec_specific: codec_specific, | ||
protection_info: protection_info, | ||
})) | ||
.ok_or_else(|| Error::InvalidData("malformed video sample entry")) | ||
} | ||
|
@@ -1537,14 +1563,6 @@ fn read_qt_wave_atom<T: Read>(src: &mut BMFFBox<T>) -> Result<ES_Descriptor> { | |
/// Parse an audio description inside an stsd box. | ||
fn read_audio_sample_entry<T: Read>(src: &mut BMFFBox<T>, track: &mut Track) -> Result<SampleEntry> { | ||
let name = src.get_header().name; | ||
track.codec_type = match name { | ||
// TODO(kinetik): stagefright inspects ESDS to detect MP3 (audio/mpeg). | ||
BoxType::MP4AudioSampleEntry => CodecType::AAC, | ||
BoxType::FLACSampleEntry => CodecType::FLAC, | ||
BoxType::OpusSampleEntry => CodecType::Opus, | ||
BoxType::ProtectedAudioSampleEntry => CodecType::EncryptedAudio, | ||
_ => CodecType::Unknown, | ||
}; | ||
|
||
// Skip uninteresting fields. | ||
skip(src, 6)?; | ||
|
@@ -1580,6 +1598,7 @@ fn read_audio_sample_entry<T: Read>(src: &mut BMFFBox<T>, track: &mut Track) -> | |
|
||
// Skip chan/etc. for now. | ||
let mut codec_specific = None; | ||
let mut protection_info = None; | ||
let mut iter = src.box_iter(); | ||
while let Some(mut b) = iter.next_box()? { | ||
match b.head.name { | ||
|
@@ -1617,6 +1636,15 @@ fn read_audio_sample_entry<T: Read>(src: &mut BMFFBox<T>, track: &mut Track) -> | |
track.codec_type = qt_esds.audio_codec; | ||
codec_specific = Some(AudioCodecSpecific::ES_Descriptor(qt_esds)); | ||
} | ||
BoxType::ProtectionSchemeInformationBox => { | ||
if name != BoxType::ProtectedAudioSampleEntry { | ||
return Err(Error::InvalidData("malformed audio sample entry")); | ||
} | ||
let sinf = read_sinf(&mut b)?; | ||
log!("{:?} (sinf)", sinf); | ||
track.codec_type = CodecType::EncryptedAudio; | ||
protection_info = Some(sinf); | ||
} | ||
_ => skip_box_content(&mut b)?, | ||
} | ||
check_parser_state!(b.content); | ||
|
@@ -1629,6 +1657,7 @@ fn read_audio_sample_entry<T: Read>(src: &mut BMFFBox<T>, track: &mut Track) -> | |
samplesize: samplesize, | ||
samplerate: samplerate, | ||
codec_specific: codec_specific, | ||
protection_info: protection_info, | ||
})) | ||
.ok_or_else(|| Error::InvalidData("malformed audio sample entry")) | ||
} | ||
|
@@ -1682,6 +1711,69 @@ fn read_stsd<T: Read>(src: &mut BMFFBox<T>, track: &mut Track) -> Result<SampleD | |
}) | ||
} | ||
|
||
fn read_sinf<T: Read>(src: &mut BMFFBox<T>) -> Result<ProtectionSchemeInfoBox> { | ||
let mut sinf = ProtectionSchemeInfoBox::default(); | ||
|
||
let mut has_frma_schi_boxes = (false, false); | ||
let mut iter = src.box_iter(); | ||
while let Some(mut b) = iter.next_box()? { | ||
match b.head.name { | ||
BoxType::OriginalFormatBox => { | ||
let frma = read_frma(&mut b)?; | ||
sinf.code_name = frma; | ||
has_frma_schi_boxes.0 = true; | ||
}, | ||
BoxType::SchemeInformationBox => { | ||
// We only need tenc box in schi box so far. | ||
let schi_tenc = read_schi(&mut b)?; | ||
sinf.tenc = schi_tenc; | ||
has_frma_schi_boxes.1 = true | ||
}, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do we depend on the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. fixed. |
||
_ => skip_box_content(&mut b)?, | ||
} | ||
check_parser_state!(b.content); | ||
} | ||
|
||
if has_frma_schi_boxes != (true, true) { | ||
return Err(Error::InvalidData("malformat sinf box")); | ||
} | ||
|
||
Ok(sinf) | ||
} | ||
|
||
fn read_schi<T: Read>(src: &mut BMFFBox<T>) -> Result<TrackEncryptionBox> { | ||
let mut iter = src.box_iter(); | ||
while let Some(mut b) = iter.next_box()? { | ||
match b.head.name { | ||
BoxType::TrackEncryptionBox => { | ||
return read_tenc(&mut b); | ||
}, | ||
_ => skip_box_content(&mut b)?, | ||
} | ||
} | ||
|
||
Err(Error::InvalidData("malformed schi box")) | ||
} | ||
|
||
fn read_tenc<T: Read>(src: &mut BMFFBox<T>) -> Result<TrackEncryptionBox> { | ||
let (_, _) = read_fullbox_extra(src)?; | ||
|
||
let default_is_encrypted = be_u24(src)?; | ||
let default_iv_size = src.read_u8()?; | ||
let default_kid = read_buf(src, 16)?; | ||
|
||
Ok(TrackEncryptionBox { | ||
is_encrypted: default_is_encrypted, | ||
iv_size: default_iv_size, | ||
kid: default_kid, | ||
}) | ||
} | ||
|
||
fn read_frma<T: Read>(src: &mut BMFFBox<T>) -> Result<String> { | ||
let code_name = read_buf(src, 4)?; | ||
String::from_utf8(code_name).map_err(From::from) | ||
} | ||
|
||
/// Skip a number of bytes that we don't care to parse. | ||
fn skip<T: Read>(src: &mut T, mut bytes: usize) -> Result<()> { | ||
const BUF_SIZE: usize = 64 * 1024; | ||
|
Binary file not shown.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't have the
cenc
spec, but 14496-12 says theOriginalFormatBox
is required. Can we reject streams without one here? We don't seem to check later whether this is what we expect.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed.