Bug 1374194 - update rust mp4 parser. r=kinetik

MozReview-Commit-ID: BcFrpt0E4Zn

--HG--
extra : rebase_source : aa833169c8c3dfb1a01b54e9ccdda9170de8f407
This commit is contained in:
Alfredo Yang 2017-07-03 11:09:36 +08:00
Родитель 28a8ae8f7a
Коммит aa3bc119ce
7 изменённых файлов: 128 добавлений и 14 удалений

Просмотреть файл

@ -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