diff --git a/src/main.rs b/src/main.rs index 80d3646..a2aa36a 100644 --- a/src/main.rs +++ b/src/main.rs @@ -32,73 +32,860 @@ fn main() { // Create a converter to get the video frames into the color format // we want. - // It's a bit weird, but we do this by creating a scaler, which also - // resizes images. Apparently it's an all-in-one kind of thing for - // scaling and color format conversion. - let mut converter = ffmpeg::software::scaling::context::Context::get( - decoder.format(), - decoder.width(), - decoder.height(), - Pixel::RGB24, // Output color format. - decoder.width(), - decoder.height(), - Flags::POINT, // Nearest neighbor, since we're not actually scaling. - ) - .unwrap(); - - // Place to store the image data. - let mut width = 0; - let mut height = 0; - let mut pixels = Vec::new(); + let bit_depth = pixel_channel_size(decoder.format()).unwrap_or(8); + let mut converter = decoder + .converter(if bit_depth <= 8 { + Pixel::RGB24 + } else { + // Note: don't use plain `RGB48`, because it doesn't work + // for some reason. Always use either the `BE` or `LE` + // variant, as appropriate for the platform. + Pixel::RGB48BE + }) + .unwrap(); // Get the first frame of the video. - // To access it we have to process packets until the frame is - // available. - let mut decoded_frame = ffmpeg::util::frame::video::Video::empty(); - for (stream, packet) in input_ctx.packets() { - if stream.index() == stream_idx { - decoder.send_packet(&packet).unwrap(); - if decoder.receive_frame(&mut decoded_frame).is_ok() { - // Convert to RGB. - let mut converted_frame = ffmpeg::util::frame::video::Video::empty(); - converter.run(&decoded_frame, &mut converted_frame).unwrap(); + let mut frame = None; + { + // To access a frame we have to process packets until a frame is + // available. + let mut decoded_frame = ffmpeg::util::frame::video::Video::empty(); + for (stream, packet) in input_ctx.packets() { + if stream.index() == stream_idx { + decoder.send_packet(&packet).unwrap(); + if decoder.receive_frame(&mut decoded_frame).is_ok() { + // Convert to RGB. + let mut converted_frame = ffmpeg::util::frame::video::Video::empty(); + converter.run(&decoded_frame, &mut converted_frame).unwrap(); - // Save the image data to our own in-memory area. - width = converted_frame.width() as u32; - height = converted_frame.height() as u32; - // The `0` parameter is the plane. For this pixel format - // there's just one plane anyway. - for byte in converted_frame.data(0).iter() { - pixels.push(*byte); + // We got the first frame, so stop. + frame = Some(converted_frame); + break; } - - // We got the first frame, so stop. - break; } } } - // Write out a PNG file. - let mut encoder = png::Encoder::new( - BufWriter::new(File::create(output_path).unwrap()), - width, - height, - ); - encoder.set_color(png::ColorType::Rgb); - encoder.set_depth(png::BitDepth::Eight); - let mut writer = encoder.write_header().unwrap(); - writer.write_image_data(&pixels).unwrap(); + // Write out a PNG file of the frame. + if let Some(frame) = frame { + let mut encoder = png::Encoder::new( + BufWriter::new(File::create(output_path).unwrap()), + frame.width(), + frame.height(), + ); + encoder.set_color(png::ColorType::Rgb); + encoder.set_depth(if bit_depth <= 8 { + png::BitDepth::Eight + } else { + png::BitDepth::Sixteen + }); + let mut writer = encoder.write_header().unwrap(); + writer.write_image_data(frame.data(0)).unwrap(); - println!("{:?}", decoder.format()); + println!("Done"); + } else { + println!("Could not process video."); + } } // Returns the number of bits needed to store any of the pixel channels // for a given format. -fn pixel_channel_size(f: Pixel) -> usize { - use Pixel::*; +fn pixel_channel_size(f: Pixel) -> Option { match f { - YUV420P => 8, - YUV422P10LE => 10, - _ => panic!("Haven't decided how to decode '{:?}' yet", f), + // No specific pixel format defined. + Pixel::None => None, + Pixel::VAAPI_MOCO => None, + Pixel::VAAPI_IDCT => None, + Pixel::VAAPI_VLD => None, + Pixel::DXVA2_VLD => None, + Pixel::VDPAU => None, + Pixel::QSV => None, + Pixel::MMAL => None, + Pixel::D3D11VA_VLD => None, + Pixel::CUDA => None, + Pixel::XVMC => None, + Pixel::VIDEOTOOLBOX => None, + Pixel::MEDIACODEC => None, + Pixel::D3D11 => None, + Pixel::DRM_PRIME => None, + Pixel::OPENCL => None, + Pixel::VULKAN => None, + + // Defined pixel formats. + Pixel::YUV420P => Some(8), + Pixel::YUYV422 => Some(8), + Pixel::RGB24 => Some(8), + Pixel::BGR24 => Some(8), + Pixel::YUV422P => Some(8), + Pixel::YUV444P => Some(8), + Pixel::YUV410P => Some(8), + Pixel::YUV411P => Some(8), + Pixel::GRAY8 => Some(8), + Pixel::MonoWhite => Some(1), + Pixel::MonoBlack => Some(1), + Pixel::PAL8 => Some(8), + Pixel::YUVJ420P => Some(8), + Pixel::YUVJ422P => Some(8), + Pixel::YUVJ444P => Some(8), + Pixel::UYVY422 => Some(8), + Pixel::UYYVYY411 => Some(8), + Pixel::BGR8 => Some(3), + Pixel::BGR4 => Some(2), + Pixel::BGR4_BYTE => Some(2), + Pixel::RGB8 => Some(3), + Pixel::RGB4 => Some(2), + Pixel::RGB4_BYTE => Some(2), + Pixel::NV12 => Some(8), + Pixel::NV21 => Some(8), + Pixel::ARGB => Some(8), + Pixel::RGBA => Some(8), + Pixel::ABGR => Some(8), + Pixel::BGRA => Some(8), + Pixel::GRAY16BE => Some(16), + Pixel::GRAY16LE => Some(16), + Pixel::YUV440P => Some(8), + Pixel::YUVJ440P => Some(8), + Pixel::YUVA420P => Some(8), + Pixel::RGB48BE => Some(16), + Pixel::RGB48LE => Some(16), + Pixel::RGB565BE => Some(6), + Pixel::RGB565LE => Some(6), + Pixel::RGB555BE => Some(5), + Pixel::RGB555LE => Some(5), + Pixel::BGR565BE => Some(6), + Pixel::BGR565LE => Some(6), + Pixel::BGR555BE => Some(5), + Pixel::BGR555LE => Some(5), + Pixel::YUV420P16LE => Some(16), + Pixel::YUV420P16BE => Some(16), + Pixel::YUV422P16LE => Some(16), + Pixel::YUV422P16BE => Some(16), + Pixel::YUV444P16LE => Some(16), + Pixel::YUV444P16BE => Some(16), + Pixel::RGB444LE => Some(4), + Pixel::RGB444BE => Some(4), + Pixel::BGR444LE => Some(4), + Pixel::BGR444BE => Some(4), + Pixel::YA8 => Some(8), + Pixel::BGR48BE => Some(16), + Pixel::BGR48LE => Some(16), + Pixel::YUV420P9BE => Some(9), + Pixel::YUV420P9LE => Some(9), + Pixel::YUV420P10BE => Some(10), + Pixel::YUV420P10LE => Some(10), + Pixel::YUV422P10BE => Some(10), + Pixel::YUV422P10LE => Some(10), + Pixel::YUV444P9BE => Some(9), + Pixel::YUV444P9LE => Some(9), + Pixel::YUV444P10BE => Some(10), + Pixel::YUV444P10LE => Some(10), + Pixel::YUV422P9BE => Some(9), + Pixel::YUV422P9LE => Some(9), + Pixel::GBRP => Some(8), + Pixel::GBRP9BE => Some(9), + Pixel::GBRP9LE => Some(9), + Pixel::GBRP10BE => Some(10), + Pixel::GBRP10LE => Some(10), + Pixel::GBRP16BE => Some(16), + Pixel::GBRP16LE => Some(16), + Pixel::YUVA420P9BE => Some(9), + Pixel::YUVA420P9LE => Some(9), + Pixel::YUVA422P9BE => Some(9), + Pixel::YUVA422P9LE => Some(9), + Pixel::YUVA444P9BE => Some(9), + Pixel::YUVA444P9LE => Some(9), + Pixel::YUVA420P10BE => Some(10), + Pixel::YUVA420P10LE => Some(10), + Pixel::YUVA422P10BE => Some(10), + Pixel::YUVA422P10LE => Some(10), + Pixel::YUVA444P10BE => Some(10), + Pixel::YUVA444P10LE => Some(10), + Pixel::YUVA420P16BE => Some(16), + Pixel::YUVA420P16LE => Some(16), + Pixel::YUVA422P16BE => Some(16), + Pixel::YUVA422P16LE => Some(16), + Pixel::YUVA444P16BE => Some(16), + Pixel::YUVA444P16LE => Some(16), + Pixel::XYZ12LE => Some(12), + Pixel::XYZ12BE => Some(12), + Pixel::NV16 => Some(8), + Pixel::NV20LE => Some(10), + Pixel::NV20BE => Some(10), + Pixel::RGBA64BE => Some(16), + Pixel::RGBA64LE => Some(16), + Pixel::BGRA64BE => Some(16), + Pixel::BGRA64LE => Some(16), + Pixel::YVYU422 => Some(8), + Pixel::YA16BE => Some(16), + Pixel::YA16LE => Some(16), + Pixel::ZRGB => Some(8), + Pixel::RGBZ => Some(8), + Pixel::ZBGR => Some(8), + Pixel::BGRZ => Some(8), + Pixel::YUVA444P => Some(8), + Pixel::YUVA422P => Some(8), + Pixel::YUV420P12BE => Some(12), + Pixel::YUV420P12LE => Some(12), + Pixel::YUV420P14BE => Some(14), + Pixel::YUV420P14LE => Some(14), + Pixel::YUV422P12BE => Some(12), + Pixel::YUV422P12LE => Some(12), + Pixel::YUV422P14BE => Some(14), + Pixel::YUV422P14LE => Some(14), + Pixel::YUV444P12BE => Some(12), + Pixel::YUV444P12LE => Some(12), + Pixel::YUV444P14BE => Some(14), + Pixel::YUV444P14LE => Some(14), + Pixel::GBRP12BE => Some(12), + Pixel::GBRP12LE => Some(12), + Pixel::GBRP14BE => Some(14), + Pixel::GBRP14LE => Some(14), + Pixel::GBRAP => Some(8), + Pixel::GBRAP16BE => Some(16), + Pixel::GBRAP16LE => Some(16), + Pixel::YUVJ411P => Some(8), + Pixel::BAYER_BGGR8 => Some(8), + Pixel::BAYER_RGGB8 => Some(8), + Pixel::BAYER_GBRG8 => Some(8), + Pixel::BAYER_GRBG8 => Some(8), + Pixel::BAYER_BGGR16LE => Some(16), + Pixel::BAYER_BGGR16BE => Some(16), + Pixel::BAYER_RGGB16LE => Some(16), + Pixel::BAYER_RGGB16BE => Some(16), + Pixel::BAYER_GBRG16LE => Some(16), + Pixel::BAYER_GBRG16BE => Some(16), + Pixel::BAYER_GRBG16LE => Some(16), + Pixel::BAYER_GRBG16BE => Some(16), + Pixel::YUV440P10LE => Some(10), + Pixel::YUV440P10BE => Some(10), + Pixel::YUV440P12LE => Some(12), + Pixel::YUV440P12BE => Some(12), + Pixel::AYUV64LE => Some(16), + Pixel::AYUV64BE => Some(16), + Pixel::P010LE => Some(10), + Pixel::P010BE => Some(10), + Pixel::GBRAP12BE => Some(12), + Pixel::GBRAP12LE => Some(12), + Pixel::GBRAP10LE => Some(10), + Pixel::GBRAP10BE => Some(10), + Pixel::GRAY12BE => Some(12), + Pixel::GRAY12LE => Some(12), + Pixel::GRAY10BE => Some(10), + Pixel::GRAY10LE => Some(10), + Pixel::P016LE => Some(16), + Pixel::P016BE => Some(16), + Pixel::GRAY9BE => Some(9), + Pixel::GRAY9LE => Some(9), + Pixel::GBRPF32BE => Some(32), + Pixel::GBRPF32LE => Some(32), + Pixel::GBRAPF32BE => Some(32), + Pixel::GBRAPF32LE => Some(32), + Pixel::GRAY14BE => Some(14), + Pixel::GRAY14LE => Some(14), + Pixel::GRAYF32BE => Some(32), + Pixel::GRAYF32LE => Some(32), + Pixel::YUVA422P12BE => Some(12), + Pixel::YUVA422P12LE => Some(12), + Pixel::YUVA444P12BE => Some(12), + Pixel::YUVA444P12LE => Some(12), + Pixel::NV24 => Some(8), + Pixel::NV42 => Some(8), + Pixel::Y210BE => Some(10), + Pixel::Y210LE => Some(10), + Pixel::X2RGB10LE => Some(10), + Pixel::X2RGB10BE => Some(10), + + // Native-endian aliases for some of the above formats. + Pixel::RGB32 => Some(8), + Pixel::RGB32_1 => Some(8), + Pixel::BGR32 => Some(8), + Pixel::BGR32_1 => Some(8), + Pixel::ZRGB32 => Some(8), + Pixel::ZBGR32 => Some(8), + Pixel::GRAY16 => Some(16), + Pixel::YA16 => Some(16), + Pixel::RGB48 => Some(16), + Pixel::RGB565 => Some(6), + Pixel::RGB555 => Some(5), + Pixel::RGB444 => Some(4), + Pixel::BGR48 => Some(16), + Pixel::BGR565 => Some(6), + Pixel::BGR555 => Some(5), + Pixel::BGR444 => Some(4), + Pixel::YUV420P9 => Some(9), + Pixel::YUV422P9 => Some(9), + Pixel::YUV444P9 => Some(9), + Pixel::YUV420P10 => Some(10), + Pixel::YUV422P10 => Some(10), + Pixel::YUV440P10 => Some(10), + Pixel::YUV444P10 => Some(10), + Pixel::YUV420P12 => Some(12), + Pixel::YUV422P12 => Some(12), + Pixel::YUV440P12 => Some(12), + Pixel::YUV444P12 => Some(12), + Pixel::YUV420P14 => Some(14), + Pixel::YUV422P14 => Some(14), + Pixel::YUV444P14 => Some(14), + Pixel::YUV420P16 => Some(16), + Pixel::YUV422P16 => Some(16), + Pixel::YUV444P16 => Some(16), + Pixel::GBRP9 => Some(9), + Pixel::GBRP10 => Some(10), + Pixel::GBRP12 => Some(12), + Pixel::GBRP14 => Some(14), + Pixel::GBRP16 => Some(16), + Pixel::GBRAP16 => Some(16), + Pixel::BAYER_BGGR16 => Some(16), + Pixel::BAYER_RGGB16 => Some(16), + Pixel::BAYER_GBRG16 => Some(16), + Pixel::BAYER_GRBG16 => Some(16), + Pixel::YUVA420P9 => Some(9), + Pixel::YUVA422P9 => Some(9), + Pixel::YUVA444P9 => Some(9), + Pixel::YUVA420P10 => Some(10), + Pixel::YUVA422P10 => Some(10), + Pixel::YUVA444P10 => Some(10), + Pixel::YUVA420P16 => Some(16), + Pixel::YUVA422P16 => Some(16), + Pixel::YUVA444P16 => Some(16), + Pixel::XYZ12 => Some(12), + Pixel::NV20 => Some(10), + Pixel::AYUV64 => Some(16), + } +} + +// Returns the number of color channels in the pixel format. +// +// Note 1: this excludes the alpha channel. +// Note 2: for bayer-like formats this represents the total number of +// photo sites in one complete tile pattern. Usually this is 4. +// Note 3: for palette-indexed formats, this is the number of channels +// in a palette color. +fn pixel_color_channel_count(f: Pixel) -> Option { + match f { + // No specific pixel format defined. + Pixel::None => None, + Pixel::VAAPI_MOCO => None, + Pixel::VAAPI_IDCT => None, + Pixel::VAAPI_VLD => None, + Pixel::DXVA2_VLD => None, + Pixel::VDPAU => None, + Pixel::QSV => None, + Pixel::MMAL => None, + Pixel::D3D11VA_VLD => None, + Pixel::CUDA => None, + Pixel::XVMC => None, + Pixel::VIDEOTOOLBOX => None, + Pixel::MEDIACODEC => None, + Pixel::D3D11 => None, + Pixel::DRM_PRIME => None, + Pixel::OPENCL => None, + Pixel::VULKAN => None, + + // Defined pixel formats. + Pixel::YUV420P => Some(3), + Pixel::YUYV422 => Some(3), + Pixel::RGB24 => Some(3), + Pixel::BGR24 => Some(3), + Pixel::YUV422P => Some(3), + Pixel::YUV444P => Some(3), + Pixel::YUV410P => Some(3), + Pixel::YUV411P => Some(3), + Pixel::GRAY8 => Some(1), + Pixel::MonoWhite => Some(1), + Pixel::MonoBlack => Some(1), + Pixel::PAL8 => Some(3), + Pixel::YUVJ420P => Some(3), + Pixel::YUVJ422P => Some(3), + Pixel::YUVJ444P => Some(3), + Pixel::UYVY422 => Some(3), + Pixel::UYYVYY411 => Some(3), + Pixel::BGR8 => Some(3), + Pixel::BGR4 => Some(3), + Pixel::BGR4_BYTE => Some(3), + Pixel::RGB8 => Some(3), + Pixel::RGB4 => Some(3), + Pixel::RGB4_BYTE => Some(3), + Pixel::NV12 => Some(3), + Pixel::NV21 => Some(3), + Pixel::ARGB => Some(3), + Pixel::RGBA => Some(3), + Pixel::ABGR => Some(3), + Pixel::BGRA => Some(3), + Pixel::GRAY16BE => Some(1), + Pixel::GRAY16LE => Some(1), + Pixel::YUV440P => Some(3), + Pixel::YUVJ440P => Some(3), + Pixel::YUVA420P => Some(3), + Pixel::RGB48BE => Some(3), + Pixel::RGB48LE => Some(3), + Pixel::RGB565BE => Some(3), + Pixel::RGB565LE => Some(3), + Pixel::RGB555BE => Some(3), + Pixel::RGB555LE => Some(3), + Pixel::BGR565BE => Some(3), + Pixel::BGR565LE => Some(3), + Pixel::BGR555BE => Some(3), + Pixel::BGR555LE => Some(3), + Pixel::YUV420P16LE => Some(3), + Pixel::YUV420P16BE => Some(3), + Pixel::YUV422P16LE => Some(3), + Pixel::YUV422P16BE => Some(3), + Pixel::YUV444P16LE => Some(3), + Pixel::YUV444P16BE => Some(3), + Pixel::RGB444LE => Some(3), + Pixel::RGB444BE => Some(3), + Pixel::BGR444LE => Some(3), + Pixel::BGR444BE => Some(3), + Pixel::YA8 => Some(1), + Pixel::BGR48BE => Some(3), + Pixel::BGR48LE => Some(3), + Pixel::YUV420P9BE => Some(3), + Pixel::YUV420P9LE => Some(3), + Pixel::YUV420P10BE => Some(3), + Pixel::YUV420P10LE => Some(3), + Pixel::YUV422P10BE => Some(3), + Pixel::YUV422P10LE => Some(3), + Pixel::YUV444P9BE => Some(3), + Pixel::YUV444P9LE => Some(3), + Pixel::YUV444P10BE => Some(3), + Pixel::YUV444P10LE => Some(3), + Pixel::YUV422P9BE => Some(3), + Pixel::YUV422P9LE => Some(3), + Pixel::GBRP => Some(3), + Pixel::GBRP9BE => Some(3), + Pixel::GBRP9LE => Some(3), + Pixel::GBRP10BE => Some(3), + Pixel::GBRP10LE => Some(3), + Pixel::GBRP16BE => Some(3), + Pixel::GBRP16LE => Some(3), + Pixel::YUVA420P9BE => Some(3), + Pixel::YUVA420P9LE => Some(3), + Pixel::YUVA422P9BE => Some(3), + Pixel::YUVA422P9LE => Some(3), + Pixel::YUVA444P9BE => Some(3), + Pixel::YUVA444P9LE => Some(3), + Pixel::YUVA420P10BE => Some(3), + Pixel::YUVA420P10LE => Some(3), + Pixel::YUVA422P10BE => Some(3), + Pixel::YUVA422P10LE => Some(3), + Pixel::YUVA444P10BE => Some(3), + Pixel::YUVA444P10LE => Some(3), + Pixel::YUVA420P16BE => Some(3), + Pixel::YUVA420P16LE => Some(3), + Pixel::YUVA422P16BE => Some(3), + Pixel::YUVA422P16LE => Some(3), + Pixel::YUVA444P16BE => Some(3), + Pixel::YUVA444P16LE => Some(3), + Pixel::XYZ12LE => Some(3), + Pixel::XYZ12BE => Some(3), + Pixel::NV16 => Some(3), + Pixel::NV20LE => Some(3), + Pixel::NV20BE => Some(3), + Pixel::RGBA64BE => Some(3), + Pixel::RGBA64LE => Some(3), + Pixel::BGRA64BE => Some(3), + Pixel::BGRA64LE => Some(3), + Pixel::YVYU422 => Some(3), + Pixel::YA16BE => Some(1), + Pixel::YA16LE => Some(1), + Pixel::ZRGB => Some(3), + Pixel::RGBZ => Some(3), + Pixel::ZBGR => Some(3), + Pixel::BGRZ => Some(3), + Pixel::YUVA444P => Some(3), + Pixel::YUVA422P => Some(3), + Pixel::YUV420P12BE => Some(3), + Pixel::YUV420P12LE => Some(3), + Pixel::YUV420P14BE => Some(3), + Pixel::YUV420P14LE => Some(3), + Pixel::YUV422P12BE => Some(3), + Pixel::YUV422P12LE => Some(3), + Pixel::YUV422P14BE => Some(3), + Pixel::YUV422P14LE => Some(3), + Pixel::YUV444P12BE => Some(3), + Pixel::YUV444P12LE => Some(3), + Pixel::YUV444P14BE => Some(3), + Pixel::YUV444P14LE => Some(3), + Pixel::GBRP12BE => Some(3), + Pixel::GBRP12LE => Some(3), + Pixel::GBRP14BE => Some(3), + Pixel::GBRP14LE => Some(3), + Pixel::GBRAP => Some(3), + Pixel::GBRAP16BE => Some(3), + Pixel::GBRAP16LE => Some(3), + Pixel::YUVJ411P => Some(3), + Pixel::BAYER_BGGR8 => Some(4), + Pixel::BAYER_RGGB8 => Some(4), + Pixel::BAYER_GBRG8 => Some(4), + Pixel::BAYER_GRBG8 => Some(4), + Pixel::BAYER_BGGR16LE => Some(4), + Pixel::BAYER_BGGR16BE => Some(4), + Pixel::BAYER_RGGB16LE => Some(4), + Pixel::BAYER_RGGB16BE => Some(4), + Pixel::BAYER_GBRG16LE => Some(4), + Pixel::BAYER_GBRG16BE => Some(4), + Pixel::BAYER_GRBG16LE => Some(4), + Pixel::BAYER_GRBG16BE => Some(4), + Pixel::YUV440P10LE => Some(3), + Pixel::YUV440P10BE => Some(3), + Pixel::YUV440P12LE => Some(3), + Pixel::YUV440P12BE => Some(3), + Pixel::AYUV64LE => Some(3), + Pixel::AYUV64BE => Some(3), + Pixel::P010LE => Some(3), + Pixel::P010BE => Some(3), + Pixel::GBRAP12BE => Some(3), + Pixel::GBRAP12LE => Some(3), + Pixel::GBRAP10LE => Some(3), + Pixel::GBRAP10BE => Some(3), + Pixel::GRAY12BE => Some(1), + Pixel::GRAY12LE => Some(1), + Pixel::GRAY10BE => Some(1), + Pixel::GRAY10LE => Some(1), + Pixel::P016LE => Some(3), + Pixel::P016BE => Some(3), + Pixel::GRAY9BE => Some(1), + Pixel::GRAY9LE => Some(1), + Pixel::GBRPF32BE => Some(3), + Pixel::GBRPF32LE => Some(3), + Pixel::GBRAPF32BE => Some(3), + Pixel::GBRAPF32LE => Some(3), + Pixel::GRAY14BE => Some(1), + Pixel::GRAY14LE => Some(1), + Pixel::GRAYF32BE => Some(1), + Pixel::GRAYF32LE => Some(1), + Pixel::YUVA422P12BE => Some(3), + Pixel::YUVA422P12LE => Some(3), + Pixel::YUVA444P12BE => Some(3), + Pixel::YUVA444P12LE => Some(3), + Pixel::NV24 => Some(3), + Pixel::NV42 => Some(3), + Pixel::Y210BE => Some(3), + Pixel::Y210LE => Some(3), + Pixel::X2RGB10LE => Some(3), + Pixel::X2RGB10BE => Some(3), + + // Aliases for some of the above formats, but native endian. + Pixel::RGB32 => Some(3), + Pixel::RGB32_1 => Some(3), + Pixel::BGR32 => Some(3), + Pixel::BGR32_1 => Some(3), + Pixel::ZRGB32 => Some(3), + Pixel::ZBGR32 => Some(3), + Pixel::GRAY16 => Some(1), + Pixel::YA16 => Some(1), + Pixel::RGB48 => Some(3), + Pixel::RGB565 => Some(3), + Pixel::RGB555 => Some(3), + Pixel::RGB444 => Some(3), + Pixel::BGR48 => Some(3), + Pixel::BGR565 => Some(3), + Pixel::BGR555 => Some(3), + Pixel::BGR444 => Some(3), + Pixel::YUV420P9 => Some(3), + Pixel::YUV422P9 => Some(3), + Pixel::YUV444P9 => Some(3), + Pixel::YUV420P10 => Some(3), + Pixel::YUV422P10 => Some(3), + Pixel::YUV440P10 => Some(3), + Pixel::YUV444P10 => Some(3), + Pixel::YUV420P12 => Some(3), + Pixel::YUV422P12 => Some(3), + Pixel::YUV440P12 => Some(3), + Pixel::YUV444P12 => Some(3), + Pixel::YUV420P14 => Some(3), + Pixel::YUV422P14 => Some(3), + Pixel::YUV444P14 => Some(3), + Pixel::YUV420P16 => Some(3), + Pixel::YUV422P16 => Some(3), + Pixel::YUV444P16 => Some(3), + Pixel::GBRP9 => Some(1), + Pixel::GBRP10 => Some(1), + Pixel::GBRP12 => Some(1), + Pixel::GBRP14 => Some(1), + Pixel::GBRP16 => Some(1), + Pixel::GBRAP16 => Some(1), + Pixel::BAYER_BGGR16 => Some(4), + Pixel::BAYER_RGGB16 => Some(4), + Pixel::BAYER_GBRG16 => Some(4), + Pixel::BAYER_GRBG16 => Some(4), + Pixel::YUVA420P9 => Some(3), + Pixel::YUVA422P9 => Some(3), + Pixel::YUVA444P9 => Some(3), + Pixel::YUVA420P10 => Some(3), + Pixel::YUVA422P10 => Some(3), + Pixel::YUVA444P10 => Some(3), + Pixel::YUVA420P16 => Some(3), + Pixel::YUVA422P16 => Some(3), + Pixel::YUVA444P16 => Some(3), + Pixel::XYZ12 => Some(3), + Pixel::NV20 => Some(3), + Pixel::AYUV64 => Some(3), + } +} + +// Returns whether the given pixel format has an alpha channel or not. +fn pixel_has_alpha(f: Pixel) -> Option { + match f { + // No specific pixel format defined. + Pixel::None => None, + Pixel::VAAPI_MOCO => None, + Pixel::VAAPI_IDCT => None, + Pixel::VAAPI_VLD => None, + Pixel::DXVA2_VLD => None, + Pixel::VDPAU => None, + Pixel::QSV => None, + Pixel::MMAL => None, + Pixel::D3D11VA_VLD => None, + Pixel::CUDA => None, + Pixel::XVMC => None, + Pixel::VIDEOTOOLBOX => None, + Pixel::MEDIACODEC => None, + Pixel::D3D11 => None, + Pixel::DRM_PRIME => None, + Pixel::OPENCL => None, + Pixel::VULKAN => None, + + // Defined pixel formats. + Pixel::YUV420P => Some(false), + Pixel::YUYV422 => Some(false), + Pixel::RGB24 => Some(false), + Pixel::BGR24 => Some(false), + Pixel::YUV422P => Some(false), + Pixel::YUV444P => Some(false), + Pixel::YUV410P => Some(false), + Pixel::YUV411P => Some(false), + Pixel::GRAY8 => Some(false), + Pixel::MonoWhite => Some(false), + Pixel::MonoBlack => Some(false), + Pixel::PAL8 => Some(false), + Pixel::YUVJ420P => Some(false), + Pixel::YUVJ422P => Some(false), + Pixel::YUVJ444P => Some(false), + Pixel::UYVY422 => Some(false), + Pixel::UYYVYY411 => Some(false), + Pixel::BGR8 => Some(false), + Pixel::BGR4 => Some(false), + Pixel::BGR4_BYTE => Some(false), + Pixel::RGB8 => Some(false), + Pixel::RGB4 => Some(false), + Pixel::RGB4_BYTE => Some(false), + Pixel::NV12 => Some(false), + Pixel::NV21 => Some(false), + Pixel::ARGB => Some(true), + Pixel::RGBA => Some(true), + Pixel::ABGR => Some(true), + Pixel::BGRA => Some(true), + Pixel::GRAY16BE => Some(false), + Pixel::GRAY16LE => Some(false), + Pixel::YUV440P => Some(false), + Pixel::YUVJ440P => Some(false), + Pixel::YUVA420P => Some(false), + Pixel::RGB48BE => Some(false), + Pixel::RGB48LE => Some(false), + Pixel::RGB565BE => Some(false), + Pixel::RGB565LE => Some(false), + Pixel::RGB555BE => Some(false), + Pixel::RGB555LE => Some(false), + Pixel::BGR565BE => Some(false), + Pixel::BGR565LE => Some(false), + Pixel::BGR555BE => Some(false), + Pixel::BGR555LE => Some(false), + Pixel::YUV420P16LE => Some(false), + Pixel::YUV420P16BE => Some(false), + Pixel::YUV422P16LE => Some(false), + Pixel::YUV422P16BE => Some(false), + Pixel::YUV444P16LE => Some(false), + Pixel::YUV444P16BE => Some(false), + Pixel::RGB444LE => Some(false), + Pixel::RGB444BE => Some(false), + Pixel::BGR444LE => Some(false), + Pixel::BGR444BE => Some(false), + Pixel::YA8 => Some(true), + Pixel::BGR48BE => Some(false), + Pixel::BGR48LE => Some(false), + Pixel::YUV420P9BE => Some(false), + Pixel::YUV420P9LE => Some(false), + Pixel::YUV420P10BE => Some(false), + Pixel::YUV420P10LE => Some(false), + Pixel::YUV422P10BE => Some(false), + Pixel::YUV422P10LE => Some(false), + Pixel::YUV444P9BE => Some(false), + Pixel::YUV444P9LE => Some(false), + Pixel::YUV444P10BE => Some(false), + Pixel::YUV444P10LE => Some(false), + Pixel::YUV422P9BE => Some(false), + Pixel::YUV422P9LE => Some(false), + Pixel::GBRP => Some(false), + Pixel::GBRP9BE => Some(false), + Pixel::GBRP9LE => Some(false), + Pixel::GBRP10BE => Some(false), + Pixel::GBRP10LE => Some(false), + Pixel::GBRP16BE => Some(false), + Pixel::GBRP16LE => Some(false), + Pixel::YUVA420P9BE => Some(true), + Pixel::YUVA420P9LE => Some(true), + Pixel::YUVA422P9BE => Some(true), + Pixel::YUVA422P9LE => Some(true), + Pixel::YUVA444P9BE => Some(true), + Pixel::YUVA444P9LE => Some(true), + Pixel::YUVA420P10BE => Some(true), + Pixel::YUVA420P10LE => Some(true), + Pixel::YUVA422P10BE => Some(true), + Pixel::YUVA422P10LE => Some(true), + Pixel::YUVA444P10BE => Some(true), + Pixel::YUVA444P10LE => Some(true), + Pixel::YUVA420P16BE => Some(true), + Pixel::YUVA420P16LE => Some(true), + Pixel::YUVA422P16BE => Some(true), + Pixel::YUVA422P16LE => Some(true), + Pixel::YUVA444P16BE => Some(true), + Pixel::YUVA444P16LE => Some(true), + Pixel::XYZ12LE => Some(false), + Pixel::XYZ12BE => Some(false), + Pixel::NV16 => Some(false), + Pixel::NV20LE => Some(false), + Pixel::NV20BE => Some(false), + Pixel::RGBA64BE => Some(true), + Pixel::RGBA64LE => Some(true), + Pixel::BGRA64BE => Some(true), + Pixel::BGRA64LE => Some(true), + Pixel::YVYU422 => Some(false), + Pixel::YA16BE => Some(true), + Pixel::YA16LE => Some(true), + Pixel::ZRGB => Some(false), + Pixel::RGBZ => Some(false), + Pixel::ZBGR => Some(false), + Pixel::BGRZ => Some(false), + Pixel::YUVA444P => Some(true), + Pixel::YUVA422P => Some(true), + Pixel::YUV420P12BE => Some(false), + Pixel::YUV420P12LE => Some(false), + Pixel::YUV420P14BE => Some(false), + Pixel::YUV420P14LE => Some(false), + Pixel::YUV422P12BE => Some(false), + Pixel::YUV422P12LE => Some(false), + Pixel::YUV422P14BE => Some(false), + Pixel::YUV422P14LE => Some(false), + Pixel::YUV444P12BE => Some(false), + Pixel::YUV444P12LE => Some(false), + Pixel::YUV444P14BE => Some(false), + Pixel::YUV444P14LE => Some(false), + Pixel::GBRP12BE => Some(false), + Pixel::GBRP12LE => Some(false), + Pixel::GBRP14BE => Some(false), + Pixel::GBRP14LE => Some(false), + Pixel::GBRAP => Some(true), + Pixel::GBRAP16BE => Some(true), + Pixel::GBRAP16LE => Some(true), + Pixel::YUVJ411P => Some(false), + Pixel::BAYER_BGGR8 => Some(false), + Pixel::BAYER_RGGB8 => Some(false), + Pixel::BAYER_GBRG8 => Some(false), + Pixel::BAYER_GRBG8 => Some(false), + Pixel::BAYER_BGGR16LE => Some(false), + Pixel::BAYER_BGGR16BE => Some(false), + Pixel::BAYER_RGGB16LE => Some(false), + Pixel::BAYER_RGGB16BE => Some(false), + Pixel::BAYER_GBRG16LE => Some(false), + Pixel::BAYER_GBRG16BE => Some(false), + Pixel::BAYER_GRBG16LE => Some(false), + Pixel::BAYER_GRBG16BE => Some(false), + Pixel::YUV440P10LE => Some(false), + Pixel::YUV440P10BE => Some(false), + Pixel::YUV440P12LE => Some(false), + Pixel::YUV440P12BE => Some(false), + Pixel::AYUV64LE => Some(true), + Pixel::AYUV64BE => Some(true), + Pixel::P010LE => Some(false), + Pixel::P010BE => Some(false), + Pixel::GBRAP12BE => Some(true), + Pixel::GBRAP12LE => Some(true), + Pixel::GBRAP10LE => Some(true), + Pixel::GBRAP10BE => Some(true), + Pixel::GRAY12BE => Some(false), + Pixel::GRAY12LE => Some(false), + Pixel::GRAY10BE => Some(false), + Pixel::GRAY10LE => Some(false), + Pixel::P016LE => Some(false), + Pixel::P016BE => Some(false), + Pixel::GRAY9BE => Some(false), + Pixel::GRAY9LE => Some(false), + Pixel::GBRPF32BE => Some(false), + Pixel::GBRPF32LE => Some(false), + Pixel::GBRAPF32BE => Some(true), + Pixel::GBRAPF32LE => Some(true), + Pixel::GRAY14BE => Some(false), + Pixel::GRAY14LE => Some(false), + Pixel::GRAYF32BE => Some(false), + Pixel::GRAYF32LE => Some(false), + Pixel::YUVA422P12BE => Some(true), + Pixel::YUVA422P12LE => Some(true), + Pixel::YUVA444P12BE => Some(true), + Pixel::YUVA444P12LE => Some(true), + Pixel::NV24 => Some(false), + Pixel::NV42 => Some(false), + Pixel::Y210BE => Some(false), + Pixel::Y210LE => Some(false), + Pixel::X2RGB10LE => Some(false), + Pixel::X2RGB10BE => Some(false), + + // Aliases for some of the above formats, but native endian. + Pixel::RGB32 => Some(false), + Pixel::RGB32_1 => Some(false), + Pixel::BGR32 => Some(false), + Pixel::BGR32_1 => Some(false), + Pixel::ZRGB32 => Some(false), + Pixel::ZBGR32 => Some(false), + Pixel::GRAY16 => Some(false), + Pixel::YA16 => Some(true), + Pixel::RGB48 => Some(false), + Pixel::RGB565 => Some(false), + Pixel::RGB555 => Some(false), + Pixel::RGB444 => Some(false), + Pixel::BGR48 => Some(false), + Pixel::BGR565 => Some(false), + Pixel::BGR555 => Some(false), + Pixel::BGR444 => Some(false), + Pixel::YUV420P9 => Some(false), + Pixel::YUV422P9 => Some(false), + Pixel::YUV444P9 => Some(false), + Pixel::YUV420P10 => Some(false), + Pixel::YUV422P10 => Some(false), + Pixel::YUV440P10 => Some(false), + Pixel::YUV444P10 => Some(false), + Pixel::YUV420P12 => Some(false), + Pixel::YUV422P12 => Some(false), + Pixel::YUV440P12 => Some(false), + Pixel::YUV444P12 => Some(false), + Pixel::YUV420P14 => Some(false), + Pixel::YUV422P14 => Some(false), + Pixel::YUV444P14 => Some(false), + Pixel::YUV420P16 => Some(false), + Pixel::YUV422P16 => Some(false), + Pixel::YUV444P16 => Some(false), + Pixel::GBRP9 => Some(false), + Pixel::GBRP10 => Some(false), + Pixel::GBRP12 => Some(false), + Pixel::GBRP14 => Some(false), + Pixel::GBRP16 => Some(false), + Pixel::GBRAP16 => Some(true), + Pixel::BAYER_BGGR16 => Some(false), + Pixel::BAYER_RGGB16 => Some(false), + Pixel::BAYER_GBRG16 => Some(false), + Pixel::BAYER_GRBG16 => Some(false), + Pixel::YUVA420P9 => Some(true), + Pixel::YUVA422P9 => Some(true), + Pixel::YUVA444P9 => Some(true), + Pixel::YUVA420P10 => Some(true), + Pixel::YUVA422P10 => Some(true), + Pixel::YUVA444P10 => Some(true), + Pixel::YUVA420P16 => Some(true), + Pixel::YUVA422P16 => Some(true), + Pixel::YUVA444P16 => Some(true), + Pixel::XYZ12 => Some(false), + Pixel::NV20 => Some(false), + Pixel::AYUV64 => Some(true), } }