+use nihav_core::frame::*;
+use sdl2::pixels::PixelFormatEnum;
+use sdl2::rect::Rect;
+use sdl2::render::*;
+use sdl2::video::WindowContext;
+
+pub struct SDLFrame<'r> {
+ pub id: u32,
+ pub time: u64,
+ pub rect: Rect,
+ pub tex: Texture<'r>,
+ pub yuv: bool,
+}
+
+impl<'r> SDLFrame<'r> {
+ pub fn load_frame_yuv(&mut self, buf: NAVideoBufferRef<u8>) {
+ let (width, height) = buf.get_dimensions(0);
+ let aheight = (height + 1) & !1;
+ let src = buf.get_data();
+ let ysstride = buf.get_stride(0);
+ let ysrc = &src[buf.get_offset(0)..][..ysstride * aheight];
+ let usstride = buf.get_stride(2);
+ let usrc = &src[buf.get_offset(2)..][..usstride * (aheight / 2)];
+ let vsstride = buf.get_stride(1);
+ let vsrc = &src[buf.get_offset(1)..][..vsstride * (aheight / 2)];
+ self.rect = Rect::new(0, 0, (width as u32 + 1) & !1, aheight as u32);
+ self.tex.update_yuv(self.rect, ysrc, ysstride, vsrc, vsstride, usrc, usstride)
+ .expect("YUV surface updated");
+ }
+ pub fn load_frame_rgb(&mut self, buf: NAVideoBufferRef<u8>) {
+ let (width, height) = buf.get_dimensions(0);
+ self.rect = Rect::new(0, 0, width as u32, height as u32);
+ let sstride = buf.get_stride(0);
+ let src = buf.get_data();
+ self.tex.update(self.rect, src, sstride).expect("updated");
+ }
+}
+
+pub struct SDLPool<'r> {
+ pub yuv_pool: Vec<SDLFrame<'r>>,
+ pub rgb_pool: Vec<SDLFrame<'r>>,
+}
+
+impl<'r> SDLPool<'r> {
+ pub fn new(texture_creator: &'r TextureCreator<WindowContext>, width: usize, height: usize, len: usize) -> Self {
+ let mut yuv_pool = Vec::with_capacity(len);
+ let mut rgb_pool = Vec::with_capacity(len);
+ let rect = Rect::new(0, 0, width as u32, height as u32);
+ for i in 0..len {
+ let mut rgb_tex = texture_creator.create_texture_streaming(PixelFormatEnum::RGB24, width as u32, height as u32).expect("failed to create RGB texture");
+ let mut yuv_tex = texture_creator.create_texture_streaming(PixelFormatEnum::IYUV, ((width + 1) & !1) as u32, ((height + 1) & !1) as u32).expect("failed to create YUV texture");
+ rgb_tex.set_blend_mode(BlendMode::None);
+ //rgb_tex.set_scale_mode(ScaleMode::Nearest);
+ yuv_tex.set_blend_mode(BlendMode::None);
+ rgb_pool.push(SDLFrame{ id: i as u32, time: 0, rect, tex: rgb_tex, yuv: false });
+ yuv_pool.push(SDLFrame{ id: i as u32, time: 0, rect, tex: yuv_tex, yuv: true });
+ }
+ Self { yuv_pool, rgb_pool }
+ }
+ pub fn is_empty(&self) -> bool { self.yuv_pool.is_empty() || self.rgb_pool.is_empty() }
+ pub fn get_frame(&mut self, yuv: bool) -> Option<SDLFrame<'r>> {
+ if yuv { self.yuv_pool.pop() } else { self.rgb_pool.pop() }
+ }
+ pub fn return_frame(&mut self, frm: SDLFrame<'r>) {
+ if frm.yuv {
+ self.yuv_pool.push(frm);
+ } else {
+ self.rgb_pool.push(frm);
+ }
+ }
+}