--- a/media/libstagefright/binding/include/mp4parse.h
+++ b/media/libstagefright/binding/include/mp4parse.h
@@ -43,26 +43,30 @@ typedef enum mp4parse_codec {
typedef struct mp4parse_track_info {
mp4parse_track_type track_type;
mp4parse_codec codec;
uint32_t track_id;
uint64_t duration;
int64_t media_time;
} mp4parse_track_info;
-typedef struct mp4parse_codec_specific_config {
+typedef struct mp4parse_byte_data {
uint32_t length;
uint8_t const* data;
-} mp4parse_codec_specific_config;
+} mp4parse_byte_data;
+
+typedef struct mp4parse_pssh_info {
+ mp4parse_byte_data data;
+} mp4parse_pssh_info;
typedef struct mp4parse_track_audio_info {
uint16_t channels;
uint16_t bit_depth;
uint32_t sample_rate;
- mp4parse_codec_specific_config codec_specific_config;
+ mp4parse_byte_data codec_specific_config;
} mp4parse_track_audio_info;
typedef struct mp4parse_track_video_info {
uint32_t display_width;
uint32_t display_height;
uint16_t image_width;
uint16_t image_height;
} mp4parse_track_video_info;
@@ -94,20 +98,30 @@ mp4parse_error mp4parse_get_track_count(
mp4parse_error mp4parse_get_track_info(mp4parse_parser* parser, uint32_t track_index, mp4parse_track_info* info);
/// Fill the supplied `mp4parse_track_audio_info` with metadata for `track`.
mp4parse_error mp4parse_get_track_audio_info(mp4parse_parser* parser, uint32_t track_index, mp4parse_track_audio_info* info);
/// Fill the supplied `mp4parse_track_video_info` with metadata for `track`.
mp4parse_error mp4parse_get_track_video_info(mp4parse_parser* parser, uint32_t track_index, mp4parse_track_video_info* info);
+/// Fill the supplied `mp4parse_fragment_info` with metadata from fragmented file.
mp4parse_error mp4parse_get_fragment_info(mp4parse_parser* parser, mp4parse_fragment_info* info);
+/// A fragmented file needs mvex table and contains no data in stts, stsc, and stco boxes.
mp4parse_error mp4parse_is_fragmented(mp4parse_parser* parser, uint32_t track_id, uint8_t* fragmented);
+/// Get 'pssh' system id and 'pssh' box content for eme playback.
+///
+/// The data format in 'info' passing to gecko is:
+/// system_id
+/// pssh box size (in native endian)
+/// pssh box content (including header)
+mp4parse_error mp4parse_get_pssh_info(mp4parse_parser* parser, mp4parse_pssh_info* info);
+
#ifdef __cplusplus
}
#endif
#endif
--- a/media/libstagefright/binding/mp4parse-cargo.patch
+++ b/media/libstagefright/binding/mp4parse-cargo.patch
@@ -20,23 +20,24 @@ index ff9422c..814c4c6 100644
-
# Somewhat heavy-handed, but we want at least -Z force-overflow-checks=on.
[profile.release]
debug-assertions = true
diff --git a/media/libstagefright/binding/mp4parse_capi/Cargo.toml b/media/libstagefright/binding/mp4parse_capi/Cargo.toml
index aeeebc65..5c0836a 100644
--- a/media/libstagefright/binding/mp4parse_capi/Cargo.toml
+++ b/media/libstagefright/binding/mp4parse_capi/Cargo.toml
-@@ -18,17 +18,9 @@ exclude = [
+@@ -18,18 +18,10 @@ exclude = [
"*.mp4",
]
-build = "build.rs"
-
[dependencies]
+ byteorder = "0.5.0"
"mp4parse" = {version = "0.6.0", path = "../mp4parse"}
-[build-dependencies]
-rusty-cheddar = "0.3.2"
-
-[features]
-fuzz = ["mp4parse/fuzz"]
-
--- a/media/libstagefright/binding/mp4parse/src/boxes.rs
+++ b/media/libstagefright/binding/mp4parse/src/boxes.rs
@@ -18,45 +18,46 @@ macro_rules! box_database {
_ => UnknownBox(t),
}
}
}
}
}
box_database!(
- FileTypeBox 0x66747970, // "ftyp"
- MovieBox 0x6d6f6f76, // "moov"
- MovieHeaderBox 0x6d766864, // "mvhd"
- TrackBox 0x7472616b, // "trak"
- TrackHeaderBox 0x746b6864, // "tkhd"
- EditBox 0x65647473, // "edts"
- MediaBox 0x6d646961, // "mdia"
- EditListBox 0x656c7374, // "elst"
- MediaHeaderBox 0x6d646864, // "mdhd"
- HandlerBox 0x68646c72, // "hdlr"
- MediaInformationBox 0x6d696e66, // "minf"
- SampleTableBox 0x7374626c, // "stbl"
- SampleDescriptionBox 0x73747364, // "stsd"
- TimeToSampleBox 0x73747473, // "stts"
- SampleToChunkBox 0x73747363, // "stsc"
- SampleSizeBox 0x7374737a, // "stsz"
- ChunkOffsetBox 0x7374636f, // "stco"
- ChunkLargeOffsetBox 0x636f3634, // "co64"
- SyncSampleBox 0x73747373, // "stss"
- AVCSampleEntry 0x61766331, // "avc1"
- AVC3SampleEntry 0x61766333, // "avc3" - Need to check official name in spec.
- AVCConfigurationBox 0x61766343, // "avcC"
- MP4AudioSampleEntry 0x6d703461, // "mp4a"
- ESDBox 0x65736473, // "esds"
- VP8SampleEntry 0x76703038, // "vp08"
- VP9SampleEntry 0x76703039, // "vp09"
- VPCodecConfigurationBox 0x76706343, // "vpcC"
- FLACSampleEntry 0x664c6143, // "fLaC"
- FLACSpecificBox 0x64664c61, // "dfLa"
- OpusSampleEntry 0x4f707573, // "Opus"
- OpusSpecificBox 0x644f7073, // "dOps"
- ProtectedVisualSampleEntry 0x656e6376, // "encv" - Need to check official name in spec.
- ProtectedAudioSampleEntry 0x656e6361, // "enca" - Need to check official name in spec.
- MovieExtendsBox 0x6d766578, // "mvex"
- MovieExtendsHeaderBox 0x6d656864, // "mehd"
- QTWaveAtom 0x77617665, // "wave" - quicktime atom
+ FileTypeBox 0x66747970, // "ftyp"
+ MovieBox 0x6d6f6f76, // "moov"
+ MovieHeaderBox 0x6d766864, // "mvhd"
+ TrackBox 0x7472616b, // "trak"
+ TrackHeaderBox 0x746b6864, // "tkhd"
+ EditBox 0x65647473, // "edts"
+ MediaBox 0x6d646961, // "mdia"
+ EditListBox 0x656c7374, // "elst"
+ MediaHeaderBox 0x6d646864, // "mdhd"
+ HandlerBox 0x68646c72, // "hdlr"
+ MediaInformationBox 0x6d696e66, // "minf"
+ SampleTableBox 0x7374626c, // "stbl"
+ SampleDescriptionBox 0x73747364, // "stsd"
+ TimeToSampleBox 0x73747473, // "stts"
+ SampleToChunkBox 0x73747363, // "stsc"
+ SampleSizeBox 0x7374737a, // "stsz"
+ ChunkOffsetBox 0x7374636f, // "stco"
+ ChunkLargeOffsetBox 0x636f3634, // "co64"
+ SyncSampleBox 0x73747373, // "stss"
+ AVCSampleEntry 0x61766331, // "avc1"
+ AVC3SampleEntry 0x61766333, // "avc3" - Need to check official name in spec.
+ AVCConfigurationBox 0x61766343, // "avcC"
+ MP4AudioSampleEntry 0x6d703461, // "mp4a"
+ ESDBox 0x65736473, // "esds"
+ VP8SampleEntry 0x76703038, // "vp08"
+ VP9SampleEntry 0x76703039, // "vp09"
+ VPCodecConfigurationBox 0x76706343, // "vpcC"
+ FLACSampleEntry 0x664c6143, // "fLaC"
+ FLACSpecificBox 0x64664c61, // "dfLa"
+ OpusSampleEntry 0x4f707573, // "Opus"
+ OpusSpecificBox 0x644f7073, // "dOps"
+ ProtectedVisualSampleEntry 0x656e6376, // "encv" - Need to check official name in spec.
+ ProtectedAudioSampleEntry 0x656e6361, // "enca" - Need to check official name in spec.
+ MovieExtendsBox 0x6d766578, // "mvex"
+ MovieExtendsHeaderBox 0x6d656864, // "mehd"
+ QTWaveAtom 0x77617665, // "wave" - quicktime atom
+ ProtectionSystemSpecificHeaderBox 0x70737368, // "pssh"
);
--- a/media/libstagefright/binding/mp4parse/src/lib.rs
+++ b/media/libstagefright/binding/mp4parse/src/lib.rs
@@ -4,17 +4,17 @@
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
#![cfg_attr(feature = "fuzz", feature(plugin))]
#![cfg_attr(feature = "fuzz", plugin(afl_plugin))]
#[cfg(feature = "fuzz")]
extern crate afl;
extern crate byteorder;
-use byteorder::ReadBytesExt;
+use byteorder::{ReadBytesExt, WriteBytesExt};
use std::io::{Read, Take};
use std::io::Cursor;
use std::cmp;
mod boxes;
use boxes::BoxType;
// Unit tests.
@@ -289,23 +289,36 @@ pub struct OpusSpecificBox {
channel_mapping_table: Option<ChannelMappingTable>,
}
#[derive(Debug)]
pub struct MovieExtendsBox {
pub fragment_duration: Option<MediaScaledTime>,
}
+pub type ByteData = Vec<u8>;
+
+#[derive(Debug, Default)]
+pub struct ProtectionSystemSpecificHeaderBox {
+ pub system_id: ByteData,
+ pub kid: Vec<ByteData>,
+ pub data: ByteData,
+
+ // The entire pssh box (include header) required by Gecko.
+ pub box_content: ByteData,
+}
+
/// Internal data structures.
#[derive(Debug, Default)]
pub struct MediaContext {
pub timescale: Option<MediaTimeScale>,
/// Tracks found in the file.
pub tracks: Vec<Track>,
pub mvex: Option<MovieExtendsBox>,
+ pub psshs: Vec<ProtectionSystemSpecificHeaderBox>
}
impl MediaContext {
pub fn new() -> MediaContext {
Default::default()
}
}
@@ -596,23 +609,67 @@ fn read_moov<T: Read>(f: &mut BMFFBox<T>
try!(read_trak(&mut b, &mut track));
context.tracks.push(track);
}
BoxType::MovieExtendsBox => {
let mvex = try!(read_mvex(&mut b));
log!("{:?}", mvex);
context.mvex = Some(mvex);
}
+ BoxType::ProtectionSystemSpecificHeaderBox => {
+ let pssh = try!(read_pssh(&mut b));
+ log!("{:?}", pssh);
+ context.psshs.push(pssh);
+ }
_ => try!(skip_box_content(&mut b)),
};
check_parser_state!(b.content);
}
Ok(())
}
+fn read_pssh<T: Read>(src: &mut BMFFBox<T>) -> Result<ProtectionSystemSpecificHeaderBox> {
+ let mut box_content = Vec::with_capacity(src.head.size as usize);
+ try!(src.read_to_end(&mut box_content));
+
+ let (system_id, kid, data) = {
+ let pssh = &mut Cursor::new(box_content.as_slice());
+
+ let (version, _) = try!(read_fullbox_extra(pssh));
+
+ let system_id = try!(read_buf(pssh, 16));
+
+ let mut kid: Vec<ByteData> = Vec::new();
+ if version > 0 {
+ let count = try!(be_i32(pssh));
+ for _ in 0..count {
+ let item = try!(read_buf(pssh, 16));
+ kid.push(item);
+ }
+ }
+
+ let data_size = try!(be_i32(pssh)) as usize;
+ let data = try!(read_buf(pssh, data_size));
+
+ (system_id, kid, data)
+ };
+
+ let mut pssh_box = Vec::new();
+ try!(write_be_u32(&mut pssh_box, src.head.size as u32));
+ pssh_box.append(&mut b"pssh".to_vec());
+ pssh_box.append(&mut box_content);
+
+ Ok(ProtectionSystemSpecificHeaderBox {
+ system_id: system_id,
+ kid: kid,
+ data: data,
+ box_content: pssh_box,
+ })
+}
+
fn read_mvex<T: Read>(src: &mut BMFFBox<T>) -> Result<MovieExtendsBox> {
let mut iter = src.box_iter();
let mut fragment_duration = None;
while let Some(mut b) = try!(iter.next_box()) {
match b.head.name {
BoxType::MovieExtendsHeaderBox => {
let duration = try!(read_mehd(&mut b));
fragment_duration = Some(duration);
@@ -1697,8 +1754,12 @@ fn be_u24<T: ReadBytesExt>(src: &mut T)
fn be_u32<T: ReadBytesExt>(src: &mut T) -> Result<u32> {
src.read_u32::<byteorder::BigEndian>().map_err(From::from)
}
fn be_u64<T: ReadBytesExt>(src: &mut T) -> Result<u64> {
src.read_u64::<byteorder::BigEndian>().map_err(From::from)
}
+
+fn write_be_u32<T: WriteBytesExt>(des: &mut T, num: u32) -> Result<()> {
+ des.write_u32::<byteorder::BigEndian>(num).map_err(From::from)
+}
--- a/media/libstagefright/binding/mp4parse/tests/public.rs
+++ b/media/libstagefright/binding/mp4parse/tests/public.rs
@@ -90,8 +90,40 @@ fn public_api() {
}, "ES");
assert!(a.samplesize > 0);
assert!(a.samplerate > 0);
}
Some(mp4::SampleEntry::Unknown) | None => {}
}
}
}
+
+#[test]
+fn public_cenc() {
+ let mut fd = File::open("tests/bipbop_480wp_1001kbps-cenc-video-key1-init.mp4").expect("Unknown file");
+ let mut buf = Vec::new();
+ fd.read_to_end(&mut buf).expect("File error");
+
+ let mut c = Cursor::new(&buf);
+ let mut context = mp4::MediaContext::new();
+ mp4::read_mp4(&mut c, &mut context).expect("read_mp4 failed");
+ for track in context.tracks {
+ assert_eq!(track.codec_type, mp4::CodecType::EncryptedVideo);
+ }
+
+ let system_id = vec![0x10, 0x77, 0xef, 0xec, 0xc0, 0xb2, 0x4d, 0x02, 0xac, 0xe3, 0x3c, 0x1e, 0x52, 0xe2, 0xfb, 0x4b];
+
+ let kid = vec![0x7e, 0x57, 0x1d, 0x03, 0x7e, 0x57, 0x1d, 0x03, 0x7e, 0x57, 0x1d, 0x03, 0x7e, 0x57, 0x1d, 0x11];
+
+ let pssh_box = vec![0x00, 0x00, 0x00, 0x34, 0x70, 0x73, 0x73, 0x68, 0x01, 0x00, 0x00, 0x00, 0x10, 0x77,
+ 0xef, 0xec, 0xc0, 0xb2, 0x4d, 0x02, 0xac, 0xe3, 0x3c, 0x1e, 0x52, 0xe2, 0xfb, 0x4b, 0x00, 0x00,
+ 0x00, 0x01, 0x7e, 0x57, 0x1d, 0x03, 0x7e, 0x57, 0x1d, 0x03, 0x7e, 0x57, 0x1d, 0x03, 0x7e, 0x57,
+ 0x1d, 0x11, 0x00, 0x00, 0x00, 0x00];
+
+ for pssh in context.psshs {
+ assert_eq!(pssh.system_id, system_id);
+ for kid_id in pssh.kid {
+ assert_eq!(kid_id, kid);
+ }
+ assert_eq!(pssh.data.len(), 0);
+ assert_eq!(pssh.box_content, pssh_box);
+ }
+}
--- a/media/libstagefright/binding/mp4parse_capi/Cargo.toml
+++ b/media/libstagefright/binding/mp4parse_capi/Cargo.toml
@@ -14,13 +14,14 @@ license = "MPL-2.0"
repository = "https://github.com/mozilla/mp4parse-rust"
# Avoid complaints about trying to package test files.
exclude = [
"*.mp4",
]
[dependencies]
+byteorder = "0.5.0"
"mp4parse" = {version = "0.6.0", path = "../mp4parse"}
# Somewhat heavy-handed, but we want at least -Z force-overflow-checks=on.
[profile.release]
debug-assertions = true
--- a/media/libstagefright/binding/mp4parse_capi/src/lib.rs
+++ b/media/libstagefright/binding/mp4parse_capi/src/lib.rs
@@ -30,19 +30,21 @@
//! }
//! ```
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
extern crate mp4parse;
+extern crate byteorder;
use std::io::Read;
use std::collections::HashMap;
+use byteorder::WriteBytesExt;
// Symbols we need from our rust api.
use mp4parse::MediaContext;
use mp4parse::TrackType;
use mp4parse::read_mp4;
use mp4parse::Error;
use mp4parse::SampleEntry;
use mp4parse::AudioCodecSpecific;
@@ -98,40 +100,53 @@ pub struct mp4parse_track_info {
pub codec: mp4parse_codec,
pub track_id: u32,
pub duration: u64,
pub media_time: i64, // wants to be u64? understand how elst adjustment works
// TODO(kinetik): include crypto guff
}
#[repr(C)]
-pub struct mp4parse_codec_specific_config {
+pub struct mp4parse_byte_data {
pub length: u32,
pub data: *const u8,
}
-impl Default for mp4parse_codec_specific_config {
+impl Default for mp4parse_byte_data {
fn default() -> Self {
- mp4parse_codec_specific_config {
+ mp4parse_byte_data {
length: 0,
data: std::ptr::null_mut(),
}
}
}
+impl mp4parse_byte_data {
+ fn set_data(&mut self, data: &Vec<u8>) {
+ self.length = data.len() as u32;
+ self.data = data.as_ptr();
+ }
+}
+
+#[repr(C)]
+#[derive(Default)]
+pub struct mp4parse_pssh_info {
+ pub data: mp4parse_byte_data,
+}
+
#[derive(Default)]
#[repr(C)]
pub struct mp4parse_track_audio_info {
pub channels: u16,
pub bit_depth: u16,
pub sample_rate: u32,
// TODO(kinetik):
// int32_t profile;
// int32_t extended_profile; // check types
- codec_specific_config: mp4parse_codec_specific_config,
+ codec_specific_config: mp4parse_byte_data,
}
#[repr(C)]
pub struct mp4parse_track_video_info {
pub display_width: u32,
pub display_height: u32,
pub image_width: u16,
pub image_height: u16,
@@ -149,16 +164,17 @@ pub struct mp4parse_fragment_info {
// Even though mp4parse_parser is opaque to C, rusty-cheddar won't let us
// use more than one member, so we introduce *another* wrapper.
struct Wrap {
context: MediaContext,
io: mp4parse_io,
poisoned: bool,
opus_header: HashMap<u32, Vec<u8>>,
+ pssh_data: Vec<u8>,
}
#[repr(C)]
#[allow(non_camel_case_types)]
pub struct mp4parse_parser(Wrap);
impl mp4parse_parser {
fn context(&self) -> &MediaContext {
@@ -179,16 +195,20 @@ impl mp4parse_parser {
fn set_poisoned(&mut self, poisoned: bool) {
self.0.poisoned = poisoned;
}
fn opus_header_mut(&mut self) -> &mut HashMap<u32, Vec<u8>> {
&mut self.0.opus_header
}
+
+ fn pssh_data_mut(&mut self) -> &mut Vec<u8> {
+ &mut self.0.pssh_data
+ }
}
#[repr(C)]
#[derive(Clone)]
pub struct mp4parse_io {
pub read: extern fn(buffer: *mut u8, size: usize, userdata: *mut std::os::raw::c_void) -> isize,
pub userdata: *mut std::os::raw::c_void,
}
@@ -223,16 +243,17 @@ pub unsafe extern fn mp4parse_new(io: *c
if ((*io).read as *mut std::os::raw::c_void).is_null() {
return std::ptr::null_mut();
}
let parser = Box::new(mp4parse_parser(Wrap {
context: MediaContext::new(),
io: (*io).clone(),
poisoned: false,
opus_header: HashMap::new(),
+ pssh_data: Vec::new(),
}));
Box::into_raw(parser)
}
/// Free an `mp4parse_parser*` allocated by `mp4parse_new()`.
#[no_mangle]
pub unsafe extern fn mp4parse_free(parser: *mut mp4parse_parser) {
assert!(!parser.is_null());
@@ -524,16 +545,17 @@ pub unsafe extern fn mp4parse_get_track_
return MP4PARSE_ERROR_INVALID;
}
(*info).image_width = video.width;
(*info).image_height = video.height;
MP4PARSE_OK
}
+/// Fill the supplied `mp4parse_fragment_info` with metadata from fragmented file.
#[no_mangle]
pub unsafe extern fn mp4parse_get_fragment_info(parser: *mut mp4parse_parser, info: *mut mp4parse_fragment_info) -> mp4parse_error {
if parser.is_null() || info.is_null() || (*parser).poisoned() {
return MP4PARSE_ERROR_BADARG;
}
let context = (*parser).context();
let info: &mut mp4parse_fragment_info = &mut *info;
@@ -550,17 +572,17 @@ pub unsafe extern fn mp4parse_get_fragme
Some(time_us) => time_us as u64,
None => return MP4PARSE_ERROR_INVALID,
}
}
MP4PARSE_OK
}
-// A fragmented file needs mvex table and contains no data in stts, stsc, and stco boxes.
+/// A fragmented file needs mvex table and contains no data in stts, stsc, and stco boxes.
#[no_mangle]
pub unsafe extern fn mp4parse_is_fragmented(parser: *mut mp4parse_parser, track_id: u32, fragmented: *mut u8) -> mp4parse_error {
if parser.is_null() || (*parser).poisoned() {
return MP4PARSE_ERROR_BADARG;
}
let context = (*parser).context_mut();
let tracks = &context.tracks;
@@ -576,16 +598,51 @@ pub unsafe extern fn mp4parse_is_fragmen
Some(track) if track.empty_sample_boxes.all_empty() => (*fragmented) = true as u8,
Some(_) => {},
None => return MP4PARSE_ERROR_BADARG,
}
MP4PARSE_OK
}
+/// Get 'pssh' system id and 'pssh' box content for eme playback.
+///
+/// The data format in 'info' passing to gecko is:
+/// system_id
+/// pssh box size (in native endian)
+/// pssh box content (including header)
+#[no_mangle]
+pub unsafe extern fn mp4parse_get_pssh_info(parser: *mut mp4parse_parser, info: *mut mp4parse_pssh_info) -> mp4parse_error {
+ if parser.is_null() || info.is_null() || (*parser).poisoned() {
+ return MP4PARSE_ERROR_BADARG;
+ }
+
+ let context = (*parser).context_mut();
+ let pssh_data = (*parser).pssh_data_mut();
+ let info: &mut mp4parse_pssh_info = &mut *info;
+
+ pssh_data.clear();
+ for pssh in &context.psshs {
+ let mut data_len = Vec::new();
+ match data_len.write_u32::<byteorder::NativeEndian>(pssh.box_content.len() as u32) {
+ Err(_) => {
+ return MP4PARSE_ERROR_IO;
+ },
+ _ => (),
+ }
+ pssh_data.extend_from_slice(pssh.system_id.as_slice());
+ pssh_data.extend_from_slice(data_len.as_slice());
+ pssh_data.extend_from_slice(pssh.box_content.as_slice());
+ }
+
+ info.data.set_data(&pssh_data);
+
+ MP4PARSE_OK
+}
+
#[cfg(test)]
extern fn panic_read(_: *mut u8, _: usize, _: *mut std::os::raw::c_void) -> isize {
panic!("panic_read shouldn't be called in these tests");
}
#[cfg(test)]
extern fn error_read(_: *mut u8, _: usize, _: *mut std::os::raw::c_void) -> isize {
-1
--- a/toolkit/library/gtest/rust/Cargo.lock
+++ b/toolkit/library/gtest/rust/Cargo.lock
@@ -51,16 +51,17 @@ dependencies = [
[[package]]
name = "mp4parse-gtest"
version = "0.1.0"
[[package]]
name = "mp4parse_capi"
version = "0.6.0"
dependencies = [
+ "byteorder 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)",
"mp4parse 0.6.0",
]
[[package]]
name = "nsstring"
version = "0.1.0"
[[package]]
--- a/toolkit/library/rust/Cargo.lock
+++ b/toolkit/library/rust/Cargo.lock
@@ -45,16 +45,17 @@ version = "0.6.0"
dependencies = [
"byteorder 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "mp4parse_capi"
version = "0.6.0"
dependencies = [
+ "byteorder 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)",
"mp4parse 0.6.0",
]
[[package]]
name = "nsstring"
version = "0.1.0"
[[package]]