mirror of
https://github.com/rustdesk/magnum-opus.git
synced 2026-10-27 14:30:08 +00:00
Add documentation
This commit is contained in:
1 parent
4d93aaad66
commit
1df6208ba8
1 file changed
+103
-8
+103
-8
@@ -1,3 +1,9 @@
|
|||||||
|
//! High-level bindings for libopus.
|
||||||
|
//!
|
||||||
|
//! Only brief descriptions are included here. For detailed information, consult
|
||||||
|
//! the [libopus documentation](https://opus-codec.org/docs/opus_api-1.1.2/).
|
||||||
|
#![warn(missing_docs)]
|
||||||
|
|
||||||
extern crate opus_sys as ffi;
|
extern crate opus_sys as ffi;
|
||||||
extern crate libc;
|
extern crate libc;
|
||||||
|
|
||||||
@@ -5,8 +11,6 @@ use std::ffi::CStr;
|
|||||||
|
|
||||||
use libc::{c_int};
|
use libc::{c_int};
|
||||||
|
|
||||||
// TODO: Documentation
|
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
// Constants
|
// Constants
|
||||||
|
|
||||||
@@ -16,40 +20,79 @@ const OPUS_GET_FINAL_RANGE: c_int = 4031; // *uint
|
|||||||
const OPUS_GET_BANDWIDTH: c_int = 4009; // *int
|
const OPUS_GET_BANDWIDTH: c_int = 4009; // *int
|
||||||
const OPUS_GET_SAMPLE_RATE: c_int = 4029; // *int
|
const OPUS_GET_SAMPLE_RATE: c_int = 4029; // *int
|
||||||
|
|
||||||
|
/// The possible coding modes for the codec.
|
||||||
#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
|
#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
|
||||||
pub enum CodingMode {
|
pub enum CodingMode {
|
||||||
|
/// Best for most VoIP/videoconference applications where listening quality and intelligibility matter most.
|
||||||
Voip = 2048,
|
Voip = 2048,
|
||||||
|
/// Best for broadcast/high-fidelity application where the decoded audio should be as close as possible to the input.
|
||||||
Audio = 2049,
|
Audio = 2049,
|
||||||
|
/// Only use when lowest-achievable latency is what matters most.
|
||||||
LowDelay = 2051,
|
LowDelay = 2051,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The available channel setings.
|
||||||
#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
|
#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
|
||||||
pub enum Channels {
|
pub enum Channels {
|
||||||
Stereo = 1,
|
/// One channel.
|
||||||
Mono = 2,
|
Mono = 2,
|
||||||
|
/// Two channels, left and right.
|
||||||
|
Stereo = 1,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The available bandwidth level settings.
|
||||||
#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
|
#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
|
||||||
pub enum Bandwidth {
|
pub enum Bandwidth {
|
||||||
|
/// Auto/default setting.
|
||||||
|
Auto = -1000,
|
||||||
|
/// 4kHz bandpass.
|
||||||
Narrowband = 1101,
|
Narrowband = 1101,
|
||||||
|
/// 6kHz bandpass.
|
||||||
Mediumband = 1102,
|
Mediumband = 1102,
|
||||||
|
/// 8kHz bandpass.
|
||||||
Wideband = 1103,
|
Wideband = 1103,
|
||||||
|
/// 12kHz bandpass.
|
||||||
Superwideband = 1104,
|
Superwideband = 1104,
|
||||||
|
/// 20kHz bandpass.
|
||||||
Fullband = 1105,
|
Fullband = 1105,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Bandwidth {
|
||||||
|
fn from_int(value: i32) -> Option<Bandwidth> {
|
||||||
|
Some(match value {
|
||||||
|
-1000 => Bandwidth::Auto,
|
||||||
|
1101 => Bandwidth::Narrowband,
|
||||||
|
1102 => Bandwidth::Mediumband,
|
||||||
|
1103 => Bandwidth::Wideband,
|
||||||
|
1104 => Bandwidth::Superwideband,
|
||||||
|
1105 => Bandwidth::Fullband,
|
||||||
|
_ => return None,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Possible error codes.
|
||||||
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
|
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
|
||||||
pub enum ErrorCode {
|
pub enum ErrorCode {
|
||||||
|
/// One or more invalid/out of range arguments.
|
||||||
BadArg = -1,
|
BadArg = -1,
|
||||||
|
/// Not enough bytes allocated in the buffer.
|
||||||
BufferTooSmall = -2,
|
BufferTooSmall = -2,
|
||||||
|
/// An internal error was detected.
|
||||||
InternalError = -3,
|
InternalError = -3,
|
||||||
|
/// The compressed data passed is corrupted.
|
||||||
InvalidPacket = -4,
|
InvalidPacket = -4,
|
||||||
|
/// Invalid/unsupported request number.
|
||||||
Unimplemented = -5,
|
Unimplemented = -5,
|
||||||
|
/// An encoder or decoder structure is invalid or already freed.
|
||||||
InvalidState = -6,
|
InvalidState = -6,
|
||||||
|
/// Memory allocation has failed.
|
||||||
AllocFail = -7,
|
AllocFail = -7,
|
||||||
|
/// An unknown failure.
|
||||||
Unknown = -8,
|
Unknown = -8,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get the libopus version string.
|
||||||
pub fn version() -> &'static str {
|
pub fn version() -> &'static str {
|
||||||
// verison string should always be ASCII
|
// verison string should always be ASCII
|
||||||
unsafe { CStr::from_ptr(ffi::opus_get_version_string()) }.to_str().unwrap()
|
unsafe { CStr::from_ptr(ffi::opus_get_version_string()) }.to_str().unwrap()
|
||||||
@@ -58,12 +101,14 @@ pub fn version() -> &'static str {
|
|||||||
// ============================================================================
|
// ============================================================================
|
||||||
// Encoder
|
// Encoder
|
||||||
|
|
||||||
|
/// An Opus encoder with associated state.
|
||||||
pub struct Encoder {
|
pub struct Encoder {
|
||||||
ptr: *mut ffi::OpusEncoder,
|
ptr: *mut ffi::OpusEncoder,
|
||||||
channels: Channels,
|
channels: Channels,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Encoder {
|
impl Encoder {
|
||||||
|
/// Create and initialize an encoder.
|
||||||
pub fn new(sample_rate: u32, channels: Channels, mode: CodingMode) -> Result<Encoder> {
|
pub fn new(sample_rate: u32, channels: Channels, mode: CodingMode) -> Result<Encoder> {
|
||||||
let mut error = 0;
|
let mut error = 0;
|
||||||
let ptr = unsafe { ffi::opus_encoder_create(
|
let ptr = unsafe { ffi::opus_encoder_create(
|
||||||
@@ -78,6 +123,7 @@ impl Encoder {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Encode an Opus frame.
|
||||||
pub fn encode(&mut self, input: &[i16], output: &mut [u8]) -> Result<usize> {
|
pub fn encode(&mut self, input: &[i16], output: &mut [u8]) -> Result<usize> {
|
||||||
let len = unsafe { ffi::opus_encode(self.ptr,
|
let len = unsafe { ffi::opus_encode(self.ptr,
|
||||||
input.as_ptr(), input.len() as c_int / self.channels as c_int,
|
input.as_ptr(), input.len() as c_int / self.channels as c_int,
|
||||||
@@ -86,6 +132,7 @@ impl Encoder {
|
|||||||
Ok(len as usize)
|
Ok(len as usize)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Encode an Opus frame from floating point input.
|
||||||
pub fn encode_float(&mut self, input: &[f32], output: &mut [u8]) -> Result<usize> {
|
pub fn encode_float(&mut self, input: &[f32], output: &mut [u8]) -> Result<usize> {
|
||||||
let len = unsafe { ffi::opus_encode_float(self.ptr,
|
let len = unsafe { ffi::opus_encode_float(self.ptr,
|
||||||
input.as_ptr(), input.len() as c_int / self.channels as c_int,
|
input.as_ptr(), input.len() as c_int / self.channels as c_int,
|
||||||
@@ -94,10 +141,12 @@ impl Encoder {
|
|||||||
Ok(len as usize)
|
Ok(len as usize)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Reset the codec state to be equivalent to a freshly initialized state.
|
||||||
pub fn reset_state(&mut self) -> Result<()> {
|
pub fn reset_state(&mut self) -> Result<()> {
|
||||||
check("opus_encoder_ctl(OPUS_RESET_STATE)", unsafe { ffi::opus_encoder_ctl(self.ptr, OPUS_RESET_STATE) })
|
check("opus_encoder_ctl(OPUS_RESET_STATE)", unsafe { ffi::opus_encoder_ctl(self.ptr, OPUS_RESET_STATE) })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get the final range of the codec's entropy coder.
|
||||||
pub fn get_final_range(&mut self) -> Result<u32> {
|
pub fn get_final_range(&mut self) -> Result<u32> {
|
||||||
let mut value = 0;
|
let mut value = 0;
|
||||||
let result = unsafe { ffi::opus_encoder_ctl(self.ptr, OPUS_GET_FINAL_RANGE, &mut value) };
|
let result = unsafe { ffi::opus_encoder_ctl(self.ptr, OPUS_GET_FINAL_RANGE, &mut value) };
|
||||||
@@ -105,18 +154,20 @@ impl Encoder {
|
|||||||
Ok(value)
|
Ok(value)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_bandwidth(&mut self) -> Result<i32> {
|
/// Get the encoder's configured bandpass.
|
||||||
|
pub fn get_bandwidth(&mut self) -> Result<Bandwidth> {
|
||||||
let mut value = 0;
|
let mut value = 0;
|
||||||
let result = unsafe { ffi::opus_encoder_ctl(self.ptr, OPUS_GET_BANDWIDTH, &mut value) };
|
let result = unsafe { ffi::opus_encoder_ctl(self.ptr, OPUS_GET_BANDWIDTH, &mut value) };
|
||||||
try!(check("opus_encoder_ctl(OPUS_GET_BANDWIDTH)", result));
|
try!(check("opus_encoder_ctl(OPUS_GET_BANDWIDTH)", result));
|
||||||
Ok(value)
|
Bandwidth::from_int(result).ok_or_else(|| Error::from_code("opus_encoder_ctl(OPUS_GET_BANDWIDTH)", ffi::OPUS_BAD_ARG))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_sample_rate(&mut self) -> Result<i32> {
|
/// Get the samping rate the encoder was intialized with.
|
||||||
|
pub fn get_sample_rate(&mut self) -> Result<u32> {
|
||||||
let mut value = 0;
|
let mut value = 0;
|
||||||
let result = unsafe { ffi::opus_encoder_ctl(self.ptr, OPUS_GET_SAMPLE_RATE, &mut value) };
|
let result = unsafe { ffi::opus_encoder_ctl(self.ptr, OPUS_GET_SAMPLE_RATE, &mut value) };
|
||||||
try!(check("opus_encoder_ctl(OPUS_GET_SAMPLE_RATE)", result));
|
try!(check("opus_encoder_ctl(OPUS_GET_SAMPLE_RATE)", result));
|
||||||
Ok(value)
|
Ok(value as u32)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Encoder-specific CTLs
|
// TODO: Encoder-specific CTLs
|
||||||
@@ -131,12 +182,14 @@ impl Drop for Encoder {
|
|||||||
// ============================================================================
|
// ============================================================================
|
||||||
// Decoder
|
// Decoder
|
||||||
|
|
||||||
|
/// An Opus decoder with associated state.
|
||||||
pub struct Decoder {
|
pub struct Decoder {
|
||||||
ptr: *mut ffi::OpusDecoder,
|
ptr: *mut ffi::OpusDecoder,
|
||||||
channels: Channels,
|
channels: Channels,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Decoder {
|
impl Decoder {
|
||||||
|
/// Create and initialize a decoder.
|
||||||
pub fn new(sample_rate: u32, channels: Channels) -> Result<Decoder> {
|
pub fn new(sample_rate: u32, channels: Channels) -> Result<Decoder> {
|
||||||
let mut error = 0;
|
let mut error = 0;
|
||||||
let ptr = unsafe { ffi::opus_decoder_create(
|
let ptr = unsafe { ffi::opus_decoder_create(
|
||||||
@@ -150,7 +203,7 @@ impl Decoder {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: support null inputs ("packet loss")
|
/// Decode an Opus packet.
|
||||||
pub fn decode(&mut self, input: &[u8], output: &mut [i16], fec: bool) -> Result<usize> {
|
pub fn decode(&mut self, input: &[u8], output: &mut [i16], fec: bool) -> Result<usize> {
|
||||||
let len = unsafe { ffi::opus_decode(self.ptr,
|
let len = unsafe { ffi::opus_decode(self.ptr,
|
||||||
input.as_ptr(), input.len() as c_int,
|
input.as_ptr(), input.len() as c_int,
|
||||||
@@ -160,6 +213,7 @@ impl Decoder {
|
|||||||
Ok(len as usize)
|
Ok(len as usize)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Decode an Opus packet with floating point output.
|
||||||
pub fn decode_float(&mut self, input: &[u8], output: &mut [f32], fec: bool) -> Result<usize> {
|
pub fn decode_float(&mut self, input: &[u8], output: &mut [f32], fec: bool) -> Result<usize> {
|
||||||
let len = unsafe { ffi::opus_decode_float(self.ptr,
|
let len = unsafe { ffi::opus_decode_float(self.ptr,
|
||||||
input.as_ptr(), input.len() as c_int,
|
input.as_ptr(), input.len() as c_int,
|
||||||
@@ -169,6 +223,7 @@ impl Decoder {
|
|||||||
Ok(len as usize)
|
Ok(len as usize)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get the number of samples of an Opus packet.
|
||||||
pub fn get_nb_samples(&self, packet: &[u8]) -> Result<usize> {
|
pub fn get_nb_samples(&self, packet: &[u8]) -> Result<usize> {
|
||||||
let len = unsafe { ffi::opus_decoder_get_nb_samples(self.ptr,
|
let len = unsafe { ffi::opus_decoder_get_nb_samples(self.ptr,
|
||||||
packet.as_ptr(), packet.len() as i32) };
|
packet.as_ptr(), packet.len() as i32) };
|
||||||
@@ -189,12 +244,14 @@ impl Drop for Decoder {
|
|||||||
// ============================================================================
|
// ============================================================================
|
||||||
// Packet Analysis
|
// Packet Analysis
|
||||||
|
|
||||||
|
/// Analyze raw Opus packets.
|
||||||
pub mod packet {
|
pub mod packet {
|
||||||
use super::*;
|
use super::*;
|
||||||
use super::{ffi, check};
|
use super::{ffi, check};
|
||||||
use std::{ptr, slice};
|
use std::{ptr, slice};
|
||||||
use libc::c_int;
|
use libc::c_int;
|
||||||
|
|
||||||
|
/// Get the bandwidth of an Opus packet.
|
||||||
pub fn get_bandwidth(packet: &[u8]) -> Result<Bandwidth> {
|
pub fn get_bandwidth(packet: &[u8]) -> Result<Bandwidth> {
|
||||||
if packet.len() < 1 {
|
if packet.len() < 1 {
|
||||||
return Err(Error::from_code("opus_packet_get_bandwidth", ffi::OPUS_BAD_ARG))
|
return Err(Error::from_code("opus_packet_get_bandwidth", ffi::OPUS_BAD_ARG))
|
||||||
@@ -211,6 +268,7 @@ pub mod packet {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get the number of channels from an Opus packet.
|
||||||
pub fn get_nb_channels(packet: &[u8]) -> Result<Channels> {
|
pub fn get_nb_channels(packet: &[u8]) -> Result<Channels> {
|
||||||
if packet.len() < 1 {
|
if packet.len() < 1 {
|
||||||
return Err(Error::from_code("opus_packet_get_nb_channels", ffi::OPUS_BAD_ARG))
|
return Err(Error::from_code("opus_packet_get_nb_channels", ffi::OPUS_BAD_ARG))
|
||||||
@@ -224,12 +282,14 @@ pub mod packet {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get the number of frames in an Opus packet.
|
||||||
pub fn get_nb_frames(packet: &[u8]) -> Result<usize> {
|
pub fn get_nb_frames(packet: &[u8]) -> Result<usize> {
|
||||||
let frames = unsafe { ffi::opus_packet_get_nb_frames(packet.as_ptr(), packet.len() as c_int) };
|
let frames = unsafe { ffi::opus_packet_get_nb_frames(packet.as_ptr(), packet.len() as c_int) };
|
||||||
try!(check("opus_packet_get_nb_frames", frames));
|
try!(check("opus_packet_get_nb_frames", frames));
|
||||||
Ok(frames as usize)
|
Ok(frames as usize)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get the number of samples of an Opus packet.
|
||||||
pub fn get_nb_samples(packet: &[u8], sample_rate: u32) -> Result<usize> {
|
pub fn get_nb_samples(packet: &[u8], sample_rate: u32) -> Result<usize> {
|
||||||
let frames = unsafe { ffi::opus_packet_get_nb_samples(
|
let frames = unsafe { ffi::opus_packet_get_nb_samples(
|
||||||
packet.as_ptr(), packet.len() as c_int,
|
packet.as_ptr(), packet.len() as c_int,
|
||||||
@@ -238,6 +298,7 @@ pub mod packet {
|
|||||||
Ok(frames as usize)
|
Ok(frames as usize)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get the number of samples per frame from an Opus packet.
|
||||||
pub fn get_samples_per_frame(packet: &[u8], sample_rate: u32) -> Result<usize> {
|
pub fn get_samples_per_frame(packet: &[u8], sample_rate: u32) -> Result<usize> {
|
||||||
if packet.len() < 1 {
|
if packet.len() < 1 {
|
||||||
return Err(Error::from_code("opus_packet_get_samples_per_frame", ffi::OPUS_BAD_ARG))
|
return Err(Error::from_code("opus_packet_get_samples_per_frame", ffi::OPUS_BAD_ARG))
|
||||||
@@ -247,6 +308,7 @@ pub mod packet {
|
|||||||
Ok(samples as usize)
|
Ok(samples as usize)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Parse an Opus packet into one or more frames.
|
||||||
pub fn parse(packet: &[u8]) -> Result<Packet> {
|
pub fn parse(packet: &[u8]) -> Result<Packet> {
|
||||||
let mut toc: u8 = 0;
|
let mut toc: u8 = 0;
|
||||||
let mut frames = [ptr::null(); 48];
|
let mut frames = [ptr::null(); 48];
|
||||||
@@ -270,18 +332,28 @@ pub mod packet {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A parsed Opus packet, retuned from `parse`.
|
||||||
pub struct Packet<'a> {
|
pub struct Packet<'a> {
|
||||||
|
/// The TOC byte of the packet.
|
||||||
pub toc: u8,
|
pub toc: u8,
|
||||||
|
/// The frames contained in the packet.
|
||||||
pub frames: Vec<&'a [u8]>,
|
pub frames: Vec<&'a [u8]>,
|
||||||
|
/// The offset into the packet at which the payload is located.
|
||||||
pub payload_offset: usize,
|
pub payload_offset: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Pad a given Opus packet to a larger size.
|
||||||
|
///
|
||||||
|
/// The packet will be extended from the first `prev_len` bytes of the
|
||||||
|
/// buffer into the rest of the available space.
|
||||||
pub fn pad(packet: &mut [u8], prev_len: usize) -> Result<usize> {
|
pub fn pad(packet: &mut [u8], prev_len: usize) -> Result<usize> {
|
||||||
let result = unsafe { ffi::opus_packet_pad(packet.as_mut_ptr(), prev_len as c_int, packet.len() as c_int) };
|
let result = unsafe { ffi::opus_packet_pad(packet.as_mut_ptr(), prev_len as c_int, packet.len() as c_int) };
|
||||||
try!(check("opus_packet_pad", result));
|
try!(check("opus_packet_pad", result));
|
||||||
Ok(result as usize)
|
Ok(result as usize)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Remove all padding from a given Opus packet and rewrite the TOC sequence
|
||||||
|
/// to minimize space usage.
|
||||||
pub fn unpad(packet: &mut [u8]) -> Result<usize> {
|
pub fn unpad(packet: &mut [u8]) -> Result<usize> {
|
||||||
let result = unsafe { ffi::opus_packet_unpad(packet.as_mut_ptr(), packet.len() as c_int) };
|
let result = unsafe { ffi::opus_packet_unpad(packet.as_mut_ptr(), packet.len() as c_int) };
|
||||||
try!(check("opus_packet_unpad", result));
|
try!(check("opus_packet_unpad", result));
|
||||||
@@ -292,16 +364,19 @@ pub mod packet {
|
|||||||
// ============================================================================
|
// ============================================================================
|
||||||
// Float Soft Clipping
|
// Float Soft Clipping
|
||||||
|
|
||||||
|
/// Soft-clipping to bring a float signal within the [-1,1] range.
|
||||||
pub struct SoftClip {
|
pub struct SoftClip {
|
||||||
channels: Channels,
|
channels: Channels,
|
||||||
memory: [f32; 2],
|
memory: [f32; 2],
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SoftClip {
|
impl SoftClip {
|
||||||
|
/// Initialize a new soft-clipping state.
|
||||||
pub fn new(channels: Channels) -> SoftClip {
|
pub fn new(channels: Channels) -> SoftClip {
|
||||||
SoftClip { channels: channels, memory: [0.0; 2] }
|
SoftClip { channels: channels, memory: [0.0; 2] }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Apply soft-clipping to a float signal.
|
||||||
pub fn apply(&mut self, signal: &mut [f32]) {
|
pub fn apply(&mut self, signal: &mut [f32]) {
|
||||||
unsafe { ffi::opus_pcm_soft_clip(
|
unsafe { ffi::opus_pcm_soft_clip(
|
||||||
signal.as_mut_ptr(),
|
signal.as_mut_ptr(),
|
||||||
@@ -314,11 +389,15 @@ impl SoftClip {
|
|||||||
// ============================================================================
|
// ============================================================================
|
||||||
// Repacketizer
|
// Repacketizer
|
||||||
|
|
||||||
|
// TODO: fix soundness hole by holding a borrow to the input packets
|
||||||
|
|
||||||
|
/// A repacketizer used to merge together or split apart multiple Opus packets.
|
||||||
pub struct Repacketizer {
|
pub struct Repacketizer {
|
||||||
ptr: *mut ffi::OpusRepacketizer,
|
ptr: *mut ffi::OpusRepacketizer,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Repacketizer {
|
impl Repacketizer {
|
||||||
|
/// Create and initialize a repacketizer.
|
||||||
pub fn new() -> Result<Repacketizer> {
|
pub fn new() -> Result<Repacketizer> {
|
||||||
let ptr = unsafe { ffi::opus_repacketizer_create() };
|
let ptr = unsafe { ffi::opus_repacketizer_create() };
|
||||||
if ptr.is_null() {
|
if ptr.is_null() {
|
||||||
@@ -328,20 +407,27 @@ impl Repacketizer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Reset the repacketizer to its initial state.
|
||||||
pub fn reset(&mut self) {
|
pub fn reset(&mut self) {
|
||||||
unsafe { ffi::opus_repacketizer_init(self.ptr); }
|
unsafe { ffi::opus_repacketizer_init(self.ptr); }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get the total number of frames contained in packet data submitted so
|
||||||
|
/// far via `cat` since the last call to `reset`.
|
||||||
pub fn get_nb_frames(&mut self) -> usize {
|
pub fn get_nb_frames(&mut self) -> usize {
|
||||||
unsafe { ffi::opus_repacketizer_get_nb_frames(self.ptr) as usize }
|
unsafe { ffi::opus_repacketizer_get_nb_frames(self.ptr) as usize }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Add a packet to the current repacketizer state.
|
||||||
pub fn cat(&mut self, packet: &[u8]) -> Result<()> {
|
pub fn cat(&mut self, packet: &[u8]) -> Result<()> {
|
||||||
let result = unsafe { ffi::opus_repacketizer_cat(self.ptr,
|
let result = unsafe { ffi::opus_repacketizer_cat(self.ptr,
|
||||||
packet.as_ptr(), packet.len() as c_int) };
|
packet.as_ptr(), packet.len() as c_int) };
|
||||||
check("opus_repacketizer_cat", result)
|
check("opus_repacketizer_cat", result)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Construct a new packet from data previously submitted via `cat`.
|
||||||
|
///
|
||||||
|
/// All previously submitted frames are used.
|
||||||
pub fn out(&mut self, buffer: &mut [u8]) -> Result<usize> {
|
pub fn out(&mut self, buffer: &mut [u8]) -> Result<usize> {
|
||||||
let result = unsafe { ffi::opus_repacketizer_out(self.ptr,
|
let result = unsafe { ffi::opus_repacketizer_out(self.ptr,
|
||||||
buffer.as_mut_ptr(), buffer.len() as c_int) };
|
buffer.as_mut_ptr(), buffer.len() as c_int) };
|
||||||
@@ -349,6 +435,10 @@ impl Repacketizer {
|
|||||||
Ok(result as usize)
|
Ok(result as usize)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Construct a new packet from data previously submitted via `cat`, with
|
||||||
|
/// a manually specified subrange.
|
||||||
|
///
|
||||||
|
/// The `end` index should not exceed the value of `get_nb_frames()`.
|
||||||
pub fn out_range(&mut self, begin: usize, end: usize, buffer: &mut [u8]) -> Result<usize> {
|
pub fn out_range(&mut self, begin: usize, end: usize, buffer: &mut [u8]) -> Result<usize> {
|
||||||
let result = unsafe { ffi::opus_repacketizer_out_range(self.ptr,
|
let result = unsafe { ffi::opus_repacketizer_out_range(self.ptr,
|
||||||
begin as c_int, end as c_int,
|
begin as c_int, end as c_int,
|
||||||
@@ -370,8 +460,10 @@ impl Drop for Repacketizer {
|
|||||||
// ============================================================================
|
// ============================================================================
|
||||||
// Error Handling
|
// Error Handling
|
||||||
|
|
||||||
|
/// Opus error Result alias.
|
||||||
pub type Result<T> = std::result::Result<T, Error>;
|
pub type Result<T> = std::result::Result<T, Error>;
|
||||||
|
|
||||||
|
/// An error generated by the Opus library.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Error {
|
pub struct Error {
|
||||||
function: &'static str,
|
function: &'static str,
|
||||||
@@ -396,8 +488,11 @@ impl Error {
|
|||||||
Error { function: what, description: description, code: code }
|
Error { function: what, description: description, code: code }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get the name of the Opus function from which the error originated.
|
||||||
pub fn function(&self) -> &'static str { self.function }
|
pub fn function(&self) -> &'static str { self.function }
|
||||||
|
/// Get a textual description of the error provided by Opus.
|
||||||
pub fn description(&self) -> &'static str { self.description }
|
pub fn description(&self) -> &'static str { self.description }
|
||||||
|
/// Get the Opus error code of the error.
|
||||||
pub fn code(&self) -> ErrorCode { self.code }
|
pub fn code(&self) -> ErrorCode { self.code }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user