libde265 0.2.0

Low-level bindings for libdeH265.
Documentation
use libde265::{De265, Decoder};

const NAL_MIN_0_COUNT: usize = 2;
#[inline]
fn nth_nal_index(stream: &[u8], nth: usize) -> Option<usize> {
    let mut count_0 = 0;
    let mut n = 0;

    for (i, byte) in stream.iter().enumerate() {
        match byte {
            0 => count_0 += 1,
            1 if count_0 >= NAL_MIN_0_COUNT => {
                if n == nth {
                    return Some(i - NAL_MIN_0_COUNT);
                } else {
                    count_0 = 0;
                    n += 1;
                }
            }
            _ => count_0 = 0,
        }
    }

    None
}

pub fn nal_units(mut stream: &[u8]) -> impl Iterator<Item = &[u8]> {
    std::iter::from_fn(move || {
        let first = nth_nal_index(stream, 0);
        let next = nth_nal_index(stream, 1);

        match (first, next) {
            (Some(f), Some(n)) => {
                let rval = &stream[f..n];
                stream = &stream[n..];
                Some(rval)
            }
            (Some(f), None) => {
                let rval = &stream[f..];
                stream = &stream[f + NAL_MIN_0_COUNT..];
                Some(rval)
            }
            _ => None,
        }
    })
}

fn main() {
    let de = De265::new().unwrap();
    println!("libde265 {}", de.get_version());

    let mut decoder = Decoder::new(de.clone());
    decoder.start_worker_threads(16).unwrap();

    let h264_in = std::fs::read("/home/andrey/demo/h265/big_buck_bunney.h265").unwrap();

    for packet in nal_units(&h264_in) {
        decoder.push_data(packet, 0, None).unwrap();
        decoder.decode().unwrap();

        if let Some(img) = decoder.get_next_picture() {
            let y = img.get_image_plane(0);
            let u = img.get_image_plane(1);
            let v = img.get_image_plane(2);

            println!(
                "pic {}x{} {:?} {:?} {:?} {:?} {:?} {:?} {:?}",
                img.get_image_width(0),
                img.get_image_height(0),
                img.get_chroma_format(),
                &y.0[0..20],
                y.1,
                &u.0[0..20],
                u.1,
                &v.0[0..20],
                v.1
            );
        }
    }
}