зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1374194 - update rust mp4 parser. r=kinetik
MozReview-Commit-ID: BcFrpt0E4Zn --HG-- extra : rebase_source : aa833169c8c3dfb1a01b54e9ccdda9170de8f407
This commit is contained in:
Родитель
28a8ae8f7a
Коммит
aa3bc119ce
|
@ -39,6 +39,9 @@ typedef enum mp4parse_codec {
|
|||
mp4parse_codec_VP9,
|
||||
mp4parse_codec_MP3,
|
||||
mp4parse_codec_MP4V,
|
||||
mp4parse_codec_JPEG,
|
||||
mp4parse_codec_AC3,
|
||||
mp4parse_codec_EC3,
|
||||
} mp4parse_codec;
|
||||
|
||||
typedef struct mp4parse_track_info {
|
||||
|
|
|
@ -137,4 +137,9 @@ box_database!(
|
|||
OriginalFormatBox 0x66726d61, // "frma"
|
||||
MP3AudioSampleEntry 0x2e6d7033, // ".mp3" - from F4V.
|
||||
CompositionOffsetBox 0x63747473, // "ctts"
|
||||
JPEGAtom 0x6a706567, // "jpeg" - QT JPEG
|
||||
AC3SampleEntry 0x61632d33, // "ac-3"
|
||||
EC3SampleEntry 0x65632d33, // "ec-3"
|
||||
AC3SpecificBox 0x64616333, // "dac3"
|
||||
EC3SpecificBox 0x64656333, // "dec3"
|
||||
);
|
||||
|
|
|
@ -267,6 +267,8 @@ pub enum AudioCodecSpecific {
|
|||
ES_Descriptor(ES_Descriptor),
|
||||
FLACSpecificBox(FLACSpecificBox),
|
||||
OpusSpecificBox(OpusSpecificBox),
|
||||
AC3SpecificBox,
|
||||
EC3SpecificBox,
|
||||
MP3,
|
||||
}
|
||||
|
||||
|
@ -285,6 +287,7 @@ pub enum VideoCodecSpecific {
|
|||
AVCConfig(Vec<u8>),
|
||||
VPxConfig(VPxConfigBox),
|
||||
ESDSConfig(Vec<u8>),
|
||||
JPEG,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
|
@ -413,6 +416,9 @@ pub enum CodecType {
|
|||
VP8,
|
||||
EncryptedVideo,
|
||||
EncryptedAudio,
|
||||
JPEG, // QT JPEG atom
|
||||
AC3, // Digital Audio Compression (AC-3, Enhanced AC-3) Standard, ETSI TS 102 366.
|
||||
EC3, // Digital Audio Compression (AC-3, Enhanced AC-3) Standard, ETSI TS 102 366.
|
||||
}
|
||||
|
||||
impl Default for CodecType {
|
||||
|
@ -1668,6 +1674,7 @@ fn read_video_sample_entry<T: Read>(src: &mut BMFFBox<T>) -> Result<(CodecType,
|
|||
BoxType::VP8SampleEntry => CodecType::VP8,
|
||||
BoxType::VP9SampleEntry => CodecType::VP9,
|
||||
BoxType::ProtectedVisualSampleEntry => CodecType::EncryptedVideo,
|
||||
BoxType::JPEGAtom => CodecType::JPEG,
|
||||
_ => CodecType::Unknown,
|
||||
};
|
||||
|
||||
|
@ -1686,7 +1693,11 @@ fn read_video_sample_entry<T: Read>(src: &mut BMFFBox<T>) -> Result<(CodecType,
|
|||
skip(src, 50)?;
|
||||
|
||||
// Skip clap/pasp/etc. for now.
|
||||
let mut codec_specific = None;
|
||||
let mut codec_specific = if name == BoxType::JPEGAtom {
|
||||
Some(VideoCodecSpecific::JPEG)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let mut protection_info = Vec::new();
|
||||
let mut iter = src.box_iter();
|
||||
while let Some(mut b) = iter.next_box()? {
|
||||
|
@ -1723,6 +1734,11 @@ fn read_video_sample_entry<T: Read>(src: &mut BMFFBox<T>) -> Result<(CodecType,
|
|||
let esds = read_buf(&mut b.content, esds_size as usize)?;
|
||||
codec_specific = Some(VideoCodecSpecific::ESDSConfig(esds));
|
||||
}
|
||||
BoxType::JPEGAtom => {
|
||||
if name != BoxType::JPEGAtom || codec_specific.is_some() {
|
||||
return Err(Error::InvalidData("malformed video sample entry"));
|
||||
}
|
||||
}
|
||||
BoxType::ProtectionSchemeInformationBox => {
|
||||
if name != BoxType::ProtectedVisualSampleEntry {
|
||||
return Err(Error::InvalidData("malformed video sample entry"));
|
||||
|
@ -1853,6 +1869,26 @@ fn read_audio_sample_entry<T: Read>(src: &mut BMFFBox<T>) -> Result<(CodecType,
|
|||
codec_type = CodecType::EncryptedAudio;
|
||||
protection_info.push(sinf);
|
||||
}
|
||||
BoxType::AC3SpecificBox => {
|
||||
if name != BoxType::AC3SampleEntry {
|
||||
return Err(Error::InvalidData("malformed AC3 sample entry"));
|
||||
}
|
||||
// TODO: AC3SpecificBox needs to be parsed for detail information.
|
||||
skip_box_remain(&mut b)?;
|
||||
log!("(ac3)");
|
||||
codec_type = CodecType::AC3;
|
||||
codec_specific = Some(AudioCodecSpecific::AC3SpecificBox);
|
||||
}
|
||||
BoxType::EC3SpecificBox => {
|
||||
if name != BoxType::EC3SpecificBox {
|
||||
return Err(Error::InvalidData("malformed EC3 sample entry"));
|
||||
}
|
||||
// TODO: EC3SpecificBox needs to be parsed for detail information.
|
||||
skip_box_remain(&mut b)?;
|
||||
log!("(ec3)");
|
||||
codec_type = CodecType::EC3;
|
||||
codec_specific = Some(AudioCodecSpecific::EC3SpecificBox);
|
||||
}
|
||||
_ => skip_box_content(&mut b)?,
|
||||
}
|
||||
check_parser_state!(b.content);
|
||||
|
|
|
@ -900,6 +900,31 @@ fn read_esds() {
|
|||
assert_eq!(es.decoder_specific_data, aac_dc_descriptor);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn read_ac3_sample_entry() {
|
||||
let ac3 =
|
||||
vec![
|
||||
0x00, 0x00, 0x00, 0x0b, 0x64, 0x61, 0x63, 0x33, 0x10, 0x11, 0x60
|
||||
];
|
||||
|
||||
let mut stream = make_box(BoxSize::Auto, b"ac-3", |s| {
|
||||
s.append_repeated(0, 6)
|
||||
.B16(1) // data_reference_count
|
||||
.B16(0)
|
||||
.append_repeated(0, 6)
|
||||
.B16(2)
|
||||
.B16(16)
|
||||
.append_repeated(0, 4)
|
||||
.B32(48000 << 16)
|
||||
.append_bytes(ac3.as_slice())
|
||||
});
|
||||
|
||||
let mut iter = super::BoxIter::new(&mut stream);
|
||||
let mut stream = iter.next_box().unwrap().unwrap();
|
||||
let (codec_type, _) = super::read_audio_sample_entry(&mut stream)
|
||||
.expect("fail to read ac3 atom");
|
||||
assert_eq!(codec_type, super::CodecType::AC3);
|
||||
}
|
||||
#[test]
|
||||
fn read_stsd_mp4v() {
|
||||
let mp4v =
|
||||
|
@ -1011,3 +1036,38 @@ fn max_table_limit() {
|
|||
_ => panic!("expected a different error result"),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn jpeg_video_sample_entry() {
|
||||
let jpeg = make_box(BoxSize::Auto, b"jpeg", |s| {
|
||||
s.append_repeated(0, 6)
|
||||
.B16(1)
|
||||
.append_repeated(0, 16)
|
||||
.B16(1024)
|
||||
.B16(1024)
|
||||
.append_repeated(0, 14)
|
||||
.append_repeated(0, 32)
|
||||
.append_repeated(0, 4)
|
||||
}).into_inner();
|
||||
let mut stream = make_fullbox(BoxSize::Auto, b"stsd", 0, |s| {
|
||||
s.B32(1)
|
||||
.append_bytes(jpeg.as_slice())
|
||||
});
|
||||
|
||||
let mut iter = super::BoxIter::new(&mut stream);
|
||||
let mut stream = iter.next_box().unwrap().unwrap();
|
||||
let mut track = super::Track::new(0);
|
||||
match super::read_stsd(&mut stream, &mut track) {
|
||||
Ok(sample_description) => {
|
||||
match sample_description.descriptions[0] {
|
||||
super::SampleEntry::Video(ref jpeg) => {
|
||||
assert_eq!(track.codec_type, super::CodecType::JPEG);
|
||||
assert_eq!(jpeg.height, 1024);
|
||||
assert_eq!(jpeg.width, 1024);
|
||||
} ,
|
||||
_ => {},
|
||||
}
|
||||
},
|
||||
_ => panic!("failed to parse a jpeg atom"),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -60,6 +60,9 @@ fn public_api() {
|
|||
assert!(!mp4v.is_empty());
|
||||
"MP4V"
|
||||
}
|
||||
mp4::VideoCodecSpecific::JPEG => {
|
||||
"JPEG"
|
||||
}
|
||||
}, "AVC");
|
||||
}
|
||||
Some(mp4::SampleEntry::Audio(a)) => {
|
||||
|
@ -99,6 +102,12 @@ fn public_api() {
|
|||
mp4::AudioCodecSpecific::MP3 => {
|
||||
"MP3"
|
||||
}
|
||||
mp4::AudioCodecSpecific::AC3SpecificBox => {
|
||||
"AC3"
|
||||
}
|
||||
mp4::AudioCodecSpecific::EC3SpecificBox => {
|
||||
"EC3"
|
||||
}
|
||||
}, "ES");
|
||||
assert!(a.samplesize > 0);
|
||||
assert!(a.samplerate > 0);
|
||||
|
|
|
@ -95,6 +95,9 @@ pub enum mp4parse_codec {
|
|||
VP9,
|
||||
MP3,
|
||||
MP4V,
|
||||
JPEG, // for QT JPEG atom in video track
|
||||
AC3,
|
||||
EC3,
|
||||
}
|
||||
|
||||
impl Default for mp4parse_codec {
|
||||
|
@ -428,6 +431,10 @@ pub unsafe extern fn mp4parse_get_track_info(parser: *mut mp4parse_parser, track
|
|||
mp4parse_codec::UNKNOWN,
|
||||
AudioCodecSpecific::MP3 =>
|
||||
mp4parse_codec::MP3,
|
||||
AudioCodecSpecific::AC3SpecificBox =>
|
||||
mp4parse_codec::AC3,
|
||||
AudioCodecSpecific::EC3SpecificBox =>
|
||||
mp4parse_codec::EC3,
|
||||
},
|
||||
Some(SampleEntry::Video(ref video)) => match video.codec_specific {
|
||||
VideoCodecSpecific::VPxConfig(_) =>
|
||||
|
@ -436,6 +443,8 @@ pub unsafe extern fn mp4parse_get_track_info(parser: *mut mp4parse_parser, track
|
|||
mp4parse_codec::AVC,
|
||||
VideoCodecSpecific::ESDSConfig(_) =>
|
||||
mp4parse_codec::MP4V,
|
||||
VideoCodecSpecific::JPEG =>
|
||||
mp4parse_codec::JPEG,
|
||||
},
|
||||
_ => mp4parse_codec::UNKNOWN,
|
||||
};
|
||||
|
@ -564,6 +573,8 @@ pub unsafe extern fn mp4parse_get_track_audio_info(parser: *mut mp4parse_parser,
|
|||
}
|
||||
}
|
||||
}
|
||||
AudioCodecSpecific::AC3SpecificBox => (),
|
||||
AudioCodecSpecific::EC3SpecificBox => (),
|
||||
AudioCodecSpecific::MP3 => (),
|
||||
}
|
||||
|
||||
|
@ -944,19 +955,9 @@ fn create_sample_table(track: &Track, track_offset_time: i64) -> Option<Vec<mp4p
|
|||
// ctts_offset is the current sample offset time.
|
||||
let ctts_offset = ctts_offset_iter.next_offset_time();
|
||||
|
||||
// ctts_offset could be negative but (decode_time + ctts_offset) should always be positive
|
||||
// value.
|
||||
let start_composition = track_time_to_us(decode_time + ctts_offset, timescale).and_then(|t| {
|
||||
if t < 0 { return None; }
|
||||
Some(t)
|
||||
});
|
||||
let start_composition = track_time_to_us(decode_time + ctts_offset, timescale);
|
||||
|
||||
// ctts_offset could be negative but (sum_delta + ctts_offset) should always be positive
|
||||
// value.
|
||||
let end_composition = track_time_to_us(sum_delta + ctts_offset, timescale).and_then(|t| {
|
||||
if t < 0 { return None; }
|
||||
Some(t)
|
||||
});
|
||||
let end_composition = track_time_to_us(sum_delta + ctts_offset, timescale);
|
||||
|
||||
let start_decode = track_time_to_us(decode_time, timescale);
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
# Script to update mp4parse-rust sources to latest upstream
|
||||
|
||||
# Default version.
|
||||
VER=5bff34a85f2c0b1f147798ea701f7b704e651ae8
|
||||
VER=ae58bb5063cde8018d51c1778a52392777ddb0d4
|
||||
|
||||
# Accept version or commit from the command line.
|
||||
if test -n "$1"; then
|
||||
|
|
Загрузка…
Ссылка в новой задаче