struct Indeo2Decoder {
info: Rc<NACodecInfo>,
cb: Codebook<u8>,
- lastfrm: Option<Rc<NAFrame>>,
+ frmmgr: HAMShuffler,
}
impl Indeo2Decoder {
let dummy_info = Rc::new(DUMMY_CODEC_INFO);
let mut coderead = IR2CodeReader{};
let cb = Codebook::new(&mut coderead, CodebookMode::LSB).unwrap();
- Indeo2Decoder { info: dummy_info, cb: cb, lastfrm: None }
+ Indeo2Decoder { info: dummy_info, cb: cb, frmmgr: HAMShuffler::new() }
}
fn decode_plane_intra(&self, br: &mut BitReader,
let stride = frm.get_stride(planeno);
let cb = &self.cb;
- let mut buffer = frm.get_buffer_mut().unwrap();
- let mut data = buffer.get_data_mut().unwrap();
+ let mut buffer = frm.get_buffer_mut();
+ let mut data = buffer.get_data_mut();
let mut framebuf: &mut [u8] = data.as_mut_slice();
let table = &INDEO2_DELTA_TABLE[tableno];
let stride = frm.get_stride(planeno);
let cb = &self.cb;
- let mut buffer = frm.get_buffer_mut().unwrap();
- let mut data = buffer.get_data_mut().unwrap();
+ let mut buffer = frm.get_buffer_mut();
+ let mut data = buffer.get_data_mut();
let mut framebuf: &mut [u8] = data.as_mut_slice();
let table = &INDEO2_DELTA_TABLE[tableno];
let fmt = formats::YUV410_FORMAT;
let myinfo = NACodecTypeInfo::Video(NAVideoInfo::new(w, h, f, fmt));
self.info = Rc::new(NACodecInfo::new_ref(info.get_name(), myinfo, info.get_extradata()));
+ self.frmmgr.clear();
Ok(())
} else {
Err(DecoderError::InvalidData)
}
}
- fn decode(&mut self, pkt: &NAPacket) -> DecoderResult<Rc<NAFrame>> {
+ fn decode(&mut self, pkt: &NAPacket) -> DecoderResult<NAFrameRef> {
let src = pkt.get_buffer();
if src.len() <= IR2_START { return Err(DecoderError::ShortData); }
let interframe = src[18];
let chroma_tab = (tabs >> 2) & 3;
if interframe != 0 {
let mut frm = NAFrame::new_from_pkt(pkt, self.info.clone());
+ frm.set_keyframe(true);
+ frm.set_frame_type(FrameType::I);
for plane in 0..3 {
let tabidx = (if plane == 0 { luma_tab } else { chroma_tab }) as usize;
self.decode_plane_intra(&mut br, &mut frm, plane, tabidx)?;
}
- let rcf = Rc::new(frm);
- self.lastfrm = Some(rcf.clone());
- Ok(rcf)
+ self.frmmgr.add_frame(frm);
} else {
- let lf = self.lastfrm.clone();
- if let None = lf { return Err(DecoderError::MissingReference); }
- let lastfr = lf.unwrap();
- let mut frm = NAFrame::from_copy(lastfr.as_ref());
+ let frmref = self.frmmgr.clone_ref();
+ if let None = frmref { return Err(DecoderError::MissingReference); }
+ let ffrmref = frmref.unwrap();
+ let mut frm = ffrmref.borrow_mut();
+ frm.set_keyframe(false);
+ frm.set_frame_type(FrameType::P);
frm.fill_timestamps(pkt);
for plane in 0..3 {
let tabidx = (if plane == 0 { luma_tab } else { chroma_tab }) as usize;
self.decode_plane_inter(&mut br, &mut frm, plane, tabidx)?;
}
- let rcf = Rc::new(frm);
- self.lastfrm = Some(rcf.clone());
- Ok(rcf)
}
+ Ok(self.frmmgr.get_output_frame().unwrap())
}
}
mod test {
use codecs;
use demuxers::*;
- use frame::NAFrame;
+ use frame::NAFrameRef;
use io::byteio::*;
use std::fs::File;
use std::io::prelude::*;
let pkt = pktres.unwrap();
if pkt.get_stream().get_id() == str {
let frm = dec.decode(&pkt).unwrap();
- write_pgmyuv(pkt.get_pts().unwrap(), &frm);
+ write_pgmyuv(pkt.get_pts().unwrap(), frm);
}
}
}
- fn write_pgmyuv(num: u64, frm: &NAFrame) {
+ fn write_pgmyuv(num: u64, frmref: NAFrameRef) {
+ let frm = frmref.borrow();
let name = format!("assets/out{:04}.pgm", num);
let mut ofile = File::create(name).unwrap();
let (w, h) = frm.get_dimensions(0);
#[cfg(feature="decoder_indeo2")]
pub mod indeo2;
-use std::rc::Rc;
use frame::*;
+use std::rc::Rc;
+use std::cell::RefCell;
use io::byteio::ByteIOError;
use io::bitreader::BitReaderError;
use io::codebook::CodebookError;
fn from(_: CodebookError) -> Self { DecoderError::InvalidData }
}
+#[allow(dead_code)]
+struct HAMShuffler {
+ lastframe: Option<NAFrameRef>,
+}
+
+impl HAMShuffler {
+ #[allow(dead_code)]
+ fn new() -> Self { HAMShuffler { lastframe: None } }
+ #[allow(dead_code)]
+ fn clear(&mut self) { self.lastframe = None; }
+ #[allow(dead_code)]
+ fn add_frame(&mut self, frm: NAFrame) {
+ self.lastframe = Some(Rc::new(RefCell::new(frm)));
+ }
+ #[allow(dead_code)]
+ fn clone_ref(&mut self) -> Option<NAFrameRef> {
+ match self.lastframe {
+ Some(ref frm) => Some(Rc::new(RefCell::new(NAFrame::from_copy(&frm.borrow())))),
+ None => None,
+ }
+ }
+ #[allow(dead_code)]
+ fn get_output_frame(&mut self) -> Option<NAFrameRef> {
+ match self.lastframe {
+ Some(ref frm) => Some(frm.clone()),
+ None => None,
+ }
+ }
+}
+
pub trait NADecoder {
fn init(&mut self, info: Rc<NACodecInfo>) -> DecoderResult<()>;
- fn decode(&mut self, pkt: &NAPacket) -> DecoderResult<Rc<NAFrame>>;
+ fn decode(&mut self, pkt: &NAPacket) -> DecoderResult<NAFrameRef>;
}
#[derive(Clone,Copy)]
use std::collections::HashMap;
use std::fmt;
use std::rc::Rc;
+use std::cell::*;
use formats::*;
#[allow(dead_code)]
}
}
+pub type BufferRef = Rc<RefCell<Vec<u8>>>;
#[allow(dead_code)]
#[derive(Clone)]
pub struct NABuffer {
id: u64,
- data: Rc<Vec<u8>>,
+ data: BufferRef,
}
impl Drop for NABuffer {
}
impl NABuffer {
- pub fn get_data(&self) -> Rc<Vec<u8>> { self.data.clone() }
- pub fn get_data_mut(&mut self) -> Option<&mut Vec<u8>> { Rc::get_mut(&mut self.data) }
+ pub fn get_data(&self) -> Ref<Vec<u8>> { self.data.borrow() }
+ pub fn get_data_mut(&mut self) -> RefMut<Vec<u8>> { self.data.borrow_mut() }
}
+pub type NABufferRef = Rc<RefCell<NABuffer>>;
+
#[allow(dead_code)]
#[derive(Clone)]
pub struct NACodecInfo {
}
}
-pub fn alloc_buf(info: &NACodecInfo) -> (Rc<NABuffer>, Vec<usize>) {
+pub fn alloc_buf(info: &NACodecInfo) -> (NABufferRef, Vec<usize>) {
let mut data: Vec<u8> = Vec::new();
let mut offs: Vec<usize> = Vec::new();
match info.properties {
NACodecTypeInfo::Video(vinfo) => alloc_video_buf(vinfo, &mut data, &mut offs),
_ => (),
}
- (Rc::new(NABuffer { id: 0, data: Rc::new(data) }), offs)
+ (Rc::new(RefCell::new(NABuffer { id: 0, data: Rc::new(RefCell::new(data)) })), offs)
}
-pub fn copy_buf(buf: &NABuffer) -> Rc<NABuffer> {
+pub fn copy_buf(buf: &NABuffer) -> NABufferRef {
let mut data: Vec<u8> = Vec::new();
data.clone_from(buf.get_data().as_ref());
- Rc::new(NABuffer { id: 0, data: Rc::new(data) })
+ Rc::new(RefCell::new(NABuffer { id: 0, data: Rc::new(RefCell::new(data)) }))
}
#[derive(Debug,Clone)]
Data(Rc<Vec<u8>>),
}
+#[derive(Debug,Clone,Copy,PartialEq)]
+#[allow(dead_code)]
+pub enum FrameType {
+ I,
+ P,
+ B,
+ Other,
+}
+
+impl fmt::Display for FrameType {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ match *self {
+ FrameType::I => write!(f, "I"),
+ FrameType::P => write!(f, "P"),
+ FrameType::B => write!(f, "B"),
+ FrameType::Other => write!(f, "x"),
+ }
+ }
+}
+
#[allow(dead_code)]
#[derive(Clone)]
pub struct NAFrame {
pts: Option<u64>,
dts: Option<u64>,
duration: Option<u64>,
- buffer: Rc<NABuffer>,
+ buffer: NABufferRef,
info: Rc<NACodecInfo>,
+ ftype: FrameType,
+ key: bool,
offsets: Vec<usize>,
options: HashMap<String, NAValue>,
}
pub fn new(pts: Option<u64>,
dts: Option<u64>,
duration: Option<u64>,
+ ftype: FrameType,
+ keyframe: bool,
info: Rc<NACodecInfo>,
options: HashMap<String, NAValue>) -> Self {
let (buf, offs) = alloc_buf(&info);
- NAFrame { pts: pts, dts: dts, duration: duration, buffer: buf, offsets: offs, info: info, options: options }
+ NAFrame { pts: pts, dts: dts, duration: duration, buffer: buf, offsets: offs, info: info, ftype: ftype, key: keyframe, options: options }
}
pub fn from_copy(src: &NAFrame) -> Self {
- let buf = copy_buf(src.get_buffer().as_ref());
+ let buf = copy_buf(&src.get_buffer());
let mut offs: Vec<usize> = Vec::new();
offs.clone_from(&src.offsets);
- NAFrame { pts: None, dts: None, duration: None, buffer: buf, offsets: offs, info: src.info.clone(), options: src.options.clone() }
+ NAFrame { pts: None, dts: None, duration: None, buffer: buf, offsets: offs, info: src.info.clone(), ftype: src.ftype, key: src.key, options: src.options.clone() }
}
pub fn get_pts(&self) -> Option<u64> { self.pts }
pub fn get_dts(&self) -> Option<u64> { self.dts }
pub fn get_duration(&self) -> Option<u64> { self.duration }
+ pub fn get_frame_type(&self) -> FrameType { self.ftype }
+ pub fn is_keyframe(&self) -> bool { self.key }
pub fn set_pts(&mut self, pts: Option<u64>) { self.pts = pts; }
pub fn set_dts(&mut self, dts: Option<u64>) { self.dts = dts; }
pub fn set_duration(&mut self, dur: Option<u64>) { self.duration = dur; }
+ pub fn set_frame_type(&mut self, ftype: FrameType) { self.ftype = ftype; }
+ pub fn set_keyframe(&mut self, key: bool) { self.key = key; }
pub fn get_offset(&self, idx: usize) -> usize { self.offsets[idx] }
- pub fn get_buffer(&self) -> Rc<NABuffer> { self.buffer.clone() }
- pub fn get_buffer_mut(&mut self) -> Option<&mut NABuffer> { Rc::get_mut(&mut self.buffer) }
+ pub fn get_buffer(&self) -> Ref<NABuffer> { self.buffer.borrow() }
+ pub fn get_buffer_mut(&mut self) -> RefMut<NABuffer> { self.buffer.borrow_mut() }
pub fn get_stride(&self, idx: usize) -> usize {
if let NACodecTypeInfo::Video(vinfo) = self.info.get_properties() {
if idx >= vinfo.get_format().get_num_comp() { return 0; }
}
}
+pub type NAFrameRef = Rc<RefCell<NAFrame>>;
+
/// Possible stream types.
#[derive(Debug,Clone,Copy)]
#[allow(dead_code)]
impl FrameFromPacket for NAFrame {
fn new_from_pkt(pkt: &NAPacket, info: Rc<NACodecInfo>) -> NAFrame {
- NAFrame::new(pkt.pts, pkt.dts, pkt.duration, info, HashMap::new())
+ NAFrame::new(pkt.pts, pkt.dts, pkt.duration, FrameType::Other, pkt.keyframe, info, HashMap::new())
}
fn fill_timestamps(&mut self, pkt: &NAPacket) {
self.set_pts(pkt.pts);