//! Packets and decoded frames functionality.
use std::cmp::max;
-use std::collections::HashMap;
+//use std::collections::HashMap;
use std::fmt;
-use std::sync::Arc;
+pub use std::sync::Arc;
pub use crate::formats::*;
pub use crate::refs::*;
pub fn into_ref(self) -> NABufferRef<Self> {
NABufferRef::new(self)
}
+
+ fn print_contents(&self, datatype: &str) {
+ println!("{} video buffer size {}", datatype, self.data.len());
+ println!(" format {}", self.info);
+ print!(" offsets:");
+ for off in self.offs.iter() {
+ print!(" {}", *off);
+ }
+ println!();
+ print!(" strides:");
+ for stride in self.strides.iter() {
+ print!(" {}", *stride);
+ }
+ println!();
+ }
}
/// A specialised type for reference-counted `NAVideoBuffer`.
data: NABufferRef<Vec<T>>,
offs: Vec<usize>,
stride: usize,
+ step: usize,
chmap: NAChannelMap,
len: usize,
}
}
/// Returns the distance between the start of one channel and the next one.
pub fn get_stride(&self) -> usize { self.stride }
+ /// Returns the distance between the samples in one channel.
+ pub fn get_step(&self) -> usize { self.step }
/// Returns audio format information.
pub fn get_info(&self) -> NAAudioInfo { self.info }
/// Returns channel map.
data.clone_from(self.data.as_ref());
let mut offs: Vec<usize> = Vec::with_capacity(self.offs.len());
offs.clone_from(&self.offs);
- NAAudioBuffer { info: self.info, data: NABufferRef::new(data), offs, chmap: self.get_chmap().clone(), len: self.len, stride: self.stride }
+ NAAudioBuffer { info: self.info, data: NABufferRef::new(data), offs, chmap: self.get_chmap().clone(), len: self.len, stride: self.stride, step: self.step }
}
/// Return the length of frame in samples.
pub fn get_length(&self) -> usize { self.len }
+
+ fn print_contents(&self, datatype: &str) {
+ println!("Audio buffer with {} data, stride {}, step {}", datatype, self.stride, self.step);
+ println!(" format {}", self.info);
+ println!(" channel map {}", self.chmap);
+ print!(" offsets:");
+ for off in self.offs.iter() {
+ print!(" {}", *off);
+ }
+ println!();
+ }
}
impl NAAudioBuffer<u8> {
/// Constructs a new `NAAudioBuffer` instance.
pub fn new_from_buf(info: NAAudioInfo, data: NABufferRef<Vec<u8>>, chmap: NAChannelMap) -> Self {
let len = data.len();
- NAAudioBuffer { info, data, chmap, offs: Vec::new(), len, stride: 0 }
+ NAAudioBuffer { info, data, chmap, offs: Vec::new(), len, stride: 0, step: 0 }
}
}
NABufferType::VideoPacked(ref vb) => vb.get_offset(idx),
NABufferType::AudioU8(ref ab) => ab.get_offset(idx),
NABufferType::AudioI16(ref ab) => ab.get_offset(idx),
+ NABufferType::AudioI32(ref ab) => ab.get_offset(idx),
NABufferType::AudioF32(ref ab) => ab.get_offset(idx),
NABufferType::AudioPacked(ref ab) => ab.get_offset(idx),
_ => 0,
_ => 0,
}
}
+ /// Returns the distance between two samples in one channel.
+ pub fn get_audio_step(&self) -> usize {
+ match *self {
+ NABufferType::AudioU8(ref ab) => ab.get_step(),
+ NABufferType::AudioI16(ref ab) => ab.get_step(),
+ NABufferType::AudioI32(ref ab) => ab.get_step(),
+ NABufferType::AudioF32(ref ab) => ab.get_step(),
+ NABufferType::AudioPacked(ref ab) => ab.get_step(),
+ _ => 0,
+ }
+ }
/// Returns reference to 8-bit (or packed) audio buffer.
pub fn get_abuf_u8(&self) -> Option<NAAudioBuffer<u8>> {
match *self {
_ => None,
}
}
+ /// Prints internal buffer layout.
+ pub fn print_buffer_metadata(&self) {
+ match *self {
+ NABufferType::Video(ref buf) => buf.print_contents("8-bit"),
+ NABufferType::Video16(ref buf) => buf.print_contents("16-bit"),
+ NABufferType::Video32(ref buf) => buf.print_contents("32-bit"),
+ NABufferType::VideoPacked(ref buf) => buf.print_contents("packed"),
+ NABufferType::AudioU8(ref buf) => buf.print_contents("8-bit unsigned integer"),
+ NABufferType::AudioI16(ref buf) => buf.print_contents("16-bit integer"),
+ NABufferType::AudioI32(ref buf) => buf.print_contents("32-bit integer"),
+ NABufferType::AudioF32(ref buf) => buf.print_contents("32-bit float"),
+ NABufferType::AudioPacked(ref buf) => buf.print_contents("packed"),
+ NABufferType::Data(ref buf) => { println!("Data buffer, len = {}", buf.len()); },
+ NABufferType::None => { println!("No buffer"); },
+ };
+ }
}
const NA_SIMPLE_VFRAME_COMPONENTS: usize = 4;
#[allow(clippy::collapsible_if)]
pub fn alloc_audio_buffer(ainfo: NAAudioInfo, nsamples: usize, chmap: NAChannelMap) -> Result<NABufferType, AllocatorError> {
let mut offs: Vec<usize> = Vec::new();
- if ainfo.format.is_planar() || (ainfo.channels == 1 && (ainfo.format.get_bits() % 8) == 0) {
+ if ainfo.format.is_planar() || ((ainfo.format.get_bits() % 8) == 0) {
let len = nsamples.checked_mul(ainfo.channels as usize);
if len == None { return Err(AllocatorError::TooLargeDimensions); }
let length = len.unwrap();
- let stride = nsamples;
- for i in 0..ainfo.channels {
- offs.push((i as usize) * stride);
+ let stride;
+ let step;
+ if ainfo.format.is_planar() {
+ stride = nsamples;
+ step = 1;
+ for i in 0..ainfo.channels {
+ offs.push((i as usize) * stride);
+ }
+ } else {
+ stride = 1;
+ step = ainfo.channels as usize;
+ for i in 0..ainfo.channels {
+ offs.push(i as usize);
+ }
}
if ainfo.format.is_float() {
if ainfo.format.get_bits() == 32 {
let data: Vec<f32> = vec![0.0; length];
- let buf: NAAudioBuffer<f32> = NAAudioBuffer { data: NABufferRef::new(data), info: ainfo, offs, chmap, len: nsamples, stride };
+ let buf: NAAudioBuffer<f32> = NAAudioBuffer { data: NABufferRef::new(data), info: ainfo, offs, chmap, len: nsamples, stride, step };
Ok(NABufferType::AudioF32(buf))
} else {
Err(AllocatorError::TooLargeDimensions)
} else {
if ainfo.format.get_bits() == 8 && !ainfo.format.is_signed() {
let data: Vec<u8> = vec![0; length];
- let buf: NAAudioBuffer<u8> = NAAudioBuffer { data: NABufferRef::new(data), info: ainfo, offs, chmap, len: nsamples, stride };
+ let buf: NAAudioBuffer<u8> = NAAudioBuffer { data: NABufferRef::new(data), info: ainfo, offs, chmap, len: nsamples, stride, step };
Ok(NABufferType::AudioU8(buf))
} else if ainfo.format.get_bits() == 16 && ainfo.format.is_signed() {
let data: Vec<i16> = vec![0; length];
- let buf: NAAudioBuffer<i16> = NAAudioBuffer { data: NABufferRef::new(data), info: ainfo, offs, chmap, len: nsamples, stride };
+ let buf: NAAudioBuffer<i16> = NAAudioBuffer { data: NABufferRef::new(data), info: ainfo, offs, chmap, len: nsamples, stride, step };
Ok(NABufferType::AudioI16(buf))
} else {
Err(AllocatorError::TooLargeDimensions)
if len == None { return Err(AllocatorError::TooLargeDimensions); }
let length = ainfo.format.get_audio_size(len.unwrap() as u64);
let data: Vec<u8> = vec![0; length];
- let buf: NAAudioBuffer<u8> = NAAudioBuffer { data: NABufferRef::new(data), info: ainfo, offs, chmap, len: nsamples, stride: 0 };
+ let buf: NAAudioBuffer<u8> = NAAudioBuffer { data: NABufferRef::new(data), info: ainfo, offs, chmap, len: nsamples, stride: 0, step: 0 };
Ok(NABufferType::AudioPacked(buf))
}
}
properties: NACodecTypeInfo::None,
extradata: None };
-/// A list of accepted option values.
-#[derive(Debug,Clone)]
-pub enum NAValue {
- /// Empty value.
- None,
- /// Integer value.
- Int(i32),
- /// Long integer value.
- Long(i64),
- /// String value.
- String(String),
- /// Binary data value.
- Data(Arc<Vec<u8>>),
-}
-
/// A list of recognized frame types.
#[derive(Debug,Clone,Copy,PartialEq)]
#[allow(dead_code)]
pub frame_type: FrameType,
/// Keyframe flag.
pub key: bool,
- options: HashMap<String, NAValue>,
+// options: HashMap<String, NAValue>,
}
/// A specialised type for reference-counted `NAFrame`.
ftype: FrameType,
keyframe: bool,
info: NACodecInfoRef,
- options: HashMap<String, NAValue>,
+ /*options: HashMap<String, NAValue>,*/
buffer: NABufferType) -> Self {
- NAFrame { ts, id: 0, buffer, info, frame_type: ftype, key: keyframe, options }
+ NAFrame { ts, id: 0, buffer, info, frame_type: ftype, key: keyframe/*, options*/ }
}
/// Returns frame format information.
pub fn get_info(&self) -> NACodecInfoRef { self.info.clone() }
/// Converts current instance into a reference-counted one.
pub fn into_ref(self) -> NAFrameRef { Arc::new(self) }
+
+ /// Creates new frame with metadata from `NAPacket`.
+ pub fn new_from_pkt(pkt: &NAPacket, info: NACodecInfoRef, buf: NABufferType) -> NAFrame {
+ NAFrame::new(pkt.ts, FrameType::Other, pkt.keyframe, info, /*HashMap::new(),*/ buf)
+ }
}
impl fmt::Display for NAFrame {
}
}
+/// Side data that may accompany demuxed data.
+#[derive(Clone)]
+pub enum NASideData {
+ /// Palette information.
+ ///
+ /// This side data contains a flag signalling that palette has changed since previous time and a reference to the current palette.
+ /// Palette is stored in 8-bit RGBA format.
+ Palette(bool, Arc<[u8; 1024]>),
+ /// Generic user data.
+ UserData(Arc<Vec<u8>>),
+}
+
/// Packet with compressed data.
#[allow(dead_code)]
pub struct NAPacket {
/// Keyframe flag.
pub keyframe: bool,
// options: HashMap<String, NAValue<'a>>,
+ /// Packet side data (e.g. palette for paletted formats).
+ pub side_data: Vec<NASideData>,
}
impl NAPacket {
pub fn new(str: NAStreamRef, ts: NATimeInfo, kf: bool, vec: Vec<u8>) -> Self {
// let mut vec: Vec<u8> = Vec::new();
// vec.resize(size, 0);
- NAPacket { stream: str, ts, keyframe: kf, buffer: NABufferRef::new(vec) }
+ NAPacket { stream: str, ts, keyframe: kf, buffer: NABufferRef::new(vec), side_data: Vec::new() }
}
/// Returns information about the stream packet belongs to.
pub fn get_stream(&self) -> NAStreamRef { self.stream.clone() }
pub fn is_keyframe(&self) -> bool { self.keyframe }
/// Returns a reference to packet data.
pub fn get_buffer(&self) -> NABufferRef<Vec<u8>> { self.buffer.clone() }
+ /// Adds side data for a packet.
+ pub fn add_side_data(&mut self, side_data: NASideData) { self.side_data.push(side_data); }
+ /// Assigns packet to a new stream.
+ pub fn reassign(&mut self, str: NAStreamRef, ts: NATimeInfo) {
+ self.stream = str;
+ self.ts = ts;
+ }
}
impl Drop for NAPacket {
write!(f, "{}", ostr)
}
}
-
-/// A trait for creating `NAFrame` using information from `NAPacket`.
-pub trait FrameFromPacket {
- /// Creates new frame with metadata from `NAPacket`.
- fn new_from_pkt(pkt: &NAPacket, info: NACodecInfoRef, buf: NABufferType) -> NAFrame;
- /// Sets frame timestamp from `NAPacket`.
- fn fill_timestamps(&mut self, pkt: &NAPacket);
-}
-
-impl FrameFromPacket for NAFrame {
- fn new_from_pkt(pkt: &NAPacket, info: NACodecInfoRef, buf: NABufferType) -> NAFrame {
- NAFrame::new(pkt.ts, FrameType::Other, pkt.keyframe, info, HashMap::new(), buf)
- }
- fn fill_timestamps(&mut self, pkt: &NAPacket) {
- self.ts = pkt.get_time_information();
- }
-}
-