Tidy Repacketizer interface and add more tests

The combine() method can be used to avoid manually managing a
RepacketizerState in the simplest use case, and cat_move now simply
calls cat internally, in a way that is easier to verify the safety of.
This commit is contained in:
Tad Hardesty
2016-02-25 18:02:19 -06:00
parent 3c6ce567f6
commit 6b1228288a
2 changed files with 43 additions and 22 deletions
+23 -10
View File
@@ -399,6 +399,15 @@ impl Repacketizer {
} }
} }
/// Shortcut to combine several smaller packets into one larger one.
pub fn combine(&mut self, input: &[&[u8]], output: &mut [u8]) -> Result<usize> {
let mut state = self.begin();
for &packet in input {
try!(state.cat(packet));
}
state.out(output)
}
/// Begin using the repacketizer. /// Begin using the repacketizer.
pub fn begin<'rp, 'buf>(&'rp mut self) -> RepacketizerState<'rp, 'buf> { pub fn begin<'rp, 'buf>(&'rp mut self) -> RepacketizerState<'rp, 'buf> {
unsafe { ffi::opus_repacketizer_init(self.ptr); } unsafe { ffi::opus_repacketizer_init(self.ptr); }
@@ -412,6 +421,12 @@ impl Drop for Repacketizer {
} }
} }
// To understand why these lifetime bounds are needed, imagine that the
// repacketizer keeps an internal Vec<&'buf [u8]>, which is added to by cat()
// and accessed by get_nb_frames(), out(), and out_range(). To prove that these
// lifetime bounds are correct, a dummy implementation with the same signatures
// but a real Vec<&'buf [u8]> rather than unsafe blocks may be substituted.
/// An in-progress repacketization. /// An in-progress repacketization.
pub struct RepacketizerState<'rp, 'buf> { pub struct RepacketizerState<'rp, 'buf> {
rp: &'rp mut Repacketizer, rp: &'rp mut Repacketizer,
@@ -421,19 +436,17 @@ pub struct RepacketizerState<'rp, 'buf> {
impl<'rp, 'buf> RepacketizerState<'rp, 'buf> { impl<'rp, 'buf> RepacketizerState<'rp, 'buf> {
/// Add a packet to the current repacketizer state. /// Add a packet to the current repacketizer state.
pub fn cat(&mut self, packet: &'buf [u8]) -> Result<()> { pub fn cat(&mut self, packet: &'buf [u8]) -> Result<()> {
unsafe { self.cat_priv(packet) } let result = unsafe { ffi::opus_repacketizer_cat(self.rp.ptr,
packet.as_ptr(), packet.len() as c_int) };
check("opus_repacketizer_cat", result)
} }
/// Add a packet to the current repacketizer state, moving it. /// Add a packet to the current repacketizer state, moving it.
pub fn cat_move<'b2>(mut self, packet: &'b2 [u8]) -> Result<RepacketizerState<'rp, 'b2>> where 'buf: 'b2 { #[inline]
try!(unsafe { self.cat_priv(packet) }); pub fn cat_move<'b2>(self, packet: &'b2 [u8]) -> Result<RepacketizerState<'rp, 'b2>> where 'buf: 'b2 {
Ok(self) let mut shorter = self;
} try!(shorter.cat(packet));
Ok(shorter)
unsafe fn cat_priv(&mut self, packet: &[u8]) -> Result<()> {
let result = ffi::opus_repacketizer_cat(self.rp.ptr,
packet.as_ptr(), packet.len() as c_int);
check("opus_repacketizer_cat", result)
} }
/// Get the total number of frames contained in packet data submitted so /// Get the total number of frames contained in packet data submitted so
+20 -12
View File
@@ -68,30 +68,38 @@ fn encode_bad_buffer() {
#[test] #[test]
fn repacketizer() { fn repacketizer() {
let mut rp = opus::Repacketizer::new().unwrap(); let mut rp = opus::Repacketizer::new().unwrap();
let mut out = [0; 256];
for _ in 0..2 { for _ in 0..2 {
let packets = &[ let packet1 = [249, 255, 254, 255, 254];
&[249, 255, 254, 255, 254][..], let packet2 = [248, 255, 254];
&[248, 255, 254][..],
];
let mut state = rp.begin(); let mut state = rp.begin();
for &packet in packets { state.cat(&packet1).unwrap();
state.cat(packet).unwrap(); state.cat(&packet2).unwrap();
}
let mut out = [0; 256];
let len = state.out(&mut out).unwrap(); let len = state.out(&mut out).unwrap();
assert_eq!(&out[..len], &[251, 3, 255, 254, 255, 254, 255, 254]); assert_eq!(&out[..len], &[251, 3, 255, 254, 255, 254, 255, 254]);
} }
for _ in 0..2 {
{
let packet = [248, 255, 254]; let packet = [248, 255, 254];
let state = rp.begin().cat_move(&packet).unwrap(); let state = rp.begin().cat_move(&packet).unwrap();
let packet = [249, 255, 254, 255, 254]; let packet = [249, 255, 254, 255, 254];
let state = state.cat_move(&packet).unwrap(); let state = state.cat_move(&packet).unwrap();
let mut out = [0; 256];
let len = {state}.out(&mut out).unwrap(); let len = {state}.out(&mut out).unwrap();
assert_eq!(&out[..len], &[251, 3, 255, 254, 255, 254, 255, 254]); assert_eq!(&out[..len], &[251, 3, 255, 254, 255, 254, 255, 254]);
} }
for _ in 0..2 {
let len = rp.combine(&[
&[249, 255, 254, 255, 254],
&[248, 255, 254],
], &mut out).unwrap();
assert_eq!(&out[..len], &[251, 3, 255, 254, 255, 254, 255, 254]);
}
for _ in 0..2 {
let len = rp.begin()
.cat_move(&[248, 255, 254]).unwrap()
.cat_move(&[248, 71, 71]).unwrap()
.out(&mut out).unwrap();
assert_eq!(&out[..len], &[249, 255, 254, 71, 71]);
}
} }